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