diff --git a/tests/unit/app/test_app_admin_routes.py b/tests/unit/app/test_app_admin_routes.py index e5edc5c..b5258b2 100644 --- a/tests/unit/app/test_app_admin_routes.py +++ b/tests/unit/app/test_app_admin_routes.py @@ -160,6 +160,59 @@ def test_access_flags_fallback(monkeypatch) -> None: assert resp.status_code == 200 assert resp.json()["flags"] == ["demo"] +def test_access_flags_fallback_when_keycloak_listing_fails(monkeypatch) -> None: + ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) + client = _client(monkeypatch, ctx) + monkeypatch.setattr(app_module.keycloak_admin, "ready", lambda: True) + monkeypatch.setattr( + app_module.keycloak_admin, + "list_group_names", + lambda **kwargs: (_ for _ in ()).throw(RuntimeError("keycloak unavailable")), + ) + monkeypatch.setattr( + app_module, + "settings", + dataclasses.replace(app_module.settings, allowed_flag_groups=["fallback"]), + ) + + resp = client.get( + "/api/admin/access/flags", + headers={"Authorization": "Bearer token"}, + ) + + assert resp.status_code == 200 + assert resp.json()["flags"] == ["fallback"] + +def test_cluster_state_admin_and_internal_routes(monkeypatch) -> None: + ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) + client = _client(monkeypatch, ctx) + monkeypatch.setattr(app_module.storage, "latest_cluster_state", lambda: {"nodes": [{"name": "titan-01"}]}) + + admin_resp = client.get( + "/api/admin/cluster/state", + headers={"Authorization": "Bearer token"}, + ) + internal_resp = client.get("/api/internal/cluster/state") + + assert admin_resp.status_code == 200 + assert admin_resp.json()["nodes"][0]["name"] == "titan-01" + assert internal_resp.status_code == 200 + assert internal_resp.json()["nodes"][0]["name"] == "titan-01" + +def test_cluster_state_routes_report_unavailable(monkeypatch) -> None: + ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) + client = _client(monkeypatch, ctx) + monkeypatch.setattr(app_module.storage, "latest_cluster_state", lambda: None) + + admin_resp = client.get( + "/api/admin/cluster/state", + headers={"Authorization": "Bearer token"}, + ) + internal_resp = client.get("/api/internal/cluster/state") + + assert admin_resp.status_code == 404 + assert internal_resp.status_code == 404 + def test_access_request_approve(monkeypatch) -> None: ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) client = _client(monkeypatch, ctx) @@ -284,3 +337,43 @@ def test_access_request_deny_bad_json(monkeypatch) -> None: data="{bad}", ) assert resp.status_code == 200 + +def test_retry_access_request_rejects_invalid_and_unready(monkeypatch) -> None: + ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) + client = _client(monkeypatch, ctx) + + blank_resp = client.post("/api/access/requests/%20/retry") + monkeypatch.setattr(app_module.keycloak_admin, "ready", lambda: False) + unready_resp = client.post("/api/access/requests/REQ1/retry") + + assert blank_resp.status_code == 400 + assert unready_resp.status_code == 503 + +def test_retry_access_request_reports_load_failure(monkeypatch) -> None: + ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) + client = _client(monkeypatch, ctx) + monkeypatch.setattr(app_module.keycloak_admin, "ready", lambda: True) + monkeypatch.setattr( + app_module.portal_db, + "fetchone", + lambda *args, **kwargs: (_ for _ in ()).throw(RuntimeError("database unavailable")), + ) + + resp = client.post("/api/access/requests/REQ1/retry") + + assert resp.status_code == 502 + +def test_retry_access_request_reports_update_failure(monkeypatch) -> None: + ctx = AuthContext(username="bstein", email="", groups=["admin"], claims={}) + client = _client(monkeypatch, ctx) + monkeypatch.setattr(app_module.keycloak_admin, "ready", lambda: True) + monkeypatch.setattr(app_module.portal_db, "fetchone", lambda *args, **kwargs: {"status": "approved"}) + monkeypatch.setattr( + app_module.portal_db, + "execute", + lambda *args, **kwargs: (_ for _ in ()).throw(RuntimeError("database unavailable")), + ) + + resp = client.post("/api/access/requests/REQ1/retry") + + assert resp.status_code == 502