fix(web): gate /docs, /redoc, /openapi.json behind login
FastAPI auto-registers these with no auth of its own -- every other data route is individually wrapped in Depends(require_user), but these three are wired up internally by the FastAPI() constructor and were never covered by that. Confirmed live: all three returned 200 with zero session, handing anyone who could reach the port a full map of every route -- VM remove, cache purge, template delete, service control included -- without logging in. Disabled FastAPI's built-in docs_url/redoc_url/openapi_url and re-added all three as ordinary routes behind the same require_user dependency every other route uses. Verified against the live deployment: all three now 303 to /login instead of 200.
This commit is contained in:
@@ -94,6 +94,30 @@ def test_healthz_returns_ok(tmp_path: Path) -> None:
|
||||
assert resp.json() == {"status": "ok"}
|
||||
|
||||
|
||||
# ── /docs, /redoc, /openapi.json ────────────────────────────────────────
|
||||
# Gated behind require_user like every other data route (test_web_auth.py's
|
||||
# _PROTECTED_ROUTES proves the redirect-when-unauthenticated half); this
|
||||
# proves the positive path still works once past that gate.
|
||||
|
||||
|
||||
def test_openapi_json_lists_a_mutating_route(tmp_path: Path) -> None:
|
||||
app = create_app(_make_config(tmp_path))
|
||||
client = TestClient(app)
|
||||
|
||||
resp = client.get("/openapi.json")
|
||||
|
||||
assert resp.status_code == 200
|
||||
assert "/vms/{vmx_id}/remove" in resp.json()["paths"]
|
||||
|
||||
|
||||
def test_docs_and_redoc_render(tmp_path: Path) -> None:
|
||||
app = create_app(_make_config(tmp_path))
|
||||
client = TestClient(app)
|
||||
|
||||
assert client.get("/docs").status_code == 200
|
||||
assert client.get("/redoc").status_code == 200
|
||||
|
||||
|
||||
# ── / (dashboard) ────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user