aether-framework/resources/[aether]/aether-admin/server/db.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

151 lines
5.2 KiB
Lua

-- =====================================================================
-- aether-admin — Datenbankzugriff (oxmysql)
--
-- Kapselt die wiederkehrenden Abfragen, die mehrere Fachmodule teilen:
-- Einstellungen, Benutzer-/Charakterdaten, Bans. Domänenspezifische
-- Abfragen (Reports, Warns, Immobilien …) liegen in ihren Modulen.
-- =====================================================================
Admin = Admin or {}
Admin.DB = {}
-- ---------------------------------------------------------------------
-- Persistierte Einstellungen (Schlüssel/Wert)
-- ---------------------------------------------------------------------
--- Liest eine Einstellung als Text
--- @param schluessel string
--- @param standard any Rückfallwert
--- @return string
function Admin.DB.Einstellung(schluessel, standard)
local wert = MySQL.scalar.await(
'SELECT wert FROM aether_admin_settings WHERE schluessel = ?', { schluessel })
if wert == nil then return standard end
return wert
end
--- Liest eine Einstellung als Zahl
--- @param schluessel string
--- @param standard number
--- @return number
function Admin.DB.EinstellungZahl(schluessel, standard)
return tonumber(Admin.DB.Einstellung(schluessel, standard)) or standard or 0
end
--- Liest eine Einstellung als Schalter
--- @param schluessel string
--- @param standard boolean
--- @return boolean
function Admin.DB.EinstellungAn(schluessel, standard)
local wert = Admin.DB.Einstellung(schluessel, standard and '1' or '0')
return wert == '1' or wert == 'true' or wert == true
end
--- Schreibt eine Einstellung
--- @param schluessel string
--- @param wert any
function Admin.DB.SetzeEinstellung(schluessel, wert)
MySQL.prepare.await([[
INSERT INTO aether_admin_settings (schluessel, wert) VALUES (?, ?)
ON DUPLICATE KEY UPDATE wert = VALUES(wert)
]], { schluessel, tostring(wert) })
end
-- ---------------------------------------------------------------------
-- Benutzer & Charaktere (aus aether-core)
-- ---------------------------------------------------------------------
--- Rechtegruppe eines Benutzers direkt aus der Datenbank
--- @param lizenz string
--- @return string
function Admin.DB.GruppeVonLizenz(lizenz)
local wert = MySQL.scalar.await(
'SELECT admin_group FROM aether_users WHERE license = ?', { lizenz })
return wert or 'user'
end
--- Setzt die Rechtegruppe eines Benutzers
--- @param lizenz string
--- @param gruppe string
--- @return boolean
function Admin.DB.SetzeGruppe(lizenz, gruppe)
local betroffen = MySQL.update.await(
'UPDATE aether_users SET admin_group = ? WHERE license = ?', { gruppe, lizenz })
return (betroffen or 0) > 0
end
--- Sucht einen Benutzer über Lizenz oder Namen
--- @param begriff string
--- @return table Liste
function Admin.DB.SucheBenutzer(begriff)
local muster = '%' .. begriff .. '%'
return MySQL.query.await([[
SELECT license, name, admin_group, is_banned
FROM aether_users
WHERE license = ? OR name LIKE ?
ORDER BY last_seen DESC
LIMIT 25
]], { begriff, muster }) or {}
end
-- ---------------------------------------------------------------------
-- Bans · Durchsetzung in aether_users, Gedächtnis in aether_admin_bans
-- ---------------------------------------------------------------------
--- Sperrt einen Benutzer: setzt die Core-Felder und schreibt den Verlauf.
--- @param lizenz string|nil Lizenz (nil = nur Verlaufseintrag, Offline-Ban)
--- @param name string Anzeigename
--- @param grund string
--- @param bis string|nil DATETIME oder nil (dauerhaft)
--- @param adminLizenz string|nil
--- @param adminName string
--- @return number Ban-ID
function Admin.DB.Sperre(lizenz, name, grund, bis, adminLizenz, adminName)
if lizenz then
MySQL.update.await([[
UPDATE aether_users SET is_banned = 1, ban_reason = ?, ban_until = ?
WHERE license = ?
]], { grund, bis, lizenz })
end
return MySQL.insert.await([[
INSERT INTO aether_admin_bans
(license, name, grund, admin_license, admin_name, bis, aktiv)
VALUES (?, ?, ?, ?, ?, ?, 1)
]], { lizenz, name, grund, adminLizenz, adminName, bis })
end
--- Hebt einen Bann auf: löscht die Core-Sperre und markiert den Verlauf.
--- @param banId number
--- @param adminName string
--- @return boolean
function Admin.DB.Entsperre(banId, adminName)
local zeilen = MySQL.query.await(
'SELECT license FROM aether_admin_bans WHERE id = ? AND aktiv = 1', { banId })
if not zeilen or not zeilen[1] then return false end
if zeilen[1].license then
MySQL.update.await([[
UPDATE aether_users SET is_banned = 0, ban_reason = NULL, ban_until = NULL
WHERE license = ?
]], { zeilen[1].license })
end
MySQL.update.await([[
UPDATE aether_admin_bans
SET aktiv = 0, aufgehoben_am = NOW(), aufgehoben_von = ?
WHERE id = ?
]], { adminName, banId })
return true
end
--- Liste aktiver Bans
--- @return table
function Admin.DB.AktiveBans()
return MySQL.query.await([[
SELECT id, license, name, grund, admin_name, bis, erstellt_am
FROM aether_admin_bans WHERE aktiv = 1
ORDER BY id DESC LIMIT 200
]]) or {}
end