From ff91b644fb1b063d0a8eff7492beb1a9bf7e4ce1 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 14 Nov 2022 14:49:50 +0100 Subject: [PATCH] Add ability to install alpha/beta/rc plugin --- server/helpers/custom-validators/plugins.ts | 22 +++++++++++--- server/lib/plugins/yarn.ts | 4 +-- server/middlewares/validators/plugins.ts | 13 ++++++--- server/middlewares/validators/themes.ts | 4 +-- server/models/server/plugin.ts | 9 +++--- server/tests/cli/peertube.ts | 21 +++++++++++++- server/tests/helpers/index.ts | 1 + server/tests/helpers/validator.ts | 32 +++++++++++++++++++++ server/tools/peertube-plugins.ts | 2 +- 9 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 server/tests/helpers/validator.ts 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 @@ -import { exists, isArray, isSafePath } from './misc' import validator from 'validator' +import { PluginPackageJSON } from '../../../shared/models/plugins/plugin-package-json.model' import { PluginType } from '../../../shared/models/plugins/plugin.type' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' -import { PluginPackageJSON } from '../../../shared/models/plugins/plugin-package-json.model' import { isUrlValid } from './activitypub/misc' +import { exists, isArray, isSafePath } from './misc' const PLUGINS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.PLUGINS @@ -29,7 +29,7 @@ function isPluginDescriptionValid (value: string) { return exists(value) && validator.isLength(value, PLUGINS_CONSTRAINTS_FIELDS.DESCRIPTION) } -function isPluginVersionValid (value: string) { +function isPluginStableVersionValid (value: string) { if (!exists(value)) return false const parts = (value + '').split('.') @@ -37,6 +37,19 @@ function isPluginVersionValid (value: string) { return parts.length === 3 && parts.every(p => validator.isInt(p)) } +function isPluginStableOrUnstableVersionValid (value: string) { + if (!exists(value)) return false + + // suffix is beta.x or alpha.x + const [ stable, suffix ] = value.split('-') + if (!isPluginStableVersionValid(stable)) return false + + const suffixRegex = /^(rc|alpha|beta)\.\d+$/ + if (suffix && !suffixRegex.test(suffix)) return false + + return true +} + function isPluginEngineValid (engine: any) { return exists(engine) && exists(engine.peertube) } @@ -156,7 +169,8 @@ export { isPackageJSONValid, isThemeNameValid, isPluginHomepage, - isPluginVersionValid, + isPluginStableVersionValid, + isPluginStableOrUnstableVersionValid, isPluginNameValid, isPluginDescriptionValid, 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 @@ import { outputJSON, pathExists } from 'fs-extra' import { join } from 'path' import { execShell } from '../../helpers/core-utils' -import { isNpmPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' +import { isNpmPluginNameValid, isPluginStableOrUnstableVersionValid } from '../../helpers/custom-validators/plugins' import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers/config' import { getLatestPluginVersion } from './plugin-index' @@ -69,5 +69,5 @@ function checkNpmPluginNameOrThrow (name: string) { } function checkPluginVersionOrThrow (name: string) { - if (!isPluginVersionValid(name)) throw new Error('Invalid NPM plugin version to install') + if (!isPluginStableOrUnstableVersionValid(name)) throw new Error('Invalid NPM plugin version to install') } 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' import { PluginType } from '../../../shared/models/plugins/plugin.type' import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model' import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' -import { isNpmPluginNameValid, isPluginNameValid, isPluginTypeValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' +import { + isNpmPluginNameValid, + isPluginNameValid, + isPluginStableOrUnstableVersionValid, + isPluginTypeValid +} from '../../helpers/custom-validators/plugins' import { CONFIG } from '../../initializers/config' import { PluginManager } from '../../lib/plugins/plugin-manager' import { PluginModel } from '../../models/server/plugin' @@ -19,7 +24,7 @@ const getPluginValidator = (pluginType: PluginType, withVersion = true) => { if (withVersion) { validators.push( param('pluginVersion') - .custom(isPluginVersionValid) + .custom(isPluginStableOrUnstableVersionValid) ) } @@ -113,7 +118,7 @@ const installOrUpdatePluginValidator = [ .custom(isNpmPluginNameValid), body('pluginVersion') .optional() - .custom(isPluginVersionValid), + .custom(isPluginStableOrUnstableVersionValid), body('path') .optional() .custom(isSafePath), @@ -185,7 +190,7 @@ const listAvailablePluginsValidator = [ .custom(isPluginTypeValid), query('currentPeerTubeEngine') .optional() - .custom(isPluginVersionValid), + .custom(isPluginStableOrUnstableVersionValid), (req: express.Request, res: express.Response, next: express.NextFunction) => { 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' import { param } from 'express-validator' import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' import { isSafePath } from '../../helpers/custom-validators/misc' -import { isPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' +import { isPluginNameValid, isPluginStableOrUnstableVersionValid } from '../../helpers/custom-validators/plugins' import { PluginManager } from '../../lib/plugins/plugin-manager' import { areValidationErrors } from './shared' @@ -10,7 +10,7 @@ const serveThemeCSSValidator = [ param('themeName') .custom(isPluginNameValid), param('themeVersion') - .custom(isPluginVersionValid), + .custom(isPluginStableOrUnstableVersionValid), param('staticEndpoint') .custom(isSafePath), 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 { isPluginDescriptionValid, isPluginHomepage, isPluginNameValid, - isPluginTypeValid, - isPluginVersionValid + isPluginStableOrUnstableVersionValid, + isPluginStableVersionValid, + isPluginTypeValid } from '../../helpers/custom-validators/plugins' import { getSort, throwIfNotValid } from '../utils' @@ -40,12 +41,12 @@ export class PluginModel extends Model>> { type: number @AllowNull(false) - @Is('PluginVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version')) + @Is('PluginVersion', value => throwIfNotValid(value, isPluginStableOrUnstableVersionValid, 'version')) @Column version: string @AllowNull(true) - @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version')) + @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginStableVersionValid, 'version')) @Column latestVersion: string 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 () { before(async function () { this.timeout(30000) - server = await createSingleServer(1) + server = await createSingleServer(1, { + rates_limit: { + login: { + max: 30 + } + } + }) await setAccessTokensToServers([ server ]) await server.users.create({ username: 'user_1', password: 'super_password' }) @@ -240,6 +246,19 @@ describe('Test CLI wrapper', function () { expect(res).to.not.contain('peertube-plugin-hello-world') }) + + it('Should install a plugin in requested beta version', async function () { + this.timeout(60000) + + await cliCommand.execWithEnv(`${cmd} plugins install --npm-name peertube-plugin-hello-world --plugin-version 0.0.21-beta.1`) + + const res = await cliCommand.execWithEnv(`${cmd} plugins list`) + + expect(res).to.contain('peertube-plugin-hello-world') + expect(res).to.contain('0.0.21-beta.1') + + await cliCommand.execWithEnv(`${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`) + }) }) 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' import './image' import './markdown' import './request' +import './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 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ + +import { expect } from 'chai' +import { isPluginStableOrUnstableVersionValid, isPluginStableVersionValid } from '@server/helpers/custom-validators/plugins' + +describe('Validators', function () { + + it('Should correctly check stable plugin versions', async function () { + expect(isPluginStableVersionValid('3.4.0')).to.be.true + expect(isPluginStableVersionValid('0.4.0')).to.be.true + expect(isPluginStableVersionValid('0.1.0')).to.be.true + + expect(isPluginStableVersionValid('0.1.0-beta-1')).to.be.false + expect(isPluginStableVersionValid('hello')).to.be.false + expect(isPluginStableVersionValid('0.x.a')).to.be.false + }) + + it('Should correctly check unstable plugin versions', async function () { + expect(isPluginStableOrUnstableVersionValid('3.4.0')).to.be.true + expect(isPluginStableOrUnstableVersionValid('0.4.0')).to.be.true + expect(isPluginStableOrUnstableVersionValid('0.1.0')).to.be.true + + expect(isPluginStableOrUnstableVersionValid('0.1.0-beta.1')).to.be.true + expect(isPluginStableOrUnstableVersionValid('0.1.0-alpha.45')).to.be.true + expect(isPluginStableOrUnstableVersionValid('0.1.0-rc.45')).to.be.true + + expect(isPluginStableOrUnstableVersionValid('hello')).to.be.false + expect(isPluginStableOrUnstableVersionValid('0.x.a')).to.be.false + expect(isPluginStableOrUnstableVersionValid('0.1.0-rc-45')).to.be.false + expect(isPluginStableOrUnstableVersionValid('0.1.0-rc.45d')).to.be.false + }) +}) 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) { const table = new CliTable3({ head: [ 'name', 'version', 'homepage' ], - colWidths: [ 50, 10, 50 ] + colWidths: [ 50, 20, 50 ] }) as any for (const plugin of data) { -- 2.41.0