1
0
Fork 0
mirror of https://github.com/mmumshad/ansible-playable.git synced 2025-02-15 04:42:05 +00:00
ansible-playable/server/api/user/user.model.js
Mumshad Mannambeth c92f737237 Initial Commit
2017-06-07 13:36:45 -04:00

258 lines
5.2 KiB
JavaScript

'use strict';
/*eslint no-invalid-this:0*/
import crypto from 'crypto';
mongoose.Promise = require('bluebird');
import mongoose, {Schema} from 'mongoose';
import {registerEvents} from './user.events';
const authTypes = ['github', 'twitter', 'facebook', 'google'];
var UserSchema = new Schema({
name: String,
email: {
type: String,
lowercase: true,
required() {
if(authTypes.indexOf(this.provider) === -1) {
return true;
} else {
return false;
}
}
},
role: {
type: String,
default: 'user'
},
password: {
type: String,
required() {
if(authTypes.indexOf(this.provider) === -1) {
return true;
} else {
return false;
}
}
},
provider: String,
salt: String,
facebook: {},
google: {},
github: {}
});
/**
* Virtuals
*/
// Public profile information
UserSchema
.virtual('profile')
.get(function() {
return {
name: this.name,
role: this.role
};
});
// Non-sensitive info we'll be putting in the token
UserSchema
.virtual('token')
.get(function() {
return {
_id: this._id,
role: this.role
};
});
/**
* 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('password')
.validate(function(password) {
if(authTypes.indexOf(this.provider) !== -1) {
return true;
}
return password.length;
}, 'Password cannot be blank');
// Validate email is not taken
UserSchema
.path('email')
.validate(function(value) {
if(authTypes.indexOf(this.provider) !== -1) {
return true;
}
return this.constructor.findOne({ email: value }).exec()
.then(user => {
if(user) {
if(this.id === user.id) {
return true;
}
return false;
}
return true;
})
.catch(function(err) {
throw err;
});
}, 'The specified email address is already in use.');
var validatePresenceOf = function(value) {
return value && value.length;
};
/**
* Pre-save hook
*/
UserSchema
.pre('save', function(next) {
// Handle new/update passwords
if(!this.isModified('password')) {
return next();
}
if(!validatePresenceOf(this.password)) {
if(authTypes.indexOf(this.provider) === -1) {
return next(new Error('Invalid password'));
} else {
return next();
}
}
// Make salt with a callback
this.makeSalt((saltErr, salt) => {
if(saltErr) {
return next(saltErr);
}
this.salt = salt;
this.encryptPassword(this.password, (encryptErr, hashedPassword) => {
if(encryptErr) {
return next(encryptErr);
}
this.password = hashedPassword;
return next();
});
});
});
/**
* Methods
*/
UserSchema.methods = {
/**
* Authenticate - check if the passwords are the same
*
* @param {String} password
* @param {Function} callback
* @return {Boolean}
* @api public
*/
authenticate(password, callback) {
if(!callback) {
return this.password === this.encryptPassword(password);
}
this.encryptPassword(password, (err, pwdGen) => {
if(err) {
return callback(err);
}
if(this.password === pwdGen) {
return callback(null, true);
} else {
return callback(null, false);
}
});
},
/**
* Make salt
*
* @param {Number} [byteSize] - Optional salt byte size, default to 16
* @param {Function} callback
* @return {String}
* @api public
*/
makeSalt(...args) {
let byteSize;
let callback;
let defaultByteSize = 16;
if(typeof args[0] === 'function') {
callback = args[0];
byteSize = defaultByteSize;
} else if(typeof args[1] === 'function') {
callback = args[1];
} else {
throw new Error('Missing Callback');
}
if(!byteSize) {
byteSize = defaultByteSize;
}
return crypto.randomBytes(byteSize, (err, salt) => {
if(err) {
return callback(err);
} else {
return callback(null, salt.toString('base64'));
}
});
},
/**
* Encrypt password
*
* @param {String} password
* @param {Function} callback
* @return {String}
* @api public
*/
encryptPassword(password, callback) {
if(!password || !this.salt) {
if(!callback) {
return null;
} else {
return callback('Missing password or salt');
}
}
var defaultIterations = 10000;
var defaultKeyLength = 64;
var salt = new Buffer(this.salt, 'base64');
if(!callback) {
// eslint-disable-next-line no-sync
return crypto.pbkdf2Sync(password, salt, defaultIterations,
defaultKeyLength, 'sha1')
.toString('base64');
}
return crypto.pbkdf2(password, salt, defaultIterations, defaultKeyLength,
'sha1', (err, key) => {
if(err) {
return callback(err);
} else {
return callback(null, key.toString('base64'));
}
});
}
};
registerEvents(UserSchema);
export default mongoose.model('User', UserSchema);