Issue
Hi everyone am trying to hash my put request using bcrypt in my express-mongoose server
the put request
// updating a user
router.put('/:id', async (req, res) => {
const {error} = validate(req.body)
if (error) return res.status(400).send(error.details[0].message)
const user = await User.findByIdAndUpdate(req.params.id, {
$set : {
name: req.body.name,
email: req.body.email,
password: req.body.password
}
})
// hashing user passwords
const salt = await bcrypt.genSalt(10)
user.password = await bcrypt.hash(user.password, salt)
if (!user) return res.status(404).send('User with that id does not exist')
res.send(user)
})
All other functions inside the update request is working perfectly apart from hashing the updated password. As a newbie I need your help/ best approach recommendation in this.
Thanks in advance…
Solution
Solution 1: Easy Way
For your personal solution, without really modifying the code, it works like the following.
// updating a user
router.put('/:id', async (req, res) => {
const {error} = validate(req.body)
if (error) return res.status(400).send(error.details[0].message)
// Why not make the hash function here?
const salt = await bcrypt.genSalt(10)
const newPassword = await bcrypt.hash(req.body.password, salt)
const user = await User.findByIdAndUpdate(req.params.id, {
$set : {
name: req.body.name,
email: req.body.email,
password: newPassword
}
})
if (!user) return res.status(404).send('User with that id does not exist')
res.send(user)
})
You have a mistake in your user.password
call. The findByIdAndUpdate
method does not return an object that you can modify instantly. In above workaround, we simply move the function so that it hashes the new password first before updating your document.
Solution 2: My Own Style
For my personal solution, I’d go like this. Let’s say that you have a userModel
that stores the schema of your User
entity. I will add a new middleware that will run every time the password changes.
/** your user schema code. **/
userSchema.pre('save', async function (next) {
// Only run the encryption if password is modified.
if (!this.isModified('password')) {
return next();
}
// Hash the password with BCRYPT Algorithm, with 12 characters of randomly generated salt.
this.password = await bcrypt.hash(this.password, 12);
next();
});
Next, we’ll create a new dedicated route in order to handle password changes. I think it’s better if we define a new route for it as passwords are sensitive data. Below is pseudocode, don’t instantly copy and paste it, it wouldn’t work.
const user = await User.findById(...);
user.password = req.body.password;
await user.save({ validateBeforeSave: true });
Remember that save
middleware runs every time after the save
command is run.
Further reading about Mongoose’s middlewares here.