nodejs - passport.use callback return dataValues and _previousDataValues instead of a normal object - mysql

I am using passport.js module for Authentication and Sequelize mysql for database management.
error occurs when authenticating user:
{
"errors": {
"message": "WHERE parameter \"id\" has invalid \"undefined\" value",
"error": {}
}
}
When authenticating the user, console.log(jwtPayload) in file passport.js shows below results.
{
dataValues: {
id: '06c19eb0-995f-45f4-81d7-26ec3b401234',
email: 'CCCC#gmail.com',
createdAt: '2021-05-14T01:51:31.000Z',
updatedAt: '2021-05-14T01:51:31.000Z'
},
_previousDataValues: {
id: '06c19eb0-995f-45f4-81d7-26ec3b401234',
email: 'CCCC#gmail.com',
createdAt: '2021-05-14T01:51:31.000Z',
updatedAt: '2021-05-14T01:51:31.000Z'
},
_changed: {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [ 'id', 'email', 'createdAt', 'updatedAt' ]
},
isNewRecord: false,
iat: 1620961695
}
instead of
{
id: '06c19eb0-995f-45f4-81d7-26ec3b401234',
email: 'CCCC#gmail.com',
createdAt: '2021-05-14T01:51:31.000Z',
updatedAt: '2021-05-14T01:51:31.000Z'
}
passport.js
var passport = require('passport');
const passportJWT = require("passport-jwt");
const JWTStrategy = passportJWT.Strategy;
var LocalStrategy = require('passport-local').Strategy;
const ExtractJWT = passportJWT.ExtractJwt;
const bcrypt = require('bcryptjs');
var User = require('../models/Users')
module.exports = function(passport) {
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey : 'your_jwt_secret'
},
function (jwtPayload, done) {
console.log(jwtPayload)
return User.findOne({where: {id:jwtPayload.id}})
.then(user => {
return done(null, user);
})
.catch(err => {
return done(err);
});
}
));
};

Sequelize returns dataValues and _previousDataValues properties by design. You can pass the current values with a small modification.
return User.findOne({where: {id:jwtPayload.id}})
.then(user => {
return done(null, user.dataValues);
})

Related

How do I skip the primary key auto increment in nodejs ORM sequelize when unique constraint error occurs

