diff --git a/full_updater/backend/scanner.py b/full_updater/backend/scanner.py index 6180049..6fd044a 100644 --- a/full_updater/backend/scanner.py +++ b/full_updater/backend/scanner.py @@ -51,33 +51,34 @@ def _is_cve_actionable(cve_id: str, suite: str = "bookworm") -> bool: def filter_actionable_cves(cves: list[dict]) -> tuple[list[dict], int]: - """Filtre la liste des CVE pour ne garder que les actionnables. - Retourne (cve_actionnables, cve_total).""" + """Filtre la liste des CVE pour ajouter un flag 'fixable'. + Retourne (cve_avec_flag, nombre_actionnables).""" if not cves: return [], 0 - total = len(cves) - - def check(cve: dict) -> dict | None: + def check(cve: dict) -> dict: try: - if _is_cve_actionable(cve["id"]): - return cve + is_fixable = _is_cve_actionable(cve["id"]) + cve["fixable"] = is_fixable + return cve except Exception: - pass - return None + cve["fixable"] = False + return cve - actionable = [] + all_cves = [] + actionable_count = 0 with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(check, cve) for cve in cves] for future in futures: try: - result = future.result() - if result: - actionable.append(result) + cve = future.result() + all_cves.append(cve) + if cve.get("fixable"): + actionable_count += 1 except Exception: pass - return actionable, total + return all_cves, actionable_count @dataclass @@ -218,10 +219,10 @@ def scan_target(target: Target, progress_cb: Callable) -> ScanResult: # Filtrer les CVE actionnables via l'API Debian if cve_list: - actionable, total = filter_actionable_cves(cve_list) - result.cve_list = actionable - result.cve_count = len(actionable) - result.cve_total = total + all_cves, actionable_count = filter_actionable_cves(cve_list) + result.cve_list = all_cves + result.cve_count = actionable_count + result.cve_total = len(all_cves) else: result.cve_list = [] result.cve_count = 0 diff --git a/full_updater/ui/detail_screens.py b/full_updater/ui/detail_screens.py index dc64962..78b31b4 100644 --- a/full_updater/ui/detail_screens.py +++ b/full_updater/ui/detail_screens.py @@ -9,6 +9,21 @@ except Exception: PYPERCLIP_OK = False +SCREEN_CSS = """ + align: left top; + padding: 1 2; + #toolbar { + height: auto; + dock: top; + margin-bottom: 1; + } + DataTable { + height: 1fr; + border: solid $primary; + } +""" + + class PackageListScreen(Screen): BINDINGS = [("b", "back", "Retour")] DEFAULT_CSS = """ @@ -75,14 +90,15 @@ class CVEListScreen(Screen): with Horizontal(id="toolbar"): yield Button("⬅ Retour", id="cve-back", variant="default") table = DataTable(id="cve-table") - table.add_columns("CVE-ID", "Paquet", "Lien") + table.add_columns("CVE-ID", "Paquet", "Corrigeable", "Lien") table.cursor_type = "row" for i, cve in enumerate(self.cves): cve_id = cve.get("id", "?") pkg = cve.get("package", "?") url = cve.get("url", "") + fixable = "🟢 Oui" if cve.get("fixable") else "🔴 Non" self.urls[i] = url - table.add_row(cve_id, pkg, url) + table.add_row(cve_id, pkg, fixable, url) yield table def on_data_table_row_selected(self, event: DataTable.RowSelected):