""" Automated unit/integration tests to verify Case Access Control. Ensures that an investigator can only access and edit their own cases (or guest sessions). """ from fastapi.testclient import TestClient from server import app # We use headers with "Bearer guest:" to simulate active investigator sessions ALICE_HEADERS = {"Authorization": "Bearer guest:user_alice"} BOB_HEADERS = {"Authorization": "Bearer guest:user_bob"} def test_row_level_access_control(): client = TestClient(app) # 1. Create a case as Alice create_resp = client.post( "/api/v1/cases", json={ "title": "Alice's Investigation", "description": "Cyclic round tripping suspected.", "priority": "HIGH", "primary_subject_account_id": "ACC_11111", "subject_account_ids": ["ACC_11111"], "tags": ["suspicious", "ml_flagged"] }, headers=ALICE_HEADERS ) assert create_resp.status_code == 201, create_resp.text case = create_resp.json() case_id = case["id"] assert case["investigator_id"] == "user_alice" # 2. Alice can read her own case details get_resp = client.get(f"/api/v1/cases/{case_id}", headers=ALICE_HEADERS) assert get_resp.status_code == 200 assert get_resp.json()["id"] == case_id # 3. Bob attempts to read Alice's case -> 403 Forbidden get_resp_bob = client.get(f"/api/v1/cases/{case_id}", headers=BOB_HEADERS) assert get_resp_bob.status_code == 403, get_resp_bob.text assert "access" in get_resp_bob.json()["detail"].lower() # 4. Bob attempts to update Alice's case -> 403 Forbidden patch_resp_bob = client.patch( f"/api/v1/cases/{case_id}", json={"title": "Bob's Malicious Edit"}, headers=BOB_HEADERS ) assert patch_resp_bob.status_code == 403 # 5. Bob attempts to list cases -> Alice's case is NOT returned in Bob's list list_resp_bob = client.get("/api/v1/cases", headers=BOB_HEADERS) assert list_resp_bob.status_code == 200 items = list_resp_bob.json()["items"] for item in items: assert item["id"] != case_id # 6. Alice can successfully update her case patch_resp_alice = client.patch( f"/api/v1/cases/{case_id}", json={"title": "Alice's Authorized Edit"}, headers=ALICE_HEADERS ) assert patch_resp_alice.status_code == 200 assert patch_resp_alice.json()["title"] == "Alice's Authorized Edit" # 7. Alice can delete/soft-delete her case del_resp = client.delete(f"/api/v1/cases/{case_id}", headers=ALICE_HEADERS) assert del_resp.status_code == 204