How do I skip the primary key auto increment in sequelize node.js when unique constraint error occurs
When I enter same username twice that was defined as unique into mysql by using of Postman my program is running correct way but the problem is the incremental primary key is still continuing.
For example
when I insert another different username value the program is jumping at one of the sequential primary key as expected.
So that, How can I stop the auto increment id as I restricted not to insert duplicate username values in my database
/* DATABASE CONFIGURATION FILE */
const { Sequelize, QueryTypes, DataTypes, Op, UniqueConstraintError, ValidationErrorItem } = require(`sequelize`);
const sequelize = new Sequelize(`tutorialdb`, `root`, ``, {
host: `localhost`,
dialect: `mysql`,
logging: true,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
});
sequelize
.authenticate()
.then(() => {
console.log(`Connection has been established successfully...`);
})
.catch((err) => {
console.log(`Unable to connect to the database: `, err);
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.QueryTypes = QueryTypes;
db.DataTypes = DataTypes;
db.Op = Op;
db.ValidationErrorItem = ValidationErrorItem;
db.UniqueConstraintError = UniqueConstraintError;
db.postModel = require(`../models/post.model.jsx`)(sequelize, DataTypes);
db.sequelize.sync({ force: false, alter: false, match: /tutorialdb$/ }).then(() => {
console.log(`Tables were synced successfully`);
});
module.exports = db;
/* Model definition File */
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define(
`post`,
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
title: {
type: DataTypes.STRING(30),
allowNull: false,
validate: {
notEmpty: {
args: true,
msg: `Title is required`,
},
len: {
args: [3, 50],
msg: `Title must between 3 and 30 characters`,
},
},
},
text: {
type: DataTypes.STRING(100),
allowNull: false,
validate: {
notEmpty: {
args: true,
msg: `Text is required`,
},
len: {
args: [5, 100],
msg: `Text must between 5 and 100 characters`,
},
},
},
username: {
type: DataTypes.STRING(20),
allowNull: false,
unique: true,
validate: {
notEmpty: {
args: true,
msg: `Username is required`,
},
len: {
args: [3, 20],
msg: `Username must between 3 and 20 characters`,
},
},
},
},
{
timestamps: true,
paranoid: true,
}
);
Post.beforeCreate(async (post, options) => {
post.username = post.username.toLowerCase();
});
Post.beforeUpdate(async (post, options) => {
post.username = post.username.toLowerCase();
});
return Post;
};
/* Controller File */
const db = require(`../config/db.config.jsx`);
const postModel = db.postModel;
const Sequelize = db.Sequelize;
const sequelize = db.sequelize;
const QueryTypes = db.QueryTypes;
const DataTypes = db.DataTypes;
const Op = db.Op;
const ValidationErrorItem = db.ValidationErrorItem;
const UniqueConstraintError = db.UniqueConstraintError;
/* Create new Post */
exports.create = async (req, res) => {
const transactions = await sequelize.transaction();
try {
const trim = (noSpace) => {
return noSpace.replace(/\s/g, ``);
};
const post = await postModel.create(
{
title: req.body.title,
text: req.body.text,
username: trim(req.body.username),
},
{ transaction: transactions }
);
await transactions.commit();
res.status(200).json(post);
} catch (err) {
await transactions.rollback();
const messages = {};
let message;
err.errors.forEach((error) => {
messages[error.path] = error.message;
message = messages[error.path];
});
res.status(500).json(message);
}
};
/* Find All posts */
exports.findAll = async (req, res) => {
const transactions = await sequelize.transaction();
try {
const title = req.query.title;
const text = req.query.text;
const username = req.query.username;
let finder = title ? { title: { [Op.like]: `%${title}%` } } : text ? { text: { [Op.like]: `%${text}%` } } : username ? { username: { [Op.like]: `%${username}%` } } : null;
const posts = await postModel.findAll({
as: `posts`,
attributes: [`id`, `title`, `text`, `username`, `createdAt`, `updatedAt`, `deletedAt`],
transaction: transactions,
lock: false,
paranoid: false,
order: [[`id`, `DESC`]],
where: finder,
});
await transactions.commit();
res.status(200).json(posts);
} catch (err) {
await transactions.rollback();
res.status(500).json(err.message);
}
};
/* Router File */
module.exports = (app) => {
const router = require(`express`).Router();
const postCtrl = require(`../controllers/post.controller.jsx`);
router.route(`/post`).post(postCtrl.create).get(postCtrl.findAll);
app.use(`/api/v1`, router);
};
/* MiddleWare Logger File */
const moment = require(`moment`);
/* Create Logger */
const logger = (req, res, next) => {
console.log(`${req.protocol}://${req.get(`host`)}${req.originalUrl} : ${moment().format()}`);
next();
};
module.exports = logger;
/* Server File */
const express = require(`express`);
const cors = require(`cors`);
const logger = require(`./src/middleware/logger.jsx`);
const app = express();
const corsOptions = {
origin: `http://localhost:4001`,
optionsSuccessStatus: 200,
};
app
.use(cors(corsOptions))
.use(logger)
.use(express.json())
.use(express.urlencoded({ extended: false }))
.get(`/`, (req, res) => res.status(200).send(`Welcome to fullstack tutorial application`));
require(`./src/routes/routers.jsx`)(app);
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => console.log(`Server is running on port ${PORT}...`));
The output result is working well. But the primary Key auto-increment is still continuing
http://localhost:4000/api/v1/post : 2022-08-28T11:02:47+03:00
Executing (ac12d76f-d7dc-4040-9692-3d6b853feac9): START TRANSACTION;
Executing (ac12d76f-d7dc-4040-9692-3d6b853feac9): INSERT INTO posts
(id,title,text,username,createdAt,updatedAt) VALUES
(DEFAULT,?,?,?,?,?); Executing (ac12d76f-d7dc-4040-9692-3d6b853feac9):
ROLLBACK;
I had attempted the following solution and works me perfectly.
/* Create new User */
exports.create = async (req, res) => {
const trim = (noSpace) => {
return noSpace.replace(/\s/g, ``);
};
const transactions = await sequelize.transaction();
try {
const { username, password } = req.body;
const users = await userModel.findOne({
where: { username: trim(username) },
transaction: transactions,
});
if (users !== null) {
await transactions.rollback();
res.json(`Username ${username} already exist`);
} else {
const user = await userModel.create(
{
username: trim(username),
password: trim(password),
},
{
transaction: transactions,
}
);
await transactions.commit();
res.status(200).json(user);
}
} catch (err) {
await transactions.rollback();
const messages = {};
let message;
err.errors.forEach((error) => {
messages[error.path] = error.message;
message = messages[error.path];
});
res.status(500).json(message);
}
};
exports.create = async (req, res) => {
const transactions = await sequelize.transaction();
try {
const trim = (noSpace) => {
return noSpace.replace(/\s/g, ``);
};
const [user, created] = await userModel.findOrCreate({
where: { username: trim(req.body.username) },
defaults: { password: trim(req.body.password) },
transaction: transactions,
});
return created ? (await transactions.commit(), res.status(200).json(user)) : user ? (await transactions.rollback(), res.json(`Username already exist`)) : err;
} catch (err) {
await transactions.rollback();
const messages = {};
let message;
err.errors.forEach((error) => {
messages[error.path] = error.message;
message = messages[error.path];
});
res.status(500).json(message);
}
};
I am not sure about issue's existence in previous versions of sequelize. But this issue does not exist if using Object.findOrCreate() with following mentioned versions.
However this issue does appear if using Object.create() method with unique constraint set for field value and not checking field value existence prior to using Object.create() e.g in following code email unique property is set and if user.create() is used for an existing email in db an error is thrown but userid is incremented thus for next successful creation userid is not as expected.
An alternate solution is using user.findOne() prior to use user.create() but out of the scope of this answer and issue can be avoided using object.findOrCreate() as following
Versions: "mysql2": "^2.3.3", "sequelize": "^6.28.0"
To avoid the issue try using following approach
const router = require("express").Router();
const { Sequelize, DataTypes, Model } = require("sequelize");
const dotenv = require("dotenv");
dotenv.config();
const sequelize = new Sequelize(
process.env.MYSQL_DB_NAME,
process.env.MYSQL_DB_USER,
process.env.MYSQL_DB_PASS,
{
host: process.env.MYSQL_DB_HOST,
dialect: "mysql",
}
);
class User extends Model {}
User.init(
{
userid: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
field: "fUserID",
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
field: "fEmail",
},
password: {
type: DataTypes.STRING(1024),
allowNull: false,
field: "fPassword",
},
firstname: {
type: DataTypes.STRING,
field: "fFirstName",
},
lastname: {
type: DataTypes.STRING,
field: "fLastName",
},
metadata: {
type: DataTypes.STRING(2048),
field: "fMetaData",
},
created: {
type: DataTypes.DATE,
field: "fCreated",
},
updated: {
type: DataTypes.DATE,
field: "fUpdated",
},
},
{
sequelize,
tableName: "tbl_user",
timestamps: true,
id: "userid",
createdAt: "created",
updatedAt: "updated",
}
);
router.post("/register", async (req, res) => {
try {
const [user, created] = await User.findOrCreate({
where: { email: req.body.email },
defaults: {
password: req.body.password,
firstname: req.body.firstname,
lastname: req.body.lastname,
metadata: "Any thing",
},
});
if (created === false) return res.status(400).send("email already exist");
res.send(user.toJSON());
} catch (ex) {
res.status(400).send(ex.errors[0].message);
}
});
module.exports = router;

