如何在Sequelize中的setterMethod之前运行模型验证?

时间:2015-08-23 11:34:23

标签: javascript coffeescript sequelize.js

我想保存一个哈希密码。我正在使用setterMethod:

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)

首先运行setter。空字符串密码('')被散列为非空密码(例如$2a$10$pDDIGnV.r47i9YOv0Fls/euQ0yYvfyq8T1SyP9VRQsTUAqptNmxXO)。

验证器验证后,密码不再为空。

如何在设置者之前验证密码?

我调查了hooks,但他们也没有提到制定者。

我正在使用sequelize@2.1.3

3 个答案:

答案 0 :(得分:0)

我通过使用两个字段解决了这个问题,一个是处理输入和验证的类型VIRTUAL,另一个是包含哈希密码的类型STRING

此示例不是coffeescript,但您应该可以轻松翻译。

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.',
    },
  },
},

当您对用户进行身份验证时,会将输入的密码与User.password_hash而不是User.password进行比较。

instanceMethods: {
  // authenticate user given a password
  authenticate(password) {
    return bcrypt.compareSync(password, this.password_hash);
  },
},

然后,您可以调用此实例方法来验证User

User.findById(userId)
.then((user) => {
  if (user.authenticate(password)) {
    console.log('Authenticated');
  } else {
    console.log('Not authenticated');
  }
});

答案 1 :(得分:0)

您可以使用here所述的beforeCreate钩子来完成

本质上,您的模型代码看起来像这样

User.init(
  {
    password: {
      type: DataTypes.TEXT,
      allowNull: false,
      validate: {
        len: {
          args: [6],
          msg: "Minimum password length is 6 characters",
        },
        notEmpty: {
          args: [true],
          msg: "Please enter a password",
        },
        notNull: {
          args: [true],
          msg: "Please enter a password",
        },
      },
    },
  },
  {
    hooks: {
      beforeCreate: async (user) =>
        (user.password = await bcrypt.hash(user.password, 10)),
    },
    sequelize,
    modelName: "User",
  },
);

检查Sequelize挂钩API参考here

答案 2 :(得分:0)

所以我使用 beforeSave 钩子,用于插入和更新。我测试了它似乎可以解决问题 - 验证也按预期工作。

onClick