1 /* tslint:disable:no-unused-expression */
3 import { omit } from 'lodash'
5 import { join } from 'path'
6 import { UserRole, VideoImport, VideoImportState } from '../../../../shared'
9 createUser, flushTests, getMyUserInformation, getMyUserVideoRating, getUsersList, immutableAssign, killallServers, makeGetRequest,
10 makePostBodyRequest, makeUploadRequest, makePutBodyRequest, registerUser, removeUser, runServer, ServerInfo, setAccessTokensToServers,
11 updateUser, uploadVideo, userLogin, deleteMe, unblockUser, blockUser
12 } from '../../../../shared/utils'
14 checkBadCountPagination,
15 checkBadSortPagination,
16 checkBadStartPagination
17 } from '../../../../shared/utils/requests/check-api-params'
18 import { getMagnetURI, getMyVideoImports, getYoutubeVideoUrl, importVideo } from '../../../../shared/utils/videos/video-imports'
19 import { VideoPrivacy } from '../../../../shared/models/videos'
20 import { waitJobs } from '../../../../shared/utils/server/jobs'
21 import { expect } from 'chai'
22 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
24 describe('Test users API validators', function () {
25 const path = '/api/v1/users/'
29 let server: ServerInfo
30 let serverWithRegistrationDisabled: ServerInfo
31 let userAccessToken = ''
35 password: 'my super password'
38 // ---------------------------------------------------------------
40 before(async function () {
45 server = await runServer(1)
46 serverWithRegistrationDisabled = await runServer(2)
48 await setAccessTokensToServers([ server ])
50 const videoQuota = 42000000
53 accessToken: server.accessToken,
54 username: user.username,
55 password: user.password,
56 videoQuota: videoQuota
58 userAccessToken = await userLogin(server, user)
61 const res = await getMyUserInformation(server.url, server.accessToken)
62 channelId = res.body.videoChannels[ 0 ].id
66 const res = await uploadVideo(server.url, server.accessToken, {})
67 videoId = res.body.video.id
71 describe('When listing users', function () {
72 it('Should fail with a bad start pagination', async function () {
73 await checkBadStartPagination(server.url, path, server.accessToken)
76 it('Should fail with a bad count pagination', async function () {
77 await checkBadCountPagination(server.url, path, server.accessToken)
80 it('Should fail with an incorrect sort', async function () {
81 await checkBadSortPagination(server.url, path, server.accessToken)
84 it('Should fail with a non authenticated user', async function () {
85 await makeGetRequest({
88 statusCodeExpected: 401
92 it('Should fail with a non admin user', async function () {
93 await makeGetRequest({
96 token: userAccessToken,
97 statusCodeExpected: 403
102 describe('When adding a new user', function () {
103 const baseCorrectParams = {
105 email: 'test@example.com',
106 password: 'my super password',
110 adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST
113 it('Should fail with a too small username', async function () {
114 const fields = immutableAssign(baseCorrectParams, { username: '' })
116 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
119 it('Should fail with a too long username', async function () {
120 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
122 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
125 it('Should fail with a not lowercase username', async function () {
126 const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
128 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
131 it('Should fail with an incorrect username', async function () {
132 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
134 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
137 it('Should fail with a missing email', async function () {
138 const fields = omit(baseCorrectParams, 'email')
140 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
143 it('Should fail with an invalid email', async function () {
144 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
146 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
149 it('Should fail with a too small password', async function () {
150 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
152 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
155 it('Should fail with a too long password', async function () {
156 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
158 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
161 it('Should fail with invalid admin flags', async function () {
162 const fields = immutableAssign(baseCorrectParams, { adminFlags: 'toto' })
164 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
167 it('Should fail with an non authenticated user', async function () {
168 await makePostBodyRequest({
171 token: 'super token',
172 fields: baseCorrectParams,
173 statusCodeExpected: 401
177 it('Should fail if we add a user with the same username', async function () {
178 const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
180 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
183 it('Should fail if we add a user with the same email', async function () {
184 const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
186 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
189 it('Should fail without a videoQuota', async function () {
190 const fields = omit(baseCorrectParams, 'videoQuota')
192 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
195 it('Should fail without a videoQuotaDaily', async function () {
196 const fields = omit(baseCorrectParams, 'videoQuotaDaily')
198 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
201 it('Should fail with an invalid videoQuota', async function () {
202 const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
204 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
207 it('Should fail with an invalid videoQuotaDaily', async function () {
208 const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
210 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
213 it('Should fail without a user role', async function () {
214 const fields = omit(baseCorrectParams, 'role')
216 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
219 it('Should fail with an invalid user role', async function () {
220 const fields = immutableAssign(baseCorrectParams, { role: 88989 })
222 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
225 it('Should fail with a "peertube" username', async function () {
226 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
228 await makePostBodyRequest({
231 token: server.accessToken,
233 statusCodeExpected: 409
237 it('Should succeed with the correct params', async function () {
238 await makePostBodyRequest({
241 token: server.accessToken,
242 fields: baseCorrectParams,
243 statusCodeExpected: 200
247 it('Should fail with a non admin user', async function () {
250 password: 'my super password'
252 userAccessToken = await userLogin(server, user)
256 email: 'test@example.com',
257 password: 'my super password',
260 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
264 describe('When updating my account', function () {
265 it('Should fail with an invalid email attribute', async function () {
270 await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
273 it('Should fail with a too small password', async function () {
275 currentPassword: 'my super password',
279 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
282 it('Should fail with a too long password', async function () {
284 currentPassword: 'my super password',
285 password: 'super'.repeat(61)
288 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
291 it('Should fail without the current password', async function () {
293 currentPassword: 'my super password',
294 password: 'super'.repeat(61)
297 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
300 it('Should fail with an invalid current password', async function () {
302 currentPassword: 'my super password fail',
303 password: 'super'.repeat(61)
306 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 401 })
309 it('Should fail with an invalid NSFW policy attribute', async function () {
314 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
317 it('Should fail with an invalid autoPlayVideo attribute', async function () {
322 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
325 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
327 videosHistoryEnabled: -1
330 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
333 it('Should fail with an non authenticated user', async function () {
335 currentPassword: 'my super password',
336 password: 'my super password'
339 await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 })
342 it('Should fail with a too long description', async function () {
344 description: 'super'.repeat(201)
347 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
350 it('Should succeed to change password with the correct params', async function () {
352 currentPassword: 'my super password',
353 password: 'my super password',
355 autoPlayVideo: false,
356 email: 'super_email@example.com'
359 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
362 it('Should succeed without password change with the correct params', async function () {
365 autoPlayVideo: false,
366 email: 'super_email@example.com'
369 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
373 describe('When updating my avatar', function () {
374 it('Should fail without an incorrect input file', async function () {
377 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
379 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
382 it('Should fail with a big file', async function () {
385 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
387 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
390 it('Should fail with an unauthenticated user', async function () {
393 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
395 await makeUploadRequest({
397 path: path + '/me/avatar/pick',
400 statusCodeExpected: 401
404 it('Should succeed with the correct params', async function () {
407 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
409 await makeUploadRequest({
411 path: path + '/me/avatar/pick',
412 token: server.accessToken,
415 statusCodeExpected: 200
420 describe('When getting a user', function () {
421 before(async function () {
422 const res = await getUsersList(server.url, server.accessToken)
424 userId = res.body.data[1].id
427 it('Should fail with an non authenticated user', async function () {
428 await makeGetRequest({ url: server.url, path: path + userId, token: 'super token', statusCodeExpected: 401 })
431 it('Should fail with a non admin user', async function () {
432 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 403 })
435 it('Should succeed with the correct params', async function () {
436 await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: 200 })
440 describe('When updating a user', function () {
442 before(async function () {
443 const res = await getUsersList(server.url, server.accessToken)
445 userId = res.body.data[1].id
446 rootId = res.body.data[2].id
449 it('Should fail with an invalid email attribute', async function () {
454 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
457 it('Should fail with an invalid emailVerified attribute', async function () {
462 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
465 it('Should fail with an invalid videoQuota attribute', async function () {
470 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
473 it('Should fail with an invalid user role attribute', async function () {
478 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
481 it('Should fail with a too small password', async function () {
483 currentPassword: 'my super password',
487 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
490 it('Should fail with a too long password', async function () {
492 currentPassword: 'my super password',
493 password: 'super'.repeat(61)
496 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
499 it('Should fail with an non authenticated user', async function () {
504 await makePutBodyRequest({ url: server.url, path: path + userId, token: 'super token', fields, statusCodeExpected: 401 })
507 it('Should fail when updating root role', async function () {
509 role: UserRole.MODERATOR
512 await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
515 it('Should fail with invalid admin flags', async function () {
516 const fields = { adminFlags: 'toto' }
518 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
521 it('Should succeed with the correct params', async function () {
523 email: 'email@example.com',
529 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 })
533 describe('When getting my information', function () {
534 it('Should fail with a non authenticated user', async function () {
535 await getMyUserInformation(server.url, 'fake_token', 401)
538 it('Should success with the correct parameters', async function () {
539 await getMyUserInformation(server.url, userAccessToken)
543 describe('When getting my video rating', function () {
544 it('Should fail with a non authenticated user', async function () {
545 await getMyUserVideoRating(server.url, 'fake_token', videoId, 401)
548 it('Should fail with an incorrect video uuid', async function () {
549 await getMyUserVideoRating(server.url, server.accessToken, 'blabla', 400)
552 it('Should fail with an unknown video', async function () {
553 await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', 404)
556 it('Should succeed with the correct parameters', async function () {
557 await getMyUserVideoRating(server.url, server.accessToken, videoId)
561 describe('When retrieving my global ratings', function () {
562 const path = '/api/v1/accounts/user1/ratings'
564 it('Should fail with a bad start pagination', async function () {
565 await checkBadStartPagination(server.url, path, userAccessToken)
568 it('Should fail with a bad count pagination', async function () {
569 await checkBadCountPagination(server.url, path, userAccessToken)
572 it('Should fail with an incorrect sort', async function () {
573 await checkBadSortPagination(server.url, path, userAccessToken)
576 it('Should fail with a unauthenticated user', async function () {
577 await makeGetRequest({ url: server.url, path, statusCodeExpected: 401 })
580 it('Should fail with a another user', async function () {
581 await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 403 })
584 it('Should fail with a bad type', async function () {
585 await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { rating: 'toto ' }, statusCodeExpected: 400 })
588 it('Should succeed with the correct params', async function () {
589 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 200 })
593 describe('When blocking/unblocking/removing user', function () {
594 it('Should fail with an incorrect id', async function () {
595 await removeUser(server.url, 'blabla', server.accessToken, 400)
596 await blockUser(server.url, 'blabla', server.accessToken, 400)
597 await unblockUser(server.url, 'blabla', server.accessToken, 400)
600 it('Should fail with the root user', async function () {
601 await removeUser(server.url, rootId, server.accessToken, 400)
602 await blockUser(server.url, rootId, server.accessToken, 400)
603 await unblockUser(server.url, rootId, server.accessToken, 400)
606 it('Should return 404 with a non existing id', async function () {
607 await removeUser(server.url, 4545454, server.accessToken, 404)
608 await blockUser(server.url, 4545454, server.accessToken, 404)
609 await unblockUser(server.url, 4545454, server.accessToken, 404)
612 it('Should fail with a non admin user', async function () {
613 await removeUser(server.url, userId, userAccessToken, 403)
614 await blockUser(server.url, userId, userAccessToken, 403)
615 await unblockUser(server.url, userId, userAccessToken, 403)
619 describe('When deleting our account', function () {
620 it('Should fail with with the root account', async function () {
621 await deleteMe(server.url, server.accessToken, 400)
625 describe('When register a new user', function () {
626 const registrationPath = path + '/register'
627 const baseCorrectParams = {
629 email: 'test3@example.com',
630 password: 'my super password'
633 it('Should fail with a too small username', async function () {
634 const fields = immutableAssign(baseCorrectParams, { username: '' })
636 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
639 it('Should fail with a too long username', async function () {
640 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
642 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
645 it('Should fail with an incorrect username', async function () {
646 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
648 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
651 it('Should fail with a missing email', async function () {
652 const fields = omit(baseCorrectParams, 'email')
654 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
657 it('Should fail with an invalid email', async function () {
658 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
660 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
663 it('Should fail with a too small password', async function () {
664 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
666 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
669 it('Should fail with a too long password', async function () {
670 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
672 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
675 it('Should fail if we register a user with the same username', async function () {
676 const fields = immutableAssign(baseCorrectParams, { username: 'root' })
678 await makePostBodyRequest({
680 path: registrationPath,
681 token: server.accessToken,
683 statusCodeExpected: 409
687 it('Should fail with a "peertube" username', async function () {
688 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
690 await makePostBodyRequest({
692 path: registrationPath,
693 token: server.accessToken,
695 statusCodeExpected: 409
699 it('Should fail if we register a user with the same email', async function () {
700 const fields = immutableAssign(baseCorrectParams, { email: 'admin1@example.com' })
702 await makePostBodyRequest({
704 path: registrationPath,
705 token: server.accessToken,
707 statusCodeExpected: 409
711 it('Should succeed with the correct params', async function () {
712 await makePostBodyRequest({
714 path: registrationPath,
715 token: server.accessToken,
716 fields: baseCorrectParams,
717 statusCodeExpected: 204
721 it('Should fail on a server with registration disabled', async function () {
724 email: 'test4@example.com',
725 password: 'my super password 4'
728 await makePostBodyRequest({
729 url: serverWithRegistrationDisabled.url,
730 path: registrationPath,
731 token: serverWithRegistrationDisabled.accessToken,
733 statusCodeExpected: 403
738 describe('When registering multiple users on a server with users limit', function () {
739 it('Should fail when after 3 registrations', async function () {
740 await registerUser(server.url, 'user42', 'super password', 403)
744 describe('When having a video quota', function () {
745 it('Should fail with a user having too many videos', async function () {
749 accessToken: server.accessToken,
753 await uploadVideo(server.url, server.accessToken, {}, 403)
756 it('Should fail with a registered user having too many videos', async function () {
761 password: 'my super password'
763 userAccessToken = await userLogin(server, user)
765 const videoAttributes = { fixture: 'video_short2.webm' }
766 await uploadVideo(server.url, userAccessToken, videoAttributes)
767 await uploadVideo(server.url, userAccessToken, videoAttributes)
768 await uploadVideo(server.url, userAccessToken, videoAttributes)
769 await uploadVideo(server.url, userAccessToken, videoAttributes)
770 await uploadVideo(server.url, userAccessToken, videoAttributes)
771 await uploadVideo(server.url, userAccessToken, videoAttributes, 403)
774 it('Should fail to import with HTTP/Torrent/magnet', async function () {
777 const baseAttributes = {
779 privacy: VideoPrivacy.PUBLIC
781 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() }))
782 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
783 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' }))
785 await waitJobs([ server ])
787 const res = await getMyVideoImports(server.url, server.accessToken)
789 expect(res.body.total).to.equal(3)
790 const videoImports: VideoImport[] = res.body.data
791 expect(videoImports).to.have.lengthOf(3)
793 for (const videoImport of videoImports) {
794 expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
795 expect(videoImport.error).not.to.be.undefined
796 expect(videoImport.error).to.contain('user video quota is exceeded')
801 describe('When having a daily video quota', function () {
802 it('Should fail with a user having too many videos', async function () {
806 accessToken: server.accessToken,
810 await uploadVideo(server.url, server.accessToken, {}, 403)
814 describe('When having an absolute and daily video quota', function () {
815 it('Should fail if exceeding total quota', async function () {
819 accessToken: server.accessToken,
821 videoQuotaDaily: 1024 * 1024 * 1024
824 await uploadVideo(server.url, server.accessToken, {}, 403)
827 it('Should fail if exceeding daily quota', async function () {
831 accessToken: server.accessToken,
832 videoQuota: 1024 * 1024 * 1024,
836 await uploadVideo(server.url, server.accessToken, {}, 403)
840 describe('When asking a password reset', function () {
841 const path = '/api/v1/users/ask-reset-password'
843 it('Should fail with a missing email', async function () {
846 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
849 it('Should fail with an invalid email', async function () {
850 const fields = { email: 'hello' }
852 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
855 it('Should success with the correct params', async function () {
856 const fields = { email: 'admin@example.com' }
858 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
862 describe('When asking for an account verification email', function () {
863 const path = '/api/v1/users/ask-send-verify-email'
865 it('Should fail with a missing email', async function () {
868 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
871 it('Should fail with an invalid email', async function () {
872 const fields = { email: 'hello' }
874 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
877 it('Should succeed with the correct params', async function () {
878 const fields = { email: 'admin@example.com' }
880 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
884 after(async function () {
885 killallServers([ server, serverWithRegistrationDisabled ])
887 // Keep the logs if the test failed