var bcrypt = require('bcrypt'); var FacebookService = require('../services/FacebookService').FacebookService; UserModel = function (mongoose) { // store all categories a category is associated with var CategoryAlertSchema = new mongoose.Schema({ categoryId: {type: String}, categoryName: {type: String}, disabledDate: {type: Date}, createdDate: {type: Date, default: Date.now}, updatedDate: {type: Date, default: Date.now} }); // store user information var UserSchema = new mongoose.Schema({ //emailAddress: { type: String }, username: { type: String, unique: true }, firstName: {type: String}, lastName: {type: String}, password: {type: String}, subscribeBotsOfDay: {type: Boolean}, facebookBot: { id: {type: String}, firstName: {type: String}, lastName: {type: String}, profilePic: {type: String}, gender: {type: String}, locale: {type: String}, payload: {type: String} }, administrator: { isAdmin: {type: Boolean, default: false}, isApproved: {type: Boolean} }, categoryAlerts: [CategoryAlertSchema], receiveAlerts: {type: Boolean}, lastIpAddress: {type: String}, lastLogin: {type: Date, default: Date.now}, disabledDate: {type: Date}, lastReceivedDate: {type: Date, default: Date.now}, createdDate: {type: Date, default: Date.now}, updatedDate: {type: Date, default: Date.now}, location: {type: mongoose.Schema.ObjectId, ref: 'Location'}, /* For reset password */ resetPasswordToken: { type: String }, resetPasswordExpires: { type: Date }, stripeServer:{ idCustomer: {type: String, default: null}, idSubscription: {type: String, default: null}, paid: {type: Boolean, default: false}, renewalDate: {type: Number, default: null} } }); // check logic as it saves UserSchema.pre('save', function (next) { var user = this; // check to see if the password is changing if (this.isModified('password')) { bcrypt.genSalt(10, function (err, salt) { if (err) { return next(err); } bcrypt.hash(user.password, salt, function (err, hash) { if (err) { return next(err); } user.password = hash; next(); }); }); } else { return next(); } }); // set up model this.userModel = mongoose.model("User", UserSchema); }; //------------------------------------------------------------------- // retrieve all users //------------------------------------------------------------------- UserModel.prototype.getAll = function (search, sort, direction, callback) { console.log("Searching %s by %s %s", search, sort, direction); // set sort key - we could use sort(sort) but we need to add direction var sortKey = {}; switch (sort) { case "lastName": sortKey = {"lastName": direction}; break; case "createdDate": sortKey = {createdDate: direction}; break; } // handle search text if (search != null && search != "") { this.userModel .find({ $or: [ {"lastName": {$regex: search, $options: "i"}}, {"firstName": {$regex: search, $options: "i"}} ], disabledDate: null }) .sort(sortKey).exec(function (err, users) { if (err) console.log("Error: " + err); else callback(users); }); } else { this.userModel .find({disabledDate: null}) .sort(sortKey) .exec(function (err, users) { if (err) console.log("Error: " + err); else callback(users); }); } }; //------------------------------------------------------------------- // this function compares password //------------------------------------------------------------------- UserModel.prototype.comparePassword = function (passw, password, callback) { bcrypt.compare(passw, password, function (err, isMatch) { if (err) { return callback(err); } callback(null, isMatch); }); }; //------------------------------------------------------------------- // get user by username //------------------------------------------------------------------- UserModel.prototype.getByUsername = function (username, callback) { this.userModel.find({ username: {$regex: username, $options: "i"}, // disabledDate: null // disabled is handled in UserController -- /api/user/authenticate }).populate('location').exec(function (err, users) { if (err) { console.log("Error: " + err); } else { //console.log("getByUserName", users); } callback(users); }); }; //------------------------------------------------------------------- // retrieve total users //------------------------------------------------------------------- UserModel.prototype.getTotalUsers = function (callback) { this.userModel.aggregate( [ {$match: {'disabledDate': null}}, {$group: {_id: "total", count: {$sum: 1}}} ], function (err, users) { if (err) console.log("Error: " + err); else callback(users); }); }; //------------------------------------------------------------------- // retrieve active users //------------------------------------------------------------------- // UsageModel.prototype.getActiveUsers = function(startDate, endDate, callback) { // // this.usageModel.aggregate( // [ // { $match: { // "createdDate": { $gt: new Date(startDate), $lt: new Date(endDate) }, // 'disabledDate': null // } }, // { $group: { _id: "$userId", count: { $sum: 1 } } } // ] ,function(err, usage) { // if(err) // console.log(err); // else // callback(usage); // }); // }; // //------------------------------------------------------------------- // get user by admin //------------------------------------------------------------------- UserModel.prototype.getByAdminUsername = function (username, callback) { this.userModel.find({ username: {$regex: username, $options: "i"}, disabledDate: null, "administrator.isAdmin": true }, function (err, users) { if (err) console.log(err); else callback(users); }); }; //------------------------------------------------------------------- // register new user //------------------------------------------------------------------- UserModel.prototype.register = function (firstName, lastName, username, password, ipAddress, location, callback) { // check for null username //if(username == null) username = emailAddress; // add new user user = new this.userModel({ firstName: firstName, lastName: lastName, username: username, //emailAddress: emailAddress, password: password, lastIpAddress: ipAddress, lastLogin: new Date().toUTCString(), createdDate: new Date().toUTCString(), updatedDate: new Date().toUTCString(), location: location }); // save user user.save(function (userErr, savedUser) { if (userErr) { return {success: false, msg: 'Username already exists.'}; } else { savedUser.success = true; callback(savedUser); } }) }; //------------------------------------------------------------------- // set up user if none exists //------------------------------------------------------------------- UserModel.prototype.setFacebookProfile = function (id, firstName, lastName, profilePic, gender, locale, callback) { console.log("Updating user %s %s with id %s", firstName, lastName, id); // interesting cheat var that = this; this.userModel.findOne({"facebookBot.id": id}, function (err, user) { if (err) { // need a good method for capturing errors and notifiing developers console.log("ERROR: %s", err); } else { // check for user if (user != null) { console.log("Found existing user"); user.facebookBot.firstName = firstName; user.facebookBot.lastName = lastName; user.facebookBot.profilePic = profilePic; user.facebookBot.gender = gender; user.facebookBot.locale = locale; // save user user.save(function (userErr, savedUser) { if (userErr) { console.log("Error in existing facebook user save: %s", userErr); } else { callback(savedUser); } }) } else { console.log("Adding new user"); // add new user var newUser = new that.userModel({ username: id, facebookBot: { id: id, firstName: firstName, lastName: lastName, profilePic: profilePic, gender: gender, locale: locale }, createdDate: new Date().toUTCString(), updatedDate: new Date().toUTCString() }); // save user newUser.save(function (userErr, savedUser) { if (userErr) { console.log("Error in new facebook user save: %s", userErr); } else { callback(savedUser); } }) } } } ); }; //------------------------------------------------------------------- // update Next facebook bot command payload //------------------------------------------------------------------- UserModel.prototype.setFacebookCommandPayload = function (id, payload, Config, request, callback) { // interesting cheat var that = this; // set payload Date payload.commandDate = new Date().toUTCString(); // find facebook user this.userModel.findOne({"facebookBot.id": id}, function (err, user) { if (err) { // need a good method for capturing errors and notifiing developers console.log("Error getting a user: " + err); } else { // check for user if (user != null) { // set next command payload user.facebookBot.payload = JSON.stringify(payload) user.lastReceivedDate = new Date().toUTCString(); // save user user.save(function (userErr, savedUser) { if (userErr) { console.log(userErr); } else { callback(savedUser); } }) } else { console.log("Adding new facebook user: " + id); // get user information facebookService = new FacebookService(); // get profile facebookService.getFacebookProfile(Config, request, id, function (profile) { // log console.log("Creating new user: " + profile.first_name + " " + profile.last_name); // add new user user = new that.userModel({ username: id, firstName: profile.first_name, lastName: profile.last_name, profilePic: profile.profile_pic, facebookBot: { id: id, payload: JSON.stringify(payload), firstName: profile.first_name, lastName: profile.last_name, profilePic: profile.profile_pic, gender: profile.gender, locale: profile.locale }, lastReceivedDate: new Date().toUTCString(), createdDate: new Date().toUTCString(), updatedDate: new Date().toUTCString() }); // save user user.save(function (userErr, savedUser) { if (userErr) { console.log(userErr); } else { callback(savedUser); } }) }); } } } ); }; //------------------------------------------------------------------- // get category alert for a user //------------------------------------------------------------------- UserModel.prototype.getCategoryAlert = function (id, categoryId, callback) { this.userModel.find({ "facebookBot.id": id, "categoryAlerts": {"$elemMatch": {categoryId: categoryId}}, disabledDate: null }, function (err, user) { if (err) { console.log(err); } else { callback(user); } } ); }; //------------------------------------------------------------------- // get category alert for a user //------------------------------------------------------------------- UserModel.prototype.addCategoryAlert = function (id, categoryId, categoryName, callback) { this.userModel.findOne({"facebookBot.id": id}, function (err, user) { // push new category alert user.categoryAlerts.push({ categoryId: categoryId, categoryName: categoryName }); user.save(function (userErr, savedUser) { if (userErr) { console.log(userErr); return false; } else { callback(true); } }) } ); }; //------------------------------------------------------------------- // update subscribe to bots //------------------------------------------------------------------- UserModel.prototype.updateSubscribeBotsOfDay = function (id, subscribe, callback) { this.userModel.findOne({"facebookBot.id": id}, function (err, user) { // update subscribe user.subscribeBotsOfDay = subscribe; // save user user.save(function (userErr, savedUser) { if (userErr) { console.log(userErr); return false; } else { callback(true); } }) } ); }; //------------------------------------------------------------------- // get user by facebook id //------------------------------------------------------------------- UserModel.prototype.getFacebookUser = function (id, callback) { this.userModel.findOne({"facebookBot.id": id}, function (err, user) { if (err) { console.log(err); } else { callback(user); } } ); }; // DJH 1/7/2017 //------------------------------------------------------------------- // get user by id //------------------------------------------------------------------- UserModel.prototype.getById = function (id, callback) { this.userModel.findById(id).populate('location').exec(function (err, user) { if (err) console.log("Error: " + err); else console.log("getById", user); callback(user); }); }; module.exports.UserModel = UserModel;