mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-07 22:45:46 +01:00
fix: #8991, logout on password reset, dont verify email if password expired
dont allow same password on reset
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
"username-too-long": "Username too long",
|
||||
"password-too-long": "Password too long",
|
||||
"reset-rate-limited": "Too many password reset requests (rate limited)",
|
||||
"reset-same-password": "Please use a password that is different from your current one",
|
||||
|
||||
"user-banned": "User banned",
|
||||
"user-banned-reason": "Sorry, this account has been banned (Reason: %1)",
|
||||
|
||||
@@ -180,8 +180,9 @@ app.cacheBuster = null;
|
||||
message = message.message || message;
|
||||
|
||||
if (message === '[[error:invalid-session]]') {
|
||||
app.handleInvalidSession();
|
||||
app.logout(false);
|
||||
return app.handleInvalidSession();
|
||||
return;
|
||||
}
|
||||
|
||||
app.alert({
|
||||
|
||||
@@ -69,6 +69,9 @@ socket = window.socket;
|
||||
});
|
||||
|
||||
socket.on('event:banned', onEventBanned);
|
||||
socket.on('event:logout', function () {
|
||||
app.logout();
|
||||
});
|
||||
socket.on('event:alert', function (params) {
|
||||
app.alert(params);
|
||||
});
|
||||
|
||||
@@ -120,6 +120,7 @@ User.forcePasswordReset = async function (socket, uids) {
|
||||
|
||||
await db.setObjectField(uids.map(uid => 'user:' + uid), 'passwordExpiry', Date.now());
|
||||
await user.auth.revokeAllSessions(uids);
|
||||
uids.forEach(uid => sockets.in('uid_' + uid).emit('event:logout'));
|
||||
};
|
||||
|
||||
User.deleteUsers = async function (socket, uids) {
|
||||
|
||||
@@ -11,6 +11,7 @@ const batch = require('../batch');
|
||||
const db = require('../database');
|
||||
const meta = require('../meta');
|
||||
const emailer = require('../emailer');
|
||||
const Password = require('../password');
|
||||
|
||||
const UserReset = module.exports;
|
||||
|
||||
@@ -67,12 +68,28 @@ UserReset.commit = async function (code, password) {
|
||||
if (!uid) {
|
||||
throw new Error('[[error:reset-code-not-valid]]');
|
||||
}
|
||||
|
||||
const userData = await db.getObjectFields(
|
||||
'user:' + uid,
|
||||
['password', 'passwordExpiry', 'password:shaWrapped']
|
||||
);
|
||||
const ok = await Password.compare(password, userData.password, !!parseInt(userData['password:shaWrapped'], 10));
|
||||
if (ok) {
|
||||
throw new Error('[[error:reset-same-password]]');
|
||||
}
|
||||
const hash = await user.hashPassword(password);
|
||||
const data = {
|
||||
password: hash,
|
||||
'password:shaWrapped': 1,
|
||||
};
|
||||
|
||||
await user.setUserFields(uid, { password: hash, 'email:confirmed': 1, 'password:shaWrapped': 1 });
|
||||
// don't verify email if password reset is due to expiry
|
||||
const isPasswordExpired = userData.passwordExpiry && userData.passwordExpiry < Date.now();
|
||||
if (!isPasswordExpired) {
|
||||
data['email:confirmed'] = 1;
|
||||
await groups.join('verified-users', uid);
|
||||
await groups.leave('unverified-users', uid);
|
||||
}
|
||||
await user.setUserFields(uid, data);
|
||||
await db.deleteObjectField('reset:uid', code);
|
||||
await db.sortedSetRemoveBulk([
|
||||
['reset:issueDate', code],
|
||||
|
||||
29
test/user.js
29
test/user.js
@@ -628,6 +628,35 @@ describe('User', function () {
|
||||
},
|
||||
], done);
|
||||
});
|
||||
|
||||
it('.should error if same password is used for reset', async function () {
|
||||
const uid = await User.create({ username: 'badmemory', email: 'bad@memory.com', password: '123456' });
|
||||
const code = await User.reset.generate(uid);
|
||||
let err;
|
||||
try {
|
||||
await User.reset.commit(code, '123456');
|
||||
} catch (_err) {
|
||||
err = _err;
|
||||
}
|
||||
assert.strictEqual(err.message, '[[error:reset-same-password]]');
|
||||
});
|
||||
|
||||
it('should not validate email if password reset is due to expiry', async function () {
|
||||
const uid = await User.create({ username: 'resetexpiry', email: 'reset@expiry.com', password: '123456' });
|
||||
let confirmed = await User.getUserField(uid, 'email:confirmed');
|
||||
let [verified, unverified] = await groups.isMemberOfGroups(uid, ['verified-users', 'unverified-users']);
|
||||
assert.strictEqual(confirmed, 0);
|
||||
assert.strictEqual(verified, false);
|
||||
assert.strictEqual(unverified, true);
|
||||
await User.setUserField(uid, 'passwordExpiry', Date.now());
|
||||
const code = await User.reset.generate(uid);
|
||||
await User.reset.commit(code, '654321');
|
||||
confirmed = await User.getUserField(uid, 'email:confirmed');
|
||||
[verified, unverified] = await groups.isMemberOfGroups(uid, ['verified-users', 'unverified-users']);
|
||||
assert.strictEqual(confirmed, 0);
|
||||
assert.strictEqual(verified, false);
|
||||
assert.strictEqual(unverified, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hash methods', function () {
|
||||
|
||||
Reference in New Issue
Block a user