From 24a6d3d59f47459be8f58694dab2e7fcbf258cfe Mon Sep 17 00:00:00 2001 From: Francesco Picone Date: Sat, 25 Jul 2026 23:05:20 +0200 Subject: [PATCH] ++ fix permessi assegnazioni --- HANDOFF.md | 24 +++++++++++++++++++ app/Livewire/Territori/TerritorioCestino.php | 4 ++++ app/Livewire/Territori/TerritorioCreate.php | 2 ++ app/Livewire/Territori/TerritorioEdit.php | 4 ++++ app/Livewire/Territori/TerritorioIndex.php | 9 +++++++ .../views/components/layouts/app.blade.php | 2 +- .../territori/territorio-index.blade.php | 4 ++++ .../territori/territorio-show.blade.php | 2 ++ routes/web.php | 15 ++++++++++-- 9 files changed, 63 insertions(+), 3 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index 8b04c71..44649a1 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -123,6 +123,30 @@ i pulsanti Modifica/Elimina in `campagna-index`/`campagna-show` sono sotto `@can('settings.manage')`. Nota: `Campagna` non ha soft delete — l'eliminazione è definitiva. +Per i **territori** vale un modello leggermente diverso, perché la +visualizzazione va aperta a tutti gli operativi: lista (`territori.index`) e +dettaglio (`territori.show`) sono ora su `territori.assign` (che hanno admin, +assistente e operatore); creazione/modifica/cestino restano su `territori.manage` +(solo admin). Attenzione a due punti: + +- **Ordine delle rotte.** Le rotte letterali `territori/create` e + `territori/cestino` devono restare registrate PRIMA del wildcard + `territori/{territorio}`, altrimenti verrebbero catturate dalla rotta di + dettaglio. + +- **`TerritorioIndex` perde la copertura del middleware persistente.** Il suo + componente è ora servito da una rotta rilassata (`territori.assign`), quindi i + suoi metodi di mutazione (`toggleActive`, `togglePriority`, `deleteTerritorio`) + NON sono più protetti dal middleware di route e hanno un + `$this->authorize('territori.manage')` interno — senza, un operativo potrebbe + invocarli via `/livewire/update` col pulsante nascosto. Per difesa in + profondità lo stesso check è stato aggiunto anche a `TerritorioCreate::save`, + `TerritorioEdit::save`/`removePdf`, `TerritorioCestino::restore`/`forceDelete` + (che restano comunque su rotte `territori.manage`). I pulsanti + Modifica/toggle/Elimina/Nuovo/Cestino in `territorio-index`/`territorio-show` + sono sotto `@can('territori.manage')`; il link "Dettaglio" resta visibile a + tutti. Il menu laterale mostra "Territori" a chi ha `territori.assign`. + ### Export/Import XML: backup completo e round-trip `Livewire/Settings/XmlExchange` esporta e reimporta **tutti** i dati gestionali, diff --git a/app/Livewire/Territori/TerritorioCestino.php b/app/Livewire/Territori/TerritorioCestino.php index 769251a..c7ece4f 100644 --- a/app/Livewire/Territori/TerritorioCestino.php +++ b/app/Livewire/Territori/TerritorioCestino.php @@ -12,6 +12,8 @@ class TerritorioCestino extends Component public function restore(int $id) { + $this->authorize('territori.manage'); + $territorio = Territorio::onlyTrashed()->findOrFail($id); $territorio->restore(); activity()->causedBy(auth()->user()) @@ -22,6 +24,8 @@ class TerritorioCestino extends Component public function forceDelete(int $id) { + $this->authorize('territori.manage'); + $territorio = Territorio::onlyTrashed()->findOrFail($id); if ($territorio->assegnazioni()->exists()) { diff --git a/app/Livewire/Territori/TerritorioCreate.php b/app/Livewire/Territori/TerritorioCreate.php index 2c84bf4..e35c0cd 100644 --- a/app/Livewire/Territori/TerritorioCreate.php +++ b/app/Livewire/Territori/TerritorioCreate.php @@ -36,6 +36,8 @@ class TerritorioCreate extends Component public function save() { + $this->authorize('territori.manage'); + $this->validate(); $data = [ diff --git a/app/Livewire/Territori/TerritorioEdit.php b/app/Livewire/Territori/TerritorioEdit.php index a041385..4b2f097 100644 --- a/app/Livewire/Territori/TerritorioEdit.php +++ b/app/Livewire/Territori/TerritorioEdit.php @@ -49,6 +49,8 @@ class TerritorioEdit extends Component public function save() { + $this->authorize('territori.manage'); + $this->validate(); $data = [ @@ -82,6 +84,8 @@ class TerritorioEdit extends Component public function removePdf() { + $this->authorize('territori.manage'); + if ($this->territorio->pdf_path) { Storage::disk('public')->delete($this->territorio->pdf_path); if ($this->territorio->thumbnail_path) { diff --git a/app/Livewire/Territori/TerritorioIndex.php b/app/Livewire/Territori/TerritorioIndex.php index d984eb4..9e1e5fc 100644 --- a/app/Livewire/Territori/TerritorioIndex.php +++ b/app/Livewire/Territori/TerritorioIndex.php @@ -96,6 +96,11 @@ class TerritorioIndex extends Component public function toggleActive(Territorio $territorio) { + // La lista è ora visibile agli utenti operativi (territori.assign), ma + // modificare/eliminare i territori resta riservato all'amministratore. + // Il check DEVE stare nel metodo: la rotta index non lo garantisce più. + $this->authorize('territori.manage'); + $territorio->update(['attivo' => !$territorio->attivo]); activity()->causedBy(auth()->user()) ->performedOn($territorio) @@ -105,6 +110,8 @@ class TerritorioIndex extends Component public function togglePriority(Territorio $territorio) { + $this->authorize('territori.manage'); + $territorio->update(['prioritario' => !$territorio->prioritario]); activity()->causedBy(auth()->user()) ->performedOn($territorio) @@ -114,6 +121,8 @@ class TerritorioIndex extends Component public function deleteTerritorio(Territorio $territorio) { + $this->authorize('territori.manage'); + activity()->causedBy(auth()->user()) ->performedOn($territorio) ->log('soft_deleted'); diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php index fd41619..99e6ba0 100644 --- a/resources/views/components/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -70,7 +70,7 @@ Home - @can('territori.manage') + @can('territori.assign') diff --git a/resources/views/livewire/territori/territorio-index.blade.php b/resources/views/livewire/territori/territorio-index.blade.php index 7e81a23..dd87cbd 100644 --- a/resources/views/livewire/territori/territorio-index.blade.php +++ b/resources/views/livewire/territori/territorio-index.blade.php @@ -4,6 +4,7 @@

Territori

Gestione dei territori della congregazione

+ @can('territori.manage')
@@ -14,6 +15,7 @@ Nuovo territorio
+ @endcan {{-- Filters --}} @@ -159,6 +161,7 @@ + @can('territori.manage') @@ -172,6 +175,7 @@ + @endcan diff --git a/resources/views/livewire/territori/territorio-show.blade.php b/resources/views/livewire/territori/territorio-show.blade.php index 2a0a02d..c483dd3 100644 --- a/resources/views/livewire/territori/territorio-show.blade.php +++ b/resources/views/livewire/territori/territorio-show.blade.php @@ -24,10 +24,12 @@ @endif @endcan + @can('territori.manage') Modifica + @endcan diff --git a/routes/web.php b/routes/web.php index cd564c0..f12d339 100644 --- a/routes/web.php +++ b/routes/web.php @@ -66,12 +66,23 @@ Route::middleware('auth')->group(function () { // Home Dashboard Route::get('/', Home::class)->name('dashboard'); - // Territori - Route::middleware('permission:territori.manage')->group(function () { + // 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'); });