- Extract Repo calls from LiveViews into Agents.get_agent_token_for_org/2 and Accounts.verify_new_totp_device/2 context functions - Remove Process dictionary usage for cookie consent; use explicit assigns - Reject url() references in status page custom CSS changeset - Add per-organization rate limit check alongside per-IP - Document Oban flush as emergency-only with audit logging - Gate /admin/headers behind dev_routes (debug endpoint)
56 lines
1.6 KiB
Elixir
56 lines
1.6 KiB
Elixir
defmodule ToweropsWeb.AdminController do
|
|
@moduledoc """
|
|
Controller for admin operations including user impersonation.
|
|
"""
|
|
use ToweropsWeb, :controller
|
|
|
|
alias ToweropsWeb.UserAuth
|
|
|
|
@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
|
|
import Ecto.Query
|
|
|
|
require Logger
|
|
|
|
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
|