app->resolved('mail.manager')) { app(ConfigurazionePosta::class)->applica(); } }); // L'email di conferma in italiano. Il link resta quello di Laravel // (firmato, scade dopo auth.verification.expire minuti) e porta a // VerificaEmailController::conferma, che funziona anche senza login. VerifyEmail::toMailUsing(function ($utente, string $link) { $minuti = (int) config('auth.verification.expire', 60); return (new MailMessage) ->subject('Conferma il tuo indirizzo email — TerManager2') ->greeting('Ciao ' . $utente->name . ',') ->line('per usare TerManager2 conferma che questo indirizzo email è tuo.') ->action('Conferma l\'indirizzo', $link) ->line("Il link vale {$minuti} minuti. Se è scaduto, entra in TerManager2 e chiedine uno nuovo.") ->line('Se non sai di cosa si tratta, ignora questa email.') ->salutation('TerManager2'); }); // Le richieste di Livewire non ripassano dal gruppo di rotte della // pagina: senza, una scheda aperta prima del blocco continuerebbe a // lavorare con un'email non confermata. Livewire::addPersistentMiddleware([EnsureEmailIsVerified::class]); // Il server di posta configurato in Impostazioni prende il posto di // quello del .env, appena Laravel crea il sistema di posta. $this->app->afterResolving('mail.manager', function ($manager) { app(ConfigurazionePosta::class)->applica($manager); }); // Pin generated URLs to APP_URL. // // Behind a trusted proxy, Symfony derives the port from // X-Forwarded-Port and falls back to the scheme's default when that // header is absent — which silently drops a non-standard port from // every generated link. Anchoring the root to APP_URL makes the // public address explicit instead of reconstructed per request, and // keeps PDF/e-mail links correct regardless of proxy behaviour. $appUrl = (string) config('app.url'); if ($appUrl !== '') { URL::forceRootUrl($appUrl); if (str_starts_with($appUrl, 'https://')) { URL::forceScheme('https'); } } // NOTE: APP_KEY is deliberately NOT auto-generated here. // // This provider boots on every request. Generating a key at runtime // meant that if the key ever failed to persist, each request could // mint a *different* one — and since proclamatori names are encrypted // at column level with APP_KEY, every row written under a superseded // key becomes permanently unreadable. // // The key is now resolved once at container start (docker/php/ // entrypoint.sh) and persisted to the storage volume. Fail loudly // instead of silently rotating. // Only enforced when serving HTTP. Build-time tooling (package:discover, // config:cache) legitimately runs before the key exists, and failing // there would break the image build rather than surface a real problem. if (empty(config('app.key')) && ! $this->app->runningInConsole()) { throw new RuntimeException( 'APP_KEY is not set. Set it in the environment before starting the application. ' .'Generate one with: php artisan key:generate --show' ); } // Livewire only re-applies a fixed allow-list of middleware to // /livewire/update requests. Spatie's permission middleware is not on // that list, so a component whose route is guarded by // `permission:territori.manage` would keep accepting mutating actions // from a user whose permission was revoked after page load, until they // reload. Registering them as persistent closes that window. Livewire::addPersistentMiddleware([ \Spatie\Permission\Middleware\PermissionMiddleware::class, \Spatie\Permission\Middleware\RoleMiddleware::class, \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class, ]); Gate::before(function ($user, $ability) { return $user->hasRole('amministratore') ? true : null; }); } }