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