diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index c34b0acd0a..bb575a3c76 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -334,10 +334,13 @@ authenticationController.localLogin = function(req, username, password, next) { function (next) { async.parallel({ userData: function(next) { - db.getObjectFields('user:' + uid, ['password', 'banned', 'passwordExpiry'], next); + db.getObjectFields('user:' + uid, ['password', 'passwordExpiry'], next); }, isAdmin: function(next) { user.isAdministrator(uid, next); + }, + banned: function(next) { + user.isBanned(uid, next); } }, next); }, @@ -349,13 +352,13 @@ authenticationController.localLogin = function(req, username, password, next) { if (!result.isAdmin && parseInt(meta.config.allowLocalLogin, 10) === 0) { return next(new Error('[[error:local-login-disabled]]')); } - if (!userData || !userData.password) { return next(new Error('[[error:invalid-user-data]]')); } - if (userData.banned && parseInt(userData.banned, 10) === 1) { + if (result.banned) { return next(new Error('[[error:user-banned]]')); } + Password.compare(password, userData.password, next); }, function (passwordMatch, next) { diff --git a/src/socket.io/user/ban.js b/src/socket.io/user/ban.js index a8a67b17b0..d52251d76d 100644 --- a/src/socket.io/user/ban.js +++ b/src/socket.io/user/ban.js @@ -7,17 +7,20 @@ var events = require('../../events'); module.exports = function(SocketUser) { - SocketUser.banUsers = function(socket, uids, until, callback) { - if (!callback && typeof until === 'function') { - callback = until; - until = 0; + SocketUser.banUsers = function(socket, data, callback) { + // Backwards compatibility + if (Array.isArray(data)) { + data = { + uids: data, + until: 0 + } } - toggleBan(socket.uid, uids, SocketUser.banUser, function(err) { + toggleBan(socket.uid, data.uids, banUser.bind(null, data.until || 0), function(err) { if (err) { return callback(err); } - async.each(uids, function(uid, next) { + async.each(data.uids, function(uid, next) { events.log({ type: 'user-ban', uid: socket.uid, @@ -50,7 +53,7 @@ module.exports = function(SocketUser) { ], callback); } - SocketUser.banUser = function(uid, until, callback) { + function banUser(until, uid, callback) { async.waterfall([ function (next) { user.isAdministrator(uid, next); diff --git a/src/user.js b/src/user.js index 50df737bc7..3303d04e79 100644 --- a/src/user.js +++ b/src/user.js @@ -256,6 +256,35 @@ var utils = require('../public/src/utils'); }); }; + User.isBanned = function(uid, callback) { + async.waterfall([ + async.apply(User.getUserField, uid, 'banned'), + function(banned, next) { + banned = parseInt(banned, 10) === 1; + if (!banned) { + return next(null, banned); + } else { + // If they are banned, see if the ban has expired + db.sortedSetScore('users:banned:expire', uid, function(err, score) { + var stillBanned = Date.now() < score; + + if (!stillBanned) { + async.parallel([ + async.apply(db.sortedSetRemove.bind(db), 'users:banned:expire', uid), + async.apply(db.sortedSetRemove.bind(db), 'users:banned', uid), + async.apply(User.setUserField, uid, 'banned', 0) + ], function(err) { + next(err, false); + }); + } else { + next(err, true); + } + }); + } + } + ], callback); + }; + User.addInterstitials = function(callback) { plugins.registerHook('core', { hook: 'filter:register.interstitial', diff --git a/src/user/admin.js b/src/user/admin.js index 402c8c57a9..c402eb7e7a 100644 --- a/src/user/admin.js +++ b/src/user/admin.js @@ -71,6 +71,8 @@ module.exports = function(User) { if (until > 0 && Date.now() < until) { tasks.push(async.apply(db.sortedSetAdd, 'users:banned:expire', until, uid)); + } else { + until = 0; } async.series(tasks, function (err) { @@ -78,7 +80,10 @@ module.exports = function(User) { return callback(err); } - plugins.fireHook('action:user.banned', {uid: uid}); + plugins.fireHook('action:user.banned', { + uid: uid, + until: until > 0 ? until : undefined + }); callback(); }); };