from fastapi import APIRouter, Request, Depends from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from sqlalchemy import text from ..dependencies import get_db, get_current_user from ..config import APP_NAME router = APIRouter() templates = Jinja2Templates(directory="app/templates") @router.get("/dashboard", response_class=HTMLResponse) async def dashboard(request: Request, db=Depends(get_db)): user = get_current_user(request) if not user: return RedirectResponse(url="/login") # Stats stats = {} stats["total_servers"] = db.execute(text("SELECT COUNT(*) FROM servers")).scalar() stats["patchable"] = db.execute(text("SELECT COUNT(*) FROM servers WHERE patch_os_owner='secops' AND etat='en_production'")).scalar() stats["linux"] = db.execute(text("SELECT COUNT(*) FROM servers WHERE os_family='linux'")).scalar() stats["windows"] = db.execute(text("SELECT COUNT(*) FROM servers WHERE os_family='windows'")).scalar() stats["decom"] = db.execute(text("SELECT COUNT(*) FROM servers WHERE etat='decommissionne'")).scalar() stats["eol"] = db.execute(text("SELECT COUNT(*) FROM servers WHERE licence_support='eol'")).scalar() stats["qualys_assets"] = db.execute(text("SELECT COUNT(*) FROM qualys_assets")).scalar() stats["qualys_tags"] = db.execute(text("SELECT COUNT(*) FROM qualys_tags")).scalar() # Par domaine domains = db.execute(text(""" SELECT d.name, d.code, COUNT(s.id) as total, COUNT(*) FILTER (WHERE s.etat='en_production') as actifs, COUNT(*) FILTER (WHERE s.os_family='linux') as linux, COUNT(*) FILTER (WHERE s.os_family='windows') as windows FROM servers s JOIN domain_environments de ON s.domain_env_id = de.id JOIN domains d ON de.domain_id = d.id GROUP BY d.name, d.code, d.display_order ORDER BY d.display_order """)).fetchall() # Par tier tiers = db.execute(text("SELECT tier, COUNT(*) FROM servers GROUP BY tier ORDER BY tier")).fetchall() return templates.TemplateResponse("dashboard.html", { "request": request, "user": user, "app_name": APP_NAME, "stats": stats, "domains": domains, "tiers": tiers })