-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
feat: Add beforePasswordResetRequest hook
#9906
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
base: alpha
Are you sure you want to change the base?
Changes from 5 commits
c354da3
e30572d
2971acf
8076a65
659ab5e
fce3723
2045d87
8bfc13b
39f0e47
73aa8dd
0b3b21d
57712ce
903c00f
10acf6a
2cccdc4
6dee8bf
39a6a0b
ed0af6a
7d17d09
4316248
6d5c94d
08654bd
2a6df76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3307,19 +3307,19 @@ describe('afterFind hooks', () => { | |
| }).not.toThrow('Only the _User class is allowed for the beforeLogin and afterLogin triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.beforeLogin('SomeClass', () => { }); | ||
| }).toThrow('Only the _User class is allowed for the beforeLogin and afterLogin triggers'); | ||
| }).toThrow('Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.afterLogin(() => { }); | ||
| }).not.toThrow('Only the _User class is allowed for the beforeLogin and afterLogin triggers'); | ||
| }).not.toThrow('Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.afterLogin('_User', () => { }); | ||
| }).not.toThrow('Only the _User class is allowed for the beforeLogin and afterLogin triggers'); | ||
| }).not.toThrow('Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.afterLogin(Parse.User, () => { }); | ||
| }).not.toThrow('Only the _User class is allowed for the beforeLogin and afterLogin triggers'); | ||
| }).not.toThrow('Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.afterLogin('SomeClass', () => { }); | ||
| }).toThrow('Only the _User class is allowed for the beforeLogin and afterLogin triggers'); | ||
| }).toThrow('Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.afterLogout(() => { }); | ||
| }).not.toThrow(); | ||
|
|
@@ -4656,3 +4656,201 @@ describe('sendEmail', () => { | |
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe('beforePasswordResetRequest hook', () => { | ||
| it('should run beforePasswordResetRequest with valid user', async done => { | ||
| let hit = 0; | ||
| let sendPasswordResetEmailCalled = false; | ||
| const emailAdapter = { | ||
| sendVerificationEmail: () => Promise.resolve(), | ||
| sendPasswordResetEmail: () => { | ||
| sendPasswordResetEmailCalled = true; | ||
| }, | ||
| sendMail: () => {}, | ||
| }; | ||
|
|
||
| await reconfigureServer({ | ||
| appName: 'test', | ||
| emailAdapter: emailAdapter, | ||
| publicServerURL: 'http://localhost:8378/1', | ||
| }); | ||
|
|
||
| Parse.Cloud.beforePasswordResetRequest(req => { | ||
| hit++; | ||
| expect(req.object).toBeDefined(); | ||
| expect(req.object.get('email')).toEqual('test@parse.com'); | ||
| expect(req.object.get('username')).toEqual('testuser'); | ||
| }); | ||
|
|
||
| const user = new Parse.User(); | ||
| user.setUsername('testuser'); | ||
| user.setPassword('password'); | ||
| user.set('email', 'test@parse.com'); | ||
| await user.signUp(); | ||
|
|
||
| await Parse.User.requestPasswordReset('test@parse.com'); | ||
| expect(hit).toBe(1); | ||
| expect(sendPasswordResetEmailCalled).toBe(true); | ||
| done(); | ||
| }); | ||
|
|
||
| it('should be able to block password reset request if an error is thrown', async done => { | ||
| let hit = 0; | ||
| let sendPasswordResetEmailCalled = false; | ||
| const emailAdapter = { | ||
| sendVerificationEmail: () => Promise.resolve(), | ||
| sendPasswordResetEmail: () => { | ||
| sendPasswordResetEmailCalled = true; | ||
| }, | ||
| sendMail: () => {}, | ||
| }; | ||
|
|
||
| await reconfigureServer({ | ||
| appName: 'test', | ||
| emailAdapter: emailAdapter, | ||
| publicServerURL: 'http://localhost:8378/1', | ||
| }); | ||
|
|
||
| Parse.Cloud.beforePasswordResetRequest(req => { | ||
| hit++; | ||
| if (req.object.get('isBanned')) { | ||
| throw new Error('banned account'); | ||
| } | ||
| }); | ||
|
|
||
| const user = new Parse.User(); | ||
| user.setUsername('banneduser'); | ||
| user.setPassword('password'); | ||
| user.set('email', 'banned@parse.com'); | ||
| await user.signUp(); | ||
| await user.save({ isBanned: true }); | ||
|
|
||
| try { | ||
| await Parse.User.requestPasswordReset('banned@parse.com'); | ||
| throw new Error('should not have sent password reset email.'); | ||
| } catch (e) { | ||
| expect(e.message).toBe('banned account'); | ||
| } | ||
| expect(hit).toBe(1); | ||
| expect(sendPasswordResetEmailCalled).toBe(false); | ||
| done(); | ||
| }); | ||
|
|
||
| it('should be able to block password reset request if an error is thrown even if the user has an attached file', async done => { | ||
| let hit = 0; | ||
| let sendPasswordResetEmailCalled = false; | ||
| const emailAdapter = { | ||
| sendVerificationEmail: () => Promise.resolve(), | ||
| sendPasswordResetEmail: () => { | ||
| sendPasswordResetEmailCalled = true; | ||
| }, | ||
| sendMail: () => {}, | ||
| }; | ||
|
|
||
| await reconfigureServer({ | ||
| appName: 'test', | ||
| emailAdapter: emailAdapter, | ||
| publicServerURL: 'http://localhost:8378/1', | ||
| }); | ||
|
|
||
| Parse.Cloud.beforePasswordResetRequest(req => { | ||
| hit++; | ||
| if (req.object.get('isBanned')) { | ||
| throw new Error('banned account'); | ||
| } | ||
| }); | ||
|
|
||
| const user = new Parse.User(); | ||
| user.setUsername('banneduser2'); | ||
| user.setPassword('password'); | ||
| user.set('email', 'banned2@parse.com'); | ||
| await user.signUp(); | ||
| const base64 = 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE='; | ||
| const file = new Parse.File('myfile.txt', { base64 }); | ||
| await file.save(); | ||
| await user.save({ isBanned: true, file }); | ||
|
||
|
|
||
| try { | ||
| await Parse.User.requestPasswordReset('banned2@parse.com'); | ||
coratgerl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| throw new Error('should not have sent password reset email.'); | ||
| } catch (e) { | ||
| expect(e.message).toBe('banned account'); | ||
| } | ||
| expect(hit).toBe(1); | ||
| expect(sendPasswordResetEmailCalled).toBe(false); | ||
| done(); | ||
| }); | ||
|
|
||
| it('should not run beforePasswordResetRequest if email does not exist', async done => { | ||
| let hit = 0; | ||
| const emailAdapter = { | ||
| sendVerificationEmail: () => Promise.resolve(), | ||
| sendPasswordResetEmail: () => {}, | ||
| sendMail: () => {}, | ||
| }; | ||
|
|
||
| await reconfigureServer({ | ||
| emailAdapter: emailAdapter, | ||
| publicServerURL: 'http://localhost:8378/1', | ||
| }); | ||
|
|
||
| Parse.Cloud.beforePasswordResetRequest(req => { | ||
| hit++; | ||
| }); | ||
|
|
||
| try { | ||
| await Parse.User.requestPasswordReset('nonexistent@parse.com'); | ||
| } catch (e) { | ||
| // May or may not throw depending on passwordPolicy.resetPasswordSuccessOnInvalidEmail | ||
coratgerl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| expect(hit).toBe(0); | ||
| done(); | ||
| }); | ||
|
|
||
| it('should have expected data in request in beforePasswordResetRequest', async done => { | ||
| const emailAdapter = { | ||
| sendVerificationEmail: () => Promise.resolve(), | ||
| sendPasswordResetEmail: () => {}, | ||
| sendMail: () => {}, | ||
| }; | ||
|
|
||
| await reconfigureServer({ | ||
| appName: 'test', | ||
| emailAdapter: emailAdapter, | ||
| publicServerURL: 'http://localhost:8378/1', | ||
| }); | ||
|
|
||
| Parse.Cloud.beforePasswordResetRequest(req => { | ||
| expect(req.object).toBeDefined(); | ||
| expect(req.object.get('email')).toBeDefined(); | ||
| expect(req.headers).toBeDefined(); | ||
| expect(req.ip).toBeDefined(); | ||
| expect(req.installationId).toBeDefined(); | ||
| expect(req.context).toBeDefined(); | ||
| expect(req.config).toBeDefined(); | ||
| }); | ||
|
|
||
| const user = new Parse.User(); | ||
| user.setUsername('testuser2'); | ||
| user.setPassword('password'); | ||
| user.set('email', 'test2@parse.com'); | ||
| await user.signUp(); | ||
| await Parse.User.requestPasswordReset('test2@parse.com'); | ||
| done(); | ||
| }); | ||
|
|
||
| it('should validate that only _User class is allowed for beforePasswordResetRequest', () => { | ||
| expect(() => { | ||
| Parse.Cloud.beforePasswordResetRequest('SomeClass', () => { }); | ||
| }).toThrow('Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers'); | ||
| expect(() => { | ||
| Parse.Cloud.beforePasswordResetRequest(() => { }); | ||
| }).not.toThrow(); | ||
| expect(() => { | ||
| Parse.Cloud.beforePasswordResetRequest('_User', () => { }); | ||
| }).not.toThrow(); | ||
| expect(() => { | ||
| Parse.Cloud.beforePasswordResetRequest(Parse.User, () => { }); | ||
| }).not.toThrow(); | ||
| }); | ||
| }); | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Uh oh!
There was an error while loading. Please reload this page.