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