]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - 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
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import { omit } from 'lodash'
5 import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, FIXTURE_URLS } from '@server/tests/shared'
6 import { buildAbsoluteFixturePath } from '@shared/core-utils'
7 import { HttpStatusCode, VideoPrivacy } from '@shared/models'
8 import {
9 cleanupTests,
10 createSingleServer,
11 makeGetRequest,
12 makePostBodyRequest,
13 makeUploadRequest,
14 PeerTubeServer,
15 setAccessTokensToServers,
16 setDefaultVideoChannel,
17 waitJobs
18 } from '@shared/server-commands'
19
20 describe('Test video imports API validator', function () {
21 const path = '/api/v1/videos/imports'
22 let server: PeerTubeServer
23 let userAccessToken = ''
24 let channelId: number
25
26 // ---------------------------------------------------------------
27
28 before(async function () {
29 this.timeout(30000)
30
31 server = await createSingleServer(1)
32
33 await setAccessTokensToServers([ server ])
34 await setDefaultVideoChannel([ server ])
35
36 const username = 'user1'
37 const password = 'my super password'
38 await server.users.create({ username, password })
39 userAccessToken = await server.login.getAccessToken({ username, password })
40
41 {
42 const { videoChannels } = await server.users.getMyInfo()
43 channelId = videoChannels[0].id
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
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
71 it('Should success with the correct parameters', async function () {
72 await makeGetRequest({ url: server.url, path: myPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
73 })
74 })
75
76 describe('When adding a video import', function () {
77 let baseCorrectParams
78
79 before(function () {
80 baseCorrectParams = {
81 targetUrl: FIXTURE_URLS.goodVideo,
82 name: 'my super name',
83 category: 5,
84 licence: 1,
85 language: 'pt',
86 nsfw: false,
87 commentsEnabled: true,
88 downloadEnabled: true,
89 waitTranscoding: true,
90 description: 'my super description',
91 support: 'my super support text',
92 tags: [ 'tag1', 'tag2' ],
93 privacy: VideoPrivacy.PUBLIC,
94 channelId
95 }
96 })
97
98 it('Should fail with nothing', async function () {
99 const fields = {}
100 await makePostBodyRequest({
101 url: server.url,
102 path,
103 token: server.accessToken,
104 fields,
105 expectedStatus: HttpStatusCode.BAD_REQUEST_400
106 })
107 })
108
109 it('Should fail without a target url', async function () {
110 const fields = omit(baseCorrectParams, 'targetUrl')
111 await makePostBodyRequest({
112 url: server.url,
113 path,
114 token: server.accessToken,
115 fields,
116 expectedStatus: HttpStatusCode.BAD_REQUEST_400
117 })
118 })
119
120 it('Should fail with a bad target url', async function () {
121 const fields = { ...baseCorrectParams, targetUrl: 'htt://hello' }
122
123 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
124 })
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',
138 'http://192.168.1.42',
139 'http://127.0.0.1.cpy.re'
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 })
154
155 it('Should fail with a long name', async function () {
156 const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
157
158 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
159 })
160
161 it('Should fail with a bad category', async function () {
162 const fields = { ...baseCorrectParams, category: 125 }
163
164 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
165 })
166
167 it('Should fail with a bad licence', async function () {
168 const fields = { ...baseCorrectParams, licence: 125 }
169
170 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
171 })
172
173 it('Should fail with a bad language', async function () {
174 const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
175
176 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
177 })
178
179 it('Should fail with a long description', async function () {
180 const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
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 () {
186 const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
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 () {
198 const fields = { ...baseCorrectParams, channelId: 545454 }
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 }
208 await server.users.create({ username: user.username, password: user.password })
209
210 const accessTokenUser = await server.login.getAccessToken(user)
211 const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
212 const customChannelId = videoChannels[0].id
213
214 const fields = { ...baseCorrectParams, channelId: customChannelId }
215
216 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
217 })
218
219 it('Should fail with too many tags', async function () {
220 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
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 () {
226 const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
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 () {
232 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
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 = {
240 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
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 = {
249 thumbnailfile: buildAbsoluteFixturePath('preview-big.png')
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 = {
258 previewfile: buildAbsoluteFixturePath('video_short.mp4')
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 = {
267 previewfile: buildAbsoluteFixturePath('preview-big.png')
268 }
269
270 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
271 })
272
273 it('Should fail with an invalid torrent file', async function () {
274 const fields = omit(baseCorrectParams, 'targetUrl')
275 const attaches = {
276 torrentfile: buildAbsoluteFixturePath('avatar-big.png')
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')
284 fields = { ...fields, magnetUri: 'blabla' }
285
286 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
287 })
288
289 it('Should succeed with the correct parameters', async function () {
290 this.timeout(120000)
291
292 await makePostBodyRequest({
293 url: server.url,
294 path,
295 token: server.accessToken,
296 fields: baseCorrectParams,
297 expectedStatus: HttpStatusCode.OK_200
298 })
299 })
300
301 it('Should forbid to import http videos', async function () {
302 await server.config.updateCustomSubConfig({
303 newConfig: {
304 import: {
305 videos: {
306 http: {
307 enabled: false
308 },
309 torrent: {
310 enabled: true
311 }
312 }
313 }
314 }
315 })
316
317 await makePostBodyRequest({
318 url: server.url,
319 path,
320 token: server.accessToken,
321 fields: baseCorrectParams,
322 expectedStatus: HttpStatusCode.CONFLICT_409
323 })
324 })
325
326 it('Should forbid to import torrent videos', async function () {
327 await server.config.updateCustomSubConfig({
328 newConfig: {
329 import: {
330 videos: {
331 http: {
332 enabled: true
333 },
334 torrent: {
335 enabled: false
336 }
337 }
338 }
339 }
340 })
341
342 let fields = omit(baseCorrectParams, 'targetUrl')
343 fields = { ...fields, magnetUri: FIXTURE_URLS.magnet }
344
345 await makePostBodyRequest({
346 url: server.url,
347 path,
348 token: server.accessToken,
349 fields,
350 expectedStatus: HttpStatusCode.CONFLICT_409
351 })
352
353 fields = omit(fields, 'magnetUri')
354 const attaches = {
355 torrentfile: buildAbsoluteFixturePath('video-720p.torrent')
356 }
357
358 await makeUploadRequest({
359 url: server.url,
360 path,
361 token: server.accessToken,
362 fields,
363 attaches,
364 expectedStatus: HttpStatusCode.CONFLICT_409
365 })
366 })
367 })
368
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
430 after(async function () {
431 await cleanupTests([ server ])
432 })
433 })