mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-17 03:01:08 +01:00
deleteObjectFields method
cleaned up user reset
This commit is contained in:
@@ -200,13 +200,20 @@ module.exports = function(db, module) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.deleteObjectField = function(key, field, callback) {
|
module.deleteObjectField = function(key, field, callback) {
|
||||||
|
module.deleteObjectFields(key, [field], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.deleteObjectFields = function(key, fields, callback) {
|
||||||
callback = callback || helpers.noop;
|
callback = callback || helpers.noop;
|
||||||
if (!key || !field) {
|
if (!key || !Array.isArray(fields) || !fields.length) {
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
var data = {};
|
var data = {};
|
||||||
|
fields.forEach(function(field) {
|
||||||
field = helpers.fieldToString(field);
|
field = helpers.fieldToString(field);
|
||||||
data[field] = '';
|
data[field] = '';
|
||||||
|
});
|
||||||
|
|
||||||
db.collection('objects').update({_key: key}, {$unset : data}, function(err, res) {
|
db.collection('objects').update({_key: key}, {$unset : data}, function(err, res) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -94,6 +94,12 @@ module.exports = function(redisClient, module) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.deleteObjectFields = function(key, fields, callback) {
|
||||||
|
helpers.multiKeyValues(redisClient, 'hdel', key, fields, function(err, results) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
module.incrObjectField = function(key, field, callback) {
|
module.incrObjectField = function(key, field, callback) {
|
||||||
redisClient.hincrby(key, field, 1, callback);
|
redisClient.hincrby(key, field, 1, callback);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,91 +10,109 @@ var async = require('async'),
|
|||||||
|
|
||||||
db = require('../database'),
|
db = require('../database'),
|
||||||
meta = require('../meta'),
|
meta = require('../meta'),
|
||||||
events = require('../events'),
|
|
||||||
emailer = require('../emailer');
|
emailer = require('../emailer');
|
||||||
|
|
||||||
(function(UserReset) {
|
(function(UserReset) {
|
||||||
|
var twoHours = 7200000;
|
||||||
|
|
||||||
UserReset.validate = function(code, callback) {
|
UserReset.validate = function(code, callback) {
|
||||||
db.getObjectField('reset:uid', code, function(err, uid) {
|
async.waterfall([
|
||||||
if (err || !uid) {
|
function(next) {
|
||||||
return callback(err, false);
|
db.getObjectField('reset:uid', code, next);
|
||||||
|
},
|
||||||
|
function(uid, next) {
|
||||||
|
if (!uid) {
|
||||||
|
return callback(null, false);
|
||||||
}
|
}
|
||||||
|
db.sortedSetScore('reset:issueDate', code, next);
|
||||||
db.sortedSetScore('reset:issueDate', code, function(err, issueDate) {
|
},
|
||||||
if (err) {
|
function(issueDate, next) {
|
||||||
return callback(err);
|
next(null, parseInt(issueDate, 10) > Date.now() - twoHours);
|
||||||
}
|
}
|
||||||
|
], callback);
|
||||||
callback(null, parseInt(issueDate, 10) > (Date.now() - (1000*60*120)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UserReset.send = function(email, callback) {
|
UserReset.send = function(email, callback) {
|
||||||
user.getUidByEmail(email, function(err, uid) {
|
var reset_code = utils.generateUUID();
|
||||||
if (err || !uid) {
|
var uid;
|
||||||
return callback(err || new Error('[[error:invalid-email]]'));
|
async.waterfall([
|
||||||
|
function(next) {
|
||||||
|
user.getUidByEmail(email, next);
|
||||||
|
},
|
||||||
|
function(_uid, next) {
|
||||||
|
if (!_uid) {
|
||||||
|
return next(new Error('[[error:invalid-email]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var reset_code = utils.generateUUID();
|
uid = _uid;
|
||||||
db.setObjectField('reset:uid', reset_code, uid);
|
async.parallel([
|
||||||
db.sortedSetAdd('reset:issueDate', Date.now(), reset_code);
|
async.apply(db.setObjectField, 'reset:uid', reset_code, uid),
|
||||||
|
async.apply(db.sortedSetAdd, 'reset:issueDate', Date.now(), reset_code)
|
||||||
var reset_link = nconf.get('url') + '/reset/' + reset_code;
|
], next);
|
||||||
|
},
|
||||||
|
function(results, next) {
|
||||||
translator.translate('[[email:password-reset-requested, ' + (meta.config.title || 'NodeBB') + ']]', meta.config.defaultLang, function(subject) {
|
translator.translate('[[email:password-reset-requested, ' + (meta.config.title || 'NodeBB') + ']]', meta.config.defaultLang, function(subject) {
|
||||||
|
next(null, subject);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(subject, next) {
|
||||||
|
var reset_link = nconf.get('url') + '/reset/' + reset_code;
|
||||||
emailer.send('reset', uid, {
|
emailer.send('reset', uid, {
|
||||||
site_title: (meta.config.title || 'NodeBB'),
|
site_title: (meta.config.title || 'NodeBB'),
|
||||||
reset_link: reset_link,
|
reset_link: reset_link,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
template: 'reset',
|
template: 'reset',
|
||||||
uid: uid
|
uid: uid
|
||||||
});
|
}, next);
|
||||||
callback(null, reset_code);
|
},
|
||||||
});
|
function(next) {
|
||||||
});
|
next(null, reset_code);
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
UserReset.commit = function(code, password, callback) {
|
UserReset.commit = function(code, password, callback) {
|
||||||
UserReset.validate(code, function(err, validated) {
|
var uid;
|
||||||
if(err) {
|
async.waterfall([
|
||||||
return callback(err);
|
function(next) {
|
||||||
}
|
UserReset.validate(code, next);
|
||||||
|
},
|
||||||
|
function(validated, next) {
|
||||||
if (!validated) {
|
if (!validated) {
|
||||||
return callback(new Error('[[error:reset-code-not-valid]]'));
|
return next(new Error('[[error:reset-code-not-valid]]'));
|
||||||
|
}
|
||||||
|
db.getObjectField('reset:uid', code, next);
|
||||||
|
},
|
||||||
|
function(_uid, next) {
|
||||||
|
uid = _uid;
|
||||||
|
if (!uid) {
|
||||||
|
return next(new Error('[[error:reset-code-not-valid]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
db.getObjectField('reset:uid', code, function(err, uid) {
|
user.hashPassword(password, next);
|
||||||
if (err) {
|
},
|
||||||
return callback(err);
|
function(hash, next) {
|
||||||
|
async.parallel([
|
||||||
|
async.apply(user.setUserField, uid, 'password', hash),
|
||||||
|
async.apply(db.deleteObjectField, 'reset:uid', code),
|
||||||
|
async.apply(db.sortedSetRemove, 'reset:issueDate', code),
|
||||||
|
async.apply(user.auth.resetLockout, uid)
|
||||||
|
], next);
|
||||||
}
|
}
|
||||||
|
], callback);
|
||||||
user.hashPassword(password, function(err, hash) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
user.setUserField(uid, 'password', hash);
|
|
||||||
|
|
||||||
db.deleteObjectField('reset:uid', code);
|
|
||||||
db.sortedSetRemove('reset:issueDate', code);
|
|
||||||
|
|
||||||
user.auth.resetLockout(uid, callback);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UserReset.clean = function(callback) {
|
UserReset.clean = function(callback) {
|
||||||
// Locate all codes that have expired, and remove them from the set/hash
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
async.apply(db.getSortedSetRangeByScore, 'reset:issueDate', 0, -1, -1, +new Date()-(1000*60*120)),
|
async.apply(db.getSortedSetRangeByScore, 'reset:issueDate', 0, -1, 0, Date.now() - twoHours),
|
||||||
function(tokens, next) {
|
function(tokens, next) {
|
||||||
if (!tokens.length) { return next(); }
|
if (!tokens.length) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
winston.verbose('[UserReset.clean] Removing ' + tokens.length + ' reset tokens from database');
|
winston.verbose('[UserReset.clean] Removing ' + tokens.length + ' reset tokens from database');
|
||||||
async.parallel([
|
async.parallel([
|
||||||
async.apply(db.deleteObjectField, 'reset:uid', tokens),
|
async.apply(db.deleteObjectFields, 'reset:uid', tokens),
|
||||||
async.apply(db.sortedSetRemove, 'reset:issueDate', tokens)
|
async.apply(db.sortedSetRemove, 'reset:issueDate', tokens)
|
||||||
], next);
|
], next);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ describe('Hash methods', function() {
|
|||||||
|
|
||||||
describe('deleteObjectField()', function() {
|
describe('deleteObjectField()', function() {
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
db.setObject('testObject10', {foo: 'bar', delete: 'this'}, done);
|
db.setObject('testObject10', {foo: 'bar', delete: 'this', delete1: 'this', delete2: 'this'}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete an objects field', function(done) {
|
it('should delete an objects field', function(done) {
|
||||||
@@ -277,6 +277,22 @@ describe('Hash methods', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete multiple fields of the object', function(done) {
|
||||||
|
db.deleteObjectFields('testObject10', ['delete1', 'delete2'], function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(arguments.length, 1);
|
||||||
|
async.parallel({
|
||||||
|
delete1: async.apply(db.isObjectField, 'testObject10', 'delete1'),
|
||||||
|
delete2: async.apply(db.isObjectField, 'testObject10', 'delete2')
|
||||||
|
}, function(err, results) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(results.delete1, false);
|
||||||
|
assert.equal(results.delete2, false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('incrObjectField()', function() {
|
describe('incrObjectField()', function() {
|
||||||
|
|||||||
Reference in New Issue
Block a user