feat(qualys/dashboard): is_running base sur DB (multi-worker safe) + bouton Annuler

This commit is contained in:
Pierre & Lumière 2026-04-25 00:05:49 +00:00
parent 17f508c1d1
commit daf87891a7
2 changed files with 31 additions and 4 deletions

View File

@ -1186,16 +1186,23 @@ async def qualys_dashboard(request: Request, db=Depends(get_db)):
# TODO: ajouter perm specifique 'qualys_dashboard_view' (admin + DSI) # TODO: ajouter perm specifique 'qualys_dashboard_view' (admin + DSI)
if not can_view(perms, "qualys"): if not can_view(perms, "qualys"):
return RedirectResponse(url="/dashboard") return RedirectResponse(url="/dashboard")
from app.services.qualys_service import load_vuln_dashboard, is_dashboard_running from app.services.qualys_service import load_vuln_dashboard
data = load_vuln_dashboard(db) data = load_vuln_dashboard(db)
# Check si un run est en cours via DB (multi-worker safe)
pending = db.execute(text("""SELECT id, run_at FROM qualys_vuln_snapshot_run
WHERE status='pending' AND run_at > now() - interval '15 minutes'
ORDER BY run_at DESC LIMIT 1""")).fetchone()
is_running = pending is not None
env_set = sorted({d["name"] for d in data["env"]}) env_set = sorted({d["name"] for d in data["env"]})
pos_set = sorted({d["name"] for d in data["pos"]}) pos_set = sorted({d["name"] for d in data["pos"]})
matrix = {(c["name"], c["name2"]): c for c in data["env_pos"]} matrix = {(c["name"], c["name2"]): c for c in data["env_pos"]}
ctx = base_context(request, db, user) ctx = base_context(request, db, user)
ctx.update({"data": data, "env_list": env_set, "pos_list": pos_set, ctx.update({"data": data, "env_list": env_set, "pos_list": pos_set,
"matrix": matrix, "is_running": is_dashboard_running()}) "matrix": matrix, "is_running": is_running,
"running_since": pending.run_at if pending else None})
return templates.TemplateResponse("qualys_dashboard.html", ctx) return templates.TemplateResponse("qualys_dashboard.html", ctx)
@ -1207,8 +1214,10 @@ async def qualys_dashboard_refresh(request: Request, db=Depends(get_db)):
perms = get_user_perms(db, user) perms = get_user_perms(db, user)
if not can_edit(perms, "qualys"): if not can_edit(perms, "qualys"):
return RedirectResponse(url="/qualys/dashboard") return RedirectResponse(url="/qualys/dashboard")
from app.services.qualys_service import compute_vuln_dashboard, is_dashboard_running from app.services.qualys_service import compute_vuln_dashboard
if is_dashboard_running(): pending = db.execute(text("""SELECT id FROM qualys_vuln_snapshot_run
WHERE status='pending' AND run_at > now() - interval '15 minutes' LIMIT 1""")).fetchone()
if pending:
return RedirectResponse(url="/qualys/dashboard?msg=already_running", status_code=303) return RedirectResponse(url="/qualys/dashboard?msg=already_running", status_code=303)
import threading import threading
def _runner(): def _runner():
@ -1222,6 +1231,21 @@ async def qualys_dashboard_refresh(request: Request, db=Depends(get_db)):
return RedirectResponse(url="/qualys/dashboard?msg=refresh_started", status_code=303) return RedirectResponse(url="/qualys/dashboard?msg=refresh_started", status_code=303)
@router.post("/qualys/dashboard/cancel")
async def qualys_dashboard_cancel(request: Request, db=Depends(get_db)):
user = get_current_user(request)
if not user:
return RedirectResponse(url="/login")
perms = get_user_perms(db, user)
if not can_edit(perms, "qualys"):
return RedirectResponse(url="/qualys/dashboard")
db.execute(text("""UPDATE qualys_vuln_snapshot_run
SET status='cancelled', msg='annule par utilisateur'
WHERE status='pending'"""))
db.commit()
return RedirectResponse(url="/qualys/dashboard?msg=cancelled", status_code=303)
@router.get("/qualys/dashboard/history", response_class=HTMLResponse) @router.get("/qualys/dashboard/history", response_class=HTMLResponse)
async def qualys_dashboard_history(request: Request, db=Depends(get_db), async def qualys_dashboard_history(request: Request, db=Depends(get_db),
period: str = "day", days: int = 30, period: str = "day", days: int = 30,

View File

@ -15,6 +15,9 @@
<span id="elapsed" class="font-mono text-cyber-accent ml-2"></span> <span id="elapsed" class="font-mono text-cyber-accent ml-2"></span>
</div> </div>
</div> </div>
<form method="POST" action="/qualys/dashboard/cancel" style="flex-shrink:0">
<button class="btn-sm bg-red-900/40 text-red-300 hover:bg-red-900/60" type="submit">Annuler</button>
</form>
</div> </div>
<script> <script>
setTimeout(function() { window.location.href = '/qualys/dashboard'; }, 15000); setTimeout(function() { window.location.href = '/qualys/dashboard'; }, 15000);