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' ) ,
fs = require ( 'fs-extra' ) ,
2015-10-06 20:14:38 +00:00
mUtilities = require ( 'mongoose-utilities' ) ,
2016-07-05 00:24:27 +00:00
path = require ( 'path' ) ,
querystring = require ( 'querystring' ) ,
config = require ( '../../config/config' ) ,
nodemailer = require ( 'nodemailer' ) ;
var smtpTransport = nodemailer . createTransport ( config . mailer . options ) ;
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
} ;
/ * *
* A Validation function for local strategy password
* /
var validateLocalStrategyPassword = function ( password ) {
return ( this . provider !== 'local' || ( password && password . length > 6 ) ) ;
} ;
/ * *
* User Schema
* /
var UserSchema = new Schema ( {
firstName : {
type : String ,
trim : true ,
default : '' ,
2016-08-25 23:33:10 +00:00
/ * v a l i d a t e : {
2016-03-30 03:45:16 +00:00
validator : validateLocalStrategyProperty ,
2016-03-30 01:16:36 +00:00
message : 'Please fill in your first name'
2016-08-25 23:33:10 +00:00
} * /
2015-06-29 22:51:29 +00:00
} ,
lastName : {
type : String ,
trim : true ,
default : '' ,
2016-08-25 23:33:10 +00:00
/ * v a l i d a t e : {
2016-03-30 03:45:16 +00:00
validator : validateLocalStrategyProperty ,
2016-03-30 01:16:36 +00:00
message : 'Please fill in your last name'
2016-08-25 23:33:10 +00:00
} * /
2015-06-29 22:51:29 +00:00
} ,
email : {
type : String ,
trim : true ,
2015-08-07 21:02:44 +00:00
unique : 'Account already exists with this email' ,
2015-07-27 18:11:43 +00:00
required : 'Please enter your email' ,
2016-03-30 01:16:36 +00:00
validate : {
2016-03-30 03:45:16 +00:00
validator : validateLocalStrategyProperty ,
2016-03-30 01:16:36 +00:00
message : 'Please fill in your email'
} ,
2015-06-29 22:51:29 +00:00
match : [ /.+\@.+\..+/ , 'Please fill a valid email address' ]
} ,
username : {
type : String ,
2015-07-27 18:11:43 +00:00
unique : true ,
2015-08-07 21:02:44 +00:00
required : false ,
2015-06-29 22:51:29 +00:00
trim : true
} ,
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
required : 'Provider is required' ,
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
required : 'User must have a language'
} ,
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
} ,
token : String
} ) ;
2015-07-28 22:29:07 +00:00
UserSchema . virtual ( 'displayName' ) . get ( function ( ) {
return this . firstName + ' ' + this . lastName ;
} ) ;
2015-10-06 20:14:38 +00:00
UserSchema . plugin ( mUtilities . timestamp , {
createdPath : 'created' ,
modifiedPath : 'lastModified' ,
useVirtual : false
} ) ;
2015-07-28 22:29:07 +00:00
2016-07-05 00:49:26 +00:00
/ *
2016-07-05 00:46:14 +00:00
UserSchema . pre ( 'find' , function ( next ) {
//Change username if it is still the user's email
if ( this . username === this . email ) {
var emailUsername = this . email . split ( '@' ) [ 0 ] ;
this . username = querystring . stringify ( { query : emailUsername } ) ;
var mailOptions = {
from : '"TellForm Support" <noreply@tellform.com>' , // sender address
to : this . email , // list of receivers
subject : 'Your TellForm Username has Changed' , // Subject line
text : 'Due to upgrades, your TellForm username has change from ' + this . email + ' to ' + this . username + '. Please use your new username to login.\n Using your old username will not work.\n We apologize for the inconvenience,\n - the TellForm team' , // plaintext body
} ;
transporter . sendMail ( mailOptions , function ( error , info ) {
if ( error ) {
return console . error ( error ) ;
}
console . log ( 'Username change message sent: ' + info . response ) ;
} ) ;
}
2016-07-05 00:49:26 +00:00
} ) ; * /
2016-07-05 00:46:14 +00:00
2015-07-07 01:21:43 +00:00
UserSchema . pre ( 'save' , function ( next ) {
2016-07-05 00:24:27 +00:00
//Change username if it is still the user's email
if ( this . username === this . email ) {
var emailUsername = this . email . split ( '@' ) [ 0 ] ;
this . username = querystring . stringify ( { query : emailUsername } ) ;
var mailOptions = {
from : '"TellForm Support" <noreply@tellform.com>' , // sender address
to : this . email , // list of receivers
subject : 'Your TellForm Username has Changed' , // Subject line
text : 'Due to upgrades, your TellForm username has change from ' + this . email + ' to ' + this . username + '. Please use your new username to login.\n Using your old username will not work.\n We apologize for the inconvenience,\n - the TellForm team' , // plaintext body
} ;
2016-07-05 00:51:25 +00:00
smtpTransport . sendMail ( mailOptions , function ( error , info ) {
2016-07-05 00:24:27 +00:00
if ( error ) {
return console . error ( error ) ;
}
console . log ( 'Username change message sent: ' + info . response ) ;
} ) ;
}
//Create folder for user's pdfs
2016-04-10 21:23:13 +00:00
if ( process . env . NODE _ENV === 'local-development' ) {
2015-07-30 00:32:46 +00:00
var newDestination = path . join ( config . pdfUploadPath , this . username . replace ( / /g , '' ) ) ,
stat = null ;
2015-07-07 01:21:43 +00:00
2015-07-30 00:32:46 +00:00
try {
stat = fs . statSync ( newDestination ) ;
} catch ( err ) {
fs . mkdirSync ( newDestination ) ;
}
if ( stat && ! stat . isDirectory ( ) ) {
// console.log('Directory cannot be created');
next ( new Error ( 'Directory cannot be created because an inode of a different type exists at "' + newDestination + '"' ) ) ;
} else {
next ( ) ;
}
2016-03-30 01:16:36 +00:00
}
2015-07-30 00:32:46 +00:00
next ( ) ;
2015-07-07 01:21:43 +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 ) {
2015-08-11 20:32:27 +00:00
//Generate salt if it doesn't exist yet
if ( ! this . salt ) {
this . salt = crypto . randomBytes ( 64 ) . toString ( 'base64' ) ;
}
if ( password ) {
return crypto . pbkdf2Sync ( password , new Buffer ( this . salt , 'base64' ) , 10000 , 128 ) . toString ( 'base64' ) ;
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 ) {
callback ( possibleUsername ) ;
} else {
return _this . findUniqueUsername ( username , ( suffix || 0 ) + 1 , callback ) ;
}
} else {
callback ( null ) ;
}
} ) ;
} ;
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 ) ;