more auth tests

v1.18.x
Barış Soner Uşaklı 8 years ago
parent b8cc67dfff
commit b29745aa44

@ -52,19 +52,7 @@ authenticationController.register = function (req, res) {
user.isPasswordValid(userData.password, next);
},
function (next) {
if (registrationType === 'normal' || registrationType === 'invite-only' || registrationType === 'admin-invite-only') {
next(null, false);
} else if (registrationType === 'admin-approval') {
next(null, true);
} else if (registrationType === 'admin-approval-ip') {
db.sortedSetCard('ip:' + req.ip + ':uid', function (err, count) {
if (err) {
next(err);
} else {
next(null, !!count);
}
});
}
user.shouldQueueUser(req.ip, next);
},
function (queue, next) {
res.locals.processLogin = true; // set it to false in plugin if you wish to just register only
@ -200,13 +188,15 @@ authenticationController.login = function (req, res, next) {
var loginWith = meta.config.allowLoginWith || 'username-email';
if (req.body.username && utils.isEmailValid(req.body.username) && loginWith.indexOf('email') !== -1) {
user.getUsernameByEmail(req.body.username, function (err, username) {
if (err) {
return next(err);
}
req.body.username = username || req.body.username;
continueLogin(req, res, next);
});
async.waterfall([
function (next) {
user.getUsernameByEmail(req.body.username, next);
},
function (username, next) {
req.body.username = username || req.body.username;
continueLogin(req, res, next);
},
], next);
} else if (loginWith.indexOf('username') !== -1 && !validator.isEmail(req.body.username)) {
continueLogin(req, res, next);
} else {
@ -375,7 +365,7 @@ authenticationController.localLogin = function (req, username, password, next) {
}
if (result.banned) {
return banUser(uid, next);
return getBanInfo(uid, next);
}
user.auth.logAttempt(uid, req.ip, next);
@ -394,48 +384,57 @@ authenticationController.localLogin = function (req, username, password, next) {
};
authenticationController.logout = function (req, res, next) {
if (req.user && parseInt(req.user.uid, 10) > 0 && req.sessionID) {
var uid = parseInt(req.user.uid, 10);
var sessionID = req.sessionID;
if (!req.uid || !req.sessionID) {
return res.status(200).send('not-logged-in');
}
user.auth.revokeSession(sessionID, uid, function (err) {
if (err) {
return next(err);
}
async.waterfall([
function (next) {
user.auth.revokeSession(req.sessionID, req.uid, next);
},
function (next) {
req.logout();
req.session.destroy();
user.setUserField(uid, 'lastonline', Date.now() - 300000);
plugins.fireHook('static:user.loggedOut', { req: req, res: res, uid: uid }, function () {
res.status(200).send('');
// Force session check for all connected socket.io clients with the same session id
sockets.in('sess_' + sessionID).emit('checkSession', 0);
});
});
} else {
res.status(200).send('');
}
user.setUserField(req.uid, 'lastonline', Date.now() - 300000, next);
},
function (next) {
plugins.fireHook('static:user.loggedOut', { req: req, res: res, uid: req.uid }, next);
},
function () {
// Force session check for all connected socket.io clients with the same session id
sockets.in('sess_' + req.sessionID).emit('checkSession', 0);
res.status(200).send('');
},
], next);
};
function banUser(uid, next) {
user.getLatestBanInfo(uid, function (err, banInfo) {
if (err) {
if (err.message === 'no-ban-info') {
return next(new Error('[[error:user-banned]]'));
function getBanInfo(uid, callback) {
var banInfo;
async.waterfall([
function (next) {
user.getLatestBanInfo(uid, next);
},
function (_banInfo, next) {
banInfo = _banInfo;
if (banInfo.reason) {
return next();
}
return next(err);
}
if (!banInfo.reason) {
translator.translate('[[user:info.banned-no-reason]]', function (translated) {
banInfo.reason = translated;
next(new Error(banInfo.expiry ? '[[error:user-banned-reason-until, ' + banInfo.expiry_readable + ', ' + banInfo.reason + ']]' : '[[error:user-banned-reason, ' + banInfo.reason + ']]'));
next();
});
} else {
},
function (next) {
next(new Error(banInfo.expiry ? '[[error:user-banned-reason-until, ' + banInfo.expiry_readable + ', ' + banInfo.reason + ']]' : '[[error:user-banned-reason, ' + banInfo.reason + ']]'));
},
], function (err) {
if (err) {
if (err.message === 'no-ban-info') {
err.message = '[[error:user-banned]]';
}
}
callback(err);
});
}

@ -3,6 +3,7 @@
var async = require('async');
var request = require('request');
var winston = require('winston');
var db = require('../database');
var meta = require('../meta');
@ -138,6 +139,19 @@ module.exports = function (User) {
});
}
User.shouldQueueUser = function (ip, callback) {
var registrationType = meta.config.registrationType || 'normal';
if (registrationType === 'normal' || registrationType === 'invite-only' || registrationType === 'admin-invite-only') {
setImmediate(callback, null, false);
} else if (registrationType === 'admin-approval') {
setImmediate(callback, null, true);
} else if (registrationType === 'admin-approval-ip') {
db.sortedSetCard('ip:' + ip + ':uid', function (err, count) {
callback(err, !!count);
});
}
};
User.getRegistrationQueue = function (start, stop, callback) {
var data;
async.waterfall([
@ -152,58 +166,22 @@ module.exports = function (User) {
db.getObjects(keys, next);
},
function (users, next) {
users = users.map(function (user, index) {
if (user) {
user.timestampISO = utils.toISOString(data[index].score);
delete user.hashedPassword;
}
users = users.filter(Boolean).map(function (user, index) {
user.timestampISO = utils.toISOString(data[index].score);
delete user.hashedPassword;
return user;
}).filter(Boolean);
});
async.map(users, function (user, next) {
if (!user) {
return next(null, user);
}
// temporary: see http://www.stopforumspam.com/forum/viewtopic.php?id=6392
user.ip = user.ip.replace('::ffff:', '');
async.parallel([
function (next) {
User.getUidsFromSet('ip:' + user.ip + ':uid', 0, -1, function (err, uids) {
if (err) {
return next(err);
}
User.getUsersFields(uids, ['uid', 'username', 'picture'], function (err, ipMatch) {
user.ipMatch = ipMatch;
next(err);
});
});
getIPMatchedUsers(user.ip, next);
},
function (next) {
request({
method: 'get',
url: 'http://api.stopforumspam.org/api' +
'?ip=' + encodeURIComponent(user.ip) +
'&email=' + encodeURIComponent(user.email) +
'&username=' + encodeURIComponent(user.username) +
'&f=json',
json: true,
}, function (err, response, body) {
if (err) {
return next();
}
if (response.statusCode === 200 && body) {
user.spamData = body;
user.usernameSpam = body.username ? (body.username.frequency > 0 || body.username.appears > 0) : true;
user.emailSpam = body.email ? (body.email.frequency > 0 || body.email.appears > 0) : true;
user.ipSpam = body.ip ? (body.ip.frequency > 0 || body.ip.appears > 0) : true;
}
next();
});
getSpamData(user, next);
},
], function (err) {
next(err, user);
@ -218,4 +196,45 @@ module.exports = function (User) {
},
], callback);
};
function getIPMatchedUsers(ip, callback) {
async.waterfall([
function (next) {
User.getUidsFromSet('ip:' + ip + ':uid', 0, -1, next);
},
function (uids, next) {
User.getUsersFields(uids, ['uid', 'username', 'picture'], next);
},
], callback);
}
function getSpamData(user, callback) {
async.waterfall([
function (next) {
request({
method: 'get',
url: 'http://api.stopforumspam.org/api' +
'?ip=' + encodeURIComponent(user.ip) +
'&email=' + encodeURIComponent(user.email) +
'&username=' + encodeURIComponent(user.username) +
'&f=json',
json: true,
}, next);
},
function (response, body, next) {
if (response.statusCode === 200 && body) {
user.spamData = body;
user.usernameSpam = body.username ? (body.username.frequency > 0 || body.username.appears > 0) : true;
user.emailSpam = body.email ? (body.email.frequency > 0 || body.email.appears > 0) : true;
user.ipSpam = body.ip ? (body.ip.frequency > 0 || body.ip.appears > 0) : true;
}
next();
},
], function (err) {
if (err) {
winston.error(err);
}
callback();
});
}
};

@ -118,22 +118,28 @@ module.exports = function (User) {
User.auth.revokeSession = function (sessionId, uid, callback) {
winston.verbose('[user.auth] Revoking session ' + sessionId + ' for user ' + uid);
db.sessionStore.get(sessionId, function (err, sessionObj) {
if (err) {
return callback(err);
}
async.parallel([
function (next) {
if (sessionObj && sessionObj.meta && sessionObj.meta.uuid) {
db.deleteObjectField('uid:' + uid + ':sessionUUID:sessionId', sessionObj.meta.uuid, next);
} else {
next();
}
},
async.apply(db.sortedSetRemove, 'uid:' + uid + ':sessions', sessionId),
async.apply(db.sessionStore.destroy.bind(db.sessionStore), sessionId),
], callback);
});
async.waterfall([
function (next) {
db.sessionStore.get(sessionId, function (err, sessionObj) {
next(err, sessionObj || null);
});
},
function (sessionObj, next) {
async.parallel([
function (next) {
if (sessionObj && sessionObj.meta && sessionObj.meta.uuid) {
db.deleteObjectField('uid:' + uid + ':sessionUUID:sessionId', sessionObj.meta.uuid, next);
} else {
next();
}
},
async.apply(db.sortedSetRemove, 'uid:' + uid + ':sessions', sessionId),
async.apply(db.sessionStore.destroy.bind(db.sessionStore), sessionId),
], function (err) {
next(err);
});
},
], callback);
};
User.auth.revokeAllSessions = function (uid, callback) {

@ -88,6 +88,7 @@ describe('authentication', function () {
email: 'admin@nodebb.org',
username: 'admin',
password: 'adminpwd',
userLang: 'it',
},
json: true,
jar: jar,
@ -107,7 +108,11 @@ describe('authentication', function () {
assert(body);
assert.equal(body.username, 'admin');
assert.equal(body.email, 'admin@nodebb.org');
done();
user.getSettings(body.uid, function (err, settings) {
assert.ifError(err);
assert.equal(settings.userLang, 'it');
done();
});
});
});
});
@ -298,6 +303,92 @@ describe('authentication', function () {
});
});
it('should queue user if ip is used before', function (done) {
meta.config.registrationType = 'admin-approval-ip';
registerUser('another@user.com', 'anotheruser', 'anotherpwd', function (err, response, body) {
meta.config.registrationType = 'normal';
assert.ifError(err);
assert.equal(response.statusCode, 200);
assert.equal(body.message, '[[register:registration-added-to-queue]]');
done();
});
});
it('should be able to login with email', function (done) {
user.create({ username: 'ginger', password: '123456', email: 'ginger@nodebb.org' }, function (err, uid) {
assert.ifError(err);
loginUser('ginger@nodebb.org', '123456', function (err, response, body) {
assert.ifError(err);
assert.equal(response.statusCode, 200);
done();
});
});
});
it('should fail to login if login type is username and an email is sent', function (done) {
meta.config.allowLoginWith = 'username';
loginUser('ginger@nodebb.org', '123456', function (err, response, body) {
meta.config.allowLoginWith = 'username-email';
assert.ifError(err);
assert.equal(response.statusCode, 500);
assert.equal(body, '[[error:wrong-login-type-username]]');
done();
});
});
it('should send 200 if not logged in', function (done) {
var jar = request.jar();
request({
url: nconf.get('url') + '/api/config',
json: true,
jar: jar,
}, function (err, response, body) {
assert.ifError(err);
request.post(nconf.get('url') + '/logout', {
form: {},
json: true,
jar: jar,
headers: {
'x-csrf-token': body.csrf_token,
},
}, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert.equal(body, 'not-logged-in');
done();
});
});
});
it('should prevent banned user from logging in', function (done) {
user.create({ username: 'banme', password: '123456', email: 'ban@me.com' }, function (err, uid) {
assert.ifError(err);
user.ban(uid, 0, 'spammer', function (err) {
assert.ifError(err);
loginUser('banme', '123456', function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 403);
assert.equal(body, '[[error:user-banned-reason, spammer]]');
user.unban(uid, function (err) {
assert.ifError(err);
var expiry = Date.now() + 10000;
user.ban(uid, expiry, '', function (err) {
assert.ifError(err);
loginUser('banme', '123456', function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 403);
assert.equal(body, '[[error:user-banned-reason-until, ' + (new Date(parseInt(expiry, 10)).toString()) + ', No reason given.]]');
done();
});
});
});
});
});
});
});
after(function (done) {
db.emptydb(done);
});

@ -1384,7 +1384,7 @@ describe('User', function () {
done();
});
it('should send digetst', function (done) {
it('should send digest', function (done) {
db.sortedSetAdd('digest:day:uids', [Date.now(), Date.now()], [1, 2], function (err) {
assert.ifError(err);
User.digest.execute('day', function (err) {

Loading…
Cancel
Save