sequelize: beforeUpsert hook is unable to change values sent to the database

What are you doing?

const User = sequelize.define('User', {
      username: {
        type: Sequelize.STRING,
        allowNull: false,
        unique: true,
        validate: {
          not: /\s/,
        },
      },
      password: {
        type: Sequelize.STRING,
        allowNull: false,
      },
    }
)
async function hashPasswordUpsertHook(values: UserInitAttributes): Promise<void> {
  const hash = await promisify(pw => bcrypt.hash(pw, 10))(values.password)
  values.password = hash
  console.log('beforeUpsert', values)
  return values
}
User.beforeUpsert(hashPasswordUpsertHook)

User.upsert({username: 'andy', password: 'correct horse battery staple'}, {hooks: true})

What do you expect to happen?

Sequelize upserts the hashed password from the hook

What is actually happening?

It upserts the unhashed password.

Output, either JSON or SQL

beforeUpsert { username: 'root',
  password: '$2a$10$caNF8AHVmTBA6yabF1oB2uc4jNfd6GdjU8mx1W5pqv8T3tbojmgum' }
Executing (default): CREATE OR REPLACE FUNCTION pg_temp.sequelize_upsert() RETURNS integer AS $func$ BEGIN INSERT INTO "Users" ("username","password","createdAt","updatedAt") VALUES ('root','correct horse battery staple','2018-01-02 21:57:36.628 +00:00','2018-01-02 21:57:36.628 +00:00'); RETURN 1; EXCEPTION WHEN unique_violation THEN UPDATE "Users" SET "username"='root',"password"='correct horse battery staple',"updatedAt"='2018-01-02 21:57:36.628 +00:00' WHERE ("id" IS NULL OR "username" = 'root'); RETURN 2; END; $func$ LANGUAGE plpgsql; SELECT * FROM pg_temp.sequelize_upsert();

Dialect: postgres Dialect version: 6.4.2 Database version: XXX Sequelize version: 4.28.6 Tested with latest release: Yes (If yes, specify that version)

Note : Your issue may be ignored OR closed by maintainers if it’s not tested against latest version OR does not follow issue template.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 1
  • Comments: 15 (6 by maintainers)

Most upvoted comments

@jedwards1211 However, we would want the object owned by the user to be changed. When the QueryInterface does the upsert, it is taking the values from insertValues and updateValues, not the values passed into the hook.

My suggested code would be after the hook occurs, prior to the QueryInterface.upsert. It would modify insertValues and updateValues with fields from the values passed into the hook. I am sure a bit more work would need to be done to make it neater, but would that concept work?

@mccabemj did you do the PR for this issue?

Hey guys, any news on this?