1 /* tslint:disable:no-unused-expression */
3 import { omit } from 'lodash'
5 import { join } from 'path'
6 import { UserRole, VideoImport, VideoImportState } from '../../../../shared'
25 setAccessTokensToServers,
30 } from '../../../../shared/extra-utils'
32 checkBadCountPagination,
33 checkBadSortPagination,
34 checkBadStartPagination
35 } from '../../../../shared/extra-utils/requests/check-api-params'
36 import { getMagnetURI, getMyVideoImports, getYoutubeVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
37 import { VideoPrivacy } from '../../../../shared/models/videos'
38 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
39 import { expect } from 'chai'
40 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
42 describe('Test users API validators', function () {
43 const path = '/api/v1/users/'
47 let server: ServerInfo
48 let serverWithRegistrationDisabled: ServerInfo
49 let userAccessToken = ''
53 password: 'my super password'
56 // ---------------------------------------------------------------
58 before(async function () {
61 server = await flushAndRunServer(1)
62 serverWithRegistrationDisabled = await flushAndRunServer(2)
64 await setAccessTokensToServers([ server ])
66 const videoQuota = 42000000
69 accessToken: server.accessToken,
70 username: user.username,
71 password: user.password,
72 videoQuota: videoQuota
74 userAccessToken = await userLogin(server, user)
77 const res = await getMyUserInformation(server.url, server.accessToken)
78 channelId = res.body.videoChannels[ 0 ].id
82 const res = await uploadVideo(server.url, server.accessToken, {})
83 videoId = res.body.video.id
87 describe('When listing users', function () {
88 it('Should fail with a bad start pagination', async function () {
89 await checkBadStartPagination(server.url, path, server.accessToken)
92 it('Should fail with a bad count pagination', async function () {
93 await checkBadCountPagination(server.url, path, server.accessToken)
96 it('Should fail with an incorrect sort', async function () {
97 await checkBadSortPagination(server.url, path, server.accessToken)
100 it('Should fail with a non authenticated user', async function () {
101 await makeGetRequest({
104 statusCodeExpected: 401
108 it('Should fail with a non admin user', async function () {
109 await makeGetRequest({
112 token: userAccessToken,
113 statusCodeExpected: 403
118 describe('When adding a new user', function () {
119 const baseCorrectParams = {
121 email: 'test@example.com',
122 password: 'my super password',
126 adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST
129 it('Should fail with a too small username', async function () {
130 const fields = immutableAssign(baseCorrectParams, { username: '' })
132 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
135 it('Should fail with a too long username', async function () {
136 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
138 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
141 it('Should fail with a not lowercase username', async function () {
142 const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
144 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
147 it('Should fail with an incorrect username', async function () {
148 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
150 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
153 it('Should fail with a missing email', async function () {
154 const fields = omit(baseCorrectParams, 'email')
156 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
159 it('Should fail with an invalid email', async function () {
160 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
162 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
165 it('Should fail with a too small password', async function () {
166 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
168 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
171 it('Should fail with a too long password', async function () {
172 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
174 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
177 it('Should fail with invalid admin flags', async function () {
178 const fields = immutableAssign(baseCorrectParams, { adminFlags: 'toto' })
180 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
183 it('Should fail with an non authenticated user', async function () {
184 await makePostBodyRequest({
187 token: 'super token',
188 fields: baseCorrectParams,
189 statusCodeExpected: 401
193 it('Should fail if we add a user with the same username', async function () {
194 const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
196 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
199 it('Should fail if we add a user with the same email', async function () {
200 const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
202 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
205 it('Should fail without a videoQuota', async function () {
206 const fields = omit(baseCorrectParams, 'videoQuota')
208 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
211 it('Should fail without a videoQuotaDaily', async function () {
212 const fields = omit(baseCorrectParams, 'videoQuotaDaily')
214 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
217 it('Should fail with an invalid videoQuota', async function () {
218 const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
220 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
223 it('Should fail with an invalid videoQuotaDaily', async function () {
224 const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
226 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
229 it('Should fail without a user role', async function () {
230 const fields = omit(baseCorrectParams, 'role')
232 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
235 it('Should fail with an invalid user role', async function () {
236 const fields = immutableAssign(baseCorrectParams, { role: 88989 })
238 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
241 it('Should fail with a "peertube" username', async function () {
242 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
244 await makePostBodyRequest({
247 token: server.accessToken,
249 statusCodeExpected: 409
253 it('Should succeed with the correct params', async function () {
254 await makePostBodyRequest({
257 token: server.accessToken,
258 fields: baseCorrectParams,
259 statusCodeExpected: 200
263 it('Should fail with a non admin user', async function () {
266 password: 'my super password'
268 userAccessToken = await userLogin(server, user)
272 email: 'test@example.com',
273 password: 'my super password',
276 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
280 describe('When updating my account', function () {
281 it('Should fail with an invalid email attribute', async function () {
286 await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
289 it('Should fail with a too small password', async function () {
291 currentPassword: 'my super password',
295 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
298 it('Should fail with a too long password', async function () {
300 currentPassword: 'my super password',
301 password: 'super'.repeat(61)
304 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
307 it('Should fail without the current password', async function () {
309 currentPassword: 'my super password',
310 password: 'super'.repeat(61)
313 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
316 it('Should fail with an invalid current password', async function () {
318 currentPassword: 'my super password fail',
319 password: 'super'.repeat(61)
322 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 401 })
325 it('Should fail with an invalid NSFW policy attribute', async function () {
330 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
333 it('Should fail with an invalid autoPlayVideo attribute', async function () {
338 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
341 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
343 videosHistoryEnabled: -1
346 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
349 it('Should fail with an non authenticated user', async function () {
351 currentPassword: 'my super password',
352 password: 'my super password'
355 await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 })
358 it('Should fail with a too long description', async function () {
360 description: 'super'.repeat(201)
363 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
366 it('Should succeed to change password with the correct params', async function () {
368 currentPassword: 'my super password',
369 password: 'my super password',
371 autoPlayVideo: false,
372 email: 'super_email@example.com'
375 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
378 it('Should succeed without password change with the correct params', async function () {
381 autoPlayVideo: false,
382 email: 'super_email@example.com'
385 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
389 describe('When updating my avatar', function () {
390 it('Should fail without an incorrect input file', async function () {
393 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
395 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
398 it('Should fail with a big file', async function () {
401 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
403 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
406 it('Should fail with an unauthenticated user', async function () {
409 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
411 await makeUploadRequest({
413 path: path + '/me/avatar/pick',
416 statusCodeExpected: 401
420 it('Should succeed with the correct params', async function () {
423 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
425 await makeUploadRequest({
427 path: path + '/me/avatar/pick',
428 token: server.accessToken,
431 statusCodeExpected: 200
436 describe('When getting a user', function () {
437 before(async function () {
438 const res = await getUsersList(server.url, server.accessToken)
440 userId = res.body.data[1].id
443 it('Should fail with an non authenticated user', async function () {
444 await makeGetRequest({ url: server.url, path: path + userId, token: 'super token', statusCodeExpected: 401 })
447 it('Should fail with a non admin user', async function () {
448 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 403 })
451 it('Should succeed with the correct params', async function () {
452 await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: 200 })
456 describe('When updating a user', function () {
458 before(async function () {
459 const res = await getUsersList(server.url, server.accessToken)
461 userId = res.body.data[1].id
462 rootId = res.body.data[2].id
465 it('Should fail with an invalid email attribute', async function () {
470 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
473 it('Should fail with an invalid emailVerified attribute', async function () {
478 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
481 it('Should fail with an invalid videoQuota attribute', async function () {
486 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
489 it('Should fail with an invalid user role attribute', async function () {
494 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
497 it('Should fail with a too small password', async function () {
499 currentPassword: 'my super password',
503 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
506 it('Should fail with a too long password', async function () {
508 currentPassword: 'my super password',
509 password: 'super'.repeat(61)
512 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
515 it('Should fail with an non authenticated user', async function () {
520 await makePutBodyRequest({ url: server.url, path: path + userId, token: 'super token', fields, statusCodeExpected: 401 })
523 it('Should fail when updating root role', async function () {
525 role: UserRole.MODERATOR
528 await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
531 it('Should fail with invalid admin flags', async function () {
532 const fields = { adminFlags: 'toto' }
534 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
537 it('Should succeed with the correct params', async function () {
539 email: 'email@example.com',
545 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 })
549 describe('When getting my information', function () {
550 it('Should fail with a non authenticated user', async function () {
551 await getMyUserInformation(server.url, 'fake_token', 401)
554 it('Should success with the correct parameters', async function () {
555 await getMyUserInformation(server.url, userAccessToken)
559 describe('When getting my video rating', function () {
560 it('Should fail with a non authenticated user', async function () {
561 await getMyUserVideoRating(server.url, 'fake_token', videoId, 401)
564 it('Should fail with an incorrect video uuid', async function () {
565 await getMyUserVideoRating(server.url, server.accessToken, 'blabla', 400)
568 it('Should fail with an unknown video', async function () {
569 await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', 404)
572 it('Should succeed with the correct parameters', async function () {
573 await getMyUserVideoRating(server.url, server.accessToken, videoId)
577 describe('When retrieving my global ratings', function () {
578 const path = '/api/v1/accounts/user1/ratings'
580 it('Should fail with a bad start pagination', async function () {
581 await checkBadStartPagination(server.url, path, userAccessToken)
584 it('Should fail with a bad count pagination', async function () {
585 await checkBadCountPagination(server.url, path, userAccessToken)
588 it('Should fail with an incorrect sort', async function () {
589 await checkBadSortPagination(server.url, path, userAccessToken)
592 it('Should fail with a unauthenticated user', async function () {
593 await makeGetRequest({ url: server.url, path, statusCodeExpected: 401 })
596 it('Should fail with a another user', async function () {
597 await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 403 })
600 it('Should fail with a bad type', async function () {
601 await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { rating: 'toto ' }, statusCodeExpected: 400 })
604 it('Should succeed with the correct params', async function () {
605 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 200 })
609 describe('When blocking/unblocking/removing user', function () {
610 it('Should fail with an incorrect id', async function () {
611 await removeUser(server.url, 'blabla', server.accessToken, 400)
612 await blockUser(server.url, 'blabla', server.accessToken, 400)
613 await unblockUser(server.url, 'blabla', server.accessToken, 400)
616 it('Should fail with the root user', async function () {
617 await removeUser(server.url, rootId, server.accessToken, 400)
618 await blockUser(server.url, rootId, server.accessToken, 400)
619 await unblockUser(server.url, rootId, server.accessToken, 400)
622 it('Should return 404 with a non existing id', async function () {
623 await removeUser(server.url, 4545454, server.accessToken, 404)
624 await blockUser(server.url, 4545454, server.accessToken, 404)
625 await unblockUser(server.url, 4545454, server.accessToken, 404)
628 it('Should fail with a non admin user', async function () {
629 await removeUser(server.url, userId, userAccessToken, 403)
630 await blockUser(server.url, userId, userAccessToken, 403)
631 await unblockUser(server.url, userId, userAccessToken, 403)
635 describe('When deleting our account', function () {
636 it('Should fail with with the root account', async function () {
637 await deleteMe(server.url, server.accessToken, 400)
641 describe('When register a new user', function () {
642 const registrationPath = path + '/register'
643 const baseCorrectParams = {
645 email: 'test3@example.com',
646 password: 'my super password'
649 it('Should fail with a too small username', async function () {
650 const fields = immutableAssign(baseCorrectParams, { username: '' })
652 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
655 it('Should fail with a too long username', async function () {
656 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
658 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
661 it('Should fail with an incorrect username', async function () {
662 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
664 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
667 it('Should fail with a missing email', async function () {
668 const fields = omit(baseCorrectParams, 'email')
670 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
673 it('Should fail with an invalid email', async function () {
674 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
676 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
679 it('Should fail with a too small password', async function () {
680 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
682 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
685 it('Should fail with a too long password', async function () {
686 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
688 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
691 it('Should fail if we register a user with the same username', async function () {
692 const fields = immutableAssign(baseCorrectParams, { username: 'root' })
694 await makePostBodyRequest({
696 path: registrationPath,
697 token: server.accessToken,
699 statusCodeExpected: 409
703 it('Should fail with a "peertube" username', async function () {
704 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
706 await makePostBodyRequest({
708 path: registrationPath,
709 token: server.accessToken,
711 statusCodeExpected: 409
715 it('Should fail if we register a user with the same email', async function () {
716 const fields = immutableAssign(baseCorrectParams, { email: 'admin' + server.internalServerNumber + '@example.com' })
718 await makePostBodyRequest({
720 path: registrationPath,
721 token: server.accessToken,
723 statusCodeExpected: 409
727 it('Should succeed with the correct params', async function () {
728 await makePostBodyRequest({
730 path: registrationPath,
731 token: server.accessToken,
732 fields: baseCorrectParams,
733 statusCodeExpected: 204
737 it('Should fail on a server with registration disabled', async function () {
740 email: 'test4@example.com',
741 password: 'my super password 4'
744 await makePostBodyRequest({
745 url: serverWithRegistrationDisabled.url,
746 path: registrationPath,
747 token: serverWithRegistrationDisabled.accessToken,
749 statusCodeExpected: 403
754 describe('When registering multiple users on a server with users limit', function () {
755 it('Should fail when after 3 registrations', async function () {
756 await registerUser(server.url, 'user42', 'super password', 403)
760 describe('When having a video quota', function () {
761 it('Should fail with a user having too many videos', async function () {
765 accessToken: server.accessToken,
769 await uploadVideo(server.url, server.accessToken, {}, 403)
772 it('Should fail with a registered user having too many videos', async function () {
777 password: 'my super password'
779 userAccessToken = await userLogin(server, user)
781 const videoAttributes = { fixture: 'video_short2.webm' }
782 await uploadVideo(server.url, userAccessToken, videoAttributes)
783 await uploadVideo(server.url, userAccessToken, videoAttributes)
784 await uploadVideo(server.url, userAccessToken, videoAttributes)
785 await uploadVideo(server.url, userAccessToken, videoAttributes)
786 await uploadVideo(server.url, userAccessToken, videoAttributes)
787 await uploadVideo(server.url, userAccessToken, videoAttributes, 403)
790 it('Should fail to import with HTTP/Torrent/magnet', async function () {
793 const baseAttributes = {
795 privacy: VideoPrivacy.PUBLIC
797 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() }))
798 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
799 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' }))
801 await waitJobs([ server ])
803 const res = await getMyVideoImports(server.url, server.accessToken)
805 expect(res.body.total).to.equal(3)
806 const videoImports: VideoImport[] = res.body.data
807 expect(videoImports).to.have.lengthOf(3)
809 for (const videoImport of videoImports) {
810 expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
811 expect(videoImport.error).not.to.be.undefined
812 expect(videoImport.error).to.contain('user video quota is exceeded')
817 describe('When having a daily video quota', function () {
818 it('Should fail with a user having too many videos', async function () {
822 accessToken: server.accessToken,
826 await uploadVideo(server.url, server.accessToken, {}, 403)
830 describe('When having an absolute and daily video quota', function () {
831 it('Should fail if exceeding total quota', async function () {
835 accessToken: server.accessToken,
837 videoQuotaDaily: 1024 * 1024 * 1024
840 await uploadVideo(server.url, server.accessToken, {}, 403)
843 it('Should fail if exceeding daily quota', async function () {
847 accessToken: server.accessToken,
848 videoQuota: 1024 * 1024 * 1024,
852 await uploadVideo(server.url, server.accessToken, {}, 403)
856 describe('When asking a password reset', function () {
857 const path = '/api/v1/users/ask-reset-password'
859 it('Should fail with a missing email', async function () {
862 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
865 it('Should fail with an invalid email', async function () {
866 const fields = { email: 'hello' }
868 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
871 it('Should success with the correct params', async function () {
872 const fields = { email: 'admin@example.com' }
874 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
878 describe('When asking for an account verification email', function () {
879 const path = '/api/v1/users/ask-send-verify-email'
881 it('Should fail with a missing email', async function () {
884 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
887 it('Should fail with an invalid email', async function () {
888 const fields = { email: 'hello' }
890 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
893 it('Should succeed with the correct params', async function () {
894 const fields = { email: 'admin@example.com' }
896 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
900 after(async function () {
901 await cleanupTests([ server, serverWithRegistrationDisabled ])