]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/check-params/video-imports.ts
Add ability to list imports of a channel sync
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / video-imports.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
5d08a6a7 2
5d08a6a7 3import 'mocha'
b488ba1e 4import { omit } from 'lodash'
c55e3d72
C
5import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, FIXTURE_URLS } from '@server/tests/shared'
6import { buildAbsoluteFixturePath } from '@shared/core-utils'
7import { HttpStatusCode, VideoPrivacy } from '@shared/models'
5d08a6a7 8import {
7c3b7976 9 cleanupTests,
254d3579 10 createSingleServer,
5d08a6a7
C
11 makeGetRequest,
12 makePostBodyRequest,
13 makeUploadRequest,
254d3579 14 PeerTubeServer,
419b520c
C
15 setAccessTokensToServers,
16 setDefaultVideoChannel,
17 waitJobs
bf54587a 18} from '@shared/server-commands'
5d08a6a7
C
19
20describe('Test video imports API validator', function () {
21 const path = '/api/v1/videos/imports'
254d3579 22 let server: PeerTubeServer
5d08a6a7 23 let userAccessToken = ''
5d08a6a7 24 let channelId: number
5d08a6a7
C
25
26 // ---------------------------------------------------------------
27
28 before(async function () {
29 this.timeout(30000)
30
254d3579 31 server = await createSingleServer(1)
5d08a6a7
C
32
33 await setAccessTokensToServers([ server ])
419b520c 34 await setDefaultVideoChannel([ server ])
5d08a6a7
C
35
36 const username = 'user1'
37 const password = 'my super password'
ba2684ce 38 await server.users.create({ username, password })
89d241a7 39 userAccessToken = await server.login.getAccessToken({ username, password })
5d08a6a7
C
40
41 {
89d241a7 42 const { videoChannels } = await server.users.getMyInfo()
7926c5f9 43 channelId = videoChannels[0].id
5d08a6a7
C
44 }
45 })
46
47 describe('When listing my video imports', function () {
48 const myPath = '/api/v1/users/me/videos/imports'
49
50 it('Should fail with a bad start pagination', async function () {
51 await checkBadStartPagination(server.url, myPath, server.accessToken)
52 })
53
54 it('Should fail with a bad count pagination', async function () {
55 await checkBadCountPagination(server.url, myPath, server.accessToken)
56 })
57
58 it('Should fail with an incorrect sort', async function () {
59 await checkBadSortPagination(server.url, myPath, server.accessToken)
60 })
61
a3b472a1
C
62 it('Should fail with a bad videoChannelSyncId param', async function () {
63 await makeGetRequest({
64 url: server.url,
65 path: myPath,
66 query: { videoChannelSyncId: 'toto' },
67 token: server.accessToken
68 })
69 })
70
5d08a6a7 71 it('Should success with the correct parameters', async function () {
c0e8b12e 72 await makeGetRequest({ url: server.url, path: myPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
5d08a6a7
C
73 })
74 })
75
76 describe('When adding a video import', function () {
77 let baseCorrectParams
78
79 before(function () {
80 baseCorrectParams = {
59bbcced 81 targetUrl: FIXTURE_URLS.goodVideo,
5d08a6a7
C
82 name: 'my super name',
83 category: 5,
84 licence: 1,
85 language: 'pt',
86 nsfw: false,
87 commentsEnabled: true,
7f2cfe3a 88 downloadEnabled: true,
5d08a6a7
C
89 waitTranscoding: true,
90 description: 'my super description',
91 support: 'my super support text',
92 tags: [ 'tag1', 'tag2' ],
93 privacy: VideoPrivacy.PUBLIC,
c8861d5d 94 channelId
5d08a6a7
C
95 }
96 })
97
98 it('Should fail with nothing', async function () {
99 const fields = {}
2a491182
F
100 await makePostBodyRequest({
101 url: server.url,
102 path,
103 token: server.accessToken,
104 fields,
105 expectedStatus: HttpStatusCode.BAD_REQUEST_400
106 })
5d08a6a7
C
107 })
108
590fb506
C
109 it('Should fail without a target url', async function () {
110 const fields = omit(baseCorrectParams, 'targetUrl')
2d53be02
RK
111 await makePostBodyRequest({
112 url: server.url,
113 path,
114 token: server.accessToken,
115 fields,
c0e8b12e 116 expectedStatus: HttpStatusCode.BAD_REQUEST_400
2d53be02 117 })
590fb506
C
118 })
119
120 it('Should fail with a bad target url', async function () {
6c5065a0 121 const fields = { ...baseCorrectParams, targetUrl: 'htt://hello' }
590fb506
C
122
123 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
124 })
7b54a81c
C
125
126 it('Should fail with localhost', async function () {
127 const fields = { ...baseCorrectParams, targetUrl: 'http://localhost:8000' }
128
129 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
130 })
131
132 it('Should fail with a private IP target urls', async function () {
133 const targetUrls = [
134 'http://127.0.0.1:8000',
135 'http://127.0.0.1',
136 'http://127.0.0.1/hello',
137 'https://192.168.1.42',
f33e5159
C
138 'http://192.168.1.42',
139 'http://127.0.0.1.cpy.re'
7b54a81c
C
140 ]
141
142 for (const targetUrl of targetUrls) {
143 const fields = { ...baseCorrectParams, targetUrl }
144
145 await makePostBodyRequest({
146 url: server.url,
147 path,
148 token: server.accessToken,
149 fields,
150 expectedStatus: HttpStatusCode.FORBIDDEN_403
151 })
152 }
153 })
590fb506 154
5d08a6a7 155 it('Should fail with a long name', async function () {
6c5065a0 156 const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
5d08a6a7
C
157
158 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
159 })
160
161 it('Should fail with a bad category', async function () {
6c5065a0 162 const fields = { ...baseCorrectParams, category: 125 }
5d08a6a7
C
163
164 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
165 })
166
167 it('Should fail with a bad licence', async function () {
6c5065a0 168 const fields = { ...baseCorrectParams, licence: 125 }
5d08a6a7
C
169
170 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
171 })
172
173 it('Should fail with a bad language', async function () {
6c5065a0 174 const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
5d08a6a7
C
175
176 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
177 })
178
179 it('Should fail with a long description', async function () {
6c5065a0 180 const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
5d08a6a7
C
181
182 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
183 })
184
185 it('Should fail with a long support text', async function () {
6c5065a0 186 const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
5d08a6a7
C
187
188 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
189 })
190
191 it('Should fail without a channel', async function () {
192 const fields = omit(baseCorrectParams, 'channelId')
193
194 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
195 })
196
197 it('Should fail with a bad channel', async function () {
6c5065a0 198 const fields = { ...baseCorrectParams, channelId: 545454 }
5d08a6a7
C
199
200 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
201 })
202
203 it('Should fail with another user channel', async function () {
204 const user = {
205 username: 'fake',
206 password: 'fake_password'
207 }
89d241a7 208 await server.users.create({ username: user.username, password: user.password })
5d08a6a7 209
89d241a7
C
210 const accessTokenUser = await server.login.getAccessToken(user)
211 const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
7926c5f9 212 const customChannelId = videoChannels[0].id
5d08a6a7 213
6c5065a0 214 const fields = { ...baseCorrectParams, channelId: customChannelId }
5d08a6a7
C
215
216 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
217 })
218
219 it('Should fail with too many tags', async function () {
6c5065a0 220 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
5d08a6a7
C
221
222 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
223 })
224
225 it('Should fail with a tag length too low', async function () {
6c5065a0 226 const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
5d08a6a7
C
227
228 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
229 })
230
231 it('Should fail with a tag length too big', async function () {
6c5065a0 232 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
5d08a6a7
C
233
234 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
235 })
236
237 it('Should fail with an incorrect thumbnail file', async function () {
238 const fields = baseCorrectParams
239 const attaches = {
3d470a53 240 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
5d08a6a7
C
241 }
242
243 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
244 })
245
246 it('Should fail with a big thumbnail file', async function () {
247 const fields = baseCorrectParams
248 const attaches = {
3d470a53 249 thumbnailfile: buildAbsoluteFixturePath('preview-big.png')
5d08a6a7
C
250 }
251
252 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
253 })
254
255 it('Should fail with an incorrect preview file', async function () {
256 const fields = baseCorrectParams
257 const attaches = {
3d470a53 258 previewfile: buildAbsoluteFixturePath('video_short.mp4')
5d08a6a7
C
259 }
260
261 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
262 })
263
264 it('Should fail with a big preview file', async function () {
265 const fields = baseCorrectParams
266 const attaches = {
3d470a53 267 previewfile: buildAbsoluteFixturePath('preview-big.png')
5d08a6a7
C
268 }
269
270 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
271 })
272
187501f8
C
273 it('Should fail with an invalid torrent file', async function () {
274 const fields = omit(baseCorrectParams, 'targetUrl')
275 const attaches = {
3d470a53 276 torrentfile: buildAbsoluteFixturePath('avatar-big.png')
187501f8
C
277 }
278
279 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
280 })
281
282 it('Should fail with an invalid magnet URI', async function () {
283 let fields = omit(baseCorrectParams, 'targetUrl')
6c5065a0 284 fields = { ...fields, magnetUri: 'blabla' }
187501f8
C
285
286 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
287 })
288
5d08a6a7 289 it('Should succeed with the correct parameters', async function () {
8d57e728 290 this.timeout(120000)
5d08a6a7 291
b488ba1e
C
292 await makePostBodyRequest({
293 url: server.url,
294 path,
295 token: server.accessToken,
296 fields: baseCorrectParams,
c0e8b12e 297 expectedStatus: HttpStatusCode.OK_200
b488ba1e 298 })
5d08a6a7
C
299 })
300
187501f8 301 it('Should forbid to import http videos', async function () {
89d241a7 302 await server.config.updateCustomSubConfig({
65e6e260
C
303 newConfig: {
304 import: {
305 videos: {
306 http: {
307 enabled: false
308 },
309 torrent: {
310 enabled: true
311 }
590fb506
C
312 }
313 }
314 }
315 })
316
317 await makePostBodyRequest({
318 url: server.url,
319 path,
320 token: server.accessToken,
321 fields: baseCorrectParams,
c0e8b12e 322 expectedStatus: HttpStatusCode.CONFLICT_409
590fb506
C
323 })
324 })
187501f8
C
325
326 it('Should forbid to import torrent videos', async function () {
89d241a7 327 await server.config.updateCustomSubConfig({
65e6e260
C
328 newConfig: {
329 import: {
330 videos: {
331 http: {
332 enabled: true
333 },
334 torrent: {
335 enabled: false
336 }
187501f8
C
337 }
338 }
339 }
340 })
341
342 let fields = omit(baseCorrectParams, 'targetUrl')
59bbcced 343 fields = { ...fields, magnetUri: FIXTURE_URLS.magnet }
187501f8 344
2d53be02
RK
345 await makePostBodyRequest({
346 url: server.url,
347 path,
348 token: server.accessToken,
349 fields,
c0e8b12e 350 expectedStatus: HttpStatusCode.CONFLICT_409
2d53be02 351 })
187501f8
C
352
353 fields = omit(fields, 'magnetUri')
354 const attaches = {
3d470a53 355 torrentfile: buildAbsoluteFixturePath('video-720p.torrent')
187501f8
C
356 }
357
2d53be02
RK
358 await makeUploadRequest({
359 url: server.url,
360 path,
361 token: server.accessToken,
362 fields,
363 attaches,
c0e8b12e 364 expectedStatus: HttpStatusCode.CONFLICT_409
2d53be02 365 })
187501f8 366 })
5d08a6a7
C
367 })
368
419b520c
C
369 describe('Deleting/cancelling a video import', function () {
370 let importId: number
371
372 async function importVideo () {
373 const attributes = { channelId: server.store.channel.id, targetUrl: FIXTURE_URLS.goodVideo }
374 const res = await server.imports.importVideo({ attributes })
375
376 return res.id
377 }
378
379 before(async function () {
380 importId = await importVideo()
381 })
382
383 it('Should fail with an invalid import id', async function () {
384 await server.imports.cancel({ importId: 'artyom' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
385 await server.imports.delete({ importId: 'artyom' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
386 })
387
388 it('Should fail with an unknown import id', async function () {
389 await server.imports.cancel({ importId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
390 await server.imports.delete({ importId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
391 })
392
393 it('Should fail without token', async function () {
394 await server.imports.cancel({ importId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
395 await server.imports.delete({ importId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
396 })
397
398 it('Should fail with another user token', async function () {
399 await server.imports.cancel({ importId, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
400 await server.imports.delete({ importId, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
401 })
402
403 it('Should fail to cancel non pending import', async function () {
404 this.timeout(60000)
405
406 await waitJobs([ server ])
407
408 await server.imports.cancel({ importId, expectedStatus: HttpStatusCode.CONFLICT_409 })
409 })
410
411 it('Should succeed to delete an import', async function () {
412 await server.imports.delete({ importId })
413 })
414
415 it('Should fail to delete a pending import', async function () {
416 await server.jobs.pauseJobQueue()
417
418 importId = await importVideo()
419
420 await server.imports.delete({ importId, expectedStatus: HttpStatusCode.CONFLICT_409 })
421 })
422
423 it('Should succeed to cancel an import', async function () {
424 importId = await importVideo()
425
426 await server.imports.cancel({ importId })
427 })
428 })
429
7c3b7976
C
430 after(async function () {
431 await cleanupTests([ server ])
5d08a6a7
C
432 })
433})