withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { // '*' is deliberate. The container is only reachable through Traefik // (no published port in Dokploy), and nginx's real_ip module has // already rewritten REMOTE_ADDR to the client's address. Restricting // this to private ranges would therefore stop Laravel from honouring // the X-Forwarded-Proto that nginx sets server-side, and every signed // URL and secure cookie would break behind HTTPS. // // X_FORWARDED_HOST is deliberately excluded. Trusting it lets a client // set an arbitrary Host and have route()/url() emit links pointing at // an attacker's domain — including the public assignment PDF links, // which carry a valid access code. $middleware->trustProxies( at: '*', headers: Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO ); // Second line of defence: only serve requests whose Host matches // APP_URL. Relaxed outside production so local access by IP works. $middleware->trustHosts(at: function () { $host = parse_url((string) config('app.url'), PHP_URL_HOST); // localhost/127.0.0.1 are kept for container-internal probes: the // Docker health check and Dokploy's own checks address the // container directly, not through the public domain. They are not // an external hole — Traefik only forwards requests whose Host // matches a configured domain. return array_values(array_filter([$host, 'localhost', '127.0.0.1'])); }, subdomains: false); // Dopo il ripristino di un backup ogni account resta bloccato finche' // non imposta una password nuova. In coda al gruppo web, quindi la // sessione e' gia' avviata e l'utente risolto quando gira. // // AuthenticateSession prima: ogni sessione ricorda l'impronta della // password, e quando la password cambia (profilo, cambio obbligatorio, // l'amministratore che la reimposta) le sessioni aperte altrove si // chiudono alla richiesta successiva. Quella che ha fatto il cambio // resta aperta: il middleware ci registra l'impronta nuova. Senza, // session()->regenerate() cambiava solo l'id della sessione corrente e // le altre restavano valide su Redis. $middleware->web(append: [ \Illuminate\Session\Middleware\AuthenticateSession::class, \App\Http\Middleware\RequirePasswordChange::class, ]); $middleware->alias([ 'role' => \Spatie\Permission\Middleware\RoleMiddleware::class, 'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class, 'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class, ]); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();