PHP_AdminTool_Projekt/app/Controllers/AuthController.php
blaerf 9a8d90a6db feature/logging_Service (#17)
Reviewed-on: https://git.eckertplayground.de/taarly/PHP_AdminTool_Projekt/pulls/17
Co-authored-by: blaerf <blaerf@gmx.de>
Co-committed-by: blaerf <blaerf@gmx.de>
2025-12-05 07:42:10 +00:00

165 lines
6.2 KiB
PHP

<?php
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
declare(strict_types=1);
namespace App\Controllers;
use App\Services\Ldap\LdapAuthService;
use App\Services\Logging\LoggingService;
use Throwable;
/**
* Zuständig für alles rund um den Login:
* - Login-Formular anzeigen
* - Login-Daten verarbeiten (Authentifizierung gegen LDAP/AD)
* - Logout durchführen
*
* NEU:
* - Statt direkt HTML auszugeben oder header()-Redirects zu setzen,
* liefert der Controller "View-Results" zurück, die von index.php
* und einem zentralen Layout verarbeitet werden.
*/
class AuthController
{
/** @var array<string, mixed> Konfigurationswerte der Anwendung (aus config.php) */
private array $config;
/** @var LdapAuthService Service, der die eigentliche LDAP/AD-Authentifizierung übernimmt */
private LdapAuthService $ldapAuthService;
/** @var LoggingService Logger für technische Fehler */
private LoggingService $logger;
/**
* Übergibt die Konfiguration an den Controller und initialisiert den LDAP-Authentifizierungsservice.
*
* @param array<string, mixed> $config Vollständige Konfiguration aus config.php
*/
public function __construct(array $config)
{
// Komplette Config in der Instanz speichern (z. B. für Zugriff auf security- oder ldap-Settings)
$this->config = $config;
// LdapAuthService mit dem Teilbereich "ldap" aus der Konfiguration initialisieren.
// Wenn 'ldap' nicht gesetzt ist, wird ein leeres Array übergeben (Fail fast erfolgt dann im Service).
$this->ldapAuthService = new LdapAuthService($config['ldap'] ?? []);
// LoggingService mit dem Teilbereich "logging" aus der Konfiguration initialisieren.
$this->logger = new LoggingService($config['logging'] ?? []);
}
/**
* Zeigt das Login-Formular an.
* Optional kann eine Fehlermeldung übergeben werden, die in der View dargestellt wird.
*
* @return array<string, mixed> View-Result für das zentrale Layout
*/
public function showLoginForm(?string $errorMessage = null): array
{
// Pfad zur Login-View (Template-Datei) ermitteln.
$viewPath = __DIR__ . '/../../public/views/login.php';
// Wichtig: Die View erwartet aktuell die Variable $error.
return [
'view' => $viewPath,
'data' => [
'error' => $errorMessage,
'loginPage' => true,
],
'pageTitle' => 'Login',
// Beim Login ist typischerweise kein Menüpunkt aktiv.
'activeMenu' => null,
];
}
/**
* Verarbeitet das Login-Formular:
* - Liest Benutzername und Passwort aus $_POST
* - Ruft den LdapAuthService zur Authentifizierung auf
* - Liefert bei Erfolg ein Redirect-Result zum Dashboard
* - Liefert bei Fehlern ein View-Result für das Login-Formular mit Fehlermeldung
*
* @return array<string, mixed> View-Result ODER Redirect-Result
*/
public function processLogin(): array
{
// Formulardaten aus dem POST-Request lesen.
$username = trim($_POST['username'] ?? '');
$password = (string)($_POST['password'] ?? '');
try {
// Versuch, den Benutzer per LDAP/AD zu authentifizieren.
// true = Authentifizierung erfolgreich
// false = Anmeldedaten fachlich ungültig (Benutzer/Passwort falsch)
$authenticated = $this->ldapAuthService->authenticate($username, $password);
} catch (Throwable $exception) {
// HIER ist vorher dein Fehler entstanden:
// - showLoginForm() wurde nur aufgerufen, das Ergebnis aber ignoriert
// - danach kam ein "return;" ohne Rückgabewert → Rückgabetyp array wurde verletzt
// Technischen Fehler ausführlich ins Log schreiben
$this->logger->logException(
'Technischer Fehler bei der Anmeldung.',
$exception,
[
'route' => 'login.submit',
'username' => $username,
'remote_addr'=> $_SERVER['REMOTE_ADDR'] ?? null,
]
);
// Für den Benutzer nur eine allgemeine, aber verständliche Meldung anzeigen
return $this->showLoginForm(
'Technischer Fehler bei der Anmeldung. Bitte versuchen Sie es später erneut '
. 'oder wenden Sie sich an den Administrator.'
);
}
// Fachlich fehlgeschlagene Anmeldung (z. B. falsches Passwort).
if ($authenticated === false) {
return $this->showLoginForm('Benutzername oder Passwort ist ungültig.');
}
// Ab hier ist die Anmeldung erfolgreich.
// Session-Key für den eingeloggten Benutzer aus der Konfiguration lesen.
// Wenn nicht gesetzt, wird "admin_user" als Standard verwendet.
$sessionKey = $this->config['security']['session_key_user'] ?? 'admin_user';
// Benutzerinformationen in der Session hinterlegen.
// Diese Daten werden später von requireLogin() bzw. im Layout ausgewertet.
$_SESSION[$sessionKey] = [
'username' => $username,
'login_at' => date('c'), // ISO-8601 Datum/Zeit der Anmeldung
];
// Nach erfolgreicher Anmeldung zum Dashboard weiterleiten.
// Kein direkter header()-Aufruf, sondern ein Redirect-Result
// für die zentrale Steuerung in index.php.
return [
'redirect' => 'index.php?route=dashboard',
];
}
/**
* Meldet den aktuell eingeloggten Benutzer ab, indem der entsprechende Session-Eintrag entfernt wird,
* und liefert anschließend ein Redirect-Result zurück auf die Login-Seite.
*
* @return array<string, mixed> Redirect-Result
*/
public function logout(): array
{
// Session-Key für den eingeloggten Benutzer aus der Konfiguration lesen.
$sessionKey = $this->config['security']['session_key_user'] ?? 'admin_user';
// Eintrag aus der Session entfernen → Benutzer gilt als ausgeloggt.
unset($_SESSION[$sessionKey]);
// Redirect-Result zur Login-Seite.
return [
'redirect' => 'index.php?route=login',
];
}
}