defmodule ToweropsWeb.Api.V1.AgentsController do @moduledoc "API controller for agent tokens." use ToweropsWeb, :controller alias Towerops.Agents def index(conn, _params) do organization_id = conn.assigns.current_organization_id agents = organization_id |> Agents.list_organization_agent_tokens() |> Enum.map(&format_agent/1) json(conn, %{data: agents}) end def create(conn, %{"name" => name}) do organization_id = conn.assigns.current_organization_id case Agents.create_agent_token(organization_id, name) do {:ok, agent_token, raw_token} -> conn |> put_status(:created) |> json(%{data: Map.put(format_agent(agent_token), :token, raw_token)}) {:error, changeset} -> conn |> put_status(:unprocessable_entity) |> json(%{errors: translate_errors(changeset)}) end end def create(conn, _params) do conn |> put_status(:bad_request) |> json(%{error: "Missing 'name' parameter"}) end def show(conn, %{"id" => id}) do organization_id = conn.assigns.current_organization_id agent = Agents.get_agent_token!(id) if agent.organization_id == organization_id do device_count = Agents.count_assigned_devices(id) json(conn, %{ data: format_agent(agent) |> Map.put(:device_count, device_count) }) else conn |> put_status(:not_found) |> json(%{error: "Agent not found"}) end rescue Ecto.NoResultsError -> conn |> put_status(:not_found) |> json(%{error: "Agent not found"}) end def delete(conn, %{"id" => id}) do organization_id = conn.assigns.current_organization_id agent = Agents.get_agent_token!(id) if agent.organization_id == organization_id do case Agents.delete_agent_token(id) do {:ok, _} -> conn |> put_status(:no_content) |> send_resp(204, "") {:error, _} -> conn |> put_status(:unprocessable_entity) |> json(%{error: "Could not delete agent"}) end else conn |> put_status(:not_found) |> json(%{error: "Agent not found"}) end rescue Ecto.NoResultsError -> conn |> put_status(:not_found) |> json(%{error: "Agent not found"}) end defp format_agent(agent) do %{ id: agent.id, name: agent.name, enabled: agent.enabled, last_seen_at: agent.last_seen_at, last_ip: agent.last_ip, metadata: agent.metadata, inserted_at: agent.inserted_at } end defp translate_errors(changeset) do Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} -> Regex.replace(~r"%{(\w+)}", msg, fn _, key -> if String.length(key) <= 50 and String.match?(key, ~r/^[a-z_]+$/) do opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() else key end end) end) end end