]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/check-params/plugins.ts
Introduce blacklist command
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / plugins.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import { HttpStatusCode } from '@shared/core-utils'
5 import {
6 checkBadCountPagination,
7 checkBadSortPagination,
8 checkBadStartPagination,
9 cleanupTests,
10 createUser,
11 flushAndRunServer,
12 immutableAssign,
13 makeGetRequest,
14 makePostBodyRequest,
15 makePutBodyRequest,
16 ServerInfo,
17 setAccessTokensToServers,
18 userLogin
19 } from '@shared/extra-utils'
20 import { PeerTubePlugin, PluginType } from '@shared/models'
21
22 describe('Test server plugins API validators', function () {
23 let server: ServerInfo
24 let userAccessToken = null
25
26 const npmPlugin = 'peertube-plugin-hello-world'
27 const pluginName = 'hello-world'
28 let npmVersion: string
29
30 const themePlugin = 'peertube-theme-background-red'
31 const themeName = 'background-red'
32 let themeVersion: string
33
34 // ---------------------------------------------------------------
35
36 before(async function () {
37 this.timeout(30000)
38
39 server = await flushAndRunServer(1)
40
41 await setAccessTokensToServers([ server ])
42
43 const user = {
44 username: 'user1',
45 password: 'password'
46 }
47
48 await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
49 userAccessToken = await userLogin(server, user)
50
51 {
52 const res = await server.pluginsCommand.install({ npmName: npmPlugin })
53 const plugin = res.body as PeerTubePlugin
54 npmVersion = plugin.version
55 }
56
57 {
58 const res = await server.pluginsCommand.install({ npmName: themePlugin })
59 const plugin = res.body as PeerTubePlugin
60 themeVersion = plugin.version
61 }
62 })
63
64 describe('With static plugin routes', function () {
65 it('Should fail with an unknown plugin name/plugin version', async function () {
66 const paths = [
67 '/plugins/' + pluginName + '/0.0.1/auth/fake-auth',
68 '/plugins/' + pluginName + '/0.0.1/static/images/chocobo.png',
69 '/plugins/' + pluginName + '/0.0.1/client-scripts/client/common-client-plugin.js',
70 '/themes/' + themeName + '/0.0.1/static/images/chocobo.png',
71 '/themes/' + themeName + '/0.0.1/client-scripts/client/video-watch-client-plugin.js',
72 '/themes/' + themeName + '/0.0.1/css/assets/style1.css'
73 ]
74
75 for (const p of paths) {
76 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
77 }
78 })
79
80 it('Should fail when requesting a plugin in the theme path', async function () {
81 await makeGetRequest({
82 url: server.url,
83 path: '/themes/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
84 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
85 })
86 })
87
88 it('Should fail with invalid versions', async function () {
89 const paths = [
90 '/plugins/' + pluginName + '/0.0.1.1/auth/fake-auth',
91 '/plugins/' + pluginName + '/0.0.1.1/static/images/chocobo.png',
92 '/plugins/' + pluginName + '/0.1/client-scripts/client/common-client-plugin.js',
93 '/themes/' + themeName + '/1/static/images/chocobo.png',
94 '/themes/' + themeName + '/0.0.1000a/client-scripts/client/video-watch-client-plugin.js',
95 '/themes/' + themeName + '/0.a.1/css/assets/style1.css'
96 ]
97
98 for (const p of paths) {
99 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
100 }
101 })
102
103 it('Should fail with invalid paths', async function () {
104 const paths = [
105 '/plugins/' + pluginName + '/' + npmVersion + '/static/images/../chocobo.png',
106 '/plugins/' + pluginName + '/' + npmVersion + '/client-scripts/../client/common-client-plugin.js',
107 '/themes/' + themeName + '/' + themeVersion + '/static/../images/chocobo.png',
108 '/themes/' + themeName + '/' + themeVersion + '/client-scripts/client/video-watch-client-plugin.js/..',
109 '/themes/' + themeName + '/' + themeVersion + '/css/../assets/style1.css'
110 ]
111
112 for (const p of paths) {
113 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
114 }
115 })
116
117 it('Should fail with an unknown auth name', async function () {
118 const path = '/plugins/' + pluginName + '/' + npmVersion + '/auth/bad-auth'
119
120 await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
121 })
122
123 it('Should fail with an unknown static file', async function () {
124 const paths = [
125 '/plugins/' + pluginName + '/' + npmVersion + '/static/fake/chocobo.png',
126 '/plugins/' + pluginName + '/' + npmVersion + '/client-scripts/client/fake.js',
127 '/themes/' + themeName + '/' + themeVersion + '/static/fake/chocobo.png',
128 '/themes/' + themeName + '/' + themeVersion + '/client-scripts/client/fake.js'
129 ]
130
131 for (const p of paths) {
132 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
133 }
134 })
135
136 it('Should fail with an unknown CSS file', async function () {
137 await makeGetRequest({
138 url: server.url,
139 path: '/themes/' + themeName + '/' + themeVersion + '/css/assets/fake.css',
140 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
141 })
142 })
143
144 it('Should succeed with the correct parameters', async function () {
145 const paths = [
146 '/plugins/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
147 '/plugins/' + pluginName + '/' + npmVersion + '/client-scripts/client/common-client-plugin.js',
148 '/themes/' + themeName + '/' + themeVersion + '/static/images/chocobo.png',
149 '/themes/' + themeName + '/' + themeVersion + '/client-scripts/client/video-watch-client-plugin.js',
150 '/themes/' + themeName + '/' + themeVersion + '/css/assets/style1.css'
151 ]
152
153 for (const p of paths) {
154 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.OK_200 })
155 }
156
157 const authPath = '/plugins/' + pluginName + '/' + npmVersion + '/auth/fake-auth'
158 await makeGetRequest({ url: server.url, path: authPath, statusCodeExpected: HttpStatusCode.FOUND_302 })
159 })
160 })
161
162 describe('When listing available plugins/themes', function () {
163 const path = '/api/v1/plugins/available'
164 const baseQuery = {
165 search: 'super search',
166 pluginType: PluginType.PLUGIN,
167 currentPeerTubeEngine: '1.2.3'
168 }
169
170 it('Should fail with an invalid token', async function () {
171 await makeGetRequest({
172 url: server.url,
173 path,
174 token: 'fake_token',
175 query: baseQuery,
176 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
177 })
178 })
179
180 it('Should fail if the user is not an administrator', async function () {
181 await makeGetRequest({
182 url: server.url,
183 path,
184 token: userAccessToken,
185 query: baseQuery,
186 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
187 })
188 })
189
190 it('Should fail with a bad start pagination', async function () {
191 await checkBadStartPagination(server.url, path, server.accessToken)
192 })
193
194 it('Should fail with a bad count pagination', async function () {
195 await checkBadCountPagination(server.url, path, server.accessToken)
196 })
197
198 it('Should fail with an incorrect sort', async function () {
199 await checkBadSortPagination(server.url, path, server.accessToken)
200 })
201
202 it('Should fail with an invalid plugin type', async function () {
203 const query = immutableAssign(baseQuery, { pluginType: 5 })
204
205 await makeGetRequest({
206 url: server.url,
207 path,
208 token: server.accessToken,
209 query
210 })
211 })
212
213 it('Should fail with an invalid current peertube engine', async function () {
214 const query = immutableAssign(baseQuery, { currentPeerTubeEngine: '1.0' })
215
216 await makeGetRequest({
217 url: server.url,
218 path,
219 token: server.accessToken,
220 query
221 })
222 })
223
224 it('Should success with the correct parameters', async function () {
225 await makeGetRequest({
226 url: server.url,
227 path,
228 token: server.accessToken,
229 query: baseQuery,
230 statusCodeExpected: HttpStatusCode.OK_200
231 })
232 })
233 })
234
235 describe('When listing local plugins/themes', function () {
236 const path = '/api/v1/plugins'
237 const baseQuery = {
238 pluginType: PluginType.THEME
239 }
240
241 it('Should fail with an invalid token', async function () {
242 await makeGetRequest({
243 url: server.url,
244 path,
245 token: 'fake_token',
246 query: baseQuery,
247 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
248 })
249 })
250
251 it('Should fail if the user is not an administrator', async function () {
252 await makeGetRequest({
253 url: server.url,
254 path,
255 token: userAccessToken,
256 query: baseQuery,
257 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
258 })
259 })
260
261 it('Should fail with a bad start pagination', async function () {
262 await checkBadStartPagination(server.url, path, server.accessToken)
263 })
264
265 it('Should fail with a bad count pagination', async function () {
266 await checkBadCountPagination(server.url, path, server.accessToken)
267 })
268
269 it('Should fail with an incorrect sort', async function () {
270 await checkBadSortPagination(server.url, path, server.accessToken)
271 })
272
273 it('Should fail with an invalid plugin type', async function () {
274 const query = immutableAssign(baseQuery, { pluginType: 5 })
275
276 await makeGetRequest({
277 url: server.url,
278 path,
279 token: server.accessToken,
280 query
281 })
282 })
283
284 it('Should success with the correct parameters', async function () {
285 await makeGetRequest({
286 url: server.url,
287 path,
288 token: server.accessToken,
289 query: baseQuery,
290 statusCodeExpected: HttpStatusCode.OK_200
291 })
292 })
293 })
294
295 describe('When getting a plugin or the registered settings or public settings', function () {
296 const path = '/api/v1/plugins/'
297
298 it('Should fail with an invalid token', async function () {
299 for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) {
300 await makeGetRequest({
301 url: server.url,
302 path: path + suffix,
303 token: 'fake_token',
304 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
305 })
306 }
307 })
308
309 it('Should fail if the user is not an administrator', async function () {
310 for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) {
311 await makeGetRequest({
312 url: server.url,
313 path: path + suffix,
314 token: userAccessToken,
315 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
316 })
317 }
318 })
319
320 it('Should fail with an invalid npm name', async function () {
321 for (const suffix of [ 'toto', 'toto/registered-settings', 'toto/public-settings' ]) {
322 await makeGetRequest({
323 url: server.url,
324 path: path + suffix,
325 token: server.accessToken,
326 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
327 })
328 }
329
330 for (const suffix of [ 'peertube-plugin-TOTO', 'peertube-plugin-TOTO/registered-settings', 'peertube-plugin-TOTO/public-settings' ]) {
331 await makeGetRequest({
332 url: server.url,
333 path: path + suffix,
334 token: server.accessToken,
335 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
336 })
337 }
338 })
339
340 it('Should fail with an unknown plugin', async function () {
341 for (const suffix of [ 'peertube-plugin-toto', 'peertube-plugin-toto/registered-settings', 'peertube-plugin-toto/public-settings' ]) {
342 await makeGetRequest({
343 url: server.url,
344 path: path + suffix,
345 token: server.accessToken,
346 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
347 })
348 }
349 })
350
351 it('Should succeed with the correct parameters', async function () {
352 for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings`, `${npmPlugin}/public-settings` ]) {
353 await makeGetRequest({
354 url: server.url,
355 path: path + suffix,
356 token: server.accessToken,
357 statusCodeExpected: HttpStatusCode.OK_200
358 })
359 }
360 })
361 })
362
363 describe('When updating plugin settings', function () {
364 const path = '/api/v1/plugins/'
365 const settings = { setting1: 'value1' }
366
367 it('Should fail with an invalid token', async function () {
368 await makePutBodyRequest({
369 url: server.url,
370 path: path + npmPlugin + '/settings',
371 fields: { settings },
372 token: 'fake_token',
373 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
374 })
375 })
376
377 it('Should fail if the user is not an administrator', async function () {
378 await makePutBodyRequest({
379 url: server.url,
380 path: path + npmPlugin + '/settings',
381 fields: { settings },
382 token: userAccessToken,
383 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
384 })
385 })
386
387 it('Should fail with an invalid npm name', async function () {
388 await makePutBodyRequest({
389 url: server.url,
390 path: path + 'toto/settings',
391 fields: { settings },
392 token: server.accessToken,
393 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
394 })
395
396 await makePutBodyRequest({
397 url: server.url,
398 path: path + 'peertube-plugin-TOTO/settings',
399 fields: { settings },
400 token: server.accessToken,
401 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
402 })
403 })
404
405 it('Should fail with an unknown plugin', async function () {
406 await makePutBodyRequest({
407 url: server.url,
408 path: path + 'peertube-plugin-toto/settings',
409 fields: { settings },
410 token: server.accessToken,
411 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
412 })
413 })
414
415 it('Should succeed with the correct parameters', async function () {
416 await makePutBodyRequest({
417 url: server.url,
418 path: path + npmPlugin + '/settings',
419 fields: { settings },
420 token: server.accessToken,
421 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
422 })
423 })
424 })
425
426 describe('When installing/updating/uninstalling a plugin', function () {
427 const path = '/api/v1/plugins/'
428
429 it('Should fail with an invalid token', async function () {
430 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
431 await makePostBodyRequest({
432 url: server.url,
433 path: path + suffix,
434 fields: { npmName: npmPlugin },
435 token: 'fake_token',
436 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
437 })
438 }
439 })
440
441 it('Should fail if the user is not an administrator', async function () {
442 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
443 await makePostBodyRequest({
444 url: server.url,
445 path: path + suffix,
446 fields: { npmName: npmPlugin },
447 token: userAccessToken,
448 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
449 })
450 }
451 })
452
453 it('Should fail with an invalid npm name', async function () {
454 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
455 await makePostBodyRequest({
456 url: server.url,
457 path: path + suffix,
458 fields: { npmName: 'toto' },
459 token: server.accessToken,
460 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
461 })
462 }
463
464 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
465 await makePostBodyRequest({
466 url: server.url,
467 path: path + suffix,
468 fields: { npmName: 'peertube-plugin-TOTO' },
469 token: server.accessToken,
470 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
471 })
472 }
473 })
474
475 it('Should succeed with the correct parameters', async function () {
476 this.timeout(10000)
477
478 const it = [
479 { suffix: 'install', status: HttpStatusCode.OK_200 },
480 { suffix: 'update', status: HttpStatusCode.OK_200 },
481 { suffix: 'uninstall', status: HttpStatusCode.NO_CONTENT_204 }
482 ]
483
484 for (const obj of it) {
485 await makePostBodyRequest({
486 url: server.url,
487 path: path + obj.suffix,
488 fields: { npmName: npmPlugin },
489 token: server.accessToken,
490 statusCodeExpected: obj.status
491 })
492 }
493 })
494 })
495
496 after(async function () {
497 await cleanupTests([ server ])
498 })
499 })