Я добавил некоторые функции сброса пароля к моему процессу регистрации, которые позволяют пользователям изменять свой пароль, но когда пользователь сбрасывает свой пароль, он не может войти в систему с новым паролем, и я получаю консольное сообщение Server Error
. Мне интересно, связано ли это с обновлением пароля пользователя за пределами логики паспорта или, может быть, потому, что мой пароль не хэшируется при обновлении?
Вот лог консоли:
GET /login 200 9.507 ms - 1793
GET /stylesheets/styles.css 304 1.093 ms - -
Database query triggered
Executing (default): SELECT `user_id`, `first_name` AS `firstName`, `last_name` AS `lastName`, `email`, `password`, `organization_id` AS `organizationId`, `reset_password_token` AS `resetPasswordToken`, `reset_password_expires` AS `resetPasswordExpires`, `createdAt`, `updatedAt` FROM `user` AS `user` WHERE `user`.`email` = '[email protected]' LIMIT 1;
Server Error
POST /login 302 16.169 ms - 56
GET /login 200 10.926 ms - 1862
Вот мой маршрут обновления пароля:
var express = require('express');
var siteRoutes = express.Router();
var path = require('path');
var async = require('async');
var crypto = require('crypto');
var nodemailer = require('nodemailer');
var sgTransport = require('nodemailer-sendgrid-transport');
var moment = require('moment');
var url = require('url');
var passport = require(path.resolve(__dirname, '..', '..','./config/passport.js'));
var models = require('../models/db-index');
/*==== /RESET ====*/
siteRoutes.route('/reset/:token')
.get(function(req, res){
var urlPath = url.parse(req.url).pathname.split('/');
var urlToken = urlPath[2];
console.log(urlToken);
models.User.findOne({
where: {
resetPasswordToken: req.params.token,
resetPasswordExpires: {
$gt: moment().format('YYYY-MM-DD HH:mm:ss')
}
}
}).then(function(){
res.render('pages/app/reset-password.hbs',{
urlToken: urlToken
});
})
})
.post(function(req, res){
async.waterfall([
function(done){
models.User.update({
password: req.body.password,
resetPasswordToken: null,
resetPasswordExpires: null
}, { where: {
resetPasswordToken: req.body.token,
resetPasswordExpires: {
$gt: moment().format('YYYY-MM-DD HH:mm:ss')
}
}})
// Nodemailer
var transporter = nodemailer.createTransport(sgTransport(options));
var mailOptions = {
from: '"Tester" <[email protected]',
to: '[email protected]', //Replace with Email
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
'This is a confirmation that the password for your account ' + '[email protected]' + ' has just been changed.\n'
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error + 'During Post');
}
console.log('Message sent: ' + info.response);
})
}
])
res.redirect('/login');
});
Вот мой маршрут входа:
/*==== Login ====*/
siteRoutes.route('/login')
.get(function(req, res){
res.render('pages/site/login.hbs',{
error: req.flash('error')
});
})
.post(passport.authenticate('local', {
successRedirect: '/app',
failureRedirect: '/login',
failureFlash: 'Invalid email or password.'
}));
Вот модель пользователя:
var bcrypt = require('bcrypt-nodejs');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('user', {
user_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'first_name'
},
lastName: {
type: DataTypes.STRING,
field: 'last_name'
},
email: {
type: DataTypes.STRING,
isEmail: true,
unique: true,
set: function(val) {
this.setDataValue('email', val.toLowerCase());
}
},
password: DataTypes.STRING,
organizationId: {
type: DataTypes.INTEGER,
field: 'organization_id',
allowNull: true
},
resetPasswordToken: {
type: DataTypes.STRING,
field: 'reset_password_token'
},
resetPasswordExpires: {
type: DataTypes.DATE,
field: 'reset_password_expires'
}
}, {
freezeTableName: true,
classMethods: {
associate: function(db) {
User.belongsToMany(db.Organization, { through: 'member', foreignKey: 'organizationId'})
},
generateHash: function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
},
},
instanceMethods: {
validPassword: function(password) {
return bcrypt.compareSync(password, this.password);
},
},
});
return User;
}
Вот логика паспорта:
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../app/models/db-index');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
console.log("User ID: " + user.user_id + " is serializing");
done(null, user.user_id);
});
passport.deserializeUser(function(user_id, done) {
models.User.find({where: {user_id: user_id}}).then(function(user){
console.log("User ID: " + user.user_id + " is deserializing");
done(null, user);
}).error(function(err){
done(err, null);
});
});
//Login logic
passport.use('local', new LocalStrategy({
passReqToCallback: true,
usernameField: 'email'
}, function(req, email, password, done) {
console.log("Database query triggered");
//Find user by email
models.User.findOne({
where: {
email: req.body.email
}
}).then(function(user) {
if (!user) {
done(null, false, { message: 'The email you entered is incorrect' }, console.log("Unknown User"));
} else if (!user.validPassword(password)){
done(null, false, console.log("Incorrect Password"));
} else {
console.log("User match");
done(null, user);
}
}).catch(function(err) {
console.log("Server Error");
return done(null, false);
});
}));
//Sign Up Logic
passport.use('local-signup', new LocalStrategy({
passReqToCallback: true,
usernameField: 'email'
}, function(req, email, password, done){
models.User.findOne({
where: {
email: email
}
}).then(function(existingUser){
if (existingUser)
return done(null, false, req.flash('error', 'Email already exists.'));
if (req.user) {
var user = req.user;
user.firstName = firstName;
user.lastName = lastName;
user.email = email;
user.password = models.User.generateHash(password);
user.save().catch(function(err){
throw err;
}).then(function(){
done(null, user, req.flash('error', 'All fields need to be filled in'));
});
} else {
var newUser = models.User.build({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: models.User.generateHash(password)
});
newUser.save().then(function(){
done(null, newUser);
}).catch(function(err){
done(null, false, console.log(err));
});
}
}).catch(function(e){
done(null, false, req.flash('error', 'All fields need to be filled in'),console.log(e.email + e.message));
})
}));
module.exports = passport;