"""Routes du dashboard admin -- authentification requise.""" import logging from datetime import datetime from pathlib import Path from fastapi import APIRouter, Request, Form from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates logger = logging.getLogger(__name__) router = APIRouter() _templates = Jinja2Templates( directory=Path(__file__).parent.parent.parent / "frontend" / "templates" ) def _is_auth(request: Request) -> bool: return request.session.get("authenticated") is True def _require_auth(request: Request): if not _is_auth(request): return RedirectResponse(url="/admin/login", status_code=302) return None # -- Auth ---------------------------------------------------------------------- @router.get("/admin/login", response_class=HTMLResponse) async def login_page(request: Request): if _is_auth(request): return RedirectResponse(url="/admin", status_code=302) return _templates.TemplateResponse(request, "admin/login.html", {"error": None}) @router.post("/admin/login") async def login(request: Request, password: str = Form(...)): cfg = request.app.state.config if password == cfg.app.admin_password: request.session["authenticated"] = True return RedirectResponse(url="/admin", status_code=302) return _templates.TemplateResponse( request, "admin/login.html", {"error": "Mot de passe incorrect"}, ) @router.get("/admin/logout") async def logout(request: Request): request.session.clear() return RedirectResponse(url="/admin/login", status_code=302) # -- Pages admin --------------------------------------------------------------- @router.get("/admin", response_class=HTMLResponse) async def admin_dashboard(request: Request): redirect = _require_auth(request) if redirect: return redirect sys_svc = request.app.state.system_service cfg = request.app.state.config led = request.app.state.led_service btn = request.app.state.button_service stats = sys_svc.get_stats() services = sys_svc.get_services_status() return _templates.TemplateResponse(request, "admin/dashboard.html", { "config": cfg, "stats": stats, "services": services, "led_effect": led.current_effect, "relay_state": btn.relay_state if btn else True, "print_mode": cfg.print.mode, }) @router.get("/admin/gallery", response_class=HTMLResponse) async def admin_gallery(request: Request): redirect = _require_auth(request) if redirect: return redirect cfg = request.app.state.config return _templates.TemplateResponse(request, "admin/gallery.html", { "config": cfg, }) @router.get("/admin/actions", response_class=HTMLResponse) async def admin_actions(request: Request): redirect = _require_auth(request) if redirect: return redirect cfg = request.app.state.config return _templates.TemplateResponse(request, "admin/actions.html", {"config": cfg}) @router.get("/admin/settings", response_class=HTMLResponse) async def admin_settings(request: Request): redirect = _require_auth(request) if redirect: return redirect cfg = request.app.state.config return _templates.TemplateResponse(request, "admin/settings.html", { "config": cfg, "button": cfg.button, }) @router.get("/admin/events", response_class=HTMLResponse) async def admin_events(request: Request): redirect = _require_auth(request) if redirect: return redirect cfg = request.app.state.config return _templates.TemplateResponse(request, "admin/events.html", {"config": cfg}) @router.get("/admin/print", response_class=HTMLResponse) async def admin_print(request: Request): redirect = _require_auth(request) if redirect: return redirect printer_svc = request.app.state.printer_service cfg = request.app.state.config queue = await printer_svc.get_queue() printers = await printer_svc.get_printers_status() # Formate les dates pour le template Jinja2 for q in queue: ts = q.get("requested_at") q["requested_at_str"] = ( datetime.fromtimestamp(ts).strftime("%d/%m %H:%M") if ts else "—" ) return _templates.TemplateResponse(request, "admin/print.html", { "config": cfg, "queue": queue, "printers": printers, })