Note: this is my first time posting, if you have feedback please let me know
Goal: I am building some endpoints that let a user reset their password if they forgot it. Flow would look like this:
I am using Insomnia to hit the endpoints for testing.
Things that are working:
Bugs:
Things I have tried:
Here is my code: Any guidance would be appreciated. If you need to look at any other files please let me know.
Forgot.password.js
const router = require('express').Router(); const crypto = require('crypto') const User = require('../models/users.model') const nodemailer = require('nodemailer') router.post('/forgotpassword', (req, res) => { let { email } = req.body console.log(req.body) // if (req.body.email === '') { // res.status(400).json({ message: 'Email is required'}) // } console.error(req.body.email) User.findBy({ email }) .first() .then(user => { if (user === null) { res.status(403).json({ message: 'Email not in db' }) } else { const token = crypto.randomBytes(20).toString('hex') User.update({ resetPasswordToken: token, resetPasswordExpires: Date.now() + 3600000, }) const transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: `${process.env.EMAIL_USER}`, pass: `${process.env.EMAIL_PASS}` } }) const mailOptions = { from: `${process.env.EMAIL_USER}`, to: `${user.email}`, subject: '[Promoquo] Reset Password Link', text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\\n\\n' + 'Please click on the following link, or paste this into your browser to complete the process within one hour of receiving it:\\n\\n' + `http://localhost:5000/reset/${token}\\n\\n` + 'If you did not request this, please ignore this email and your password will remain unchanged.\\n', } transporter.sendMail(mailOptions, (err, res) => { if (err) { console.log('ERROR coming from forgot.password js and it sucks', err) } else { console.log('here is the res', res) res.status(200).json({ message: 'recovery email sent hell yes' }) } }) } res.status(200).json({ message: 'Reset password email has been sent WOOHOO 🎉' }) }) .catch(error => { res.status(500).json({ message: 'ERROR on last catch forgotpassword.js, likely no user exists', error }) console.log(error) }) }) module.exports = router
Update.password.js
const router = require('express').Router(); const passport = require('passport') const bcrypt = require('bcrypt') const User = require('../models/users.model') const BCRYPT_SALT_ROUNDS = 12 router.put('/updatePasswordViaEmail', (req, res) => { User.find({ where: { username: req.body.username, resetPasswordToken: req.body.resetPasswordToken, resetPasswordExpires: Date.now() + 3600000, } }) .then(user => { if (user == null) { console.error('password reset link has expired') res.status(403).json({ message: 'Password reset link is invalid or has expired' }) } else if (user != null) { console.log('user exists in db') bcrypt.hash(req.body.password, BCRYPT_SALT_ROUNDS) .then(hashedPassword => { User.update({ password: hashedPassword, resetPasswordToken: null, resetPasswordExpires: null, }) }) .then(() => { console.log('log for THEN updating password') res.status(200).json({ message: 'password updated' }) }) } else { console.error('no user exists in db to update') res.status(401).json({ message: 'no user exists in db to update'}) } }) }) module.exports = router
Users.model.js
const db = require('../dbConfig') module.exports = { add, find, findBy, findById, findByEmail, findByType, update }; function find() { return db('users').select('id', 'username', 'email', 'password'); } function findBy(filter) { return db('users').where(filter); } async function add(user) { const [id] = await db('users').insert(user); return findById(id); } function findById(id) { return db('users').where({ id }).first(); } function findByEmail(email) { return db('users').where({ email }).first(); } function findByType(type) { return db('users').where({ type }).first(); } function update(changes, id) { return db('users').where({ id }).update(changes) }
20200913211559_users.js (this is the table)
exports.up = function(knex) { return knex.schema.createTable('users', tbl => { tbl.increments(); tbl.string('firstname', 30).notNullable(); tbl.string('lastname', 30).notNullable(); tbl.string('username', 30).notNullable() tbl.string('email', 50).notNullable() tbl.string('password', 128).notNullable(); tbl.string('type').notNullable(); tbl.boolean('confirmed').defaultTo('false'); tbl.string('resetPasswordToken'); tbl.date('resetPasswordExpires'); }) }; exports.down = function(knex) { return knex.schema.dropTableIfExists('users') };
Your User.update()
lines aren't running (you either need to return their promises into the chains of promises, or hook into their callbacks). async/await
is your friend here to avoid "callback hell."
const user = await User.find({
where: {
username: req.body.username,
resetPasswordToken: req.body.resetPasswordToken,
resetPasswordExpires: Date.now() + 3600000,
}
})
if (!user) { /* ... */ }
const token = crypto.randomBytes(20).toString('hex')
await User.update({ // await here!
resetPasswordToken: token,
resetPasswordExpires: Date.now() + 3600000,
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.