Add JSON integrity hash checks

This commit is contained in:
Marcel Peterkau
2026-06-27 10:35:35 +02:00
parent d1dab793a6
commit 87e972bb43
9 changed files with 302 additions and 11 deletions
+43
View File
@@ -510,3 +510,46 @@ class AssetClaimDialog(tk.Toplevel):
return
self.destroy()
self.on_created(str(result["claim"]["claim_id"]))
class IntegrityWarningDialog(tk.Toplevel):
def __init__(
self,
master: tk.Misc,
*,
title: str,
warnings: list[str],
on_confirm: Callable[[], None],
):
super().__init__(master)
self.on_confirm = on_confirm
self.title(title)
self.transient(master.winfo_toplevel())
self.resizable(False, False)
self.warnings = warnings
self._build_ui()
self.bind("<Escape>", lambda _event: self.destroy())
self.after_idle(self._activate_modal)
def _build_ui(self) -> None:
frame = ttk.Frame(self, padding=18)
frame.pack(fill="both", expand=True)
message = (
"ACHTUNG: Die zugehörigen JSON-Dateien wurden vermutlich extern geändert.\n\n"
"Haben Sie alle Daten geprüft und soll der Hash jetzt aktualisiert werden?"
)
ttk.Label(frame, text=message, justify="left").grid(row=0, column=0, sticky="w")
ttk.Label(frame, text="\n".join(f"{item}" for item in self.warnings), style="Warning.TLabel", justify="left").grid(
row=1, column=0, sticky="w", pady=(12, 0)
)
buttons = ttk.Frame(frame)
buttons.grid(row=2, column=0, sticky="e", pady=(18, 0))
ttk.Button(buttons, text="Nein", command=self.destroy).pack(side="left", padx=(0, 8))
ttk.Button(buttons, text="Ja, bestätigen", style="Accent.TButton", command=self._confirm).pack(side="left")
def _activate_modal(self) -> None:
_activate_modal_window(self)
def _confirm(self) -> None:
self.destroy()
self.on_confirm()
+12 -2
View File
@@ -471,7 +471,7 @@ class MainWindow(ttk.Frame):
tab = HousekeeperTab(
self.notebook,
self.findings,
self.open_member,
self._open_housekeeper_target,
self.run_housekeeper,
self.delete_housekeeper_task,
lambda: self.tabs.close(key),
@@ -545,12 +545,22 @@ class MainWindow(ttk.Frame):
self.tabs.refresh_icons(self.icons)
def _show_validation_warning(self) -> None:
display_errors = [item for item in self.validation_errors if "Hash fehlt oder stimmt nicht" not in item]
if not display_errors:
return
messagebox.showwarning(
"Datenprüfung",
"Der Store enthält ungültige Akten:\n\n" + "\n".join(self.validation_errors[:12]),
"Der Store enthält ungültige Akten:\n\n" + "\n".join(display_errors[:12]),
parent=self,
)
def _open_housekeeper_target(self, finding: HousekeeperFinding) -> None:
if finding.target_type == "asset" and finding.asset_id:
self.open_asset(finding.asset_id)
return
if finding.member_id:
self.open_member(finding.member_id)
def _member_reference_label(self, member_id: str) -> str:
if not member_id:
return ""
+7 -3
View File
@@ -485,14 +485,14 @@ class HousekeeperTab(ttk.Frame):
self,
master: tk.Misc,
findings: list[HousekeeperFinding],
on_open_member: Callable[[str], None],
on_open_target: Callable[[HousekeeperFinding], None],
on_refresh: Callable[[], list[HousekeeperFinding]],
on_delete: Callable[[str], list[HousekeeperFinding]],
on_close: Callable[[], None],
):
super().__init__(master, padding=12)
self.findings = findings
self.on_open_member = on_open_member
self.on_open_target = on_open_target
self.on_refresh = on_refresh
self.on_delete = on_delete
self.on_close = on_close
@@ -602,11 +602,15 @@ class HousekeeperTab(ttk.Frame):
def _open_selected(self) -> None:
selected = self.tree.selection()
if selected:
self.on_open_member(self.findings[int(selected[0])].member_id)
self.on_open_target(self.findings[int(selected[0])])
def _finding_details(finding: HousekeeperFinding) -> str:
lines = [f"{finding.severity.upper()} · {finding.code}", finding.title]
if finding.target_type == "asset" and finding.asset_id:
lines.append(f"Asset: {finding.asset_id}")
elif finding.member_id:
lines.append(f"Mitglied: {finding.member_id}")
if finding.key:
lines.append(f"Key: {finding.key}")
if finding.due_date: