var crypto = require('crypto')
var MongoDB = require('mongodb').Db;
var Server = require('mongodb').Server;
var moment = require('moment');
var dbPort = 27017;
var dbHost = 'localhost';
var dbName = 'DERStest';
/* establish the database connection */
var db = new MongoDB(dbName, new Server(dbHost, dbPort, {auto_reconnect: true}), {w: 1});
db.open(function(e, d){
if (e) {
console.log(e);
} else{
console.log('connected to database :: ' + dbName);
}
});
var accounts = db.collection('accounts');
/* login validation methods */
exports.autoLogin = function(user, pass, callback)
{
accounts.findOne({user:user}, function(e, o) {
if (o){
o.pass == pass ? callback(o) : callback(null);
} else{
callback(null);
}
});
}
exports.manualLogin = function(user, pass, callback)
{
accounts.findOne({user:user}, function(e, o) {
if (o == null){
callback('user-not-found');
} else{
validatePassword(pass, o.pass, function(err, res) {
if (res){
callback(null, o);
} else{
callback('invalid-password');
}
});
}
});
}
/* record insertion, update & deletion methods */
exports.addNewAccount = function(newData, callback)
{
accounts.findOne({user:newData.user}, function(e, o) {
if (o){
callback('username-taken');
} else{
accounts.findOne({email:newData.email}, function(e, o) {
if (o){
callback('email-taken');
} else{
saltAndHash(newData.pass, function(hash){
newData.pass = hash;
// append date stamp when record was created //
newData.date = moment().format('MMMM Do YYYY, h:mm:ss a');
accounts.insert(newData, {safe: true}, callback);
});
}
});
}
});
}
exports.updateAccount = function(newData, callback)
{
accounts.findOne({user:newData.user}, function(e, o){
o.name = newData.name;
o.email = newData.email;
o.country = newData.country;
if (newData.pass == ''){
accounts.save(o, {safe: true}, callback);
} else{
saltAndHash(newData.pass, function(hash){
o.pass = hash;
accounts.save(o, {safe: true}, callback);
});
}
});
}
exports.updatePassword = function(email, newPass, callback)
{
accounts.findOne({email:email}, function(e, o){
if (e){
callback(e, null);
} else{
saltAndHash(newPass, function(hash){
o.pass = hash;
accounts.save(o, {safe: true}, callback);
});
}
});
}
/* account lookup methods */
exports.deleteAccount = function(id, callback)
{
accounts.remove({_id: getObjectId(id)}, callback);
}
exports.getAccountByEmail = function(email, callback)
{
accounts.findOne({email:email}, function(e, o){ callback(o); });
}
exports.validateResetLink = function(email, passHash, callback)
{
accounts.find({ $and: [{email:email, pass:passHash}] }, function(e, o){
callback(o ? 'ok' : null);
});
}
exports.getAllRecords = function(callback)
{
accounts.find().toArray(
function(e, res) {
if (e) callback(e)
else callback(null, res)
});
};
exports.delAllRecords = function(callback)
{
accounts.remove({}, callback); // reset accounts collection for testing //
}
/* private encryption & validation methods */
var generateSalt = function()
{
var set = '0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ';
var salt = '';
for (var i = 0; i < 10; i++) {
var p = Math.floor(Math.random() * set.length);
salt += set[p];
}
return salt;
}
var md5 = function(str) {
return crypto.createHash('md5').update(str).digest('hex');
}
var saltAndHash = function(pass, callback)
{
var salt = generateSalt();
callback(salt + md5(pass + salt));
}
var validatePassword = function(plainPass, hashedPass, callback)
{
var salt = hashedPass.substr(0, 10);
var validHash = salt + md5(plainPass + salt);
callback(null, hashedPass === validHash);
}
/* auxiliary methods */
var getObjectId = function(id)
{
return accounts.db.bson_serializer.ObjectID.createFromHexString(id)
}
var findById = function(id, callback)
{
accounts.findOne({_id: getObjectId(id)},
function(e, res) {
if (e) callback(e)
else callback(null, res)
});
};
var findByMultipleFields = function(a, callback)
{
// this takes an array of name/val pairs to search against {fieldName : 'value'} //
accounts.find( { $or : a } ).toArray(
function(e, results) {
if (e) callback(e)
else callback(null, results)
});
}