Konsolidierter Entwicklungsplan aus den zwei Analyse-Dokumenten plus
Umsetzung der Phase-0-Massnahmen (Korrektheit/Security, je mit Tests):
0.1 BasicAuth: timing-sicherer Vergleich (hash_equals, beide Felder ohne
Short-Circuit); Enabled-Check zur Laufzeit via config('auth.basic.*')
statt env() im Bootstrap-Closure (greift jetzt unter config:cache);
Config-Block + .env.example. Fund: auth.basic.* war nie als Config
definiert, Gate war faktisch unkonfigurierbar.
0.2 Legacy-Invoice-"latest"-Abfrage zentralisiert (LegacyInvoice::
scopeLatestFirst + User::latestLegacyInvoice); beide Consumer N+1-frei
umgestellt; unterschiedliches null-Verhalten bewusst erhalten.
0.3 Payment-Option-Eligibility vereinheitlicht (period-aware, strikt):
UserPaymentOption::scopeActiveNow/grandfatheredNow + User::
hasActivePaymentOption; hasActiveBooking/hasUnlimitedPressReleaseQuota
und ApiAccessEligibilityService darauf umgestellt; $hasGrandfathered-
Mislabel behoben.
0.4 Theme->Portal-Vokabular: totes, projektfremdes ThemeMiddleware
geloescht; Mapping in Portal::fromTheme() zentralisiert; fremden
b2in-Default im ThemeServiceProvider auf Portal-Default korrigiert.
0.5 InvoiceNumberGenerator: Erst-Insert race-sicher via insertOrIgnore
(Unique-Index auf circle existiert bereits). CreditWalletService war
bereits abgesichert (Unique-Index + createOrFirst).
Tests: 4 neue Dateien, 5 bestehende auf gueltiges grandfathered_until
angepasst. Volle Suite gruen (793 passed, 1 skipped).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
2.6 KiB
PHP
72 lines
2.6 KiB
PHP
<?php
|
|
|
|
use App\Http\Middleware\BasicAuthMiddleware;
|
|
use App\Http\Middleware\LogApiUsage;
|
|
use App\Http\Middleware\RejectLegacyApiKeys;
|
|
use App\Http\Middleware\SetCurrentPortal;
|
|
use App\Http\Middleware\SetEdition;
|
|
use Illuminate\Foundation\Application;
|
|
use Illuminate\Foundation\Configuration\Exceptions;
|
|
use Illuminate\Foundation\Configuration\Middleware;
|
|
use Illuminate\Http\Request;
|
|
use Laravel\Sanctum\Http\Middleware\CheckAbilities;
|
|
use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;
|
|
|
|
return Application::configure(basePath: dirname(__DIR__))
|
|
->withRouting(
|
|
web: __DIR__.'/../routes/domains.php',
|
|
api: __DIR__.'/../routes/api.php',
|
|
commands: __DIR__.'/../routes/console.php',
|
|
health: '/up',
|
|
)
|
|
->withMiddleware(function (Middleware $middleware) {
|
|
|
|
// Portal-Kontext nach dem Theme-Provider setzen (liest config('app.theme'))
|
|
$middleware->append(SetCurrentPortal::class);
|
|
|
|
// Ausgabe/Sprache (de|en) aus dem URL-Präfix ableiten und URL-Defaults setzen.
|
|
$middleware->append(SetEdition::class);
|
|
|
|
// Wohin eingeloggte User von Gast-Routen (/login, /register) gelenkt
|
|
// werden: rollen- und verifizierungsbewusst statt fix auf /dashboard,
|
|
// sonst landet ein Customer dort im 403 und sitzt fest.
|
|
$middleware->redirectUsersTo(function (Request $request) {
|
|
$user = $request->user();
|
|
|
|
if ($user && ! $user->hasVerifiedEmail()) {
|
|
return route('verification.notice');
|
|
}
|
|
|
|
if ($user?->canAccessAdmin()) {
|
|
return route('dashboard');
|
|
}
|
|
|
|
return $user?->canAccessCustomer() ? route('me.dashboard') : '/';
|
|
});
|
|
|
|
$middleware->api(prepend: [
|
|
LogApiUsage::class,
|
|
RejectLegacyApiKeys::class,
|
|
]);
|
|
|
|
$middleware->alias([
|
|
'abilities' => CheckAbilities::class,
|
|
'ability' => CheckForAnyAbility::class,
|
|
]);
|
|
|
|
// BasicAuth ganz am Ende, nach Session-Middleware. Immer anhängen;
|
|
// ob erzwungen wird, entscheidet die Middleware zur Laufzeit anhand
|
|
// von config('auth.basic.*') (greift auch unter `config:cache`).
|
|
$middleware->append(BasicAuthMiddleware::class);
|
|
// Trust all proxies (for Traefik/Docker setup)
|
|
$middleware->trustProxies(
|
|
at: '*',
|
|
headers: Request::HEADER_X_FORWARDED_FOR |
|
|
Request::HEADER_X_FORWARDED_HOST |
|
|
Request::HEADER_X_FORWARDED_PORT |
|
|
Request::HEADER_X_FORWARDED_PROTO
|
|
);
|
|
})
|
|
->withExceptions(function (Exceptions $exceptions) {
|
|
//
|
|
})->create();
|