beforeCreate挂钩更改未保存到数据库

时间:2020-07-02 08:32:23

标签: mysql node.js sequelize.js

在保存到数据库之前,我正在使用beforeCreate加密密码。

当我这样做时:

const user = await User.create({name, email, password});
res.json(user);

我看到加密的密码作为回应。但是在数据库中,密码未加密。如果我执行user.reload()然后发送,我会看到数据库中存储了什么(未加密的密码)。

这是模型:

    User.init({
    name: {
        type: DataTypes.STRING,
        allowNull: false
    }, 
    ...
},{
    sequelize,
    hooks: {
        beforeCreate: (user, options) => {
           return bcrypt.genSalt(10)
            .then(salt => {
                bcrypt.hash(user.password, salt)
                    .then(hashedPassword => {
                        user.password = hashedPassword;
                        console.log(user.password, "FS");
                        return user.password;
                    })
                    .catch(err => console.log(err));
            })
            .catch(err => console.log(err));
        }
    }

})

这是控制器:

 try{
        const {name, email, password} = req.body;
        if(isEmpty(name) || isEmpty(email) || isEmpty(password)){
            res.status(400).json({errMessage: 'Enter name, email and password'});
        }
        const user = await User.create({name, email, password});
        res.json(user); //data with encrypted password is sent, but not saved in db
    }

1 个答案:

答案 0 :(得分:0)

beforeCreate钩子不需要返回值,该函数签名的返回值类型如下:

export type HookReturn = Promise<void> | void;

此外,您忘记在return语句之前添加bcrypt.hash(user.password, salt),导致beforeCreate函数不等待加密异步操作完成。

这是一个可行的示例:

import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
import bcrypt from 'bcrypt';

class User extends Model {
  password!: string;
  name!: string;
}
User.init(
  {
    name: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    email: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    modelName: 'users',
    hooks: {
      beforeCreate: (user: User) => {
        return bcrypt
          .genSalt(10)
          .then((salt) => {
            return bcrypt
              .hash(user.password, salt)
              .then((hashedPassword) => {
                user.password = hashedPassword;
              })
              .catch((err) => console.log(err));
          })
          .catch((err) => console.log(err));
      },
    },
  },
);

(async function() {
  try {
    await sequelize.sync({ force: true });
    await User.create({ name: 'ab', email: 'test@gmail.com', password: '123456' });
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

执行日志:

Executing (default): DROP TABLE IF EXISTS "users" CASCADE;
Executing (default): DROP TABLE IF EXISTS "users" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "users" ("id"   SERIAL , "name" VARCHAR(255) NOT NULL, "email" VARCHAR(255) NOT NULL, "password" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "users" ("id","name","email","password") VALUES (DEFAULT,$1,$2,$3) RETURNING *;

检查数据库中的数据记录:

node-sequelize-examples=# select * from users;
 id | name |     email      |                           password
----+------+----------------+--------------------------------------------------------------
  1 | ab   | test@gmail.com | $2b$10$XQb89m.b6ie8ImokS6JPdurWfIH4Cq19y.XGhb7LpWYUklp5jaYh2
(1 row)