modified: web/blueprints/panel.py
modified: web/templates/admin/audit_log.html modified: web/templates/admin/dashboard.html
This commit is contained in:
@@ -14,6 +14,20 @@ from roles import can_manage_group
|
|||||||
panel = Blueprint("panel", __name__)
|
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
|
# Hilfsfunktionen
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
@@ -170,6 +184,7 @@ def dashboard():
|
|||||||
def players():
|
def players():
|
||||||
search = request.args.get("q", "")
|
search = request.args.get("q", "")
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
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:
|
if search:
|
||||||
base = "FROM players WHERE username LIKE %s"
|
base = "FROM players WHERE username LIKE %s"
|
||||||
args = (f"%{search}%",)
|
args = (f"%{search}%",)
|
||||||
@@ -191,6 +206,8 @@ def player_detail(uuid):
|
|||||||
if not player:
|
if not player:
|
||||||
flash("Player not found.", "danger")
|
flash("Player not found.", "danger")
|
||||||
return redirect(url_for("panel.players"))
|
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", {})
|
perms = session.get("permissions", {})
|
||||||
is_admin = session.get("is_site_admin") or can_manage_group(session.get("role"))
|
is_admin = session.get("is_site_admin") or can_manage_group(session.get("role"))
|
||||||
return render_template("panel/player_detail.html",
|
return render_template("panel/player_detail.html",
|
||||||
@@ -216,6 +233,7 @@ def sessions():
|
|||||||
page = max(1, request.args.get("page", 1, type=int))
|
page = max(1, request.args.get("page", 1, type=int))
|
||||||
player = request.args.get("player", "")
|
player = request.args.get("player", "")
|
||||||
server = request.args.get("server", "")
|
server = request.args.get("server", "")
|
||||||
|
_audit("panel.view_sessions", {"page": page})
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
||||||
if server: conditions.append("server_name = %s"); args.append(server)
|
if server: conditions.append("server_name = %s"); args.append(server)
|
||||||
@@ -239,6 +257,7 @@ def sessions():
|
|||||||
def chat():
|
def chat():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
page = max(1, request.args.get("page", 1, type=int))
|
||||||
search = request.args.get("q", ""); server = request.args.get("server", "")
|
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", "")
|
date_from = request.args.get("from", ""); date_to = request.args.get("to", "")
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if search: conditions.append("message LIKE %s"); args.append(f"%{search}%")
|
if search: conditions.append("message LIKE %s"); args.append(f"%{search}%")
|
||||||
@@ -265,6 +284,7 @@ def chat():
|
|||||||
def commands():
|
def commands():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
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", "")
|
player = request.args.get("player", ""); search = request.args.get("q", ""); server = request.args.get("server", "")
|
||||||
|
_audit("panel.view_commands", {"page": page})
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
||||||
if search: conditions.append("command LIKE %s"); args.append(f"%{search}%")
|
if search: conditions.append("command LIKE %s"); args.append(f"%{search}%")
|
||||||
@@ -289,6 +309,7 @@ def commands():
|
|||||||
def deaths():
|
def deaths():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
page = max(1, request.args.get("page", 1, type=int))
|
||||||
player = request.args.get("player", ""); cause = request.args.get("cause", "")
|
player = request.args.get("player", ""); cause = request.args.get("cause", "")
|
||||||
|
_audit("panel.view_deaths", {"page": page})
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
||||||
if cause: conditions.append("cause = %s"); args.append(cause)
|
if cause: conditions.append("cause = %s"); args.append(cause)
|
||||||
@@ -311,6 +332,7 @@ def deaths():
|
|||||||
def blocks():
|
def blocks():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
page = max(1, request.args.get("page", 1, type=int))
|
||||||
event_type = request.args.get("type", ""); player = request.args.get("player", "")
|
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", "")
|
world = request.args.get("world", ""); server = request.args.get("server", ""); block = request.args.get("block", "")
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if event_type: conditions.append("event_type = %s"); args.append(event_type)
|
if event_type: conditions.append("event_type = %s"); args.append(event_type)
|
||||||
@@ -340,6 +362,7 @@ def blocks():
|
|||||||
def proxy():
|
def proxy():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
page = max(1, request.args.get("page", 1, type=int))
|
||||||
event_type = request.args.get("type", ""); player = request.args.get("player", "")
|
event_type = request.args.get("type", ""); player = request.args.get("player", "")
|
||||||
|
_audit("panel.view_proxy", {"page": page})
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if event_type: conditions.append("event_type = %s"); args.append(event_type)
|
if event_type: conditions.append("event_type = %s"); args.append(event_type)
|
||||||
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
||||||
@@ -361,6 +384,7 @@ def proxy():
|
|||||||
def server_events():
|
def server_events():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
page = max(1, request.args.get("page", 1, type=int))
|
||||||
server = request.args.get("server", ""); etype = request.args.get("type", "")
|
server = request.args.get("server", ""); etype = request.args.get("type", "")
|
||||||
|
_audit("panel.view_server_events", {"page": page})
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if server: conditions.append("server_name = %s"); args.append(server)
|
if server: conditions.append("server_name = %s"); args.append(server)
|
||||||
if etype: conditions.append("event_type = %s"); args.append(etype)
|
if etype: conditions.append("event_type = %s"); args.append(etype)
|
||||||
@@ -385,6 +409,7 @@ def server_events():
|
|||||||
def perms():
|
def perms():
|
||||||
page = max(1, request.args.get("page", 1, type=int))
|
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", "")
|
player = request.args.get("player", ""); plugin_filter = request.args.get("plugin", ""); etype = request.args.get("type", "")
|
||||||
|
_audit("panel.view_perms", {"page": page})
|
||||||
conditions, args = [], []
|
conditions, args = [], []
|
||||||
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
if player: conditions.append("player_name LIKE %s"); args.append(f"%{player}%")
|
||||||
if plugin_filter: conditions.append("plugin_name = %s"); args.append(plugin_filter)
|
if plugin_filter: conditions.append("plugin_name = %s"); args.append(plugin_filter)
|
||||||
|
|||||||
@@ -121,6 +121,16 @@
|
|||||||
'consent.given': 'badge bg-success',
|
'consent.given': 'badge bg-success',
|
||||||
'consent.declined': 'badge bg-warning text-dark',
|
'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',
|
||||||
} %}
|
} %}
|
||||||
<span class="{{ action_class.get(row.action, 'badge bg-secondary') }} font-monospace" style="font-size:.75em">
|
<span class="{{ action_class.get(row.action, 'badge bg-secondary') }} font-monospace" style="font-size:.75em">
|
||||||
{{ row.action }}
|
{{ row.action }}
|
||||||
|
|||||||
@@ -191,8 +191,16 @@
|
|||||||
'mail.settings_deleted': 'badge bg-danger',
|
'mail.settings_deleted': 'badge bg-danger',
|
||||||
'consent.given': 'badge bg-success',
|
'consent.given': 'badge bg-success',
|
||||||
'consent.declined': 'badge bg-warning text-dark',
|
'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', } %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-muted small">{{ row.created_at | fmt_dt }}</td>
|
<td class="text-muted small">{{ row.created_at | fmt_dt }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
Reference in New Issue
Block a user