Steuerkram/src/Controllers/UserAdminController.php
fds2610 a338631dbd Session-basierte Authentifizierung + Benutzerverwaltung
- HTTP Basic Auth durch cookie-basierte Session-Auth ersetzt (24 h absolutes Timeout)
- Neue users-Tabelle (Migration 005) mit bcrypt-Passwort-Hashing
- Login-/Logout-Routen und eigenständiges Login-Template
- Ersteinrichtungsflow: erster Benutzer beim ersten Start direkt über /login anlegen
- Neuer Menüpunkt "Benutzer" (/useradmin) zum Anlegen, Deaktivieren und Löschen von Benutzern
- AUTH_USER/AUTH_PASS aus Konfiguration und docker-compose.yml entfernt
2026-03-25 15:28:07 +01:00

107 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Steuerkram\Controllers;
use Steuerkram\Models\User;
use Steuerkram\View;
class UserAdminController
{
public function index(array $params): void
{
$users = User::all();
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Benutzerverwaltung',
'content' => $this->renderView('useradmin/list', [
'users' => $users,
'errors' => [],
]),
]);
}
public function store(array $params): void
{
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
$errors = [];
if ($username === '') {
$errors['username'] = 'Pflichtfeld';
} elseif (strlen($username) > 64) {
$errors['username'] = 'Maximal 64 Zeichen';
} elseif (User::findByUsername($username)) {
$errors['username'] = 'Benutzername bereits vergeben';
}
if (strlen($password) < 8) {
$errors['password'] = 'Mindestens 8 Zeichen erforderlich';
}
if ($errors) {
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Benutzerverwaltung',
'content' => $this->renderView('useradmin/list', [
'users' => User::all(),
'errors' => $errors,
'formData' => ['username' => $username],
]),
]);
return;
}
User::create($username, $password);
View::redirect('/useradmin', 'Benutzer angelegt.');
}
public function delete(array $params): void
{
$id = (int)($params['id'] ?? 0);
// Letzten aktiven Benutzer nicht löschen
if (User::count() <= 1) {
View::redirect('/useradmin', 'Der letzte Benutzer kann nicht gelöscht werden.', 'error');
return;
}
User::delete($id);
View::redirect('/useradmin', 'Benutzer gelöscht.');
}
public function toggleActive(array $params): void
{
$id = (int)($params['id'] ?? 0);
$user = User::find($id);
if (!$user) {
View::redirect('/useradmin', 'Benutzer nicht gefunden.', 'error');
return;
}
$newState = !(bool)$user['active'];
// Letzten aktiven Benutzer nicht deaktivieren
if (!$newState) {
$activeCount = count(array_filter(User::all(), fn($u) => $u['active']));
if ($activeCount <= 1) {
View::redirect('/useradmin', 'Der letzte aktive Benutzer kann nicht deaktiviert werden.', 'error');
return;
}
}
User::setActive($id, $newState);
$msg = $newState ? 'Benutzer aktiviert.' : 'Benutzer deaktiviert.';
View::redirect('/useradmin', $msg);
}
private function renderView(string $template, array $data): string
{
extract($data, EXTR_SKIP);
ob_start();
include dirname(__DIR__) . '/Views/' . $template . '.php';
return ob_get_clean();
}
}