Qualys: cancel button for ongoing refresh

This commit is contained in:
Pierre & Lumière 2026-04-14 16:12:44 +02:00
parent 69aeb0e77a
commit 67287b8256
3 changed files with 43 additions and 0 deletions

View File

@ -539,6 +539,21 @@ def qualys_agents_refresh(request: Request, db=Depends(get_db)):
return JSONResponse({"ok": False, "msg": str(e)[:200]}, status_code=500)
@router.post("/qualys/agents/cancel")
def qualys_agents_cancel(request: Request, db=Depends(get_db)):
from fastapi.responses import JSONResponse
user = get_current_user(request)
if not user:
return JSONResponse({"ok": False}, status_code=401)
perms = get_user_perms(db, user)
if not can_edit(perms, "qualys"):
return JSONResponse({"ok": False}, status_code=403)
from ..services.qualys_service import cancel_refresh, is_refresh_running
if not is_refresh_running():
return JSONResponse({"ok": False, "msg": "Aucun refresh en cours"}, status_code=404)
return JSONResponse(cancel_refresh())
@router.get("/qualys/agents/export-no-agent")
async def export_no_agent_csv(request: Request, db=Depends(get_db)):
user = get_current_user(request)

View File

@ -5,6 +5,7 @@ import threading
_refresh_lock = threading.Lock()
_refresh_running = False
_refresh_cancel = threading.Event()
import urllib3
from sqlalchemy import text
from .secrets_service import get_secret
@ -544,6 +545,7 @@ def refresh_all_agents(db):
if not _refresh_lock.acquire(blocking=False):
return {"ok": False, "msg": "Une synchronisation Qualys est déjà en cours", "busy": True}
_refresh_running = True
_refresh_cancel.clear()
try:
return _refresh_all_agents_impl(db)
finally:
@ -576,6 +578,11 @@ def _refresh_all_agents_impl(db):
pass
while stats["pages"] < max_pages:
if _refresh_cancel.is_set():
stats["ok"] = True
stats["cancelled"] = True
stats["msg"] = f"Annulé après {stats['pages']} pages: {stats['created']} créés, {stats['updated']} mis à jour"
return stats
stats["pages"] += 1
criteria = [{"field": "tagName", "operator": "CONTAINS", "value": "server"}]
if last_id:
@ -693,3 +700,13 @@ def _refresh_all_agents_impl(db):
stats["ok"] = True
stats["msg"] = f"{stats['created']} créés, {stats['updated']} mis à jour ({stats['pages']} pages, {stats['errors']} erreurs)"
return stats
def cancel_refresh():
"""Demande l'annulation du refresh Qualys en cours"""
_refresh_cancel.set()
return {"ok": True, "msg": "Annulation demandée"}
def is_refresh_running():
return _refresh_running

View File

@ -24,6 +24,7 @@
<div class="text-cyber-accent font-bold text-sm" id="refresh-title">Rafraîchissement en cours...</div>
<div class="text-gray-400 text-xs mt-2" id="refresh-detail">Synchronisation des agents depuis l'API Qualys</div>
<div class="text-gray-500 text-xs mt-3" id="refresh-timer">0s</div>
<button id="btn-cancel" class="btn-secondary px-3 py-1 text-xs mt-4" onclick="cancelRefresh()">Annuler</button>
</div>
</div>
<style>@keyframes spin{to{transform:rotate(360deg)}}</style>
@ -32,6 +33,16 @@
<div id="refresh-msg" style="display:none;padding:8px 16px;border-radius:6px;margin-bottom:12px;font-size:0.85rem"></div>
<script>
function cancelRefresh() {
fetch('/qualys/agents/cancel', {method: 'POST'})
.then(function(r){ return r.json(); })
.then(function(d){
var title = document.getElementById('refresh-title');
if (title) title.textContent = 'Annulation en cours...';
});
}
function refreshAgents() {
var btn = document.getElementById('btn-refresh');
var overlay = document.getElementById('refresh-overlay');