Update server dependencies
[oweals/peertube.git] / server / tests / api / check-params / users.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import { omit } from 'lodash'
4 import 'mocha'
5 import { join } from 'path'
6 import { User, UserRole, VideoImport, VideoImportState } from '../../../../shared'
7
8 import {
9   addVideoChannel,
10   blockUser,
11   cleanupTests,
12   createUser,
13   deleteMe,
14   flushAndRunServer,
15   getMyUserInformation,
16   getMyUserVideoRating,
17   getUsersList,
18   immutableAssign,
19   killallServers,
20   makeGetRequest,
21   makePostBodyRequest,
22   makePutBodyRequest,
23   makeUploadRequest,
24   registerUser,
25   removeUser,
26   reRunServer,
27   ServerInfo,
28   setAccessTokensToServers,
29   unblockUser,
30   updateUser,
31   uploadVideo,
32   userLogin
33 } from '../../../../shared/extra-utils'
34 import {
35   checkBadCountPagination,
36   checkBadSortPagination,
37   checkBadStartPagination
38 } from '../../../../shared/extra-utils/requests/check-api-params'
39 import { getMagnetURI, getMyVideoImports, getYoutubeVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
40 import { VideoPrivacy } from '../../../../shared/models/videos'
41 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
42 import { expect } from 'chai'
43 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
44 import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
45
46 describe('Test users API validators', function () {
47   const path = '/api/v1/users/'
48   let userId: number
49   let rootId: number
50   let moderatorId: number
51   let videoId: number
52   let server: ServerInfo
53   let serverWithRegistrationDisabled: ServerInfo
54   let userAccessToken = ''
55   let moderatorAccessToken = ''
56   let emailPort: number
57   let overrideConfig: Object
58
59   // ---------------------------------------------------------------
60
61   before(async function () {
62     this.timeout(30000)
63
64     const emails: object[] = []
65     emailPort = await MockSmtpServer.Instance.collectEmails(emails)
66
67     overrideConfig = { signup: { limit: 8 } }
68
69     {
70       const res = await Promise.all([
71         flushAndRunServer(1, overrideConfig),
72         flushAndRunServer(2)
73       ])
74
75       server = res[0]
76       serverWithRegistrationDisabled = res[1]
77
78       await setAccessTokensToServers([ server ])
79     }
80
81     {
82       const user = {
83         username: 'user1',
84         password: 'my super password'
85       }
86
87       const videoQuota = 42000000
88       await createUser({
89         url: server.url,
90         accessToken: server.accessToken,
91         username: user.username,
92         password: user.password,
93         videoQuota: videoQuota
94       })
95       userAccessToken = await userLogin(server, user)
96     }
97
98     {
99       const moderator = {
100         username: 'moderator1',
101         password: 'super password'
102       }
103
104       await createUser({
105         url: server.url,
106         accessToken: server.accessToken,
107         username: moderator.username,
108         password: moderator.password,
109         role: UserRole.MODERATOR
110       })
111
112       moderatorAccessToken = await userLogin(server, moderator)
113     }
114
115     {
116       const moderator = {
117         username: 'moderator2',
118         password: 'super password'
119       }
120
121       await createUser({
122         url: server.url,
123         accessToken: server.accessToken,
124         username: moderator.username,
125         password: moderator.password,
126         role: UserRole.MODERATOR
127       })
128     }
129
130     {
131       const res = await uploadVideo(server.url, server.accessToken, {})
132       videoId = res.body.video.id
133     }
134
135     {
136       const res = await getUsersList(server.url, server.accessToken)
137       const users: User[] = res.body.data
138
139       userId = users.find(u => u.username === 'user1').id
140       rootId = users.find(u => u.username === 'root').id
141       moderatorId = users.find(u => u.username === 'moderator2').id
142     }
143   })
144
145   describe('When listing users', function () {
146     it('Should fail with a bad start pagination', async function () {
147       await checkBadStartPagination(server.url, path, server.accessToken)
148     })
149
150     it('Should fail with a bad count pagination', async function () {
151       await checkBadCountPagination(server.url, path, server.accessToken)
152     })
153
154     it('Should fail with an incorrect sort', async function () {
155       await checkBadSortPagination(server.url, path, server.accessToken)
156     })
157
158     it('Should fail with a non authenticated user', async function () {
159       await makeGetRequest({
160         url: server.url,
161         path,
162         statusCodeExpected: 401
163       })
164     })
165
166     it('Should fail with a non admin user', async function () {
167       await makeGetRequest({
168         url: server.url,
169         path,
170         token: userAccessToken,
171         statusCodeExpected: 403
172       })
173     })
174   })
175
176   describe('When adding a new user', function () {
177     const baseCorrectParams = {
178       username: 'user2',
179       email: 'test@example.com',
180       password: 'my super password',
181       videoQuota: -1,
182       videoQuotaDaily: -1,
183       role: UserRole.USER,
184       adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
185     }
186
187     it('Should fail with a too small username', async function () {
188       const fields = immutableAssign(baseCorrectParams, { username: '' })
189
190       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
191     })
192
193     it('Should fail with a too long username', async function () {
194       const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
195
196       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
197     })
198
199     it('Should fail with a not lowercase username', async function () {
200       const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
201
202       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
203     })
204
205     it('Should fail with an incorrect username', async function () {
206       const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
207
208       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
209     })
210
211     it('Should fail with a missing email', async function () {
212       const fields = omit(baseCorrectParams, 'email')
213
214       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
215     })
216
217     it('Should fail with an invalid email', async function () {
218       const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
219
220       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
221     })
222
223     it('Should fail with a too small password', async function () {
224       const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
225
226       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
227     })
228
229     it('Should fail with a too long password', async function () {
230       const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
231
232       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
233     })
234
235     it('Should fail with empty password and no smtp configured', async function () {
236       const fields = immutableAssign(baseCorrectParams, { password: '' })
237
238       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
239     })
240
241     it('Should succeed with no password on a server with smtp enabled', async function () {
242       this.timeout(10000)
243
244       killallServers([ server ])
245
246       const config = immutableAssign(overrideConfig, {
247         smtp: {
248           hostname: 'localhost',
249           port: emailPort
250         }
251       })
252       await reRunServer(server, config)
253
254       const fields = immutableAssign(baseCorrectParams, {
255         password: '',
256         username: 'create_password',
257         email: 'create_password@example.com'
258       })
259
260       await makePostBodyRequest({
261         url: server.url,
262         path: path,
263         token: server.accessToken,
264         fields,
265         statusCodeExpected: 200
266       })
267     })
268
269     it('Should fail with invalid admin flags', async function () {
270       const fields = immutableAssign(baseCorrectParams, { adminFlags: 'toto' })
271
272       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
273     })
274
275     it('Should fail with an non authenticated user', async function () {
276       await makePostBodyRequest({
277         url: server.url,
278         path,
279         token: 'super token',
280         fields: baseCorrectParams,
281         statusCodeExpected: 401
282       })
283     })
284
285     it('Should fail if we add a user with the same username', async function () {
286       const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
287
288       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
289     })
290
291     it('Should fail if we add a user with the same email', async function () {
292       const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
293
294       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
295     })
296
297     it('Should fail without a videoQuota', async function () {
298       const fields = omit(baseCorrectParams, 'videoQuota')
299
300       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
301     })
302
303     it('Should fail without a videoQuotaDaily', async function () {
304       const fields = omit(baseCorrectParams, 'videoQuotaDaily')
305
306       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
307     })
308
309     it('Should fail with an invalid videoQuota', async function () {
310       const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
311
312       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
313     })
314
315     it('Should fail with an invalid videoQuotaDaily', async function () {
316       const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
317
318       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
319     })
320
321     it('Should fail without a user role', async function () {
322       const fields = omit(baseCorrectParams, 'role')
323
324       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
325     })
326
327     it('Should fail with an invalid user role', async function () {
328       const fields = immutableAssign(baseCorrectParams, { role: 88989 })
329
330       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
331     })
332
333     it('Should fail with a "peertube" username', async function () {
334       const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
335
336       await makePostBodyRequest({
337         url: server.url,
338         path,
339         token: server.accessToken,
340         fields,
341         statusCodeExpected: 409
342       })
343     })
344
345     it('Should fail to create a moderator or an admin with a moderator', async function () {
346       for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
347         const fields = immutableAssign(baseCorrectParams, { role })
348
349         await makePostBodyRequest({
350           url: server.url,
351           path,
352           token: moderatorAccessToken,
353           fields,
354           statusCodeExpected: 403
355         })
356       }
357     })
358
359     it('Should succeed to create a user with a moderator', async function () {
360       const fields = immutableAssign(baseCorrectParams, { username: 'a4656', email: 'a4656@example.com', role: UserRole.USER })
361
362       await makePostBodyRequest({
363         url: server.url,
364         path,
365         token: moderatorAccessToken,
366         fields,
367         statusCodeExpected: 200
368       })
369     })
370
371     it('Should succeed with the correct params', async function () {
372       await makePostBodyRequest({
373         url: server.url,
374         path,
375         token: server.accessToken,
376         fields: baseCorrectParams,
377         statusCodeExpected: 200
378       })
379     })
380
381     it('Should fail with a non admin user', async function () {
382       const user = {
383         username: 'user1',
384         password: 'my super password'
385       }
386       userAccessToken = await userLogin(server, user)
387
388       const fields = {
389         username: 'user3',
390         email: 'test@example.com',
391         password: 'my super password',
392         videoQuota: 42000000
393       }
394       await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
395     })
396   })
397
398   describe('When updating my account', function () {
399     it('Should fail with an invalid email attribute', async function () {
400       const fields = {
401         email: 'blabla'
402       }
403
404       await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
405     })
406
407     it('Should fail with a too small password', async function () {
408       const fields = {
409         currentPassword: 'my super password',
410         password: 'bla'
411       }
412
413       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
414     })
415
416     it('Should fail with a too long password', async function () {
417       const fields = {
418         currentPassword: 'my super password',
419         password: 'super'.repeat(61)
420       }
421
422       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
423     })
424
425     it('Should fail without the current password', async function () {
426       const fields = {
427         currentPassword: 'my super password',
428         password: 'super'.repeat(61)
429       }
430
431       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
432     })
433
434     it('Should fail with an invalid current password', async function () {
435       const fields = {
436         currentPassword: 'my super password fail',
437         password: 'super'.repeat(61)
438       }
439
440       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 401 })
441     })
442
443     it('Should fail with an invalid NSFW policy attribute', async function () {
444       const fields = {
445         nsfwPolicy: 'hello'
446       }
447
448       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
449     })
450
451     it('Should fail with an invalid autoPlayVideo attribute', async function () {
452       const fields = {
453         autoPlayVideo: -1
454       }
455
456       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
457     })
458
459     it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
460       const fields = {
461         autoPlayNextVideo: -1
462       }
463
464       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
465     })
466
467     it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
468       const fields = {
469         videosHistoryEnabled: -1
470       }
471
472       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
473     })
474
475     it('Should fail with an non authenticated user', async function () {
476       const fields = {
477         currentPassword: 'my super password',
478         password: 'my super password'
479       }
480
481       await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 })
482     })
483
484     it('Should fail with a too long description', async function () {
485       const fields = {
486         description: 'super'.repeat(201)
487       }
488
489       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
490     })
491
492     it('Should fail with an invalid videoLanguages attribute', async function () {
493       {
494         const fields = {
495           videoLanguages: 'toto'
496         }
497
498         await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
499       }
500
501       {
502         const languages = []
503         for (let i = 0; i < 1000; i++) {
504           languages.push('fr')
505         }
506
507         const fields = {
508           videoLanguages: languages
509         }
510
511         await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
512       }
513     })
514
515     it('Should fail with an invalid theme', async function () {
516       const fields = { theme: 'invalid' }
517       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
518     })
519
520     it('Should fail with an unknown theme', async function () {
521       const fields = { theme: 'peertube-theme-unknown' }
522       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
523     })
524
525     it('Should fail with an invalid noInstanceConfigWarningModal attribute', async function () {
526       const fields = {
527         noInstanceConfigWarningModal: -1
528       }
529
530       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
531     })
532
533     it('Should fail with an invalid noWelcomeModal attribute', async function () {
534       const fields = {
535         noWelcomeModal: -1
536       }
537
538       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
539     })
540
541     it('Should succeed to change password with the correct params', async function () {
542       const fields = {
543         currentPassword: 'my super password',
544         password: 'my super password',
545         nsfwPolicy: 'blur',
546         autoPlayVideo: false,
547         email: 'super_email@example.com',
548         theme: 'default',
549         noInstanceConfigWarningModal: true,
550         noWelcomeModal: true
551       }
552
553       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
554     })
555
556     it('Should succeed without password change with the correct params', async function () {
557       const fields = {
558         nsfwPolicy: 'blur',
559         autoPlayVideo: false
560       }
561
562       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
563     })
564   })
565
566   describe('When updating my avatar', function () {
567     it('Should fail without an incorrect input file', async function () {
568       const fields = {}
569       const attaches = {
570         avatarfile: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
571       }
572       await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
573     })
574
575     it('Should fail with a big file', async function () {
576       const fields = {}
577       const attaches = {
578         avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
579       }
580       await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
581     })
582
583     it('Should fail with an unauthenticated user', async function () {
584       const fields = {}
585       const attaches = {
586         avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
587       }
588       await makeUploadRequest({
589         url: server.url,
590         path: path + '/me/avatar/pick',
591         fields,
592         attaches,
593         statusCodeExpected: 401
594       })
595     })
596
597     it('Should succeed with the correct params', async function () {
598       const fields = {}
599       const attaches = {
600         avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
601       }
602       await makeUploadRequest({
603         url: server.url,
604         path: path + '/me/avatar/pick',
605         token: server.accessToken,
606         fields,
607         attaches,
608         statusCodeExpected: 200
609       })
610     })
611   })
612
613   describe('When getting a user', function () {
614
615     it('Should fail with an non authenticated user', async function () {
616       await makeGetRequest({ url: server.url, path: path + userId, token: 'super token', statusCodeExpected: 401 })
617     })
618
619     it('Should fail with a non admin user', async function () {
620       await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 403 })
621     })
622
623     it('Should succeed with the correct params', async function () {
624       await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: 200 })
625     })
626   })
627
628   describe('When updating a user', function () {
629
630     it('Should fail with an invalid email attribute', async function () {
631       const fields = {
632         email: 'blabla'
633       }
634
635       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
636     })
637
638     it('Should fail with an invalid emailVerified attribute', async function () {
639       const fields = {
640         emailVerified: 'yes'
641       }
642
643       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
644     })
645
646     it('Should fail with an invalid videoQuota attribute', async function () {
647       const fields = {
648         videoQuota: -90
649       }
650
651       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
652     })
653
654     it('Should fail with an invalid user role attribute', async function () {
655       const fields = {
656         role: 54878
657       }
658
659       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
660     })
661
662     it('Should fail with a too small password', async function () {
663       const fields = {
664         currentPassword: 'my super password',
665         password: 'bla'
666       }
667
668       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
669     })
670
671     it('Should fail with a too long password', async function () {
672       const fields = {
673         currentPassword: 'my super password',
674         password: 'super'.repeat(61)
675       }
676
677       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
678     })
679
680     it('Should fail with an non authenticated user', async function () {
681       const fields = {
682         videoQuota: 42
683       }
684
685       await makePutBodyRequest({ url: server.url, path: path + userId, token: 'super token', fields, statusCodeExpected: 401 })
686     })
687
688     it('Should fail when updating root role', async function () {
689       const fields = {
690         role: UserRole.MODERATOR
691       }
692
693       await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
694     })
695
696     it('Should fail with invalid admin flags', async function () {
697       const fields = { adminFlags: 'toto' }
698
699       await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
700     })
701
702     it('Should fail to update an admin with a moderator', async function () {
703       const fields = {
704         videoQuota: 42
705       }
706
707       await makePutBodyRequest({
708         url: server.url,
709         path: path + moderatorId,
710         token: moderatorAccessToken,
711         fields,
712         statusCodeExpected: 403
713       })
714     })
715
716     it('Should succeed to update a user with a moderator', async function () {
717       const fields = {
718         videoQuota: 42
719       }
720
721       await makePutBodyRequest({
722         url: server.url,
723         path: path + userId,
724         token: moderatorAccessToken,
725         fields,
726         statusCodeExpected: 204
727       })
728     })
729
730     it('Should succeed with the correct params', async function () {
731       const fields = {
732         email: 'email@example.com',
733         emailVerified: true,
734         videoQuota: 42,
735         role: UserRole.USER
736       }
737
738       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 })
739     })
740   })
741
742   describe('When getting my information', function () {
743     it('Should fail with a non authenticated user', async function () {
744       await getMyUserInformation(server.url, 'fake_token', 401)
745     })
746
747     it('Should success with the correct parameters', async function () {
748       await getMyUserInformation(server.url, userAccessToken)
749     })
750   })
751
752   describe('When getting my video rating', function () {
753     it('Should fail with a non authenticated user', async function () {
754       await getMyUserVideoRating(server.url, 'fake_token', videoId, 401)
755     })
756
757     it('Should fail with an incorrect video uuid', async function () {
758       await getMyUserVideoRating(server.url, server.accessToken, 'blabla', 400)
759     })
760
761     it('Should fail with an unknown video', async function () {
762       await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', 404)
763     })
764
765     it('Should succeed with the correct parameters', async function () {
766       await getMyUserVideoRating(server.url, server.accessToken, videoId)
767     })
768   })
769
770   describe('When retrieving my global ratings', function () {
771     const path = '/api/v1/accounts/user1/ratings'
772
773     it('Should fail with a bad start pagination', async function () {
774       await checkBadStartPagination(server.url, path, userAccessToken)
775     })
776
777     it('Should fail with a bad count pagination', async function () {
778       await checkBadCountPagination(server.url, path, userAccessToken)
779     })
780
781     it('Should fail with an incorrect sort', async function () {
782       await checkBadSortPagination(server.url, path, userAccessToken)
783     })
784
785     it('Should fail with a unauthenticated user', async function () {
786       await makeGetRequest({ url: server.url, path, statusCodeExpected: 401 })
787     })
788
789     it('Should fail with a another user', async function () {
790       await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 403 })
791     })
792
793     it('Should fail with a bad type', async function () {
794       await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { rating: 'toto ' }, statusCodeExpected: 400 })
795     })
796
797     it('Should succeed with the correct params', async function () {
798       await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 200 })
799     })
800   })
801
802   describe('When blocking/unblocking/removing user', function () {
803     it('Should fail with an incorrect id', async function () {
804       await removeUser(server.url, 'blabla', server.accessToken, 400)
805       await blockUser(server.url, 'blabla', server.accessToken, 400)
806       await unblockUser(server.url, 'blabla', server.accessToken, 400)
807     })
808
809     it('Should fail with the root user', async function () {
810       await removeUser(server.url, rootId, server.accessToken, 400)
811       await blockUser(server.url, rootId, server.accessToken, 400)
812       await unblockUser(server.url, rootId, server.accessToken, 400)
813     })
814
815     it('Should return 404 with a non existing id', async function () {
816       await removeUser(server.url, 4545454, server.accessToken, 404)
817       await blockUser(server.url, 4545454, server.accessToken, 404)
818       await unblockUser(server.url, 4545454, server.accessToken, 404)
819     })
820
821     it('Should fail with a non admin user', async function () {
822       await removeUser(server.url, userId, userAccessToken, 403)
823       await blockUser(server.url, userId, userAccessToken, 403)
824       await unblockUser(server.url, userId, userAccessToken, 403)
825     })
826
827     it('Should fail on a moderator with a moderator', async function () {
828       await removeUser(server.url, moderatorId, moderatorAccessToken, 403)
829       await blockUser(server.url, moderatorId, moderatorAccessToken, 403)
830       await unblockUser(server.url, moderatorId, moderatorAccessToken, 403)
831     })
832
833     it('Should succeed on a user with a moderator', async function () {
834       await blockUser(server.url, userId, moderatorAccessToken)
835       await unblockUser(server.url, userId, moderatorAccessToken)
836     })
837   })
838
839   describe('When deleting our account', function () {
840     it('Should fail with with the root account', async function () {
841       await deleteMe(server.url, server.accessToken, 400)
842     })
843   })
844
845   describe('When registering a new user', function () {
846     const registrationPath = path + '/register'
847     const baseCorrectParams = {
848       username: 'user3',
849       displayName: 'super user',
850       email: 'test3@example.com',
851       password: 'my super password'
852     }
853
854     it('Should fail with a too small username', async function () {
855       const fields = immutableAssign(baseCorrectParams, { username: '' })
856
857       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
858     })
859
860     it('Should fail with a too long username', async function () {
861       const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
862
863       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
864     })
865
866     it('Should fail with an incorrect username', async function () {
867       const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
868
869       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
870     })
871
872     it('Should fail with a missing email', async function () {
873       const fields = omit(baseCorrectParams, 'email')
874
875       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
876     })
877
878     it('Should fail with an invalid email', async function () {
879       const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
880
881       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
882     })
883
884     it('Should fail with a too small password', async function () {
885       const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
886
887       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
888     })
889
890     it('Should fail with a too long password', async function () {
891       const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
892
893       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
894     })
895
896     it('Should fail if we register a user with the same username', async function () {
897       const fields = immutableAssign(baseCorrectParams, { username: 'root' })
898
899       await makePostBodyRequest({
900         url: server.url,
901         path: registrationPath,
902         token: server.accessToken,
903         fields,
904         statusCodeExpected: 409
905       })
906     })
907
908     it('Should fail with a "peertube" username', async function () {
909       const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
910
911       await makePostBodyRequest({
912         url: server.url,
913         path: registrationPath,
914         token: server.accessToken,
915         fields,
916         statusCodeExpected: 409
917       })
918     })
919
920     it('Should fail if we register a user with the same email', async function () {
921       const fields = immutableAssign(baseCorrectParams, { email: 'admin' + server.internalServerNumber + '@example.com' })
922
923       await makePostBodyRequest({
924         url: server.url,
925         path: registrationPath,
926         token: server.accessToken,
927         fields,
928         statusCodeExpected: 409
929       })
930     })
931
932     it('Should fail with a bad display name', async function () {
933       const fields = immutableAssign(baseCorrectParams, { displayName: 'a'.repeat(150) })
934
935       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
936     })
937
938     it('Should fail with a bad channel name', async function () {
939       const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } })
940
941       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
942     })
943
944     it('Should fail with a bad channel display name', async function () {
945       const fields = immutableAssign(baseCorrectParams, { channel: { name: 'toto', displayName: '' } })
946
947       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
948     })
949
950     it('Should fail with a channel name that is the same as username', async function () {
951       const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
952       const fields = immutableAssign(baseCorrectParams, source)
953
954       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
955     })
956
957     it('Should fail with an existing channel', async function () {
958       const videoChannelAttributesArg = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
959       await addVideoChannel(server.url, server.accessToken, videoChannelAttributesArg)
960
961       const fields = immutableAssign(baseCorrectParams, { channel: { name: 'existing_channel', displayName: 'toto' } })
962
963       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields, statusCodeExpected: 409 })
964     })
965
966     it('Should succeed with the correct params', async function () {
967       const fields = immutableAssign(baseCorrectParams, { channel: { name: 'super_channel', displayName: 'toto' } })
968
969       await makePostBodyRequest({
970         url: server.url,
971         path: registrationPath,
972         token: server.accessToken,
973         fields: fields,
974         statusCodeExpected: 204
975       })
976     })
977
978     it('Should fail on a server with registration disabled', async function () {
979       const fields = {
980         username: 'user4',
981         email: 'test4@example.com',
982         password: 'my super password 4'
983       }
984
985       await makePostBodyRequest({
986         url: serverWithRegistrationDisabled.url,
987         path: registrationPath,
988         token: serverWithRegistrationDisabled.accessToken,
989         fields,
990         statusCodeExpected: 403
991       })
992     })
993   })
994
995   describe('When registering multiple users on a server with users limit', function () {
996     it('Should fail when after 3 registrations', async function () {
997       await registerUser(server.url, 'user42', 'super password', 403)
998     })
999   })
1000
1001   describe('When having a video quota', function () {
1002     it('Should fail with a user having too many videos', async function () {
1003       await updateUser({
1004         url: server.url,
1005         userId: rootId,
1006         accessToken: server.accessToken,
1007         videoQuota: 42
1008       })
1009
1010       await uploadVideo(server.url, server.accessToken, {}, 403)
1011     })
1012
1013     it('Should fail with a registered user having too many videos', async function () {
1014       this.timeout(30000)
1015
1016       const user = {
1017         username: 'user3',
1018         password: 'my super password'
1019       }
1020       userAccessToken = await userLogin(server, user)
1021
1022       const videoAttributes = { fixture: 'video_short2.webm' }
1023       await uploadVideo(server.url, userAccessToken, videoAttributes)
1024       await uploadVideo(server.url, userAccessToken, videoAttributes)
1025       await uploadVideo(server.url, userAccessToken, videoAttributes)
1026       await uploadVideo(server.url, userAccessToken, videoAttributes)
1027       await uploadVideo(server.url, userAccessToken, videoAttributes)
1028       await uploadVideo(server.url, userAccessToken, videoAttributes, 403)
1029     })
1030
1031     it('Should fail to import with HTTP/Torrent/magnet', async function () {
1032       this.timeout(120000)
1033
1034       const baseAttributes = {
1035         channelId: 1,
1036         privacy: VideoPrivacy.PUBLIC
1037       }
1038       await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() }))
1039       await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
1040       await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' as any }))
1041
1042       await waitJobs([ server ])
1043
1044       const res = await getMyVideoImports(server.url, server.accessToken)
1045
1046       expect(res.body.total).to.equal(3)
1047       const videoImports: VideoImport[] = res.body.data
1048       expect(videoImports).to.have.lengthOf(3)
1049
1050       for (const videoImport of videoImports) {
1051         expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
1052         expect(videoImport.error).not.to.be.undefined
1053         expect(videoImport.error).to.contain('user video quota is exceeded')
1054       }
1055     })
1056   })
1057
1058   describe('When having a daily video quota', function () {
1059     it('Should fail with a user having too many videos', async function () {
1060       await updateUser({
1061         url: server.url,
1062         userId: rootId,
1063         accessToken: server.accessToken,
1064         videoQuotaDaily: 42
1065       })
1066
1067       await uploadVideo(server.url, server.accessToken, {}, 403)
1068     })
1069   })
1070
1071   describe('When having an absolute and daily video quota', function () {
1072     it('Should fail if exceeding total quota', async function () {
1073       await updateUser({
1074         url: server.url,
1075         userId: rootId,
1076         accessToken: server.accessToken,
1077         videoQuota: 42,
1078         videoQuotaDaily: 1024 * 1024 * 1024
1079       })
1080
1081       await uploadVideo(server.url, server.accessToken, {}, 403)
1082     })
1083
1084     it('Should fail if exceeding daily quota', async function () {
1085       await updateUser({
1086         url: server.url,
1087         userId: rootId,
1088         accessToken: server.accessToken,
1089         videoQuota: 1024 * 1024 * 1024,
1090         videoQuotaDaily: 42
1091       })
1092
1093       await uploadVideo(server.url, server.accessToken, {}, 403)
1094     })
1095   })
1096
1097   describe('When asking a password reset', function () {
1098     const path = '/api/v1/users/ask-reset-password'
1099
1100     it('Should fail with a missing email', async function () {
1101       const fields = {}
1102
1103       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1104     })
1105
1106     it('Should fail with an invalid email', async function () {
1107       const fields = { email: 'hello' }
1108
1109       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1110     })
1111
1112     it('Should success with the correct params', async function () {
1113       const fields = { email: 'admin@example.com' }
1114
1115       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
1116     })
1117   })
1118
1119   describe('When asking for an account verification email', function () {
1120     const path = '/api/v1/users/ask-send-verify-email'
1121
1122     it('Should fail with a missing email', async function () {
1123       const fields = {}
1124
1125       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1126     })
1127
1128     it('Should fail with an invalid email', async function () {
1129       const fields = { email: 'hello' }
1130
1131       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1132     })
1133
1134     it('Should succeed with the correct params', async function () {
1135       const fields = { email: 'admin@example.com' }
1136
1137       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
1138     })
1139   })
1140
1141   after(async function () {
1142     MockSmtpServer.Instance.kill()
1143
1144     await cleanupTests([ server, serverWithRegistrationDisabled ])
1145   })
1146 })