]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/plugins.ts
feature/ability to disable video history by default (#5728)
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / plugins.ts
CommitLineData
41fb13c3 1import express from 'express'
5e2b2e27 2import { body, param, query, ValidationChain } from 'express-validator'
c0e8b12e 3import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
428ccb8b
C
4import { PluginType } from '../../../shared/models/plugins/plugin.type'
5import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model'
6import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
ff91b644
C
7import {
8 isNpmPluginNameValid,
9 isPluginNameValid,
10 isPluginStableOrUnstableVersionValid,
11 isPluginTypeValid
12} from '../../helpers/custom-validators/plugins'
428ccb8b 13import { CONFIG } from '../../initializers/config'
345da516 14import { PluginManager } from '../../lib/plugins/plugin-manager'
ad91e700 15import { PluginModel } from '../../models/server/plugin'
10363c74 16import { areValidationErrors } from './shared'
345da516 17
5e2b2e27
C
18const getPluginValidator = (pluginType: PluginType, withVersion = true) => {
19 const validators: (ValidationChain | express.Handler)[] = [
396f6f01
C
20 param('pluginName')
21 .custom(isPluginNameValid)
5e2b2e27 22 ]
345da516 23
5e2b2e27
C
24 if (withVersion) {
25 validators.push(
396f6f01 26 param('pluginVersion')
ff91b644 27 .custom(isPluginStableOrUnstableVersionValid)
5e2b2e27
C
28 )
29 }
345da516 30
5e2b2e27
C
31 return validators.concat([
32 (req: express.Request, res: express.Response, next: express.NextFunction) => {
5e2b2e27
C
33 if (areValidationErrors(req, res)) return
34
35 const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType)
36 const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName)
37
76148b27
RK
38 if (!plugin) {
39 return res.fail({
40 status: HttpStatusCode.NOT_FOUND_404,
41 message: 'No plugin found named ' + npmName
42 })
43 }
44 if (withVersion && plugin.version !== req.params.pluginVersion) {
45 return res.fail({
46 status: HttpStatusCode.NOT_FOUND_404,
47 message: 'No plugin found named ' + npmName + ' with version ' + req.params.pluginVersion
48 })
49 }
345da516 50
5e2b2e27 51 res.locals.registeredPlugin = plugin
345da516 52
5e2b2e27 53 return next()
345da516 54 }
5e2b2e27
C
55 ])
56}
57
4a8d113b 58const getExternalAuthValidator = [
396f6f01
C
59 param('authName')
60 .custom(exists),
4a8d113b
C
61
62 (req: express.Request, res: express.Response, next: express.NextFunction) => {
4a8d113b
C
63 if (areValidationErrors(req, res)) return
64
65 const plugin = res.locals.registeredPlugin
76148b27
RK
66 if (!plugin.registerHelpers) {
67 return res.fail({
68 status: HttpStatusCode.NOT_FOUND_404,
69 message: 'No registered helpers were found for this plugin'
70 })
71 }
4a8d113b 72
1896bca0 73 const externalAuth = plugin.registerHelpers.getExternalAuths().find(a => a.authName === req.params.authName)
76148b27
RK
74 if (!externalAuth) {
75 return res.fail({
76 status: HttpStatusCode.NOT_FOUND_404,
77 message: 'No external auths were found for this plugin'
78 })
79 }
4a8d113b
C
80
81 res.locals.externalAuth = externalAuth
82
83 return next()
84 }
85]
86
5e2b2e27 87const pluginStaticDirectoryValidator = [
396f6f01
C
88 param('staticEndpoint')
89 .custom(isSafePath),
345da516 90
5e2b2e27 91 (req: express.Request, res: express.Response, next: express.NextFunction) => {
5e2b2e27 92 if (areValidationErrors(req, res)) return
345da516
C
93
94 return next()
95 }
96]
97
ad91e700 98const listPluginsValidator = [
6702a1b2 99 query('pluginType')
ad91e700 100 .optional()
a02b93ce 101 .customSanitizer(toIntOrNull)
396f6f01 102 .custom(isPluginTypeValid),
ad91e700
C
103 query('uninstalled')
104 .optional()
c8861d5d 105 .customSanitizer(toBooleanOrNull)
396f6f01 106 .custom(isBooleanValid),
ad91e700
C
107
108 (req: express.Request, res: express.Response, next: express.NextFunction) => {
ad91e700
C
109 if (areValidationErrors(req, res)) return
110
111 return next()
112 }
113]
114
b5f919ac 115const installOrUpdatePluginValidator = [
8d2be0ed
C
116 body('npmName')
117 .optional()
396f6f01 118 .custom(isNpmPluginNameValid),
3a1157a6
JL
119 body('pluginVersion')
120 .optional()
ff91b644 121 .custom(isPluginStableOrUnstableVersionValid),
8d2be0ed
C
122 body('path')
123 .optional()
396f6f01 124 .custom(isSafePath),
ad91e700
C
125
126 (req: express.Request, res: express.Response, next: express.NextFunction) => {
ad91e700
C
127 if (areValidationErrors(req, res)) return
128
b5f919ac 129 const body: InstallOrUpdatePlugin = req.body
8d2be0ed 130 if (!body.path && !body.npmName) {
76148b27 131 return res.fail({ message: 'Should have either a npmName or a path' })
8d2be0ed 132 }
3a1157a6
JL
133 if (body.pluginVersion && !body.npmName) {
134 return res.fail({ message: 'Should have a npmName when specifying a pluginVersion' })
135 }
8d2be0ed 136
ad91e700
C
137 return next()
138 }
139]
140
141const uninstallPluginValidator = [
396f6f01
C
142 body('npmName')
143 .custom(isNpmPluginNameValid),
ad91e700
C
144
145 (req: express.Request, res: express.Response, next: express.NextFunction) => {
ad91e700
C
146 if (areValidationErrors(req, res)) return
147
148 return next()
149 }
150]
151
dba85a1e 152const existingPluginValidator = [
396f6f01
C
153 param('npmName')
154 .custom(isNpmPluginNameValid),
ad91e700
C
155
156 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
ad91e700
C
157 if (areValidationErrors(req, res)) return
158
dba85a1e 159 const plugin = await PluginModel.loadByNpmName(req.params.npmName)
ad91e700 160 if (!plugin) {
76148b27
RK
161 return res.fail({
162 status: HttpStatusCode.NOT_FOUND_404,
163 message: 'Plugin not found'
164 })
ad91e700
C
165 }
166
167 res.locals.plugin = plugin
ad91e700
C
168 return next()
169 }
170]
171
172const updatePluginSettingsValidator = [
396f6f01
C
173 body('settings')
174 .exists(),
ad91e700
C
175
176 (req: express.Request, res: express.Response, next: express.NextFunction) => {
ad91e700
C
177 if (areValidationErrors(req, res)) return
178
179 return next()
180 }
181]
182
6702a1b2 183const listAvailablePluginsValidator = [
6702a1b2
C
184 query('search')
185 .optional()
396f6f01 186 .exists(),
6702a1b2
C
187 query('pluginType')
188 .optional()
a02b93ce 189 .customSanitizer(toIntOrNull)
396f6f01 190 .custom(isPluginTypeValid),
09071200
C
191 query('currentPeerTubeEngine')
192 .optional()
ff91b644 193 .custom(isPluginStableOrUnstableVersionValid),
6702a1b2
C
194
195 (req: express.Request, res: express.Response, next: express.NextFunction) => {
6702a1b2
C
196 if (areValidationErrors(req, res)) return
197
198 if (CONFIG.PLUGINS.INDEX.ENABLED === false) {
76148b27 199 return res.fail({ message: 'Plugin index is not enabled' })
6702a1b2
C
200 }
201
202 return next()
203 }
204]
205
345da516
C
206// ---------------------------------------------------------------------------
207
208export {
5e2b2e27
C
209 pluginStaticDirectoryValidator,
210 getPluginValidator,
ad91e700
C
211 updatePluginSettingsValidator,
212 uninstallPluginValidator,
6702a1b2 213 listAvailablePluginsValidator,
dba85a1e 214 existingPluginValidator,
b5f919ac 215 installOrUpdatePluginValidator,
4a8d113b
C
216 listPluginsValidator,
217 getExternalAuthValidator
345da516 218}