From 3f660533fc23c8e6e72391cf9caa550fd0eefb1c Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 11:41:02 +0200 Subject: [PATCH] modified: web/blueprints/panel.py modified: web/templates/admin/audit_log.html modified: web/templates/admin/dashboard.html --- web/blueprints/panel.py | 25 +++++++++++++++++++++++++ web/templates/admin/audit_log.html | 10 ++++++++++ web/templates/admin/dashboard.html | 12 ++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/web/blueprints/panel.py b/web/blueprints/panel.py index 7ce3699..9974678 100644 --- a/web/blueprints/panel.py +++ b/web/blueprints/panel.py @@ -14,6 +14,20 @@ from roles import can_manage_group panel = Blueprint("panel", __name__) +def _audit(action: str, details: dict | None = None, entity_type: str | None = None, entity_id=None): + """Fire-and-forget audit event for panel data access (never raises).""" + pdb.log_audit_event( + session.get("user_id"), + session.get("username"), + action, + entity_type=entity_type, + entity_id=entity_id, + details=details, + group_id=session.get("group_id"), + ip_address=request.remote_addr, + ) + + # ───────────────────────────────────────────────────────────── # Hilfsfunktionen # ───────────────────────────────────────────────────────────── @@ -170,6 +184,7 @@ def dashboard(): def players(): search = request.args.get("q", "") page = max(1, request.args.get("page", 1, type=int)) + _audit("panel.view_players", {"search": search, "page": page} if search else {"page": page}) if search: base = "FROM players WHERE username LIKE %s" args = (f"%{search}%",) @@ -191,6 +206,8 @@ def player_detail(uuid): if not player: flash("Player not found.", "danger") return redirect(url_for("panel.players")) + _audit("panel.view_player", {"player_name": player.get("username"), "uuid": uuid}, + entity_type="mc_player", entity_id=uuid) perms = session.get("permissions", {}) is_admin = session.get("is_site_admin") or can_manage_group(session.get("role")) return render_template("panel/player_detail.html", @@ -216,6 +233,7 @@ def sessions(): page = max(1, request.args.get("page", 1, type=int)) player = request.args.get("player", "") server = request.args.get("server", "") + _audit("panel.view_sessions", {"page": page}) conditions, args = [], [] if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%") if server: conditions.append("server_name = %s"); args.append(server) @@ -239,6 +257,7 @@ def sessions(): def chat(): page = max(1, request.args.get("page", 1, type=int)) search = request.args.get("q", ""); server = request.args.get("server", "") + _audit("panel.view_chat", {"page": page}) date_from = request.args.get("from", ""); date_to = request.args.get("to", "") conditions, args = [], [] if search: conditions.append("message LIKE %s"); args.append(f"%{search}%") @@ -265,6 +284,7 @@ def chat(): def commands(): page = max(1, request.args.get("page", 1, type=int)) player = request.args.get("player", ""); search = request.args.get("q", ""); server = request.args.get("server", "") + _audit("panel.view_commands", {"page": page}) conditions, args = [], [] if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%") if search: conditions.append("command LIKE %s"); args.append(f"%{search}%") @@ -289,6 +309,7 @@ def commands(): def deaths(): page = max(1, request.args.get("page", 1, type=int)) player = request.args.get("player", ""); cause = request.args.get("cause", "") + _audit("panel.view_deaths", {"page": page}) conditions, args = [], [] if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%") if cause: conditions.append("cause = %s"); args.append(cause) @@ -311,6 +332,7 @@ def deaths(): def blocks(): page = max(1, request.args.get("page", 1, type=int)) event_type = request.args.get("type", ""); player = request.args.get("player", "") + _audit("panel.view_blocks", {"page": page}) world = request.args.get("world", ""); server = request.args.get("server", ""); block = request.args.get("block", "") conditions, args = [], [] if event_type: conditions.append("event_type = %s"); args.append(event_type) @@ -340,6 +362,7 @@ def blocks(): def proxy(): page = max(1, request.args.get("page", 1, type=int)) event_type = request.args.get("type", ""); player = request.args.get("player", "") + _audit("panel.view_proxy", {"page": page}) conditions, args = [], [] if event_type: conditions.append("event_type = %s"); args.append(event_type) if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%") @@ -361,6 +384,7 @@ def proxy(): def server_events(): page = max(1, request.args.get("page", 1, type=int)) server = request.args.get("server", ""); etype = request.args.get("type", "") + _audit("panel.view_server_events", {"page": page}) conditions, args = [], [] if server: conditions.append("server_name = %s"); args.append(server) if etype: conditions.append("event_type = %s"); args.append(etype) @@ -385,6 +409,7 @@ def server_events(): def perms(): page = max(1, request.args.get("page", 1, type=int)) player = request.args.get("player", ""); plugin_filter = request.args.get("plugin", ""); etype = request.args.get("type", "") + _audit("panel.view_perms", {"page": page}) conditions, args = [], [] if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%") if plugin_filter: conditions.append("plugin_name = %s"); args.append(plugin_filter) diff --git a/web/templates/admin/audit_log.html b/web/templates/admin/audit_log.html index e9b14d9..e01e62f 100644 --- a/web/templates/admin/audit_log.html +++ b/web/templates/admin/audit_log.html @@ -121,6 +121,16 @@ 'consent.given': 'badge bg-success', 'consent.declined': 'badge bg-warning text-dark', 'audit.purged': 'badge bg-danger', + 'panel.view_players': 'badge bg-dark border border-info', + 'panel.view_player': 'badge bg-info text-dark', + 'panel.view_sessions': 'badge bg-dark border border-info', + 'panel.view_chat': 'badge bg-dark border border-info', + 'panel.view_commands': 'badge bg-dark border border-info', + 'panel.view_deaths': 'badge bg-dark border border-info', + 'panel.view_blocks': 'badge bg-dark border border-info', + 'panel.view_proxy': 'badge bg-dark border border-info', + 'panel.view_server_events': 'badge bg-dark border border-info', + 'panel.view_perms': 'badge bg-dark border border-info', } %} {{ row.action }} diff --git a/web/templates/admin/dashboard.html b/web/templates/admin/dashboard.html index d0a0502..655438c 100644 --- a/web/templates/admin/dashboard.html +++ b/web/templates/admin/dashboard.html @@ -191,8 +191,16 @@ 'mail.settings_deleted': 'badge bg-danger', 'consent.given': 'badge bg-success', 'consent.declined': 'badge bg-warning text-dark', - 'audit.purged': 'badge bg-danger', - } %} + 'audit.purged': 'badge bg-danger', 'panel.view_players': 'badge bg-dark border border-info', + 'panel.view_player': 'badge bg-info text-dark', + 'panel.view_sessions': 'badge bg-dark border border-info', + 'panel.view_chat': 'badge bg-dark border border-info', + 'panel.view_commands': 'badge bg-dark border border-info', + 'panel.view_deaths': 'badge bg-dark border border-info', + 'panel.view_blocks': 'badge bg-dark border border-info', + 'panel.view_proxy': 'badge bg-dark border border-info', + 'panel.view_server_events': 'badge bg-dark border border-info', + 'panel.view_perms': 'badge bg-dark border border-info', } %} {{ row.created_at | fmt_dt }}