From afb52b4084f9cd3483b52f30f7cbfe5ae6fa6d92 Mon Sep 17 00:00:00 2001 From: Keith Irwin Date: Wed, 13 Dec 2017 20:29:22 +0000 Subject: [PATCH] #64 Returned promises in model method definitions --- config/models.js | 204 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 144 insertions(+), 60 deletions(-) diff --git a/config/models.js b/config/models.js index a2565bc..61dd392 100644 --- a/config/models.js +++ b/config/models.js @@ -47,94 +47,178 @@ const userSchema = new mongoose.Schema({ }).plugin(unique) /* User methods */ -// TODO: Return promises instead of taking callbacks -// See https://gist.github.com/7h1b0/5154fda207e68ad1cefc#file-random-js -// For an example // Create email confirmation token -userSchema.methods.createEmailToken = function (next) { // next(err,token) +userSchema.methods.createEmailToken = function (next) { debug('user.createEmailToken() called') var user = this - crypto.randomBytes(16, (err, buf) => { - if (err) return next(err) - if (buf) { - debug(`Buffer ${buf.toString('hex')} created`) - user.emailToken = buf.toString('hex') + // Callback next(err, token) + if (typeof next === 'function') { + crypto.randomBytes(16, (err, buf) => { + if (err) return next(err) + if (buf) { + debug(`Buffer ${buf.toString('hex')} created`) + user.emailToken = buf.toString('hex') + user.save() + .then(() => { + return next(null, user.emailToken) + }) + .catch((err) => { + return next(err) + }) + } + }) + + // Promise + } else return new Promise((resolve, reject) => { + crypto.randomBytes(16, (err, buf) => { + if (err) reject(err) + if (buf) { + debug(`Buffer ${buf.toString('hex')} created`) + user.emailToken = buf.toString('hex') + user.save() + .then(() => { + resolve(user.emailToken) + }) + .catch((err) => { + reject(err) + }) + } + }) + }) + +} + +// Create password reset token +userSchema.methods.createPassToken = function (next) { + debug('user.createPassToken() called') + var user = this + + // Callback next(err, token, expires) + if (typeof next === 'function') { + + // Reuse old token, resetting clock + if (user.auth.passTokenExpires >= Date.now()) { + debug(`Reusing old password token...`) + user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour user.save() .then(() => { - return next(null, user.emailToken) + return next(null, user.auth.passToken, user.auth.passTokenExpires) }) .catch((err) => { - return next(err, null) + return next(err) + }) + + // Create new token + } else { + debug(`Creating new password token...`) + crypto.randomBytes(16, (err, buf) => { + if (err) return next(err) + if (buf) { + user.auth.passToken = buf.toString('hex') + user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour + user.save() + .then(() => { + debug('successfully saved user in createPassToken') + return next(null, user.auth.passToken, user.auth.passTokenExpires) + }) + .catch((err) => { + debug('error saving user in createPassToken') + return next(err) + }) + } + }) + } + + // Promise + + } else return new Promise((resolve, reject) => { + + // Reuse old token, resetting clock + if (user.auth.passTokenExpires >= Date.now()) { + debug(`Reusing old password token...`) + user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour + user.save() + .then(() => { + resolve(user.auth.passToken, user.auth.passTokenExpires) + }) + .catch((err) => { + reject(err) + }) + + // Create new token + } else { + debug(`Creating new password token...`) + crypto.randomBytes(16, (err, buf) => { + if (err) return next(err) + if (buf) { + user.auth.passToken = buf.toString('hex') + user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour + user.save() + .then(() => { + debug('successfully saved user in createPassToken') + resolve(user.auth.passToken, user.auth.passTokenExpires) + }) + .catch((err) => { + debug('error saving user in createPassToken') + reject(err) + }) + } }) } }) } -// Create password reset token -userSchema.methods.createPassToken = function (next) { // next(err,token,expires) - var user = this - - // Reuse old token, resetting clock - if (user.auth.passTokenExpires >= Date.now()) { - debug(`Reusing old password token...`) - user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour - user.save() - .then(() => { - return next(null, user.auth.passToken, user.auth.passTokenExpires) - }) - .catch((err) => { - return next(err) - }) - - // Create new token - } else { - debug(`Creating new password token...`) - crypto.randomBytes(16, (err, buf) => { - if (err) return next(err) - if (buf) { - user.auth.passToken = buf.toString('hex') - user.auth.passTokenExpires = Date.now() + 3600000 // 1 hour - user.save() - .then(() => { - debug('successfully saved user in createPassToken') - return next(null, user.auth.passToken, user.auth.passTokenExpires) - }) - .catch((err) => { - debug('error saving user in createPassToken') - return next(err) - }) - } - }) - } -} - // Generate hash for new password and save it to the database userSchema.methods.generateHashedPassword = function (password, next) { - // next(err); // Delete token this.auth.passToken = undefined this.auth.passTokenExpires = undefined - // Generate hash - bcrypt.genSalt(8, (err, salt) => { - if (err) return next(err) - bcrypt.hash(password, salt, (err, hash) => { + // Callback next(err, token, expires) + if (typeof next === 'function') { + + // Generate hash + bcrypt.genSalt(8, (err, salt) => { if (err) return next(err) - this.auth.password = hash - this.save() - next() + bcrypt.hash(password, salt, (err, hash) => { + if (err) return next(err) + this.auth.password = hash + this.save() + .then(next) + .catch((err) => next(err) ) + }) }) + + } else return new Promise((resolve, reject) => { + + // Generate hash + bcrypt.genSalt(8, (err, salt) => { + if (err) reject(err) + bcrypt.hash(password, salt, (err, hash) => { + if (err) reject(err) + this.auth.password = hash + this.save() + .then(resolve) + .catch( (err) => reject(err) ) + }) + }) + }) } // Check for valid password userSchema.methods.validPassword = function (password, next) { - // next(err,res); - // res = true/false - bcrypt.compare(password, this.auth.password, next) + // Callback next(err, res) + if (typeof next === 'function') bcrypt.compare(password, this.auth.password, next) + else bcrypt.compare(password, this.auth.password) + .then((result) => { + if (result===true) resolve() + else reject(new Error('Passwords don\'t match')) + }) + .catch( (err) => reject(err) ) } module.exports = {