248 lines
8.1 KiB
PHP
248 lines
8.1 KiB
PHP
<?php
|
|
|
|
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Front-Controller der Webanwendung.
|
|
*
|
|
* Aufgaben:
|
|
* - Startet die Session und initialisiert den Autoloader für den App-Namespace.
|
|
* - Lädt die zentrale Konfiguration aus config/config.php.
|
|
* - Instanziiert die Hauptcontroller (Auth, Dashboard, User-Management).
|
|
* - Steuert das Routing anhand des GET-Parameters "route".
|
|
* - Leitet View-Result-Arrays an das zentrale Layout (renderLayout) weiter
|
|
* oder führt Redirects aus.
|
|
*
|
|
* WICHTIG:
|
|
* - Diese Datei ist der einzige öffentliche Einstiegspunkt (Entry Point) der App.
|
|
* - Alle neuen Routen sollten über den Switch-Block am Ende ergänzt werden.
|
|
*/
|
|
|
|
// Eine neue Session wird gestartet und die entsprechende Variable ($_SESSION) angelegt
|
|
// oder eine bestehende wird fortgesetzt.
|
|
session_start();
|
|
|
|
// PHP-Fehler erfassen, aber veraltete Hinweise (E_DEPRECATED) ignorieren,
|
|
// weil sie sonst im Zusammenspiel mit IIS/fastcgi zu 500-Fehlern führen können.
|
|
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
|
ini_set('display_errors', '0');
|
|
|
|
/*
|
|
* Registriert eine Autoload-Funktion für Klassen mit dem Namespace-Präfix "App\".
|
|
* Statt jede Klasse manuell über "require pfad_zur_klasse.php" einzubinden,
|
|
* versucht PHP nun automatisch, die passende Datei zu laden, sobald eine Klasse
|
|
* im Namespace "App\..." verwendet wird.
|
|
*/
|
|
spl_autoload_register(
|
|
static function (string $class): void {
|
|
$prefix = 'App\\';
|
|
$baseDir = __DIR__ . '/../app/';
|
|
|
|
$len = strlen($prefix);
|
|
if (strncmp($prefix, $class, $len) !== 0) {
|
|
return;
|
|
}
|
|
|
|
$relativeClass = substr($class, $len);
|
|
$file = $baseDir . str_replace('\\', DIRECTORY_SEPARATOR, $relativeClass) . '.php';
|
|
|
|
if (file_exists($file) === true) {
|
|
require $file;
|
|
}
|
|
}
|
|
);
|
|
|
|
// Layout-Funktion einbinden (renderLayout)
|
|
require __DIR__ . '/views/layout.php';
|
|
|
|
// Die Konfigurationsdatei liefert ein assoziatives Array mit den Teilbereichen
|
|
// "ldap", "snmp", "security" und "logging" (u. a. Session-Keys, Timeout-Einstellungen, OIDs, Log-Pfade).
|
|
$configPath = __DIR__ . '/../config/config.php';
|
|
if (file_exists($configPath) === false) {
|
|
// Fail fast: ohne Konfiguration macht die App keinen Sinn
|
|
http_response_code(500);
|
|
echo 'Konfigurationsdatei config/config.php wurde nicht gefunden. '
|
|
. 'Bitte config.example.php kopieren und anpassen.';
|
|
exit;
|
|
}
|
|
|
|
/** @var array<string, mixed> $config */
|
|
$config = require $configPath;
|
|
|
|
use App\Controllers\AuthController;
|
|
use App\Controllers\DashboardController;
|
|
use App\Controllers\UserManagementController;
|
|
use App\Services\Logging\LoggingService;
|
|
|
|
// Globalen Logger initialisieren, damit auch Fehler außerhalb der Controller
|
|
// (z. B. in index.php selbst) sauber protokolliert werden.
|
|
$globalLogger = new LoggingService($config['logging'] ?? []);
|
|
|
|
/**
|
|
* Globale Fehlerbehandlung:
|
|
* - PHP-Fehler (Warnings, Notices, ...) werden in den Logger geschrieben.
|
|
* - Unbehandelte Exceptions werden ebenfalls geloggt und führen zu einer generischen 500er-Meldung.
|
|
*/
|
|
set_error_handler(
|
|
static function (
|
|
int $severity,
|
|
string $message,
|
|
string $file = '',
|
|
int $line = 0
|
|
) use ($globalLogger): bool {
|
|
// Fehler nur loggen, wenn sie durch error_reporting() nicht unterdrückt sind.
|
|
if ((error_reporting() & $severity) === 0) {
|
|
return false;
|
|
}
|
|
|
|
$globalLogger->log(
|
|
'error',
|
|
'PHP-Fehler: ' . $message,
|
|
[
|
|
'severity' => $severity,
|
|
'file' => $file,
|
|
'line' => $line,
|
|
]
|
|
);
|
|
|
|
// false zurückgeben = PHP darf seinen Standard-Handler zusätzlich verwenden
|
|
// (der Browser sieht wegen display_errors=0 trotzdem nichts).
|
|
return false;
|
|
}
|
|
);
|
|
|
|
set_exception_handler(
|
|
static function (\Throwable $exception) use ($globalLogger): void {
|
|
$globalLogger->logException(
|
|
'Unbehandelte Exception in der Anwendung.',
|
|
$exception,
|
|
[
|
|
'request_uri' => $_SERVER['REQUEST_URI'] ?? null,
|
|
'route' => $_GET['route'] ?? null,
|
|
]
|
|
);
|
|
|
|
http_response_code(500);
|
|
echo 'Es ist ein unerwarteter Fehler aufgetreten. '
|
|
. 'Bitte versuchen Sie es später erneut oder wenden Sie sich an den Administrator.';
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Hilfsfunktion: Prüft, ob ein Benutzer eingeloggt ist.
|
|
* Wenn nicht, wird auf die Login-Seite umgeleitet.
|
|
*
|
|
* @param array<string, mixed> $config
|
|
*/
|
|
function requireLogin(array $config): void
|
|
{
|
|
// session_key_user aus dem Config-Array lesen. Wenn nicht gesetzt oder null, Standard "admin_user" verwenden.
|
|
$sessionKey = $config['security']['session_key_user'] ?? 'admin_user';
|
|
|
|
// Prüfen, ob in $_SESSION unter diesem Key ein eingeloggter Benutzer hinterlegt ist.
|
|
// Falls nicht, zurück zur Login-Seite umleiten.
|
|
if (isset($_SESSION[$sessionKey]) === false) {
|
|
header('Location: index.php?route=login');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verarbeitet ein View-Result oder Redirect-Result.
|
|
*
|
|
* @param array<string, mixed>|null $result
|
|
*/
|
|
function handleResult(?array $result): void
|
|
{
|
|
if ($result === null) {
|
|
return;
|
|
}
|
|
|
|
// Redirect-Result
|
|
if (isset($result['redirect']) === true) {
|
|
header('Location: ' . (string)$result['redirect']);
|
|
exit;
|
|
}
|
|
|
|
// View-Result
|
|
$contentView = (string)($result['view'] ?? '');
|
|
$viewData = (array)($result['data'] ?? []);
|
|
|
|
// Standard: Wir gehen davon aus, dass es KEINE Loginseite ist,
|
|
// außer der Controller sagt explizit etwas anderes.
|
|
if (array_key_exists('loginPage', $viewData) === false) {
|
|
$viewData['loginPage'] = false;
|
|
}
|
|
|
|
$pageTitle = (string)($result['pageTitle'] ?? '');
|
|
$activeMenu = $result['activeMenu'] ?? null;
|
|
|
|
if ($contentView === '' || file_exists($contentView) === false) {
|
|
http_response_code(500);
|
|
echo 'Interner Fehler: Content-View wurde nicht gefunden.';
|
|
exit;
|
|
}
|
|
|
|
// Hier rufen wir jetzt die Layout-Funktion aus layout.php auf
|
|
renderLayout(
|
|
$contentView,
|
|
$viewData,
|
|
$pageTitle,
|
|
is_string($activeMenu) ? $activeMenu : null
|
|
);
|
|
}
|
|
|
|
// Zentrale Controller der Anwendung initialisieren und ihnen die vollständige Konfiguration übergeben.
|
|
// Die Controller holen sich daraus bei Bedarf ihre spezifischen Teilkonfigurationen (z. B. "ldap" oder "snmp").
|
|
// Jeder Controller erzeugt intern seinen eigenen LoggingService aus $config['logging'].
|
|
$authController = new AuthController($config);
|
|
$dashboardController = new DashboardController($config);
|
|
$userManagementController = new UserManagementController($config);
|
|
|
|
// Route aus dem Query-Parameter lesen. Standardroute ist "login",
|
|
// sodass nicht angemeldete Benutzer automatisch auf die Login-Seite geführt werden.
|
|
$route = $_GET['route'] ?? 'login';
|
|
|
|
// Einfache Router-Logik: Jede Route ruft eine Controller-Methode auf und
|
|
// übergibt deren View-Result an handleResult(). Neue Seiten werden hier ergänzt.
|
|
switch ($route) {
|
|
case 'login':
|
|
// Login-Formular anzeigen (ggf. mit Fehlermeldung)
|
|
$result = $authController->showLoginForm();
|
|
handleResult($result);
|
|
break;
|
|
|
|
case 'login.submit':
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
// Falscher HTTP-Verb: einfach zurück zum Login
|
|
header('Location: index.php?route=login');
|
|
exit;
|
|
}
|
|
$result = $authController->processLogin();
|
|
handleResult($result);
|
|
break;
|
|
|
|
case 'logout':
|
|
$result = $authController->logout();
|
|
handleResult($result);
|
|
break;
|
|
|
|
case 'dashboard':
|
|
requireLogin($config);
|
|
$result = $dashboardController->show();
|
|
handleResult($result);
|
|
break;
|
|
|
|
case 'users':
|
|
requireLogin($config);
|
|
$result = $userManagementController->show();
|
|
handleResult($result);
|
|
break;
|
|
|
|
default:
|
|
http_response_code(404);
|
|
echo 'Route nicht gefunden.';
|
|
break;
|
|
}
|