]>
Commit | Line | Data |
---|---|---|
345da516 | 1 | import * as express from 'express' |
5e2b2e27 | 2 | import { body, param, query, ValidationChain } from 'express-validator' |
345da516 C |
3 | import { logger } from '../../helpers/logger' |
4 | import { areValidationErrors } from './utils' | |
b5f919ac | 5 | import { isNpmPluginNameValid, isPluginNameValid, isPluginTypeValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' |
345da516 | 6 | import { PluginManager } from '../../lib/plugins/plugin-manager' |
a02b93ce | 7 | import { isBooleanValid, isSafePath, toBooleanOrNull, exists, toIntOrNull } from '../../helpers/custom-validators/misc' |
ad91e700 | 8 | import { PluginModel } from '../../models/server/plugin' |
b5f919ac C |
9 | import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/install-plugin.model' |
10 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | |
6702a1b2 | 11 | import { CONFIG } from '../../initializers/config' |
2d53be02 | 12 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' |
345da516 | 13 | |
5e2b2e27 C |
14 | const getPluginValidator = (pluginType: PluginType, withVersion = true) => { |
15 | const validators: (ValidationChain | express.Handler)[] = [ | |
16 | param('pluginName').custom(isPluginNameValid).withMessage('Should have a valid plugin name') | |
17 | ] | |
345da516 | 18 | |
5e2b2e27 C |
19 | if (withVersion) { |
20 | validators.push( | |
21 | param('pluginVersion').custom(isPluginVersionValid).withMessage('Should have a valid plugin version') | |
22 | ) | |
23 | } | |
345da516 | 24 | |
5e2b2e27 C |
25 | return validators.concat([ |
26 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
27 | logger.debug('Checking getPluginValidator parameters', { parameters: req.params }) | |
28 | ||
29 | if (areValidationErrors(req, res)) return | |
30 | ||
31 | const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType) | |
32 | const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName) | |
33 | ||
2d53be02 RK |
34 | if (!plugin) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) |
35 | if (withVersion && plugin.version !== req.params.pluginVersion) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) | |
345da516 | 36 | |
5e2b2e27 | 37 | res.locals.registeredPlugin = plugin |
345da516 | 38 | |
5e2b2e27 | 39 | return next() |
345da516 | 40 | } |
5e2b2e27 C |
41 | ]) |
42 | } | |
43 | ||
4a8d113b C |
44 | const getExternalAuthValidator = [ |
45 | param('authName').custom(exists).withMessage('Should have a valid auth name'), | |
46 | ||
47 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
48 | logger.debug('Checking getExternalAuthValidator parameters', { parameters: req.params }) | |
49 | ||
50 | if (areValidationErrors(req, res)) return | |
51 | ||
52 | const plugin = res.locals.registeredPlugin | |
1896bca0 | 53 | if (!plugin.registerHelpers) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) |
4a8d113b | 54 | |
1896bca0 | 55 | const externalAuth = plugin.registerHelpers.getExternalAuths().find(a => a.authName === req.params.authName) |
2d53be02 | 56 | if (!externalAuth) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) |
4a8d113b C |
57 | |
58 | res.locals.externalAuth = externalAuth | |
59 | ||
60 | return next() | |
61 | } | |
62 | ] | |
63 | ||
5e2b2e27 C |
64 | const pluginStaticDirectoryValidator = [ |
65 | param('staticEndpoint').custom(isSafePath).withMessage('Should have a valid static endpoint'), | |
345da516 | 66 | |
5e2b2e27 C |
67 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
68 | logger.debug('Checking pluginStaticDirectoryValidator parameters', { parameters: req.params }) | |
69 | ||
70 | if (areValidationErrors(req, res)) return | |
345da516 C |
71 | |
72 | return next() | |
73 | } | |
74 | ] | |
75 | ||
ad91e700 | 76 | const listPluginsValidator = [ |
6702a1b2 | 77 | query('pluginType') |
ad91e700 | 78 | .optional() |
a02b93ce | 79 | .customSanitizer(toIntOrNull) |
ad91e700 C |
80 | .custom(isPluginTypeValid).withMessage('Should have a valid plugin type'), |
81 | query('uninstalled') | |
82 | .optional() | |
c8861d5d | 83 | .customSanitizer(toBooleanOrNull) |
ad91e700 C |
84 | .custom(isBooleanValid).withMessage('Should have a valid uninstalled attribute'), |
85 | ||
86 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
87 | logger.debug('Checking listPluginsValidator parameters', { parameters: req.query }) | |
88 | ||
89 | if (areValidationErrors(req, res)) return | |
90 | ||
91 | return next() | |
92 | } | |
93 | ] | |
94 | ||
b5f919ac | 95 | const installOrUpdatePluginValidator = [ |
8d2be0ed C |
96 | body('npmName') |
97 | .optional() | |
98 | .custom(isNpmPluginNameValid).withMessage('Should have a valid npm name'), | |
99 | body('path') | |
100 | .optional() | |
101 | .custom(isSafePath).withMessage('Should have a valid safe path'), | |
ad91e700 C |
102 | |
103 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
b5f919ac | 104 | logger.debug('Checking installOrUpdatePluginValidator parameters', { parameters: req.body }) |
ad91e700 C |
105 | |
106 | if (areValidationErrors(req, res)) return | |
107 | ||
b5f919ac | 108 | const body: InstallOrUpdatePlugin = req.body |
8d2be0ed | 109 | if (!body.path && !body.npmName) { |
2d53be02 | 110 | return res.status(HttpStatusCode.BAD_REQUEST_400) |
8d2be0ed C |
111 | .json({ error: 'Should have either a npmName or a path' }) |
112 | .end() | |
113 | } | |
114 | ||
ad91e700 C |
115 | return next() |
116 | } | |
117 | ] | |
118 | ||
119 | const uninstallPluginValidator = [ | |
120 | body('npmName').custom(isNpmPluginNameValid).withMessage('Should have a valid npm name'), | |
121 | ||
122 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
dba85a1e | 123 | logger.debug('Checking uninstallPluginValidator parameters', { parameters: req.body }) |
ad91e700 C |
124 | |
125 | if (areValidationErrors(req, res)) return | |
126 | ||
127 | return next() | |
128 | } | |
129 | ] | |
130 | ||
dba85a1e | 131 | const existingPluginValidator = [ |
60cfd4cb | 132 | param('npmName').custom(isNpmPluginNameValid).withMessage('Should have a valid plugin name'), |
ad91e700 C |
133 | |
134 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
dba85a1e | 135 | logger.debug('Checking enabledPluginValidator parameters', { parameters: req.params }) |
ad91e700 C |
136 | |
137 | if (areValidationErrors(req, res)) return | |
138 | ||
dba85a1e | 139 | const plugin = await PluginModel.loadByNpmName(req.params.npmName) |
ad91e700 | 140 | if (!plugin) { |
2d53be02 RK |
141 | return res.status(HttpStatusCode.NOT_FOUND_404) |
142 | .json({ error: 'Plugin not found' }) | |
143 | .end() | |
ad91e700 C |
144 | } |
145 | ||
146 | res.locals.plugin = plugin | |
147 | ||
148 | return next() | |
149 | } | |
150 | ] | |
151 | ||
152 | const updatePluginSettingsValidator = [ | |
153 | body('settings').exists().withMessage('Should have settings'), | |
154 | ||
155 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
156 | logger.debug('Checking enabledPluginValidator parameters', { parameters: req.body }) | |
157 | ||
158 | if (areValidationErrors(req, res)) return | |
159 | ||
160 | return next() | |
161 | } | |
162 | ] | |
163 | ||
6702a1b2 | 164 | const listAvailablePluginsValidator = [ |
6702a1b2 C |
165 | query('search') |
166 | .optional() | |
167 | .exists().withMessage('Should have a valid search'), | |
168 | query('pluginType') | |
169 | .optional() | |
a02b93ce | 170 | .customSanitizer(toIntOrNull) |
6702a1b2 | 171 | .custom(isPluginTypeValid).withMessage('Should have a valid plugin type'), |
09071200 C |
172 | query('currentPeerTubeEngine') |
173 | .optional() | |
174 | .custom(isPluginVersionValid).withMessage('Should have a valid current peertube engine'), | |
6702a1b2 C |
175 | |
176 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
177 | logger.debug('Checking enabledPluginValidator parameters', { parameters: req.query }) | |
178 | ||
179 | if (areValidationErrors(req, res)) return | |
180 | ||
181 | if (CONFIG.PLUGINS.INDEX.ENABLED === false) { | |
2d53be02 RK |
182 | return res.status(HttpStatusCode.BAD_REQUEST_400) |
183 | .json({ error: 'Plugin index is not enabled' }) | |
184 | .end() | |
6702a1b2 C |
185 | } |
186 | ||
187 | return next() | |
188 | } | |
189 | ] | |
190 | ||
345da516 C |
191 | // --------------------------------------------------------------------------- |
192 | ||
193 | export { | |
5e2b2e27 C |
194 | pluginStaticDirectoryValidator, |
195 | getPluginValidator, | |
ad91e700 C |
196 | updatePluginSettingsValidator, |
197 | uninstallPluginValidator, | |
6702a1b2 | 198 | listAvailablePluginsValidator, |
dba85a1e | 199 | existingPluginValidator, |
b5f919ac | 200 | installOrUpdatePluginValidator, |
4a8d113b C |
201 | listPluginsValidator, |
202 | getExternalAuthValidator | |
345da516 | 203 | } |