Stand: SMTP-Test, Admin-Mail-Tab, Notifiable-Fix, Lazy-Quill

- Fix: Notifiable-Trait zum User-Model hinzugefuegt (behebt notify()-500er)
- Installer: SMTP-Verbindungstest mit EsmtpTransport + Ueberspringen-Link
- Admin: Neuer E-Mail-Tab mit SMTP-Konfiguration + Verbindungstest
- Admin: Lazy Quill-Initialisierung (nur sichtbare Locale wird geladen)
- Uebersetzungen: 17 neue Mail-Keys in allen 6 Sprachen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Rhino
2026-03-02 07:30:37 +01:00
commit 2e24a40d68
9633 changed files with 1300799 additions and 0 deletions

72
bootstrap/app.php Executable file
View File

@@ -0,0 +1,72 @@
<?php
use App\Http\Middleware\ActiveUserMiddleware;
use App\Http\Middleware\AdminMiddleware;
use App\Http\Middleware\AdminOnlyMiddleware;
use App\Http\Middleware\DsgvoConsentMiddleware;
use App\Http\Middleware\InstallerMiddleware;
use App\Http\Middleware\SecurityHeadersMiddleware;
use App\Http\Middleware\SetLocaleMiddleware;
use App\Http\Middleware\StaffMiddleware;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withProviders()
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'admin' => AdminMiddleware::class,
'admin-only' => AdminOnlyMiddleware::class,
'staff' => StaffMiddleware::class,
'active' => ActiveUserMiddleware::class,
'dsgvo' => DsgvoConsentMiddleware::class,
]);
// InstallerMiddleware NACH StartSession (nicht prepend), damit
// das Setup-Token in der Session gespeichert werden kann.
// AppServiceProvider::register() setzt session.driver='file'
// vor der Installation, daher braucht StartSession keine DB.
$middleware->web(append: [
InstallerMiddleware::class,
SetLocaleMiddleware::class,
ActiveUserMiddleware::class,
SecurityHeadersMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
// Waehrend der Installation: Fehler ohne View-Engine rendern.
// Verhindert den kaskadierenden "Target class [view]"-Fehler,
// falls ein Provider-Fehler auftritt bevor Views verfuegbar sind.
$exceptions->render(function (\Throwable $e, \Illuminate\Http\Request $request) {
if (file_exists(storage_path('installed'))) {
return null; // Nach Installation: Standard-Handler
}
$msg = htmlspecialchars($e->getMessage());
$file = htmlspecialchars($e->getFile()) . ':' . $e->getLine();
$trace = htmlspecialchars($e->getTraceAsString());
$html = '<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8">'
. '<meta name="viewport" content="width=device-width, initial-scale=1.0">'
. '<title>Installationsfehler</title>'
. '<script src="https://cdn.tailwindcss.com"></script></head>'
. '<body class="min-h-screen bg-gray-100 flex items-center justify-center p-4">'
. '<div class="max-w-2xl w-full bg-white rounded-lg shadow-md p-6">'
. '<h1 class="text-lg font-bold text-red-700 mb-3">Fehler beim Starten</h1>'
. '<div class="bg-red-50 border border-red-200 rounded p-4 mb-4">'
. '<p class="text-sm font-medium text-red-800">' . $msg . '</p>'
. '<p class="text-xs text-red-600 mt-1">Datei: ' . $file . '</p></div>'
. '<details class="mb-4"><summary class="text-sm text-gray-600 cursor-pointer">Stack-Trace anzeigen</summary>'
. '<pre class="mt-2 text-xs bg-gray-50 p-3 rounded overflow-x-auto max-h-64 overflow-y-auto">' . $trace . '</pre></details>'
. '<a href="/" class="inline-block px-4 py-2 text-sm text-white bg-blue-600 rounded hover:bg-blue-700">Erneut versuchen</a>'
. '</div></body></html>';
return new \Illuminate\Http\Response($html, 500);
});
})->create();