doesn't matter if I try findOne() or findAll()
I get : []
empty array.
the query being called for findAll() is:
SELECT "id", "password", "firstName", "lastName", "email", "phone", "roleId", "userId", "createdAt", "updatedAt" FROM "Users" AS "Users";
while when I manually use in pgadmin cli this query: select * from Users;
I get all the rows of the table.
could you please advise?
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = require('../db/database')
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
//console.log(sequelize);
const User = sequelize.define("Users", {
password: {
type: Sequelize.STRING,
allowNull: false,
validate:{
len: [8,40],
trim: true
}
},
firstName: {
type: Sequelize.STRING,
allowNull: false,
validate:{
len: [0,20],
trim: true,
lowercase: true
}
},
lastName: {
type: Sequelize.STRING,
allowNull: false,
validate:{
len: [0,20],
trim: true,
lowercase: true
}
},
email: {
type: Sequelize.STRING,
unique: true,
allowNull: false,
validate:{
len: [0,20],
trim: true,
lowercase: true,
isEmail: true
}
},
phone: {
type: Sequelize.STRING,
validate:{
len: [10,10],
trim: true,
}
},
roleId: {
type: Sequelize.INTEGER,
allowNull: false,
validate:{
trim: true
/* must convert roleId from string to integer
toInt(value){
return parseInt(value);
}*/
}
},
userId: {
type: Sequelize.INTEGER,
allowNull: false
}
},
{
timestamps: true,
versionKey: false,
hooks:{
beforeSave: async function(user,options){
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
}
}
}
}
);
User.prototype.toJSON = function () {
const user = this;
const userObject = user.toObject();
delete userObject.password;
delete userObject.tokens;
return userObject;
};
User.prototype.generateAuthToken = async function () {
const user = this;
const payload = { user };
const token = jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: 360000
});
return token;
};
const findByCredentials = async (email, password) => {
const users= await User.findAll();
const user = await User.findOne({where: {email}});
if (!user) {
throw Error('invalid email');
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
throw Error('invalid password');
}
return user;
}
User.sync();
module.exports = {
User,
findByCredentials
}
Related
I am writing an endpoint that would create a record but before then, I want to be able to validate if one of those data exist before allowing the data to be saved. This is being done using the custom validator in express-validator. I am also using Sequelize as well.
My migration files looks like this:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('merchant_temp', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
firstname: {
type: Sequelize.STRING,
allowNull: false
},
lastname: {
type: Sequelize.STRING,
allowNull: false
},
phone: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
password: {
type: Sequelize.STRING,
allowNull: false
},
ip_address: {
type: Sequelize.STRING
},
created_at: {
allowNull: false,
type: Sequelize.DATE
},
updated_at: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('merchant_temp');
}
};
Model file (merchanttemp.js)
'use strict';
const {
Model, Sequelize
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class MerchantTemp extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
MerchantTemp.init({
firstname: {
type: DataTypes.STRING,
allowNull: false
},
lastname: {
type: DataTypes.STRING,
allowNull: false
},
phone: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
ip_address: DataTypes.STRING,
}, {
sequelize,
modelName: 'merchant_temp',
});
return MerchantTemp;
};
validator.js
const { check, body, validationResult } = require('express-validator')
const bcrypt = require('bcrypt')
const models = require('../app/models')
const MerchantTemp = db.rest.models.MerchantTemp
const signupValidation = () => {
return [
body('firstname')
.not().isEmpty().trim().withMessage('Firstname field is required'),
body('lastname')
.not().isEmpty().trim().withMessage('Lastname field is required'),
body('phone')
.not().isEmpty().trim().withMessage('Phone Number field is required')
.isNumeric().withMessage('Phone Number field can only contain Numbers')
.isLength({min: 11, max: 13}).withMessage('Phone Number field can only contain minimum of 11 and max of 13 digits respectively'),
body('email')
.not().isEmpty().trim().withMessage('Email Address field is required')
.isEmail().withMessage('Email field is not a valid format').normalizeEmail()
.custom((value, { req }) => {
/**
** THIS PART IS WHERE I AM VALIDATING IF IT EXIST
**/
MerchantTemp.findOne({ where: { email: req.body.email } })
.then((result) => {
console.log(result)
}).catch(error => {
console.log(error)
})
}),
body('password')
.not().isEmpty().trim().withMessage('Password field is required')
.isStrongPassword(
{
minLength: 6,
minLowercase: 1,
minUppercase: 1,
minSymbols: 1
}).withMessage('Password is too weak. Field must contain min. of 6 characters, 1 lowercase and uppercase character and a symbol')
]
}
const validate = (req, res, next) => {
const errors = validationResult(req)
if (errors.isEmpty()) {
return next()
}
const extractedErrors = []
errors.array().map(err => extractedErrors.push({ msg: err.msg }))
res.status(200).json({
statusCode: 400,
errors: extractedErrors
})
}
module.exports = {
signupValidation,
validate
}
router file
require('dotenv').config()
const router = require('express').Router()
const account = require('../controllers/account.controller')
const { signupValidation, validate } = require('../../helpers/validator')
router.get('/', (req, res) => {
let p = "This serves as a repository of API calls for application"
res.status(200).json({message:p, statusCode: 200})
})
//Endpoint to create new merchant
router.post('/account/create-merchant', signupValidation(), validate, async (req, res) => {
res.status(200).json({
statusCode: 201,
message: req.body
})
})
//Endpoint to login merchant
router.post('/account/login', (req, res) => {
})
module.exports = router
The validation on the /account/create-merchant route works well prior to when I included the findOne part in the validator.js. What exactly I am doing wrong?
I'm using Sequelize for my Postgres database. I have a Messages and a Users table; a user has many messages and a message belongs to a user. I've defined my models as follows:
User
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
}
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {
len: [8, 50],
}
},
}, {
modelName: 'User',
});
User.associate = (models) => {
User.hasMany(models.Message, { foreignKey: 'userId', as: 'Messages' })
}
return User;
};
Message
module.exports = (sequelize, DataTypes) => {
const Message = sequelize.define('Message', {
content: {
allowNull: false,
type: DataTypes.STRING,
validate: {
len: [1, 248],
}
},
userId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'Users',
key: 'id'
}
},
likes: {
defaultValue: 0,
type: DataTypes.INTEGER
},
}, {
modelName: 'Message',
});
Message.associate = (models) => {
Message.belongsTo(models.User, { foreignKey: 'userId', as: 'User', onDelete: 'CASCADE' })
}
return Message;
};
And here's how I'm testing them:
User.create({
firstName: 'Test', lastName: 'Test', email: 'test#test.com', password: '87654321'
}).then((newUser) => {
console.log(newUser.get())
})
Message.bulkCreate([
{ content: "Hello", likes: 0, userId: 1 },
{ content: "Hello World", likes: 0, userId: 1 },
{ content: "Hello World 2", likes: 123, userId: 1 }
])
.then((newMessages) => {
console.log(newMessages)
})
const findAllWithMessages = async () => {
const users = await User.findAll({
include: [{
model: Message
}]
});
console.log(JSON.stringify(users, null));
}
Here's my Migration file to create the users table:
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
}
},
password: {
type: Sequelize.STRING,
allowNull: false,
validate: {
len: [8, 50],
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Users');
}
};
And the messages table:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Messages', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'Users',
key: 'id',
as: 'userId',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
},
content: {
allowNull: false,
type: Sequelize.STRING,
validate: {
len: [1, 248],
}
},
likes: {
defaultValue: 0,
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Messages');
}
};
I'm registering my models and associations using Sequelize CLI out of the box code when you run sequelize-cli init:
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
const User = require('./user')(sequelize, Sequelize.DataTypes)
const Message = require('./message')(sequelize, Sequelize.DataTypes)
db.models = { User, Message }
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.DataTypes = Sequelize.DataTypes
module.exports = db;
Finally, when I run findAllWithMessages(), I'm getting this error UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError: Message is not associated to User!
I can confirm that the models are being created and that the association between the models work because when I run a raw SQL query select * from "Messages" as a inner join "Users" as b on b.id = a."userId" where a."userId"=1; I get the correct results. So I'm assuming its a Sequelize thing.
Any help is appreciated!
I've found my issue. In the code I was importing from db.models = { User, Message } so this block Object.keys(db).forEach(modelName)... wasn't associating the models I was using. Essentially, I was calling the .associate function on instances of the models that were different than the instances I was using.
I'm trying to use the Sequelize model.create function but keep running into this error: Unhandled rejection SequelizeDatabaseError: relation "users" does not exist. The User class is making my table name all lowercased instead of capitalized.The table I created is called "Users" but the create function keeps trying to look for a table called "users".
Executing (default): SELECT "id", "first_name", "last_name", "email", "username", "password", "dob", "created_at" AS "createdAt", "updated_at" AS "updatedAt" FROM "users" AS "User";
It seems like the User class is trying to access a "users" table whenever it communicates with postgres. I tried using other functions and kept running into the same problem. My code is down below.
/model/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../../config/db.js')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
/model/users.js
'use strict';
const bcrypt = require('bcrypt');
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
first_name: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
last_name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false
},
dob: {
type: DataTypes.DATE,
allowNull: false
}
}, {
underscored: true,
instanceMethods: {
validPassword(password) {
return bcrypt.compareSync(password, this.password);
}
}
});
User.beforeCreate((user) => {
user.email = user.email.toLowerCase();
user.first_name = user.first_name.charAt(0).toUpperCase(0) + user.first_name.slice(1);
user.last_name = user.last_name.charAt(0).toUpperCase(0) + user.last_name.slice(1);
return bcrypt.hash(user.password, 8).then((hash) => {
user.password = hash;
});
});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
/migrations/20191025125151-create-user.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
first_name: {
type: Sequelize.STRING,
allowNull: false
},
last_name: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
password: {
type: Sequelize.STRING,
allowNull: false
},
dob: {
type: Sequelize.DATE,
allowNull: false
},
created_at: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()')
},
updated_at: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()')
}
}, {
timestamps: true,
underscored: true
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
/controllers/user
const { User } = require('../../db/models');
const signup = (req, res) => {
const { first_name, last_name, username, email, password, dob } = req.swagger.params.data.value;
User.create({
first_name,
last_name,
password,
dob,
username,
email
})
.then((user) => {
console.log(user);
res.json({message: 'Success'});
})
}
Error Message:
Executing (default): SELECT "id", "first_name", "last_name", "email", "username", "password", "dob", "created_at" AS "createdAt", "updated_at" AS "updatedAt" FROM "users" AS "User";
Unhandled rejection SequelizeDatabaseError: relation "users" does not exist
at Query.formatError (/home/ubu/projects/stat/node_modules/sequelize/lib/dialects/postgres/query.js:366:16)
at query.catch.err (/home/ubu/projects/stat/node_modules/sequelize/lib/dialects/postgres/query.js:72:18)
at bound (domain.js:301:14)
at runBound (domain.js:314:12)
at tryCatcher (/home/ubu/projects/stat/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/ubu/projects/stat/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/home/ubu/projects/stat/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/home/ubu/projects/stat/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/home/ubu/projects/stat/node_modules/bluebird/js/release/promise.js:725:18)
at _drainQueueStep (/home/ubu/projects/stat/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/home/ubu/projects/stat/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/home/ubu/projects/stat/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues (/home/ubu/projects/stat/node_modules/bluebird/js/release/async.js:15:14)
at runCallback (timers.js:794:20)
at tryOnImmediate (timers.js:752:5)
at processImmediate [as _immediateCallback] (timers.js:729:5)
You have a probleme in the creation of the table in database at the columns createdAt and updatedAt :
`'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
first_name: {
type: Sequelize.STRING,
allowNull: false
},
last_name: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
password: {
type: Sequelize.STRING,
allowNull: false
},
dob: {
type: Sequelize.DATE,
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()')
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()')
}
}, {
timestamps: true,
underscored: true
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};`
Add the tableName property to your define call.
...
underscored: true,
tableName: 'Users',
instanceMethods: ...
My app is running nodejs 10.16 and sequelizejs 5.7 with postgresql 11. The initial connection is setup as:
const Sql = require("sequelize");
const db = new Sql('mydb', 'postgres', `${process.env.DB_PASSWORD}`, {
host: 'localhost',
dialect: 'postgres',
port:5432,
} );
A Group model is defined as:
const Joi = require('#hapi/joi');
const Sql = require('sequelize');
const db = require("../startup/db");
const Group = db.define('group', {
name: {type: Sql.STRING,
allowNull: false,
min: 1,
max: 50,
required: true,
},
owner_id: {
type: Sql.INTEGER,
allowNull: false,
required: true,
},
status: {type: Sql.STRING,
allowNull: false,
isIn: ['active', 'inactive']
},
last_updated_by_id: {type: Sql.INTEGER},
createdAt: Sql.DATE,
updatedAt: Sql.DATE
}, {
indexes: [
{
fields: ['name', 'owner_id']
}
]
});
function validateGroup(group) {
const schema = Joi.object({
name: Joi.string()
.min(1)
.max(50)
.required()
.trim(),
status: Joi.string()
.required()
.trim(),
});
return schema.validate(group, {allowUnknown: true});
};
module.exports.Group = Group;
module.exports.validateGroup = validateGroup;
Here is the in router /group/new to save a new group:
router.post('/new', async (req, res) => {
const { err } = validateGroup(req.body);
if (err) return res.status(400).send(err.details[0].message);
let group = Group.build(_.pick(req.body, ['name', 'status']));
group.owner_id = req.user.id;
group.last_updated_by_id = req.user.id;
let grpmember = new Groupmember({owner_id: req.user.id});
try {
await db.transaction(async () => {
await group.save();
grpmember.group_id = group.id;
await grpmember.save();
return res.status(200).send(`${group.name}-已经保存!`);
});
} catch (err) {
console.log("error in saving new group ", err);
return res.status(400).send('保存错误,请再试一遍!');
};
});
Here is the Group table output which contains both empty and non-empty name:
Why the validation for name field, such as allowNull:false and required: true did not validate the input value?
The following is the code that works:
const Group = db.define('group', {
name: {type: Sql.STRING,
validate: {
len:{
args:[1,50],
msg:"Name between 1 to 50 chars"
} ,
}
},
owner_id: {
type: Sql.INTEGER,
validate: {
isInt: true,
},
},
status: {type: Sql.STRING,
validate: {
isIn: ['active', 'inactive'],
},
},
group_data: {
type: Sql.JSONB
},
last_updated_by_id: {type: Sql.INTEGER},
fort_token: {type: Sql.STRING,
validate: {
min:20, //64 for production
},
},
createdAt: Sql.DATE,
updatedAt: Sql.DATE
}
I can't seem to set the User model properly. I've implemented some instance methods that don't seem to be working
var UserDetails = mysequelize.sequelize.define('user_tb', {
id: {
autoIncrement: true,
type: mysequelize.sequelize.Sequelize.INTEGER,
allowNull: false,
},
username: {
type: mysequelize.sequelize.Sequelize.STRING,
primaryKey: true,
unique: true,
},
hierarchyid: {
type: mysequelize.sequelize.Sequelize.STRING
},
password: {
type: mysequelize.sequelize.Sequelize.STRING,
validate: {
len: {
args: [6, 15],
msg: "Please enter a password with at least 6 chars but no more than 15"
}
},
allowNull: false
},
customerid: {
type: mysequelize.sequelize.Sequelize.INTEGER
},
statususer: {
type: mysequelize.sequelize.Sequelize.STRING,
allowNull: false
},
userid: {
unique: true,
type: mysequelize.sequelize.Sequelize.STRING,
allowNull: false
},
authtoken: {
unique: true,
type: mysequelize.sequelize.Sequelize.STRING,
allowNull: false
}
},
{
tableName: 'user_tb',
timestamps: false,
freezeTableName: true
});
UserDetails.prototype.toJSON = function(){
var user = this;
var userObject = user.toObject();
return _.pick(userObject,['userid','password']);
};
UserDetails.prototype.findByCredentials = function(userid, password)
{
console.log('Sunddep');
var User = this;
// return User.fin
User.findOne({userid}).then((user)=> {
if(!user)
{
return Promise.reject();
}
return new Promise((resolve,reject) => {
bcrypt.compare(password,user.password,(err,res) => {
if(res)
{
resolve(user);
}
else{
reject();
}
})
})
});
}
UserDetails.prototype.generateAuthToken = function()
{
var user = this;
var access = 'authtoken';
var token = jwt.sign({userid:
user.userid.toHexString(),access},process.env.JWT_SECRET).toString();
user.build({
access: token
});
user.save().then(() =>{
return token;
});
}
module.exports = {UserDetails}
server.js
app.post('/user/login', (req, res) => {
console.log(req.body);
var body = _.pick(req.body, ['userId', 'password']);
user.findByCredentials(body.userId, body.password).then(() => {
res.send('Sundeep');
},
(e) => {
sendData: ({
wsState: '0',
messageCode: 'WS000001',
message: 'No user find with this Id',
userData: []
});
res.status(400).send(sendData)
});
});
Hi, I am getting error while calling instance method from other class. Can any one tell me how can i achieve it
UserDetails.prototype.findByCredentials = function(userid, password) {.....}
But while run the server.js file i getting error like UserDetails.findByCredentials is not a function while calling from other class
Thanks for help in advance.