How update the password in mongodb - node.js

app.get('/changePass', function(req, res) {
password = req.body.password;
password1 = req.body.password1;
xyz = req.body.xyz;
User.find({ email: xyz, password: password }, function(err, data) {
if (err) {
throw err;
}
if (data.length === 0) {
return res.json({ success: false, data: 'please enter valid
Old password' })
} else {
// User.update({ password: password }, {
// $set: {
// password: password1
// }
// });
var usr = new User();
usr.update({ "password":password }, password1, { upsert:true
});
//usr.password = password;
usr.save(function(err, data) {
if (err)
throw err;
return res.json({ success: true, data: 'password changed
successfully' });
})
}
})
how i update password in mongodb i am matching password to password and updating password to password1.this is giving me alert with please enter valid old password.
xyz is cookie that contains email.

You should use findOne on model to return userObject.
Then you can update the object that was found like regular javascript object and save it with .save function.
User.findOne({email: xyz, password: req.body.password1}, function(err, user){
if(err)return handleErr(err);
user.password = req.body.password2;
user.save(function(err){
if(err)return handleErr(err);
//user has been updated
});
});

Related

Nodejs password reset I get an emai and click on the link but the new password does not change. I can only log in with old password

I am 99% done with my password reset application. I get an email for the password reset, but my new password change does not change in my mongodb. I can't log in with new password only old password. What am I doing wrong
router.post('/reset/:token', function(req, res) {
async.waterfall([
function(done) {
Account.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
if (!user) {
req.flash('error', 'Password reset token is invalid or has expired.');
return res.redirect('back');
}
user.password = req.body.password;
//user.password = hashedPassword;
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
user.save(function(err) {
req.logIn(user, function(err) {
done(err, user);
});
});
});
},
function(user, done) {
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth:{
user: '',
pass: ''
}
});
var mailOptions = {
to: user.email,
from: '',
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n'
};
transporter.sendMail(mailOptions, function(err) {
req.flash('success', 'Success! Your password has been changed.');
done(err);
});
}
], function(err) {
res.redirect('/');
});
});
I figured it out. I had to user setPassword function
if(req.body.password === req.body.confirm) {
user.setPassword(req.body.password, function(err) {
Thanks.

Reset Password. Token Expire every time in MEAN Stack

i am new in MEAN Stack, working on forgot password and reset password. i complete forgot password front end with Angular 8 and node and express. Mail sent to user email for reset password. but whenever i click on link given in mail message show "TOken expires"
forgot password node js:-
exports.forgot_password= function(req, res){
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ userEmail: req.body.userEmail }, function(err, user) {
if (!user) {
return res.json({status:false, message:'E-Mail not Found'})
}
console.log('step 1')
user.reset_password_token = token;
user.reset_password_expaire = Date.now() + 3600000; // 1 hour
user.save(function(err) {
done(err,token, user);
});
});
},
function(token, user, done) {
console.log('step 2')
var smtpTrans = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'myemail',
pass: 'mypass'
}
});
console.log('step 3')
smtpTrans.sendMail({
from: 'myemail',
to:user.userEmail,
subject:'Password Reset',
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:\n\n' +
'http://' + req.headers.host + '/api/reset_password/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n',
});
console.log('Email Send');
}
], function(err) {
console.log('this err' + ' ' + err)
});
};
Reset Password
exports.reset_password= function(req, res,next) {
console.log('Step 1');
User.findOne({
reset_password_token: req.body.token,
reset_password_expires: {$gt: Date.now()}
})
.exec(function(err, user) {
console.log ('step 2')
if (!err && user) {
if (req.body.userPassword === req.body.userConfPassword) {
user.hash_password = bcrypt.hash(req.body.newPassword, 10);
user.reset_password_token = undefined;
user.reset_password_expires = undefined;
user.save(function(err) {
if (err) {
return res.status(422).send({
message: err
});
} else {
var data = {
to: user.userEmail,
from: 'myemail',
subject: 'Password Reset Confirmation',
text: 'Hello,\n\n' +
' - This is a confirmation that the password for your account ' + user.userEmail + ' has just been changed.\n',
};
smtpTransport.sendMail(data, function(err) {
if (!err) {
return res.json({ message: 'Password reset' });
} else {
return done(err);
}
});
}
});
} else {
return res.status(422).send({
message: 'Passwords do not match'
});
}
} else {
return res.status(400).send({
message: 'Password reset token is invalid or has expired.'
});
}
});
};
node Routes
router.post('/forgot_password',forgot_password_Ctrl.forgot_password)
router.get('/reset_password/:token',reset_password_ctrl.reset_password)
Angular ROute
forgotpassword(value) {
return this.http.post(`${this.uri}/forgot_password`, value);
}
resetpassword(token) {
return this.http.post(`${this.uri}/reset_password/${token}`, token);
}
Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const User = new Schema({
userName: String,
userEmail: String,
userPassword: {type: String,required: true, bcrypt: true},
userConfPassword: String,
userPhone: Number,
userExperience: String,
reset_password_token: String,
reset_password_expaire: Date,
new_user: String
});
const user = mongoose.model("user", User); //"user" is collections
module.exports= user;

How to fix "TypeError: cb is not a function" error for comparing passwords

