X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fhelpers%2Fcustom-validators%2Fplugins.ts;h=a20de0c4a66a2ff094736d245857c1b4ed167713;hb=HEAD;hp=b5e32abc26839c70eba277499b7488409ddd3bb1;hpb=d75db01f14138ea660c4c519e37ab05228b39d13;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/helpers/custom-validators/plugins.ts b/server/helpers/custom-validators/plugins.ts index b5e32abc2..a20de0c4a 100644 --- a/server/helpers/custom-validators/plugins.ts +++ b/server/helpers/custom-validators/plugins.ts @@ -1,26 +1,27 @@ -import { exists, isArray, isSafePath } from './misc' -import * as 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 { 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 function isPluginTypeValid (value: any) { - return exists(value) && validator.isInt('' + value) && PluginType[value] !== undefined + return exists(value) && + (value === PluginType.PLUGIN || value === PluginType.THEME) } function isPluginNameValid (value: string) { return exists(value) && validator.isLength(value, PLUGINS_CONSTRAINTS_FIELDS.NAME) && - validator.matches(value, /^[a-z\-]+$/) + validator.matches(value, /^[a-z-0-9]+$/) } function isNpmPluginNameValid (value: string) { return exists(value) && validator.isLength(value, PLUGINS_CONSTRAINTS_FIELDS.NAME) && - validator.matches(value, /^[a-z\-]+$/) && + validator.matches(value, /^[a-z\-._0-9]+$/) && (value.startsWith('peertube-plugin-') || value.startsWith('peertube-theme-')) } @@ -28,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('.') @@ -36,12 +37,29 @@ 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) } function isPluginHomepage (value: string) { - return isUrlValid(value) + return exists(value) && (!value || isUrlValid(value)) +} + +function isPluginBugs (value: string) { + return exists(value) && (!value || isUrlValid(value)) } function areStaticDirectoriesValid (staticDirs: any) { @@ -79,23 +97,71 @@ function isThemeNameValid (name: string) { return isPluginNameValid(name) } -function isPackageJSONValid (packageJSON: PluginPackageJson, pluginType: PluginType) { - return isNpmPluginNameValid(packageJSON.name) && - isPluginDescriptionValid(packageJSON.description) && - isPluginEngineValid(packageJSON.engine) && - isPluginHomepage(packageJSON.homepage) && - exists(packageJSON.author) && - isUrlValid(packageJSON.bugs) && - (pluginType === PluginType.THEME || isSafePath(packageJSON.library)) && - areStaticDirectoriesValid(packageJSON.staticDirs) && - areCSSPathsValid(packageJSON.css) && - areClientScriptsValid(packageJSON.clientScripts) && - areTranslationPathsValid(packageJSON.translations) +function isPackageJSONValid (packageJSON: PluginPackageJSON, pluginType: PluginType) { + let result = true + const badFields: string[] = [] + + if (!isNpmPluginNameValid(packageJSON.name)) { + result = false + badFields.push('name') + } + + if (!isPluginDescriptionValid(packageJSON.description)) { + result = false + badFields.push('description') + } + + if (!isPluginEngineValid(packageJSON.engine)) { + result = false + badFields.push('engine') + } + + if (!isPluginHomepage(packageJSON.homepage)) { + result = false + badFields.push('homepage') + } + + if (!exists(packageJSON.author)) { + result = false + badFields.push('author') + } + + if (!isPluginBugs(packageJSON.bugs)) { + result = false + badFields.push('bugs') + } + + if (pluginType === PluginType.PLUGIN && !isSafePath(packageJSON.library)) { + result = false + badFields.push('library') + } + + if (!areStaticDirectoriesValid(packageJSON.staticDirs)) { + result = false + badFields.push('staticDirs') + } + + if (!areCSSPathsValid(packageJSON.css)) { + result = false + badFields.push('css') + } + + if (!areClientScriptsValid(packageJSON.clientScripts)) { + result = false + badFields.push('clientScripts') + } + + if (!areTranslationPathsValid(packageJSON.translations)) { + result = false + badFields.push('translations') + } + + return { result, badFields } } function isLibraryCodeValid (library: any) { - return typeof library.register === 'function' - && typeof library.unregister === 'function' + return typeof library.register === 'function' && + typeof library.unregister === 'function' } export { @@ -103,7 +169,8 @@ export { isPackageJSONValid, isThemeNameValid, isPluginHomepage, - isPluginVersionValid, + isPluginStableVersionValid, + isPluginStableOrUnstableVersionValid, isPluginNameValid, isPluginDescriptionValid, isLibraryCodeValid,