Julius Guevarra
Julius Guevarra

Reputation: 888

Sequelize: beforeCreate hook not updating hashed password

I am trying to save the hashed password using beforeCreate hook. However, the hashed that I generate doesn't get saved but instead saves the plain text version.

This what my UserAuth model looks like

interface IUserAuthAttributes {
  user_auth_id: number;
  username: string;
  password: string;
  full_name: string;
  disable_user: number;
  user_level_id: number;
  created_modified: string | Date;
}

interface IUserAuthCreationAttributes
  extends Optional<IUserAuthAttributes, 'user_auth_id' | 'disable_user' | 'user_level_id' | 'created_modified'> {
  username: string;
  password: string;
  full_name: string;
}

export class UserAuth
  extends Model<IUserAuthAttributes, IUserAuthCreationAttributes>
  implements IUserAuthAttributes {
  public user_auth_id!: number;
  public username!: string;
  public password!: string;
  public full_name!: string;
  public disable_user: number;
  public user_level_id!: number;
  public created_modified: string | Date;

  public toUserJSON: () => UserAuth;
  public generateAccessToken: (payload: IUser) => string;
  public generateRefreshToken: (payload: IUser) => string;
  public passwordMatch: (pw: string, cb: (err: any, isMatch?: any) => void) => void;
  public getRole: () => 'meter_reader' | 'evaluator' | null;
}

UserAuth.init({
  user_auth_id: {
    autoIncrement: true,
    type: DataTypes.INTEGER.UNSIGNED,
    allowNull: false,
    primaryKey: true
  },
  username: {
    type: DataTypes.STRING(20),
    allowNull: false,
    defaultValue: ""
  },
  password: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: ""
  },
  full_name: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: ""
  }
  // ... other 
},
  {
    sequelize: DBInstance,
    tableName: 'user_auth',
    timestamps: false,
});

This is how I defined the hook:

UserAuth.beforeCreate((user, option) => {
  const salt = bcrypt.genSaltSync();

  //  Using hashSync throws an error "Illegal arguments: undefined, string"
  // const hash = bcrypt.hashSync(user.password, salt);

  bcrypt.hash("password", salt, (err, hash) => {
    if (err) throw new Error(err.message);

    console.log('HASH -------', hash);
    user.password = hash;
  });
});

When I create a user:

const { username, password, full_name } = req.body;

const user = await UserAuth.create({
   username, password, full_name
});

Upon logging the hashed value to the console, I indeed generate one successfully

HASH ------- $2a$10$KN.OSRXR7Od8WajjuD3hyutqk1tGS/Be.V9NDrm3F7fyZWxYAbJ/2

Upvotes: 1

Views: 715

Answers (1)

Julius Guevarra
Julius Guevarra

Reputation: 888

Finally found the solution.

In my previous code I was using a callback for the generating salt and hash. Also from the previous code const hash = bcrypt.hashSync(user.getDataValue('password'), salt); it was throwing an error Illegal arguments: undefined, string because user.password returns undefined from the Instance, so instead, I get the value of the password using getDataValue method of the instance then using setDataValue to set the hashed password instead of using an assignment operation user.password = hash

UserAuth.beforeCreate((user, option) => {
  if (user.isNewRecord) {
    const salt = bcrypt.genSaltSync();
    const hash = bcrypt.hashSync(user.getDataValue('password'), salt);

   // user.password = hash; Not working
    user.setDataValue('password', hash); // use this instead
  }
})

Upvotes: 1

Related Questions