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