@@ -3307,19 +3307,19 @@ describe('afterFind hooks', () => {
33073307 } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin and afterLogin triggers' ) ;
33083308 expect ( ( ) => {
33093309 Parse . Cloud . beforeLogin ( 'SomeClass' , ( ) => { } ) ;
3310- } ) . toThrow ( 'Only the _User class is allowed for the beforeLogin and afterLogin triggers' ) ;
3310+ } ) . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
33113311 expect ( ( ) => {
33123312 Parse . Cloud . afterLogin ( ( ) => { } ) ;
3313- } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin and afterLogin triggers' ) ;
3313+ } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
33143314 expect ( ( ) => {
33153315 Parse . Cloud . afterLogin ( '_User' , ( ) => { } ) ;
3316- } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin and afterLogin triggers' ) ;
3316+ } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
33173317 expect ( ( ) => {
33183318 Parse . Cloud . afterLogin ( Parse . User , ( ) => { } ) ;
3319- } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin and afterLogin triggers' ) ;
3319+ } ) . not . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
33203320 expect ( ( ) => {
33213321 Parse . Cloud . afterLogin ( 'SomeClass' , ( ) => { } ) ;
3322- } ) . toThrow ( 'Only the _User class is allowed for the beforeLogin and afterLogin triggers' ) ;
3322+ } ) . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
33233323 expect ( ( ) => {
33243324 Parse . Cloud . afterLogout ( ( ) => { } ) ;
33253325 } ) . not . toThrow ( ) ;
@@ -4656,3 +4656,157 @@ describe('sendEmail', () => {
46564656 ) ;
46574657 } ) ;
46584658} ) ;
4659+
4660+ describe ( 'beforePasswordResetRequest hook' , ( ) => {
4661+ it ( 'should run beforePasswordResetRequest with valid user' , async ( ) => {
4662+ let hit = 0 ;
4663+ let sendPasswordResetEmailCalled = false ;
4664+ const emailAdapter = {
4665+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
4666+ sendPasswordResetEmail : ( ) => {
4667+ sendPasswordResetEmailCalled = true ;
4668+ } ,
4669+ sendMail : ( ) => { } ,
4670+ } ;
4671+
4672+ await reconfigureServer ( {
4673+ appName : 'test' ,
4674+ emailAdapter : emailAdapter ,
4675+ publicServerURL : 'http://localhost:8378/1' ,
4676+ } ) ;
4677+
4678+ Parse . Cloud . beforePasswordResetRequest ( req => {
4679+ hit ++ ;
4680+ expect ( req . object ) . toBeDefined ( ) ;
4681+ expect ( req . object . get ( 'email' ) ) . toEqual ( '[email protected] ' ) ; 4682+ expect ( req . object . get ( 'username' ) ) . toEqual ( 'testuser' ) ;
4683+ } ) ;
4684+
4685+ const user = new Parse . User ( ) ;
4686+ user . setUsername ( 'testuser' ) ;
4687+ user . setPassword ( 'password' ) ;
4688+ user . set ( 'email' , '[email protected] ' ) ; 4689+ await user . signUp ( ) ;
4690+
4691+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 4692+ expect ( hit ) . toBe ( 1 ) ;
4693+ expect ( sendPasswordResetEmailCalled ) . toBe ( true ) ;
4694+ } ) ;
4695+
4696+ it ( 'should be able to block password reset request if an error is thrown' , async ( ) => {
4697+ let hit = 0 ;
4698+ let sendPasswordResetEmailCalled = false ;
4699+ const emailAdapter = {
4700+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
4701+ sendPasswordResetEmail : ( ) => {
4702+ sendPasswordResetEmailCalled = true ;
4703+ } ,
4704+ sendMail : ( ) => { } ,
4705+ } ;
4706+
4707+ await reconfigureServer ( {
4708+ appName : 'test' ,
4709+ emailAdapter : emailAdapter ,
4710+ publicServerURL : 'http://localhost:8378/1' ,
4711+ } ) ;
4712+
4713+ Parse . Cloud . beforePasswordResetRequest ( req => {
4714+ hit ++ ;
4715+ throw new Error ( 'password reset blocked' ) ;
4716+ } ) ;
4717+
4718+ const user = new Parse . User ( ) ;
4719+ user . setUsername ( 'testuser' ) ;
4720+ user . setPassword ( 'password' ) ;
4721+ user . set ( 'email' , '[email protected] ' ) ; 4722+ await user . signUp ( ) ;
4723+
4724+ try {
4725+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 4726+ throw new Error ( 'should not have sent password reset email.' ) ;
4727+ } catch ( e ) {
4728+ expect ( e . message ) . toBe ( 'password reset blocked' ) ;
4729+ }
4730+ expect ( hit ) . toBe ( 1 ) ;
4731+ expect ( sendPasswordResetEmailCalled ) . toBe ( false ) ;
4732+ } ) ;
4733+
4734+ it ( 'should not run beforePasswordResetRequest if email does not exist' , async ( ) => {
4735+ let hit = 0 ;
4736+ const emailAdapter = {
4737+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
4738+ sendPasswordResetEmail : ( ) => { } ,
4739+ sendMail : ( ) => { } ,
4740+ } ;
4741+
4742+ await reconfigureServer ( {
4743+ appName : 'test' ,
4744+ emailAdapter : emailAdapter ,
4745+ publicServerURL : 'http://localhost:8378/1' ,
4746+ } ) ;
4747+
4748+ Parse . Cloud . beforePasswordResetRequest ( req => {
4749+ hit ++ ;
4750+ } ) ;
4751+
4752+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 4753+
4754+ expect ( hit ) . toBe ( 0 ) ;
4755+ } ) ;
4756+
4757+ it ( 'should have expected data in request in beforePasswordResetRequest' , async ( ) => {
4758+ const emailAdapter = {
4759+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
4760+ sendPasswordResetEmail : ( ) => { } ,
4761+ sendMail : ( ) => { } ,
4762+ } ;
4763+
4764+ await reconfigureServer ( {
4765+ appName : 'test' ,
4766+ emailAdapter : emailAdapter ,
4767+ publicServerURL : 'http://localhost:8378/1' ,
4768+ } ) ;
4769+
4770+ const base64 = 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=' ;
4771+ const file = new Parse . File ( 'myfile.txt' , { base64 } ) ;
4772+ await file . save ( ) ;
4773+
4774+ Parse . Cloud . beforePasswordResetRequest ( req => {
4775+ expect ( req . object ) . toBeDefined ( ) ;
4776+ expect ( req . object . get ( 'email' ) ) . toBeDefined ( ) ;
4777+ expect ( req . object . get ( 'email' ) ) . toBe ( '[email protected] ' ) ; 4778+ expect ( req . object . get ( 'file' ) ) . toBeDefined ( ) ;
4779+ expect ( req . object . get ( 'file' ) ) . toBeInstanceOf ( Parse . File ) ;
4780+ expect ( req . object . get ( 'file' ) . name ( ) ) . toContain ( 'myfile.txt' ) ;
4781+ expect ( req . headers ) . toBeDefined ( ) ;
4782+ expect ( req . ip ) . toBeDefined ( ) ;
4783+ expect ( req . installationId ) . toBeDefined ( ) ;
4784+ expect ( req . context ) . toBeDefined ( ) ;
4785+ expect ( req . config ) . toBeDefined ( ) ;
4786+ } ) ;
4787+
4788+ const user = new Parse . User ( ) ;
4789+ user . setUsername ( 'testuser2' ) ;
4790+ user . setPassword ( 'password' ) ;
4791+ user . set ( 'email' , '[email protected] ' ) ; 4792+ user . set ( 'file' , file ) ;
4793+ await user . signUp ( ) ;
4794+
4795+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 4796+ } ) ;
4797+
4798+ it ( 'should validate that only _User class is allowed for beforePasswordResetRequest' , ( ) => {
4799+ expect ( ( ) => {
4800+ Parse . Cloud . beforePasswordResetRequest ( 'SomeClass' , ( ) => { } ) ;
4801+ } ) . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
4802+ expect ( ( ) => {
4803+ Parse . Cloud . beforePasswordResetRequest ( ( ) => { } ) ;
4804+ } ) . not . toThrow ( ) ;
4805+ expect ( ( ) => {
4806+ Parse . Cloud . beforePasswordResetRequest ( '_User' , ( ) => { } ) ;
4807+ } ) . not . toThrow ( ) ;
4808+ expect ( ( ) => {
4809+ Parse . Cloud . beforePasswordResetRequest ( Parse . User , ( ) => { } ) ;
4810+ } ) . not . toThrow ( ) ;
4811+ } ) ;
4812+ } ) ;
0 commit comments