I've been starting to add user authentication into my app and when adding the login route, i've been getting the error "TypeError: cb is not a function". I know it is coming from my login route as all my other routes work fine.
I have tried researching the issue and trying a few fixes that i've found but none have worked. So i'm starting to believe i've messed up somewhere and I can't find where.
Login Route:
router.post('/login', function (req, res) {
User.findOne({ username: req.body.username }, function (err, user) {
if (err || user == null) {
console.log(err);
res.redirect('/login');
}
if (!user.comparePassword(req.body.password)) {
req.flash('invalidDetails', 'Wrong username or password!');
res.redirect('/login');
} else {
req.session.userId = user._id;
req.flash('loggedIn', 'User ' + req.body.username + ' has been logged in!');
return res.redirect('/');
}
});
});
User Model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcrypt'),
SALT_WORK_FACTOR = 10;
var UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
trim: true
},
username: {
type: String,
unique: true,
required: true,
trim: true
},
password: {
type: String,
required: true
}
});
UserSchema.statics.authenticate = function (email, password, callback) {
User.findOne({ email: email }).exec(function (err, user) {
if (err) {
return callback(err);
} else if (!user) {
var err = new Error('User not found.');
err.status = 401;
return callback(err);
}
bcrypt.compare(password, hash, function (err, result) {
if (result === true) {
return callback(null, user);
} else {
return callback();
}
});
});
};
UserSchema.pre('save', function (next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
if (err) return next(err);
// hash the password along with our new salt
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
UserSchema.methods.comparePassword = function comparePassword(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};
var User = mongoose.model('User', UserSchema);
module.exports = User;
I'm expecting it to compare the password with the password that has been entered into the login form with the password that is stored in the database and log in the user if the password is correct or redirect back to the login page with the invalidDetails flash message if the password is incorrect.
But what i'm actually getting is the "TypeError: cb is not a function" error when trying to login.
You are not passing a callback that's why.
If you want a promise based method you can write something like this
AuthSchema.methods.comparePassword = function(candidatePassword) {
const currentPassword = this.password;
return new Promise((resolve, reject) => {
bcrypt.compare(candidatePassword, currentPassword, function(err, isMatch) {
if (err) return reject(err);
resolve(isMatch);
});
})
};
And now you can call that with await

Prevent updating user's password if the input was left empty?

I'm struggling to prevent updating user's password in database if the password input was left empty.
Here is the route responsible for updating user data:
router.put('/update', passport.authenticate('jwt', {session: false}), (req, res) => {
let user = req.user;
user.firstname = req.body.firstname;
user.lastname = req.body.lastname;
user.username = req.body.username;
user.email = req.body.email;
user.password = req.body.password || null;
User.updateUser(user, (err) => {
if (err) {
res.json({
success: false,
message: 'User details couldn\'t be updated.'
});
} else {
res.json({
success: true,
message: 'User updated'
});
}
});
});
And here is the User model method which generates a hash of a password and saves the new data in the database:
module.exports.updateUser = function (user, callback) {
if (user.password) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) throw err;
user.password = hash;
});
});
}
user.save(callback);
};
I check if the password value was given but I don't know how to keep the old encrypted password in the database if there is no new value given for the password. If user doesn't fill the password input, it is being saved as null, as expected though...
I hope there is an approach to achieve this, I just can't figure out at the moment as I'm a beginner.
Thank you in advance!
I guess that you are using Mongoose to communicate with the Database.
Change this Line of your code :
user.password = req.body.password || null;
with this :
if(req.body.password != null) {
user.password = req.body.password
}else{
/* find each user with a last name matching 'user.userame', selecting
/*the `password` field and returning the result in 'usr'
*/
User.find({'username' : user.username}, 'password', function (err, usr) {
if (err) return handleError(err);
user.password = usr.password;
})
}
Based on #Neil Lunn's suggestion about checking the documentation, I came up with a solution. I changed the updateUser method to this:
module.exports.updateUser = function (user, callback) {
if (user.password) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) throw err;
user.password = hash;
user.save(callback);
});
});
} else {
User.findById(user.id).update({
username: user.username,
email: user.email,
firstname: user.firstname,
lastname: user.lastname
}, callback);
}
};
If the password is present, then update everything as is, if no password provided, then update only the needed fields except the password.
Maybe this is not the best solution, but it works for now.
Thank you!

Create New User with Passport-Local using MongoDB and Node.JS

Here's the code for a new user:
var User = mongoose.model('User', userSchema);
var usr = new User({ username: 'bob', email: 'bob#example.com', password: 'secret' });
Here's the code for checking login.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
If the username doesn't exist, it says "Unknown user __________"
Instead of saying unknown user, I want to create a new user in the database. How do I modify this code to do that?
I'd like to create a new user with the login info they entered if that login name doesn't already exist.
Update
I'm trying this and it's not working. bob5 isn't saving to the database.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) { usr = new User({ username: 'bob5', email: 'bob5#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
If I type this, bob99 gets saved to the database. So I can create a user... I just need to pass the arguments to it within the if statement (I think).
usr = new User({ username: 'bob99', email: 'bob99#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
usr = new User({ username: 'bob99', email: 'bob99#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
}
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));

Resources