var crypto = require('crypto'); var mongoose = require('mongoose'); var Member = require('../models/member'); var settings = require('./config'); var utils = require('./utils'); module.exports = { create: function(member) { return function(done) { var _member = new Member({ name: member.name, email: member.email, phone: member.phone, gender: member.gender, idno: member.idno, salt: utils.generateSalt(), birthday: member.birthday, cardno: member.cardno, tokens: member.tokens }); if (member.password) { // Encrypt plain password _member.password = utils.encryptPassword(_member.salt, member.password); } else { _member.password = ''; } _member.save(function(err) { done(err, _member); }); }; }, getMember: function(id) { return function(done) { Member.findOne({ _id: id }, function(err, member) { if (err) return done(err); if (!member) return done(); return done(null, member); }); }; }, getMemberByEmail: function(email) { return function(done) { Member.findOne({ email: email}, function(err, member) { if (err) return done(err); if (!member) return done(); return done(null, member); }); }; }, deleteMembers: function(ids) { return function(done) { Member.remove({ _id: { $in: ids } }, function(err) { done(err); }); }; }, insert: function(members) { return function(done) { Member.collection.insert(members, done); }; }, updateByEmail: function(email, member, opts) { return function(done) { // Update time member.updated = Date.now(); Member.update({ email: email }, member, opts, done); }; }, changePassword: function(id, password) { return function(done) { // Generate a new salt for encryption var salt = utils.generateSalt(); var newPassword = utils.encryptPassword(salt, password); // Update password Member.findOneAndUpdate({ _id: id }, { salt: salt, password: newPassword, updated: Date.now() }, { new: true }, function(err, member) { if (err) return done(err); done(null, member ? true : false); }); }; }, changePasswordWithToken: function(id, token, password) { return function(done) { // Generate a new salt for encryption var salt = utils.generateSalt(); var newPassword = utils.encryptPassword(salt, password); // TODO: Should check expired time of token // Update password Member.findOneAndUpdate({ _id: id, 'rule_tokens.name': 'reset_password' }, { $pull: { rule_tokens: { name: 'reset_password' } }, salt: salt, password: newPassword, updated: Date.now() }, { new: true }, function(err, member) { if (err) return done(err); done(null, member ? true : false); }); }; }, checkCard: function(token) { return function(done) { Member.findOne({ tokens: token }, function(err, member) { if (err) return done(err); if (!member) return done(new Error('Not Found')); return done(null, member); }); }; }, authorizeMember: function(username, password) { return function(done) { Member.findOne({ email: username }, function(err, member) { if (err) return done(err); // Found nothing if (!member) return done(); // First time to login if (!member.password) { // Using phone to be password if (member.phone == password) return done(null, member); else return done(); } // Check password if (utils.encryptPassword(member.salt, password) == member.password) return done(null, member); else return done(); }); }; }, save: function(id, member) { return function(done) { var updated = Date.now(); var m = { name: member.name || undefined, email: member.email || undefined, phone: member.phone || undefined, gender: member.gender || undefined, idno: member.idno || undefined, birthday: member.birthday || undefined, tokens: member.tokens || undefined, updated: updated }; // Remove fields which is unset for (var key in m) { if (m[key] == undefined) delete m[key]; } Member.findOneAndUpdate({ _id: id }, m, { new: true }, function(err, _member) { if (err) return done(err); done(null, _member); }); }; }, count: function() { return function(done) { Member.count({}, done); }; }, list: function() { var conditions = {}; var columns; var opts = {}; if (arguments.length == 3) { conditions = arguments[0]; columns = arguments[1]; opts = arguments[2]; } else if (arguments.length == 2) { if (arguments[0] instanceof Array) { columns = arguments[0]; opts = arguments[1]; } else if (arguments[1] instanceof Array) { conditions = arguments[0]; columns = arguments[1]; } else { conditions = arguments[0]; opts = arguments[1]; } } else if (arguments.length == 1) { columns = null; opts = arguments[0]; } return function(done) { var cols = null; if (columns) cols = columns.join(' '); Member.count(conditions, function(err, count) { if (err) { done(err); return; } if (!count) { done(err, { count: 0 }); return; } Member.find(conditions, cols, opts, function(err, members) { done(err, { count: count, members: members }); }); }); }; }, setupRuleToken: function(id, name, expired) { return function(done) { var token = utils.generateToken(); // Remove old token Member.findOneAndUpdate({ _id: id, 'rule_tokens.name': name }, { $pull: { 'rule_tokens.$.name': name } }, function(err) { if (err) { return done(err); } // Update rule token. add a new one if no key exists Member.findOneAndUpdate({ _id: id }, { $addToSet: { rule_tokens: { name: name, token: token, expired: expired } } }, function(err, member) { done(err, member ? { token: token, id: member._id } : null); }); }); }; }, setupRuleTokenByEmail: function(email, name, expired) { return function(done) { var token = utils.generateToken(); // Remove old token Member.findOneAndUpdate({ email: email, 'rule_tokens.name': name }, { $pull: { 'rule_tokens.$.name': name } }, function(err) { if (err) { return done(err); } // Update rule token. add a new one if no key exists Member.findOneAndUpdate({ email: email }, { $addToSet: { rule_tokens: { name: name, token: token, expired: expired } } }, function(err, member) { done(err, member ? { token: token, id: member._id } : null); }); }); }; }, updateCardno: function(id, cardno) { return function(done) { Member.update({ _id: id }, { cardno: cardno, updated: Date.now() }, done); }; }, updateCardnoByEmail: function(email, token, cardno) { return function(done) { Member.update({ email: email }, { tokens: [ token ], cardno: cardno, updated: Date.now() }, done); }; } };