defmodule ToweropsWeb.UserSudoController do @moduledoc """ Controller for sudo mode verification. Handles re-authentication for sensitive operations by requiring TOTP verification (no recovery codes allowed). """ use ToweropsWeb, :controller import ToweropsWeb.UserAuth, only: [require_authenticated_user: 2] alias Towerops.Accounts plug :require_authenticated_user def verify(conn, _params) do # Render the sudo verification form form = Phoenix.Component.to_form(%{}, as: "user") render(conn, :verify, form: form) end def create(conn, %{"user" => %{"totp_code" => totp_code}}) do user = conn.assigns.current_scope.user case Accounts.verify_totp_only(user, totp_code) do {:ok, _verified_user} -> # Grant sudo mode case Accounts.grant_sudo_mode(user) do {:ok, _updated_user} -> # Redirect to return_to path or default return_to = get_session(conn, :user_return_to) || ~p"/orgs" conn |> delete_session(:user_return_to) |> redirect(to: return_to) {:error, _changeset} -> # Shouldn't happen, but handle gracefully form = Phoenix.Component.to_form(%{"totp_code" => totp_code}, as: "user") conn |> put_flash(:error, "Failed to grant sudo mode. Please try again.") |> render(:verify, form: form) end {:error, :recovery_code_not_allowed} -> form = Phoenix.Component.to_form(%{"totp_code" => totp_code}, as: "user") conn |> put_flash( :error, "Recovery codes are not allowed for sudo mode verification. Please use your authenticator app." ) |> render(:verify, form: form) {:error, :invalid_code} -> form = Phoenix.Component.to_form(%{"totp_code" => totp_code}, as: "user") conn |> put_flash(:error, "Invalid authentication code. Please try again.") |> render(:verify, form: form) end end def create(conn, _params) do # Handle missing totp_code parameter form = Phoenix.Component.to_form(%{}, as: "user") render(conn, :verify, form: form) end end