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'
23 describe('Test users API validators', function () {
24 const path = '/api/v1/users/'
28 let server: ServerInfo
29 let serverWithRegistrationDisabled: ServerInfo
30 let userAccessToken = ''
34 password: 'my super password'
37 // ---------------------------------------------------------------
39 before(async function () {
44 server = await runServer(1)
45 serverWithRegistrationDisabled = await runServer(2)
47 await setAccessTokensToServers([ server ])
49 const videoQuota = 42000000
50 await createUser(server.url, server.accessToken, user.username, user.password, videoQuota)
51 userAccessToken = await userLogin(server, user)
54 const res = await getMyUserInformation(server.url, server.accessToken)
55 channelId = res.body.videoChannels[ 0 ].id
59 const res = await uploadVideo(server.url, server.accessToken, {})
60 videoId = res.body.video.id
64 describe('When listing users', function () {
65 it('Should fail with a bad start pagination', async function () {
66 await checkBadStartPagination(server.url, path, server.accessToken)
69 it('Should fail with a bad count pagination', async function () {
70 await checkBadCountPagination(server.url, path, server.accessToken)
73 it('Should fail with an incorrect sort', async function () {
74 await checkBadSortPagination(server.url, path, server.accessToken)
77 it('Should fail with a non authenticated user', async function () {
78 await makeGetRequest({
81 statusCodeExpected: 401
85 it('Should fail with a non admin user', async function () {
86 await makeGetRequest({
89 token: userAccessToken,
90 statusCodeExpected: 403
95 describe('When adding a new user', function () {
96 const baseCorrectParams = {
98 email: 'test@example.com',
99 password: 'my super password',
105 it('Should fail with a too small username', async function () {
106 const fields = immutableAssign(baseCorrectParams, { username: '' })
108 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
111 it('Should fail with a too long username', async function () {
112 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
114 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
117 it('Should fail with a not lowercase username', async function () {
118 const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
120 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
123 it('Should fail with an incorrect username', async function () {
124 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
126 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
129 it('Should fail with a missing email', async function () {
130 const fields = omit(baseCorrectParams, 'email')
132 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
135 it('Should fail with an invalid email', async function () {
136 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
138 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
141 it('Should fail with a too small password', async function () {
142 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
144 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
147 it('Should fail with a too long password', async function () {
148 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
150 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
153 it('Should fail with an non authenticated user', async function () {
154 await makePostBodyRequest({
157 token: 'super token',
158 fields: baseCorrectParams,
159 statusCodeExpected: 401
163 it('Should fail if we add a user with the same username', async function () {
164 const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
166 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
169 it('Should fail if we add a user with the same email', async function () {
170 const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
172 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
175 it('Should fail without a videoQuota', async function () {
176 const fields = omit(baseCorrectParams, 'videoQuota')
178 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
181 it('Should fail without a videoQuotaDaily', async function () {
182 const fields = omit(baseCorrectParams, 'videoQuotaDaily')
184 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
187 it('Should fail with an invalid videoQuota', async function () {
188 const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
190 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
193 it('Should fail with an invalid videoQuotaDaily', async function () {
194 const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
196 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
199 it('Should fail without a user role', async function () {
200 const fields = omit(baseCorrectParams, 'role')
202 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
205 it('Should fail with an invalid user role', async function () {
206 const fields = immutableAssign(baseCorrectParams, { role: 88989 })
208 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
211 it('Should fail with a "peertube" username', async function () {
212 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
214 await makePostBodyRequest({
217 token: server.accessToken,
219 statusCodeExpected: 409
223 it('Should succeed with the correct params', async function () {
224 await makePostBodyRequest({
227 token: server.accessToken,
228 fields: baseCorrectParams,
229 statusCodeExpected: 200
233 it('Should fail with a non admin user', async function () {
236 password: 'my super password'
238 userAccessToken = await userLogin(server, user)
242 email: 'test@example.com',
243 password: 'my super password',
246 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
250 describe('When updating my account', function () {
251 it('Should fail with an invalid email attribute', async function () {
256 await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
259 it('Should fail with a too small password', async function () {
261 currentPassword: 'my super password',
265 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
268 it('Should fail with a too long password', async function () {
270 currentPassword: 'my super password',
271 password: 'super'.repeat(61)
274 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
277 it('Should fail without the current password', async function () {
279 currentPassword: 'my super password',
280 password: 'super'.repeat(61)
283 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
286 it('Should fail with an invalid current password', async function () {
288 currentPassword: 'my super password fail',
289 password: 'super'.repeat(61)
292 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 401 })
295 it('Should fail with an invalid NSFW policy attribute', async function () {
300 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
303 it('Should fail with an invalid autoPlayVideo attribute', async function () {
308 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
311 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
313 videosHistoryEnabled: -1
316 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
319 it('Should fail with an non authenticated user', async function () {
321 currentPassword: 'my super password',
322 password: 'my super password'
325 await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 })
328 it('Should fail with a too long description', async function () {
330 description: 'super'.repeat(201)
333 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
336 it('Should succeed to change password with the correct params', async function () {
338 currentPassword: 'my super password',
339 password: 'my super password',
341 autoPlayVideo: false,
342 email: 'super_email@example.com'
345 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
348 it('Should succeed without password change with the correct params', async function () {
351 autoPlayVideo: false,
352 email: 'super_email@example.com'
355 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
359 describe('When updating my avatar', function () {
360 it('Should fail without an incorrect input file', async function () {
363 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
365 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
368 it('Should fail with a big file', async function () {
371 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
373 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
376 it('Should fail with an unauthenticated user', async function () {
379 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
381 await makeUploadRequest({
383 path: path + '/me/avatar/pick',
386 statusCodeExpected: 401
390 it('Should succeed with the correct params', async function () {
393 'avatarfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png')
395 await makeUploadRequest({
397 path: path + '/me/avatar/pick',
398 token: server.accessToken,
401 statusCodeExpected: 200
406 describe('When getting a user', function () {
407 before(async function () {
408 const res = await getUsersList(server.url, server.accessToken)
410 userId = res.body.data[1].id
413 it('Should fail with an non authenticated user', async function () {
414 await makeGetRequest({ url: server.url, path: path + userId, token: 'super token', statusCodeExpected: 401 })
417 it('Should fail with a non admin user', async function () {
418 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 403 })
421 it('Should succeed with the correct params', async function () {
422 await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: 200 })
426 describe('When updating a user', function () {
428 before(async function () {
429 const res = await getUsersList(server.url, server.accessToken)
431 userId = res.body.data[1].id
432 rootId = res.body.data[2].id
435 it('Should fail with an invalid email attribute', async function () {
440 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
443 it('Should fail with an invalid emailVerified attribute', async function () {
448 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
451 it('Should fail with an invalid videoQuota attribute', async function () {
456 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
459 it('Should fail with an invalid user role attribute', async function () {
464 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
467 it('Should fail with a too small password', async function () {
469 currentPassword: 'my super password',
473 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
476 it('Should fail with a too long password', async function () {
478 currentPassword: 'my super password',
479 password: 'super'.repeat(61)
482 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
485 it('Should fail with an non authenticated user', async function () {
490 await makePutBodyRequest({ url: server.url, path: path + userId, token: 'super token', fields, statusCodeExpected: 401 })
493 it('Should fail when updating root role', async function () {
495 role: UserRole.MODERATOR
498 await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
501 it('Should succeed with the correct params', async function () {
503 email: 'email@example.com',
509 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 })
513 describe('When getting my information', function () {
514 it('Should fail with a non authenticated user', async function () {
515 await getMyUserInformation(server.url, 'fake_token', 401)
518 it('Should success with the correct parameters', async function () {
519 await getMyUserInformation(server.url, userAccessToken)
523 describe('When getting my video rating', function () {
524 it('Should fail with a non authenticated user', async function () {
525 await getMyUserVideoRating(server.url, 'fake_token', videoId, 401)
528 it('Should fail with an incorrect video uuid', async function () {
529 await getMyUserVideoRating(server.url, server.accessToken, 'blabla', 400)
532 it('Should fail with an unknown video', async function () {
533 await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', 404)
536 it('Should succeed with the correct parameters', async function () {
537 await getMyUserVideoRating(server.url, server.accessToken, videoId)
541 describe('When retrieving my global ratings', function () {
542 const path = '/api/v1/accounts/user1/ratings'
544 it('Should fail with a bad start pagination', async function () {
545 await checkBadStartPagination(server.url, path, userAccessToken)
548 it('Should fail with a bad count pagination', async function () {
549 await checkBadCountPagination(server.url, path, userAccessToken)
552 it('Should fail with an incorrect sort', async function () {
553 await checkBadSortPagination(server.url, path, userAccessToken)
556 it('Should fail with a unauthenticated user', async function () {
557 await makeGetRequest({ url: server.url, path, statusCodeExpected: 401 })
560 it('Should fail with a another user', async function () {
561 await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 403 })
564 it('Should fail with a bad type', async function () {
565 await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { rating: 'toto ' }, statusCodeExpected: 400 })
568 it('Should succeed with the correct params', async function () {
569 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 200 })
573 describe('When blocking/unblocking/removing user', function () {
574 it('Should fail with an incorrect id', async function () {
575 await removeUser(server.url, 'blabla', server.accessToken, 400)
576 await blockUser(server.url, 'blabla', server.accessToken, 400)
577 await unblockUser(server.url, 'blabla', server.accessToken, 400)
580 it('Should fail with the root user', async function () {
581 await removeUser(server.url, rootId, server.accessToken, 400)
582 await blockUser(server.url, rootId, server.accessToken, 400)
583 await unblockUser(server.url, rootId, server.accessToken, 400)
586 it('Should return 404 with a non existing id', async function () {
587 await removeUser(server.url, 4545454, server.accessToken, 404)
588 await blockUser(server.url, 4545454, server.accessToken, 404)
589 await unblockUser(server.url, 4545454, server.accessToken, 404)
592 it('Should fail with a non admin user', async function () {
593 await removeUser(server.url, userId, userAccessToken, 403)
594 await blockUser(server.url, userId, userAccessToken, 403)
595 await unblockUser(server.url, userId, userAccessToken, 403)
599 describe('When deleting our account', function () {
600 it('Should fail with with the root account', async function () {
601 await deleteMe(server.url, server.accessToken, 400)
605 describe('When register a new user', function () {
606 const registrationPath = path + '/register'
607 const baseCorrectParams = {
609 email: 'test3@example.com',
610 password: 'my super password'
613 it('Should fail with a too small username', async function () {
614 const fields = immutableAssign(baseCorrectParams, { username: '' })
616 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
619 it('Should fail with a too long username', async function () {
620 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
622 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
625 it('Should fail with an incorrect username', async function () {
626 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
628 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
631 it('Should fail with a missing email', async function () {
632 const fields = omit(baseCorrectParams, 'email')
634 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
637 it('Should fail with an invalid email', async function () {
638 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
640 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
643 it('Should fail with a too small password', async function () {
644 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
646 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
649 it('Should fail with a too long password', async function () {
650 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
652 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
655 it('Should fail if we register a user with the same username', async function () {
656 const fields = immutableAssign(baseCorrectParams, { username: 'root' })
658 await makePostBodyRequest({
660 path: registrationPath,
661 token: server.accessToken,
663 statusCodeExpected: 409
667 it('Should fail with a "peertube" username', async function () {
668 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
670 await makePostBodyRequest({
672 path: registrationPath,
673 token: server.accessToken,
675 statusCodeExpected: 409
679 it('Should fail if we register a user with the same email', async function () {
680 const fields = immutableAssign(baseCorrectParams, { email: 'admin1@example.com' })
682 await makePostBodyRequest({
684 path: registrationPath,
685 token: server.accessToken,
687 statusCodeExpected: 409
691 it('Should succeed with the correct params', async function () {
692 await makePostBodyRequest({
694 path: registrationPath,
695 token: server.accessToken,
696 fields: baseCorrectParams,
697 statusCodeExpected: 204
701 it('Should fail on a server with registration disabled', async function () {
704 email: 'test4@example.com',
705 password: 'my super password 4'
708 await makePostBodyRequest({
709 url: serverWithRegistrationDisabled.url,
710 path: registrationPath,
711 token: serverWithRegistrationDisabled.accessToken,
713 statusCodeExpected: 403
718 describe('When registering multiple users on a server with users limit', function () {
719 it('Should fail when after 3 registrations', async function () {
720 await registerUser(server.url, 'user42', 'super password', 403)
724 describe('When having a video quota', function () {
725 it('Should fail with a user having too many videos', async function () {
729 accessToken: server.accessToken,
733 await uploadVideo(server.url, server.accessToken, {}, 403)
736 it('Should fail with a registered user having too many videos', async function () {
741 password: 'my super password'
743 userAccessToken = await userLogin(server, user)
745 const videoAttributes = { fixture: 'video_short2.webm' }
746 await uploadVideo(server.url, userAccessToken, videoAttributes)
747 await uploadVideo(server.url, userAccessToken, videoAttributes)
748 await uploadVideo(server.url, userAccessToken, videoAttributes)
749 await uploadVideo(server.url, userAccessToken, videoAttributes)
750 await uploadVideo(server.url, userAccessToken, videoAttributes)
751 await uploadVideo(server.url, userAccessToken, videoAttributes, 403)
754 it('Should fail to import with HTTP/Torrent/magnet', async function () {
757 const baseAttributes = {
759 privacy: VideoPrivacy.PUBLIC
761 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() }))
762 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
763 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' }))
765 await waitJobs([ server ])
767 const res = await getMyVideoImports(server.url, server.accessToken)
769 expect(res.body.total).to.equal(3)
770 const videoImports: VideoImport[] = res.body.data
771 expect(videoImports).to.have.lengthOf(3)
773 for (const videoImport of videoImports) {
774 expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
775 expect(videoImport.error).not.to.be.undefined
776 expect(videoImport.error).to.contain('user video quota is exceeded')
781 describe('When having a daily video quota', function () {
782 it('Should fail with a user having too many videos', async function () {
786 accessToken: server.accessToken,
790 await uploadVideo(server.url, server.accessToken, {}, 403)
794 describe('When having an absolute and daily video quota', function () {
795 it('Should fail if exceeding total quota', async function () {
799 accessToken: server.accessToken,
801 videoQuotaDaily: 1024 * 1024 * 1024
804 await uploadVideo(server.url, server.accessToken, {}, 403)
807 it('Should fail if exceeding daily quota', async function () {
811 accessToken: server.accessToken,
812 videoQuota: 1024 * 1024 * 1024,
816 await uploadVideo(server.url, server.accessToken, {}, 403)
820 describe('When asking a password reset', function () {
821 const path = '/api/v1/users/ask-reset-password'
823 it('Should fail with a missing email', async function () {
826 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
829 it('Should fail with an invalid email', async function () {
830 const fields = { email: 'hello' }
832 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
835 it('Should success with the correct params', async function () {
836 const fields = { email: 'admin@example.com' }
838 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
842 describe('When asking for an account verification email', function () {
843 const path = '/api/v1/users/ask-send-verify-email'
845 it('Should fail with a missing email', async function () {
848 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
851 it('Should fail with an invalid email', async function () {
852 const fields = { email: 'hello' }
854 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
857 it('Should succeed with the correct params', async function () {
858 const fields = { email: 'admin@example.com' }
860 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
864 after(async function () {
865 killallServers([ server, serverWithRegistrationDisabled ])
867 // Keep the logs if the test failed