@@ -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 ( ) ;
@@ -3777,60 +3777,258 @@ describe('beforeLogin hook', () => {
37773777 await Parse . User . logIn ( 'tupac' , 'shakur' ) ;
37783778 done ( ) ;
37793779 } ) ;
3780+ } ) ;
3781+
3782+ describe ( 'beforePasswordResetRequest hook' , ( ) => {
3783+ it ( 'should run beforePasswordResetRequest with valid user' , async done => {
3784+ let hit = 0 ;
3785+ let sendPasswordResetEmailCalled = false ;
3786+ const emailAdapter = {
3787+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
3788+ sendPasswordResetEmail : ( ) => {
3789+ sendPasswordResetEmailCalled = true ;
3790+ } ,
3791+ sendMail : ( ) => { } ,
3792+ } ;
37803793
3781- it ( 'afterFind should not be triggered when saving an object' , async ( ) => {
3782- let beforeSaves = 0 ;
3783- Parse . Cloud . beforeSave ( 'SavingTest' , ( ) => {
3784- beforeSaves ++ ;
3794+ await reconfigureServer ( {
3795+ appName : 'test' ,
3796+ emailAdapter : emailAdapter ,
3797+ publicServerURL : 'http://localhost:8378/1' ,
37853798 } ) ;
37863799
3787- let afterSaves = 0 ;
3788- Parse . Cloud . afterSave ( 'SavingTest' , ( ) => {
3789- afterSaves ++ ;
3800+ Parse . Cloud . beforePasswordResetRequest ( req => {
3801+ hit ++ ;
3802+ expect ( req . object ) . toBeDefined ( ) ;
3803+ expect ( req . object . get ( 'email' ) ) . toEqual ( '[email protected] ' ) ; 3804+ expect ( req . object . get ( 'username' ) ) . toEqual ( 'testuser' ) ;
37903805 } ) ;
37913806
3792- let beforeFinds = 0 ;
3793- Parse . Cloud . beforeFind ( 'SavingTest' , ( ) => {
3794- beforeFinds ++ ;
3807+ const user = new Parse . User ( ) ;
3808+ user . setUsername ( 'testuser' ) ;
3809+ user . setPassword ( 'password' ) ;
3810+ user . set ( 'email' , '[email protected] ' ) ; 3811+ await user . signUp ( ) ;
3812+
3813+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 3814+ expect ( hit ) . toBe ( 1 ) ;
3815+ expect ( sendPasswordResetEmailCalled ) . toBe ( true ) ;
3816+ done ( ) ;
3817+ } ) ;
3818+
3819+ it ( 'should be able to block password reset request if an error is thrown' , async done => {
3820+ let hit = 0 ;
3821+ let sendPasswordResetEmailCalled = false ;
3822+ const emailAdapter = {
3823+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
3824+ sendPasswordResetEmail : ( ) => {
3825+ sendPasswordResetEmailCalled = true ;
3826+ } ,
3827+ sendMail : ( ) => { } ,
3828+ } ;
3829+
3830+ await reconfigureServer ( {
3831+ appName : 'test' ,
3832+ emailAdapter : emailAdapter ,
3833+ publicServerURL : 'http://localhost:8378/1' ,
37953834 } ) ;
37963835
3797- let afterFinds = 0 ;
3798- Parse . Cloud . afterFind ( 'SavingTest' , ( ) => {
3799- afterFinds ++ ;
3836+ Parse . Cloud . beforePasswordResetRequest ( req => {
3837+ hit ++ ;
3838+ if ( req . object . get ( 'isBanned' ) ) {
3839+ throw new Error ( 'banned account' ) ;
3840+ }
38003841 } ) ;
38013842
3802- const obj = new Parse . Object ( 'SavingTest' ) ;
3803- obj . set ( 'someField' , 'some value 1' ) ;
3804- await obj . save ( ) ;
3843+ const user = new Parse . User ( ) ;
3844+ user . setUsername ( 'banneduser' ) ;
3845+ user . setPassword ( 'password' ) ;
3846+ user . set ( 'email' , '[email protected] ' ) ; 3847+ await user . signUp ( ) ;
3848+ await user . save ( { isBanned : true } ) ;
38053849
3806- expect ( beforeSaves ) . toEqual ( 1 ) ;
3807- expect ( afterSaves ) . toEqual ( 1 ) ;
3808- expect ( beforeFinds ) . toEqual ( 0 ) ;
3809- expect ( afterFinds ) . toEqual ( 0 ) ;
3850+ try {
3851+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 3852+ throw new Error ( 'should not have sent password reset email.' ) ;
3853+ } catch ( e ) {
3854+ expect ( e . message ) . toBe ( 'banned account' ) ;
3855+ }
3856+ expect ( hit ) . toBe ( 1 ) ;
3857+ expect ( sendPasswordResetEmailCalled ) . toBe ( false ) ;
3858+ done ( ) ;
3859+ } ) ;
38103860
3811- obj . set ( 'someField' , 'some value 2' ) ;
3812- await obj . save ( ) ;
3861+ it ( 'should be able to block password reset request if an error is thrown even if the user has an attached file' , async done => {
3862+ let hit = 0 ;
3863+ let sendPasswordResetEmailCalled = false ;
3864+ const emailAdapter = {
3865+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
3866+ sendPasswordResetEmail : ( ) => {
3867+ sendPasswordResetEmailCalled = true ;
3868+ } ,
3869+ sendMail : ( ) => { } ,
3870+ } ;
38133871
3814- expect ( beforeSaves ) . toEqual ( 2 ) ;
3815- expect ( afterSaves ) . toEqual ( 2 ) ;
3816- expect ( beforeFinds ) . toEqual ( 0 ) ;
3817- expect ( afterFinds ) . toEqual ( 0 ) ;
3872+ await reconfigureServer ( {
3873+ appName : 'test' ,
3874+ emailAdapter : emailAdapter ,
3875+ publicServerURL : 'http://localhost:8378/1' ,
3876+ } ) ;
38183877
3819- await obj . fetch ( ) ;
3878+ Parse . Cloud . beforePasswordResetRequest ( req => {
3879+ hit ++ ;
3880+ if ( req . object . get ( 'isBanned' ) ) {
3881+ throw new Error ( 'banned account' ) ;
3882+ }
3883+ } ) ;
38203884
3821- expect ( beforeSaves ) . toEqual ( 2 ) ;
3822- expect ( afterSaves ) . toEqual ( 2 ) ;
3823- expect ( beforeFinds ) . toEqual ( 1 ) ;
3824- expect ( afterFinds ) . toEqual ( 1 ) ;
3885+ const user = new Parse . User ( ) ;
3886+ user . setUsername ( 'banneduser2' ) ;
3887+ user . setPassword ( 'password' ) ;
3888+ user . set ( 'email' , '[email protected] ' ) ; 3889+ await user . signUp ( ) ;
3890+ const base64 = 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=' ;
3891+ const file = new Parse . File ( 'myfile.txt' , { base64 } ) ;
3892+ await file . save ( ) ;
3893+ await user . save ( { isBanned : true , file } ) ;
38253894
3826- obj . set ( 'someField' , 'some value 3' ) ;
3827- await obj . save ( ) ;
3895+ try {
3896+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 3897+ throw new Error ( 'should not have sent password reset email.' ) ;
3898+ } catch ( e ) {
3899+ expect ( e . message ) . toBe ( 'banned account' ) ;
3900+ }
3901+ expect ( hit ) . toBe ( 1 ) ;
3902+ expect ( sendPasswordResetEmailCalled ) . toBe ( false ) ;
3903+ done ( ) ;
3904+ } ) ;
3905+
3906+ it ( 'should not run beforePasswordResetRequest if email does not exist' , async done => {
3907+ let hit = 0 ;
3908+ const emailAdapter = {
3909+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
3910+ sendPasswordResetEmail : ( ) => { } ,
3911+ sendMail : ( ) => { } ,
3912+ } ;
3913+
3914+ await reconfigureServer ( {
3915+ emailAdapter : emailAdapter ,
3916+ publicServerURL : 'http://localhost:8378/1' ,
3917+ } ) ;
3918+
3919+ Parse . Cloud . beforePasswordResetRequest ( req => {
3920+ hit ++ ;
3921+ } ) ;
3922+
3923+ try {
3924+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 3925+ } catch ( e ) {
3926+ // May or may not throw depending on passwordPolicy.resetPasswordSuccessOnInvalidEmail
3927+ }
3928+ expect ( hit ) . toBe ( 0 ) ;
3929+ done ( ) ;
3930+ } ) ;
3931+
3932+ it ( 'should have expected data in request in beforePasswordResetRequest' , async done => {
3933+ const emailAdapter = {
3934+ sendVerificationEmail : ( ) => Promise . resolve ( ) ,
3935+ sendPasswordResetEmail : ( ) => { } ,
3936+ sendMail : ( ) => { } ,
3937+ } ;
3938+
3939+ await reconfigureServer ( {
3940+ appName : 'test' ,
3941+ emailAdapter : emailAdapter ,
3942+ publicServerURL : 'http://localhost:8378/1' ,
3943+ } ) ;
3944+
3945+ Parse . Cloud . beforePasswordResetRequest ( req => {
3946+ expect ( req . object ) . toBeDefined ( ) ;
3947+ expect ( req . object . get ( 'email' ) ) . toBeDefined ( ) ;
3948+ expect ( req . headers ) . toBeDefined ( ) ;
3949+ expect ( req . ip ) . toBeDefined ( ) ;
3950+ expect ( req . installationId ) . toBeDefined ( ) ;
3951+ expect ( req . context ) . toBeDefined ( ) ;
3952+ expect ( req . config ) . toBeDefined ( ) ;
3953+ } ) ;
3954+
3955+ const user = new Parse . User ( ) ;
3956+ user . setUsername ( 'testuser2' ) ;
3957+ user . setPassword ( 'password' ) ;
3958+ user . set ( 'email' , '[email protected] ' ) ; 3959+ await user . signUp ( ) ;
3960+ await Parse . User . requestPasswordReset ( '[email protected] ' ) ; 3961+ done ( ) ;
3962+ } ) ;
3963+
3964+ it ( 'should validate that only _User class is allowed for beforePasswordResetRequest' , ( ) => {
3965+ expect ( ( ) => {
3966+ Parse . Cloud . beforePasswordResetRequest ( 'SomeClass' , ( ) => { } ) ;
3967+ } ) . toThrow ( 'Only the _User class is allowed for the beforeLogin, afterLogin, and beforePasswordResetRequest triggers' ) ;
3968+ expect ( ( ) => {
3969+ Parse . Cloud . beforePasswordResetRequest ( ( ) => { } ) ;
3970+ } ) . not . toThrow ( ) ;
3971+ expect ( ( ) => {
3972+ Parse . Cloud . beforePasswordResetRequest ( '_User' , ( ) => { } ) ;
3973+ } ) . not . toThrow ( ) ;
3974+ expect ( ( ) => {
3975+ Parse . Cloud . beforePasswordResetRequest ( Parse . User , ( ) => { } ) ;
3976+ } ) . not . toThrow ( ) ;
3977+ } ) ;
3978+ } ) ;
3979+
3980+ it ( 'afterFind should not be triggered when saving an object' , async ( ) => {
3981+ let beforeSaves = 0 ;
3982+ Parse . Cloud . beforeSave ( 'SavingTest' , ( ) => {
3983+ beforeSaves ++ ;
3984+ } ) ;
3985+
3986+ let afterSaves = 0 ;
3987+ Parse . Cloud . afterSave ( 'SavingTest' , ( ) => {
3988+ afterSaves ++ ;
3989+ } ) ;
3990+
3991+ let beforeFinds = 0 ;
3992+ Parse . Cloud . beforeFind ( 'SavingTest' , ( ) => {
3993+ beforeFinds ++ ;
3994+ } ) ;
38283995
3829- expect ( beforeSaves ) . toEqual ( 3 ) ;
3830- expect ( afterSaves ) . toEqual ( 3 ) ;
3831- expect ( beforeFinds ) . toEqual ( 1 ) ;
3832- expect ( afterFinds ) . toEqual ( 1 ) ;
3996+ let afterFinds = 0 ;
3997+ Parse . Cloud . afterFind ( 'SavingTest' , ( ) => {
3998+ afterFinds ++ ;
38333999 } ) ;
4000+
4001+ const obj = new Parse . Object ( 'SavingTest' ) ;
4002+ obj . set ( 'someField' , 'some value 1' ) ;
4003+ await obj . save ( ) ;
4004+
4005+ expect ( beforeSaves ) . toEqual ( 1 ) ;
4006+ expect ( afterSaves ) . toEqual ( 1 ) ;
4007+ expect ( beforeFinds ) . toEqual ( 0 ) ;
4008+ expect ( afterFinds ) . toEqual ( 0 ) ;
4009+
4010+ obj . set ( 'someField' , 'some value 2' ) ;
4011+ await obj . save ( ) ;
4012+
4013+ expect ( beforeSaves ) . toEqual ( 2 ) ;
4014+ expect ( afterSaves ) . toEqual ( 2 ) ;
4015+ expect ( beforeFinds ) . toEqual ( 0 ) ;
4016+ expect ( afterFinds ) . toEqual ( 0 ) ;
4017+
4018+ await obj . fetch ( ) ;
4019+
4020+ expect ( beforeSaves ) . toEqual ( 2 ) ;
4021+ expect ( afterSaves ) . toEqual ( 2 ) ;
4022+ expect ( beforeFinds ) . toEqual ( 1 ) ;
4023+ expect ( afterFinds ) . toEqual ( 1 ) ;
4024+
4025+ obj . set ( 'someField' , 'some value 3' ) ;
4026+ await obj . save ( ) ;
4027+
4028+ expect ( beforeSaves ) . toEqual ( 3 ) ;
4029+ expect ( afterSaves ) . toEqual ( 3 ) ;
4030+ expect ( beforeFinds ) . toEqual ( 1 ) ;
4031+ expect ( afterFinds ) . toEqual ( 1 ) ;
38344032} ) ;
38354033
38364034describe ( 'afterLogin hook' , ( ) => {
0 commit comments