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