-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
feat: Add new Parse Server option preventSignupWithUnverifiedEmail
to prevent returning a user without session token on sign-up with unverified email address
#8451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 9 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
8e99930
fix: reject signup with preventLoginWithUnverifiedEmail
dblythy 0dd1c71
refactor
dblythy ea50895
refactor tests
dblythy ae2304c
Merge branch 'alpha' into prevent-login
dblythy 26205be
refactor
dblythy 20601d0
definitions
dblythy facaf93
Update ValidationAndPasswordsReset.spec.js
dblythy ecc20c2
Merge branch 'alpha' into prevent-login
dblythy e0cfbc3
Merge branch 'alpha' into prevent-login
mtrezza e6e502e
Update src/Options/index.js
dblythy 5045d14
Merge branch 'alpha' into prevent-login
dblythy 18b920d
definitions
dblythy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -242,8 +242,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => { | |
}); | ||
}); | ||
|
||
it('allows user to login only after user clicks on the link to confirm email address if preventLoginWithUnverifiedEmail is set to true', done => { | ||
const user = new Parse.User(); | ||
it('allows user to login only after user clicks on the link to confirm email address if preventLoginWithUnverifiedEmail is set to true', async () => { | ||
let sendEmailOptions; | ||
const emailAdapter = { | ||
sendVerificationEmail: options => { | ||
|
@@ -252,59 +251,32 @@ describe('Custom Pages, Email Verification, Password Reset', () => { | |
sendPasswordResetEmail: () => Promise.resolve(), | ||
sendMail: () => {}, | ||
}; | ||
reconfigureServer({ | ||
await reconfigureServer({ | ||
appName: 'emailing app', | ||
verifyUserEmails: true, | ||
preventLoginWithUnverifiedEmail: true, | ||
emailAdapter: emailAdapter, | ||
publicServerURL: 'http://localhost:8378/1', | ||
}) | ||
.then(() => { | ||
user.setPassword('other-password'); | ||
user.setUsername('user'); | ||
user.set('email', '[email protected]'); | ||
return user.signUp(); | ||
}) | ||
.then(() => { | ||
expect(sendEmailOptions).not.toBeUndefined(); | ||
request({ | ||
url: sendEmailOptions.link, | ||
followRedirects: false, | ||
}).then(response => { | ||
expect(response.status).toEqual(302); | ||
expect(response.text).toEqual( | ||
'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user' | ||
); | ||
user | ||
.fetch({ useMasterKey: true }) | ||
.then( | ||
() => { | ||
expect(user.get('emailVerified')).toEqual(true); | ||
|
||
Parse.User.logIn('user', 'other-password').then( | ||
user => { | ||
expect(typeof user).toBe('object'); | ||
expect(user.get('emailVerified')).toBe(true); | ||
done(); | ||
}, | ||
() => { | ||
fail('login should have succeeded'); | ||
done(); | ||
} | ||
); | ||
}, | ||
err => { | ||
jfail(err); | ||
fail('this should not fail'); | ||
done(); | ||
} | ||
) | ||
.catch(err => { | ||
jfail(err); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
let user = new Parse.User(); | ||
user.setPassword('other-password'); | ||
user.setUsername('user'); | ||
user.set('email', '[email protected]'); | ||
await user.signUp(); | ||
expect(sendEmailOptions).not.toBeUndefined(); | ||
const response = await request({ | ||
url: sendEmailOptions.link, | ||
followRedirects: false, | ||
}); | ||
expect(response.status).toEqual(302); | ||
expect(response.text).toEqual( | ||
'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user' | ||
); | ||
user = await new Parse.Query(Parse.User).first({ useMasterKey: true }); | ||
expect(user.get('emailVerified')).toEqual(true); | ||
user = await Parse.User.logIn('user', 'other-password'); | ||
expect(typeof user).toBe('object'); | ||
expect(user.get('emailVerified')).toBe(true); | ||
}); | ||
|
||
it('allows user to login if email is not verified but preventLoginWithUnverifiedEmail is set to false', done => { | ||
|
@@ -345,6 +317,35 @@ describe('Custom Pages, Email Verification, Password Reset', () => { | |
}); | ||
}); | ||
|
||
it('does not allow signup with preventSignupWithUnverified', async () => { | ||
let sendEmailOptions; | ||
const emailAdapter = { | ||
sendVerificationEmail: options => { | ||
sendEmailOptions = options; | ||
}, | ||
sendPasswordResetEmail: () => Promise.resolve(), | ||
sendMail: () => {}, | ||
}; | ||
await reconfigureServer({ | ||
appName: 'test', | ||
publicServerURL: 'http://localhost:1337/1', | ||
verifyUserEmails: true, | ||
preventLoginWithUnverifiedEmail: true, | ||
preventSignupWithUnverifiedEmail: true, | ||
emailAdapter, | ||
}); | ||
const newUser = new Parse.User(); | ||
newUser.setPassword('asdf'); | ||
newUser.setUsername('zxcv'); | ||
newUser.set('email', '[email protected]'); | ||
await expectAsync(newUser.signUp()).toBeRejectedWith( | ||
new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.') | ||
); | ||
const user = await new Parse.Query(Parse.User).first({ useMasterKey: true }); | ||
expect(user).toBeDefined(); | ||
expect(sendEmailOptions).toBeDefined(); | ||
}); | ||
|
||
it('fails if you include an emailAdapter, set a publicServerURL, but have no appName and send a password reset email', done => { | ||
reconfigureServer({ | ||
appName: undefined, | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -353,8 +353,9 @@ describe('Verify User Password', () => { | |
done(); | ||
}); | ||
}); | ||
it('fails to verify password when preventLoginWithUnverifiedEmail is set to true REST API', done => { | ||
reconfigureServer({ | ||
|
||
it('fails to verify password when preventLoginWithUnverifiedEmail is set to true REST API', async () => { | ||
await reconfigureServer({ | ||
publicServerURL: 'http://localhost:8378/', | ||
appName: 'emailVerify', | ||
verifyUserEmails: true, | ||
|
@@ -364,28 +365,21 @@ describe('Verify User Password', () => { | |
apiKey: 'k', | ||
domain: 'd', | ||
}), | ||
}) | ||
.then(() => { | ||
const user = new Parse.User(); | ||
return user.save({ | ||
username: 'unverified-user', | ||
password: 'mypass', | ||
email: '[email protected]', | ||
}); | ||
}) | ||
.then(() => { | ||
return verifyPassword('[email protected]', 'mypass', true); | ||
}) | ||
.then(res => { | ||
expect(res.status).toBe(400); | ||
expect(res.text).toMatch('{"code":205,"error":"User email is not verified."}'); | ||
done(); | ||
}) | ||
.catch(err => { | ||
fail(err); | ||
done(); | ||
}); | ||
}); | ||
const user = new Parse.User(); | ||
await user.save({ | ||
username: 'unverified-user', | ||
password: 'mypass', | ||
email: '[email protected]', | ||
}); | ||
const res = await verifyPassword('[email protected]', 'mypass', true); | ||
expect(res.status).toBe(400); | ||
expect(res.data).toEqual({ | ||
code: Parse.Error.EMAIL_NOT_FOUND, | ||
error: 'User email is not verified.', | ||
}); | ||
}); | ||
|
||
it('verify password lock account if failed verify password attempts are above threshold', done => { | ||
reconfigureServer({ | ||
appName: 'lockout threshold', | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.