diff options
author | Wicklow <123956049+wickloww@users.noreply.github.com> | 2023-06-29 07:48:55 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-29 09:48:55 +0200 |
commit | 40346ead2b0b7afa475aef057d3673b6c7574b7a (patch) | |
tree | 24ffdc23c3a9d987334842e0d400b5bd44500cf7 /server/tests/api/check-params | |
parent | ae22c59f14d0d553f60b281948b6c232c2aca178 (diff) | |
download | PeerTube-40346ead2b0b7afa475aef057d3673b6c7574b7a.tar.gz PeerTube-40346ead2b0b7afa475aef057d3673b6c7574b7a.tar.zst PeerTube-40346ead2b0b7afa475aef057d3673b6c7574b7a.zip |
Feature/password protected videos (#5836)
* Add server endpoints
* Refactoring test suites
* Update server and add openapi documentation
* fix compliation and tests
* upload/import password protected video on client
* add server error code
* Add video password to update resolver
* add custom message when sharing pw protected video
* improve confirm component
* Add new alert in component
* Add ability to watch protected video on client
* Cannot have password protected replay privacy
* Add migration
* Add tests
* update after review
* Update check params tests
* Add live videos test
* Add more filter test
* Update static file privacy test
* Update object storage tests
* Add test on feeds
* Add missing word
* Fix tests
* Fix tests on live videos
* add embed support on password protected videos
* fix style
* Correcting data leaks
* Unable to add password protected privacy on replay
* Updated code based on review comments
* fix validator and command
* Updated code based on review comments
Diffstat (limited to 'server/tests/api/check-params')
-rw-r--r-- | server/tests/api/check-params/live.ts | 4 | ||||
-rw-r--r-- | server/tests/api/check-params/video-passwords.ts | 609 | ||||
-rw-r--r-- | server/tests/api/check-params/video-token.ts | 44 |
3 files changed, 646 insertions, 11 deletions
diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts index 2dc735c23..406a96824 100644 --- a/server/tests/api/check-params/live.ts +++ b/server/tests/api/check-params/live.ts | |||
@@ -143,7 +143,7 @@ describe('Test video lives API validator', function () { | |||
143 | }) | 143 | }) |
144 | 144 | ||
145 | it('Should fail with a bad privacy for replay settings', async function () { | 145 | it('Should fail with a bad privacy for replay settings', async function () { |
146 | const fields = { ...baseCorrectParams, replaySettings: { privacy: 5 } } | 146 | const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: 999 } } |
147 | 147 | ||
148 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 148 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
149 | }) | 149 | }) |
@@ -472,7 +472,7 @@ describe('Test video lives API validator', function () { | |||
472 | }) | 472 | }) |
473 | 473 | ||
474 | it('Should fail with a bad privacy for replay settings', async function () { | 474 | it('Should fail with a bad privacy for replay settings', async function () { |
475 | const fields = { saveReplay: true, replaySettings: { privacy: 5 } } | 475 | const fields = { saveReplay: true, replaySettings: { privacy: 999 } } |
476 | 476 | ||
477 | await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 477 | await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
478 | }) | 478 | }) |
diff --git a/server/tests/api/check-params/video-passwords.ts b/server/tests/api/check-params/video-passwords.ts new file mode 100644 index 000000000..4e936b5d2 --- /dev/null +++ b/server/tests/api/check-params/video-passwords.ts | |||
@@ -0,0 +1,609 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | import { | ||
3 | FIXTURE_URLS, | ||
4 | checkBadCountPagination, | ||
5 | checkBadSortPagination, | ||
6 | checkBadStartPagination, | ||
7 | checkUploadVideoParam | ||
8 | } from '@server/tests/shared' | ||
9 | import { root } from '@shared/core-utils' | ||
10 | import { | ||
11 | HttpStatusCode, | ||
12 | PeerTubeProblemDocument, | ||
13 | ServerErrorCode, | ||
14 | VideoCreateResult, | ||
15 | VideoPrivacy | ||
16 | } from '@shared/models' | ||
17 | import { | ||
18 | cleanupTests, | ||
19 | createSingleServer, | ||
20 | makePostBodyRequest, | ||
21 | PeerTubeServer, | ||
22 | setAccessTokensToServers | ||
23 | } from '@shared/server-commands' | ||
24 | import { expect } from 'chai' | ||
25 | import { join } from 'path' | ||
26 | |||
27 | describe('Test video passwords validator', function () { | ||
28 | let path: string | ||
29 | let server: PeerTubeServer | ||
30 | let userAccessToken = '' | ||
31 | let video: VideoCreateResult | ||
32 | let channelId: number | ||
33 | let publicVideo: VideoCreateResult | ||
34 | let commentId: number | ||
35 | // --------------------------------------------------------------- | ||
36 | |||
37 | before(async function () { | ||
38 | this.timeout(50000) | ||
39 | |||
40 | server = await createSingleServer(1) | ||
41 | |||
42 | await setAccessTokensToServers([ server ]) | ||
43 | |||
44 | await server.config.updateCustomSubConfig({ | ||
45 | newConfig: { | ||
46 | live: { | ||
47 | enabled: true, | ||
48 | latencySetting: { | ||
49 | enabled: false | ||
50 | }, | ||
51 | allowReplay: false | ||
52 | }, | ||
53 | import: { | ||
54 | videos: { | ||
55 | http:{ | ||
56 | enabled: true | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | }) | ||
62 | |||
63 | userAccessToken = await server.users.generateUserAndToken('user1') | ||
64 | |||
65 | { | ||
66 | const body = await server.users.getMyInfo() | ||
67 | channelId = body.videoChannels[0].id | ||
68 | } | ||
69 | |||
70 | { | ||
71 | video = await server.videos.quickUpload({ | ||
72 | name: 'password protected video', | ||
73 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
74 | videoPasswords: [ 'password1', 'password2' ] | ||
75 | }) | ||
76 | } | ||
77 | path = '/api/v1/videos/' | ||
78 | }) | ||
79 | |||
80 | async function checkVideoPasswordOptions (options: { | ||
81 | server: PeerTubeServer | ||
82 | token: string | ||
83 | videoPasswords: string[] | ||
84 | expectedStatus: HttpStatusCode | ||
85 | mode: 'uploadLegacy' | 'uploadResumable' | 'import' | 'updateVideo' | 'updatePasswords' | 'live' | ||
86 | }) { | ||
87 | const { server, token, videoPasswords, expectedStatus = HttpStatusCode.OK_200, mode } = options | ||
88 | const attaches = { | ||
89 | fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.webm') | ||
90 | } | ||
91 | const baseCorrectParams = { | ||
92 | name: 'my super name', | ||
93 | category: 5, | ||
94 | licence: 1, | ||
95 | language: 'pt', | ||
96 | nsfw: false, | ||
97 | commentsEnabled: true, | ||
98 | downloadEnabled: true, | ||
99 | waitTranscoding: true, | ||
100 | description: 'my super description', | ||
101 | support: 'my super support text', | ||
102 | tags: [ 'tag1', 'tag2' ], | ||
103 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
104 | channelId, | ||
105 | originallyPublishedAt: new Date().toISOString() | ||
106 | } | ||
107 | if (mode === 'uploadLegacy') { | ||
108 | const fields = { ...baseCorrectParams, videoPasswords } | ||
109 | return checkUploadVideoParam(server, token, { ...fields, ...attaches }, expectedStatus, 'legacy') | ||
110 | } | ||
111 | |||
112 | if (mode === 'uploadResumable') { | ||
113 | const fields = { ...baseCorrectParams, videoPasswords } | ||
114 | return checkUploadVideoParam(server, token, { ...fields, ...attaches }, expectedStatus, 'resumable') | ||
115 | } | ||
116 | |||
117 | if (mode === 'import') { | ||
118 | const attributes = { ...baseCorrectParams, targetUrl: FIXTURE_URLS.goodVideo, videoPasswords } | ||
119 | return server.imports.importVideo({ attributes, expectedStatus }) | ||
120 | } | ||
121 | |||
122 | if (mode === 'updateVideo') { | ||
123 | const attributes = { ...baseCorrectParams, videoPasswords } | ||
124 | return server.videos.update({ token, expectedStatus, id: video.id, attributes }) | ||
125 | } | ||
126 | |||
127 | if (mode === 'updatePasswords') { | ||
128 | return server.videoPasswords.updateAll({ token, expectedStatus, videoId: video.id, passwords: videoPasswords }) | ||
129 | } | ||
130 | |||
131 | if (mode === 'live') { | ||
132 | const fields = { ...baseCorrectParams, videoPasswords } | ||
133 | |||
134 | return server.live.create({ fields, expectedStatus }) | ||
135 | } | ||
136 | } | ||
137 | |||
138 | function validateVideoPasswordList (mode: 'uploadLegacy' | 'uploadResumable' | 'import' | 'updateVideo' | 'updatePasswords' | 'live') { | ||
139 | |||
140 | it('Should fail with a password protected privacy without providing a password', async function () { | ||
141 | await checkVideoPasswordOptions({ | ||
142 | server, | ||
143 | token: server.accessToken, | ||
144 | videoPasswords: undefined, | ||
145 | expectedStatus: HttpStatusCode.BAD_REQUEST_400, | ||
146 | mode | ||
147 | }) | ||
148 | }) | ||
149 | |||
150 | it('Should fail with a password protected privacy and an empty password list', async function () { | ||
151 | const videoPasswords = [] | ||
152 | |||
153 | await checkVideoPasswordOptions({ | ||
154 | server, | ||
155 | token: server.accessToken, | ||
156 | videoPasswords, | ||
157 | expectedStatus: HttpStatusCode.BAD_REQUEST_400, | ||
158 | mode | ||
159 | }) | ||
160 | }) | ||
161 | |||
162 | it('Should fail with a password protected privacy and a too short password', async function () { | ||
163 | const videoPasswords = [ 'p' ] | ||
164 | |||
165 | await checkVideoPasswordOptions({ | ||
166 | server, | ||
167 | token: server.accessToken, | ||
168 | videoPasswords, | ||
169 | expectedStatus: HttpStatusCode.BAD_REQUEST_400, | ||
170 | mode | ||
171 | }) | ||
172 | }) | ||
173 | |||
174 | it('Should fail with a password protected privacy and a too long password', async function () { | ||
175 | const videoPasswords = [ 'Very very very very very very very very very very very very very very very very very very long password' ] | ||
176 | |||
177 | await checkVideoPasswordOptions({ | ||
178 | server, | ||
179 | token: server.accessToken, | ||
180 | videoPasswords, | ||
181 | expectedStatus: HttpStatusCode.BAD_REQUEST_400, | ||
182 | mode | ||
183 | }) | ||
184 | }) | ||
185 | |||
186 | it('Should fail with a password protected privacy and an empty password', async function () { | ||
187 | const videoPasswords = [ '' ] | ||
188 | |||
189 | await checkVideoPasswordOptions({ | ||
190 | server, | ||
191 | token: server.accessToken, | ||
192 | videoPasswords, | ||
193 | expectedStatus: HttpStatusCode.BAD_REQUEST_400, | ||
194 | mode | ||
195 | }) | ||
196 | }) | ||
197 | |||
198 | it('Should fail with a password protected privacy and duplicated passwords', async function () { | ||
199 | const videoPasswords = [ 'password', 'password' ] | ||
200 | |||
201 | await checkVideoPasswordOptions({ | ||
202 | server, | ||
203 | token: server.accessToken, | ||
204 | videoPasswords, | ||
205 | expectedStatus: HttpStatusCode.BAD_REQUEST_400, | ||
206 | mode | ||
207 | }) | ||
208 | }) | ||
209 | |||
210 | if (mode === 'updatePasswords') { | ||
211 | it('Should fail for an unauthenticated user', async function () { | ||
212 | const videoPasswords = [ 'password' ] | ||
213 | await checkVideoPasswordOptions({ | ||
214 | server, | ||
215 | token: null, | ||
216 | videoPasswords, | ||
217 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401, | ||
218 | mode | ||
219 | }) | ||
220 | }) | ||
221 | |||
222 | it('Should fail for an unauthorized user', async function () { | ||
223 | const videoPasswords = [ 'password' ] | ||
224 | await checkVideoPasswordOptions({ | ||
225 | server, | ||
226 | token: userAccessToken, | ||
227 | videoPasswords, | ||
228 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
229 | mode | ||
230 | }) | ||
231 | }) | ||
232 | } | ||
233 | |||
234 | it('Should succeed with a password protected privacy and correct passwords', async function () { | ||
235 | const videoPasswords = [ 'password1', 'password2' ] | ||
236 | const expectedStatus = mode === 'updatePasswords' || mode === 'updateVideo' | ||
237 | ? HttpStatusCode.NO_CONTENT_204 | ||
238 | : HttpStatusCode.OK_200 | ||
239 | |||
240 | await checkVideoPasswordOptions({ server, token: server.accessToken, videoPasswords, expectedStatus, mode }) | ||
241 | }) | ||
242 | } | ||
243 | |||
244 | describe('When adding or updating a video', function () { | ||
245 | describe('Resumable upload', function () { | ||
246 | validateVideoPasswordList('uploadResumable') | ||
247 | }) | ||
248 | |||
249 | describe('Legacy upload', function () { | ||
250 | validateVideoPasswordList('uploadLegacy') | ||
251 | }) | ||
252 | |||
253 | describe('When importing a video', function () { | ||
254 | validateVideoPasswordList('import') | ||
255 | }) | ||
256 | |||
257 | describe('When updating a video', function () { | ||
258 | validateVideoPasswordList('updateVideo') | ||
259 | }) | ||
260 | |||
261 | describe('When updating the password list of a video', function () { | ||
262 | validateVideoPasswordList('updatePasswords') | ||
263 | }) | ||
264 | |||
265 | describe('When creating a live', function () { | ||
266 | validateVideoPasswordList('live') | ||
267 | }) | ||
268 | }) | ||
269 | |||
270 | async function checkVideoAccessOptions (options: { | ||
271 | server: PeerTubeServer | ||
272 | token?: string | ||
273 | videoPassword?: string | ||
274 | expectedStatus: HttpStatusCode | ||
275 | mode: 'get' | 'getWithPassword' | 'getWithToken' | 'listCaptions' | 'createThread' | 'listThreads' | 'replyThread' | 'rate' | 'token' | ||
276 | }) { | ||
277 | const { server, token = null, videoPassword, expectedStatus, mode } = options | ||
278 | |||
279 | if (mode === 'get') { | ||
280 | return server.videos.get({ id: video.id, expectedStatus }) | ||
281 | } | ||
282 | |||
283 | if (mode === 'getWithToken') { | ||
284 | return server.videos.getWithToken({ | ||
285 | id: video.id, | ||
286 | token, | ||
287 | expectedStatus | ||
288 | }) | ||
289 | } | ||
290 | |||
291 | if (mode === 'getWithPassword') { | ||
292 | return server.videos.getWithPassword({ | ||
293 | id: video.id, | ||
294 | token, | ||
295 | expectedStatus, | ||
296 | password: videoPassword | ||
297 | }) | ||
298 | } | ||
299 | |||
300 | if (mode === 'rate') { | ||
301 | return server.videos.rate({ | ||
302 | id: video.id, | ||
303 | token, | ||
304 | expectedStatus, | ||
305 | rating: 'like', | ||
306 | videoPassword | ||
307 | }) | ||
308 | } | ||
309 | |||
310 | if (mode === 'createThread') { | ||
311 | const fields = { text: 'super comment' } | ||
312 | const headers = videoPassword !== undefined && videoPassword !== null | ||
313 | ? { 'x-peertube-video-password': videoPassword } | ||
314 | : undefined | ||
315 | const body = await makePostBodyRequest({ | ||
316 | url: server.url, | ||
317 | path: path + video.uuid + '/comment-threads', | ||
318 | token, | ||
319 | fields, | ||
320 | headers, | ||
321 | expectedStatus | ||
322 | }) | ||
323 | return JSON.parse(body.text) | ||
324 | } | ||
325 | |||
326 | if (mode === 'replyThread') { | ||
327 | const fields = { text: 'super reply' } | ||
328 | const headers = videoPassword !== undefined && videoPassword !== null | ||
329 | ? { 'x-peertube-video-password': videoPassword } | ||
330 | : undefined | ||
331 | return makePostBodyRequest({ | ||
332 | url: server.url, | ||
333 | path: path + video.uuid + '/comments/' + commentId, | ||
334 | token, | ||
335 | fields, | ||
336 | headers, | ||
337 | expectedStatus | ||
338 | }) | ||
339 | } | ||
340 | if (mode === 'listThreads') { | ||
341 | return server.comments.listThreads({ | ||
342 | videoId: video.id, | ||
343 | token, | ||
344 | expectedStatus, | ||
345 | videoPassword | ||
346 | }) | ||
347 | } | ||
348 | |||
349 | if (mode === 'listCaptions') { | ||
350 | return server.captions.list({ | ||
351 | videoId: video.id, | ||
352 | token, | ||
353 | expectedStatus, | ||
354 | videoPassword | ||
355 | }) | ||
356 | } | ||
357 | |||
358 | if (mode === 'token') { | ||
359 | return server.videoToken.create({ | ||
360 | videoId: video.id, | ||
361 | token, | ||
362 | expectedStatus, | ||
363 | videoPassword | ||
364 | }) | ||
365 | } | ||
366 | } | ||
367 | |||
368 | function checkVideoError (error: any, mode: 'providePassword' | 'incorrectPassword') { | ||
369 | const serverCode = mode === 'providePassword' | ||
370 | ? ServerErrorCode.VIDEO_REQUIRES_PASSWORD | ||
371 | : ServerErrorCode.INCORRECT_VIDEO_PASSWORD | ||
372 | |||
373 | const message = mode === 'providePassword' | ||
374 | ? 'Please provide a password to access this password protected video' | ||
375 | : 'Incorrect video password. Access to the video is denied.' | ||
376 | |||
377 | if (!error.code) { | ||
378 | error = JSON.parse(error.text) | ||
379 | } | ||
380 | |||
381 | expect(error.code).to.equal(serverCode) | ||
382 | expect(error.detail).to.equal(message) | ||
383 | expect(error.error).to.equal(message) | ||
384 | |||
385 | expect(error.status).to.equal(HttpStatusCode.FORBIDDEN_403) | ||
386 | } | ||
387 | |||
388 | function validateVideoAccess (mode: 'get' | 'listCaptions' | 'createThread' | 'listThreads' | 'replyThread' | 'rate' | 'token') { | ||
389 | const requiresUserAuth = [ 'createThread', 'replyThread', 'rate' ].includes(mode) | ||
390 | let tokens: string[] | ||
391 | if (!requiresUserAuth) { | ||
392 | it('Should fail without providing a password for an unlogged user', async function () { | ||
393 | const body = await checkVideoAccessOptions({ server, expectedStatus: HttpStatusCode.FORBIDDEN_403, mode }) | ||
394 | const error = body as unknown as PeerTubeProblemDocument | ||
395 | |||
396 | checkVideoError(error, 'providePassword') | ||
397 | }) | ||
398 | } | ||
399 | |||
400 | it('Should fail without providing a password for an unauthorised user', async function () { | ||
401 | const tmp = mode === 'get' ? 'getWithToken' : mode | ||
402 | |||
403 | const body = await checkVideoAccessOptions({ | ||
404 | server, | ||
405 | token: userAccessToken, | ||
406 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
407 | mode: tmp | ||
408 | }) | ||
409 | |||
410 | const error = body as unknown as PeerTubeProblemDocument | ||
411 | |||
412 | checkVideoError(error, 'providePassword') | ||
413 | }) | ||
414 | |||
415 | it('Should fail if a wrong password is entered', async function () { | ||
416 | const tmp = mode === 'get' ? 'getWithPassword' : mode | ||
417 | tokens = [ userAccessToken, server.accessToken ] | ||
418 | |||
419 | if (!requiresUserAuth) tokens.push(null) | ||
420 | |||
421 | for (const token of tokens) { | ||
422 | const body = await checkVideoAccessOptions({ | ||
423 | server, | ||
424 | token, | ||
425 | videoPassword: 'toto', | ||
426 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
427 | mode: tmp | ||
428 | }) | ||
429 | const error = body as unknown as PeerTubeProblemDocument | ||
430 | |||
431 | checkVideoError(error, 'incorrectPassword') | ||
432 | } | ||
433 | }) | ||
434 | |||
435 | it('Should fail if an empty password is entered', async function () { | ||
436 | const tmp = mode === 'get' ? 'getWithPassword' : mode | ||
437 | |||
438 | for (const token of tokens) { | ||
439 | const body = await checkVideoAccessOptions({ | ||
440 | server, | ||
441 | token, | ||
442 | videoPassword: '', | ||
443 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
444 | mode: tmp | ||
445 | }) | ||
446 | const error = body as unknown as PeerTubeProblemDocument | ||
447 | |||
448 | checkVideoError(error, 'incorrectPassword') | ||
449 | } | ||
450 | }) | ||
451 | |||
452 | it('Should fail if an inccorect password containing the correct password is entered', async function () { | ||
453 | const tmp = mode === 'get' ? 'getWithPassword' : mode | ||
454 | |||
455 | for (const token of tokens) { | ||
456 | const body = await checkVideoAccessOptions({ | ||
457 | server, | ||
458 | token, | ||
459 | videoPassword: 'password11', | ||
460 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
461 | mode: tmp | ||
462 | }) | ||
463 | const error = body as unknown as PeerTubeProblemDocument | ||
464 | |||
465 | checkVideoError(error, 'incorrectPassword') | ||
466 | } | ||
467 | }) | ||
468 | |||
469 | it('Should succeed without providing a password for an authorised user', async function () { | ||
470 | const tmp = mode === 'get' ? 'getWithToken' : mode | ||
471 | const expectedStatus = mode === 'rate' ? HttpStatusCode.NO_CONTENT_204 : HttpStatusCode.OK_200 | ||
472 | |||
473 | const body = await checkVideoAccessOptions({ server, token: server.accessToken, expectedStatus, mode: tmp }) | ||
474 | |||
475 | if (mode === 'createThread') commentId = body.comment.id | ||
476 | }) | ||
477 | |||
478 | it('Should succeed using correct passwords', async function () { | ||
479 | const tmp = mode === 'get' ? 'getWithPassword' : mode | ||
480 | const expectedStatus = mode === 'rate' ? HttpStatusCode.NO_CONTENT_204 : HttpStatusCode.OK_200 | ||
481 | |||
482 | for (const token of tokens) { | ||
483 | await checkVideoAccessOptions({ server, videoPassword: 'password1', token, expectedStatus, mode: tmp }) | ||
484 | await checkVideoAccessOptions({ server, videoPassword: 'password2', token, expectedStatus, mode: tmp }) | ||
485 | } | ||
486 | }) | ||
487 | } | ||
488 | |||
489 | describe('When accessing password protected video', function () { | ||
490 | |||
491 | describe('For getting a password protected video', function () { | ||
492 | validateVideoAccess('get') | ||
493 | }) | ||
494 | |||
495 | describe('For rating a video', function () { | ||
496 | validateVideoAccess('rate') | ||
497 | }) | ||
498 | |||
499 | describe('For creating a thread', function () { | ||
500 | validateVideoAccess('createThread') | ||
501 | }) | ||
502 | |||
503 | describe('For replying to a thread', function () { | ||
504 | validateVideoAccess('replyThread') | ||
505 | }) | ||
506 | |||
507 | describe('For listing threads', function () { | ||
508 | validateVideoAccess('listThreads') | ||
509 | }) | ||
510 | |||
511 | describe('For getting captions', function () { | ||
512 | validateVideoAccess('listCaptions') | ||
513 | }) | ||
514 | |||
515 | describe('For creating video file token', function () { | ||
516 | validateVideoAccess('token') | ||
517 | }) | ||
518 | }) | ||
519 | |||
520 | describe('When listing passwords', function () { | ||
521 | it('Should fail with a bad start pagination', async function () { | ||
522 | await checkBadStartPagination(server.url, path + video.uuid + '/passwords', server.accessToken) | ||
523 | }) | ||
524 | |||
525 | it('Should fail with a bad count pagination', async function () { | ||
526 | await checkBadCountPagination(server.url, path + video.uuid + '/passwords', server.accessToken) | ||
527 | }) | ||
528 | |||
529 | it('Should fail with an incorrect sort', async function () { | ||
530 | await checkBadSortPagination(server.url, path + video.uuid + '/passwords', server.accessToken) | ||
531 | }) | ||
532 | |||
533 | it('Should fail for unauthenticated user', async function () { | ||
534 | await server.videoPasswords.list({ | ||
535 | token: null, | ||
536 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401, | ||
537 | videoId: video.id | ||
538 | }) | ||
539 | }) | ||
540 | |||
541 | it('Should fail for unauthorized user', async function () { | ||
542 | await server.videoPasswords.list({ | ||
543 | token: userAccessToken, | ||
544 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
545 | videoId: video.id | ||
546 | }) | ||
547 | }) | ||
548 | |||
549 | it('Should succeed with the correct parameters', async function () { | ||
550 | await server.videoPasswords.list({ | ||
551 | token: server.accessToken, | ||
552 | expectedStatus: HttpStatusCode.OK_200, | ||
553 | videoId: video.id | ||
554 | }) | ||
555 | }) | ||
556 | }) | ||
557 | |||
558 | describe('When deleting a password', async function () { | ||
559 | const passwords = (await server.videoPasswords.list({ videoId: video.id })).data | ||
560 | |||
561 | it('Should fail with wrong password id', async function () { | ||
562 | await server.videoPasswords.remove({ id: -1, videoId: video.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
563 | }) | ||
564 | |||
565 | it('Should fail for unauthenticated user', async function () { | ||
566 | await server.videoPasswords.remove({ | ||
567 | id: passwords[0].id, | ||
568 | token: null, | ||
569 | videoId: video.id, | ||
570 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
571 | }) | ||
572 | }) | ||
573 | |||
574 | it('Should fail for unauthorized user', async function () { | ||
575 | await server.videoPasswords.remove({ | ||
576 | id: passwords[0].id, | ||
577 | token: userAccessToken, | ||
578 | videoId: video.id, | ||
579 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
580 | }) | ||
581 | }) | ||
582 | |||
583 | it('Should fail for non password protected video', async function () { | ||
584 | publicVideo = await server.videos.quickUpload({ name: 'public video' }) | ||
585 | await server.videoPasswords.remove({ id: passwords[0].id, videoId: publicVideo.id, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | ||
586 | }) | ||
587 | |||
588 | it('Should fail for password not linked to correct video', async function () { | ||
589 | const video2 = await server.videos.quickUpload({ | ||
590 | name: 'password protected video', | ||
591 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
592 | videoPasswords: [ 'password1', 'password2' ] | ||
593 | }) | ||
594 | await server.videoPasswords.remove({ id: passwords[0].id, videoId: video2.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
595 | }) | ||
596 | |||
597 | it('Should succeed with correct parameter', async function () { | ||
598 | await server.videoPasswords.remove({ id: passwords[0].id, videoId: video.id, expectedStatus: HttpStatusCode.NO_CONTENT_204 }) | ||
599 | }) | ||
600 | |||
601 | it('Should fail for last password of a video', async function () { | ||
602 | await server.videoPasswords.remove({ id: passwords[1].id, videoId: video.id, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | ||
603 | }) | ||
604 | }) | ||
605 | |||
606 | after(async function () { | ||
607 | await cleanupTests([ server ]) | ||
608 | }) | ||
609 | }) | ||
diff --git a/server/tests/api/check-params/video-token.ts b/server/tests/api/check-params/video-token.ts index 7acb9d580..7cb3e84a2 100644 --- a/server/tests/api/check-params/video-token.ts +++ b/server/tests/api/check-params/video-token.ts | |||
@@ -5,9 +5,12 @@ import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServ | |||
5 | 5 | ||
6 | describe('Test video tokens', function () { | 6 | describe('Test video tokens', function () { |
7 | let server: PeerTubeServer | 7 | let server: PeerTubeServer |
8 | let videoId: string | 8 | let privateVideoId: string |
9 | let passwordProtectedVideoId: string | ||
9 | let userToken: string | 10 | let userToken: string |
10 | 11 | ||
12 | const videoPassword = 'password' | ||
13 | |||
11 | // --------------------------------------------------------------- | 14 | // --------------------------------------------------------------- |
12 | 15 | ||
13 | before(async function () { | 16 | before(async function () { |
@@ -15,27 +18,50 @@ describe('Test video tokens', function () { | |||
15 | 18 | ||
16 | server = await createSingleServer(1) | 19 | server = await createSingleServer(1) |
17 | await setAccessTokensToServers([ server ]) | 20 | await setAccessTokensToServers([ server ]) |
18 | 21 | { | |
19 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | 22 | const { uuid } = await server.videos.quickUpload({ name: 'private video', privacy: VideoPrivacy.PRIVATE }) |
20 | videoId = uuid | 23 | privateVideoId = uuid |
21 | 24 | } | |
25 | { | ||
26 | const { uuid } = await server.videos.quickUpload({ | ||
27 | name: 'password protected video', | ||
28 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
29 | videoPasswords: [ videoPassword ] | ||
30 | }) | ||
31 | passwordProtectedVideoId = uuid | ||
32 | } | ||
22 | userToken = await server.users.generateUserAndToken('user1') | 33 | userToken = await server.users.generateUserAndToken('user1') |
23 | }) | 34 | }) |
24 | 35 | ||
25 | it('Should not generate tokens for unauthenticated user', async function () { | 36 | it('Should not generate tokens on private video for unauthenticated user', async function () { |
26 | await server.videoToken.create({ videoId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | 37 | await server.videoToken.create({ videoId: privateVideoId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) |
27 | }) | 38 | }) |
28 | 39 | ||
29 | it('Should not generate tokens of unknown video', async function () { | 40 | it('Should not generate tokens of unknown video', async function () { |
30 | await server.videoToken.create({ videoId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | 41 | await server.videoToken.create({ videoId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
31 | }) | 42 | }) |
32 | 43 | ||
44 | it('Should not generate tokens with incorrect password', async function () { | ||
45 | await server.videoToken.create({ | ||
46 | videoId: passwordProtectedVideoId, | ||
47 | token: null, | ||
48 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
49 | videoPassword: 'incorrectPassword' | ||
50 | }) | ||
51 | }) | ||
52 | |||
33 | it('Should not generate tokens of a non owned video', async function () { | 53 | it('Should not generate tokens of a non owned video', async function () { |
34 | await server.videoToken.create({ videoId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | 54 | await server.videoToken.create({ videoId: privateVideoId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) |
35 | }) | 55 | }) |
36 | 56 | ||
37 | it('Should generate token', async function () { | 57 | it('Should generate token', async function () { |
38 | await server.videoToken.create({ videoId }) | 58 | await server.videoToken.create({ videoId: privateVideoId }) |
59 | }) | ||
60 | |||
61 | it('Should generate token on password protected video', async function () { | ||
62 | await server.videoToken.create({ videoId: passwordProtectedVideoId, videoPassword, token: null }) | ||
63 | await server.videoToken.create({ videoId: passwordProtectedVideoId, videoPassword, token: userToken }) | ||
64 | await server.videoToken.create({ videoId: passwordProtectedVideoId, videoPassword }) | ||
39 | }) | 65 | }) |
40 | 66 | ||
41 | after(async function () { | 67 | after(async function () { |