【问题标题】:How can I run model validations before the setterMethod in Sequelize?如何在 Sequelize 中的 setterMethod 之前运行模型验证?
【发布时间】:2015-11-16 22:14:24
【问题描述】:

我想保存一个散列密码。我为此使用了 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)。

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

如何在 setter 之前验证密码?

我查看了hooks,但他们也没有提到二传手。

我正在使用sequelize@2.1.3

【问题讨论】:

    标签: javascript coffeescript sequelize.js


    【解决方案1】:

    我通过使用两个字段解决了这个问题,一个是处理输入和验证的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');
      }
    });
    

    【讨论】:

      【解决方案2】:

      您可以使用 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 hooks API 参考 here

      【讨论】:

        【解决方案3】:

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

        User.init(
          {
            // attributes
            email: {
              type: Sequelize.STRING,
              allowNull: false,
              unique: true,
              validate: {
                isEmail: {
                  msg: "Email address is entered is invalid",
                },
              },
            },
            password: {
              type: Sequelize.STRING,
              allowNull: false,
              validate: {
                notEmpty: {
                  msg: "Password cannot be empty",
                },
                notNull: {
                  msg: "Password cannot be null",
                },
              },
            },
          },
          {
            hooks: {
              beforeSave: (user, options) => {
                if (options.fields.includes("password")) {
                  user.password = bcrypt.hashSync(user.password, 10)
                }
              },
            },
            sequelize,
            modelName: "user",
            underscored: true,
          }
        )

        【讨论】:

          猜你喜欢
          • 2023-03-26
          • 1970-01-01
          • 2018-01-28
          • 1970-01-01
          • 1970-01-01
          • 2016-05-27
          • 2013-11-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多