diff options
author | Josh Morel <morel.josh@hotmail.com> | 2018-08-31 03:18:19 -0400 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-08-31 09:18:19 +0200 |
commit | d9eaee3939bf2e93e5d775d32bce77842201faba (patch) | |
tree | c115acb3611986b98f51b3addf29ebe66f63ee7f /server/tests | |
parent | 04291e1ba44032165388758e993d385a10c1c5a1 (diff) | |
download | PeerTube-d9eaee3939bf2e93e5d775d32bce77842201faba.tar.gz PeerTube-d9eaee3939bf2e93e5d775d32bce77842201faba.tar.zst PeerTube-d9eaee3939bf2e93e5d775d32bce77842201faba.zip |
add user account email verificiation (#977)
* add user account email verificiation
includes server and client code to:
* enable verificationRequired via custom config
* send verification email with registration
* ask for verification email
* verify via email
* prevent login if not verified and required
* conditional client links to ask for new verification email
* allow login for verified=null
these are users created when verification not required
should still be able to login when verification is enabled
* refactor email verifcation pr
* change naming from verified to emailVerified
* change naming from askVerifyEmail to askSendVerifyEmail
* undo unrelated automatic prettier formatting on api/config
* use redirectService for home
* remove redundant success notification on email verified
* revert test.yaml smpt host
Diffstat (limited to 'server/tests')
-rw-r--r-- | server/tests/api/check-params/config.ts | 3 | ||||
-rw-r--r-- | server/tests/api/check-params/users.ts | 22 | ||||
-rw-r--r-- | server/tests/api/server/config.ts | 5 | ||||
-rw-r--r-- | server/tests/api/server/email.ts | 42 | ||||
-rw-r--r-- | server/tests/api/users/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/users/users-verification.ts | 133 | ||||
-rw-r--r-- | server/tests/api/users/users.ts | 2 | ||||
-rw-r--r-- | server/tests/utils/server/config.ts | 3 | ||||
-rw-r--r-- | server/tests/utils/users/users.ts | 26 |
9 files changed, 231 insertions, 6 deletions
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts index ecfb76d47..d807f910b 100644 --- a/server/tests/api/check-params/config.ts +++ b/server/tests/api/check-params/config.ts | |||
@@ -42,7 +42,8 @@ describe('Test config API validators', function () { | |||
42 | }, | 42 | }, |
43 | signup: { | 43 | signup: { |
44 | enabled: false, | 44 | enabled: false, |
45 | limit: 5 | 45 | limit: 5, |
46 | requiresEmailVerification: false | ||
46 | }, | 47 | }, |
47 | admin: { | 48 | admin: { |
48 | email: 'superadmin1@example.com' | 49 | email: 'superadmin1@example.com' |
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index 8b2ed1b04..95903c8a5 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts | |||
@@ -737,6 +737,28 @@ describe('Test users API validators', function () { | |||
737 | }) | 737 | }) |
738 | }) | 738 | }) |
739 | 739 | ||
740 | describe('When asking for an account verification email', function () { | ||
741 | const path = '/api/v1/users/ask-send-verify-email' | ||
742 | |||
743 | it('Should fail with a missing email', async function () { | ||
744 | const fields = {} | ||
745 | |||
746 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
747 | }) | ||
748 | |||
749 | it('Should fail with an invalid email', async function () { | ||
750 | const fields = { email: 'hello' } | ||
751 | |||
752 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
753 | }) | ||
754 | |||
755 | it('Should succeed with the correct params', async function () { | ||
756 | const fields = { email: 'admin@example.com' } | ||
757 | |||
758 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 }) | ||
759 | }) | ||
760 | }) | ||
761 | |||
740 | after(async function () { | 762 | after(async function () { |
741 | killallServers([ server, serverWithRegistrationDisabled ]) | 763 | killallServers([ server, serverWithRegistrationDisabled ]) |
742 | 764 | ||
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index ece4118a6..facd1688d 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -35,6 +35,7 @@ function checkInitialConfig (data: CustomConfig) { | |||
35 | expect(data.cache.captions.size).to.equal(1) | 35 | expect(data.cache.captions.size).to.equal(1) |
36 | expect(data.signup.enabled).to.be.true | 36 | expect(data.signup.enabled).to.be.true |
37 | expect(data.signup.limit).to.equal(4) | 37 | expect(data.signup.limit).to.equal(4) |
38 | expect(data.signup.requiresEmailVerification).to.be.false | ||
38 | expect(data.admin.email).to.equal('admin1@example.com') | 39 | expect(data.admin.email).to.equal('admin1@example.com') |
39 | expect(data.user.videoQuota).to.equal(5242880) | 40 | expect(data.user.videoQuota).to.equal(5242880) |
40 | expect(data.user.videoQuotaDaily).to.equal(-1) | 41 | expect(data.user.videoQuotaDaily).to.equal(-1) |
@@ -64,6 +65,7 @@ function checkUpdatedConfig (data: CustomConfig) { | |||
64 | expect(data.cache.captions.size).to.equal(3) | 65 | expect(data.cache.captions.size).to.equal(3) |
65 | expect(data.signup.enabled).to.be.false | 66 | expect(data.signup.enabled).to.be.false |
66 | expect(data.signup.limit).to.equal(5) | 67 | expect(data.signup.limit).to.equal(5) |
68 | expect(data.signup.requiresEmailVerification).to.be.true | ||
67 | expect(data.admin.email).to.equal('superadmin1@example.com') | 69 | expect(data.admin.email).to.equal('superadmin1@example.com') |
68 | expect(data.user.videoQuota).to.equal(5242881) | 70 | expect(data.user.videoQuota).to.equal(5242881) |
69 | expect(data.user.videoQuotaDaily).to.equal(318742) | 71 | expect(data.user.videoQuotaDaily).to.equal(318742) |
@@ -148,7 +150,8 @@ describe('Test config', function () { | |||
148 | }, | 150 | }, |
149 | signup: { | 151 | signup: { |
150 | enabled: false, | 152 | enabled: false, |
151 | limit: 5 | 153 | limit: 5, |
154 | requiresEmailVerification: true | ||
152 | }, | 155 | }, |
153 | admin: { | 156 | admin: { |
154 | email: 'superadmin1@example.com' | 157 | email: 'superadmin1@example.com' |
diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts index db937f288..713a27143 100644 --- a/server/tests/api/server/email.ts +++ b/server/tests/api/server/email.ts | |||
@@ -5,6 +5,7 @@ import 'mocha' | |||
5 | import { | 5 | import { |
6 | addVideoToBlacklist, | 6 | addVideoToBlacklist, |
7 | askResetPassword, | 7 | askResetPassword, |
8 | askSendVerifyEmail, | ||
8 | blockUser, | 9 | blockUser, |
9 | createUser, removeVideoFromBlacklist, | 10 | createUser, removeVideoFromBlacklist, |
10 | reportVideoAbuse, | 11 | reportVideoAbuse, |
@@ -12,7 +13,8 @@ import { | |||
12 | runServer, | 13 | runServer, |
13 | unblockUser, | 14 | unblockUser, |
14 | uploadVideo, | 15 | uploadVideo, |
15 | userLogin | 16 | userLogin, |
17 | verifyEmail | ||
16 | } from '../../utils' | 18 | } from '../../utils' |
17 | import { flushTests, killallServers, ServerInfo, setAccessTokensToServers } from '../../utils/index' | 19 | import { flushTests, killallServers, ServerInfo, setAccessTokensToServers } from '../../utils/index' |
18 | import { mockSmtpServer } from '../../utils/miscs/email' | 20 | import { mockSmtpServer } from '../../utils/miscs/email' |
@@ -207,6 +209,44 @@ describe('Test emails', function () { | |||
207 | }) | 209 | }) |
208 | }) | 210 | }) |
209 | 211 | ||
212 | describe('When verifying a user email', function () { | ||
213 | |||
214 | it('Should ask to send the verification email', async function () { | ||
215 | this.timeout(10000) | ||
216 | |||
217 | await askSendVerifyEmail(server.url, 'user_1@example.com') | ||
218 | |||
219 | await waitJobs(server) | ||
220 | expect(emails).to.have.lengthOf(7) | ||
221 | |||
222 | const email = emails[6] | ||
223 | |||
224 | expect(email['from'][0]['address']).equal('test-admin@localhost') | ||
225 | expect(email['to'][0]['address']).equal('user_1@example.com') | ||
226 | expect(email['subject']).contains('Verify') | ||
227 | |||
228 | const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text']) | ||
229 | expect(verificationStringMatches).not.to.be.null | ||
230 | |||
231 | verificationString = verificationStringMatches[1] | ||
232 | expect(verificationString).to.not.be.undefined | ||
233 | expect(verificationString).to.have.length.above(2) | ||
234 | |||
235 | const userIdMatches = /userId=([0-9]+)/.exec(email['text']) | ||
236 | expect(userIdMatches).not.to.be.null | ||
237 | |||
238 | userId = parseInt(userIdMatches[1], 10) | ||
239 | }) | ||
240 | |||
241 | it('Should not verify the email with an invalid verification string', async function () { | ||
242 | await verifyEmail(server.url, userId, verificationString + 'b', 403) | ||
243 | }) | ||
244 | |||
245 | it('Should verify the email', async function () { | ||
246 | await verifyEmail(server.url, userId, verificationString) | ||
247 | }) | ||
248 | }) | ||
249 | |||
210 | after(async function () { | 250 | after(async function () { |
211 | killallServers([ server ]) | 251 | killallServers([ server ]) |
212 | }) | 252 | }) |
diff --git a/server/tests/api/users/index.ts b/server/tests/api/users/index.ts index 4ce87fb91..21d75da3e 100644 --- a/server/tests/api/users/index.ts +++ b/server/tests/api/users/index.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import './user-subscriptions' | 1 | import './user-subscriptions' |
2 | import './users' | 2 | import './users' |
3 | import './users-verification' | ||
3 | import './users-multiple-servers' | 4 | import './users-multiple-servers' |
diff --git a/server/tests/api/users/users-verification.ts b/server/tests/api/users/users-verification.ts new file mode 100644 index 000000000..fa5f5e371 --- /dev/null +++ b/server/tests/api/users/users-verification.ts | |||
@@ -0,0 +1,133 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | registerUser, flushTests, getUserInformation, getMyUserInformation, killallServers, | ||
7 | userLogin, login, runServer, ServerInfo, verifyEmail, updateCustomSubConfig | ||
8 | } from '../../utils' | ||
9 | import { setAccessTokensToServers } from '../../utils/users/login' | ||
10 | import { mockSmtpServer } from '../../utils/miscs/email' | ||
11 | import { waitJobs } from '../../utils/server/jobs' | ||
12 | |||
13 | const expect = chai.expect | ||
14 | |||
15 | describe('Test users account verification', function () { | ||
16 | let server: ServerInfo | ||
17 | let userId: number | ||
18 | let verificationString: string | ||
19 | let expectedEmailsLength = 0 | ||
20 | const user1 = { | ||
21 | username: 'user_1', | ||
22 | password: 'super password' | ||
23 | } | ||
24 | const user2 = { | ||
25 | username: 'user_2', | ||
26 | password: 'super password' | ||
27 | } | ||
28 | const emails: object[] = [] | ||
29 | |||
30 | before(async function () { | ||
31 | this.timeout(30000) | ||
32 | |||
33 | await mockSmtpServer(emails) | ||
34 | |||
35 | await flushTests() | ||
36 | |||
37 | const overrideConfig = { | ||
38 | smtp: { | ||
39 | hostname: 'localhost' | ||
40 | } | ||
41 | } | ||
42 | server = await runServer(1, overrideConfig) | ||
43 | |||
44 | await setAccessTokensToServers([ server ]) | ||
45 | }) | ||
46 | |||
47 | it('Should register user and send verification email if verification required', async function () { | ||
48 | this.timeout(5000) | ||
49 | await updateCustomSubConfig(server.url, server.accessToken, { | ||
50 | signup: { | ||
51 | enabled: true, | ||
52 | requiresEmailVerification: true, | ||
53 | limit: 10 | ||
54 | } | ||
55 | }) | ||
56 | |||
57 | await registerUser(server.url, user1.username, user1.password) | ||
58 | |||
59 | await waitJobs(server) | ||
60 | expectedEmailsLength++ | ||
61 | expect(emails).to.have.lengthOf(expectedEmailsLength) | ||
62 | |||
63 | const email = emails[expectedEmailsLength - 1] | ||
64 | |||
65 | const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text']) | ||
66 | expect(verificationStringMatches).not.to.be.null | ||
67 | |||
68 | verificationString = verificationStringMatches[1] | ||
69 | expect(verificationString).to.have.length.above(2) | ||
70 | |||
71 | const userIdMatches = /userId=([0-9]+)/.exec(email['text']) | ||
72 | expect(userIdMatches).not.to.be.null | ||
73 | |||
74 | userId = parseInt(userIdMatches[1], 10) | ||
75 | |||
76 | const resUserInfo = await getUserInformation(server.url, server.accessToken, userId) | ||
77 | expect(resUserInfo.body.emailVerified).to.be.false | ||
78 | }) | ||
79 | |||
80 | it('Should not allow login for user with unverified email', async function () { | ||
81 | const resLogin = await login(server.url, server.client, user1, 400) | ||
82 | expect(resLogin.body.error).to.contain('User email is not verified.') | ||
83 | }) | ||
84 | |||
85 | it('Should verify the user via email and allow login', async function () { | ||
86 | await verifyEmail(server.url, userId, verificationString) | ||
87 | await login(server.url, server.client, user1) | ||
88 | const resUserVerified = await getUserInformation(server.url, server.accessToken, userId) | ||
89 | expect(resUserVerified.body.emailVerified).to.be.true | ||
90 | }) | ||
91 | |||
92 | it('Should register user not requiring email verification if setting not enabled', async function () { | ||
93 | this.timeout(5000) | ||
94 | await updateCustomSubConfig(server.url, server.accessToken, { | ||
95 | signup: { | ||
96 | enabled: true, | ||
97 | requiresEmailVerification: false, | ||
98 | limit: 10 | ||
99 | } | ||
100 | }) | ||
101 | |||
102 | await registerUser(server.url, user2.username, user2.password) | ||
103 | |||
104 | await waitJobs(server) | ||
105 | expect(emails).to.have.lengthOf(expectedEmailsLength) | ||
106 | |||
107 | const accessToken = await userLogin(server, user2) | ||
108 | |||
109 | const resMyUserInfo = await getMyUserInformation(server.url, accessToken) | ||
110 | expect(resMyUserInfo.body.emailVerified).to.be.null | ||
111 | }) | ||
112 | |||
113 | it('Should allow login for user with unverified email when setting later enabled', async function () { | ||
114 | await updateCustomSubConfig(server.url, server.accessToken, { | ||
115 | signup: { | ||
116 | enabled: true, | ||
117 | requiresEmailVerification: true, | ||
118 | limit: 10 | ||
119 | } | ||
120 | }) | ||
121 | |||
122 | await userLogin(server, user2) | ||
123 | }) | ||
124 | |||
125 | after(async function () { | ||
126 | killallServers([ server ]) | ||
127 | |||
128 | // Keep the logs if the test failed | ||
129 | if (this[ 'ok' ]) { | ||
130 | await flushTests() | ||
131 | } | ||
132 | }) | ||
133 | }) | ||
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 04dcc8fd1..c0dd587ee 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts | |||
@@ -7,7 +7,7 @@ import { | |||
7 | createUser, flushTests, getBlacklistedVideosList, getMyUserInformation, getMyUserVideoQuotaUsed, getMyUserVideoRating, | 7 | createUser, flushTests, getBlacklistedVideosList, getMyUserInformation, getMyUserVideoQuotaUsed, getMyUserVideoRating, |
8 | getUserInformation, getUsersList, getUsersListPaginationAndSort, getVideosList, killallServers, login, makePutBodyRequest, rateVideo, | 8 | getUserInformation, getUsersList, getUsersListPaginationAndSort, getVideosList, killallServers, login, makePutBodyRequest, rateVideo, |
9 | registerUser, removeUser, removeVideo, runServer, ServerInfo, testImage, updateMyAvatar, updateMyUser, updateUser, uploadVideo, userLogin, | 9 | registerUser, removeUser, removeVideo, runServer, ServerInfo, testImage, updateMyAvatar, updateMyUser, updateUser, uploadVideo, userLogin, |
10 | deleteMe, blockUser, unblockUser | 10 | deleteMe, blockUser, unblockUser, updateCustomSubConfig |
11 | } from '../../utils/index' | 11 | } from '../../utils/index' |
12 | import { follow } from '../../utils/server/follows' | 12 | import { follow } from '../../utils/server/follows' |
13 | import { setAccessTokensToServers } from '../../utils/users/login' | 13 | import { setAccessTokensToServers } from '../../utils/users/login' |
diff --git a/server/tests/utils/server/config.ts b/server/tests/utils/server/config.ts index 799c31ae5..b85e02ab7 100644 --- a/server/tests/utils/server/config.ts +++ b/server/tests/utils/server/config.ts | |||
@@ -74,7 +74,8 @@ function updateCustomSubConfig (url: string, token: string, newConfig: any) { | |||
74 | }, | 74 | }, |
75 | signup: { | 75 | signup: { |
76 | enabled: false, | 76 | enabled: false, |
77 | limit: 5 | 77 | limit: 5, |
78 | requiresEmailVerification: false | ||
78 | }, | 79 | }, |
79 | admin: { | 80 | admin: { |
80 | email: 'superadmin1@example.com' | 81 | email: 'superadmin1@example.com' |
diff --git a/server/tests/utils/users/users.ts b/server/tests/utils/users/users.ts index 5dba34b69..cd1b07701 100644 --- a/server/tests/utils/users/users.ts +++ b/server/tests/utils/users/users.ts | |||
@@ -246,6 +246,28 @@ function resetPassword (url: string, userId: number, verificationString: string, | |||
246 | }) | 246 | }) |
247 | } | 247 | } |
248 | 248 | ||
249 | function askSendVerifyEmail (url: string, email: string) { | ||
250 | const path = '/api/v1/users/ask-send-verify-email' | ||
251 | |||
252 | return makePostBodyRequest({ | ||
253 | url, | ||
254 | path, | ||
255 | fields: { email }, | ||
256 | statusCodeExpected: 204 | ||
257 | }) | ||
258 | } | ||
259 | |||
260 | function verifyEmail (url: string, userId: number, verificationString: string, statusCodeExpected = 204) { | ||
261 | const path = '/api/v1/users/' + userId + '/verify-email' | ||
262 | |||
263 | return makePostBodyRequest({ | ||
264 | url, | ||
265 | path, | ||
266 | fields: { verificationString }, | ||
267 | statusCodeExpected | ||
268 | }) | ||
269 | } | ||
270 | |||
249 | // --------------------------------------------------------------------------- | 271 | // --------------------------------------------------------------------------- |
250 | 272 | ||
251 | export { | 273 | export { |
@@ -265,5 +287,7 @@ export { | |||
265 | unblockUser, | 287 | unblockUser, |
266 | askResetPassword, | 288 | askResetPassword, |
267 | resetPassword, | 289 | resetPassword, |
268 | updateMyAvatar | 290 | updateMyAvatar, |
291 | askSendVerifyEmail, | ||
292 | verifyEmail | ||
269 | } | 293 | } |