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