Reputation: 227
I am trying to build a user signup api using Passport, MySql, NodeJS and Sequelize. The only problem that i face is that when a user has signed up once and he tries to sign up again with the same email user is thrown a 401 Unauthorized Error instead of the user object. When i tried to debug the same the response that i was getting from the server was this [object SequelizeInstance:users]. The files have been mentioned below. Thanks a tonnn in advance!!!.
Passport.js file:
var LocalStrategy = require('passport-local').Strategy;
var mysql = require('mysql');
var Model = require('../models/models.js');
// expose this function to our app using module.exports
module.exports = function(passport) {
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
connection.query("select * from users where id = " + id, function(err, rows) {
done(err, rows[0]);
});
});
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
Model.User.findOne({
where: {
email: email
}
}).then(function(user) {
if (user == null) {
Model.User.create({
email: email,
password: password
}).then(function(user) {
return done(null, user);
}).catch(function(err) {
return done(null, err);
});
} else {
return done(null, false);
}
})
}));
};
The Signup api:
router.post('/signup', passport.authenticate('local-signup'), function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
console.log(req.user);
if(req.user){
res.send({
success: true,
response: 'signup successful'
});
} else {
res.send({
success: false,
response: 'Email already in use'
});
}
});
The User model is:
//models/users.js
var Sequelize = require('sequelize')
var attributes = {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
created_by: {
type: Sequelize.INTEGER
}
}
var options = {
// Add the timestamps attributes (updatedAt, createdAt)
timestamps: true,
// don't delete database entries but set the newly added attribute deletedAt
// to the current date (when deletion was done). paranoid will only work if
// timestamps are enabled
paranoid: true,
// don't use camelcase for automatically added attributes but underscore style
// so updatedAt will be updated_at
underscored: true,
// disable the modification of table names; By default, sequelize will automatically
// transform all passed model names (first parameter of define) into plural.
// if you don't want that, set the following
freezeTableName: true,
// define the table's name
tableName: 'users'
}
module.exports.attributes = attributes
module.exports.options = options
The automated table creation model script is:
// models/models.js
var UserMeta = require('./users.js'),
connection = require('./index.js')
var User = connection.define('users', UserMeta.attributes, UserMeta.options)
// force: true will drop the table if it already exists
User.sync({
force: true,
match: /_servernew$/
}).then(function() {
// Table created
return User.create();
});
// you can define relationships here
module.exports.User = User;
Upvotes: 1
Views: 2077
Reputation: 227
So i came up with the solution. The following code needs to be changed.
router.post('/signup', function(req, res, next) {
passport.authenticate('local-signup', function(err, user, info) {
if(user){
req.logIn(user, function(err) {
if (err) {
return next(err);
} else {
res.send({
success: true,
response: 'signup successful'
});
}
});
}
if(!user){
res.send({
success: false,
response: 'Authentication Failed'
});
}
if(err){
res.send({
success: false,
response: 'Authentication failed'
})
}
})(req, res, next);
});
and the passport.js code should be like this.
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
Model.User.findOne({
where: {
email: email
}
}).then(function(user, err) {
console.log('I entered'+user);
console.log('I entered'+err);
if(err) {
console.log(err);
return done(null, false);
}
if(user == null) {
Model.User.create({
email: email,
password: password
}).then(function(user) {
return done(null, user);
}).catch(function(err) {
return done(null, err);
});
}
if(user){
return done(null, false);
}
})
}));
It will work just like a charm :D.
Upvotes: 3