diff options
Diffstat (limited to 'packages/tests/src/api/videos/video-static-file-privacy.ts')
-rw-r--r-- | packages/tests/src/api/videos/video-static-file-privacy.ts | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/packages/tests/src/api/videos/video-static-file-privacy.ts b/packages/tests/src/api/videos/video-static-file-privacy.ts new file mode 100644 index 000000000..7c8d14815 --- /dev/null +++ b/packages/tests/src/api/videos/video-static-file-privacy.ts | |||
@@ -0,0 +1,602 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { decode } from 'magnet-uri' | ||
5 | import { getAllFiles, wait } from '@peertube/peertube-core-utils' | ||
6 | import { HttpStatusCode, HttpStatusCodeType, LiveVideo, VideoDetails, VideoPrivacy } from '@peertube/peertube-models' | ||
7 | import { | ||
8 | cleanupTests, | ||
9 | createSingleServer, | ||
10 | findExternalSavedVideo, | ||
11 | makeRawRequest, | ||
12 | PeerTubeServer, | ||
13 | sendRTMPStream, | ||
14 | setAccessTokensToServers, | ||
15 | setDefaultVideoChannel, | ||
16 | stopFfmpeg, | ||
17 | waitJobs | ||
18 | } from '@peertube/peertube-server-commands' | ||
19 | import { expectStartWith } from '@tests/shared/checks.js' | ||
20 | import { checkVideoFileTokenReinjection } from '@tests/shared/streaming-playlists.js' | ||
21 | import { parseTorrentVideo } from '@tests/shared/webtorrent.js' | ||
22 | |||
23 | describe('Test video static file privacy', function () { | ||
24 | let server: PeerTubeServer | ||
25 | let userToken: string | ||
26 | |||
27 | before(async function () { | ||
28 | this.timeout(50000) | ||
29 | |||
30 | server = await createSingleServer(1) | ||
31 | await setAccessTokensToServers([ server ]) | ||
32 | await setDefaultVideoChannel([ server ]) | ||
33 | |||
34 | userToken = await server.users.generateUserAndToken('user1') | ||
35 | }) | ||
36 | |||
37 | describe('VOD static file path', function () { | ||
38 | |||
39 | function runSuite () { | ||
40 | |||
41 | async function checkPrivateFiles (uuid: string) { | ||
42 | const video = await server.videos.getWithToken({ id: uuid }) | ||
43 | |||
44 | for (const file of video.files) { | ||
45 | expect(file.fileDownloadUrl).to.not.include('/private/') | ||
46 | expectStartWith(file.fileUrl, server.url + '/static/web-videos/private/') | ||
47 | |||
48 | const torrent = await parseTorrentVideo(server, file) | ||
49 | expect(torrent.urlList).to.have.lengthOf(0) | ||
50 | |||
51 | const magnet = decode(file.magnetUri) | ||
52 | expect(magnet.urlList).to.have.lengthOf(0) | ||
53 | |||
54 | await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
55 | } | ||
56 | |||
57 | const hls = video.streamingPlaylists[0] | ||
58 | if (hls) { | ||
59 | expectStartWith(hls.playlistUrl, server.url + '/static/streaming-playlists/hls/private/') | ||
60 | expectStartWith(hls.segmentsSha256Url, server.url + '/static/streaming-playlists/hls/private/') | ||
61 | |||
62 | await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
63 | await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
64 | } | ||
65 | } | ||
66 | |||
67 | async function checkPublicFiles (uuid: string) { | ||
68 | const video = await server.videos.get({ id: uuid }) | ||
69 | |||
70 | for (const file of getAllFiles(video)) { | ||
71 | expect(file.fileDownloadUrl).to.not.include('/private/') | ||
72 | expect(file.fileUrl).to.not.include('/private/') | ||
73 | |||
74 | const torrent = await parseTorrentVideo(server, file) | ||
75 | expect(torrent.urlList[0]).to.not.include('private') | ||
76 | |||
77 | const magnet = decode(file.magnetUri) | ||
78 | expect(magnet.urlList[0]).to.not.include('private') | ||
79 | |||
80 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) | ||
81 | await makeRawRequest({ url: torrent.urlList[0], expectedStatus: HttpStatusCode.OK_200 }) | ||
82 | await makeRawRequest({ url: magnet.urlList[0], expectedStatus: HttpStatusCode.OK_200 }) | ||
83 | } | ||
84 | |||
85 | const hls = video.streamingPlaylists[0] | ||
86 | if (hls) { | ||
87 | expect(hls.playlistUrl).to.not.include('private') | ||
88 | expect(hls.segmentsSha256Url).to.not.include('private') | ||
89 | |||
90 | await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) | ||
91 | await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | it('Should upload a private/internal/password protected video and have a private static path', async function () { | ||
96 | this.timeout(120000) | ||
97 | |||
98 | for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) { | ||
99 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy }) | ||
100 | await waitJobs([ server ]) | ||
101 | |||
102 | await checkPrivateFiles(uuid) | ||
103 | } | ||
104 | |||
105 | const { uuid } = await server.videos.quickUpload({ | ||
106 | name: 'video', | ||
107 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
108 | videoPasswords: [ 'my super password' ] | ||
109 | }) | ||
110 | await waitJobs([ server ]) | ||
111 | |||
112 | await checkPrivateFiles(uuid) | ||
113 | }) | ||
114 | |||
115 | it('Should upload a public video and update it as private/internal to have a private static path', async function () { | ||
116 | this.timeout(120000) | ||
117 | |||
118 | for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) { | ||
119 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PUBLIC }) | ||
120 | await waitJobs([ server ]) | ||
121 | |||
122 | await server.videos.update({ id: uuid, attributes: { privacy } }) | ||
123 | await waitJobs([ server ]) | ||
124 | |||
125 | await checkPrivateFiles(uuid) | ||
126 | } | ||
127 | }) | ||
128 | |||
129 | it('Should upload a private video and update it to unlisted to have a public static path', async function () { | ||
130 | this.timeout(120000) | ||
131 | |||
132 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
133 | await waitJobs([ server ]) | ||
134 | |||
135 | await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } }) | ||
136 | await waitJobs([ server ]) | ||
137 | |||
138 | await checkPublicFiles(uuid) | ||
139 | }) | ||
140 | |||
141 | it('Should upload an internal video and update it to public to have a public static path', async function () { | ||
142 | this.timeout(120000) | ||
143 | |||
144 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.INTERNAL }) | ||
145 | await waitJobs([ server ]) | ||
146 | |||
147 | await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } }) | ||
148 | await waitJobs([ server ]) | ||
149 | |||
150 | await checkPublicFiles(uuid) | ||
151 | }) | ||
152 | |||
153 | it('Should upload an internal video and schedule a public publish', async function () { | ||
154 | this.timeout(120000) | ||
155 | |||
156 | const attributes = { | ||
157 | name: 'video', | ||
158 | privacy: VideoPrivacy.PRIVATE, | ||
159 | scheduleUpdate: { | ||
160 | updateAt: new Date(Date.now() + 1000).toISOString(), | ||
161 | privacy: VideoPrivacy.PUBLIC | ||
162 | } | ||
163 | } | ||
164 | |||
165 | const { uuid } = await server.videos.upload({ attributes }) | ||
166 | |||
167 | await waitJobs([ server ]) | ||
168 | await wait(1000) | ||
169 | await server.debug.sendCommand({ body: { command: 'process-update-videos-scheduler' } }) | ||
170 | |||
171 | await waitJobs([ server ]) | ||
172 | |||
173 | await checkPublicFiles(uuid) | ||
174 | }) | ||
175 | } | ||
176 | |||
177 | describe('Without transcoding', function () { | ||
178 | runSuite() | ||
179 | }) | ||
180 | |||
181 | describe('With transcoding', function () { | ||
182 | |||
183 | before(async function () { | ||
184 | await server.config.enableMinimumTranscoding() | ||
185 | }) | ||
186 | |||
187 | runSuite() | ||
188 | }) | ||
189 | }) | ||
190 | |||
191 | describe('VOD static file right check', function () { | ||
192 | let unrelatedFileToken: string | ||
193 | |||
194 | async function checkVideoFiles (options: { | ||
195 | id: string | ||
196 | expectedStatus: HttpStatusCodeType | ||
197 | token: string | ||
198 | videoFileToken: string | ||
199 | videoPassword?: string | ||
200 | }) { | ||
201 | const { id, expectedStatus, token, videoFileToken, videoPassword } = options | ||
202 | |||
203 | const video = await server.videos.getWithToken({ id }) | ||
204 | |||
205 | for (const file of getAllFiles(video)) { | ||
206 | await makeRawRequest({ url: file.fileUrl, token, expectedStatus }) | ||
207 | await makeRawRequest({ url: file.fileDownloadUrl, token, expectedStatus }) | ||
208 | |||
209 | await makeRawRequest({ url: file.fileUrl, query: { videoFileToken }, expectedStatus }) | ||
210 | await makeRawRequest({ url: file.fileDownloadUrl, query: { videoFileToken }, expectedStatus }) | ||
211 | |||
212 | if (videoPassword) { | ||
213 | const headers = { 'x-peertube-video-password': videoPassword } | ||
214 | await makeRawRequest({ url: file.fileUrl, headers, expectedStatus }) | ||
215 | await makeRawRequest({ url: file.fileDownloadUrl, headers, expectedStatus }) | ||
216 | } | ||
217 | } | ||
218 | |||
219 | const hls = video.streamingPlaylists[0] | ||
220 | await makeRawRequest({ url: hls.playlistUrl, token, expectedStatus }) | ||
221 | await makeRawRequest({ url: hls.segmentsSha256Url, token, expectedStatus }) | ||
222 | |||
223 | await makeRawRequest({ url: hls.playlistUrl, query: { videoFileToken }, expectedStatus }) | ||
224 | await makeRawRequest({ url: hls.segmentsSha256Url, query: { videoFileToken }, expectedStatus }) | ||
225 | |||
226 | if (videoPassword) { | ||
227 | const headers = { 'x-peertube-video-password': videoPassword } | ||
228 | await makeRawRequest({ url: hls.playlistUrl, token: null, headers, expectedStatus }) | ||
229 | await makeRawRequest({ url: hls.segmentsSha256Url, token: null, headers, expectedStatus }) | ||
230 | } | ||
231 | } | ||
232 | |||
233 | before(async function () { | ||
234 | await server.config.enableMinimumTranscoding() | ||
235 | |||
236 | const { uuid } = await server.videos.quickUpload({ name: 'another video' }) | ||
237 | unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
238 | }) | ||
239 | |||
240 | it('Should not be able to access a private video files without OAuth token and file token', async function () { | ||
241 | this.timeout(120000) | ||
242 | |||
243 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
244 | await waitJobs([ server ]) | ||
245 | |||
246 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403, token: null, videoFileToken: null }) | ||
247 | }) | ||
248 | |||
249 | it('Should not be able to access password protected video files without OAuth token, file token and password', async function () { | ||
250 | this.timeout(120000) | ||
251 | const videoPassword = 'my super password' | ||
252 | |||
253 | const { uuid } = await server.videos.quickUpload({ | ||
254 | name: 'password protected video', | ||
255 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
256 | videoPasswords: [ videoPassword ] | ||
257 | }) | ||
258 | await waitJobs([ server ]) | ||
259 | |||
260 | await checkVideoFiles({ | ||
261 | id: uuid, | ||
262 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
263 | token: null, | ||
264 | videoFileToken: null, | ||
265 | videoPassword: null | ||
266 | }) | ||
267 | }) | ||
268 | |||
269 | it('Should not be able to access an password video files with incorrect OAuth token, file token and password', async function () { | ||
270 | this.timeout(120000) | ||
271 | const videoPassword = 'my super password' | ||
272 | |||
273 | const { uuid } = await server.videos.quickUpload({ | ||
274 | name: 'password protected video', | ||
275 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
276 | videoPasswords: [ videoPassword ] | ||
277 | }) | ||
278 | await waitJobs([ server ]) | ||
279 | |||
280 | await checkVideoFiles({ | ||
281 | id: uuid, | ||
282 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
283 | token: userToken, | ||
284 | videoFileToken: unrelatedFileToken, | ||
285 | videoPassword: 'incorrectPassword' | ||
286 | }) | ||
287 | }) | ||
288 | |||
289 | it('Should not be able to access an private video files without appropriate OAuth token and file token', async function () { | ||
290 | this.timeout(120000) | ||
291 | |||
292 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
293 | await waitJobs([ server ]) | ||
294 | |||
295 | await checkVideoFiles({ | ||
296 | id: uuid, | ||
297 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
298 | token: userToken, | ||
299 | videoFileToken: unrelatedFileToken | ||
300 | }) | ||
301 | }) | ||
302 | |||
303 | it('Should be able to access a private video files with appropriate OAuth token or file token', async function () { | ||
304 | this.timeout(120000) | ||
305 | |||
306 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
307 | const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
308 | |||
309 | await waitJobs([ server ]) | ||
310 | |||
311 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken }) | ||
312 | }) | ||
313 | |||
314 | it('Should be able to access a password protected video files with appropriate OAuth token or file token', async function () { | ||
315 | this.timeout(120000) | ||
316 | const videoPassword = 'my super password' | ||
317 | |||
318 | const { uuid } = await server.videos.quickUpload({ | ||
319 | name: 'video', | ||
320 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
321 | videoPasswords: [ videoPassword ] | ||
322 | }) | ||
323 | |||
324 | const videoFileToken = await server.videoToken.getVideoFileToken({ token: null, videoId: uuid, videoPassword }) | ||
325 | |||
326 | await waitJobs([ server ]) | ||
327 | |||
328 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken, videoPassword }) | ||
329 | }) | ||
330 | |||
331 | it('Should reinject video file token', async function () { | ||
332 | this.timeout(120000) | ||
333 | |||
334 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
335 | |||
336 | const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
337 | await waitJobs([ server ]) | ||
338 | |||
339 | { | ||
340 | const video = await server.videos.getWithToken({ id: uuid }) | ||
341 | const hls = video.streamingPlaylists[0] | ||
342 | const query = { videoFileToken } | ||
343 | const { text } = await makeRawRequest({ url: hls.playlistUrl, query, expectedStatus: HttpStatusCode.OK_200 }) | ||
344 | |||
345 | expect(text).to.not.include(videoFileToken) | ||
346 | } | ||
347 | |||
348 | { | ||
349 | await checkVideoFileTokenReinjection({ | ||
350 | server, | ||
351 | videoUUID: uuid, | ||
352 | videoFileToken, | ||
353 | resolutions: [ 240, 720 ], | ||
354 | isLive: false | ||
355 | }) | ||
356 | } | ||
357 | }) | ||
358 | |||
359 | it('Should be able to access a private video of another user with an admin OAuth token or file token', async function () { | ||
360 | this.timeout(120000) | ||
361 | |||
362 | const { uuid } = await server.videos.quickUpload({ name: 'video', token: userToken, privacy: VideoPrivacy.PRIVATE }) | ||
363 | const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
364 | |||
365 | await waitJobs([ server ]) | ||
366 | |||
367 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken }) | ||
368 | }) | ||
369 | }) | ||
370 | |||
371 | describe('Live static file path and check', function () { | ||
372 | let normalLiveId: string | ||
373 | let normalLive: LiveVideo | ||
374 | |||
375 | let permanentLiveId: string | ||
376 | let permanentLive: LiveVideo | ||
377 | |||
378 | let passwordProtectedLiveId: string | ||
379 | let passwordProtectedLive: LiveVideo | ||
380 | |||
381 | const correctPassword = 'my super password' | ||
382 | |||
383 | let unrelatedFileToken: string | ||
384 | |||
385 | async function checkLiveFiles (options: { live: LiveVideo, liveId: string, videoPassword?: string }) { | ||
386 | const { live, liveId, videoPassword } = options | ||
387 | const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey }) | ||
388 | await server.live.waitUntilPublished({ videoId: liveId }) | ||
389 | |||
390 | const video = await server.videos.getWithToken({ id: liveId }) | ||
391 | |||
392 | const fileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid }) | ||
393 | |||
394 | const hls = video.streamingPlaylists[0] | ||
395 | |||
396 | for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) { | ||
397 | expectStartWith(url, server.url + '/static/streaming-playlists/hls/private/') | ||
398 | |||
399 | await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
400 | await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 }) | ||
401 | |||
402 | await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
403 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
404 | await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
405 | |||
406 | if (videoPassword) { | ||
407 | await makeRawRequest({ url, headers: { 'x-peertube-video-password': videoPassword }, expectedStatus: HttpStatusCode.OK_200 }) | ||
408 | await makeRawRequest({ | ||
409 | url, | ||
410 | headers: { 'x-peertube-video-password': 'incorrectPassword' }, | ||
411 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
412 | }) | ||
413 | } | ||
414 | |||
415 | } | ||
416 | |||
417 | await stopFfmpeg(ffmpegCommand) | ||
418 | } | ||
419 | |||
420 | async function checkReplay (replay: VideoDetails) { | ||
421 | const fileToken = await server.videoToken.getVideoFileToken({ videoId: replay.uuid }) | ||
422 | |||
423 | const hls = replay.streamingPlaylists[0] | ||
424 | expect(hls.files).to.not.have.lengthOf(0) | ||
425 | |||
426 | for (const file of hls.files) { | ||
427 | await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
428 | await makeRawRequest({ url: file.fileUrl, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 }) | ||
429 | |||
430 | await makeRawRequest({ url: file.fileUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
431 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
432 | await makeRawRequest({ | ||
433 | url: file.fileUrl, | ||
434 | query: { videoFileToken: unrelatedFileToken }, | ||
435 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
436 | }) | ||
437 | } | ||
438 | |||
439 | for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) { | ||
440 | expectStartWith(url, server.url + '/static/streaming-playlists/hls/private/') | ||
441 | |||
442 | await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
443 | await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 }) | ||
444 | |||
445 | await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
446 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
447 | await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
448 | } | ||
449 | } | ||
450 | |||
451 | before(async function () { | ||
452 | await server.config.enableMinimumTranscoding() | ||
453 | |||
454 | const { uuid } = await server.videos.quickUpload({ name: 'another video' }) | ||
455 | unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
456 | |||
457 | await server.config.enableLive({ | ||
458 | allowReplay: true, | ||
459 | transcoding: true, | ||
460 | resolutions: 'min' | ||
461 | }) | ||
462 | |||
463 | { | ||
464 | const { video, live } = await server.live.quickCreate({ | ||
465 | saveReplay: true, | ||
466 | permanentLive: false, | ||
467 | privacy: VideoPrivacy.PRIVATE | ||
468 | }) | ||
469 | normalLiveId = video.uuid | ||
470 | normalLive = live | ||
471 | } | ||
472 | |||
473 | { | ||
474 | const { video, live } = await server.live.quickCreate({ | ||
475 | saveReplay: true, | ||
476 | permanentLive: true, | ||
477 | privacy: VideoPrivacy.PRIVATE | ||
478 | }) | ||
479 | permanentLiveId = video.uuid | ||
480 | permanentLive = live | ||
481 | } | ||
482 | |||
483 | { | ||
484 | const { video, live } = await server.live.quickCreate({ | ||
485 | saveReplay: false, | ||
486 | permanentLive: false, | ||
487 | privacy: VideoPrivacy.PASSWORD_PROTECTED, | ||
488 | videoPasswords: [ correctPassword ] | ||
489 | }) | ||
490 | passwordProtectedLiveId = video.uuid | ||
491 | passwordProtectedLive = live | ||
492 | } | ||
493 | }) | ||
494 | |||
495 | it('Should create a private normal live and have a private static path', async function () { | ||
496 | this.timeout(240000) | ||
497 | |||
498 | await checkLiveFiles({ live: normalLive, liveId: normalLiveId }) | ||
499 | }) | ||
500 | |||
501 | it('Should create a private permanent live and have a private static path', async function () { | ||
502 | this.timeout(240000) | ||
503 | |||
504 | await checkLiveFiles({ live: permanentLive, liveId: permanentLiveId }) | ||
505 | }) | ||
506 | |||
507 | it('Should create a password protected live and have a private static path', async function () { | ||
508 | this.timeout(240000) | ||
509 | |||
510 | await checkLiveFiles({ live: passwordProtectedLive, liveId: passwordProtectedLiveId, videoPassword: correctPassword }) | ||
511 | }) | ||
512 | |||
513 | it('Should reinject video file token on permanent live', async function () { | ||
514 | this.timeout(240000) | ||
515 | |||
516 | const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: permanentLive.rtmpUrl, streamKey: permanentLive.streamKey }) | ||
517 | await server.live.waitUntilPublished({ videoId: permanentLiveId }) | ||
518 | |||
519 | const video = await server.videos.getWithToken({ id: permanentLiveId }) | ||
520 | const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid }) | ||
521 | const hls = video.streamingPlaylists[0] | ||
522 | |||
523 | { | ||
524 | const query = { videoFileToken } | ||
525 | const { text } = await makeRawRequest({ url: hls.playlistUrl, query, expectedStatus: HttpStatusCode.OK_200 }) | ||
526 | |||
527 | expect(text).to.not.include(videoFileToken) | ||
528 | } | ||
529 | |||
530 | { | ||
531 | await checkVideoFileTokenReinjection({ | ||
532 | server, | ||
533 | videoUUID: permanentLiveId, | ||
534 | videoFileToken, | ||
535 | resolutions: [ 720 ], | ||
536 | isLive: true | ||
537 | }) | ||
538 | } | ||
539 | |||
540 | await stopFfmpeg(ffmpegCommand) | ||
541 | }) | ||
542 | |||
543 | it('Should have created a replay of the normal live with a private static path', async function () { | ||
544 | this.timeout(240000) | ||
545 | |||
546 | await server.live.waitUntilReplacedByReplay({ videoId: normalLiveId }) | ||
547 | |||
548 | const replay = await server.videos.getWithToken({ id: normalLiveId }) | ||
549 | await checkReplay(replay) | ||
550 | }) | ||
551 | |||
552 | it('Should have created a replay of the permanent live with a private static path', async function () { | ||
553 | this.timeout(240000) | ||
554 | |||
555 | await server.live.waitUntilWaiting({ videoId: permanentLiveId }) | ||
556 | await waitJobs([ server ]) | ||
557 | |||
558 | const live = await server.videos.getWithToken({ id: permanentLiveId }) | ||
559 | const replayFromList = await findExternalSavedVideo(server, live) | ||
560 | const replay = await server.videos.getWithToken({ id: replayFromList.id }) | ||
561 | |||
562 | await checkReplay(replay) | ||
563 | }) | ||
564 | }) | ||
565 | |||
566 | describe('With static file right check disabled', function () { | ||
567 | let videoUUID: string | ||
568 | |||
569 | before(async function () { | ||
570 | this.timeout(240000) | ||
571 | |||
572 | await server.kill() | ||
573 | |||
574 | await server.run({ | ||
575 | static_files: { | ||
576 | private_files_require_auth: false | ||
577 | } | ||
578 | }) | ||
579 | |||
580 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.INTERNAL }) | ||
581 | videoUUID = uuid | ||
582 | |||
583 | await waitJobs([ server ]) | ||
584 | }) | ||
585 | |||
586 | it('Should not check auth for private static files', async function () { | ||
587 | const video = await server.videos.getWithToken({ id: videoUUID }) | ||
588 | |||
589 | for (const file of getAllFiles(video)) { | ||
590 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) | ||
591 | } | ||
592 | |||
593 | const hls = video.streamingPlaylists[0] | ||
594 | await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) | ||
595 | await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) | ||
596 | }) | ||
597 | }) | ||
598 | |||
599 | after(async function () { | ||
600 | await cleanupTests([ server ]) | ||
601 | }) | ||
602 | }) | ||