- 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>
67 lines
2.3 KiB
Lua
67 lines
2.3 KiB
Lua
-- =====================================================================
|
|
-- aether-police — Protokollierung
|
|
--
|
|
-- Jede verändernde Aktion wird festgehalten: wer, wann, was, warum.
|
|
-- Lesende Zugriffe werden bewusst nicht protokolliert, damit das
|
|
-- Protokoll aussagekräftig bleibt.
|
|
-- =====================================================================
|
|
|
|
Protokoll = {}
|
|
|
|
--- Schreibt einen Protokolleintrag
|
|
--- @param beamter table|nil Handelnder Beamter
|
|
--- @param modul string Modulkennung
|
|
--- @param aktion string Was wurde getan
|
|
--- @param ziel table|nil { typ, id }
|
|
--- @param details table|nil Beliebige Zusatzdaten
|
|
--- @param grund string|nil Begründung, falls angegeben
|
|
function Protokoll.Schreibe(beamter, modul, aktion, ziel, details, grund)
|
|
MySQL.insert([[
|
|
INSERT INTO police_protokoll
|
|
(`character`, dienstnummer, modul, aktion, ziel_typ, ziel_id, details, grund)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
]], {
|
|
beamter and beamter.charakterId or nil,
|
|
beamter and beamter.dienstnummer or nil,
|
|
modul, aktion,
|
|
ziel and ziel.typ or nil,
|
|
ziel and tostring(ziel.id) or nil,
|
|
details and json.encode(details) or nil,
|
|
grund,
|
|
})
|
|
end
|
|
|
|
--- Liest Protokolleinträge mit einfachen Filtern
|
|
--- @param filter table { modul?, charakterId?, zielTyp?, zielId?, limit? }
|
|
--- @return table
|
|
function Protokoll.Lies(filter)
|
|
filter = filter or {}
|
|
local bedingungen, werte = {}, {}
|
|
|
|
if filter.modul then
|
|
bedingungen[#bedingungen + 1] = 'modul = ?'
|
|
werte[#werte + 1] = filter.modul
|
|
end
|
|
if filter.charakterId then
|
|
bedingungen[#bedingungen + 1] = '`character` = ?'
|
|
werte[#werte + 1] = filter.charakterId
|
|
end
|
|
if filter.zielTyp and filter.zielId then
|
|
bedingungen[#bedingungen + 1] = 'ziel_typ = ? AND ziel_id = ?'
|
|
werte[#werte + 1] = filter.zielTyp
|
|
werte[#werte + 1] = tostring(filter.zielId)
|
|
end
|
|
|
|
local wo = #bedingungen > 0 and ('WHERE ' .. table.concat(bedingungen, ' AND ')) or ''
|
|
werte[#werte + 1] = math.min(filter.limit or 100, 500)
|
|
|
|
return MySQL.query.await(([[
|
|
SELECT p.*, c.firstname, c.lastname
|
|
FROM police_protokoll p
|
|
LEFT JOIN aether_characters c ON c.id = p.`character`
|
|
%s
|
|
ORDER BY p.id DESC
|
|
LIMIT ?
|
|
]]):format(wo), werte) or {}
|
|
end
|