Express js - how to remove certain field from response

In my current login api, it returns
"user": {
"id": "3e85decc-2af4-436c-8b7f-e276771234f5",
"email": "cccc#cccc.com",
"password": "$xxxxxxxxxx",
"createdAt": "2021-05-14T08:48:31.000Z",
"updatedAt": "2021-05-14T08:48:31.000Z"
},
"token": "xxxxx"
}
I want to remove the password field in my response, so I use delete user.password in my code, but it's not working
/api/users.js
router.post('/login', (req, res, next) => {
passport.authenticate('local', {session: false}, (err, user, info) =>{
if (err || !user) {...}
req.login(user, {session: false}, (err) => {
if (err) {
res.send(err);
}
const token = jwt.sign(user, 'your_jwt_secret');
console.log(user) // show dataValues and _previousDataValues instead of normal JSON object
delete user.password // not working
return res.json({user, token});
});
})(req, res);
});
I tried to log user object for above file, it returns:
users {
dataValues: {
id: '3e85decc-2af4-436c-8b7f-e276771234f5',
email: 'cccc#cccc.com',
password: '$xxxxxxxxxx',
createdAt: 2021-05-14T08:48:31.000Z,
updatedAt: 2021-05-14T08:48:31.000Z
},
_previousDataValues: {
id: '3e85decc-2af4-436c-8b7f-e276771234f5',
email: 'cccc#cccc.com',
password: '$xxxxxxxxxx',
createdAt: 2021-05-14T08:48:31.000Z,
updatedAt: 2021-05-14T08:48:31.000Z
},
_changed: Set(0) {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [ 'id', 'email', 'password', 'createdAt', 'updatedAt' ]
},
isNewRecord: false
}
This is my user model. I am using Sequelize.
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
const db = require('../sequelize')
let users = db.define('users', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: 'email'
},
password: {
type: DataTypes.STRING,
},
},
{
hooks: {
beforeCount(options) {
options.raw = false;
}
}
}
);
module.exports = users;
Finally solved it using user.get({plain: true})
let plainUser = user.get({plain: true})
delete plainUser['password']
return res.json({user, token});
It's probably not a good idea to delete properties from the Model directly. Try using ToJSON() to convert the Model to a plain Javascript object and delete the password from that.
plainUser = user.ToJSON();
delete plainUser.password
why dont you re-create your result response, something like this:
let response = {
"user": {
"id": user.dataValues.id,
"email": user.dataValues.email,
"createdAt": user.dataValues.createdAt,
"updatedAt": user.dataValues.updatedAt
},
"token": "xxxxx"
}
JSON.stringify(response)
Try below code in your model to override the sequelize toJSON function
const User = db.define('users', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: 'email'
},
password: {
type: DataTypes.STRING,
},
},
{
hooks: {
beforeCount(options) {
options.raw = false;
}
}
}
);
User.prototype.toJSON = function () {
const values = Object.assign({}, this.get());
delete values.password;
return values;
};
or using omit() withlodash for cleaner code
User.prototype.toJSON = function () {
const values = {
..._.omit(this.get(), ['password'])
};
return values;
};

