test: GaiiaWebhookController auth/signature error branches

This commit is contained in:
Graham McIntire 2026-05-09 13:07:41 -05:00
parent 6481801447
commit 7eb63a0176

View file

@ -161,5 +161,82 @@ defmodule ToweropsWeb.Api.V1.GaiiaWebhookControllerTest do
assert json_response(conn, 400)["error"] =~ "Missing"
end
test "returns 404 when no Gaiia integration is configured for org", %{conn: conn} do
orphan_user = user_fixture()
orphan_org = organization_fixture(orphan_user.id)
# No integration created for orphan_org
conn = post_webhook(conn, orphan_org.id, "test.event", %{})
assert json_response(conn, 404)["error"] =~ "not found"
end
test "returns 403 when integration exists but webhook_secret is missing",
%{conn: conn} do
user = user_fixture()
org = organization_fixture(user.id)
{:ok, _integration} =
Integrations.create_integration(org.id, %{
provider: "gaiia",
enabled: true,
credentials: %{"api_key" => "key"}
})
body = Jason.encode!(%{"event" => "test", "data" => %{}})
conn =
conn
|> put_req_header("content-type", "application/json")
|> post(~p"/api/v1/webhooks/gaiia/#{org.id}", body)
assert json_response(conn, 403)["error"] =~ "Webhook secret not configured"
end
test "returns 401 when signature timestamp has expired", %{conn: conn, org: org} do
body = Jason.encode!(%{"event" => "test", "data" => %{}})
# 1 hour ago — well past the 5-minute window
timestamp = DateTime.to_unix(DateTime.utc_now()) - 3600
signed_payload = "#{timestamp}.#{body}"
signature =
:hmac
|> :crypto.mac(:sha256, @webhook_secret, signed_payload)
|> Base.encode16(case: :lower)
conn =
conn
|> put_req_header("content-type", "application/json")
|> put_req_header("x-gaiia-webhook-signature", "t=#{timestamp},v1=#{signature}")
|> post(~p"/api/v1/webhooks/gaiia/#{org.id}", body)
assert json_response(conn, 401)["error"] =~ "Invalid webhook signature"
end
test "returns 401 when signature header is malformed (no v1)",
%{conn: conn, org: org} do
body = Jason.encode!(%{"event" => "test", "data" => %{}})
conn =
conn
|> put_req_header("content-type", "application/json")
|> put_req_header("x-gaiia-webhook-signature", "garbage-no-pair")
|> post(~p"/api/v1/webhooks/gaiia/#{org.id}", body)
assert json_response(conn, 401)["error"] =~ "Invalid webhook signature"
end
test "returns 401 when signature timestamp is unparseable",
%{conn: conn, org: org} do
body = Jason.encode!(%{"event" => "test", "data" => %{}})
conn =
conn
|> put_req_header("content-type", "application/json")
|> put_req_header("x-gaiia-webhook-signature", "t=notanumber,v1=deadbeef")
|> post(~p"/api/v1/webhooks/gaiia/#{org.id}", body)
assert json_response(conn, 401)["error"] =~ "Invalid webhook signature"
end
end
end