Created
January 6, 2015 19:05
-
-
Save arunsivasankaran/5085292275468b03d0c7 to your computer and use it in GitHub Desktop.
User Model for LearnDot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var mongoose = require('mongoose'); | |
var _ = require('lodash'); | |
var extend = require('mongoose-schema-extend'); | |
var Schema = mongoose.Schema; | |
var crypto = require('crypto'); | |
var Sms = require('../../remote/sms') | |
var authTypes = ['github', 'twitter', 'facebook', 'google']; | |
var UserSchema = new Schema({ | |
firstName: String, | |
lastName:String, | |
fullName: String, | |
email: { type: String, lowercase: true }, | |
hashedPassword: { type: String, select: false }, | |
phone: String, | |
provider: String, | |
salt: {type: String, select: false }, | |
google: {}, | |
github: {}, | |
roles:[] | |
}, { collection: "users" }); | |
/** | |
* Virtuals | |
*/ | |
UserSchema | |
.virtual('name') | |
.set(function(name) { | |
var split = name.split(' '); | |
this.fullName = name; | |
this.firstName = split[0]; | |
this.lastName = split[split.length - 1]; | |
}) | |
UserSchema | |
.virtual('password') | |
.set(function(password) { | |
this._password = password; | |
this.salt = this.makeSalt(); | |
this.hashedPassword = this.encryptPassword(password); | |
}) | |
.get(function() { | |
return this._password; | |
}); | |
UserSchema | |
.virtual('role') | |
.get(function() { | |
return this.__t | |
}) | |
// Public profile information | |
UserSchema | |
.virtual('profile') | |
.get(function() { | |
return { | |
'fullName': this.fullName, | |
'firstName': this.firstName, | |
'lastName': this.lastName, | |
'email': this.email, | |
'github': this.github | |
}; | |
}); | |
// Non-sensitive info we'll be putting in the token | |
UserSchema | |
.virtual('token') | |
.get(function() { | |
return { | |
'_id': this._id, | |
'__t': this.role | |
}; | |
}); | |
/** | |
Statics | |
*/ | |
UserSchema.statics.findByRole = function(r) { | |
return this.find({roles:{$elemMatch: {$eq: r}}}); | |
} | |
/** | |
* Validations | |
*/ | |
// Validate empty email | |
UserSchema | |
.path('email') | |
.validate(function(email) { | |
if (authTypes.indexOf(this.provider) !== -1) return true; | |
return email.length; | |
}, 'Email cannot be blank'); | |
// Validate empty password | |
UserSchema | |
.path('hashedPassword') | |
.validate(function(hashedPassword) { | |
if (authTypes.indexOf(this.provider) !== -1) return true; | |
return hashedPassword.length; | |
}, 'Password cannot be blank'); | |
// Validate email is not taken | |
UserSchema | |
.path('email') | |
.validate(function(value, respond) { | |
var self = this; | |
this.constructor.findOne({email: value}, function(err, user) { | |
if(err) throw err; | |
if(user) { | |
if(self.id === user.id) return respond(true); | |
return respond(false); | |
} | |
respond(true); | |
}); | |
}, 'The specified email address is already in use.'); | |
var validatePresenceOf = function(value) { | |
return value && value.length; | |
}; | |
/** | |
* Pre-save hook | |
*/ | |
UserSchema | |
.pre('save', function(next) { | |
if (!this.isNew) return next(); | |
if (!validatePresenceOf(this.hashedPassword) && authTypes.indexOf(this.provider) === -1) | |
next(new Error('Invalid password')); | |
else | |
next(); | |
}); | |
/** | |
* Methods | |
*/ | |
UserSchema.methods = { | |
addRole: function(r) { | |
this.roles.addToSet(r); | |
}, | |
hasRole: function(r) { | |
return this.roles.indexOf(r) !== -1 | |
}, | |
/** | |
* Authenticate - check if the passwords are the same | |
* | |
* @param {String} plainText | |
* @return {Boolean} | |
* @api public | |
*/ | |
authenticate: function(plainText) { | |
return this.encryptPassword(plainText) === this.hashedPassword; | |
}, | |
/** | |
* Make salt | |
* | |
* @return {String} | |
* @api public | |
*/ | |
makeSalt: function() { | |
return crypto.randomBytes(16).toString('base64'); | |
}, | |
/** | |
* Encrypt password | |
* | |
* @param {String} password | |
* @return {String} | |
* @api public | |
*/ | |
encryptPassword: function(password) { | |
if (!password || !this.salt) return ''; | |
var salt = new Buffer(this.salt, 'base64'); | |
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64'); | |
}, | |
sms: function(msg,cb) { | |
if(!this.phone) return process.nextTick(function() { | |
cb(null, {status: 'failed', message: 'no phone number'}) | |
}) | |
var sms = new Sms(this.phone,msg) | |
sms.send(cb); | |
}, | |
sendEmail: function(config,cb) { | |
config.to = this.email; | |
var email = new Email(config); | |
email.send(cb); | |
}, | |
//this seems stupid but its not. its overwritten in the student model. this is the generic | |
getWorkshops: function(query,cb) { | |
mongoose.model('Workshop').find(query).sort('order').exec(cb); | |
} | |
}; | |
module.exports = mongoose.model('User', UserSchema); | |
require('../employee/employee.model'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment