aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/helpers/custom-validators/plugins.ts22
-rw-r--r--server/lib/plugins/yarn.ts4
-rw-r--r--server/middlewares/validators/plugins.ts13
-rw-r--r--server/middlewares/validators/themes.ts4
-rw-r--r--server/models/server/plugin.ts9
-rw-r--r--server/tests/cli/peertube.ts21
-rw-r--r--server/tests/helpers/index.ts1
-rw-r--r--server/tests/helpers/validator.ts32
-rw-r--r--server/tools/peertube-plugins.ts2
9 files changed, 90 insertions, 18 deletions
diff --git a/server/helpers/custom-validators/plugins.ts b/server/helpers/custom-validators/plugins.ts
index 60b29dc89..a20de0c4a 100644
--- a/server/helpers/custom-validators/plugins.ts
+++ b/server/helpers/custom-validators/plugins.ts
@@ -1,9 +1,9 @@
1import { exists, isArray, isSafePath } from './misc'
2import validator from 'validator' 1import validator from 'validator'
2import { PluginPackageJSON } from '../../../shared/models/plugins/plugin-package-json.model'
3import { PluginType } from '../../../shared/models/plugins/plugin.type' 3import { PluginType } from '../../../shared/models/plugins/plugin.type'
4import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 4import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
5import { PluginPackageJSON } from '../../../shared/models/plugins/plugin-package-json.model'
6import { isUrlValid } from './activitypub/misc' 5import { isUrlValid } from './activitypub/misc'
6import { exists, isArray, isSafePath } from './misc'
7 7
8const PLUGINS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.PLUGINS 8const PLUGINS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.PLUGINS
9 9
@@ -29,7 +29,7 @@ function isPluginDescriptionValid (value: string) {
29 return exists(value) && validator.isLength(value, PLUGINS_CONSTRAINTS_FIELDS.DESCRIPTION) 29 return exists(value) && validator.isLength(value, PLUGINS_CONSTRAINTS_FIELDS.DESCRIPTION)
30} 30}
31 31
32function isPluginVersionValid (value: string) { 32function isPluginStableVersionValid (value: string) {
33 if (!exists(value)) return false 33 if (!exists(value)) return false
34 34
35 const parts = (value + '').split('.') 35 const parts = (value + '').split('.')
@@ -37,6 +37,19 @@ function isPluginVersionValid (value: string) {
37 return parts.length === 3 && parts.every(p => validator.isInt(p)) 37 return parts.length === 3 && parts.every(p => validator.isInt(p))
38} 38}
39 39
40function isPluginStableOrUnstableVersionValid (value: string) {
41 if (!exists(value)) return false
42
43 // suffix is beta.x or alpha.x
44 const [ stable, suffix ] = value.split('-')
45 if (!isPluginStableVersionValid(stable)) return false
46
47 const suffixRegex = /^(rc|alpha|beta)\.\d+$/
48 if (suffix && !suffixRegex.test(suffix)) return false
49
50 return true
51}
52
40function isPluginEngineValid (engine: any) { 53function isPluginEngineValid (engine: any) {
41 return exists(engine) && exists(engine.peertube) 54 return exists(engine) && exists(engine.peertube)
42} 55}
@@ -156,7 +169,8 @@ export {
156 isPackageJSONValid, 169 isPackageJSONValid,
157 isThemeNameValid, 170 isThemeNameValid,
158 isPluginHomepage, 171 isPluginHomepage,
159 isPluginVersionValid, 172 isPluginStableVersionValid,
173 isPluginStableOrUnstableVersionValid,
160 isPluginNameValid, 174 isPluginNameValid,
161 isPluginDescriptionValid, 175 isPluginDescriptionValid,
162 isLibraryCodeValid, 176 isLibraryCodeValid,
diff --git a/server/lib/plugins/yarn.ts b/server/lib/plugins/yarn.ts
index d105b95e0..9cf6ec9e9 100644
--- a/server/lib/plugins/yarn.ts
+++ b/server/lib/plugins/yarn.ts
@@ -1,7 +1,7 @@
1import { outputJSON, pathExists } from 'fs-extra' 1import { outputJSON, pathExists } from 'fs-extra'
2import { join } from 'path' 2import { join } from 'path'
3import { execShell } from '../../helpers/core-utils' 3import { execShell } from '../../helpers/core-utils'
4import { isNpmPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' 4import { isNpmPluginNameValid, isPluginStableOrUnstableVersionValid } from '../../helpers/custom-validators/plugins'
5import { logger } from '../../helpers/logger' 5import { logger } from '../../helpers/logger'
6import { CONFIG } from '../../initializers/config' 6import { CONFIG } from '../../initializers/config'
7import { getLatestPluginVersion } from './plugin-index' 7import { getLatestPluginVersion } from './plugin-index'
@@ -69,5 +69,5 @@ function checkNpmPluginNameOrThrow (name: string) {
69} 69}
70 70
71function checkPluginVersionOrThrow (name: string) { 71function checkPluginVersionOrThrow (name: string) {
72 if (!isPluginVersionValid(name)) throw new Error('Invalid NPM plugin version to install') 72 if (!isPluginStableOrUnstableVersionValid(name)) throw new Error('Invalid NPM plugin version to install')
73} 73}
diff --git a/server/middlewares/validators/plugins.ts b/server/middlewares/validators/plugins.ts
index 78c030333..64bef2648 100644
--- a/server/middlewares/validators/plugins.ts
+++ b/server/middlewares/validators/plugins.ts
@@ -4,7 +4,12 @@ import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
4import { PluginType } from '../../../shared/models/plugins/plugin.type' 4import { PluginType } from '../../../shared/models/plugins/plugin.type'
5import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model' 5import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model'
6import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' 6import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
7import { isNpmPluginNameValid, isPluginNameValid, isPluginTypeValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' 7import {
8 isNpmPluginNameValid,
9 isPluginNameValid,
10 isPluginStableOrUnstableVersionValid,
11 isPluginTypeValid
12} from '../../helpers/custom-validators/plugins'
8import { CONFIG } from '../../initializers/config' 13import { CONFIG } from '../../initializers/config'
9import { PluginManager } from '../../lib/plugins/plugin-manager' 14import { PluginManager } from '../../lib/plugins/plugin-manager'
10import { PluginModel } from '../../models/server/plugin' 15import { PluginModel } from '../../models/server/plugin'
@@ -19,7 +24,7 @@ const getPluginValidator = (pluginType: PluginType, withVersion = true) => {
19 if (withVersion) { 24 if (withVersion) {
20 validators.push( 25 validators.push(
21 param('pluginVersion') 26 param('pluginVersion')
22 .custom(isPluginVersionValid) 27 .custom(isPluginStableOrUnstableVersionValid)
23 ) 28 )
24 } 29 }
25 30
@@ -113,7 +118,7 @@ const installOrUpdatePluginValidator = [
113 .custom(isNpmPluginNameValid), 118 .custom(isNpmPluginNameValid),
114 body('pluginVersion') 119 body('pluginVersion')
115 .optional() 120 .optional()
116 .custom(isPluginVersionValid), 121 .custom(isPluginStableOrUnstableVersionValid),
117 body('path') 122 body('path')
118 .optional() 123 .optional()
119 .custom(isSafePath), 124 .custom(isSafePath),
@@ -185,7 +190,7 @@ const listAvailablePluginsValidator = [
185 .custom(isPluginTypeValid), 190 .custom(isPluginTypeValid),
186 query('currentPeerTubeEngine') 191 query('currentPeerTubeEngine')
187 .optional() 192 .optional()
188 .custom(isPluginVersionValid), 193 .custom(isPluginStableOrUnstableVersionValid),
189 194
190 (req: express.Request, res: express.Response, next: express.NextFunction) => { 195 (req: express.Request, res: express.Response, next: express.NextFunction) => {
191 if (areValidationErrors(req, res)) return 196 if (areValidationErrors(req, res)) return
diff --git a/server/middlewares/validators/themes.ts b/server/middlewares/validators/themes.ts
index c130801a0..080b3e096 100644
--- a/server/middlewares/validators/themes.ts
+++ b/server/middlewares/validators/themes.ts
@@ -2,7 +2,7 @@ import express from 'express'
2import { param } from 'express-validator' 2import { param } from 'express-validator'
3import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' 3import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
4import { isSafePath } from '../../helpers/custom-validators/misc' 4import { isSafePath } from '../../helpers/custom-validators/misc'
5import { isPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' 5import { isPluginNameValid, isPluginStableOrUnstableVersionValid } from '../../helpers/custom-validators/plugins'
6import { PluginManager } from '../../lib/plugins/plugin-manager' 6import { PluginManager } from '../../lib/plugins/plugin-manager'
7import { areValidationErrors } from './shared' 7import { areValidationErrors } from './shared'
8 8
@@ -10,7 +10,7 @@ const serveThemeCSSValidator = [
10 param('themeName') 10 param('themeName')
11 .custom(isPluginNameValid), 11 .custom(isPluginNameValid),
12 param('themeVersion') 12 param('themeVersion')
13 .custom(isPluginVersionValid), 13 .custom(isPluginStableOrUnstableVersionValid),
14 param('staticEndpoint') 14 param('staticEndpoint')
15 .custom(isSafePath), 15 .custom(isSafePath),
16 16
diff --git a/server/models/server/plugin.ts b/server/models/server/plugin.ts
index fa5b4cc4b..6a5d80182 100644
--- a/server/models/server/plugin.ts
+++ b/server/models/server/plugin.ts
@@ -7,8 +7,9 @@ import {
7 isPluginDescriptionValid, 7 isPluginDescriptionValid,
8 isPluginHomepage, 8 isPluginHomepage,
9 isPluginNameValid, 9 isPluginNameValid,
10 isPluginTypeValid, 10 isPluginStableOrUnstableVersionValid,
11 isPluginVersionValid 11 isPluginStableVersionValid,
12 isPluginTypeValid
12} from '../../helpers/custom-validators/plugins' 13} from '../../helpers/custom-validators/plugins'
13import { getSort, throwIfNotValid } from '../utils' 14import { getSort, throwIfNotValid } from '../utils'
14 15
@@ -40,12 +41,12 @@ export class PluginModel extends Model<Partial<AttributesOnly<PluginModel>>> {
40 type: number 41 type: number
41 42
42 @AllowNull(false) 43 @AllowNull(false)
43 @Is('PluginVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version')) 44 @Is('PluginVersion', value => throwIfNotValid(value, isPluginStableOrUnstableVersionValid, 'version'))
44 @Column 45 @Column
45 version: string 46 version: string
46 47
47 @AllowNull(true) 48 @AllowNull(true)
48 @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version')) 49 @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginStableVersionValid, 'version'))
49 @Column 50 @Column
50 latestVersion: string 51 latestVersion: string
51 52
diff --git a/server/tests/cli/peertube.ts b/server/tests/cli/peertube.ts
index 9b17cdd1b..a39bcfebe 100644
--- a/server/tests/cli/peertube.ts
+++ b/server/tests/cli/peertube.ts
@@ -24,7 +24,13 @@ describe('Test CLI wrapper', function () {
24 before(async function () { 24 before(async function () {
25 this.timeout(30000) 25 this.timeout(30000)
26 26
27 server = await createSingleServer(1) 27 server = await createSingleServer(1, {
28 rates_limit: {
29 login: {
30 max: 30
31 }
32 }
33 })
28 await setAccessTokensToServers([ server ]) 34 await setAccessTokensToServers([ server ])
29 35
30 await server.users.create({ username: 'user_1', password: 'super_password' }) 36 await server.users.create({ username: 'user_1', password: 'super_password' })
@@ -240,6 +246,19 @@ describe('Test CLI wrapper', function () {
240 246
241 expect(res).to.not.contain('peertube-plugin-hello-world') 247 expect(res).to.not.contain('peertube-plugin-hello-world')
242 }) 248 })
249
250 it('Should install a plugin in requested beta version', async function () {
251 this.timeout(60000)
252
253 await cliCommand.execWithEnv(`${cmd} plugins install --npm-name peertube-plugin-hello-world --plugin-version 0.0.21-beta.1`)
254
255 const res = await cliCommand.execWithEnv(`${cmd} plugins list`)
256
257 expect(res).to.contain('peertube-plugin-hello-world')
258 expect(res).to.contain('0.0.21-beta.1')
259
260 await cliCommand.execWithEnv(`${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
261 })
243 }) 262 })
244 263
245 describe('Manage video redundancies', function () { 264 describe('Manage video redundancies', function () {
diff --git a/server/tests/helpers/index.ts b/server/tests/helpers/index.ts
index 1f0e3098a..1b5c6d15b 100644
--- a/server/tests/helpers/index.ts
+++ b/server/tests/helpers/index.ts
@@ -5,3 +5,4 @@ import './dns'
5import './image' 5import './image'
6import './markdown' 6import './markdown'
7import './request' 7import './request'
8import './validator'
diff --git a/server/tests/helpers/validator.ts b/server/tests/helpers/validator.ts
new file mode 100644
index 000000000..f40a3aaae
--- /dev/null
+++ b/server/tests/helpers/validator.ts
@@ -0,0 +1,32 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { isPluginStableOrUnstableVersionValid, isPluginStableVersionValid } from '@server/helpers/custom-validators/plugins'
5
6describe('Validators', function () {
7
8 it('Should correctly check stable plugin versions', async function () {
9 expect(isPluginStableVersionValid('3.4.0')).to.be.true
10 expect(isPluginStableVersionValid('0.4.0')).to.be.true
11 expect(isPluginStableVersionValid('0.1.0')).to.be.true
12
13 expect(isPluginStableVersionValid('0.1.0-beta-1')).to.be.false
14 expect(isPluginStableVersionValid('hello')).to.be.false
15 expect(isPluginStableVersionValid('0.x.a')).to.be.false
16 })
17
18 it('Should correctly check unstable plugin versions', async function () {
19 expect(isPluginStableOrUnstableVersionValid('3.4.0')).to.be.true
20 expect(isPluginStableOrUnstableVersionValid('0.4.0')).to.be.true
21 expect(isPluginStableOrUnstableVersionValid('0.1.0')).to.be.true
22
23 expect(isPluginStableOrUnstableVersionValid('0.1.0-beta.1')).to.be.true
24 expect(isPluginStableOrUnstableVersionValid('0.1.0-alpha.45')).to.be.true
25 expect(isPluginStableOrUnstableVersionValid('0.1.0-rc.45')).to.be.true
26
27 expect(isPluginStableOrUnstableVersionValid('hello')).to.be.false
28 expect(isPluginStableOrUnstableVersionValid('0.x.a')).to.be.false
29 expect(isPluginStableOrUnstableVersionValid('0.1.0-rc-45')).to.be.false
30 expect(isPluginStableOrUnstableVersionValid('0.1.0-rc.45d')).to.be.false
31 })
32})
diff --git a/server/tools/peertube-plugins.ts b/server/tools/peertube-plugins.ts
index 47090b3a5..c51d9ebd1 100644
--- a/server/tools/peertube-plugins.ts
+++ b/server/tools/peertube-plugins.ts
@@ -69,7 +69,7 @@ async function pluginsListCLI (command: Command, options: OptionValues) {
69 69
70 const table = new CliTable3({ 70 const table = new CliTable3({
71 head: [ 'name', 'version', 'homepage' ], 71 head: [ 'name', 'version', 'homepage' ],
72 colWidths: [ 50, 10, 50 ] 72 colWidths: [ 50, 20, 50 ]
73 }) as any 73 }) as any
74 74
75 for (const plugin of data) { 75 for (const plugin of data) {