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,
15 setAccessTokensToServers
16 } from '@shared/extra-utils'
17 import { PeerTubePlugin, PluginType } from '@shared/models'
19 describe('Test server plugins API validators', function () {
20 let server: ServerInfo
21 let userAccessToken = null
23 const npmPlugin = 'peertube-plugin-hello-world'
24 const pluginName = 'hello-world'
25 let npmVersion: string
27 const themePlugin = 'peertube-theme-background-red'
28 const themeName = 'background-red'
29 let themeVersion: string
31 // ---------------------------------------------------------------
33 before(async function () {
36 server = await flushAndRunServer(1)
38 await setAccessTokensToServers([ server ])
45 await server.usersCommand.create({ username: user.username, password: user.password })
46 userAccessToken = await server.loginCommand.getAccessToken(user)
49 const res = await server.pluginsCommand.install({ npmName: npmPlugin })
50 const plugin = res.body as PeerTubePlugin
51 npmVersion = plugin.version
55 const res = await server.pluginsCommand.install({ npmName: themePlugin })
56 const plugin = res.body as PeerTubePlugin
57 themeVersion = plugin.version
61 describe('With static plugin routes', function () {
62 it('Should fail with an unknown plugin name/plugin version', async function () {
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'
72 for (const p of paths) {
73 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
77 it('Should fail when requesting a plugin in the theme path', async function () {
78 await makeGetRequest({
80 path: '/themes/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
81 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
85 it('Should fail with invalid versions', async function () {
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'
95 for (const p of paths) {
96 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
100 it('Should fail with invalid paths', async function () {
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'
109 for (const p of paths) {
110 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.BAD_REQUEST_400 })
114 it('Should fail with an unknown auth name', async function () {
115 const path = '/plugins/' + pluginName + '/' + npmVersion + '/auth/bad-auth'
117 await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
120 it('Should fail with an unknown static file', async function () {
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'
128 for (const p of paths) {
129 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.NOT_FOUND_404 })
133 it('Should fail with an unknown CSS file', async function () {
134 await makeGetRequest({
136 path: '/themes/' + themeName + '/' + themeVersion + '/css/assets/fake.css',
137 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
141 it('Should succeed with the correct parameters', async function () {
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'
150 for (const p of paths) {
151 await makeGetRequest({ url: server.url, path: p, statusCodeExpected: HttpStatusCode.OK_200 })
154 const authPath = '/plugins/' + pluginName + '/' + npmVersion + '/auth/fake-auth'
155 await makeGetRequest({ url: server.url, path: authPath, statusCodeExpected: HttpStatusCode.FOUND_302 })
159 describe('When listing available plugins/themes', function () {
160 const path = '/api/v1/plugins/available'
162 search: 'super search',
163 pluginType: PluginType.PLUGIN,
164 currentPeerTubeEngine: '1.2.3'
167 it('Should fail with an invalid token', async function () {
168 await makeGetRequest({
173 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
177 it('Should fail if the user is not an administrator', async function () {
178 await makeGetRequest({
181 token: userAccessToken,
183 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
187 it('Should fail with a bad start pagination', async function () {
188 await checkBadStartPagination(server.url, path, server.accessToken)
191 it('Should fail with a bad count pagination', async function () {
192 await checkBadCountPagination(server.url, path, server.accessToken)
195 it('Should fail with an incorrect sort', async function () {
196 await checkBadSortPagination(server.url, path, server.accessToken)
199 it('Should fail with an invalid plugin type', async function () {
200 const query = { ...baseQuery, pluginType: 5 }
202 await makeGetRequest({
205 token: server.accessToken,
210 it('Should fail with an invalid current peertube engine', async function () {
211 const query = { ...baseQuery, currentPeerTubeEngine: '1.0' }
213 await makeGetRequest({
216 token: server.accessToken,
221 it('Should success with the correct parameters', async function () {
222 await makeGetRequest({
225 token: server.accessToken,
227 statusCodeExpected: HttpStatusCode.OK_200
232 describe('When listing local plugins/themes', function () {
233 const path = '/api/v1/plugins'
235 pluginType: PluginType.THEME
238 it('Should fail with an invalid token', async function () {
239 await makeGetRequest({
244 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
248 it('Should fail if the user is not an administrator', async function () {
249 await makeGetRequest({
252 token: userAccessToken,
254 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
258 it('Should fail with a bad start pagination', async function () {
259 await checkBadStartPagination(server.url, path, server.accessToken)
262 it('Should fail with a bad count pagination', async function () {
263 await checkBadCountPagination(server.url, path, server.accessToken)
266 it('Should fail with an incorrect sort', async function () {
267 await checkBadSortPagination(server.url, path, server.accessToken)
270 it('Should fail with an invalid plugin type', async function () {
271 const query = { ...baseQuery, pluginType: 5 }
273 await makeGetRequest({
276 token: server.accessToken,
281 it('Should success with the correct parameters', async function () {
282 await makeGetRequest({
285 token: server.accessToken,
287 statusCodeExpected: HttpStatusCode.OK_200
292 describe('When getting a plugin or the registered settings or public settings', function () {
293 const path = '/api/v1/plugins/'
295 it('Should fail with an invalid token', async function () {
296 for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) {
297 await makeGetRequest({
301 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
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({
311 token: userAccessToken,
312 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
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({
322 token: server.accessToken,
323 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
327 for (const suffix of [ 'peertube-plugin-TOTO', 'peertube-plugin-TOTO/registered-settings', 'peertube-plugin-TOTO/public-settings' ]) {
328 await makeGetRequest({
331 token: server.accessToken,
332 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
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({
342 token: server.accessToken,
343 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
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({
353 token: server.accessToken,
354 statusCodeExpected: HttpStatusCode.OK_200
360 describe('When updating plugin settings', function () {
361 const path = '/api/v1/plugins/'
362 const settings = { setting1: 'value1' }
364 it('Should fail with an invalid token', async function () {
365 await makePutBodyRequest({
367 path: path + npmPlugin + '/settings',
368 fields: { settings },
370 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
374 it('Should fail if the user is not an administrator', async function () {
375 await makePutBodyRequest({
377 path: path + npmPlugin + '/settings',
378 fields: { settings },
379 token: userAccessToken,
380 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
384 it('Should fail with an invalid npm name', async function () {
385 await makePutBodyRequest({
387 path: path + 'toto/settings',
388 fields: { settings },
389 token: server.accessToken,
390 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
393 await makePutBodyRequest({
395 path: path + 'peertube-plugin-TOTO/settings',
396 fields: { settings },
397 token: server.accessToken,
398 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
402 it('Should fail with an unknown plugin', async function () {
403 await makePutBodyRequest({
405 path: path + 'peertube-plugin-toto/settings',
406 fields: { settings },
407 token: server.accessToken,
408 statusCodeExpected: HttpStatusCode.NOT_FOUND_404
412 it('Should succeed with the correct parameters', async function () {
413 await makePutBodyRequest({
415 path: path + npmPlugin + '/settings',
416 fields: { settings },
417 token: server.accessToken,
418 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
423 describe('When installing/updating/uninstalling a plugin', function () {
424 const path = '/api/v1/plugins/'
426 it('Should fail with an invalid token', async function () {
427 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
428 await makePostBodyRequest({
431 fields: { npmName: npmPlugin },
433 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
438 it('Should fail if the user is not an administrator', async function () {
439 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
440 await makePostBodyRequest({
443 fields: { npmName: npmPlugin },
444 token: userAccessToken,
445 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
450 it('Should fail with an invalid npm name', async function () {
451 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
452 await makePostBodyRequest({
455 fields: { npmName: 'toto' },
456 token: server.accessToken,
457 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
461 for (const suffix of [ 'install', 'update', 'uninstall' ]) {
462 await makePostBodyRequest({
465 fields: { npmName: 'peertube-plugin-TOTO' },
466 token: server.accessToken,
467 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
472 it('Should succeed with the correct parameters', async function () {
476 { suffix: 'install', status: HttpStatusCode.OK_200 },
477 { suffix: 'update', status: HttpStatusCode.OK_200 },
478 { suffix: 'uninstall', status: HttpStatusCode.NO_CONTENT_204 }
481 for (const obj of it) {
482 await makePostBodyRequest({
484 path: path + obj.suffix,
485 fields: { npmName: npmPlugin },
486 token: server.accessToken,
487 statusCodeExpected: obj.status
493 after(async function () {
494 await cleanupTests([ server ])