group(function () { Route::get('login', App\Livewire\Auth\Login::class)->name('login'); Route::post('login', LoginController::class)->name('login.store'); }); Route::post('logout', function () { activity()->causedBy(auth()->user())->log('logout'); auth()->logout(); request()->session()->invalidate(); request()->session()->regenerateToken(); return redirect('/login'); })->middleware('auth')->name('logout'); Route::get('p/{code}', ShortPdfLinkController::class)->name('assignments.pdf.short'); Route::get('assegnazioni/pdf/{assignment}/{code}', [AssignmentPdfController::class, 'viewer']) ->name('assignments.pdf.viewer'); Route::get('assegnazioni/pdf/{assignment}/{code}/file', [AssignmentPdfController::class, 'file']) ->name('assignments.pdf.file'); /* |-------------------------------------------------------------------------- | Authenticated Routes |-------------------------------------------------------------------------- */ Route::middleware('auth')->group(function () { // Home Dashboard Route::get('/', Home::class)->name('dashboard'); // Profilo personale (ogni utente loggato) Route::get('profilo', Profile::class)->name('profile'); // Cambio password: raggiungibile anche quando RequirePasswordChange // blocca tutto il resto (vedi l'elenco di rotte ammesse nel middleware). Route::get('cambia-password', [PasswordChangeController::class, 'show'])->name('password.change'); Route::post('cambia-password', [PasswordChangeController::class, 'store'])->name('password.change.store'); // Territori — visualizzazione (lista + dettaglio) per tutti gli utenti // operativi, cioè chi può assegnare i territori. Route::middleware('permission:territori.assign')->group(function () { Route::get('territori', TerritorioIndex::class)->name('territori.index'); }); // Gestione territori (crea/modifica/cestino): solo amministratore // (territori.manage). Le rotte LETTERALI (create/cestino) devono essere // registrate PRIMA del wildcard {territorio}, altrimenti "create"/"cestino" // verrebbero catturate dalla rotta di dettaglio. Route::middleware('permission:territori.manage')->group(function () { Route::get('territori/create', TerritorioCreate::class)->name('territori.create'); Route::get('territori/cestino', TerritorioCestino::class)->name('territori.cestino'); }); Route::middleware('permission:territori.assign')->group(function () { Route::get('territori/{territorio}', TerritorioShow::class)->name('territori.show'); }); Route::middleware('permission:territori.manage')->group(function () { Route::get('territori/{territorio}/edit', TerritorioEdit::class)->name('territori.edit'); }); // Proclamatori — visualizzazione (lista + dettaglio) per chi ha // proclamatori.manage; sola lettura per i non-admin. Route::middleware('permission:proclamatori.manage')->group(function () { Route::get('proclamatori', ProclamatoreIndex::class)->name('proclamatori.index'); }); // Gestione proclamatori (crea/modifica/cestino): solo amministratore. Le // rotte letterali (create/cestino) devono precedere il wildcard {proclamatore}. Route::middleware('permission:settings.manage')->group(function () { Route::get('proclamatori/create', ProclamatoreCreate::class)->name('proclamatori.create'); Route::get('proclamatori/cestino', ProclamatoreCestino::class)->name('proclamatori.cestino'); }); Route::middleware('permission:proclamatori.manage')->group(function () { Route::get('proclamatori/{proclamatore}', ProclamatoreShow::class)->name('proclamatori.show'); }); Route::middleware('permission:settings.manage')->group(function () { Route::get('proclamatori/{proclamatore}/edit', ProclamatoreEdit::class)->name('proclamatori.edit'); }); // Assegnazioni Route::middleware('permission:territori.assign')->group(function () { Route::get('assegnazioni/assegna/{territorioId?}', Assegna::class)->name('assegnazioni.assegna'); }); Route::middleware('permission:territori.return')->group(function () { Route::get('assegnazioni/{assegnazione}/rientra', Rientra::class)->name('assegnazioni.rientra'); }); // Campagne — visualizzazione per chi ha campagne.manage; sola lettura per i // non-admin. Route::middleware('permission:campagne.manage')->group(function () { Route::get('campagne', CampagnaIndex::class)->name('campagne.index'); }); // Creazione campagne: solo amministratore. La rotta letterale create deve // precedere il wildcard {campagna}. Route::middleware('permission:settings.manage')->group(function () { Route::get('campagne/create', CampagnaCreate::class)->name('campagne.create'); }); Route::middleware('permission:campagne.manage')->group(function () { Route::get('campagne/{campagna}', CampagnaShow::class)->name('campagne.show'); }); // Modifica campagne: solo amministratore (settings.manage). L'eliminazione // vive in CampagnaIndex::deleteCampagna(), protetta lì con lo stesso gate. Route::middleware('permission:settings.manage')->group(function () { Route::get('campagne/{campagna}/edit', CampagnaEdit::class)->name('campagne.edit'); }); // Registro Route::middleware('permission:registro.view')->group(function () { Route::get('registro', Registro::class)->name('registro.index'); }); // Audit Log Route::middleware('permission:audit.view')->group(function () { Route::get('audit', AuditLog::class)->name('audit.index'); }); // Settings (admin) Route::middleware('permission:settings.manage')->group(function () { Route::get('impostazioni', SettingsEdit::class)->name('settings.edit'); Route::get('utenti', UsersIndex::class)->name('users.index'); Route::get('zone', ZoneIndex::class)->name('zone.index'); Route::get('tipologie', TipologieIndex::class)->name('tipologie.index'); Route::get('xml-exchange', XmlExchange::class)->name('xml.exchange'); Route::post('xml-exchange/convert-sql', [XmlExchangeUploadController::class, 'convertSqlToXml'])->name('xml.convert-sql'); Route::post('xml-exchange/import-xml', [XmlExchangeUploadController::class, 'importXml'])->name('xml.import-xml'); Route::post('imports/territori/pdf-zip', [TerritoryPdfImportController::class, 'storeZip'])->name('imports.territori.pdf-zip'); // Backup completo (.zip): dati, utenti e file caricati. L'avvio delle // operazioni e la barra di avanzamento stanno in Livewire // (Settings\BackupManager); qui passa solo il trasferimento dei file. Route::get('backup/file/{operationId}', [BackupController::class, 'file'])->name('backup.file'); Route::post('backup/restore', [BackupController::class, 'upload'])->name('backup.restore'); }); // Privacy / Informativa GDPR — visibile solo all'amministratore. Route::middleware('permission:settings.manage')->group(function () { Route::get('privacy', Privacy::class)->name('privacy'); }); });