Add hardware information in instance config
[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 fail with an invalid noInstanceConfigWarningModal attribute', async function () {
480       const fields = {
481         noInstanceConfigWarningModal: -1
482       }
483
484       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
485     })
486
487     it('Should fail with an invalid noWelcomeModal attribute', async function () {
488       const fields = {
489         noWelcomeModal: -1
490       }
491
492       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
493     })
494
495     it('Should succeed to change password with the correct params', async function () {
496       const fields = {
497         currentPassword: 'my super password',
498         password: 'my super password',
499         nsfwPolicy: 'blur',
500         autoPlayVideo: false,
501         email: 'super_email@example.com',
502         theme: 'default',
503         noInstanceConfigWarningModal: true,
504         noWelcomeModal: true
505       }
506
507       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
508     })
509
510     it('Should succeed without password change with the correct params', async function () {
511       const fields = {
512         nsfwPolicy: 'blur',
513         autoPlayVideo: false
514       }
515
516       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
517     })
518   })
519
520   describe('When updating my avatar', function () {
521     it('Should fail without an incorrect input file', async function () {
522       const fields = {}
523       const attaches = {
524         'avatarfile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
525       }
526       await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
527     })
528
529     it('Should fail with a big file', async function () {
530       const fields = {}
531       const attaches = {
532         'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
533       }
534       await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
535     })
536
537     it('Should fail with an unauthenticated user', async function () {
538       const fields = {}
539       const attaches = {
540         'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
541       }
542       await makeUploadRequest({
543         url: server.url,
544         path: path + '/me/avatar/pick',
545         fields,
546         attaches,
547         statusCodeExpected: 401
548       })
549     })
550
551     it('Should succeed with the correct params', async function () {
552       const fields = {}
553       const attaches = {
554         'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
555       }
556       await makeUploadRequest({
557         url: server.url,
558         path: path + '/me/avatar/pick',
559         token: server.accessToken,
560         fields,
561         attaches,
562         statusCodeExpected: 200
563       })
564     })
565   })
566
567   describe('When getting a user', function () {
568
569     it('Should fail with an non authenticated user', async function () {
570       await makeGetRequest({ url: server.url, path: path + userId, token: 'super token', statusCodeExpected: 401 })
571     })
572
573     it('Should fail with a non admin user', async function () {
574       await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 403 })
575     })
576
577     it('Should succeed with the correct params', async function () {
578       await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: 200 })
579     })
580   })
581
582   describe('When updating a user', function () {
583
584     it('Should fail with an invalid email attribute', async function () {
585       const fields = {
586         email: 'blabla'
587       }
588
589       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
590     })
591
592     it('Should fail with an invalid emailVerified attribute', async function () {
593       const fields = {
594         emailVerified: 'yes'
595       }
596
597       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
598     })
599
600     it('Should fail with an invalid videoQuota attribute', async function () {
601       const fields = {
602         videoQuota: -90
603       }
604
605       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
606     })
607
608     it('Should fail with an invalid user role attribute', async function () {
609       const fields = {
610         role: 54878
611       }
612
613       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
614     })
615
616     it('Should fail with a too small password', async function () {
617       const fields = {
618         currentPassword: 'my super password',
619         password: 'bla'
620       }
621
622       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
623     })
624
625     it('Should fail with a too long password', async function () {
626       const fields = {
627         currentPassword: 'my super password',
628         password: 'super'.repeat(61)
629       }
630
631       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
632     })
633
634     it('Should fail with an non authenticated user', async function () {
635       const fields = {
636         videoQuota: 42
637       }
638
639       await makePutBodyRequest({ url: server.url, path: path + userId, token: 'super token', fields, statusCodeExpected: 401 })
640     })
641
642     it('Should fail when updating root role', async function () {
643       const fields = {
644         role: UserRole.MODERATOR
645       }
646
647       await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
648     })
649
650     it('Should fail with invalid admin flags', async function () {
651       const fields = { adminFlags: 'toto' }
652
653       await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
654     })
655
656     it('Should fail to update an admin with a moderator', async function () {
657       const fields = {
658         videoQuota: 42
659       }
660
661       await makePutBodyRequest({
662         url: server.url,
663         path: path + moderatorId,
664         token: moderatorAccessToken,
665         fields,
666         statusCodeExpected: 403
667       })
668     })
669
670     it('Should succeed to update a user with a moderator', async function () {
671       const fields = {
672         videoQuota: 42
673       }
674
675       await makePutBodyRequest({
676         url: server.url,
677         path: path + userId,
678         token: moderatorAccessToken,
679         fields,
680         statusCodeExpected: 204
681       })
682     })
683
684     it('Should succeed with the correct params', async function () {
685       const fields = {
686         email: 'email@example.com',
687         emailVerified: true,
688         videoQuota: 42,
689         role: UserRole.USER
690       }
691
692       await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 })
693     })
694   })
695
696   describe('When getting my information', function () {
697     it('Should fail with a non authenticated user', async function () {
698       await getMyUserInformation(server.url, 'fake_token', 401)
699     })
700
701     it('Should success with the correct parameters', async function () {
702       await getMyUserInformation(server.url, userAccessToken)
703     })
704   })
705
706   describe('When getting my video rating', function () {
707     it('Should fail with a non authenticated user', async function () {
708       await getMyUserVideoRating(server.url, 'fake_token', videoId, 401)
709     })
710
711     it('Should fail with an incorrect video uuid', async function () {
712       await getMyUserVideoRating(server.url, server.accessToken, 'blabla', 400)
713     })
714
715     it('Should fail with an unknown video', async function () {
716       await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', 404)
717     })
718
719     it('Should succeed with the correct parameters', async function () {
720       await getMyUserVideoRating(server.url, server.accessToken, videoId)
721     })
722   })
723
724   describe('When retrieving my global ratings', function () {
725     const path = '/api/v1/accounts/user1/ratings'
726
727     it('Should fail with a bad start pagination', async function () {
728       await checkBadStartPagination(server.url, path, userAccessToken)
729     })
730
731     it('Should fail with a bad count pagination', async function () {
732       await checkBadCountPagination(server.url, path, userAccessToken)
733     })
734
735     it('Should fail with an incorrect sort', async function () {
736       await checkBadSortPagination(server.url, path, userAccessToken)
737     })
738
739     it('Should fail with a unauthenticated user', async function () {
740       await makeGetRequest({ url: server.url, path, statusCodeExpected: 401 })
741     })
742
743     it('Should fail with a another user', async function () {
744       await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 403 })
745     })
746
747     it('Should fail with a bad type', async function () {
748       await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { rating: 'toto ' }, statusCodeExpected: 400 })
749     })
750
751     it('Should succeed with the correct params', async function () {
752       await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 200 })
753     })
754   })
755
756   describe('When blocking/unblocking/removing user', function () {
757     it('Should fail with an incorrect id', async function () {
758       await removeUser(server.url, 'blabla', server.accessToken, 400)
759       await blockUser(server.url, 'blabla', server.accessToken, 400)
760       await unblockUser(server.url, 'blabla', server.accessToken, 400)
761     })
762
763     it('Should fail with the root user', async function () {
764       await removeUser(server.url, rootId, server.accessToken, 400)
765       await blockUser(server.url, rootId, server.accessToken, 400)
766       await unblockUser(server.url, rootId, server.accessToken, 400)
767     })
768
769     it('Should return 404 with a non existing id', async function () {
770       await removeUser(server.url, 4545454, server.accessToken, 404)
771       await blockUser(server.url, 4545454, server.accessToken, 404)
772       await unblockUser(server.url, 4545454, server.accessToken, 404)
773     })
774
775     it('Should fail with a non admin user', async function () {
776       await removeUser(server.url, userId, userAccessToken, 403)
777       await blockUser(server.url, userId, userAccessToken, 403)
778       await unblockUser(server.url, userId, userAccessToken, 403)
779     })
780
781     it('Should fail on a moderator with a moderator', async function () {
782       await removeUser(server.url, moderatorId, moderatorAccessToken, 403)
783       await blockUser(server.url, moderatorId, moderatorAccessToken, 403)
784       await unblockUser(server.url, moderatorId, moderatorAccessToken, 403)
785     })
786
787     it('Should succeed on a user with a moderator', async function () {
788       await blockUser(server.url, userId, moderatorAccessToken)
789       await unblockUser(server.url, userId, moderatorAccessToken)
790     })
791   })
792
793   describe('When deleting our account', function () {
794     it('Should fail with with the root account', async function () {
795       await deleteMe(server.url, server.accessToken, 400)
796     })
797   })
798
799   describe('When registering a new user', function () {
800     const registrationPath = path + '/register'
801     const baseCorrectParams = {
802       username: 'user3',
803       displayName: 'super user',
804       email: 'test3@example.com',
805       password: 'my super password'
806     }
807
808     it('Should fail with a too small username', async function () {
809       const fields = immutableAssign(baseCorrectParams, { username: '' })
810
811       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
812     })
813
814     it('Should fail with a too long username', async function () {
815       const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
816
817       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
818     })
819
820     it('Should fail with an incorrect username', async function () {
821       const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
822
823       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
824     })
825
826     it('Should fail with a missing email', async function () {
827       const fields = omit(baseCorrectParams, 'email')
828
829       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
830     })
831
832     it('Should fail with an invalid email', async function () {
833       const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
834
835       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
836     })
837
838     it('Should fail with a too small password', async function () {
839       const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
840
841       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
842     })
843
844     it('Should fail with a too long password', async function () {
845       const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
846
847       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
848     })
849
850     it('Should fail if we register a user with the same username', async function () {
851       const fields = immutableAssign(baseCorrectParams, { username: 'root' })
852
853       await makePostBodyRequest({
854         url: server.url,
855         path: registrationPath,
856         token: server.accessToken,
857         fields,
858         statusCodeExpected: 409
859       })
860     })
861
862     it('Should fail with a "peertube" username', async function () {
863       const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
864
865       await makePostBodyRequest({
866         url: server.url,
867         path: registrationPath,
868         token: server.accessToken,
869         fields,
870         statusCodeExpected: 409
871       })
872     })
873
874     it('Should fail if we register a user with the same email', async function () {
875       const fields = immutableAssign(baseCorrectParams, { email: 'admin' + server.internalServerNumber + '@example.com' })
876
877       await makePostBodyRequest({
878         url: server.url,
879         path: registrationPath,
880         token: server.accessToken,
881         fields,
882         statusCodeExpected: 409
883       })
884     })
885
886     it('Should fail with a bad display name', async function () {
887       const fields = immutableAssign(baseCorrectParams, { displayName: 'a'.repeat(150) })
888
889       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
890     })
891
892     it('Should fail with a bad channel name', async function () {
893       const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } })
894
895       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
896     })
897
898     it('Should fail with a bad channel display name', async function () {
899       const fields = immutableAssign(baseCorrectParams, { channel: { name: 'toto', displayName: '' } })
900
901       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
902     })
903
904     it('Should fail with a channel name that is the same than user username', async function () {
905       const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
906       const fields = immutableAssign(baseCorrectParams, source)
907
908       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
909     })
910
911     it('Should fail with an existing channel', async function () {
912       const videoChannelAttributesArg = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
913       await addVideoChannel(server.url, server.accessToken, videoChannelAttributesArg)
914
915       const fields = immutableAssign(baseCorrectParams, { channel: { name: 'existing_channel', displayName: 'toto' } })
916
917       await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields, statusCodeExpected: 409 })
918     })
919
920     it('Should succeed with the correct params', async function () {
921       const fields = immutableAssign(baseCorrectParams, { channel: { name: 'super_channel', displayName: 'toto' } })
922
923       await makePostBodyRequest({
924         url: server.url,
925         path: registrationPath,
926         token: server.accessToken,
927         fields: fields,
928         statusCodeExpected: 204
929       })
930     })
931
932     it('Should fail on a server with registration disabled', async function () {
933       const fields = {
934         username: 'user4',
935         email: 'test4@example.com',
936         password: 'my super password 4'
937       }
938
939       await makePostBodyRequest({
940         url: serverWithRegistrationDisabled.url,
941         path: registrationPath,
942         token: serverWithRegistrationDisabled.accessToken,
943         fields,
944         statusCodeExpected: 403
945       })
946     })
947   })
948
949   describe('When registering multiple users on a server with users limit', function () {
950     it('Should fail when after 3 registrations', async function () {
951       await registerUser(server.url, 'user42', 'super password', 403)
952     })
953   })
954
955   describe('When having a video quota', function () {
956     it('Should fail with a user having too many videos', async function () {
957       await updateUser({
958         url: server.url,
959         userId: rootId,
960         accessToken: server.accessToken,
961         videoQuota: 42
962       })
963
964       await uploadVideo(server.url, server.accessToken, {}, 403)
965     })
966
967     it('Should fail with a registered user having too many videos', async function () {
968       this.timeout(30000)
969
970       const user = {
971         username: 'user3',
972         password: 'my super password'
973       }
974       userAccessToken = await userLogin(server, user)
975
976       const videoAttributes = { fixture: 'video_short2.webm' }
977       await uploadVideo(server.url, userAccessToken, videoAttributes)
978       await uploadVideo(server.url, userAccessToken, videoAttributes)
979       await uploadVideo(server.url, userAccessToken, videoAttributes)
980       await uploadVideo(server.url, userAccessToken, videoAttributes)
981       await uploadVideo(server.url, userAccessToken, videoAttributes)
982       await uploadVideo(server.url, userAccessToken, videoAttributes, 403)
983     })
984
985     it('Should fail to import with HTTP/Torrent/magnet', async function () {
986       this.timeout(120000)
987
988       const baseAttributes = {
989         channelId: 1,
990         privacy: VideoPrivacy.PUBLIC
991       }
992       await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() }))
993       await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
994       await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' }))
995
996       await waitJobs([ server ])
997
998       const res = await getMyVideoImports(server.url, server.accessToken)
999
1000       expect(res.body.total).to.equal(3)
1001       const videoImports: VideoImport[] = res.body.data
1002       expect(videoImports).to.have.lengthOf(3)
1003
1004       for (const videoImport of videoImports) {
1005         expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
1006         expect(videoImport.error).not.to.be.undefined
1007         expect(videoImport.error).to.contain('user video quota is exceeded')
1008       }
1009     })
1010   })
1011
1012   describe('When having a daily video quota', function () {
1013     it('Should fail with a user having too many videos', async function () {
1014       await updateUser({
1015         url: server.url,
1016         userId: rootId,
1017         accessToken: server.accessToken,
1018         videoQuotaDaily: 42
1019       })
1020
1021       await uploadVideo(server.url, server.accessToken, {}, 403)
1022     })
1023   })
1024
1025   describe('When having an absolute and daily video quota', function () {
1026     it('Should fail if exceeding total quota', async function () {
1027       await updateUser({
1028         url: server.url,
1029         userId: rootId,
1030         accessToken: server.accessToken,
1031         videoQuota: 42,
1032         videoQuotaDaily: 1024 * 1024 * 1024
1033       })
1034
1035       await uploadVideo(server.url, server.accessToken, {}, 403)
1036     })
1037
1038     it('Should fail if exceeding daily quota', async function () {
1039       await updateUser({
1040         url: server.url,
1041         userId: rootId,
1042         accessToken: server.accessToken,
1043         videoQuota: 1024 * 1024 * 1024,
1044         videoQuotaDaily: 42
1045       })
1046
1047       await uploadVideo(server.url, server.accessToken, {}, 403)
1048     })
1049   })
1050
1051   describe('When asking a password reset', function () {
1052     const path = '/api/v1/users/ask-reset-password'
1053
1054     it('Should fail with a missing email', async function () {
1055       const fields = {}
1056
1057       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1058     })
1059
1060     it('Should fail with an invalid email', async function () {
1061       const fields = { email: 'hello' }
1062
1063       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1064     })
1065
1066     it('Should success with the correct params', async function () {
1067       const fields = { email: 'admin@example.com' }
1068
1069       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
1070     })
1071   })
1072
1073   describe('When asking for an account verification email', function () {
1074     const path = '/api/v1/users/ask-send-verify-email'
1075
1076     it('Should fail with a missing email', async function () {
1077       const fields = {}
1078
1079       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1080     })
1081
1082     it('Should fail with an invalid email', async function () {
1083       const fields = { email: 'hello' }
1084
1085       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1086     })
1087
1088     it('Should succeed with the correct params', async function () {
1089       const fields = { email: 'admin@example.com' }
1090
1091       await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
1092     })
1093   })
1094
1095   after(async function () {
1096     await cleanupTests([ server, serverWithRegistrationDisabled ])
1097   })
1098 })