]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/check-params/live.ts
78863fd5019952b5f5fe95480b8c530b91574daf
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / live.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import { omit } from 'lodash'
5 import { HttpStatusCode } from '@shared/core-utils'
6 import {
7 buildAbsoluteFixturePath,
8 cleanupTests,
9 flushAndRunServer,
10 LiveCommand,
11 makePostBodyRequest,
12 makeUploadRequest,
13 sendRTMPStream,
14 ServerInfo,
15 setAccessTokensToServers,
16 stopFfmpeg,
17 uploadVideoAndGetId
18 } from '@shared/extra-utils'
19 import { VideoCreateResult, VideoPrivacy } from '@shared/models'
20
21 describe('Test video lives API validator', function () {
22 const path = '/api/v1/videos/live'
23 let server: ServerInfo
24 let userAccessToken = ''
25 let channelId: number
26 let video: VideoCreateResult
27 let videoIdNotLive: number
28 let command: LiveCommand
29
30 // ---------------------------------------------------------------
31
32 before(async function () {
33 this.timeout(30000)
34
35 server = await flushAndRunServer(1)
36
37 await setAccessTokensToServers([ server ])
38
39 await server.configCommand.updateCustomSubConfig({
40 newConfig: {
41 live: {
42 enabled: true,
43 maxInstanceLives: 20,
44 maxUserLives: 20,
45 allowReplay: true
46 }
47 }
48 })
49
50 const username = 'user1'
51 const password = 'my super password'
52 await server.usersCommand.create({ username: username, password: password })
53 userAccessToken = await server.loginCommand.getAccessToken({ username, password })
54
55 {
56 const { videoChannels } = await server.usersCommand.getMyInfo()
57 channelId = videoChannels[0].id
58 }
59
60 {
61 videoIdNotLive = (await uploadVideoAndGetId({ server, videoName: 'not live' })).id
62 }
63
64 command = server.liveCommand
65 })
66
67 describe('When creating a live', function () {
68 let baseCorrectParams
69
70 before(function () {
71 baseCorrectParams = {
72 name: 'my super name',
73 category: 5,
74 licence: 1,
75 language: 'pt',
76 nsfw: false,
77 commentsEnabled: true,
78 downloadEnabled: true,
79 waitTranscoding: true,
80 description: 'my super description',
81 support: 'my super support text',
82 tags: [ 'tag1', 'tag2' ],
83 privacy: VideoPrivacy.PUBLIC,
84 channelId,
85 saveReplay: false,
86 permanentLive: false
87 }
88 })
89
90 it('Should fail with nothing', async function () {
91 const fields = {}
92 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
93 })
94
95 it('Should fail with a long name', async function () {
96 const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
97
98 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
99 })
100
101 it('Should fail with a bad category', async function () {
102 const fields = { ...baseCorrectParams, category: 125 }
103
104 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
105 })
106
107 it('Should fail with a bad licence', async function () {
108 const fields = { ...baseCorrectParams, licence: 125 }
109
110 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
111 })
112
113 it('Should fail with a bad language', async function () {
114 const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
115
116 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
117 })
118
119 it('Should fail with a long description', async function () {
120 const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
121
122 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
123 })
124
125 it('Should fail with a long support text', async function () {
126 const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
127
128 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
129 })
130
131 it('Should fail without a channel', async function () {
132 const fields = omit(baseCorrectParams, 'channelId')
133
134 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
135 })
136
137 it('Should fail with a bad channel', async function () {
138 const fields = { ...baseCorrectParams, channelId: 545454 }
139
140 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
141 })
142
143 it('Should fail with another user channel', async function () {
144 const user = {
145 username: 'fake',
146 password: 'fake_password'
147 }
148 await server.usersCommand.create({ username: user.username, password: user.password })
149
150 const accessTokenUser = await server.loginCommand.getAccessToken(user)
151 const { videoChannels } = await server.usersCommand.getMyInfo({ token: accessTokenUser })
152 const customChannelId = videoChannels[0].id
153
154 const fields = { ...baseCorrectParams, channelId: customChannelId }
155
156 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
157 })
158
159 it('Should fail with too many tags', async function () {
160 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
161
162 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
163 })
164
165 it('Should fail with a tag length too low', async function () {
166 const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
167
168 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
169 })
170
171 it('Should fail with a tag length too big', async function () {
172 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
173
174 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
175 })
176
177 it('Should fail with an incorrect thumbnail file', async function () {
178 const fields = baseCorrectParams
179 const attaches = {
180 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
181 }
182
183 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
184 })
185
186 it('Should fail with a big thumbnail file', async function () {
187 const fields = baseCorrectParams
188 const attaches = {
189 thumbnailfile: buildAbsoluteFixturePath('preview-big.png')
190 }
191
192 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
193 })
194
195 it('Should fail with an incorrect preview file', async function () {
196 const fields = baseCorrectParams
197 const attaches = {
198 previewfile: buildAbsoluteFixturePath('video_short.mp4')
199 }
200
201 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
202 })
203
204 it('Should fail with a big preview file', async function () {
205 const fields = baseCorrectParams
206 const attaches = {
207 previewfile: buildAbsoluteFixturePath('preview-big.png')
208 }
209
210 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
211 })
212
213 it('Should fail with save replay and permanent live set to true', async function () {
214 const fields = { ...baseCorrectParams, saveReplay: true, permanentLive: true }
215
216 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
217 })
218
219 it('Should succeed with the correct parameters', async function () {
220 this.timeout(30000)
221
222 const res = await makePostBodyRequest({
223 url: server.url,
224 path,
225 token: server.accessToken,
226 fields: baseCorrectParams,
227 statusCodeExpected: HttpStatusCode.OK_200
228 })
229
230 video = res.body.video
231 })
232
233 it('Should forbid if live is disabled', async function () {
234 await server.configCommand.updateCustomSubConfig({
235 newConfig: {
236 live: {
237 enabled: false
238 }
239 }
240 })
241
242 await makePostBodyRequest({
243 url: server.url,
244 path,
245 token: server.accessToken,
246 fields: baseCorrectParams,
247 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
248 })
249 })
250
251 it('Should forbid to save replay if not enabled by the admin', async function () {
252 const fields = { ...baseCorrectParams, saveReplay: true }
253
254 await server.configCommand.updateCustomSubConfig({
255 newConfig: {
256 live: {
257 enabled: true,
258 allowReplay: false
259 }
260 }
261 })
262
263 await makePostBodyRequest({
264 url: server.url,
265 path,
266 token: server.accessToken,
267 fields,
268 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
269 })
270 })
271
272 it('Should allow to save replay if enabled by the admin', async function () {
273 const fields = { ...baseCorrectParams, saveReplay: true }
274
275 await server.configCommand.updateCustomSubConfig({
276 newConfig: {
277 live: {
278 enabled: true,
279 allowReplay: true
280 }
281 }
282 })
283
284 await makePostBodyRequest({
285 url: server.url,
286 path,
287 token: server.accessToken,
288 fields,
289 statusCodeExpected: HttpStatusCode.OK_200
290 })
291 })
292
293 it('Should not allow live if max instance lives is reached', async function () {
294 await server.configCommand.updateCustomSubConfig({
295 newConfig: {
296 live: {
297 enabled: true,
298 maxInstanceLives: 1
299 }
300 }
301 })
302
303 await makePostBodyRequest({
304 url: server.url,
305 path,
306 token: server.accessToken,
307 fields: baseCorrectParams,
308 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
309 })
310 })
311
312 it('Should not allow live if max user lives is reached', async function () {
313 await server.configCommand.updateCustomSubConfig({
314 newConfig: {
315 live: {
316 enabled: true,
317 maxInstanceLives: 20,
318 maxUserLives: 1
319 }
320 }
321 })
322
323 await makePostBodyRequest({
324 url: server.url,
325 path,
326 token: server.accessToken,
327 fields: baseCorrectParams,
328 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
329 })
330 })
331 })
332
333 describe('When getting live information', function () {
334
335 it('Should fail without access token', async function () {
336 await command.get({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
337 })
338
339 it('Should fail with a bad access token', async function () {
340 await command.get({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
341 })
342
343 it('Should fail with access token of another user', async function () {
344 await command.get({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
345 })
346
347 it('Should fail with a bad video id', async function () {
348 await command.get({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
349 })
350
351 it('Should fail with an unknown video id', async function () {
352 await command.get({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
353 })
354
355 it('Should fail with a non live video', async function () {
356 await command.get({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
357 })
358
359 it('Should succeed with the correct params', async function () {
360 await command.get({ videoId: video.id })
361 await command.get({ videoId: video.uuid })
362 await command.get({ videoId: video.shortUUID })
363 })
364 })
365
366 describe('When updating live information', async function () {
367
368 it('Should fail without access token', async function () {
369 await command.update({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
370 })
371
372 it('Should fail with a bad access token', async function () {
373 await command.update({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
374 })
375
376 it('Should fail with access token of another user', async function () {
377 await command.update({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
378 })
379
380 it('Should fail with a bad video id', async function () {
381 await command.update({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
382 })
383
384 it('Should fail with an unknown video id', async function () {
385 await command.update({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
386 })
387
388 it('Should fail with a non live video', async function () {
389 await command.update({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
390 })
391
392 it('Should fail with save replay and permanent live set to true', async function () {
393 const fields = { saveReplay: true, permanentLive: true }
394
395 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
396 })
397
398 it('Should succeed with the correct params', async function () {
399 await command.update({ videoId: video.id, fields: { saveReplay: false } })
400 await command.update({ videoId: video.uuid, fields: { saveReplay: false } })
401 await command.update({ videoId: video.shortUUID, fields: { saveReplay: false } })
402 })
403
404 it('Should fail to update replay status if replay is not allowed on the instance', async function () {
405 await server.configCommand.updateCustomSubConfig({
406 newConfig: {
407 live: {
408 enabled: true,
409 allowReplay: false
410 }
411 }
412 })
413
414 await command.update({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
415 })
416
417 it('Should fail to update a live if it has already started', async function () {
418 this.timeout(40000)
419
420 const live = await command.get({ videoId: video.id })
421
422 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
423
424 await command.waitUntilPublished({ videoId: video.id })
425 await command.update({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
426
427 await stopFfmpeg(ffmpegCommand)
428 })
429
430 it('Should fail to stream twice in the save live', async function () {
431 this.timeout(40000)
432
433 const live = await command.get({ videoId: video.id })
434
435 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
436
437 await command.waitUntilPublished({ videoId: video.id })
438
439 await command.runAndTestStreamError({ videoId: video.id, shouldHaveError: true })
440
441 await stopFfmpeg(ffmpegCommand)
442 })
443 })
444
445 after(async function () {
446 await cleanupTests([ server ])
447 })
448 })