Studio-Yandex-Practicum / ProCharity_back_2.0

bot ProCharity (НКО Фонд Друзья)
13 stars 13 forks source link

Исправление бага: можно создать записи в external_site_users с одинаковым external_id #619

Closed eugemos closed 2 months ago

eugemos commented 3 months ago

Что сделано

Поведение эндпойнтов api/auth/external_user_registration/fund и api/auth/external_user_registration/volunteer изменено в соответствии с условиями задачи #615. Дополнительно введён запрет на создание в external_site_users двух неархивных записей с одинаковым id_hash, так как наличие таких записей приводит к непредсказуемому поведению при регистрации пользователя в боте командой \start id_hash. Логика поведения данных эндпойнтов теперь такая (обновлено):

Как проверял

Локально. Для обращения к эндпойнтам использовал страницу документации API. Для просмотра и внесения изменений в БД использовал DBeaver. При этом, перезапускал бот после изменений БД вручную. Проверил, что логика работы эндпойнтов соответствует заявленной выше.

gorskyolga commented 3 months ago

При тестировании поняла, что пользователь с существующим user_id не сможет изменить id_hash на какой-то другой свободный. Потенциально может быть полезно изменить id_hash (без создания дублирующей записи, как сейчас в develop).

eugemos commented 3 months ago

При тестировании поняла, что пользователь с существующим user_id не сможет изменить id_hash на какой-то другой свободный. Потенциально может быть полезно изменить id_hash (без создания дублирующей записи, как сейчас в develop).

Не уверен: id_hash, ведь, напрямую выводится сайтом из user_id, поэтому изменение id_hash при неизменном user_id выглядит сомнительно.

gorskyolga commented 3 months ago

Не уверен: id_hash, ведь, напрямую выводится сайтом из user_id, поэтому изменение id_hash при неизменном user_id выглядит сомнительно.

Только если хэширующая функция не будет изменена. Ладно, вероятность того, что её поменяют, маленькая. Наверное можно не предусматривать, что id_hash могут меняться.

Xalgina commented 2 months ago

Сейчас при попытке изменить id_hash у существующего пользователя возвращается 400 Bad Request “Изменение id_hash у существующего пользователя запрещено.” - так и должно быть, судя по последним комментам?

Xalgina commented 2 months ago

Сейчас при попытке изменить id_hash у существующего пользователя возвращается 400 Bad Request “Изменение id_hash у существующего пользователя запрещено.” - так и должно быть, судя по последним комментам?

Да, пока базовое поведение такое.

eugemos commented 2 months ago

Забавная история с этим id_hash получается. Вообще-то этот PR решает задачу о запрете создания записей с одинаковым external_id, про одинаковые id_hash в её условии ничего не говорится. Запрет на создание двух неархивных записей с одинаковым id_hash я ввёл по своей инициативе, потому что это прямо реальные грабли. Наличие же в БД нескольких записей с одинаковыми id_hash, из которых только одна неархивная, никаких проблем не создаёт, хотя, конечно, так быть не должно, т.е. это свидетельствует о каких-то проблемах в работе внешнего сайта. В связи с этим есть вопросы, @gorskyolga:

  1. Точно ли надо запрещать такое поведение?
  2. Если запрещать, то какое должно быть сообщение об ошибке? То, которое предполагает @Xalgina, на мой взгляд, не годится. Неправильно про архивного пользователя говорить, что он "уже существует", потому что он удалён, хотя и мягко. Вот, например, в аналогичном случае с external_id мы так и пишем, что "Пользователь удален. Обновление невозможно."
gorskyolga commented 2 months ago

Мне кажется, нужно запрещать создание двух записей (архивной и неархивной) с одинаковым id_hash.

  1. Уникальность id_hash (в том числе между архивными и неархивными записями) - это базовое поведение в develop сейчас.
  2. Метод get_by_id_hash предполагает возвращение одной записи. Если разрешить дубликаты id_hash с архивной записью, то при is_archived = None записи будет две, а метод будет возвращать одну запись. Это его еще рефакторить придется.
  3. У нас есть эндпоинт "api/messages/group", который рассылает сообщения по id_hash (метод send_message_to_user_by_id_hash). Это единственное место, где сейчас используется id_hash, кроме регистрации и декоратора, проверяющего авторизацию. В нем также предполагается, что может быть только одна запись с id_hash. Этот эндпоинт бы конечно переделать на отправку по user_id, но не факт, что успеем это реализовать, так что его тоже нужно принимать во внимание.

Сообщение об ошибке можно сделать: "Указанный id_hash не может быть установлен.".

eugemos commented 2 months ago

Обновил описание.

Xalgina commented 2 months ago

Протестировано, ок. Запрещается создание двух записей (архивной и неархивной) с одинаковым id_hash с сообщением об ошибке: "Указанный id_hash не может быть установлен."