defmodule ToweropsWeb.Api.V1.ProfilesController do @moduledoc """ API controller for managing device SNMP profiles. All endpoints require API token authentication. """ use ToweropsWeb, :controller require Logger @doc """ POST /api/v1/profiles/import Imports device profiles from JSON data exported via `mix export_profiles`. Request body: [ { "os": "epmp", "detection": { ... }, # YAML detection data "discovery": { ... } # YAML discovery data (optional) }, ... ] Response: { "success": 15, "failed": 2, "errors": [ {"os": "profile_name", "reason": "error message"} ] } Example: curl -X POST https://towerops.net/api/v1/profiles/import \\ -H "Authorization: Bearer YOUR_TOKEN" \\ -H "Content-Type: application/json" \\ -d @profiles.json """ def import_bulk(conn, %{"_json" => profiles}) when is_list(profiles) do Logger.info("Queueing import for #{length(profiles)} device profiles via API") # Generate unique job ID for tracking job_id = Ecto.UUID.generate() # Enqueue background job case Exq.enqueue(Exq, "maintenance", Towerops.Workers.ProfileImportWorker, [profiles, job_id]) do {:ok, _job_jid} -> Logger.info("Profile import job #{job_id} queued successfully") json(conn, %{ status: "queued", job_id: job_id, profile_count: length(profiles), message: "Import job queued successfully. #{length(profiles)} profiles will be imported in the background." }) {:error, reason} -> Logger.error("Failed to queue profile import: #{inspect(reason)}") conn |> put_status(:internal_server_error) |> json(%{error: "Failed to queue import job", reason: inspect(reason)}) end end def import_bulk(conn, _params) do conn |> put_status(:bad_request) |> json(%{error: "Invalid request format. Expected array of profile objects."}) end # Private functions (removed - logic moved to ProfileImportWorker) end