aether-framework/resources/[aether]/aether-admin/server/log.lua
Jerrit Fritzsche e4b82dd685 Aether-Framework: Fachmodule, Admin-Panel und Docker-Datenbank
- aether-medical: Stationen/Belegung, Intensivstation, Blutbank, Fuhrpark,
  Nachrichten/Aushänge, Berichte und Textbausteine (server + NUI)
- aether-admin: vollständiges Server-Admin-Panel als echtes FiveM-Resource,
  an aether-core gekoppelt (Rechte über aether_users.admin_group), mit
  WebRTC-Live-Kameras (Bildschirmfreigabe) und separatem Media-Server (SFU)
- Prototypen admin/ vervollständigt
- SQL-Schema aether_admin.sql
- Docker-Compose mit MariaDB und idempotenter Auto-Migration (schema_migrations)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 18:55:32 +02:00

70 lines
2.4 KiB
Lua

-- =====================================================================
-- aether-admin — Prüfprotokoll
--
-- Jede eingreifende Aktion hinterlässt eine Spur: wer, was, an wem,
-- mit welchem Detail. Einträge werden nur geschrieben und gelesen —
-- nie geändert oder entfernt.
-- =====================================================================
Admin = Admin or {}
Admin.Log = {}
--- Schreibt einen Protokolleintrag
--- @param handelnder table|nil { lizenz, name } — der Admin
--- @param aktion string Was getan wurde
--- @param ziel string|nil An wem / woran
--- @param detail string|nil Zusatz
function Admin.Log.Schreibe(handelnder, aktion, ziel, detail)
MySQL.insert([[
INSERT INTO aether_admin_log (admin_license, admin_name, aktion, ziel, detail)
VALUES (?, ?, ?, ?, ?)
]], {
handelnder and handelnder.lizenz or nil,
handelnder and handelnder.name or 'System',
aktion,
ziel and tostring(ziel):sub(1, 96) or nil,
detail and tostring(detail):sub(1, 512) or nil,
})
end
--- Liest Protokolleinträge mit einfachen Filtern
--- @param filter table { suche?, admin?, limit? }
--- @return table
function Admin.Log.Lies(filter)
filter = filter or {}
local bedingungen, werte = {}, {}
if filter.admin and filter.admin ~= '' then
bedingungen[#bedingungen + 1] = 'admin_name = ?'
werte[#werte + 1] = filter.admin
end
if filter.suche and filter.suche ~= '' then
local muster = '%' .. filter.suche .. '%'
bedingungen[#bedingungen + 1] = '(aktion LIKE ? OR ziel LIKE ? OR detail LIKE ?)'
werte[#werte + 1] = muster
werte[#werte + 1] = muster
werte[#werte + 1] = muster
end
local wo = #bedingungen > 0 and ('WHERE ' .. table.concat(bedingungen, ' AND ')) or ''
werte[#werte + 1] = math.min(tonumber(filter.limit) or 200, 500)
return MySQL.query.await(([[
SELECT admin_name, aktion, ziel, detail, erstellt_am
FROM aether_admin_log
%s
ORDER BY id DESC
LIMIT ?
]]):format(wo), werte) or {}
end
--- Liste der Admins, die je etwas protokolliert haben (für den Filter)
--- @return table
function Admin.Log.Admins()
local zeilen = MySQL.query.await(
'SELECT DISTINCT admin_name FROM aether_admin_log ORDER BY admin_name') or {}
local liste = {}
for _, z in ipairs(zeilen) do liste[#liste + 1] = z.admin_name end
return liste
end