From b6a5419ca11c616c1837420264473b9d131987b1 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 27 Jul 2018 11:54:23 -0400 Subject: [PATCH] closes #6674 --- src/controllers/authentication.js | 7 ++----- src/socket.io/user.js | 14 +++----------- src/socket.io/user/profile.js | 30 +++++++++++++++++------------- src/user/auth.js | 1 + src/user/password.js | 12 +++++++----- src/user/profile.js | 4 ++-- 6 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index d1a4ad9bca..739632b6c4 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -419,16 +419,13 @@ authenticationController.localLogin = function (req, username, password, next) { return getBanInfo(uid, next); } - user.auth.logAttempt(uid, req.ip, next); - }, - function (next) { - user.isPasswordCorrect(uid, password, next); + user.isPasswordCorrect(uid, password, req.ip, next); }, function (passwordMatch, next) { if (!passwordMatch) { return next(new Error('[[error:invalid-login-credentials]]')); } - user.auth.clearLoginAttempts(uid); + next(null, userData, '[[success:authentication-successful]]'); }, ], next); diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 5401ccca44..2df4cfa612 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -37,8 +37,8 @@ SocketUser.deleteAccount = function (socket, data, callback) { async.waterfall([ function (next) { - user.isPasswordCorrect(socket.uid, data.password, function (err, ok) { - next(err || !ok ? new Error('[[error:invalid-password]]') : undefined); + user.isPasswordCorrect(socket.uid, data.password, socket.ip, function (err, ok) { + next(err || (!ok ? new Error('[[error:invalid-password]]') : undefined)); }); }, function (next) { @@ -61,15 +61,7 @@ SocketUser.deleteAccount = function (socket, data, callback) { }); next(); }, - ], function (err) { - if (err) { - return setTimeout(function () { - callback(err); - }, 2500); - } - - callback(); - }); + ], callback); }; SocketUser.emailExists = function (socket, data, callback) { diff --git a/src/socket.io/user/profile.js b/src/socket.io/user/profile.js index 6cf76be9ee..036a22c366 100644 --- a/src/socket.io/user/profile.js +++ b/src/socket.io/user/profile.js @@ -15,7 +15,7 @@ module.exports = function (SocketUser) { async.waterfall([ function (next) { - isPrivilegedOrSelfAndPasswordMatch(socket.uid, data, next); + isPrivilegedOrSelfAndPasswordMatch(socket, data, next); }, function (next) { SocketUser.updateProfile(socket, data, next); @@ -72,26 +72,19 @@ module.exports = function (SocketUser) { ], callback); }; - function isPrivilegedOrSelfAndPasswordMatch(uid, data, callback) { + function isPrivilegedOrSelfAndPasswordMatch(socket, data, callback) { + const uid = socket.uid; + const isSelf = parseInt(uid, 10) === parseInt(data.uid, 10); + async.waterfall([ function (next) { async.parallel({ isAdmin: async.apply(user.isAdministrator, uid), isTargetAdmin: async.apply(user.isAdministrator, data.uid), isGlobalMod: async.apply(user.isGlobalModerator, uid), - hasPassword: async.apply(user.hasPassword, data.uid), - passwordMatch: function (next) { - if (data.password) { - user.isPasswordCorrect(data.uid, data.password, next); - } else { - next(null, false); - } - }, }, next); }, function (results, next) { - var isSelf = parseInt(uid, 10) === parseInt(data.uid, 10); - if (results.isTargetAdmin && !results.isAdmin) { return next(new Error('[[error:no-privileges]]')); } @@ -100,6 +93,17 @@ module.exports = function (SocketUser) { return next(new Error('[[error:no-privileges]]')); } + async.parallel({ + hasPassword: async.apply(user.hasPassword, data.uid), + passwordMatch: function (next) { + if (data.password) { + user.isPasswordCorrect(data.uid, data.password, socket.ip, next); + } else { + next(null, false); + } + }, + }, next); + }, function (results, next) { if (isSelf && results.hasPassword && !results.passwordMatch) { return next(new Error('[[error:invalid-password]]')); } @@ -119,7 +123,7 @@ module.exports = function (SocketUser) { } async.waterfall([ function (next) { - user.changePassword(socket.uid, data, next); + user.changePassword(socket.uid, Object.assign(data, { ip: socket.ip }), next); }, function (next) { events.log({ diff --git a/src/user/auth.js b/src/user/auth.js index 195e14ce50..ae4d8ab4f8 100644 --- a/src/user/auth.js +++ b/src/user/auth.js @@ -13,6 +13,7 @@ module.exports = function (User) { User.auth = {}; User.auth.logAttempt = function (uid, ip, callback) { + console.log('attempt logged'); if (!parseInt(uid, 10)) { return setImmediate(callback); } diff --git a/src/user/password.js b/src/user/password.js index bf39d029d0..b5b884774d 100644 --- a/src/user/password.js +++ b/src/user/password.js @@ -15,7 +15,7 @@ module.exports = function (User) { Password.hash(nconf.get('bcrypt_rounds') || 12, password, callback); }; - User.isPasswordCorrect = function (uid, password, callback) { + User.isPasswordCorrect = function (uid, password, ip, callback) { password = password || ''; var hashedPassword; async.waterfall([ @@ -30,6 +30,7 @@ module.exports = function (User) { User.isPasswordValid(password, 0, next); }, + async.apply(User.auth.logAttempt, uid, ip), function (next) { Password.compare(password, hashedPassword, next); }, @@ -38,10 +39,11 @@ module.exports = function (User) { return callback(err); } - // Delay return for incorrect current password - setTimeout(function () { - callback(null, ok); - }, ok ? 0 : 2500); + if (ok) { + User.auth.clearLoginAttempts(uid); + } + + callback(null, ok); }); }; diff --git a/src/user/profile.js b/src/user/profile.js index 2849fbde1a..cc55728d93 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -324,12 +324,12 @@ module.exports = function (User) { if (parseInt(uid, 10) !== parseInt(data.uid, 10)) { User.isAdministrator(uid, next); } else { - User.isPasswordCorrect(uid, data.currentPassword, next); + User.isPasswordCorrect(uid, data.currentPassword, data.ip, next); } }, function (isAdminOrPasswordMatch, next) { if (!isAdminOrPasswordMatch) { - return next(new Error('[[error:change_password_error_wrong_current]]')); + return next(new Error('[[user:change_password_error_wrong_current]]')); } User.hashPassword(data.newPassword, next);