Я пытался создать приложение на основе кода производителя котлов, который использует Sequelize ORM. Моя цель здесь — создать hashId для внешнего маршрута, который предотвращает раскрытие числового идентификатора пользователя на стороне клиента. На мой взгляд, длина UUID слишком велика для URI.

Вот определение пользовательской модели из шаблона.

Это довольно прямое определение модели. Хуки гарантируют, что каждый раз при изменении экземпляра, если есть изменение в поле пароля, давайте пересолим и повторно хэшируем его.

Конечно, ТДД. Я использую chai для тестирования модели. В настоящее время проходит оба теста.

Моей первой попыткой было создать hashId на основе идентификатора пользователя. Чтобы получить доступ к userId, мне пришлось бы вызывать мою хеш-функцию в хуке afterCreate. Обратите внимание, что я использовал async await для обработки промисов.

Теперь тесты №2 returns true if the password is correct” не прошли. Похоже, что функция update в afterCreate активировала хук beforeUpdate . Добавьте следующие console.log, чтобы посмотреть, что произойдет.

Вот некоторые наблюдения за поведением крючка

  1. В приложении пароль дважды сбрасывался как в beforeCreate , так и в beforeUpdate. В beforeUpdate ожидалось, что user.changed(“password”) вернет false, если я не обновлю пароль в afterCreate. Однакоuser.changed(“password”) вернул true.
//user in beforeUpdate
user._previousValues.password = 456
user.password = passwordA
user.hashId = d7wzwj

2. База данных сохранила только пароль A, а не пароль B, даже если пароль действительно был обработан дважды.

3. Тест тоже повел себя иначе. Он сравнивал пароль-кандидат, хешированный солью B, с исходным паролем, хэшированным солью A и B.

Так как пользователь beforeUpdate получил изменение hashId, но the _previousDataValues все еще указывает на "456", ссылка на пользователя должна быть зафиксирована после await user.update({...})

Затем, когда обновление было завершено, была вызвана модификация экземпляра в beforeUpdate, но .save() не было, поэтому изменения не сохранялись в БД.

Попытка 1. Как насчет того, чтобы позвонить user.save() в beforeUpdate?

Переполнение стека! Мы создали бесконечный цикл, в котором .save() вызывает beforeUpdate, и наоборот.

Попытка 2. Как насчет использования промиса или синхронного кода? В приведенном ниже коде hashId никогда не сохранялся в базе данных.

//user in beforeUpdate in attempt 2
user._previousValues.password = passwordA
user.password = passwordA
user.hashId = d7wzwj
//user hashid was not preserved in database

Последняя попытка: поскольку значение user.changed(“password”) различалось в зависимости от того, когда был вызван beforeUpdate, мой последний обходной путь состоял в том, чтобы контролировать, является ли функция setSaltAndPassword вызывается на основе того, является ли hashId изменяющимся полем или нет. См. строку 13 в приведенном ниже коде.

Теперь hashId сохранился и setSaltAndPasswordвызывался только один раз. Тест тоже прошел.

PS. Пока я пытаюсь разобраться, на Sequelize GitHub уже 5 лет существует открытая проблема.