1
0
Fork 0

Add ability to install alpha/beta/rc plugin

This commit is contained in:
Chocobozzz 2022-11-14 14:49:50 +01:00
parent a742347d50
commit ff91b644fb
No known key found for this signature in database
GPG key ID: 583A612D890159BE
9 changed files with 90 additions and 18 deletions

View file

@ -1,9 +1,9 @@
import { exists, isArray, isSafePath } from './misc'
import validator from 'validator' import validator from 'validator'
import { PluginPackageJSON } from '../../../shared/models/plugins/plugin-package-json.model'
import { PluginType } from '../../../shared/models/plugins/plugin.type' import { PluginType } from '../../../shared/models/plugins/plugin.type'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants' import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
import { PluginPackageJSON } from '../../../shared/models/plugins/plugin-package-json.model'
import { isUrlValid } from './activitypub/misc' import { isUrlValid } from './activitypub/misc'
import { exists, isArray, isSafePath } from './misc'
const PLUGINS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.PLUGINS 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) return exists(value) && validator.isLength(value, PLUGINS_CONSTRAINTS_FIELDS.DESCRIPTION)
} }
function isPluginVersionValid (value: string) { function isPluginStableVersionValid (value: string) {
if (!exists(value)) return false if (!exists(value)) return false
const parts = (value + '').split('.') const parts = (value + '').split('.')
@ -37,6 +37,19 @@ function isPluginVersionValid (value: string) {
return parts.length === 3 && parts.every(p => validator.isInt(p)) 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) { function isPluginEngineValid (engine: any) {
return exists(engine) && exists(engine.peertube) return exists(engine) && exists(engine.peertube)
} }
@ -156,7 +169,8 @@ export {
isPackageJSONValid, isPackageJSONValid,
isThemeNameValid, isThemeNameValid,
isPluginHomepage, isPluginHomepage,
isPluginVersionValid, isPluginStableVersionValid,
isPluginStableOrUnstableVersionValid,
isPluginNameValid, isPluginNameValid,
isPluginDescriptionValid, isPluginDescriptionValid,
isLibraryCodeValid, isLibraryCodeValid,

View file

@ -1,7 +1,7 @@
import { outputJSON, pathExists } from 'fs-extra' import { outputJSON, pathExists } from 'fs-extra'
import { join } from 'path' import { join } from 'path'
import { execShell } from '../../helpers/core-utils' 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 { logger } from '../../helpers/logger'
import { CONFIG } from '../../initializers/config' import { CONFIG } from '../../initializers/config'
import { getLatestPluginVersion } from './plugin-index' import { getLatestPluginVersion } from './plugin-index'
@ -69,5 +69,5 @@ function checkNpmPluginNameOrThrow (name: string) {
} }
function checkPluginVersionOrThrow (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')
} }

View file

@ -4,7 +4,12 @@ import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { PluginType } from '../../../shared/models/plugins/plugin.type' import { PluginType } from '../../../shared/models/plugins/plugin.type'
import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model' import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model'
import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' 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 { CONFIG } from '../../initializers/config'
import { PluginManager } from '../../lib/plugins/plugin-manager' import { PluginManager } from '../../lib/plugins/plugin-manager'
import { PluginModel } from '../../models/server/plugin' import { PluginModel } from '../../models/server/plugin'
@ -19,7 +24,7 @@ const getPluginValidator = (pluginType: PluginType, withVersion = true) => {
if (withVersion) { if (withVersion) {
validators.push( validators.push(
param('pluginVersion') param('pluginVersion')
.custom(isPluginVersionValid) .custom(isPluginStableOrUnstableVersionValid)
) )
} }
@ -113,7 +118,7 @@ const installOrUpdatePluginValidator = [
.custom(isNpmPluginNameValid), .custom(isNpmPluginNameValid),
body('pluginVersion') body('pluginVersion')
.optional() .optional()
.custom(isPluginVersionValid), .custom(isPluginStableOrUnstableVersionValid),
body('path') body('path')
.optional() .optional()
.custom(isSafePath), .custom(isSafePath),
@ -185,7 +190,7 @@ const listAvailablePluginsValidator = [
.custom(isPluginTypeValid), .custom(isPluginTypeValid),
query('currentPeerTubeEngine') query('currentPeerTubeEngine')
.optional() .optional()
.custom(isPluginVersionValid), .custom(isPluginStableOrUnstableVersionValid),
(req: express.Request, res: express.Response, next: express.NextFunction) => { (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return if (areValidationErrors(req, res)) return

View file

@ -2,7 +2,7 @@ import express from 'express'
import { param } from 'express-validator' import { param } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isSafePath } from '../../helpers/custom-validators/misc' 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 { PluginManager } from '../../lib/plugins/plugin-manager'
import { areValidationErrors } from './shared' import { areValidationErrors } from './shared'
@ -10,7 +10,7 @@ const serveThemeCSSValidator = [
param('themeName') param('themeName')
.custom(isPluginNameValid), .custom(isPluginNameValid),
param('themeVersion') param('themeVersion')
.custom(isPluginVersionValid), .custom(isPluginStableOrUnstableVersionValid),
param('staticEndpoint') param('staticEndpoint')
.custom(isSafePath), .custom(isSafePath),

View file

@ -7,8 +7,9 @@ import {
isPluginDescriptionValid, isPluginDescriptionValid,
isPluginHomepage, isPluginHomepage,
isPluginNameValid, isPluginNameValid,
isPluginTypeValid, isPluginStableOrUnstableVersionValid,
isPluginVersionValid isPluginStableVersionValid,
isPluginTypeValid
} from '../../helpers/custom-validators/plugins' } from '../../helpers/custom-validators/plugins'
import { getSort, throwIfNotValid } from '../utils' import { getSort, throwIfNotValid } from '../utils'
@ -40,12 +41,12 @@ export class PluginModel extends Model<Partial<AttributesOnly<PluginModel>>> {
type: number type: number
@AllowNull(false) @AllowNull(false)
@Is('PluginVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version')) @Is('PluginVersion', value => throwIfNotValid(value, isPluginStableOrUnstableVersionValid, 'version'))
@Column @Column
version: string version: string
@AllowNull(true) @AllowNull(true)
@Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version')) @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginStableVersionValid, 'version'))
@Column @Column
latestVersion: string latestVersion: string

View file

@ -24,7 +24,13 @@ describe('Test CLI wrapper', function () {
before(async function () { before(async function () {
this.timeout(30000) this.timeout(30000)
server = await createSingleServer(1) server = await createSingleServer(1, {
rates_limit: {
login: {
max: 30
}
}
})
await setAccessTokensToServers([ server ]) await setAccessTokensToServers([ server ])
await server.users.create({ username: 'user_1', password: 'super_password' }) 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') 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 () { describe('Manage video redundancies', function () {

View file

@ -5,3 +5,4 @@ import './dns'
import './image' import './image'
import './markdown' import './markdown'
import './request' import './request'
import './validator'

View file

@ -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
})
})

View file

@ -69,7 +69,7 @@ async function pluginsListCLI (command: Command, options: OptionValues) {
const table = new CliTable3({ const table = new CliTable3({
head: [ 'name', 'version', 'homepage' ], head: [ 'name', 'version', 'homepage' ],
colWidths: [ 50, 10, 50 ] colWidths: [ 50, 20, 50 ]
}) as any }) as any
for (const plugin of data) { for (const plugin of data) {