fix(admin): /admin.html retombait sur la page principale (ROADMAP #71)
CI / lint (push) Successful in 54s
CI / security (push) Successful in 26s
CI / test (push) Successful in 50s
CI / build (push) Successful in 23s
CI / e2e (push) Successful in 6m2s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s

Le menu Admin redirigeait vers /admin.html mais aucune route backend ne le
servait : le catch-all SPA /{full_path:path} renvoyait index.html, d'où le
retour à la page principale.

- backend/main.py: route GET /admin.html (gate require_admin) déclarée avant
  le catch-all SPA + correction des imports JS /frontend/js -> /static/js
- frontend/admin.html: chemins d'assets alignés sur le mount /static
- tests/test_admin.py: 3 tests de régression (page servie admin, refus 401/403)
This commit is contained in:
2026-09-07 20:29:33 -04:00
parent 11406034c9
commit 88ab8db88d
3 changed files with 49 additions and 3 deletions
+34 -1
View File
@@ -302,4 +302,37 @@ class TestAdminStream:
def test_stream_requires_admin(self, admin_client):
resp = admin_client.get("/api/admin/stream")
assert resp.status_code in (401, 403)
assert resp.status_code in (401, 403)
# ═══════════════════════════════════════════════════════════════
# Admin dashboard PAGE (/admin.html)
# ═══════════════════════════════════════════════════════════════
class TestAdminPage:
"""Regression for ROADMAP #71 — Admin menu bounced back to the main page.
Root cause: /admin.html had no explicit route, so the SPA catch-all
``/{full_path:path}`` served index.html. Guard the fix.
"""
def test_page_served_as_admin(self, admin_client):
token = _login(admin_client)
resp = admin_client.get("/admin.html", headers=_bearer(token))
assert resp.status_code == 200
body = resp.text
# Real admin page markers (NOT the main SPA index.html)
assert "admin-main" in body or "ObsiGate — Admin" in body or "admin.js" in body
# The regression: index.html markers must be absent
assert "boot-splash" not in body
# Asset paths must point to the actual static mount (/static), not /frontend
assert "/static/js/admin.js" in body
assert "/frontend/js/admin.js" not in body
def test_page_requires_auth(self, admin_client):
resp = admin_client.get("/admin.html")
assert resp.status_code in (401, 403)
def test_page_requires_admin_role(self, admin_client):
token = _login(admin_client, username="normaluser", password="normal123")
resp = admin_client.get("/admin.html", headers=_bearer(token))
assert resp.status_code == 403