Erweiterung Log Export und Login / Logout Log
This commit is contained in:
@@ -494,6 +494,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
if ($action === 'login') {
|
if ($action === 'login') {
|
||||||
$found = findUserByEmail($pdo, trim((string)($_POST['email'] ?? '')));
|
$found = findUserByEmail($pdo, trim((string)($_POST['email'] ?? '')));
|
||||||
if ($found && password_verify((string)($_POST['password'] ?? ''), $found['password_hash'])) {
|
if ($found && password_verify((string)($_POST['password'] ?? ''), $found['password_hash'])) {
|
||||||
|
addAuditLog($pdo, (int)$found['id'], 'Anmeldung erfolgreich.');
|
||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
$_SESSION['user'] = ['id' => (int)$found['id'], 'firstname' => $found['firstname'] ?? '', 'lastname' => $found['lastname'] ?? '', 'name' => displayName($found), 'email' => $found['email'], 'role' => $found['role']];
|
$_SESSION['user'] = ['id' => (int)$found['id'], 'firstname' => $found['firstname'] ?? '', 'lastname' => $found['lastname'] ?? '', 'name' => displayName($found), 'email' => $found['email'], 'role' => $found['role']];
|
||||||
header('Location: /?page=dashboard');
|
header('Location: /?page=dashboard');
|
||||||
@@ -803,6 +804,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$error = 'SQL-Dump ist ohne Datenbank nicht verfuegbar.';
|
$error = 'SQL-Dump ist ohne Datenbank nicht verfuegbar.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($user && $action === 'export_logs_csv' && $user['role'] === 'admin') {
|
||||||
|
if ($pdo) {
|
||||||
|
addAuditLog($pdo, (int)$user['id'], 'Logansicht als CSV exportiert.');
|
||||||
|
$filename = 'log-export-' . date('Y-m-d-His') . '.csv';
|
||||||
|
header('Content-Type: text/csv; charset=utf-8');
|
||||||
|
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||||
|
$output = fopen('php://output', 'wb');
|
||||||
|
if ($output !== false) {
|
||||||
|
fwrite($output, "\xEF\xBB\xBF");
|
||||||
|
$rows = $pdo->query('(SELECT w.created_at AS ts, CONCAT(a.firstname, " ", a.lastname) AS actor, CONCAT(w.hours, " Stunden für ", m.firstname, " ", m.lastname, " gebucht: ", w.note) AS action FROM work_logs w JOIN users a ON a.id = w.actor_id JOIN users m ON m.id = w.member_id) UNION ALL (SELECT l.created_at AS ts, CONCAT(a.firstname, " ", a.lastname) AS actor, l.action FROM audit_logs l JOIN users a ON a.id = l.actor_id) ORDER BY ts DESC')->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
if ($rows) {
|
||||||
|
fputcsv($output, array_keys($rows[0]));
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
fputcsv($output, $row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose($output);
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$error = 'Log-Export ist ohne Datenbank nicht verfuegbar.';
|
||||||
|
}
|
||||||
|
|
||||||
if ($user && $action === 'import_sql_dump' && $user['role'] === 'admin') {
|
if ($user && $action === 'import_sql_dump' && $user['role'] === 'admin') {
|
||||||
if (!$pdo) {
|
if (!$pdo) {
|
||||||
$error = 'SQL-Wiederherstellung ist ohne Datenbank nicht verfuegbar.';
|
$error = 'SQL-Wiederherstellung ist ohne Datenbank nicht verfuegbar.';
|
||||||
@@ -902,6 +926,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($user && $action === 'logout') {
|
if ($user && $action === 'logout') {
|
||||||
|
addAuditLog($pdo, (int)$user['id'], 'Abmeldung erfolgt.');
|
||||||
session_destroy();
|
session_destroy();
|
||||||
header('Location: /?page=login');
|
header('Location: /?page=login');
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
@@ -671,7 +671,7 @@ function renderAppShell(string $page): void
|
|||||||
<div class="col-lg-12"><div class="card"><div class="card-body admin-actions"><h3 class="section-title"><i class="ti ti-file-import"></i><span>CSV-Import</span></h3><p class="text-secondary">Importiert Benutzerdaten aus einer CSV-Datei mit den Spalten <strong>firstname</strong>, <strong>lastname</strong>, <strong>email</strong>, <strong>role</strong> und <strong>hours_worked</strong>.</p><div class="text-secondary small mb-3"><strong>Beispiel-Kopfzeile:</strong> <code>firstname,lastname,email,role,hours_worked</code></div><form method="post" enctype="multipart/form-data"><input type="hidden" name="action" value="import_csv"><div class="mb-3"><input class="form-control" name="csv_file" type="file" accept=".csv,text/csv" required></div><button class="btn btn-primary" type="submit">Benutzerdaten aus CSV importieren</button></form></div></div></div>
|
<div class="col-lg-12"><div class="card"><div class="card-body admin-actions"><h3 class="section-title"><i class="ti ti-file-import"></i><span>CSV-Import</span></h3><p class="text-secondary">Importiert Benutzerdaten aus einer CSV-Datei mit den Spalten <strong>firstname</strong>, <strong>lastname</strong>, <strong>email</strong>, <strong>role</strong> und <strong>hours_worked</strong>.</p><div class="text-secondary small mb-3"><strong>Beispiel-Kopfzeile:</strong> <code>firstname,lastname,email,role,hours_worked</code></div><form method="post" enctype="multipart/form-data"><input type="hidden" name="action" value="import_csv"><div class="mb-3"><input class="form-control" name="csv_file" type="file" accept=".csv,text/csv" required></div><button class="btn btn-primary" type="submit">Benutzerdaten aus CSV importieren</button></form></div></div></div>
|
||||||
<div class="col-lg-12"><div class="card"><div class="card-body admin-actions"><h3 class="section-title"><i class="ti ti-rotate-clockwise-2"></i><span>Arbeitsstunden zurücksetzen</span></h3><p class="text-secondary">Setzt alle gebuchten Arbeitsstunden für alle Mitglieder auf 0. Diese Aktion ist für den Jahreswechsel gedacht.</p><form method="post" onsubmit="return confirm('Wirklich alle Arbeitsstunden auf 0 zurücksetzen?');"><input type="hidden" name="action" value="reset_all_hours"><button class="btn btn-outline-danger" type="submit">Alle Arbeitsstunden auf 0 setzen</button></form></div></div></div>
|
<div class="col-lg-12"><div class="card"><div class="card-body admin-actions"><h3 class="section-title"><i class="ti ti-rotate-clockwise-2"></i><span>Arbeitsstunden zurücksetzen</span></h3><p class="text-secondary">Setzt alle gebuchten Arbeitsstunden für alle Mitglieder auf 0. Diese Aktion ist für den Jahreswechsel gedacht.</p><form method="post" onsubmit="return confirm('Wirklich alle Arbeitsstunden auf 0 zurücksetzen?');"><input type="hidden" name="action" value="reset_all_hours"><button class="btn btn-outline-danger" type="submit">Alle Arbeitsstunden auf 0 setzen</button></form></div></div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row row-cards mt-2"><div class="col-lg-12"><div class="card"><div class="card-body"><h3 class="section-title"><i class="ti ti-history"></i><span>Logansicht</span></h3><ul class="list-group list-group-flush"><?php foreach (($logs['entries'] ?? []) as $entry): ?><li class="list-group-item px-0"><strong><?= htmlspecialchars($entry['ts']) ?></strong><br><?= htmlspecialchars($entry['actor']) ?>: <?= htmlspecialchars($entry['action']) ?></li><?php endforeach; ?><?php if (empty($logs['entries'])): ?><li class="list-group-item px-0 text-secondary">Keine Logeinträge vorhanden.</li><?php endif; ?></ul><?php if (($logs['total_pages'] ?? 1) > 1): ?><div class="d-flex align-items-center justify-content-between gap-3 mt-3"><a class="btn btn-outline-secondary<?= ($logs['page'] ?? 1) <= 1 ? ' disabled' : '' ?>" href="/?page=administration&log_page=<?= max(1, (int)($logs['page'] ?? 1) - 1) ?>">Zurück</a><div class="text-secondary small">Seite <?= (int)($logs['page'] ?? 1) ?> von <?= (int)($logs['total_pages'] ?? 1) ?>, insgesamt <?= (int)($logs['total'] ?? 0) ?> Einträge</div><a class="btn btn-outline-secondary<?= ($logs['page'] ?? 1) >= ($logs['total_pages'] ?? 1) ? ' disabled' : '' ?>" href="/?page=administration&log_page=<?= min((int)($logs['total_pages'] ?? 1), (int)($logs['page'] ?? 1) + 1) ?>">Weiter</a></div><?php endif; ?></div></div></div></div>
|
<div class="row row-cards mt-2"><div class="col-lg-12"><div class="card"><div class="card-body admin-actions"><h3 class="section-title"><i class="ti ti-history"></i><span>Logansicht</span></h3><form method="post" class="mb-3"><input type="hidden" name="action" value="export_logs_csv"><button class="btn btn-primary" type="submit">Log als CSV exportieren</button></form><ul class="list-group list-group-flush"><?php foreach (($logs['entries'] ?? []) as $entry): ?><li class="list-group-item px-0"><strong><?= htmlspecialchars($entry['ts']) ?></strong><br><?= htmlspecialchars($entry['actor']) ?>: <?= htmlspecialchars($entry['action']) ?></li><?php endforeach; ?><?php if (empty($logs['entries'])): ?><li class="list-group-item px-0 text-secondary">Keine Logeinträge vorhanden.</li><?php endif; ?></ul><?php if (($logs['total_pages'] ?? 1) > 1): ?><div class="d-flex align-items-center justify-content-between gap-3 mt-3"><a class="btn btn-outline-secondary<?= ($logs['page'] ?? 1) <= 1 ? ' disabled' : '' ?>" href="/?page=administration&log_page=<?= max(1, (int)($logs['page'] ?? 1) - 1) ?>">Zurück</a><div class="text-secondary small">Seite <?= (int)($logs['page'] ?? 1) ?> von <?= (int)($logs['total_pages'] ?? 1) ?>, insgesamt <?= (int)($logs['total'] ?? 0) ?> Einträge</div><a class="btn btn-outline-secondary<?= ($logs['page'] ?? 1) >= ($logs['total_pages'] ?? 1) ? ' disabled' : '' ?>" href="/?page=administration&log_page=<?= min((int)($logs['total_pages'] ?? 1), (int)($logs['page'] ?? 1) + 1) ?>">Weiter</a></div><?php endif; ?></div></div></div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user