towerops/lib/towerops_web/controllers/admin_controller.ex
2026-06-14 08:27:57 -05:00

56 lines
1.6 KiB
Elixir

defmodule ToweropsWeb.AdminController do
@moduledoc """
Controller for admin operations including user impersonation.
"""
use ToweropsWeb, :controller
import Ecto.Query
alias ToweropsWeb.UserAuth
require Logger
@doc """
Start impersonating a user.
"""
def start_impersonate(conn, %{"user_id" => user_id}) do
UserAuth.start_impersonation(conn, user_id)
end
@doc """
Stop impersonating and return to superuser.
"""
def stop_impersonate(conn, _params) do
UserAuth.stop_impersonation(conn)
end
@doc """
Emergency-only flush of Oban jobs by state.
Directly deletes jobs in the given state(s). This bypasses Oban's
cancellation hooks and telemetry — only use when a queue is poisoned
and normal draining fails. All flushes are audit logged.
POST /admin/oban/flush?states=scheduled,retryable
"""
def flush_oban(conn, %{"states" => states_param}) do
valid_states = ~w(scheduled retryable available)
requested = states_param |> String.split(",") |> Enum.map(&String.trim/1)
states = Enum.filter(requested, &(&1 in valid_states))
if states == [] do
conn |> put_status(400) |> json(%{error: "No valid states. Use: scheduled, retryable, available"})
else
{count, _} =
Oban.Job
|> where([j], j.state in ^states)
|> Towerops.Repo.delete_all()
user = conn.assigns.current_scope.user
Logger.warning("OBAN_FLUSH: user=#{user.email} (#{user.id}) deleted #{count} jobs in states #{inspect(states)}")
json(conn, %{ok: true, deleted: count, states: states})
end
end
end