]>
Commit | Line | Data |
---|---|---|
1 | import express from 'express' | |
2 | import { body, param, query, ValidationChain } from 'express-validator' | |
3 | import { HttpStatusCode } from '../../../shared/models/http/http-error-codes' | |
4 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | |
5 | import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/server/api/install-plugin.model' | |
6 | import { exists, isBooleanValid, isSafePath, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' | |
7 | import { | |
8 | isNpmPluginNameValid, | |
9 | isPluginNameValid, | |
10 | isPluginStableOrUnstableVersionValid, | |
11 | isPluginTypeValid | |
12 | } from '../../helpers/custom-validators/plugins' | |
13 | import { CONFIG } from '../../initializers/config' | |
14 | import { PluginManager } from '../../lib/plugins/plugin-manager' | |
15 | import { PluginModel } from '../../models/server/plugin' | |
16 | import { areValidationErrors } from './shared' | |
17 | ||
18 | const getPluginValidator = (pluginType: PluginType, withVersion = true) => { | |
19 | const validators: (ValidationChain | express.Handler)[] = [ | |
20 | param('pluginName') | |
21 | .custom(isPluginNameValid) | |
22 | ] | |
23 | ||
24 | if (withVersion) { | |
25 | validators.push( | |
26 | param('pluginVersion') | |
27 | .custom(isPluginStableOrUnstableVersionValid) | |
28 | ) | |
29 | } | |
30 | ||
31 | return validators.concat([ | |
32 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
33 | if (areValidationErrors(req, res)) return | |
34 | ||
35 | const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType) | |
36 | const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName) | |
37 | ||
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 | } | |
50 | ||
51 | res.locals.registeredPlugin = plugin | |
52 | ||
53 | return next() | |
54 | } | |
55 | ]) | |
56 | } | |
57 | ||
58 | const getExternalAuthValidator = [ | |
59 | param('authName') | |
60 | .custom(exists), | |
61 | ||
62 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
63 | if (areValidationErrors(req, res)) return | |
64 | ||
65 | const plugin = res.locals.registeredPlugin | |
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 | } | |
72 | ||
73 | const externalAuth = plugin.registerHelpers.getExternalAuths().find(a => a.authName === req.params.authName) | |
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 | } | |
80 | ||
81 | res.locals.externalAuth = externalAuth | |
82 | ||
83 | return next() | |
84 | } | |
85 | ] | |
86 | ||
87 | const pluginStaticDirectoryValidator = [ | |
88 | param('staticEndpoint') | |
89 | .custom(isSafePath), | |
90 | ||
91 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
92 | if (areValidationErrors(req, res)) return | |
93 | ||
94 | return next() | |
95 | } | |
96 | ] | |
97 | ||
98 | const listPluginsValidator = [ | |
99 | query('pluginType') | |
100 | .optional() | |
101 | .customSanitizer(toIntOrNull) | |
102 | .custom(isPluginTypeValid), | |
103 | query('uninstalled') | |
104 | .optional() | |
105 | .customSanitizer(toBooleanOrNull) | |
106 | .custom(isBooleanValid), | |
107 | ||
108 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
109 | if (areValidationErrors(req, res)) return | |
110 | ||
111 | return next() | |
112 | } | |
113 | ] | |
114 | ||
115 | const installOrUpdatePluginValidator = [ | |
116 | body('npmName') | |
117 | .optional() | |
118 | .custom(isNpmPluginNameValid), | |
119 | body('pluginVersion') | |
120 | .optional() | |
121 | .custom(isPluginStableOrUnstableVersionValid), | |
122 | body('path') | |
123 | .optional() | |
124 | .custom(isSafePath), | |
125 | ||
126 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
127 | if (areValidationErrors(req, res)) return | |
128 | ||
129 | const body: InstallOrUpdatePlugin = req.body | |
130 | if (!body.path && !body.npmName) { | |
131 | return res.fail({ message: 'Should have either a npmName or a path' }) | |
132 | } | |
133 | if (body.pluginVersion && !body.npmName) { | |
134 | return res.fail({ message: 'Should have a npmName when specifying a pluginVersion' }) | |
135 | } | |
136 | ||
137 | return next() | |
138 | } | |
139 | ] | |
140 | ||
141 | const uninstallPluginValidator = [ | |
142 | body('npmName') | |
143 | .custom(isNpmPluginNameValid), | |
144 | ||
145 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
146 | if (areValidationErrors(req, res)) return | |
147 | ||
148 | return next() | |
149 | } | |
150 | ] | |
151 | ||
152 | const existingPluginValidator = [ | |
153 | param('npmName') | |
154 | .custom(isNpmPluginNameValid), | |
155 | ||
156 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
157 | if (areValidationErrors(req, res)) return | |
158 | ||
159 | const plugin = await PluginModel.loadByNpmName(req.params.npmName) | |
160 | if (!plugin) { | |
161 | return res.fail({ | |
162 | status: HttpStatusCode.NOT_FOUND_404, | |
163 | message: 'Plugin not found' | |
164 | }) | |
165 | } | |
166 | ||
167 | res.locals.plugin = plugin | |
168 | return next() | |
169 | } | |
170 | ] | |
171 | ||
172 | const updatePluginSettingsValidator = [ | |
173 | body('settings') | |
174 | .exists(), | |
175 | ||
176 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
177 | if (areValidationErrors(req, res)) return | |
178 | ||
179 | return next() | |
180 | } | |
181 | ] | |
182 | ||
183 | const listAvailablePluginsValidator = [ | |
184 | query('search') | |
185 | .optional() | |
186 | .exists(), | |
187 | query('pluginType') | |
188 | .optional() | |
189 | .customSanitizer(toIntOrNull) | |
190 | .custom(isPluginTypeValid), | |
191 | query('currentPeerTubeEngine') | |
192 | .optional() | |
193 | .custom(isPluginStableOrUnstableVersionValid), | |
194 | ||
195 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | |
196 | if (areValidationErrors(req, res)) return | |
197 | ||
198 | if (CONFIG.PLUGINS.INDEX.ENABLED === false) { | |
199 | return res.fail({ message: 'Plugin index is not enabled' }) | |
200 | } | |
201 | ||
202 | return next() | |
203 | } | |
204 | ] | |
205 | ||
206 | // --------------------------------------------------------------------------- | |
207 | ||
208 | export { | |
209 | pluginStaticDirectoryValidator, | |
210 | getPluginValidator, | |
211 | updatePluginSettingsValidator, | |
212 | uninstallPluginValidator, | |
213 | listAvailablePluginsValidator, | |
214 | existingPluginValidator, | |
215 | installOrUpdatePluginValidator, | |
216 | listPluginsValidator, | |
217 | getExternalAuthValidator | |
218 | } |