187 lines
5.7 KiB
Elixir
187 lines
5.7 KiB
Elixir
defmodule ToweropsWeb.Api.V1.AgentsControllerTest do
|
|
use ToweropsWeb.ConnCase, async: true
|
|
|
|
import Towerops.AccountsFixtures
|
|
import Towerops.AgentsFixtures
|
|
import Towerops.OrganizationsFixtures
|
|
|
|
alias Towerops.ApiTokens
|
|
|
|
setup do
|
|
user = user_fixture()
|
|
organization = organization_fixture(user.id)
|
|
|
|
{:ok, {_token, raw_token}} =
|
|
ApiTokens.create_api_token(%{
|
|
organization_id: organization.id,
|
|
user_id: user.id,
|
|
name: "Test Token"
|
|
})
|
|
|
|
conn =
|
|
build_conn()
|
|
|> put_req_header("authorization", "Bearer #{raw_token}")
|
|
|> put_req_header("accept", "application/json")
|
|
|
|
%{
|
|
conn: conn,
|
|
user: user,
|
|
organization: organization
|
|
}
|
|
end
|
|
|
|
describe "index/2" do
|
|
test "lists agents for the authenticated organization", %{
|
|
conn: conn,
|
|
organization: organization
|
|
} do
|
|
{:ok, agent1, _raw1} = agent_token_fixture(organization.id, "Agent Alpha")
|
|
{:ok, agent2, _raw2} = agent_token_fixture(organization.id, "Agent Beta")
|
|
|
|
conn = get(conn, ~p"/api/v1/agents")
|
|
|
|
assert %{"data" => agents} = json_response(conn, 200)
|
|
assert length(agents) == 2
|
|
|
|
agent_ids = Enum.map(agents, & &1["id"])
|
|
assert agent1.id in agent_ids
|
|
assert agent2.id in agent_ids
|
|
|
|
agent_json = List.first(agents)
|
|
assert Map.has_key?(agent_json, "id")
|
|
assert Map.has_key?(agent_json, "name")
|
|
assert Map.has_key?(agent_json, "enabled")
|
|
assert Map.has_key?(agent_json, "last_seen_at")
|
|
assert Map.has_key?(agent_json, "last_ip")
|
|
assert Map.has_key?(agent_json, "metadata")
|
|
assert Map.has_key?(agent_json, "inserted_at")
|
|
end
|
|
|
|
test "returns empty list when organization has no agents", %{conn: conn} do
|
|
conn = get(conn, ~p"/api/v1/agents")
|
|
|
|
assert %{"data" => []} = json_response(conn, 200)
|
|
end
|
|
|
|
test "does not return agents from other organizations", %{conn: conn} do
|
|
other_user = user_fixture()
|
|
other_org = organization_fixture(other_user.id)
|
|
|
|
{:ok, _other_agent, _raw} = agent_token_fixture(other_org.id)
|
|
|
|
conn = get(conn, ~p"/api/v1/agents")
|
|
|
|
assert %{"data" => agents} = json_response(conn, 200)
|
|
assert Enum.empty?(agents)
|
|
end
|
|
end
|
|
|
|
describe "create/2" do
|
|
test "creates agent with valid name and returns token", %{
|
|
conn: conn,
|
|
organization: organization
|
|
} do
|
|
conn = post(conn, ~p"/api/v1/agents", %{"name" => "New Agent"})
|
|
|
|
assert %{"data" => agent} = json_response(conn, 201)
|
|
assert agent["name"] == "New Agent"
|
|
assert is_binary(agent["id"]) and byte_size(agent["id"]) > 0
|
|
assert is_binary(agent["token"]) and byte_size(agent["token"]) > 0
|
|
assert agent["enabled"] == true
|
|
|
|
# Verify the agent was created in the correct organization
|
|
created = Towerops.Agents.get_agent_token!(agent["id"])
|
|
assert created.organization_id == organization.id
|
|
end
|
|
|
|
test "returns 400 without name parameter", %{conn: conn} do
|
|
conn = post(conn, ~p"/api/v1/agents", %{})
|
|
|
|
assert %{"error" => "Missing 'name' parameter"} = json_response(conn, 400)
|
|
end
|
|
end
|
|
|
|
describe "show/2" do
|
|
test "returns agent with device_count", %{conn: conn, organization: organization} do
|
|
{:ok, agent, _raw} = agent_token_fixture(organization.id, "Show Agent")
|
|
|
|
conn = get(conn, ~p"/api/v1/agents/#{agent.id}")
|
|
|
|
assert %{"data" => data} = json_response(conn, 200)
|
|
assert data["id"] == agent.id
|
|
assert data["name"] == "Show Agent"
|
|
assert Map.has_key?(data, "device_count")
|
|
assert data["device_count"] == 0
|
|
end
|
|
|
|
test "returns 404 for non-existent agent", %{conn: conn} do
|
|
conn = get(conn, ~p"/api/v1/agents/#{Ecto.UUID.generate()}")
|
|
|
|
assert %{"error" => "Agent not found"} = json_response(conn, 404)
|
|
end
|
|
|
|
test "returns 404 for agent in another organization", %{conn: conn} do
|
|
other_user = user_fixture()
|
|
other_org = organization_fixture(other_user.id)
|
|
|
|
{:ok, other_agent, _raw} = agent_token_fixture(other_org.id)
|
|
|
|
conn = get(conn, ~p"/api/v1/agents/#{other_agent.id}")
|
|
|
|
assert %{"error" => "Agent not found"} = json_response(conn, 404)
|
|
end
|
|
end
|
|
|
|
describe "delete/2" do
|
|
test "removes agent and returns 204", %{conn: conn, organization: organization} do
|
|
{:ok, agent, _raw} = agent_token_fixture(organization.id)
|
|
|
|
conn = delete(conn, ~p"/api/v1/agents/#{agent.id}")
|
|
|
|
assert response(conn, 204)
|
|
|
|
# Verify the agent was deleted
|
|
assert_raise Ecto.NoResultsError, fn ->
|
|
Towerops.Agents.get_agent_token!(agent.id)
|
|
end
|
|
end
|
|
|
|
test "returns 404 for non-existent agent", %{conn: conn} do
|
|
conn = delete(conn, ~p"/api/v1/agents/#{Ecto.UUID.generate()}")
|
|
|
|
assert %{"error" => "Agent not found"} = json_response(conn, 404)
|
|
end
|
|
|
|
test "returns 404 for agent in another organization", %{conn: conn} do
|
|
other_user = user_fixture()
|
|
other_org = organization_fixture(other_user.id)
|
|
|
|
{:ok, other_agent, _raw} = agent_token_fixture(other_org.id)
|
|
|
|
conn = delete(conn, ~p"/api/v1/agents/#{other_agent.id}")
|
|
|
|
assert %{"error" => "Agent not found"} = json_response(conn, 404)
|
|
end
|
|
end
|
|
|
|
describe "authentication" do
|
|
test "returns 401 without authorization header" do
|
|
conn =
|
|
build_conn()
|
|
|> put_req_header("accept", "application/json")
|
|
|> get(~p"/api/v1/agents")
|
|
|
|
assert %{"error" => _message} = json_response(conn, 401)
|
|
end
|
|
|
|
test "returns 401 with invalid token" do
|
|
conn =
|
|
build_conn()
|
|
|> put_req_header("authorization", "Bearer towerops_invalid_token")
|
|
|> put_req_header("accept", "application/json")
|
|
|> get(~p"/api/v1/agents")
|
|
|
|
assert %{"error" => _message} = json_response(conn, 401)
|
|
end
|
|
end
|
|
end
|