From 390a162cf4b1537d19dc1e4857d3b26c2b824f5e Mon Sep 17 00:00:00 2001 From: Khalid MOUTAOUAKIL Date: Mon, 6 Apr 2026 18:20:33 +0200 Subject: [PATCH] Fix: inclure status partial (serveurs Ayoub) dans toutes les requetes audit/patching/dashboard Co-Authored-By: Claude Opus 4.6 (1M context) --- app/routers/audit_full.py | 40 +++++++++++------------ app/routers/dashboard.py | 20 ++++++------ app/services/server_audit_full_service.py | 8 ++--- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/app/routers/audit_full.py b/app/routers/audit_full.py index 215552a..f92984e 100644 --- a/app/routers/audit_full.py +++ b/app/routers/audit_full.py @@ -64,8 +64,8 @@ async def audit_full_list(request: Request, db=Depends(get_db)): COUNT(*) FILTER (WHERE services::text ~* 'docker|podman' OR processes::text ~* 'dockerd|podman') as app_container, COUNT(*) FILTER (WHERE listen_ports::text ~* '"java"' OR processes::text ~* '\.jar') as app_java FROM server_audit_full - WHERE status = 'ok' - AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + WHERE status IN ('ok','partial') + AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) """)).fetchone() # Domaines + zones pour le filtre @@ -85,17 +85,17 @@ async def audit_full_list(request: Request, db=Depends(get_db)): elif filtre == "disk_critical": ids = {r.id for r in db.execute(text(""" SELECT saf.id FROM server_audit_full saf - WHERE saf.status = 'ok' AND EXISTS ( + WHERE saf.status IN ('ok','partial') AND EXISTS ( SELECT 1 FROM jsonb_array_elements(saf.disk_usage) d WHERE (d->>'pct')::int >= 90 - ) AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + ) AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) """)).fetchall()} audits = [a for a in audits if a.id in ids] elif filtre == "disk_warning": ids = {r.id for r in db.execute(text(""" SELECT saf.id FROM server_audit_full saf - WHERE saf.status = 'ok' AND EXISTS ( + WHERE saf.status IN ('ok','partial') AND EXISTS ( SELECT 1 FROM jsonb_array_elements(saf.disk_usage) d WHERE (d->>'pct')::int >= 80 - ) AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + ) AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) """)).fetchall()} audits = [a for a in audits if a.id in ids] elif filtre == "uptime": @@ -122,9 +122,9 @@ async def audit_full_list(request: Request, db=Depends(get_db)): if pattern: ids = {r.id for r in db.execute(text(""" SELECT id FROM server_audit_full - WHERE status = 'ok' + WHERE status IN ('ok','partial') AND (services::text ~* :pat OR listen_ports::text ~* :pat OR processes::text ~* :pat) - AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) """), {"pat": pattern}).fetchall()} audits = [a for a in audits if a.id in ids] @@ -248,8 +248,8 @@ async def audit_full_patching(request: Request, db=Depends(get_db)): f" COUNT(*) FILTER (WHERE {yr_count} >= 2) as twice," f" COUNT(*) FILTER (WHERE {yr_count} >= 3) as thrice," f" COUNT(*) FILTER (WHERE {yr_count} = 0 OR {yr_count} IS NULL) as never" - f" FROM server_audit_full WHERE status = 'ok'" - f" AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC)" + f" FROM server_audit_full WHERE status IN ('ok','partial')" + f" AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC)" )).fetchone() patch_by_domain = db.execute(text( @@ -260,8 +260,8 @@ async def audit_full_patching(request: Request, db=Depends(get_db)): f" COUNT(DISTINCT saf.hostname) FILTER (WHERE saf.{yr_count} = 0 OR saf.{yr_count} IS NULL) as never" f" FROM server_audit_full saf JOIN servers s ON saf.server_id = s.id" f" JOIN domain_environments de ON s.domain_env_id = de.id JOIN domains d ON de.domain_id = d.id" - f" WHERE saf.status = 'ok'" - f" AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC)" + f" WHERE saf.status IN ('ok','partial')" + f" AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC)" f" GROUP BY d.name, d.code, d.display_order ORDER BY d.display_order" )).fetchall() @@ -269,8 +269,8 @@ async def audit_full_patching(request: Request, db=Depends(get_db)): if year == 2026: patch_weekly = db.execute(text( "SELECT last_patch_week as week, COUNT(*) as cnt FROM server_audit_full" - " WHERE status = 'ok' AND last_patch_year = 2026 AND last_patch_week IS NOT NULL" - " AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC)" + " WHERE status IN ('ok','partial') AND last_patch_year = 2026 AND last_patch_week IS NOT NULL" + " AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC)" " GROUP BY last_patch_week ORDER BY last_patch_week" )).fetchall() @@ -288,7 +288,7 @@ async def audit_full_patching(request: Request, db=Depends(get_db)): f" LEFT JOIN domains d ON de.domain_id = d.id" f" LEFT JOIN environments e ON de.environment_id = e.id" f" LEFT JOIN zones z ON s.zone_id = z.id" - f" WHERE saf.status = 'ok'" + f" WHERE saf.status IN ('ok','partial')" f" ORDER BY saf.hostname, saf.audit_date DESC" )).fetchall() @@ -362,9 +362,9 @@ async def audit_full_export_csv(request: Request, db=Depends(get_db)): if pattern: ids = {r.id for r in db.execute(text(""" SELECT id FROM server_audit_full - WHERE status = 'ok' + WHERE status IN ('ok','partial') AND (services::text ~* :pat OR listen_ports::text ~* :pat OR processes::text ~* :pat) - AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) """), {"pat": pattern}).fetchall()} audits = [a for a in audits if a.id in ids] if domain: @@ -423,7 +423,7 @@ async def audit_full_flow_map(request: Request, db=Depends(get_db)): # Serveurs audites pour l'autocompletion audited_servers = db.execute(text(""" - SELECT DISTINCT hostname FROM server_audit_full WHERE status = 'ok' ORDER BY hostname + SELECT DISTINCT hostname FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname """)).fetchall() if server_filter: @@ -436,7 +436,7 @@ async def audit_full_flow_map(request: Request, db=Depends(get_db)): JOIN server_audit_full saf ON nfm.audit_id = saf.id WHERE saf.id IN ( SELECT DISTINCT ON (hostname) id FROM server_audit_full - WHERE status = 'ok' ORDER BY hostname, audit_date DESC + WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC ) AND (nfm.source_hostname = :srv OR nfm.dest_hostname = :srv) AND nfm.source_hostname != nfm.dest_hostname @@ -468,7 +468,7 @@ async def audit_full_flow_map(request: Request, db=Depends(get_db)): JOIN server_audit_full saf ON nfm.audit_id = saf.id WHERE saf.id IN ( SELECT DISTINCT ON (hostname) id FROM server_audit_full - WHERE status = 'ok' ORDER BY hostname, audit_date DESC + WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC ) AND (nfm.source_hostname = ANY(:hosts) OR nfm.dest_hostname = ANY(:hosts)) AND nfm.source_hostname != COALESCE(nfm.dest_hostname, '') diff --git a/app/routers/dashboard.py b/app/routers/dashboard.py index 7ca1ea1..0c674f2 100644 --- a/app/routers/dashboard.py +++ b/app/routers/dashboard.py @@ -54,16 +54,16 @@ async def dashboard(request: Request, db=Depends(get_db)): COUNT(*) FILTER (WHERE patch_count_2026 >= 3) as patched_thrice, COUNT(*) FILTER (WHERE reboot_required = true) as needs_reboot FROM server_audit_full - WHERE status = 'ok' - AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + WHERE status IN ('ok','partial') + AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) """)).fetchone() # Frequence patching par semaine 2026 patch_weekly = db.execute(text(""" SELECT last_patch_week as week, COUNT(*) as cnt FROM server_audit_full - WHERE status = 'ok' AND last_patch_year = 2026 AND last_patch_week IS NOT NULL - AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + WHERE status IN ('ok','partial') AND last_patch_year = 2026 AND last_patch_week IS NOT NULL + AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) GROUP BY last_patch_week ORDER BY last_patch_week """)).fetchall() @@ -78,8 +78,8 @@ async def dashboard(request: Request, db=Depends(get_db)): JOIN servers s ON saf.server_id = s.id JOIN domain_environments de ON s.domain_env_id = de.id JOIN domains d ON de.domain_id = d.id - WHERE saf.status = 'ok' - AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + WHERE saf.status IN ('ok','partial') + AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) GROUP BY d.name, d.code, d.display_order ORDER BY d.display_order """)).fetchall() @@ -93,8 +93,8 @@ async def dashboard(request: Request, db=Depends(get_db)): JOIN servers s ON saf.server_id = s.id JOIN domain_environments de ON s.domain_env_id = de.id JOIN environments e ON de.environment_id = e.id - WHERE saf.status = 'ok' - AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + WHERE saf.status IN ('ok','partial') + AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) GROUP BY e.name ORDER BY e.name """)).fetchall() @@ -107,8 +107,8 @@ async def dashboard(request: Request, db=Depends(get_db)): FROM server_audit_full saf JOIN servers s ON saf.server_id = s.id JOIN zones z ON s.zone_id = z.id - WHERE saf.status = 'ok' - AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) + WHERE saf.status IN ('ok','partial') + AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC) GROUP BY z.name ORDER BY z.name """)).fetchall() diff --git a/app/services/server_audit_full_service.py b/app/services/server_audit_full_service.py index 3d88dc5..0c636d7 100644 --- a/app/services/server_audit_full_service.py +++ b/app/services/server_audit_full_service.py @@ -409,7 +409,7 @@ def get_latest_audits(db, limit=100): jsonb_array_length(COALESCE(connections, '[]')) as conn_count, jsonb_array_length(COALESCE(processes, '[]')) as proc_count FROM server_audit_full - WHERE status = 'ok' + WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC LIMIT :lim """), {"lim": limit}).fetchall() @@ -430,7 +430,7 @@ def get_flow_map(db): JOIN server_audit_full saf ON nfm.audit_id = saf.id WHERE saf.id IN ( SELECT DISTINCT ON (hostname) id FROM server_audit_full - WHERE status = 'ok' ORDER BY hostname, audit_date DESC + WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC ) GROUP BY source_hostname, source_ip, dest_ip, dest_port, dest_hostname, process_name, direction, state @@ -463,7 +463,7 @@ def get_flow_map_for_domain(db, domain_code): WHERE d.code = :dc AND saf.id IN ( SELECT DISTINCT ON (hostname) id FROM server_audit_full - WHERE status = 'ok' ORDER BY hostname, audit_date DESC + WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC ) ORDER BY nfm.source_hostname """), {"dc": domain_code}).fetchall() @@ -472,7 +472,7 @@ def get_flow_map_for_domain(db, domain_code): def get_app_map(db): audits = db.execute(text(""" SELECT DISTINCT ON (hostname) hostname, server_id, processes, listen_ports - FROM server_audit_full WHERE status = 'ok' + FROM server_audit_full WHERE status IN ('ok','partial') ORDER BY hostname, audit_date DESC """)).fetchall() app_groups = {}