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