- 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
107 lines
3.1 KiB
PHP
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();
|
|
}
|
|
}
|