Files
Felix KemmlerandClaude Sonnet 5 b6c1389c55 Reorganize into monorepo layout, move mitarbeiter-app to legacy reference
Consolidates the previously separate omsorgapp and omsorgCore repos
(each had their own nested .git with GitHub history) plus the old
root-level website/mitarbeiter-app into a single monorepo, matching
the structure already documented in the root CLAUDE.md. Also moves
the PHP employee app aside as omsorgWeb/mitarbeiter-app-legacy/ to
serve as a template for a ground-up rewrite.

Fixes .gitignore in the same pass: the config-secrets/uploads/data
patterns were unanchored (relative to repo root, not depth-agnostic),
so they silently stopped matching once the app moved under omsorgWeb/.
Patterns are now **/-prefixed and cover both mitarbeiter-app and
mitarbeiter-app-legacy, keeping DB/SMTP credentials and uploaded
employee documents out of version control.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 14:21:37 +02:00

172 lines
7.5 KiB
PHP

<?php
require_once __DIR__ . '/../lib/auth.php';
require_admin();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: ../pages/admin.php');
exit;
}
/* ── Login attempts ────────────────────────────────────────────────── */
if (($_POST['_login_action'] ?? '') === 'clear') {
db()->exec('DELETE FROM login_attempts');
header('Location: ../pages/admin.php?tab=login&cleared=1');
exit;
}
/* ── User actions ──────────────────────────────────────────────────── */
if (!empty($_POST['_user_action'])) {
$action = $_POST['_user_action'];
$user_id = (int)($_POST['user_id'] ?? 0);
$back = '../pages/admin.php?tab=nutzer';
switch ($action) {
case 'add_user': {
$username = trim($_POST['username'] ?? '');
$uname = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$telefon = trim($_POST['telefon'] ?? '');
$role = in_array($_POST['role'] ?? '', ['user', 'admin'], true) ? $_POST['role'] : 'user';
$password = $_POST['password'] ?? '';
if ($username === '' || $uname === '' || strlen($password) < 6) {
header('Location: ' . $back . '&user_msg=' . urlencode('Benutzername, Name und Passwort (mind. 6 Zeichen) sind Pflichtfelder.'));
exit;
}
try {
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$stmt = db()->prepare(
'INSERT INTO users (username, name, role, password_hash, active, created_at, email, telefon)
VALUES (?, ?, ?, ?, 1, ?, ?, ?)'
);
$stmt->execute([$username, $uname, $role, $hash, date('c'), $email, $telefon]);
} catch (\PDOException $ex) {
$msg = str_contains($ex->getMessage(), 'UNIQUE') ? 'Benutzername bereits vergeben.' : 'Datenbankfehler.';
header('Location: ' . $back . '&user_msg=' . urlencode($msg));
exit;
}
header('Location: ' . $back . '&user_ok=1&user_msg=' . urlencode('Nutzer erstellt.'));
exit;
}
case 'edit_user': {
$uname = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$telefon = trim($_POST['telefon'] ?? '');
$role = in_array($_POST['role'] ?? '', ['user', 'admin'], true) ? $_POST['role'] : 'user';
$active = (int)(bool)($_POST['active'] ?? 0);
if ($user_id < 1 || $uname === '') {
header('Location: ' . $back . '&user_msg=' . urlencode('Ungültige Eingabe.'));
exit;
}
$stmt = db()->prepare(
'UPDATE users SET name=?, email=?, telefon=?, role=?, active=? WHERE id=?'
);
$stmt->execute([$uname, $email, $telefon, $role, $active, $user_id]);
header('Location: ' . $back . '&user_ok=1&user_msg=' . urlencode('Nutzer gespeichert.'));
exit;
}
case 'change_password': {
$password = $_POST['new_password'] ?? '';
if ($user_id < 1 || strlen($password) < 6) {
header('Location: ' . $back . '&user_msg=' . urlencode('Passwort muss mindestens 6 Zeichen lang sein.'));
exit;
}
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$stmt = db()->prepare('UPDATE users SET password_hash=? WHERE id=?');
$stmt->execute([$hash, $user_id]);
header('Location: ' . $back . '&user_ok=1&user_msg=' . urlencode('Passwort geändert.'));
exit;
}
case 'delete_user': {
if ($user_id < 1) {
header('Location: ' . $back . '&user_msg=' . urlencode('Ungültige Nutzer-ID.'));
exit;
}
$stmt = db()->prepare('SELECT username FROM users WHERE id=?');
$stmt->execute([$user_id]);
$row = $stmt->fetch();
if (!$row) {
header('Location: ' . $back . '&user_msg=' . urlencode('Nutzer nicht gefunden.'));
exit;
}
if ($row['username'] === current_username()) {
header('Location: ' . $back . '&user_msg=' . urlencode('Den eigenen Account kann man nicht löschen.'));
exit;
}
$stmt = db()->prepare('DELETE FROM users WHERE id=?');
$stmt->execute([$user_id]);
header('Location: ' . $back . '&user_ok=1&user_msg=' . urlencode('Nutzer gelöscht.'));
exit;
}
default:
header('Location: ' . $back . '&user_msg=' . urlencode('Unbekannte Aktion.'));
exit;
}
}
/* ── Request actions ───────────────────────────────────────────────── */
$request_id = (int)($_POST['request_id'] ?? 0);
$action = $_POST['action'] ?? '';
$admin_note = trim($_POST['admin_note'] ?? '');
$type = $_POST['type'] ?? '';
$allowed_types = ['urlaubsantrag', 'abwesenheitsantrag', 'benefitsantrag', 'werben', 'fortbildungsantrag', 'stundennachweis'];
if (!in_array($type, $allowed_types, true)) {
header('Location: ../pages/admin.php?error=' . urlencode('Ungültiger Antragstyp.'));
exit;
}
/* ── Delete request ────────────────────────────────────────────────── */
if ($action === 'delete') {
if ($request_id < 1) {
header('Location: ../pages/admin.php?error=' . urlencode('Ungültige Antrags-ID.'));
exit;
}
$table = 'requests_' . $type;
$stmt = db()->prepare("SELECT * FROM $table WHERE id = ?");
$stmt->execute([$request_id]);
$row = $stmt->fetch();
if (!$row) {
header('Location: ../pages/admin.php?error=' . urlencode('Antrag nicht gefunden.'));
exit;
}
// Delete associated file for types that have uploads
if (in_array($type, ['stundennachweis', 'fortbildungsantrag'], true) && !empty($row['filename'])) {
$file_path = __DIR__ . '/../uploads/' . $row['filename'];
if (is_file($file_path)) {
unlink($file_path);
}
}
$stmt = db()->prepare("DELETE FROM $table WHERE id = ?");
$stmt->execute([$request_id]);
header('Location: ../pages/admin.php?deleted=1');
exit;
}
/* ── Status update ─────────────────────────────────────────────────── */
if (!in_array($action, ['accepted', 'rejected'], true) || $request_id < 1) {
header('Location: ../pages/admin.php?error=' . urlencode('Ungültige Aktion.'));
exit;
}
$table = 'requests_' . $type;
$stmt = db()->prepare("SELECT id FROM $table WHERE id = ?");
$stmt->execute([$request_id]);
if (!$stmt->fetch()) {
header('Location: ../pages/admin.php?error=' . urlencode('Antrag nicht gefunden.'));
exit;
}
$stmt = db()->prepare("UPDATE $table SET status = ?, admin_note = ?, updated_at = ? WHERE id = ?");
$stmt->execute([$action, $admin_note, date('c'), $request_id]);
header('Location: ../pages/admin.php?type=' . urlencode($type) . '&id=' . $request_id . '&updated=1');
exit;