1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import { HttpStatusCode } from '@shared/core-utils'
6 checkBadCountPagination,
7 checkBadSortPagination,
8 checkBadStartPagination,
16 setAccessTokensToServers,
18 } from '@shared/extra-utils'
19 import { PeerTubePlugin, PluginType } from '@shared/models'
21 describe('Test server plugins API validators', function () {
22 let server: ServerInfo
23 let userAccessToken = null
25 const npmPlugin = 'peertube-plugin-hello-world'
26 const pluginName = 'hello-world'
27 let npmVersion: string
29 const themePlugin = 'peertube-theme-background-red'
30 const themeName = 'background-red'
31 let themeVersion: string
33 // ---------------------------------------------------------------
35 before(async function () {
38 server = await flushAndRunServer(1)
40 await setAccessTokensToServers([ server ])
47 await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
48 userAccessToken = await userLogin(server, user)
51 const res = await server.pluginsCommand.install({ npmName: npmPlugin })
52 const plugin = res.body as PeerTubePlugin
53 npmVersion = plugin.version
57 const res = await server.pluginsCommand.install({ npmName: themePlugin })
58 const plugin = res.body as PeerTubePlugin
59 themeVersion = plugin.version
63 describe('With static plugin routes', function () {
64 it('Should fail with an unknown plugin name/plugin version', async function () {
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'
74 for (const p of paths) {
75 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
79 it('Should fail when requesting a plugin in the theme path', async function () {
80 await makeGetRequest({
82 path: '/themes/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
83 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
87 it('Should fail with invalid versions', async function () {
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'
97 for (const p of paths) {
98 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
102 it('Should fail with invalid paths', async function () {
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'
111 for (const p of paths) {
112 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
116 it('Should fail with an unknown auth name', async function () {
117 const path = '/plugins/' + pluginName + '/' + npmVersion + '/auth/bad-auth'
119 await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
122 it('Should fail with an unknown static file', async function () {
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'
130 for (const p of paths) {
131 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
135 it('Should fail with an unknown CSS file', async function () {
136 await makeGetRequest({
138 path: '/themes/' + themeName + '/' + themeVersion + '/css/assets/fake.css',
139 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
143 it('Should succeed with the correct parameters', async function () {
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'
152 for (const p of paths) {
153 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.OK_200 })
156 const authPath = '/plugins/' + pluginName + '/' + npmVersion + '/auth/fake-auth'
157 await makeGetRequest({ url: server.url, path: authPath, statusCodeExpected: HttpStatusCode.FOUND_302 })
161 describe('When listing available plugins/themes', function () {
162 const path = '/api/v1/plugins/available'
164 search: 'super search',
165 pluginType: PluginType.PLUGIN,
166 currentPeerTubeEngine: '1.2.3'
169 it('Should fail with an invalid token', async function () {
170 await makeGetRequest({
175 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
179 it('Should fail if the user is not an administrator', async function () {
180 await makeGetRequest({
183 token: userAccessToken,
185 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
189 it('Should fail with a bad start pagination', async function () {
190 await checkBadStartPagination(server.url, path, server.accessToken)
193 it('Should fail with a bad count pagination', async function () {
194 await checkBadCountPagination(server.url, path, server.accessToken)
197 it('Should fail with an incorrect sort', async function () {
198 await checkBadSortPagination(server.url, path, server.accessToken)
201 it('Should fail with an invalid plugin type', async function () {
202 const query = { ...baseQuery, pluginType: 5 }
204 await makeGetRequest({
207 token: server.accessToken,
212 it('Should fail with an invalid current peertube engine', async function () {
213 const query = { ...baseQuery, currentPeerTubeEngine: '1.0' }
215 await makeGetRequest({
218 token: server.accessToken,
223 it('Should success with the correct parameters', async function () {
224 await makeGetRequest({
227 token: server.accessToken,
229 statusCodeExpected: HttpStatusCode.OK_200
234 describe('When listing local plugins/themes', function () {
235 const path = '/api/v1/plugins'
237 pluginType: PluginType.THEME
240 it('Should fail with an invalid token', async function () {
241 await makeGetRequest({
246 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
250 it('Should fail if the user is not an administrator', async function () {
251 await makeGetRequest({
254 token: userAccessToken,
256 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
260 it('Should fail with a bad start pagination', async function () {
261 await checkBadStartPagination(server.url, path, server.accessToken)
264 it('Should fail with a bad count pagination', async function () {
265 await checkBadCountPagination(server.url, path, server.accessToken)
268 it('Should fail with an incorrect sort', async function () {
269 await checkBadSortPagination(server.url, path, server.accessToken)
272 it('Should fail with an invalid plugin type', async function () {
273 const query = { ...baseQuery, pluginType: 5 }
275 await makeGetRequest({
278 token: server.accessToken,
283 it('Should success with the correct parameters', async function () {
284 await makeGetRequest({
287 token: server.accessToken,
289 statusCodeExpected: HttpStatusCode.OK_200
294 describe('When getting a plugin or the registered settings or public settings', function () {
295 const path = '/api/v1/plugins/'
297 it('Should fail with an invalid token', async function () {
298 for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) {
299 await makeGetRequest({
303 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
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({
313 token: userAccessToken,
314 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
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({
324 token: server.accessToken,
325 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
329 for (const suffix of [ 'peertube-plugin-TOTO', 'peertube-plugin-TOTO/registered-settings', 'peertube-plugin-TOTO/public-settings' ]) {
330 await makeGetRequest({
333 token: server.accessToken,
334 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
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({
344 token: server.accessToken,
345 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
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({
355 token: server.accessToken,
356 statusCodeExpected: HttpStatusCode.OK_200
362 describe('When updating plugin settings', function () {
363 const path = '/api/v1/plugins/'
364 const settings = { setting1: 'value1' }
366 it('Should fail with an invalid token', async function () {
367 await makePutBodyRequest({
369 path: path + npmPlugin + '/settings',
370 fields: { settings },
372 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
376 it('Should fail if the user is not an administrator', async function () {
377 await makePutBodyRequest({
379 path: path + npmPlugin + '/settings',
380 fields: { settings },
381 token: userAccessToken,
382 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
386 it('Should fail with an invalid npm name', async function () {
387 await makePutBodyRequest({
389 path: path + 'toto/settings',
390 fields: { settings },
391 token: server.accessToken,
392 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
395 await makePutBodyRequest({
397 path: path + 'peertube-plugin-TOTO/settings',
398 fields: { settings },
399 token: server.accessToken,
400 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
404 it('Should fail with an unknown plugin', async function () {
405 await makePutBodyRequest({
407 path: path + 'peertube-plugin-toto/settings',
408 fields: { settings },
409 token: server.accessToken,
410 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
414 it('Should succeed with the correct parameters', async function () {
415 await makePutBodyRequest({
417 path: path + npmPlugin + '/settings',
418 fields: { settings },
419 token: server.accessToken,
420 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
425 describe('When installing/updating/uninstalling a plugin', function () {
426 const path = '/api/v1/plugins/'
428 it('Should fail with an invalid token', async function () {
429 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
430 await makePostBodyRequest({
433 fields: { npmName: npmPlugin },
435 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
440 it('Should fail if the user is not an administrator', async function () {
441 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
442 await makePostBodyRequest({
445 fields: { npmName: npmPlugin },
446 token: userAccessToken,
447 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
452 it('Should fail with an invalid npm name', async function () {
453 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
454 await makePostBodyRequest({
457 fields: { npmName: 'toto' },
458 token: server.accessToken,
459 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
463 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
464 await makePostBodyRequest({
467 fields: { npmName: 'peertube-plugin-TOTO' },
468 token: server.accessToken,
469 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
474 it('Should succeed with the correct parameters', async function () {
478 { suffix: 'install', status: HttpStatusCode.OK_200 },
479 { suffix: 'update', status: HttpStatusCode.OK_200 },
480 { suffix: 'uninstall', status: HttpStatusCode.NO_CONTENT_204 }
483 for (const obj of it) {
484 await makePostBodyRequest({
486 path: path + obj.suffix,
487 fields: { npmName: npmPlugin },
488 token: server.accessToken,
489 statusCodeExpected: obj.status
495 after(async function () {
496 await cleanupTests([ server ])