""" Tests — Feature 2.3: RBAC Verifies that clinical endpoints enforce role requirements. """ import pytest HEART_PAYLOAD = { "Age": 55, "Sex": "M", "ChestPainType": "ATA", "RestingBP": 130, "Cholesterol": 250, "FastingBS": 0, "RestingECG": "Normal", "MaxHR": 150, "ExerciseAngina": "N", "Oldpeak": 1.5, "ST_Slope": "Up", } class TestUnauthenticated: async def test_predict_requires_auth(self, client, db_tables): resp = await client.post("/api/v4/heart_disease/predict", json=HEART_PAYLOAD) assert resp.status_code in (401, 403) async def test_explain_requires_auth(self, client, db_tables): resp = await client.post("/api/v4/heart_disease/explain", json=HEART_PAYLOAD) assert resp.status_code in (401, 403) async def test_counterfactuals_requires_auth(self, client, db_tables): resp = await client.post("/api/v4/heart_disease/counterfactuals", json=HEART_PAYLOAD) assert resp.status_code in (401, 403) async def test_admin_audit_logs_requires_auth(self, client, db_tables): resp = await client.get("/admin/audit-logs") assert resp.status_code in (401, 403) async def test_patients_requires_auth(self, client, db_tables): resp = await client.get("/api/v4/patients/") assert resp.status_code in (401, 403) class TestViewerRole: """Viewer role must NOT access clinical or admin routes.""" async def test_viewer_cannot_predict(self, client, viewer_token): resp = await client.post( "/api/v4/heart_disease/predict", json=HEART_PAYLOAD, headers={"Authorization": f"Bearer {viewer_token}"}, ) assert resp.status_code == 403 async def test_viewer_cannot_explain(self, client, viewer_token): resp = await client.post( "/api/v4/heart_disease/explain", json=HEART_PAYLOAD, headers={"Authorization": f"Bearer {viewer_token}"}, ) assert resp.status_code == 403 async def test_viewer_cannot_access_admin(self, client, viewer_token): resp = await client.get( "/admin/audit-logs", headers={"Authorization": f"Bearer {viewer_token}"}, ) assert resp.status_code == 403 class TestDoctorRole: """Doctor role should have clinical access but NOT admin access.""" async def test_doctor_can_predict(self, client, doctor_token): resp = await client.post( "/api/v4/heart_disease/predict", json=HEART_PAYLOAD, headers={"Authorization": f"Bearer {doctor_token}"}, ) assert resp.status_code == 200 async def test_doctor_can_explain(self, client, doctor_token): resp = await client.post( "/api/v4/heart_disease/explain", json=HEART_PAYLOAD, headers={"Authorization": f"Bearer {doctor_token}"}, ) assert resp.status_code == 200 async def test_doctor_cannot_access_admin(self, client, doctor_token): resp = await client.get( "/admin/audit-logs", headers={"Authorization": f"Bearer {doctor_token}"}, ) assert resp.status_code == 403 async def test_doctor_cannot_flush_cache(self, client, doctor_token): resp = await client.post( "/admin/cache/flush", headers={"Authorization": f"Bearer {doctor_token}"}, ) assert resp.status_code == 403 class TestAdminRole: """super_admin should have access to everything.""" async def test_admin_can_predict(self, client, admin_token): resp = await client.post( "/api/v4/heart_disease/predict", json=HEART_PAYLOAD, headers={"Authorization": f"Bearer {admin_token}"}, ) assert resp.status_code == 200 async def test_admin_can_access_audit_logs(self, client, admin_token): resp = await client.get( "/admin/audit-logs", headers={"Authorization": f"Bearer {admin_token}"}, ) assert resp.status_code == 200 async def test_admin_can_flush_cache(self, client, admin_token): resp = await client.post( "/admin/cache/flush", headers={"Authorization": f"Bearer {admin_token}"}, ) assert resp.status_code == 200