2017-12-12 17:40:07 -07:00
|
|
|
'use strict'
|
2017-04-01 11:03:31 -06:00
|
|
|
|
2017-12-12 17:40:07 -07:00
|
|
|
const mongoose = require('mongoose')
|
|
|
|
const unique = require('mongoose-unique-validator')
|
|
|
|
const bcrypt = require('bcrypt')
|
|
|
|
const crypto = require('crypto')
|
|
|
|
const debug = require('debug')('tracman-models')
|
2017-04-01 11:03:31 -06:00
|
|
|
|
|
|
|
const userSchema = new mongoose.Schema({
|
2017-12-12 17:40:07 -07:00
|
|
|
name: {type: String},
|
|
|
|
email: {type: String, unique: true},
|
|
|
|
newEmail: String,
|
|
|
|
emailToken: String,
|
|
|
|
slug: {type: String, required: true, unique: true},
|
|
|
|
auth: {
|
|
|
|
password: String,
|
|
|
|
passToken: String,
|
|
|
|
passTokenExpires: Date,
|
|
|
|
google: String,
|
|
|
|
facebook: String,
|
|
|
|
twitter: String
|
|
|
|
},
|
|
|
|
isAdmin: {type: Boolean, required: true, default: false},
|
|
|
|
isPro: {type: Boolean, required: true, default: false},
|
|
|
|
created: {type: Date, required: true},
|
|
|
|
lastLogin: Date,
|
2018-02-01 09:02:12 -07:00
|
|
|
isNewUser: Boolean,
|
2017-12-12 17:40:07 -07:00
|
|
|
settings: {
|
|
|
|
units: {type: String, default: 'standard'},
|
|
|
|
defaultMap: {type: String, default: 'road'},
|
|
|
|
defaultZoom: {type: Number, default: 11},
|
|
|
|
showScale: {type: Boolean, default: false},
|
|
|
|
showSpeed: {type: Boolean, default: false},
|
|
|
|
showTemp: {type: Boolean, default: false},
|
|
|
|
showAlt: {type: Boolean, default: false},
|
|
|
|
showStreetview: {type: Boolean, default: false},
|
|
|
|
marker: {type: String, default: 'red'}
|
|
|
|
},
|
|
|
|
last: {
|
|
|
|
time: Date,
|
|
|
|
lat: {type: Number, default: 0},
|
|
|
|
lon: {type: Number, default: 0},
|
|
|
|
dir: {type: Number, default: 0},
|
|
|
|
alt: {type: Number},
|
|
|
|
spd: {type: Number, default: 0}
|
|
|
|
},
|
|
|
|
sk32: {type: String, required: true, unique: true}
|
|
|
|
}).plugin(unique)
|
2017-04-09 21:40:08 -06:00
|
|
|
|
2017-12-12 17:40:07 -07:00
|
|
|
/* User methods */
|
2018-01-19 14:23:43 -07:00
|
|
|
// Do not replace with arrow functions!
|
|
|
|
// https://stackoverflow.com/a/37875212
|
2017-04-27 14:44:49 -06:00
|
|
|
|
2017-12-12 17:40:07 -07:00
|
|
|
// Create email confirmation token
|
2018-01-19 14:23:43 -07:00
|
|
|
userSchema.methods.createEmailToken = function () {
|
|
|
|
debug(`user.createEmailToken() called for ${user.id}`)
|
|
|
|
let user = this
|
2017-12-12 17:40:07 -07:00
|
|
|
|
2018-01-19 14:23:43 -07:00
|
|
|
return new Promise((resolve, reject) => {
|
2018-01-20 20:45:25 -07:00
|
|
|
crypto.randomBytes(16, async (err, buf) => {
|
2018-01-19 14:23:43 -07:00
|
|
|
if (err) return reject(err)
|
2017-12-13 13:29:22 -07:00
|
|
|
if (buf) {
|
|
|
|
debug(`Buffer ${buf.toString('hex')} created`)
|
|
|
|
user.emailToken = buf.toString('hex')
|
2018-01-20 20:45:25 -07:00
|
|
|
try {
|
|
|
|
await user.save()
|
2017-12-13 13:29:22 -07:00
|
|
|
resolve(user.emailToken)
|
2018-01-20 20:45:25 -07:00
|
|
|
} catch (err) { reject(err) }
|
2017-12-13 13:29:22 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create password reset token
|
2018-01-19 14:23:43 -07:00
|
|
|
userSchema.methods.createPassToken = function () {
|
|
|
|
let user = this
|
|
|
|
debug(`user.createPassToken() called for ${user.id}`)
|
2017-12-13 13:29:22 -07:00
|
|
|
|
2018-01-20 20:45:25 -07:00
|
|
|
return new Promise( async (resolve, reject) => {
|
2017-12-13 13:29:22 -07:00
|
|
|
|
2018-03-04 14:17:54 -07:00
|
|
|
// Reuse old token
|
2017-12-13 13:29:22 -07:00
|
|
|
if (user.auth.passTokenExpires >= Date.now()) {
|
|
|
|
debug(`Reusing old password token...`)
|
2018-03-04 14:17:54 -07:00
|
|
|
resolve([user.auth.passToken, user.auth.passTokenExpires])
|
2017-12-13 13:29:22 -07:00
|
|
|
|
|
|
|
// Create new token
|
|
|
|
} else {
|
|
|
|
debug(`Creating new password token...`)
|
2018-01-20 20:45:25 -07:00
|
|
|
crypto.randomBytes(16, async (err, buf) => {
|
2018-01-19 14:23:43 -07:00
|
|
|
if (err) return reject(err)
|
2017-12-13 13:29:22 -07:00
|
|
|
if (buf) {
|
|
|
|
user.auth.passToken = buf.toString('hex')
|
|
|
|
user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour
|
2018-01-20 20:45:25 -07:00
|
|
|
try {
|
|
|
|
await user.save()
|
|
|
|
debug('Successfully saved user in createPassToken')
|
|
|
|
resolve([user.auth.passToken, user.auth.passTokenExpires])
|
|
|
|
} catch (err) {
|
|
|
|
debug('Error saving user in createPassToken')
|
2017-12-13 13:29:22 -07:00
|
|
|
reject(err)
|
2018-01-20 20:45:25 -07:00
|
|
|
}
|
2017-12-13 13:29:22 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-01-19 14:23:43 -07:00
|
|
|
|
2017-12-13 13:29:22 -07:00
|
|
|
})
|
2018-01-19 14:23:43 -07:00
|
|
|
|
2017-12-12 17:40:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generate hash for new password and save it to the database
|
2018-01-19 14:23:43 -07:00
|
|
|
userSchema.methods.generateHashedPassword = function (password) {
|
|
|
|
debug(`user.generateHashedPassword() called for ${this.id}`)
|
2017-12-12 17:40:07 -07:00
|
|
|
|
|
|
|
// Delete token
|
|
|
|
this.auth.passToken = undefined
|
|
|
|
this.auth.passTokenExpires = undefined
|
|
|
|
|
2018-01-19 14:23:43 -07:00
|
|
|
return new Promise((resolve, reject) => {
|
2017-12-13 13:29:22 -07:00
|
|
|
|
|
|
|
// Generate hash
|
|
|
|
bcrypt.genSalt(8, (err, salt) => {
|
2017-12-18 23:45:04 -07:00
|
|
|
if (err) return reject(err)
|
2018-01-20 20:45:25 -07:00
|
|
|
bcrypt.hash(password, salt, async (err, hash) => {
|
2017-12-18 23:45:04 -07:00
|
|
|
if (err) return reject(err)
|
2017-12-13 13:29:22 -07:00
|
|
|
this.auth.password = hash
|
2018-01-20 20:45:25 -07:00
|
|
|
try {
|
|
|
|
await this.save()
|
|
|
|
resolve()
|
|
|
|
} catch (err) { reject() }
|
2017-12-13 13:29:22 -07:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2017-12-12 17:40:07 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for valid password
|
2018-01-19 14:23:43 -07:00
|
|
|
userSchema.methods.validPassword = function (password) {
|
|
|
|
let user = this
|
|
|
|
debug(`user.validPassword() called for ${user.id}`)
|
|
|
|
return bcrypt.compare(password, user.auth.password)
|
2017-04-09 21:40:08 -06:00
|
|
|
}
|
2017-04-01 11:03:31 -06:00
|
|
|
|
|
|
|
module.exports = {
|
2017-12-12 17:40:07 -07:00
|
|
|
'user': mongoose.model('User', userSchema)
|
|
|
|
}
|