2015-06-29 22:51:29 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Module dependencies.
|
|
|
|
*/
|
|
|
|
var mongoose = require('mongoose'),
|
|
|
|
Schema = mongoose.Schema,
|
2015-07-07 01:21:43 +00:00
|
|
|
crypto = require('crypto'),
|
|
|
|
config = require('../../config/config'),
|
2017-10-11 05:07:13 +00:00
|
|
|
timeStampPlugin = require('../libs/timestamp.server.plugin'),
|
2016-07-05 00:24:27 +00:00
|
|
|
path = require('path'),
|
2017-11-06 21:44:29 +00:00
|
|
|
querystring = require('querystring');
|
2015-06-29 22:51:29 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A Validation function for local strategy properties
|
|
|
|
*/
|
|
|
|
var validateLocalStrategyProperty = function(property) {
|
2016-03-30 03:45:16 +00:00
|
|
|
var propHasLength;
|
|
|
|
if (property) {
|
|
|
|
propHasLength = !!property.length;
|
|
|
|
} else {
|
|
|
|
propHasLength = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((this.provider !== 'local' && !this.updated) || propHasLength);
|
2015-06-29 22:51:29 +00:00
|
|
|
};
|
|
|
|
|
2016-11-09 20:25:38 +00:00
|
|
|
/**
|
|
|
|
* A Validation function for username
|
|
|
|
*/
|
|
|
|
var validateUsername = function(username) {
|
2017-10-28 02:29:19 +00:00
|
|
|
return (username.match(/^[a-zA-Z0-9.-_]+$/) !== null);
|
2016-11-09 20:25:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-06-29 22:51:29 +00:00
|
|
|
/**
|
|
|
|
* User Schema
|
|
|
|
*/
|
|
|
|
var UserSchema = new Schema({
|
|
|
|
firstName: {
|
|
|
|
type: String,
|
|
|
|
trim: true,
|
2017-04-23 04:13:56 +00:00
|
|
|
default: ''
|
2015-06-29 22:51:29 +00:00
|
|
|
},
|
|
|
|
lastName: {
|
|
|
|
type: String,
|
|
|
|
trim: true,
|
2017-04-23 04:13:56 +00:00
|
|
|
default: ''
|
2015-06-29 22:51:29 +00:00
|
|
|
},
|
|
|
|
email: {
|
|
|
|
type: String,
|
|
|
|
trim: true,
|
2017-10-28 06:23:50 +00:00
|
|
|
lowercase: true,
|
2015-08-07 21:02:44 +00:00
|
|
|
unique: 'Account already exists with this email',
|
2017-10-28 02:29:19 +00:00
|
|
|
match: [/.+\@.+\..+/, 'Please fill a valid email address'],
|
|
|
|
required: [true, 'Email is required']
|
2015-06-29 22:51:29 +00:00
|
|
|
},
|
|
|
|
username: {
|
|
|
|
type: String,
|
2015-07-27 18:11:43 +00:00
|
|
|
unique: true,
|
2016-11-02 18:30:04 +00:00
|
|
|
lowercase: true,
|
2017-10-28 06:23:50 +00:00
|
|
|
match: [/^[a-zA-Z0-9\-]+$/, 'Username can only contain alphanumeric characters and \'-\''],
|
2017-10-28 02:29:19 +00:00
|
|
|
required: [true, 'Username is required']
|
2015-06-29 22:51:29 +00:00
|
|
|
},
|
2015-08-11 20:32:27 +00:00
|
|
|
passwordHash: {
|
2015-06-29 22:51:29 +00:00
|
|
|
type: String,
|
2016-03-30 01:16:36 +00:00
|
|
|
default: ''
|
2015-06-29 22:51:29 +00:00
|
|
|
},
|
|
|
|
salt: {
|
|
|
|
type: String
|
|
|
|
},
|
|
|
|
provider: {
|
|
|
|
type: String,
|
2016-05-10 06:30:09 +00:00
|
|
|
default: 'local'
|
2015-06-29 22:51:29 +00:00
|
|
|
},
|
|
|
|
providerData: {},
|
|
|
|
additionalProvidersData: {},
|
|
|
|
roles: {
|
|
|
|
type: [{
|
|
|
|
type: String,
|
2015-07-21 23:25:45 +00:00
|
|
|
enum: ['user', 'admin', 'superuser']
|
2015-06-29 22:51:29 +00:00
|
|
|
}],
|
|
|
|
default: ['user']
|
|
|
|
},
|
2015-07-07 01:21:43 +00:00
|
|
|
language: {
|
|
|
|
type: String,
|
2016-06-16 00:38:22 +00:00
|
|
|
enum: ['en', 'fr', 'es', 'it', 'de'],
|
|
|
|
default: 'en',
|
2015-07-07 01:21:43 +00:00
|
|
|
},
|
2015-07-27 18:11:43 +00:00
|
|
|
lastModified: {
|
2015-06-29 22:51:29 +00:00
|
|
|
type: Date
|
|
|
|
},
|
|
|
|
created: {
|
|
|
|
type: Date,
|
|
|
|
default: Date.now
|
|
|
|
},
|
2015-07-21 23:25:45 +00:00
|
|
|
|
2015-06-29 22:51:29 +00:00
|
|
|
/* For reset password */
|
|
|
|
resetPasswordToken: {
|
|
|
|
type: String
|
|
|
|
},
|
|
|
|
resetPasswordExpires: {
|
|
|
|
type: Date
|
|
|
|
},
|
2016-08-26 00:54:16 +00:00
|
|
|
token: String,
|
|
|
|
apiKey: {
|
|
|
|
type: String,
|
|
|
|
unique: true,
|
|
|
|
index: true,
|
|
|
|
sparse: true
|
2017-04-23 04:13:56 +00:00
|
|
|
}
|
2015-06-29 22:51:29 +00:00
|
|
|
});
|
|
|
|
|
2015-07-28 22:29:07 +00:00
|
|
|
UserSchema.virtual('displayName').get(function () {
|
|
|
|
return this.firstName + ' ' + this.lastName;
|
|
|
|
});
|
|
|
|
|
2017-10-11 05:07:13 +00:00
|
|
|
UserSchema.plugin(timeStampPlugin, {
|
2015-10-06 20:14:38 +00:00
|
|
|
createdPath: 'created',
|
|
|
|
modifiedPath: 'lastModified',
|
|
|
|
useVirtual: false
|
|
|
|
});
|
2015-07-28 22:29:07 +00:00
|
|
|
|
2015-06-29 22:51:29 +00:00
|
|
|
/**
|
|
|
|
* Hook a pre save method to hash the password
|
|
|
|
*/
|
2015-08-11 20:32:27 +00:00
|
|
|
UserSchema.virtual('password').set(function (password) {
|
|
|
|
this.passwordHash = this.hashPassword(password);
|
|
|
|
});
|
|
|
|
UserSchema.virtual('password').get(function () {
|
|
|
|
return this.passwordHash;
|
2015-06-29 22:51:29 +00:00
|
|
|
});
|
|
|
|
|
2015-08-11 20:32:27 +00:00
|
|
|
|
2015-06-29 22:51:29 +00:00
|
|
|
/**
|
|
|
|
* Create instance method for hashing a password
|
|
|
|
*/
|
|
|
|
UserSchema.methods.hashPassword = function(password) {
|
2017-06-22 13:51:22 +00:00
|
|
|
var encoding = 'base64';
|
|
|
|
var iterations = 10000;
|
|
|
|
var keylen = 128;
|
|
|
|
var size = 64;
|
|
|
|
var digest = 'SHA1';
|
|
|
|
|
2015-08-11 20:32:27 +00:00
|
|
|
//Generate salt if it doesn't exist yet
|
|
|
|
if(!this.salt){
|
2017-06-22 13:51:22 +00:00
|
|
|
this.salt = crypto.randomBytes(size).toString(encoding);
|
2015-08-11 20:32:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (password) {
|
2017-06-22 13:51:22 +00:00
|
|
|
return crypto.pbkdf2Sync(password, new Buffer(this.salt, encoding), iterations, keylen, digest).toString(encoding);
|
2015-06-29 22:51:29 +00:00
|
|
|
} else {
|
|
|
|
return password;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create instance method for authenticating user
|
|
|
|
*/
|
|
|
|
UserSchema.methods.authenticate = function(password) {
|
|
|
|
return this.password === this.hashPassword(password);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find possible not used username
|
|
|
|
*/
|
|
|
|
UserSchema.statics.findUniqueUsername = function(username, suffix, callback) {
|
|
|
|
var _this = this;
|
|
|
|
var possibleUsername = username + (suffix || '');
|
|
|
|
|
|
|
|
_this.findOne({
|
|
|
|
username: possibleUsername
|
|
|
|
}, function(err, user) {
|
|
|
|
if (!err) {
|
|
|
|
if (!user) {
|
2017-04-23 04:13:56 +00:00
|
|
|
return callback(possibleUsername);
|
2015-06-29 22:51:29 +00:00
|
|
|
} else {
|
|
|
|
return _this.findUniqueUsername(username, (suffix || 0) + 1, callback);
|
|
|
|
}
|
|
|
|
}
|
2017-04-23 04:13:56 +00:00
|
|
|
return callback(null);
|
2015-06-29 22:51:29 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-07-02 02:49:35 +00:00
|
|
|
/**
|
|
|
|
* Function to check if user has Admin priviledges
|
|
|
|
*/
|
|
|
|
UserSchema.methods.isAdmin = function() {
|
|
|
|
if(this.roles.indexOf('admin') !== -1){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2015-11-05 22:07:56 +00:00
|
|
|
module.exports = mongoose.model('User', UserSchema);
|