I want to save a hashed password. I'm using a setterMethod for this:
module.exports = (sequelize, DataTypes) ->
sequelize.define 'User',
# other model fields [...]
password:
type: DataTypes.STRING
validate: notEmpty: msg: 'You need to set a password.'
set: (pw) ->
salt = bcrypt.genSaltSync(10)
hash = bcrypt.hashSync(pw, salt)
@setDataValue('password', hash)
The setter runs first. An empty string password (''
) is hashed into a non-empty one (say $2a$10$pDDIGnV.r47i9YOv0Fls/euQ0yYvfyq8T1SyP9VRQsTUAqptNmxXO
).
When the validator validates, the password is not empty anymore.
How can I validate the password before the setter?
I looked into hooks but they don't mention setters either.
I'm using [email protected]
.
Just change your function to specifically use the Promise -> next() pattern. Of course the easiest way to handle unique constraints is by setting unique: true on the field definition itself: var User = sequelize. define('User', { username: { type: DataTypes.
Adding constraints between tables means that tables must be created in the database in a certain order, when using sequelize. sync . If Task has a reference to User , the User table must be created before the Task table can be created.
I solved this problem by using two fields, one being type VIRTUAL
that handles the input and validation, and one being type STRING
that holds the hashed password.
This example is not coffeescript
but you should be able to translate easily.
password_hash: {
type: DatabaseTypes.STRING,
allowNull: false,
validate: {
notEmpty: true,
},
},
password: {
type: DatabaseTypes.VIRTUAL,
allowNull: false,
// note that arrow functions cannot access "this", so use the form:
set: function setPassword(val) {
// trigger validation on "password" field
this.setDataValue('password', val);
// hash the password, this can be done in one step by passing the
// number of salt rounds instead of the salt string.
this.setDataValue('password_hash', bcrypt.hashSync(val, 10));
},
validate: {
notEmpty: {
message: 'You need to set a password.',
},
},
},
When you authenticate the user compare the entered password to User.password_hash
rather than User.password
.
instanceMethods: {
// authenticate user given a password
authenticate(password) {
return bcrypt.compareSync(password, this.password_hash);
},
},
You can then call this instance method to authenticate a User
.
User.findById(userId)
.then((user) => {
if (user.authenticate(password)) {
console.log('Authenticated');
} else {
console.log('Not authenticated');
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With