error: SequelizeValidationError: string violation: created cannot be an array or an object

I am implementing MERN Stack Login / Registration and trying to test my response in Postman step by step. Firstly, I written the code for Registration then for Login but in case of calling registration link I am getting the following error in postman:
error: SequelizeValidationError: string violation: created cannot be an array or an object
Can someone provide any suggestions to help? I think in User.js findone() function is having some sort of miss from my side.
Could there be any other solution?
./database/DB.js
const db = {}
const sequelize = new Sequelize("mern", "root", "", {
host: "localhost",
dialect: "mysql",
port: "3307",
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
})
db.sequelize = sequelize
db.sequelize = sequelize
module.exports = db
./models/User.js
const db = require("../database/db")
module.exports = db.sequelize.define(
'user',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
first_name: {
type: Sequelize.STRING
},
last_name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
created: {
type: Sequelize.STRING
}
},
{
timestamps: false
}
);
./routes/User.js
const users = express.Router()
const cors = require('cors')
const jwt = require("jsonwebtoken")
const bcrypt = require('bcrypt')
const User = require("../models/User")
users.use(cors())
process.env.SECRET_KEY = 'secret'
users.post('/register', (req, res) => {
const today = new Date()
const userData = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
password: req.body.password,
created: today
}
User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if(!user){
bcrypt.hash(req.body.password, 10, (err, hash) => {
userData.password = hash
User.create(userData)
.then(user => {
res.json({status: user.email + ' registered'})
})
.catch(err => {
res.send('error: ' + err)
})
})
} else {
res.json({error: "User already exists"})
}
})
.catch(err => {
res.send('error: ' + err)
})
})
users.post('/login', (req, res) => {
User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if(user) {
if(bcrypt.compareSync(req.body.password, user.password)) {
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY, {
expiresin: 1440
})
res.send(token)
}
} else {
res.status(400).json({error: 'User does not exist'})
}
})
.catch(err => {
res.status(400).json({ error: err})
})
})
module.exports = users
package.json
"name": "login-registration",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^3.0.6",
"bcryptjs": "^2.4.3",
"body-parser": "^1.17.2",
"cors": "^2.8.4",
"express": "^4.16.3",
"jsonwebtoken": "^7.4.2",
"mysql": "^2.14.1",
"mysql2": "^1.6.1",
"nodemon": "^1.18.3",
"sequelize": "^4.38.0"
}
}
Server.js
var cors = require ('cors')
var bodyParser = require("body-parser")
var app = express()
var port = process.env.PORT || 5000
app.use(bodyParser.json())
app.use(cors())
app.use(bodyParser.urlencoded({extended: false}))
var Users = require('./routes/users')
app.use('/users', Users)
app.listen(port, () => {
console.log("Server is running at port: " + port)
})
In ./routes/User.js, under the /post register route, the userData object has a created field with today property which is a Date object.
In ./models/User.js you specify that created should have type Sequelize.STRING.
This is the contradiction that is causing the error. When you call User.create(userData), it gives you that error because the input parameter is of the wrong type.
To fix this, you either need to have created expect a type of Sequlize.Date or convert the today date object to a string.
const today = new Date().toJSON();
There are many different to string functions for the Date class. You should pick the one that best suits you here
This error is as a result of submitting a value of a wrong type compared to the
one declared in the model. Therefore, change it to the appropriate
type which is "JSON" instead of "STRING".
./models/User.js
const db = require("../database/db")
module.exports = db.sequelize.define(
'user',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
first_name: {
type: Sequelize.STRING
},
last_name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
created: {
type: Sequelize.JSON
}
},
{
timestamps: false
}
);
Its the "today" attribute that's causing the issue, you are trying to save a date obj instead of string. Change it to string while saving.

