2018-09-01 13:58:06 -04:00
'use strict' ;
2016-11-17 22:07:51 +05:30
2018-09-24 17:07:51 -04:00
const request = require ( '../lib/request' ) ;
2016-11-17 22:07:51 +05:30
2018-09-01 13:58:06 -04:00
describe ( 'Password Policy: ' , ( ) => {
2024-08-13 22:13:19 +02:00
it _id ( 'b400a867-9f05-496f-af79-933aa588dde5' ) ( it ) ( 'should show the invalid link page if the user clicks on the password reset link after the token expires' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
sendEmailOptions = options ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
resetTokenValidityDuration : 0.5 , // 0.5 second
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
user . setUsername ( 'testResetTokenValidity' ) ;
user . setPassword ( 'original' ) ;
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
. then ( ( ) => {
Parse . User . requestPasswordReset ( 'user@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
} )
. then ( ( ) => {
// wait for a bit more than the validity duration set
setTimeout ( ( ) => {
expect ( sendEmailOptions ) . not . toBeUndefined ( ) ;
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2018-09-01 13:58:06 -04:00
'Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'
) ;
done ( ) ;
} )
. catch ( error => {
fail ( error ) ;
} ) ;
} , 1000 ) ;
} )
. catch ( err => {
2016-11-21 21:16:38 +05:30
jfail ( err ) ;
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
it ( 'should show the reset password page if the user clicks on the password reset link before the token expires' , done => {
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
sendEmailOptions = options ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
resetTokenValidityDuration : 5 , // 5 seconds
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
user . setUsername ( 'testResetTokenValidity' ) ;
user . setPassword ( 'original' ) ;
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
. then ( ( ) => {
Parse . User . requestPasswordReset ( 'user@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
} )
. then ( ( ) => {
// wait for a bit but less than the validity duration
setTimeout ( ( ) => {
expect ( sendEmailOptions ) . not . toBeUndefined ( ) ;
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
simple : false ,
resolveWithFullResponse : true ,
followRedirects : false ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=[a-zA-Z0-9]+\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
expect ( response . text . match ( re ) ) . not . toBe ( null ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
fail ( error ) ;
} ) ;
} , 1000 ) ;
} )
. catch ( err => {
2016-11-21 21:16:38 +05:30
jfail ( err ) ;
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2020-11-26 04:30:52 +11:00
it ( 'should not keep reset token by default' , async done => {
const sendEmailOptions = [ ] ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
sendEmailOptions . push ( options ) ;
} ,
sendMail : ( ) => { } ,
} ;
await reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
resetTokenValidityDuration : 5 * 60 , // 5 minutes
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
const user = new Parse . User ( ) ;
user . setUsername ( 'testResetTokenValidity' ) ;
user . setPassword ( 'original' ) ;
user . set ( 'email' , 'user@example.com' ) ;
await user . signUp ( ) ;
await Parse . User . requestPasswordReset ( 'user@example.com' ) ;
await Parse . User . requestPasswordReset ( 'user@example.com' ) ;
expect ( sendEmailOptions [ 0 ] . link ) . not . toBe ( sendEmailOptions [ 1 ] . link ) ;
done ( ) ;
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( '7d98e1f2-ae89-4038-9ea7-5254854ea42e' ) ( it ) ( 'should keep reset token with resetTokenReuseIfValid' , async done => {
2020-11-26 04:30:52 +11:00
const sendEmailOptions = [ ] ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
sendEmailOptions . push ( options ) ;
} ,
sendMail : ( ) => { } ,
} ;
await reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
resetTokenValidityDuration : 5 * 60 , // 5 minutes
resetTokenReuseIfValid : true ,
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
const user = new Parse . User ( ) ;
user . setUsername ( 'testResetTokenValidity' ) ;
user . setPassword ( 'original' ) ;
user . set ( 'email' , 'user@example.com' ) ;
await user . signUp ( ) ;
await Parse . User . requestPasswordReset ( 'user@example.com' ) ;
await Parse . User . requestPasswordReset ( 'user@example.com' ) ;
expect ( sendEmailOptions [ 0 ] . link ) . toBe ( sendEmailOptions [ 1 ] . link ) ;
done ( ) ;
} ) ;
it ( 'should throw with invalid resetTokenReuseIfValid' , async done => {
const sendEmailOptions = [ ] ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
sendEmailOptions . push ( options ) ;
} ,
sendMail : ( ) => { } ,
} ;
try {
await reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
resetTokenValidityDuration : 5 * 60 , // 5 minutes
resetTokenReuseIfValid : [ ] ,
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
fail ( 'should have thrown.' ) ;
} catch ( e ) {
expect ( e ) . toBe ( 'resetTokenReuseIfValid must be a boolean value' ) ;
}
try {
await reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
resetTokenReuseIfValid : true ,
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
fail ( 'should have thrown.' ) ;
} catch ( e ) {
expect ( e ) . toBe ( 'You cannot use resetTokenReuseIfValid without resetTokenValidityDuration' ) ;
}
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
it ( 'should fail if passwordPolicy.resetTokenValidityDuration is not a number' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
resetTokenValidityDuration : 'not a number' ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'passwordPolicy.resetTokenValidityDuration "not a number" test failed' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.resetTokenValidityDuration must be a positive number' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
it ( 'should fail if passwordPolicy.resetTokenValidityDuration is zero or a negative number' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
resetTokenValidityDuration : 0 ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'resetTokenValidityDuration negative number test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.resetTokenValidityDuration must be a positive number' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
it ( 'should fail if passwordPolicy.validatorPattern setting is invalid type' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : 1234 , // number is not a valid setting
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.validatorPattern type test failed' ) ;
done ( ) ;
} )
. catch ( err => {
expect ( err ) . toEqual (
'passwordPolicy.validatorPattern must be a regex string or RegExp object.'
) ;
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
it ( 'should fail if passwordPolicy.validatorCallback setting is invalid type' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorCallback : 'abc' , // string is not a valid setting
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.validatorCallback type test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.validatorCallback must be a function.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password does not conform to the policy enforced using validatorPattern' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[0-9]+/ , // password should contain at least one digit
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'nodigit' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'Should have failed as password does not conform to the policy.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( 142 ) ;
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password does not conform to the policy enforced using validatorPattern string' , done => {
2017-01-08 20:42:44 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : '^.{8,}' , // password should contain at least 8 char
2017-01-08 20:42:44 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-01-08 20:42:44 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'less' ) ;
2017-01-08 20:42:44 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'Should have failed as password does not conform to the policy.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( 142 ) ;
done ( ) ;
} ) ;
} ) ;
2017-01-08 20:42:44 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password is empty' , done => {
2017-02-24 17:51:50 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : '^.{8,}' , // password should contain at least 8 char
2017-02-24 17:51:50 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-02-24 17:51:50 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( '' ) ;
2017-02-24 17:51:50 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'Should have failed as password does not conform to the policy.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
2020-10-25 15:06:58 -05:00
expect ( error . message ) . toEqual ( 'Cannot sign up user with an empty password.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
} ) ;
2017-02-24 17:51:50 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should succeed if password conforms to the policy enforced using validatorPattern' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[0-9]+/ , // password should contain at least one digit
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( '1digit' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . logOut ( )
. then ( ( ) => {
Parse . User . logIn ( 'user1' , '1digit' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'Should be able to login' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'logout should have succeeded' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2020-10-25 15:06:58 -05:00
fail ( 'Signup should have succeeded as password conforms to the policy.' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should succeed if password conforms to the policy enforced using validatorPattern string' , done => {
2017-01-08 20:42:44 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : '[!@#$]+' , // password should contain at least one special char
2017-01-08 20:42:44 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-01-08 20:42:44 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'p@sswrod' ) ;
2017-01-08 20:42:44 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . logOut ( )
. then ( ( ) => {
Parse . User . logIn ( 'user1' , 'p@sswrod' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'Should be able to login' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'logout should have succeeded' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2017-01-08 20:42:44 +05:30
jfail ( error ) ;
2020-10-25 15:06:58 -05:00
fail ( 'Signup should have succeeded as password conforms to the policy.' ) ;
2017-01-08 20:42:44 +05:30
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2017-01-08 20:42:44 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password does not conform to the policy enforced using validatorCallback' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorCallback : ( ) => false , // just fail
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'any' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'Should have failed as password does not conform to the policy.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( 142 ) ;
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should succeed if password conforms to the policy enforced using validatorCallback' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorCallback : ( ) => true , // never fail
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'oneUpper' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . logOut ( )
. then ( ( ) => {
Parse . User . logIn ( 'user1' , 'oneUpper' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'Should be able to login' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Logout should have succeeded' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Should have succeeded as password conforms to the policy.' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password does not match validatorPattern but succeeds validatorCallback' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[A-Z]+/ , // password should contain at least one UPPER case letter
validatorCallback : ( ) => true ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'all lower' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'Should have failed as password does not conform to the policy.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( 142 ) ;
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password matches validatorPattern but fails validatorCallback' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[A-Z]+/ , // password should contain at least one UPPER case letter
validatorCallback : ( ) => false ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'oneUpper' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'Should have failed as password does not conform to the policy.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( 142 ) ;
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should succeed if password conforms to both validatorPattern and validatorCallback' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[A-Z]+/ , // password should contain at least one digit
validatorCallback : ( ) => true ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'oneUpper' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . logOut ( )
. then ( ( ) => {
Parse . User . logIn ( 'user1' , 'oneUpper' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'Should be able to login' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'logout should have succeeded' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Should have succeeded as password conforms to the policy.' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2016-11-21 21:16:38 +05:30
it ( 'should reset password if new password conforms to password policy' , done => {
const user = new Parse . User ( ) ;
const emailAdapter = {
2016-11-17 22:07:51 +05:30
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
2018-09-24 17:07:51 -04:00
request ( {
url : options . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
const match = response . text . match ( re ) ;
2018-09-01 13:58:06 -04:00
if ( ! match ) {
fail ( 'should have a token' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
2018-09-01 13:58:06 -04:00
return ;
}
const token = match [ 1 ] ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=has2init&token= ${ token } ` ,
2018-09-24 17:07:51 -04:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2025-03-02 12:32:43 +11:00
'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html'
2018-09-01 13:58:06 -04:00
) ;
Parse . User . logIn ( 'user1' , 'has2init' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'should login with new password' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Failed to POST request password reset' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-17 22:07:51 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Failed to get the reset link' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
} ) ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
emailAdapter : emailAdapter ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[0-9]+/ , // password should contain at least one digit
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'has 1 digit' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . requestPasswordReset ( 'user1@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'signUp should not fail' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
2016-11-17 22:07:51 +05:30
} ) ;
} ) ;
} ) ;
it ( 'should fail to reset password if the new password does not conform to password policy' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
const emailAdapter = {
2016-11-17 22:07:51 +05:30
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
2018-09-24 17:07:51 -04:00
request ( {
url : options . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
const match = response . text . match ( re ) ;
2018-09-01 13:58:06 -04:00
if ( ! match ) {
fail ( 'should have a token' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
2018-09-01 13:58:06 -04:00
return ;
}
const token = match [ 1 ] ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=hasnodigit&token= ${ token } ` ,
2018-09-24 17:07:51 -04:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2025-03-02 12:32:43 +11:00
` Found. Redirecting to http://localhost:8378/1/apps/choose_password?token= ${ token } &id=test&error=Password%20should%20contain%20at%20least%20one%20digit.&app=passwordPolicy `
2018-09-01 13:58:06 -04:00
) ;
Parse . User . logIn ( 'user1' , 'has 1 digit' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'should login with old password' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Failed to POST request password reset' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-17 22:07:51 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Failed to get the reset link' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
} ) ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
emailAdapter : emailAdapter ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[0-9]+/ , // password should contain at least one digit
2019-02-28 16:17:31 -05:00
validationError : 'Password should contain at least one digit.' ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'has 1 digit' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . requestPasswordReset ( 'user1@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'signUp should not fail' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
2016-11-17 22:07:51 +05:30
} ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'should fail if passwordPolicy.doNotAllowUsername is not a boolean value' , done => {
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
doNotAllowUsername : 'no' ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.doNotAllowUsername type test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.doNotAllowUsername must be a boolean value.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should fail if password contains the username and is not allowed by policy' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
validatorPattern : /[0-9]+/ ,
2018-09-01 13:58:06 -04:00
doNotAllowUsername : true ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( '@user11' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
fail ( 'Should have failed as password contains username.' ) ;
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( 142 ) ;
2020-10-25 15:06:58 -05:00
expect ( error . message ) . toEqual ( 'Password cannot contain your username.' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should succeed if password does not contain the username and is not allowed by policy' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
doNotAllowUsername : true ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'r@nd0m' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
done ( ) ;
} )
. catch ( ( ) => {
fail ( 'Should have succeeded as password does not contain username.' ) ;
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
it ( 'signup should succeed if password contains the username and it is allowed by policy' , done => {
2016-11-17 22:07:51 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
validatorPattern : /[0-9]+/ ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
done ( ) ;
} )
. catch ( ( ) => {
fail ( 'Should have succeeded as policy allows username in password.' ) ;
done ( ) ;
} ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
it ( 'should fail to reset password if the new password contains username and not allowed by password policy' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
const emailAdapter = {
2016-11-17 22:07:51 +05:30
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
2018-09-24 17:07:51 -04:00
request ( {
url : options . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
const match = response . text . match ( re ) ;
2018-09-01 13:58:06 -04:00
if ( ! match ) {
fail ( 'should have a token' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
2018-09-01 13:58:06 -04:00
return ;
}
const token = match [ 1 ] ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=xuser12&token= ${ token } ` ,
2018-09-24 17:07:51 -04:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2025-03-02 12:32:43 +11:00
` Found. Redirecting to http://localhost:8378/1/apps/choose_password?token= ${ token } &id=test&error=Password%20cannot%20contain%20your%20username.&app=passwordPolicy `
2018-09-01 13:58:06 -04:00
) ;
2016-11-17 22:07:51 +05:30
2018-09-01 13:58:06 -04:00
Parse . User . logIn ( 'user1' , 'r@nd0m' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'should login with old password' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Failed to POST request password reset' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-17 22:07:51 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Failed to get the reset link' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
} ) ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
emailAdapter : emailAdapter ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
doNotAllowUsername : true ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-17 22:07:51 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'r@nd0m' ) ;
2016-11-17 22:07:51 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . requestPasswordReset ( 'user1@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'signUp should not fail' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
2016-11-17 22:07:51 +05:30
} ) ;
} ) ;
} ) ;
2019-03-14 23:06:18 +02:00
it ( 'Should return error when password violates Password Policy and reset through ajax' , async done => {
const user = new Parse . User ( ) ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : async options => {
const response = await request ( {
url : options . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} ) ;
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2019-03-14 23:06:18 +02:00
const match = response . text . match ( re ) ;
if ( ! match ) {
fail ( 'should have a token' ) ;
return ;
}
const token = match [ 1 ] ;
try {
await request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=xuser12&token= ${ token } ` ,
2019-03-14 23:06:18 +02:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
'X-Requested-With' : 'XMLHttpRequest' ,
} ,
followRedirects : false ,
} ) ;
} catch ( error ) {
expect ( error . status ) . not . toBe ( 302 ) ;
expect ( error . text ) . toEqual (
'{"code":-1,"error":"Password cannot contain your username."}'
) ;
}
await Parse . User . logIn ( 'user1' , 'r@nd0m' ) ;
done ( ) ;
} ,
sendMail : ( ) => { } ,
} ;
await reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
emailAdapter : emailAdapter ,
passwordPolicy : {
doNotAllowUsername : true ,
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
user . setUsername ( 'user1' ) ;
user . setPassword ( 'r@nd0m' ) ;
user . set ( 'email' , 'user1@parse.com' ) ;
await user . signUp ( ) ;
await Parse . User . requestPasswordReset ( 'user1@parse.com' ) ;
} ) ;
2016-11-17 22:07:51 +05:30
it ( 'should reset password even if the new password contains user name while the policy allows' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
const emailAdapter = {
2016-11-17 22:07:51 +05:30
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
2018-09-24 17:07:51 -04:00
request ( {
url : options . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
const match = response . text . match ( re ) ;
2018-09-01 13:58:06 -04:00
if ( ! match ) {
fail ( 'should have a token' ) ;
2016-11-17 22:07:51 +05:30
done ( ) ;
2018-09-01 13:58:06 -04:00
return ;
}
const token = match [ 1 ] ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=uuser11&token= ${ token } ` ,
2018-09-24 17:07:51 -04:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2025-03-02 12:32:43 +11:00
'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html'
2018-09-01 13:58:06 -04:00
) ;
2016-11-17 22:07:51 +05:30
2018-09-01 13:58:06 -04:00
Parse . User . logIn ( 'user1' , 'uuser11' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'should login with new password' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Failed to POST request password reset' ) ;
} ) ;
} )
. catch ( error => {
2016-11-17 22:07:51 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Failed to get the reset link' ) ;
2016-11-17 22:07:51 +05:30
} ) ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
2016-11-17 22:07:51 +05:30
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
emailAdapter : emailAdapter ,
passwordPolicy : {
validatorPattern : /[0-9]+/ ,
2018-09-01 13:58:06 -04:00
doNotAllowUsername : false ,
2016-11-17 22:07:51 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
user . setUsername ( 'user1' ) ;
user . setPassword ( 'has 1 digit' ) ;
user . set ( 'email' , 'user1@parse.com' ) ;
user . signUp ( ) . then ( ( ) => {
Parse . User . requestPasswordReset ( 'user1@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
2016-11-21 21:16:38 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'signUp should not fail' ) ;
done ( ) ;
2016-11-21 21:16:38 +05:30
} ) ;
} ) ;
it ( 'should fail if passwordPolicy.maxPasswordAge is not a number' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordAge : 'not a number' ,
2016-11-21 21:16:38 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.maxPasswordAge "not a number" test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.maxPasswordAge must be a positive number' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-21 21:16:38 +05:30
} ) ;
it ( 'should fail if passwordPolicy.maxPasswordAge is a negative number' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordAge : - 100 ,
2016-11-21 21:16:38 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.maxPasswordAge negative number test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.maxPasswordAge must be a positive number' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-21 21:16:38 +05:30
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'd7d0a93e-efe6-48c0-b622-0f7fb570ccc1' ) ( it ) ( 'should succeed if logged in before password expires' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordAge : 1 , // 1 day
2016-11-21 21:16:38 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-21 21:16:38 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-21 21:16:38 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . logIn ( 'user1' , 'user1' )
. then ( ( ) => {
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Login should have succeeded before password expiry.' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Signup failed.' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;
2016-11-21 21:16:38 +05:30
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( '22428408-8763-445d-9833-2b2d92008f62' ) ( it ) ( 'should fail if logged in after password expires' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordAge : 0.5 / ( 24 * 60 * 60 ) , // 0.5 sec
2016-11-21 21:16:38 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-21 21:16:38 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-21 21:16:38 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
// wait for a bit more than the validity duration set
setTimeout ( ( ) => {
Parse . User . logIn ( 'user1' , 'user1' )
. then ( ( ) => {
fail ( 'logIn should have failed' ) ;
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . OBJECT _NOT _FOUND ) ;
expect ( error . message ) . toEqual (
'Your password has expired. Please reset your password.'
) ;
done ( ) ;
} ) ;
} , 1000 ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Signup failed.' ) ;
done ( ) ;
} ) ;
2016-11-21 21:16:38 +05:30
} ) ;
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'cc97a109-e35f-4f94-b942-3a6134921cdd' ) ( it ) ( 'should apply password expiry policy to existing user upon first login after policy is enabled' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-21 21:16:38 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-21 21:16:38 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
Parse . User . logOut ( )
. then ( ( ) => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
maxPasswordAge : 0.5 / ( 24 * 60 * 60 ) , // 0.5 sec
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) . then ( ( ) => {
Parse . User . logIn ( 'user1' , 'user1' )
. then ( ( ) => {
Parse . User . logOut ( )
. then ( ( ) => {
// wait for a bit more than the validity duration set
setTimeout ( ( ) => {
Parse . User . logIn ( 'user1' , 'user1' )
. then ( ( ) => {
fail ( 'logIn should have failed' ) ;
done ( ) ;
} )
. catch ( error => {
2020-10-25 15:06:58 -05:00
expect ( error . code ) . toEqual ( Parse . Error . OBJECT _NOT _FOUND ) ;
2018-09-01 13:58:06 -04:00
expect ( error . message ) . toEqual (
'Your password has expired. Please reset your password.'
) ;
done ( ) ;
} ) ;
} , 2000 ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'logout should have succeeded' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Login failed.' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'logout should have succeeded' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Signup failed.' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
} ) ;
} ) ;
} ) ;
2024-08-13 22:13:19 +02:00
it _id ( 'd1e6ab9d-c091-4fea-b952-08b7484bfc89' ) ( it ) ( 'should reset password timestamp when password is reset' , done => {
2016-11-21 21:16:38 +05:30
const user = new Parse . User ( ) ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
2018-09-24 17:07:51 -04:00
request ( {
url : options . link ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
const match = response . text . match ( re ) ;
2018-09-01 13:58:06 -04:00
if ( ! match ) {
fail ( 'should have a token' ) ;
2016-11-21 21:16:38 +05:30
done ( ) ;
2018-09-01 13:58:06 -04:00
return ;
}
const token = match [ 1 ] ;
2018-09-24 17:07:51 -04:00
request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=uuser11&token= ${ token } ` ,
2018-09-24 17:07:51 -04:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2025-03-02 12:32:43 +11:00
'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html'
2018-09-01 13:58:06 -04:00
) ;
Parse . User . logIn ( 'user1' , 'uuser11' )
2020-10-25 15:06:58 -05:00
. then ( function ( ) {
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( err => {
jfail ( err ) ;
fail ( 'should login with new password' ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Failed to POST request password reset' ) ;
} ) ;
} )
. catch ( error => {
2016-11-21 21:16:38 +05:30
jfail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Failed to get the reset link' ) ;
2016-11-21 21:16:38 +05:30
} ) ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-21 21:16:38 +05:30
} ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
emailAdapter : emailAdapter ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordAge : 0.5 / ( 24 * 60 * 60 ) , // 0.5 sec
2016-11-21 21:16:38 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-21 21:16:38 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-21 21:16:38 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
// wait for a bit more than the validity duration set
setTimeout ( ( ) => {
Parse . User . logIn ( 'user1' , 'user1' )
. then ( ( ) => {
fail ( 'logIn should have failed' ) ;
done ( ) ;
} )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . OBJECT _NOT _FOUND ) ;
expect ( error . message ) . toEqual (
'Your password has expired. Please reset your password.'
) ;
2020-10-25 15:06:58 -05:00
Parse . User . requestPasswordReset ( 'user1@parse.com' ) . catch ( err => {
jfail ( err ) ;
fail ( 'Reset password request should not fail' ) ;
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;
} , 1000 ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'Signup failed.' ) ;
done ( ) ;
} ) ;
2016-11-17 22:07:51 +05:30
} ) ;
} ) ;
2016-11-29 22:31:52 +05:30
it ( 'should fail if passwordPolicy.maxPasswordHistory is not a number' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : 'not a number' ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.maxPasswordHistory "not a number" test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
it ( 'should fail if passwordPolicy.maxPasswordHistory is a negative number' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : - 10 ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.maxPasswordHistory negative number test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
it ( 'should fail if passwordPolicy.maxPasswordHistory is greater than 20' , done => {
reconfigureServer ( {
appName : 'passwordPolicy' ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : 21 ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
} )
. then ( ( ) => {
fail ( 'passwordPolicy.maxPasswordHistory negative number test failed' ) ;
done ( ) ;
} )
. catch ( err => {
2020-10-25 15:06:58 -05:00
expect ( err ) . toEqual ( 'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
it ( 'should fail to reset if the new password is same as the last password' , done => {
const user = new Parse . User ( ) ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
2018-09-24 17:07:51 -04:00
request ( {
url : options . link ,
followRedirects : false ,
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
2025-03-02 12:32:43 +11:00
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/ ;
2018-09-24 17:07:51 -04:00
const match = response . text . match ( re ) ;
2018-09-01 13:58:06 -04:00
if ( ! match ) {
fail ( 'should have a token' ) ;
return Promise . reject ( 'Invalid password link' ) ;
}
return Promise . resolve ( match [ 1 ] ) ; // token
} )
. then ( token => {
2018-09-24 17:07:51 -04:00
return request ( {
method : 'POST' ,
url : 'http://localhost:8378/1/apps/test/request_password_reset' ,
2025-03-02 12:32:43 +11:00
body : ` new_password=user1&token= ${ token } ` ,
2018-09-24 17:07:51 -04:00
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
followRedirects : false ,
simple : false ,
resolveWithFullResponse : true ,
} ) . then ( response => {
return [ response , token ] ;
2016-11-29 22:31:52 +05:30
} ) ;
2018-09-01 13:58:06 -04:00
} )
. then ( data => {
const response = data [ 0 ] ;
const token = data [ 1 ] ;
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
2025-03-02 12:32:43 +11:00
` Found. Redirecting to http://localhost:8378/1/apps/choose_password?token= ${ token } &id=test&error=New%20password%20should%20not%20be%20the%20same%20as%20last%201%20passwords.&app=passwordPolicy `
2018-09-01 13:58:06 -04:00
) ;
done ( ) ;
return Promise . resolve ( ) ;
} )
. catch ( error => {
2018-09-24 17:07:51 -04:00
fail ( error ) ;
2018-09-01 13:58:06 -04:00
fail ( 'Repeat password test failed' ) ;
done ( ) ;
2016-11-29 22:31:52 +05:30
} ) ;
} ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-11-29 22:31:52 +05:30
} ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
emailAdapter : emailAdapter ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : 1 ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-29 22:31:52 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-29 22:31:52 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
return Parse . User . logOut ( ) ;
} )
. then ( ( ) => {
return Parse . User . requestPasswordReset ( 'user1@parse.com' ) ;
} )
. catch ( error => {
jfail ( error ) ;
fail ( 'SignUp or reset request failed' ) ;
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
} ) ;
it ( 'should fail if the new password is same as the previous one' , done => {
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : 5 ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-29 22:31:52 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-29 22:31:52 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
// try to set the same password as the previous one
user . setPassword ( 'user1' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'should have failed because the new password is same as the old' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
2020-10-25 15:06:58 -05:00
expect ( error . message ) . toEqual ( 'New password should not be the same as last 5 passwords.' ) ;
2018-09-01 13:58:06 -04:00
expect ( error . code ) . toEqual ( Parse . Error . VALIDATION _ERROR ) ;
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
} ) ;
it ( 'should fail if the new password is same as the 5th oldest one and policy does not allow the previous 5' , done => {
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : 5 ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-29 22:31:52 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-29 22:31:52 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
// build history
user . setPassword ( 'user2' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user3' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user4' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user5' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
// set the same password as the initial one
user . setPassword ( 'user1' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'should have failed because the new password is same as the old' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} )
. catch ( error => {
2020-10-25 15:06:58 -05:00
expect ( error . message ) . toEqual ( 'New password should not be the same as last 5 passwords.' ) ;
2018-09-01 13:58:06 -04:00
expect ( error . code ) . toEqual ( Parse . Error . VALIDATION _ERROR ) ;
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
} ) ;
it ( 'should succeed if the new password is same as the 6th oldest one and policy does not allow only previous 5' , done => {
const user = new Parse . User ( ) ;
reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
passwordPolicy : {
2018-09-01 13:58:06 -04:00
maxPasswordHistory : 5 ,
2016-11-29 22:31:52 +05:30
} ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-11-29 22:31:52 +05:30
} ) . then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
2016-11-29 22:31:52 +05:30
user . set ( 'email' , 'user1@parse.com' ) ;
2018-09-01 13:58:06 -04:00
user
. signUp ( )
. then ( ( ) => {
// build history
user . setPassword ( 'user2' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user3' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user4' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user5' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
user . setPassword ( 'user6' ) ; // this pushes initial password out of history
return user . save ( ) ;
} )
. then ( ( ) => {
// set the same password as the initial one
user . setPassword ( 'user1' ) ;
return user . save ( ) ;
} )
. then ( ( ) => {
done ( ) ;
} )
. catch ( ( ) => {
2020-10-25 15:06:58 -05:00
fail ( 'should have succeeded because the new password is not in history' ) ;
2018-09-01 13:58:06 -04:00
done ( ) ;
} ) ;
2016-11-29 22:31:52 +05:30
} ) ;
} ) ;
2019-04-10 22:57:09 +05:45
it ( 'should not infinitely loop if maxPasswordHistory is 1 (#4918)' , async ( ) => {
2023-01-09 08:02:12 +11:00
const headers = {
'X-Parse-Application-Id' : 'test' ,
'X-Parse-Rest-API-Key' : 'test' ,
'X-Parse-Maintenance-Key' : 'test2' ,
'Content-Type' : 'application/json' ,
} ;
2019-04-10 22:57:09 +05:45
const user = new Parse . User ( ) ;
const query = new Parse . Query ( Parse . User ) ;
await reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : false ,
2023-01-09 08:02:12 +11:00
maintenanceKey : 'test2' ,
2019-04-10 22:57:09 +05:45
passwordPolicy : {
maxPasswordHistory : 1 ,
} ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
user . setUsername ( 'user1' ) ;
user . setPassword ( 'user1' ) ;
user . set ( 'email' , 'user1@parse.com' ) ;
await user . signUp ( ) ;
user . setPassword ( 'user2' ) ;
await user . save ( ) ;
2023-01-09 08:02:12 +11:00
const user1 = await query . get ( user . id , { useMasterKey : true } ) ;
expect ( user1 . get ( '_password_history' ) ) . toBeUndefined ( ) ;
const result1 = await request ( {
method : 'GET' ,
url : ` http://localhost:8378/1/classes/_User/ ${ user . id } ` ,
json : true ,
headers ,
} ) . then ( res => res . data ) ;
expect ( result1 . _password _history . length ) . toBe ( 1 ) ;
2019-04-10 22:57:09 +05:45
user . setPassword ( 'user3' ) ;
await user . save ( ) ;
2023-01-09 08:02:12 +11:00
const result2 = await request ( {
method : 'GET' ,
url : ` http://localhost:8378/1/classes/_User/ ${ user . id } ` ,
json : true ,
headers ,
} ) . then ( res => res . data ) ;
expect ( result2 . _password _history . length ) . toBe ( 1 ) ;
2019-04-10 22:57:09 +05:45
2023-01-09 08:02:12 +11:00
expect ( result1 . _password _history ) . not . toEqual ( result2 . _password _history ) ;
2019-04-10 22:57:09 +05:45
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;