infrasynth-backend-kit/tests/test_audit/test_views.py
2026-08-28 14:38:47 -05:00

130 lines
4.8 KiB
Python

import pytest
from rest_framework import status
from infrasynth.audit.models import APIInteractionLog, ModelChangeLog, SecurityEvent
@pytest.fixture
def change_log(db, user):
return ModelChangeLog.objects.create(
model_label="infrasynth_security.Role",
object_id="1",
action="create",
changes={"name": [None, "Test"]},
actor=user,
request_id="req-1",
)
@pytest.fixture
def api_log(db, user):
return APIInteractionLog.objects.create(
method="GET",
path="/api/features/",
status_code=200,
actor=user,
duration_ms=12,
request_id="req-2",
)
@pytest.fixture
def security_event(db, user):
return SecurityEvent.objects.create(
event_type="login_failed",
actor=user,
ip_address="127.0.0.1",
metadata={"reason": "bad_password"},
request_id="req-3",
)
class TestModelChangeLogEndpoints:
def test_list_changes(self, authenticated_client, change_log):
resp = authenticated_client.get("/api/audit/changes/", {"request_id": "req-1"})
assert resp.status_code == status.HTTP_200_OK
assert resp.json()["count"] == 1
assert resp.json()["results"][0]["action"] == "create"
def test_retrieve_change(self, authenticated_client, change_log):
resp = authenticated_client.get(f"/api/audit/changes/{change_log.pk}/")
assert resp.status_code == status.HTTP_200_OK
assert resp.json()["changes"] == {"name": [None, "Test"]}
def test_requires_auth(self, api_client, change_log):
resp = api_client.get("/api/audit/changes/")
assert resp.status_code == status.HTTP_401_UNAUTHORIZED
def test_list_does_not_allow_create(self, authenticated_client):
resp = authenticated_client.post("/api/audit/changes/", {"model_label": "x"}, format="json")
assert resp.status_code in (
status.HTTP_405_METHOD_NOT_ALLOWED,
status.HTTP_403_FORBIDDEN,
)
class TestAPIInteractionLogEndpoints:
def test_list_api_logs(self, authenticated_client, api_log):
resp = authenticated_client.get("/api/audit/api-logs/")
assert resp.status_code == status.HTTP_200_OK
assert resp.json()["count"] == 1
assert resp.json()["results"][0]["method"] == "GET"
def test_retrieve_api_log(self, authenticated_client, api_log):
resp = authenticated_client.get(f"/api/audit/api-logs/{api_log.pk}/")
assert resp.status_code == status.HTTP_200_OK
assert resp.json()["path"] == "/api/features/"
def test_requires_auth(self, api_client, api_log):
resp = api_client.get("/api/audit/api-logs/")
assert resp.status_code == status.HTTP_401_UNAUTHORIZED
class TestSecurityEventEndpoints:
def test_list_security_events(self, authenticated_client, security_event):
resp = authenticated_client.get("/api/audit/security-events/")
assert resp.status_code == status.HTTP_200_OK
assert resp.json()["count"] == 1
assert resp.json()["results"][0]["event_type"] == "login_failed"
def test_retrieve_security_event(self, authenticated_client, security_event):
resp = authenticated_client.get(f"/api/audit/security-events/{security_event.pk}/")
assert resp.status_code == status.HTTP_200_OK
assert resp.json()["metadata"] == {"reason": "bad_password"}
def test_requires_auth(self, api_client, security_event):
resp = api_client.get("/api/audit/security-events/")
assert resp.status_code == status.HTTP_401_UNAUTHORIZED
class TestFiltering:
def test_filter_by_model_label(self, authenticated_client, db):
ModelChangeLog.objects.create(
model_label="infrasynth_security.Role",
object_id="10",
action="create",
changes={},
request_id="x1",
)
ModelChangeLog.objects.create(
model_label="infrasynth_security.Grant",
object_id="99",
action="create",
changes={},
request_id="x2",
)
resp = authenticated_client.get("/api/audit/changes/", {"model_label": "infrasynth_security.Role"})
assert resp.json()["count"] == 1
def test_filter_by_action(self, authenticated_client, change_log):
ModelChangeLog.objects.create(
model_label="infrasynth_security.Role",
object_id="77",
action="delete",
changes={},
request_id="req-4",
)
resp = authenticated_client.get("/api/audit/changes/", {"action": "create"})
assert all(r["action"] == "create" for r in resp.json()["results"])
resp = authenticated_client.get("/api/audit/changes/", {"action": "delete"})
assert all(r["action"] == "delete" for r in resp.json()["results"])