Sequelize: Unhandled rejection TypeError: Cannot read property 'id' of undefined

Currently using ExpressJS as the framework to create a small CMS system but currently running into a problem. I am trying to create a model for a table called 'roles' but when I add it to my database file to be included, I get the following error once I run 'node app.js'
Unhandled rejection TypeError: Cannot read property 'id' of undefined
at Object.mapValueFieldNames (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\sequelize\lib\utils.js:232:19)
at Promise.try.then.then (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\sequelize\lib\model.js:2393:37)
at tryCatcher (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:512:31)
at Promise._settlePromise (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:569:18)
at Promise._settlePromise0 (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:614:10)
at Promise._settlePromises (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\promise.js:694:18)
at _drainQueueStep (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:138:12)
at _drainQueue (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:131:9)
at Async._drainQueues (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:147:5)
at Immediate.Async.drainQueues (C:\Users\Ryahn\Documents\Projects\monkeys\node_modules\bluebird\js\release\async.js:17:14)
at runCallback (timers.js:810:20)
at tryOnImmediate (timers.js:768:5)
at processImmediate [as _immediateCallback] (timers.js:745:5)
If I do not include the model in the database init file, it runs just fine. The idea is to then use a relationship to pair the two. I do not plan on having permissions assigned, just using roles. The migration file is setup the same as the model. I was assuming by matching how the user model was setup, the roles model would work as well. But now I am unsure what is going on.
Users
'use strict';
const
Promise = require('bluebird'),
bcrypt = Promise.promisifyAll(require('bcrypt'))
;
module.exports = (sequelize, DataTypes) => {
const users = sequelize.define('users', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
username: {
type: DataTypes.STRING,
notEmpty: true,
unique: true
},
password: {
type: DataTypes.STRING,
notEmpty: true
},
role: {
type: DataTypes.INTEGER(2).UNSIGNED,
validate: {
isNumeric: true
}
},
steamid: {
type: DataTypes.STRING(17),
validate: {
len: 17
}
},
link: {
type: DataTypes.STRING,
validate: {
isUrl: true
}
},
last_login: DataTypes.DATE
},
{
hooks: {
beforeCreate: function(user, options) {
if (!user.changed('password')) {
return sequelize.Promise.reject('not modified');
}
return bcrypt.hash(user.password, 10).then(hash => {
return user.password = hash;
}).catch(err => {
return sequelize.Promise.reject(err);
});
},
beforeUpdate: function(user, options) {
if (!user.changed('password')) {
return sequelize.Promise.reject('not modified');
}
return bcrypt.hash(user.password, 10).then(hash => {
return user.password = hash;
}).catch(err => {
return sequelize.Promise.reject(err);
});
}
}
});
users.prototype.generateHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
};
users.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
users.sync({force: false}).then(() => {
return users.findOrCreate({
where: {
id: 1,
username: 'Admin'
},
defaults: {
username: 'Admin',
password: 'admin123',
role: 1,
steamid: parseInt(12345678901234567),
link: 'https://www.example.com/user_profile.php?userID=1171981'
}
});
});
return users;
};
Roles
'use strict';
module.exports = (sequelize, DataTypes) => {
const roles = sequelize.define('roles', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: DataTypes.STRING,
slug: DataTypes.STRING
}, {
timestamps: false
});
let role = [];
role.push([
{ name: 'Admin', slug: 'admin'},
{ name: 'Staff', slug: 'staff'},
{ name: 'Trainer', slug: 'trainer'},
{ name: 'Captain', slug: 'captain'},
{ name: 'Monkey', slug: 'monkey'}
]);
roles.sync({force: false}).then(() => {
return roles.bulkCreate(role);
});
return roles;
};
Init
const
config = require('../config/database'),
Sequelize = require('sequelize'),
sequelize = new Sequelize(config),
db = {}
;
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.users = require('./models/users')(sequelize, Sequelize);
db.roles = require('./models/roles')(sequelize, Sequelize);
module.exports = db;

