mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Don't send plaintext reset passwords via email (#8457)
* start work to avoid sending reset password in plaintext via email * start checking parameters * fix new password reset email * render error if password reset code is missing or invalid * implement POST route, conversion to bcrypt and messages * add auth.local.passwordResetCode field * add failing tests, move reset code validation func to lib, fixes, remove old tests * fix unit tests * fix page rendering and add integration tests * fix password reset page * add integration test * fix string * fix tests url
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import {
|
||||
encrypt,
|
||||
} from '../../../../../website/server/libs/encryption';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
generateUser,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
import {
|
||||
sha1Encrypt as sha1EncryptPassword,
|
||||
sha1MakeSalt,
|
||||
@@ -7,6 +14,7 @@ import {
|
||||
bcryptCompare,
|
||||
compare,
|
||||
convertToBcrypt,
|
||||
validatePasswordResetCodeAndFindUser,
|
||||
} from '../../../../../website/server/libs/password';
|
||||
|
||||
describe('Password Utilities', () => {
|
||||
@@ -172,6 +180,95 @@ describe('Password Utilities', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('validatePasswordResetCodeAndFindUser', () => {
|
||||
it('returns false if the code is missing', async () => {
|
||||
let res = await validatePasswordResetCodeAndFindUser();
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns false if the code is invalid json', async () => {
|
||||
let res = await validatePasswordResetCodeAndFindUser('invalid json');
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns false if the code cannot be decrypted', async () => {
|
||||
let user = await generateUser();
|
||||
let res = await validatePasswordResetCodeAndFindUser(JSON.stringify({ // not encrypted
|
||||
userId: user._id,
|
||||
expiresAt: new Date(),
|
||||
}));
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns false if the code is expired', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
let code = encrypt(JSON.stringify({
|
||||
userId: user._id,
|
||||
expiresAt: moment().subtract({minutes: 1}),
|
||||
}));
|
||||
|
||||
await user.update({
|
||||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
let res = await validatePasswordResetCodeAndFindUser(code);
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns false if the user does not exist', async () => {
|
||||
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
||||
userId: Date.now().toString(),
|
||||
expiresAt: moment().add({days: 1}),
|
||||
})));
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns false if the user has no local auth', async () => {
|
||||
let user = await generateUser({
|
||||
auth: 'not an object with valid fields',
|
||||
});
|
||||
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
||||
userId: user._id,
|
||||
expiresAt: moment().add({days: 1}),
|
||||
})));
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns false if the code doesn\'t match the one saved at user.auth.passwordResetCode', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
let code = encrypt(JSON.stringify({
|
||||
userId: user._id,
|
||||
expiresAt: moment().add({days: 1}),
|
||||
}));
|
||||
|
||||
await user.update({
|
||||
'auth.local.passwordResetCode': 'invalid',
|
||||
});
|
||||
|
||||
let res = await validatePasswordResetCodeAndFindUser(code);
|
||||
expect(res).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns the user if the password reset code is valid', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
let code = encrypt(JSON.stringify({
|
||||
userId: user._id,
|
||||
expiresAt: moment().add({days: 1}),
|
||||
}));
|
||||
|
||||
await user.update({
|
||||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
let res = await validatePasswordResetCodeAndFindUser(code);
|
||||
expect(res).not.to.equal(false);
|
||||
expect(res._id).to.equal(user._id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bcrypt', () => {
|
||||
describe('Hash', () => {
|
||||
it('returns a hashed string', async () => {
|
||||
|
||||
Reference in New Issue
Block a user