import pytest from django.db import transaction from portal.audit import services from portal.audit.models import AuditEntry @pytest.mark.django_db(transaction=True) def test_record_rolls_back_with_the_change(): with pytest.raises(RuntimeError), transaction.atomic(): services.record("Alice", "profile.update", target="alice", ip="10.0.0.1") raise RuntimeError("change failed") assert AuditEntry.objects.count() == 0 @pytest.mark.django_db(transaction=True) def test_record_persists_on_commit_and_lowercases_actor(): with transaction.atomic(): services.record("Alice", "profile.update", target="alice", ip="10.0.0.1", detail={"a": 1}) entry = AuditEntry.objects.get() assert (entry.actor, entry.action, entry.ip, entry.detail) == ( "alice", "profile.update", "10.0.0.1", {"a": 1}, ) @pytest.mark.django_db(transaction=True) def test_record_outside_transaction_raises_and_writes_nothing(): with pytest.raises(services.AuditOutsideTransaction): services.record("alice", "x") assert AuditEntry.objects.count() == 0 @pytest.mark.django_db(transaction=True) @pytest.mark.parametrize("key", ["password", "New_Token", "client_secret", "pwd", "oldPassword"]) def test_secret_keys_are_refused(key): with pytest.raises(ValueError), transaction.atomic(): services.record("alice", "x", detail={"ok": 1, "nested": {key: "v"}}) with pytest.raises(ValueError): services.record_failure("alice", "x", detail={key: "v"}) assert AuditEntry.objects.count() == 0 @pytest.mark.django_db(transaction=True) def test_record_failure_inside_transaction_raises_and_writes_nothing(): with pytest.raises(services.AuditInsideTransaction), transaction.atomic(): services.record_failure("alice", "x.failed") assert AuditEntry.objects.count() == 0 @pytest.mark.django_db(transaction=True) def test_record_failure_persists_after_rollback(): with pytest.raises(RuntimeError), transaction.atomic(): services.record("alice", "x") raise RuntimeError("boom") services.record_failure("alice", "x.failed", detail={"reason": "ad"}) assert list(AuditEntry.objects.values_list("action", flat=True)) == ["x.failed"]