* Added validationError(custom message) for Password requirement fail * Changed validationError from valodationError in README.md
1578 lines
48 KiB
JavaScript
1578 lines
48 KiB
JavaScript
'use strict';
|
|
|
|
const request = require('../lib/request');
|
|
|
|
describe('Password Policy: ', () => {
|
|
it('should show the invalid link page if the user clicks on the password reset link after the token expires', done => {
|
|
const user = new Parse.User();
|
|
let sendEmailOptions;
|
|
const emailAdapter = {
|
|
sendVerificationEmail: () => Promise.resolve(),
|
|
sendPasswordResetEmail: options => {
|
|
sendEmailOptions = options;
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
resetTokenValidityDuration: 0.5, // 0.5 second
|
|
},
|
|
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();
|
|
|
|
request({
|
|
url: sendEmailOptions.link,
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
'Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
fail(error);
|
|
});
|
|
}, 1000);
|
|
})
|
|
.catch(err => {
|
|
jfail(err);
|
|
done();
|
|
});
|
|
});
|
|
|
|
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;
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
resetTokenValidityDuration: 5, // 5 seconds
|
|
},
|
|
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();
|
|
|
|
request({
|
|
url: sendEmailOptions.link,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
followRedirects: false,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=[a-zA-Z0-9]+\&id=test\&username=testResetTokenValidity/;
|
|
expect(response.text.match(re)).not.toBe(null);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
fail(error);
|
|
});
|
|
}, 1000);
|
|
})
|
|
.catch(err => {
|
|
jfail(err);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.resetTokenValidityDuration is not a number', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
resetTokenValidityDuration: 'not a number',
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail(
|
|
'passwordPolicy.resetTokenValidityDuration "not a number" test failed'
|
|
);
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.resetTokenValidityDuration must be a positive number'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.resetTokenValidityDuration is zero or a negative number', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
resetTokenValidityDuration: 0,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('resetTokenValidityDuration negative number test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.resetTokenValidityDuration must be a positive number'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.validatorPattern setting is invalid type', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: 1234, // number is not a valid setting
|
|
},
|
|
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();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.validatorCallback setting is invalid type', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorCallback: 'abc', // string is not a valid setting
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.validatorCallback type test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.validatorCallback must be a function.'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password does not conform to the policy enforced using validatorPattern', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/, // password should contain at least one digit
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('nodigit');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail(
|
|
'Should have failed as password does not conform to the policy.'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.code).toEqual(142);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password does not conform to the policy enforced using validatorPattern string', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: '^.{8,}', // password should contain at least 8 char
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('less');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail(
|
|
'Should have failed as password does not conform to the policy.'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.code).toEqual(142);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password is empty', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: '^.{8,}', // password should contain at least 8 char
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail(
|
|
'Should have failed as password does not conform to the policy.'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.message).toEqual(
|
|
'Cannot sign up user with an empty password.'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should succeed if password conforms to the policy enforced using validatorPattern', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/, // password should contain at least one digit
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('1digit');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
Parse.User.logOut()
|
|
.then(() => {
|
|
Parse.User.logIn('user1', '1digit')
|
|
.then(function() {
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
jfail(err);
|
|
fail('Should be able to login');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('logout should have succeeded');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail(
|
|
'Signup should have succeeded as password conforms to the policy.'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should succeed if password conforms to the policy enforced using validatorPattern string', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: '[!@#$]+', // password should contain at least one special char
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('p@sswrod');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
Parse.User.logOut()
|
|
.then(() => {
|
|
Parse.User.logIn('user1', 'p@sswrod')
|
|
.then(function() {
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
jfail(err);
|
|
fail('Should be able to login');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('logout should have succeeded');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail(
|
|
'Signup should have succeeded as password conforms to the policy.'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password does not conform to the policy enforced using validatorCallback', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorCallback: () => false, // just fail
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('any');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail(
|
|
'Should have failed as password does not conform to the policy.'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.code).toEqual(142);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should succeed if password conforms to the policy enforced using validatorCallback', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorCallback: () => true, // never fail
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('oneUpper');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
Parse.User.logOut()
|
|
.then(() => {
|
|
Parse.User.logIn('user1', 'oneUpper')
|
|
.then(function() {
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
jfail(err);
|
|
fail('Should be able to login');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('Logout should have succeeded');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('Should have succeeded as password conforms to the policy.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password does not match validatorPattern but succeeds validatorCallback', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[A-Z]+/, // password should contain at least one UPPER case letter
|
|
validatorCallback: () => true,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('all lower');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail(
|
|
'Should have failed as password does not conform to the policy.'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.code).toEqual(142);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password matches validatorPattern but fails validatorCallback', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[A-Z]+/, // password should contain at least one UPPER case letter
|
|
validatorCallback: () => false,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('oneUpper');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail(
|
|
'Should have failed as password does not conform to the policy.'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.code).toEqual(142);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should succeed if password conforms to both validatorPattern and validatorCallback', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[A-Z]+/, // password should contain at least one digit
|
|
validatorCallback: () => true,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('oneUpper');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
Parse.User.logOut()
|
|
.then(() => {
|
|
Parse.User.logIn('user1', 'oneUpper')
|
|
.then(function() {
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
jfail(err);
|
|
fail('Should be able to login');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('logout should have succeeded');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('Should have succeeded as password conforms to the policy.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should reset password if new password conforms to password policy', done => {
|
|
const user = new Parse.User();
|
|
const emailAdapter = {
|
|
sendVerificationEmail: () => Promise.resolve(),
|
|
sendPasswordResetEmail: options => {
|
|
request({
|
|
url: options.link,
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
|
const match = response.text.match(re);
|
|
if (!match) {
|
|
fail('should have a token');
|
|
done();
|
|
return;
|
|
}
|
|
const token = match[1];
|
|
|
|
request({
|
|
method: 'POST',
|
|
url: 'http://localhost:8378/1/apps/test/request_password_reset',
|
|
body: `new_password=has2init&token=${token}&username=user1`,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1'
|
|
);
|
|
|
|
Parse.User.logIn('user1', 'has2init')
|
|
.then(function() {
|
|
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 => {
|
|
jfail(error);
|
|
fail('Failed to get the reset link');
|
|
done();
|
|
});
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
verifyUserEmails: false,
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/, // password should contain at least one digit
|
|
},
|
|
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();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('signUp should not fail');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fail to reset password if the new password does not conform to password policy', done => {
|
|
const user = new Parse.User();
|
|
const emailAdapter = {
|
|
sendVerificationEmail: () => Promise.resolve(),
|
|
sendPasswordResetEmail: options => {
|
|
request({
|
|
url: options.link,
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
|
const match = response.text.match(re);
|
|
if (!match) {
|
|
fail('should have a token');
|
|
done();
|
|
return;
|
|
}
|
|
const token = match[1];
|
|
|
|
request({
|
|
method: 'POST',
|
|
url: 'http://localhost:8378/1/apps/test/request_password_reset',
|
|
body: `new_password=hasnodigit&token=${token}&username=user1`,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20should%20contain%20at%20least%20one%20digit.&app=passwordPolicy`
|
|
);
|
|
|
|
Parse.User.logIn('user1', 'has 1 digit')
|
|
.then(function() {
|
|
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 => {
|
|
jfail(error);
|
|
fail('Failed to get the reset link');
|
|
done();
|
|
});
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
verifyUserEmails: false,
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/, // password should contain at least one digit
|
|
validationError: 'Password should contain at least one digit.',
|
|
},
|
|
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();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('signUp should not fail');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.doNotAllowUsername is not a boolean value', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
doNotAllowUsername: 'no',
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.doNotAllowUsername type test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.doNotAllowUsername must be a boolean value.'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('signup should fail if password contains the username and is not allowed by policy', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/,
|
|
doNotAllowUsername: true,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('@user11');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
fail('Should have failed as password contains username.');
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.code).toEqual(142);
|
|
expect(error.message).toEqual(
|
|
'Password cannot contain your username.'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should succeed if password does not contain the username and is not allowed by policy', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
doNotAllowUsername: true,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('r@nd0m');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
done();
|
|
})
|
|
.catch(() => {
|
|
fail('Should have succeeded as password does not contain username.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('signup should succeed if password contains the username and it is allowed by policy', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
done();
|
|
})
|
|
.catch(() => {
|
|
fail('Should have succeeded as policy allows username in password.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fail to reset password if the new password contains username and not allowed by password policy', done => {
|
|
const user = new Parse.User();
|
|
const emailAdapter = {
|
|
sendVerificationEmail: () => Promise.resolve(),
|
|
sendPasswordResetEmail: options => {
|
|
request({
|
|
url: options.link,
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
|
const match = response.text.match(re);
|
|
if (!match) {
|
|
fail('should have a token');
|
|
done();
|
|
return;
|
|
}
|
|
const token = match[1];
|
|
|
|
request({
|
|
method: 'POST',
|
|
url: 'http://localhost:8378/1/apps/test/request_password_reset',
|
|
body: `new_password=xuser12&token=${token}&username=user1`,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20cannot%20contain%20your%20username.&app=passwordPolicy`
|
|
);
|
|
|
|
Parse.User.logIn('user1', 'r@nd0m')
|
|
.then(function() {
|
|
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 => {
|
|
jfail(error);
|
|
fail('Failed to get the reset link');
|
|
done();
|
|
});
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
verifyUserEmails: false,
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
doNotAllowUsername: true,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('r@nd0m');
|
|
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();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('signUp should not fail');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should reset password even if the new password contains user name while the policy allows', done => {
|
|
const user = new Parse.User();
|
|
const emailAdapter = {
|
|
sendVerificationEmail: () => Promise.resolve(),
|
|
sendPasswordResetEmail: options => {
|
|
request({
|
|
url: options.link,
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
|
const match = response.text.match(re);
|
|
if (!match) {
|
|
fail('should have a token');
|
|
done();
|
|
return;
|
|
}
|
|
const token = match[1];
|
|
|
|
request({
|
|
method: 'POST',
|
|
url: 'http://localhost:8378/1/apps/test/request_password_reset',
|
|
body: `new_password=uuser11&token=${token}&username=user1`,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1'
|
|
);
|
|
|
|
Parse.User.logIn('user1', 'uuser11')
|
|
.then(function() {
|
|
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 => {
|
|
jfail(error);
|
|
fail('Failed to get the reset link');
|
|
});
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
verifyUserEmails: false,
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
validatorPattern: /[0-9]+/,
|
|
doNotAllowUsername: false,
|
|
},
|
|
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();
|
|
});
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('signUp should not fail');
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.maxPasswordAge is not a number', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordAge: 'not a number',
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.maxPasswordAge "not a number" test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.maxPasswordAge must be a positive number'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.maxPasswordAge is a negative number', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordAge: -100,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.maxPasswordAge negative number test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.maxPasswordAge must be a positive number'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should succeed if logged in before password expires', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordAge: 1, // 1 day
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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 => {
|
|
jfail(error);
|
|
fail('Signup failed.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fail if logged in after password expires', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordAge: 0.5 / (24 * 60 * 60), // 0.5 sec
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should apply password expiry policy to existing user upon first login after policy is enabled', done => {
|
|
const user = new Parse.User();
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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 => {
|
|
expect(error.code).toEqual(
|
|
Parse.Error.OBJECT_NOT_FOUND
|
|
);
|
|
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.');
|
|
done();
|
|
});
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('logout should have succeeded');
|
|
done();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('Signup failed.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should reset password timestamp when password is reset', done => {
|
|
const user = new Parse.User();
|
|
const emailAdapter = {
|
|
sendVerificationEmail: () => Promise.resolve(),
|
|
sendPasswordResetEmail: options => {
|
|
request({
|
|
url: options.link,
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
|
const match = response.text.match(re);
|
|
if (!match) {
|
|
fail('should have a token');
|
|
done();
|
|
return;
|
|
}
|
|
const token = match[1];
|
|
|
|
request({
|
|
method: 'POST',
|
|
url: 'http://localhost:8378/1/apps/test/request_password_reset',
|
|
body: `new_password=uuser11&token=${token}&username=user1`,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1'
|
|
);
|
|
|
|
Parse.User.logIn('user1', 'uuser11')
|
|
.then(function() {
|
|
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 => {
|
|
jfail(error);
|
|
fail('Failed to get the reset link');
|
|
});
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
maxPasswordAge: 0.5 / (24 * 60 * 60), // 0.5 sec
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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.'
|
|
);
|
|
Parse.User.requestPasswordReset('user1@parse.com').catch(
|
|
err => {
|
|
jfail(err);
|
|
fail('Reset password request should not fail');
|
|
done();
|
|
}
|
|
);
|
|
});
|
|
}, 1000);
|
|
})
|
|
.catch(error => {
|
|
jfail(error);
|
|
fail('Signup failed.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.maxPasswordHistory is not a number', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordHistory: 'not a number',
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.maxPasswordHistory "not a number" test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.maxPasswordHistory is a negative number', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordHistory: -10,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.maxPasswordHistory negative number test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail if passwordPolicy.maxPasswordHistory is greater than 20', done => {
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
passwordPolicy: {
|
|
maxPasswordHistory: 21,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
})
|
|
.then(() => {
|
|
fail('passwordPolicy.maxPasswordHistory negative number test failed');
|
|
done();
|
|
})
|
|
.catch(err => {
|
|
expect(err).toEqual(
|
|
'passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
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 => {
|
|
request({
|
|
url: options.link,
|
|
followRedirects: false,
|
|
})
|
|
.then(response => {
|
|
expect(response.status).toEqual(302);
|
|
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
|
const match = response.text.match(re);
|
|
if (!match) {
|
|
fail('should have a token');
|
|
return Promise.reject('Invalid password link');
|
|
}
|
|
return Promise.resolve(match[1]); // token
|
|
})
|
|
.then(token => {
|
|
return request({
|
|
method: 'POST',
|
|
url: 'http://localhost:8378/1/apps/test/request_password_reset',
|
|
body: `new_password=user1&token=${token}&username=user1`,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
followRedirects: false,
|
|
simple: false,
|
|
resolveWithFullResponse: true,
|
|
}).then(response => {
|
|
return [response, token];
|
|
});
|
|
})
|
|
.then(data => {
|
|
const response = data[0];
|
|
const token = data[1];
|
|
expect(response.status).toEqual(302);
|
|
expect(response.text).toEqual(
|
|
`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=New%20password%20should%20not%20be%20the%20same%20as%20last%201%20passwords.&app=passwordPolicy`
|
|
);
|
|
done();
|
|
return Promise.resolve();
|
|
})
|
|
.catch(error => {
|
|
fail(error);
|
|
fail('Repeat password test failed');
|
|
done();
|
|
});
|
|
},
|
|
sendMail: () => {},
|
|
};
|
|
reconfigureServer({
|
|
appName: 'passwordPolicy',
|
|
verifyUserEmails: false,
|
|
emailAdapter: emailAdapter,
|
|
passwordPolicy: {
|
|
maxPasswordHistory: 1,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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();
|
|
});
|
|
});
|
|
});
|
|
|
|
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: {
|
|
maxPasswordHistory: 5,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
user
|
|
.signUp()
|
|
.then(() => {
|
|
// try to set the same password as the previous one
|
|
user.setPassword('user1');
|
|
return user.save();
|
|
})
|
|
.then(() => {
|
|
fail(
|
|
'should have failed because the new password is same as the old'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.message).toEqual(
|
|
'New password should not be the same as last 5 passwords.'
|
|
);
|
|
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
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: {
|
|
maxPasswordHistory: 5,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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(() => {
|
|
fail(
|
|
'should have failed because the new password is same as the old'
|
|
);
|
|
done();
|
|
})
|
|
.catch(error => {
|
|
expect(error.message).toEqual(
|
|
'New password should not be the same as last 5 passwords.'
|
|
);
|
|
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
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: {
|
|
maxPasswordHistory: 5,
|
|
},
|
|
publicServerURL: 'http://localhost:8378/1',
|
|
}).then(() => {
|
|
user.setUsername('user1');
|
|
user.setPassword('user1');
|
|
user.set('email', 'user1@parse.com');
|
|
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(() => {
|
|
fail(
|
|
'should have succeeded because the new password is not in history'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|