I wrote a class which extends a Model, and I need create a method to compareSync password:
const { Model, DataTypes } = require('sequelize');
class User extends Model {
static init(sequelize) {
super.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
status: DataTypes.INTEGER
},
{
sequelize,
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
)
}
static associate(model) {
this.belongsToMany(models.Movie, { through: models.Ratings });
}
}
module.exports = User;
The hook is working, I thought to add after beforeCreate a:
instanceMethods: {
validPassword: function (password) {
return bcrypt.compareSync(password, this.password);
}
}
Using this class how I can define an user method?
I got this:
const { Model, DataTypes } = require('sequelize');
const bcrypt = require("bcrypt")
class User extends Model {
static init(sequelize) {
super.init({
username: DataTypes.STRING,
password: DataTypes.STRING,
role: DataTypes.STRING,
status: DataTypes.INTEGER
},
{
sequelize,
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
}
}
)
}
static associate(model) {
this.belongsToMany(models.Movie, { through: models.Ratings });
}
validPassword(password) {
return bcrypt.compareSync(password, this.password);
}
}
module.exports = User;
If I wanna use the method inside controller for example:
const login = async (req, res) => {
const { username, password } = req.params;
const user = await User.findOne({
where: { username }
});
if (!user) {
return res.status(400).send("User not find!")
}
if(!user.validPassword(password)){..}
res.send(user)
}
Related
Have been trying to create a password hash in my nodejs code
But it not working and not showing any error message for me to debug.
And my user is not creating also.
I dont know if there is a better way to do it.
This is my file which is responsible for the code...Model/User.js
const Promise = require('bluebird')
const bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'))
function hashPassword (user) {
const SALT_FACTOR = 8
if (!user.changed('password')) {
return;
}
return bcrypt
.genSaltSyncAsync(SALT_FACTOR)
.then(salt => bcrypt.hashAsync(user.password, salt, null))
.then(hash => {
user.setDataValue('password', hash)
})}
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
}, {
hooks: {
beforeCreate: hashPassword,
beforeUpdate: hashPassword,
beforeSave: hashPassword
}
})
User.prototype.comparePassword = function (password) {
return bcrypt.compareAsync(password, this.password)
}
return User }
Does the following snippet help in any way?
const bcrypt = require('bcryptjs');
const userAbc = {
email: 'user#user.com',
password: '1234'
}
async function hashPassword(user) {
try {
const hashedPassword = await bcrypt.hash(user.password, 12);
user.password = hashedPassword;
console.log(user);
} catch (err) {
console.log(err);
}
}
hashPassword(userAbc);
I did change the bcrypt-nodejs to bcryptjs then replace genSaltSyncAsync to genSaltSync and everyother Async to Sync and it worked.
I'm trying to build a relation between the users and his favorite cryptocurrency.
Meaning, multiple Users can have the same crypto as their favorites.
Coin.js
module.exports = (sequelize, DataTypes) => {
const Coin = sequelize.define('Coin', {
cryptoName: DataTypes.STRING,
})
Coin.associate = function(models) {
Coin.belongsToMany(models.CoinsUserRelations, {foreignKey: 'CoinID', through: 'CoinsUserRelations'})
}
return Coin
}
User.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
}, {
hooks: {
beforeSave: hashPassword
}
})
User.associate = function(models) {
User.belongsToMany(models.CoinsUserRelations, {foreignKey: 'UserID', through: 'CoinsUserRelations'})
}
return User
}
These are my 2 tables at the moment and now I'm trying to build a relation between them. and I keep receiving this error on my console which I do not understand why.
I've edited multiple time to resolve the issue, This was the result with the help of Anatoly
CoinsUserRelations.js
module.exports = (sequelize, DataTypes) => {
const CoinsUsersRelations = sequelize.define('CoinsUsersRelations', {
UserID: {
type: DataTypes.INTEGER,
},
CoinID: {
type: DataTypes.INTEGER,
}
})
return CoinsUsersRelations
}
I'm really unsure on why I get this error if I'm actually defining the model before creating the relations..
Index.js
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.db.database,
config.db.user,
config.db.password,
config.db.options
)
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file))
db[model.name] = model
})
Object.keys(db).forEach(function (modelName) {
if (db[modelName].associate) {
db[modelName].associate(db)
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
Edit part for a bug called SequelizeEagerLoadingError
module.exports = {
async getUserFavoriteCrypto (req, res) {
try {
const coins = await db.Users.findOne({
where: {
UserID : req.query.userId
},
attributes: ['UserID'],
include: [{
model: db.Coins,
required: false
}]
})
console.log(coins)
res.send({
coins: coins
})
} catch (err) {
res.status(400).send({
error: err
})
}
}
}
You should register all models and only after that all their associations in one place. See my answer on a similar problem
My Product model:
const { Model, DataTypes } = require('sequelize');
class Product extends Model {
static init(connection) {
super.init({
name: DataTypes.STRING,
description: DataTypes.TEXT,
purchase_price: DataTypes.DOUBLE,
sale_price: DataTypes.DOUBLE
}, {sequelize: connection});
}
static associate(models) {
this.belongsToMany(models.Purchase, {
foreignKey: 'product_id', through: 'products_purchases', as: 'purchases'
});
}
}
module.exports = Product;
My Purchase Model:
const { Model, DataTypes } = require('sequelize');
const Product = require('../models/Product');
class Purchase extends Model {
static init(connection) {
super.init({
request_number: DataTypes.STRING,
datetime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
email: DataTypes.STRING,
status: DataTypes.ENUM([
'orderPlaced', 'paymentMade','paymentConfirmed', 'forwardedProduct','productReceived','orderCanceled'
])
}, {sequelize: connection});
}
static associate(models) {
this.belongsTo(models.User, {foreignKey: 'user_id', as: 'user'});
this.belongsToMany(models.Product, {
foreignKey: 'purchase_id', through: 'products_purchases', as: 'products'
});
}
}
module.exports = Purchase;
And finally my ProductPurchase Model:
(Note that there is some extra columns in the relationship table)
const { Model, DataTypes } = require('sequelize');
class ProductPurchase extends Model {
static init(connection) {
super.init({
product_value: DataTypes.FLOAT,
product_quantity: DataTypes.INTEGER
}, {
sequelize: connection,
modelName: 'products_purchases'
});
}
}
module.exports = ProductPurchase;
I want to insert data into purchases table and also into products_purchases. I tried to do it the way below, but I don't know how to send the data of the extra columns from ProductPurchase:
async store(req, res) {
try {
const { user_id } = req.params;
const user = await User.findByPk(user_id);
if (!user) {
return res.status(400).json('User not found!');
}
// productsData = [{ productId, productPrice, quantity }];
const { request_number, datetime, email, status, productsData } = req.body;
const purchase = await Purchase.create({
request_number, datetime, email, status, user_id
});
const productsIds = productsData.map(product => {
return product.productId;
});
const products = await Product.findAll({
where: {id: productsIds}
});
await purchase.addProduct(products);
return res.json(products);
} catch (error) {
return res.status(500).json(error);
}
}
Can anybody help me?
Before create doesn't work on my sequelize model
I created a template, but for some reason my before create doesn't work and I don't know what it can be anymore.
async createUser(req,res){
const { name,email,login,password } = req.body
const verify = await Users.findOne({where:{login: login}});
if(verify){ return res.status(400).json({result: 'User already exists'})}
const user = await Users.create({name,email,login,password});
}
model:
class Users extends Model {
static init(sequelize){
super.init({
name: DataTypes.STRING,
email: DataTypes.STRING,
login: DataTypes.STRING,
password: DataTypes.STRING,
}, {sequelize, tableName:'users'},
{
hooks: {
beforeCreate: (user) => {
console.log('ae');
},
},
}
)
do not enter my before and do not return my console.log
You should put the hooks option inside the second object parameter. Model.init() interface is:
public static init<M extends Model = Model>(this: ModelCtor<M>, attributes: ModelAttributes, options: InitOptions<M>): void;
Here is a working example:
import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
class User extends Model {}
User.init(
{
name: DataTypes.STRING,
email: DataTypes.STRING,
login: DataTypes.STRING,
password: DataTypes.STRING,
},
{
sequelize,
tableName: 'users',
hooks: {
beforeCreate: (user) => {
console.log('======== ae ========');
},
},
},
);
(async function test() {
try {
await sequelize.sync({ force: true });
await User.create({ name: 'Alanna', email: 'example#gmail.com', login: 'value', password: '123' });
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
The execution results:
======== ae ========
Executing (default): INSERT INTO "users" ("id","name","email","login","password") VALUES (DEFAULT,$1,$2,$3,$4) RETURNING *;
Now, the beforeCreate hook of the User model works fine.
I'm trying to hash my password field before storing it in the database. For that reason I've created a virtual field called password and an actual field called hashedPassword. The trouble is that when I try to encrypt the password in beforeCreate hook, it the user.password is undefined. I have tried every thing. I've also defined custom getters and setters for the virtual field. I don't know what I'm doing wrong here. Any help or guidance would be appreciated. Thanks.
import bcrypt from 'bcrypt';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
'User',
{
passwordhash: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
password: {
allowNull: false,
type: DataTypes.VIRTUAL,
set(password) {
const valid = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$^+=!*()#%&]).{8,30}$/.test(
password
);
if (!valid) {
throw new Error(`Password not valid ${password}`);
}
this.setDataValue('password', password);
},
get() {
return this.getDataValue('password');
}
}
}
},
{
hooks: {
beforeCreate: function hashPassword(user) {
console.log('user is:', user);
return bcrypt
.hash('Abcdefgh1#', 12)
.then(hashed => {
user.passwordhash = hashed;
})
.catch(error => error);
}
}
}
);
User.associate = function(models) {
// associations can be defined here
};
return User;
};
use hooks :
hooks: {
beforeCreate: async (user, options) => {
let salt = await bcrypt.genSalt(10)
let hash = await bcrypt.hash(user.password, salt)
user.password = hash;
}
}
and for updating password fields use this:
User.beforeBulkUpdate(async instance => {
if (instance.attributes.password) {
let salt = await bcrypt.genSalt(10)
let hash = await bcrypt.hash(instance.attributes.password, salt)
instance.attributes.password = hash;
}
})
this works fine for me