TypeError: Cannot read property 'findOne' of undefined while using sequelize in node

I am getting belo mentioned error when trying to make user authentication using passport-local and sequelize for MySQL. When running server it is creating new table in SQL if not already, but as soon as I hit sign up button it is showing error.
Error:
TypeError: Cannot read property 'findOne' of undefined
at Strategy._verify (E:\Web Development\node-SQL-Sequelize-passport-local\config\passport\passport.js:19:13)
at Strategy.authenticate (E:\Web Development\node-SQL-Sequelize-passport-local\node_modules\passport-local\lib\strategy.js:88:12)
at attempt (E:\Web Development\node-SQL-Sequelize-passport-local\node_modules\passport\lib\middleware\authenticate.js:361:16)
at authenticate (E:\Web Development\node-SQL-Sequelize-passport-local\node_modules\passport\lib\middleware\authenticate.js:362:7)
My server.js look like :
app.use(passport.initialize());
app.use(passport.session());
//Models
var models = require("./app/models");
//Routes
var authRoute = require('./app/routes/auth.js')(app,passport);
require('./config/passport/passport.js')(passport, models.user);
//Sync Database
models.sequelize.sync().then(function() {
console.log('Nice! Database looks fine')
}).catch(function(err) {
console.log(err, "Something went wrong with the Database Update!")
});
app.get('/', function(req, res) {
res.send('Welcome to Passport with Sequelize');
});
My user.js file:
module.exports = function(sequelize, Sequelize) {
var User = sequelize.define('userInfo', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
firstname: {
type: Sequelize.STRING,
notEmpty: true
},
lastname: {
type: Sequelize.STRING,
notEmpty: true
},
username: {
type: Sequelize.TEXT
},
about: {
type: Sequelize.TEXT
},
email: {
type: Sequelize.STRING,
validate: {
isEmail: true
}
},
password: {
type: Sequelize.STRING,
allowNull: false
},
last_login: {
type: Sequelize.DATE
},
status: {
type: Sequelize.ENUM('active', 'inactive'),
defaultValue: 'active'
}
});
return User;
}
My passport.js file :
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport, user) {
var User = user;
var LocalStrategy = require('passport-local').Strategy;
passport.use('local-signup', new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},function(req, email, password, done) {
var generateHash = function(password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null);
};
User.findOne({
where: {
email: email
}
}).then(function(user) {
if (user)
{
return done(null, false, {
message: 'That email is already taken'
});
} else
{
var userPassword = generateHash(password);
var data =
{
email: email,
password: userPassword,
firstname: req.body.firstname,
lastname: req.body.lastname
};
User.create(data).then(function(newUser, created) {
if (!newUser) {
return done(null, false);
}
if (newUser) {
return done(null, newUser);
}
});
}
});
}
));
}
Review this example: github.com/sequelize/express-example. In particular models/index.js for models load.
That way is handled in that example is:
require('./config/passport/passport.js')(passport, models.userInfo);
Because "userInfo" is defined in your model user.js: