UX-Paket: Navbar aufgeräumt, /server-Seite, Lightbox, Skeletons, Audit-Log, Reroll
- Navbar entschlackt: nur noch Devlog · Roadmap · Server · Community · Setup; Galerie/Level/Events/Changelog im Community-Dropdown, Profil/Commits/Logout im Avatar-Menü; Mobile-Burger mit Drawer - Öffentliche /server-Seite: Live-Status-Karten mit Spieler-Balken, Map, Connect-Button und 24h-Spielerzahl-Chart (SVG); Monitor sampelt jede Abfrage in player_history (7 Tage Retention), GET /api/servers liefert nur öffentliche Felder (keine Query-URLs/Hosts) - Lightbox: Galerie- und Devlog-Bilder öffnen im Overlay mit Pfeiltasten, Buttons, Wisch-Gesten und Zähler statt neuem Tab - Skeleton-Loader: schimmernde Platzhalter auf Devlogs, Roadmap, Galerie, Level, Changelog und Server statt "Lade …" - Team-Audit-Log: audit_log-Tabelle (max 500 Einträge), Logging bei Settings/Composer/Vorlagen/Rollen-Menüs/Gameservern/Team/API-Keys/ Branding, GET /api/auditlog (Owner) + Liste im Team-Tab - Giveaway: 🔁 Reroll-Button (Admin-only) + 👥 Teilnehmerliste am Gewinner-Post Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -474,6 +474,30 @@ export const webAdminScopes = (userId) =>
|
||||
export const listWebAdmins = () => listWebAdminsStmt.all();
|
||||
export const deleteWebAdmin = (userId) => deleteWebAdminStmt.run(userId).changes > 0;
|
||||
|
||||
// Audit-Log: wer (Owner/Team) hat wann was im Webinterface geändert
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
ts TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
user_id TEXT NOT NULL,
|
||||
username TEXT,
|
||||
action TEXT NOT NULL,
|
||||
detail TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
`);
|
||||
const insertAudit = db.prepare(
|
||||
'INSERT INTO audit_log (user_id, username, action, detail) VALUES (?, ?, ?, ?)'
|
||||
);
|
||||
const listAuditStmt = db.prepare('SELECT * FROM audit_log ORDER BY id DESC LIMIT ?');
|
||||
const pruneAuditStmt = db.prepare(`
|
||||
DELETE FROM audit_log WHERE id NOT IN (SELECT id FROM audit_log ORDER BY id DESC LIMIT 500)
|
||||
`);
|
||||
export function logAudit(user, action, detail = '') {
|
||||
insertAudit.run(user?.id ?? '?', user?.username ?? '?', action, String(detail).slice(0, 300));
|
||||
pruneAuditStmt.run();
|
||||
}
|
||||
export const listAudit = (limit = 100) => listAuditStmt.all(limit);
|
||||
|
||||
// Game-Server (DiscordGSM-Stil): strukturierte Server statt CSV-Setting
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS gameservers (
|
||||
@@ -528,6 +552,29 @@ export const listGameservers = () => listGameserversStmt.all();
|
||||
export const getGameserver = (id) => getGameserverStmt.get(id) ?? null;
|
||||
export const deleteGameserver = (id) => deleteGameserverStmt.run(id).changes > 0;
|
||||
|
||||
// Spielerzahl-Verlauf für die öffentliche /server-Seite (Sample alle 2 min, 7 Tage Retention)
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS player_history (
|
||||
server_id INTEGER NOT NULL,
|
||||
ts TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
online INTEGER NOT NULL,
|
||||
players INTEGER
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ph_server_ts ON player_history (server_id, ts);
|
||||
`);
|
||||
const insertPlayerSample = db.prepare(
|
||||
'INSERT INTO player_history (server_id, online, players) VALUES (?, ?, ?)'
|
||||
);
|
||||
const playerHistoryStmt = db.prepare(`
|
||||
SELECT ts, online, players FROM player_history
|
||||
WHERE server_id = ? AND ts >= datetime('now', ?) ORDER BY ts
|
||||
`);
|
||||
const prunePlayerHistoryStmt = db.prepare(`DELETE FROM player_history WHERE ts < datetime('now', '-7 days')`);
|
||||
export const recordPlayerSample = (serverId, online, players) =>
|
||||
insertPlayerSample.run(serverId, online ? 1 : 0, players);
|
||||
export const playerHistory = (serverId, hours = 24) => playerHistoryStmt.all(serverId, `-${hours} hours`);
|
||||
export const prunePlayerHistory = () => prunePlayerHistoryStmt.run();
|
||||
|
||||
// Moderation: Verwarnungen + Sticky-Roles
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS warns (
|
||||
|
||||
Reference in New Issue
Block a user