Ошибка `run_second_factor!` при попытке повысить до администратора

Продолжая тему Can't upgrade user to admin - unhandled server error

(Привет, @Discoursenaut.) Я потратил на это всё afternoon. Мне всё ещё не удалось выяснить, в чём именно проблема, но если добавить rescue вокруг строки 1099 (manager.run!), то исчезает загадочная ошибка «An unhandled server error has occurred.» (Произошла необработанная ошибка сервера). Я не могу найти эту строку нигде в исходном коде.

Перехват ошибки не помогает, так как переменная result не определена, поэтому позже происходит сбой.

Я пробовал все возможные комбинации: пользователь с включённой/отключённой 2FA, параметр enforce_second_factor выключен/установлен для сотрудников. Странно, что когда я сегодня добавил пользователя и попытался сделать его администратором с помощью другой учётной записи администратора, всё сработало как ожидалось, но другие администраторы не могут назначать администраторами других пользователей. Говорят, что эта проблема существует уже год. Не может ли это быть связано с какой-то проблемой в базе данных?

Это свежая сборка (как минимум сегодняшняя). Используются только стандартные плагины, даже в режиме safe-mode.

@Osama, у вас есть комментарий несколько строк ниже, возможно, у вас есть какая-то идея?

Не вижу, как result может быть undefined, учитывая:

Вы точно уверены, что используете самую последнюю версию?

Я сегодня запустил пересборку.

Есть ли где-то еще, куда можно поместить отладочный лог?

Если вы сможете предоставить нам минимальный пример воспроизведения (например, список настроек сайта и их значения), это очень поможет.

Можете ли вы перехватить исключение (rescue) для всего метода и записать ошибку в лог?

def run_second_factor!(action_class, action_data: nil, target_user: current_user)
  if current_user && target_user != current_user
    # Анонимные пользователи могут запускать 2FA для другого целевого пользователя, но авторизованные — нет.
    # Это должно быть проверено в месте вызова `run_second_factor!`.
    raise "running 2fa against another user is not allowed"
  end

  action = action_class.new(guardian, request, opts: action_data, target_user: target_user)
  manager = SecondFactor::AuthManager.new(guardian, action, target_user: target_user)
  yield(manager) if block_given?
  result = manager.run!(request, params, secure_session)

  if !result.no_second_factors_enabled? && !result.second_factor_auth_completed? &&
       !result.second_factor_auth_skipped?
    # такого никогда не должно происходить, но я хочу узнать, если вдруг это случится! (osama)
    raise "2fa process ended up in a bad state!"
  end

  result
+rescue => err
+  Rails.logger.error(err.full_message)
+  raise
end

После внесения этого изменения (и перезагрузки воркеров Unicorn) в /logs должно появиться сообщение, которое поможет нам понять, в чём проблема.

Вздыхаю. Похоже, ошибка в run_second_factor! возникла из-за моих отладочных сообщений; создание багов при поиске других — одно из моих любимых занятий.

Started PUT "/admin/users/30591/grant_admin" for 174.50.213.142 at 2024-07-02 14:14:38 +0000
Processing by Admin::UsersController#grant_admin as */*
  Parameters: {"user_id"=>"30591"}
Completed 403 Forbidden in 6ms (Views: 0.1ms | ActiveRecord: 0.0ms | Allocations: 2263)

Похоже, что Guardian по какой-то причине не позволяет мне сделать пользователя администратором.

Но я всё ещё не понимаю, почему это не работает и почему выводится ошибка «An unhandled server error has occurred.», когда я не могу найти эту ошибку ни в одном из файлов кода Discourse.

Ага. И это интересно. Я смог изменить адрес с jay@example.com на myaddress@gmail.com, но попытка подтвердить адрес myaddress+123@gmail.com также приводит к сообщению «An unhandled server error has occurred.». Параметр normalize_emails не установлен.

Думаю, что проблема в run_second_factor!, но я пока не могу точно понять, что именно. Добавляю несколько Rails.logger.warn с вызовами xxx.inspect, возможно, так я что-то найду.

На мой взгляд, что-то не так с auth_manager. Кажется, он по какой-то причине пытается выполнить перенаправление? Обычным пользователям не требуется двухфакторная аутентификация, поэтому я не понимаю, почему обычный пользователь не может изменить свой адрес электронной почты. Но я пробовал с пользователем без 2FA, без резервных кодов, как вошедшим в систему до нажатия на ссылку подтверждения нового адреса, так и после входа — все попытки завершаются ошибкой «An unhandled server error has occurred.».

Это, кажется, связано с следующим:

Ошибка 403 — это нормально и ожидаемо: фронтенд-приложение перехватывает ответ 403 и интерпретирует его как «нельзя предоставить права администратора, так как требуется двухфакторная аутентификация, перейдём на страницу 2FA».

Не нормально вот что:

Скажите, где именно вы видите эту ошибку? Это всплывающее окно во фронтенде? Ошибка в логах? Как вы отметили, я не могу найти это сообщение об ошибке нигде во всей истории кодовой базы, так что это очень странно.

Так может, бэкенд не рендерит то, что содержит URL для 2FA? Но ошибка возникает независимо от того, включена ли у пользователя 2FA, независимо от того, включена ли настройка force-2fa, и независимо от того, вошёл ли пользователь с уже настроенной 2FA.

Да. Я пробовал безопасный режим, но вот эти плагины установлены:

          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-topic-voting.git
          - git clone https://github.com/discourse/discourse-chat-integration.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-reactions.git
          - git clone https://github.com/discourse/discourse-docs.git
          - git clone https://github.com/discourse/discourse-user-notes.git

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

Возможно, что-то запускает сценарий «нам нужна 2FA», хотя на самом деле 2FA не требуется. Конечно, логично, что ошибка могла бы сработать для входа с 2FA, если бы её не было. Я полагаю, это в guardian? Не могу понять, куда добавить отладочные вызовы Rails.logger, чтобы разобраться в этом.

Это очень маловероятно, поэтому прошу прощения, если я говорю что-то совершенно нелепое, но поиск в Google по запросу «An unhandled server error has occurred» возвращает результаты только для кода Bitwarden, что заставляет меня полагать, что на вашей локальной системе что-то перехватывает или искажает ваш запрос. Можете ли вы воспроизвести эту проблему с другого компьютера?

Можете проверить вкладку «Network» в инструментах разработчика вашего браузера и посмотреть, какой ответ возвращается для запроса к конечной точке grant_admin?

Пожалуйста, покажите также вкладку «Payload».

image

Похоже, это исходит с сервера. Я не могу найти эту строку в базе данных (например, в пользовательском тексте) или при поиске по всем файлам в /var/www/discourse.

Вкладки Payload нет:

image

Подождите!!! Я восстановил базу данных на другом сервере, и там корректно происходит перенаправление на страницу второй факторной аутентификации, которая, после получения ключа второй факторной аутентификации, немедленно меняет статус администратора пользователя (без необходимости отправки email! чего я не знал!).

Значит, проблема связана с чем-то… чем-то, но чистая установка в основном стандартной конфигурации решает проблему. В любом случае, это явно не :discourse: :bug:. Я изменил категорию.

Другое возможное объяснение, которое тоже кажется натянутым, заключается в том, что somehow что-то не так с моделью UserSecondFactor, так как я выполнил UserSecondFactor.all.destroy_all; UserSecurityKey.all.destroy_all; на моем тестовом сервере, поскольку у него было другое доменное имя. Также я использовал Google Authenticator вместо своего YubiKey.