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