sequelize.js - Sequelize 批量更新不同的行为

标签 sequelize.js

我在我的 Sequelize 模型中找不到问题。当我批量更新(种子)我的用户时,我得到了不同的密码集,因此无法登录。当我将数据库条目更新为正确的密码时,它显然有效。批量更新钩子(Hook)或其他东西似乎有问题?这很奇怪。

'use strict';

var crypto = require('crypto');

var validatePresenceOf = function(value) {
  return value && value.length;
};

module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define('user', {
    name:     { type: DataTypes.STRING },
    email:    { type: DataTypes.STRING, unique: true, allowNull: false, validate: {notEmpty: true},
      set: function(email)  {
        this.setDataValue('email', email.toLowerCase());
      }
    },
    role:     { type: DataTypes.STRING, defaultValue: 'user' },
    password: { type: DataTypes.STRING, allowNull: false, validate: { notEmpty: true, isEmail: true },
    },
    provider: { type: DataTypes.STRING },
    salt:     { type: DataTypes.STRING }
  }, {
    underscored: true,
    getterMethods: {
      profile: function() {
        return {
          name: this.name,
          role: this.role
        }
      }
    },
    hooks: {
      beforeBulkCreate: function(users, fields, fn) {
        var totalUpdated = 0;
        users.forEach(function(user) {
          user.updatePassword(function(err) {
            if (err) {
              return fn(err);
            }
            totalUpdated += 1;
            if (totalUpdated === users.length) {
              return fn();
            }
          });
        });
      },
      beforeCreate: function(user, fields, fn) {
        user.updatePassword(fn);
      },
      beforeUpdate: function(user, fields, fn) {
        if (user.changed('password')) {
          user.updatePassword(fn);
        }
      }
    },
    instanceMethods: {
      /**
       * Authenticate - check if the passwords are the same
       *
       * @param {String} plainText
       *        {function} callBack
       * @api public
       */
      authenticate: function(password, callback) {
        if (!callback) {
          return this.password === this.encryptPassword(password);
        }

        var _this = this;
        this.encryptPassword(password, function(err, pwdGen) {
          if (err) {
            callback(err);
          }

          if (_this.password === pwdGen) {
            callback(null, true);
          }
          else {
            callback(null, false);
          }
        });
      },
      /**
       * Make salt
       *
       * @return {String}
       * @api public
       */
      makeSalt: function(byteSize, callback) {
        var defaultByteSize = 16;

        if (typeof arguments[0] === 'function') {
          callback = arguments[0];
          byteSize = defaultByteSize;
        }
        else if (typeof arguments[1] === 'function') {
          callback = arguments[1];
        }

        if (!byteSize) {
          byteSize = defaultByteSize;
        }

        if (!callback) {
          return crypto.randomBytes(byteSize).toString('base64');
        }

        return crypto.randomBytes(byteSize, function(err, salt) {
          if (err) {
            callback(err);
          }
          return callback(null, salt.toString('base64'));
        });
      },
      /**
       * Encrypt password
       *
       * @param {String} password
       * @return {String}
       * @api public
       */
      encryptPassword: function(password, callback) {
        if (!password || !this.salt) {
          if (!callback) {
            return null;
          }
          return callback(null);
        }

        var defaultIterations = 10000;
        var defaultKeyLength = 64;
        var salt = new Buffer(this.salt, 'base64');

        if (!callback) {
          return crypto.pbkdf2Sync(password, salt, defaultIterations, defaultKeyLength)
                       .toString('base64');
        }

        return crypto.pbkdf2(password, salt, defaultIterations, defaultKeyLength,
          function(err, key) {
            if (err) {
              callback(err);
            }
            return callback(null, key.toString('base64'));
          });
      },
      updatePassword: function(fn) {
        // Handle new/update passwords
        if (this.password) {
          if (!validatePresenceOf(this.password)) {
            fn(new Error('Invalid password'));
          }

          // Make salt with a callback
          var _this = this;
          this.makeSalt(function(saltErr, salt) {
            if (saltErr) {
              fn(saltErr);
            }
            _this.salt = salt;
            _this.encryptPassword(_this.password, function(encryptErr, hashedPassword) {
              if (encryptErr) {
                fn(encryptErr);
              }
              _this.password = hashedPassword;
              fn(null);
            });
          });
        } else {
          fn(null);
        }
      }

    }
  });
  return User;
}

最佳答案

我认为您需要添加一个 beforeBulkUpdate Hook ?您有一个 beforeUpdate Hook ,当您更新实例时会触发该 Hook ,但如果您通过模型进行批量更新,则需要一个 beforeBulkUpdate Hook 。

http://sequelize.readthedocs.org/en/latest/api/hooks/#beforebulkupdatename-fn

关于sequelize.js - Sequelize 批量更新不同的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28739539/

相关文章:

postgresql - Docker-compose : Postgresql ECONNREFUSED

postgresql - 使用 postgres 进行 Sequelize - 查找 uuid 数组中包含 uuid 的所有位置

Node.js + Sequelize + SQL Server

node.js - 加入 Sequelize

sequelize.js - SequelizeEagerLoadingError 和关联

json - Breeze Sequelize : get entities in the server + transaction

javascript - Node.js 的 Sequelize.js 可以定义主键未命名为 'id' 的表吗?

node.js - 插入数据时如何阻止 sequelize 创建不需要的主键?

mysql - 查询运行成功但未找到记录时的响应代码

node.js - 如何将多个数据从 sequelize promise 传递给 View 而不使用内部 then 方法