> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Autorizzazione (Gate e Policy)

> Come gestire i permessi delle azioni utente usando le Gate e le Policy di Laravel.

## Differenza tra autenticazione e autorizzazione

L'**autenticazione (Authentication)** verifica "chi è" l'utente. Il login ne è l'esempio tipico.
L'**autorizzazione (Authorization)** decide "cosa può fare" quell'utente. Ad esempio: modificare solo i propri post, solo gli amministratori possono modificare le impostazioni, ecc.

Dopo aver implementato la funzione di login con l'[autenticazione](./authentication), il passo successivo è l'autorizzazione.

<Info>
  Le funzionalità di autorizzazione di Laravel offrono due approcci: Gate e Policy. Quale usare dipende dal caso d'uso.
</Info>

**Criteri di scelta**

| Scenario                                                               | Consigliato |
| ---------------------------------------------------------------------- | ----------- |
| Verifica semplice non legata a un modello                              | Gate        |
| Gestione dei permessi CRUD su un modello                               | Policy      |
| Controllo dell'accesso alla dashboard admin                            | Gate        |
| Diritti di pubblicazione, modifica ed eliminazione di articoli di blog | Policy      |

## Gate

Le Gate sono verifiche di autorizzazione semplici basate su closure. Adatte a valutazioni di permessi non legate a un modello specifico.

### Flusso di autorizzazione tramite Gate

```mermaid theme={null}
flowchart TD
    A["AppServiceProvider::boot()<br>(App\\Providers\\AppServiceProvider)"] --> B["Gate::define('ability', fn)<br>Registra la logica di autorizzazione"]
    C["Controllo di autorizzazione dal controller"] --> D{"Gate::before()<br>è impostata?"}
    D -->|"Sì"| E{"Valore restituito da before()"}
    E -->|"true / false"| F["Usa il risultato di before() come decisione finale"]
    E -->|"null"| G["Esegue la closure di define()"]
    D -->|"No"| G
    G --> H{"Valore restituito dalla closure"}
    H -->|"true"| I["✓ Accesso consentito"]
    H -->|"false"| J["✗ Accesso negato"]
    F -->|"true"| I
    F -->|"false"| J
    J -->|"Gate::allows()"| K["Restituisce false<br>→ Chiama manualmente abort(403)"]
    J -->|"Gate::authorize()"| L["AuthorizationException<br>→ 403 Forbidden automatico"]
```

### Definire una Gate

Definisci le Gate nel metodo `boot` di `App\Providers\AppServiceProvider` con `Gate::define()`.

```php theme={null}
// app/Providers/AppServiceProvider.php

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
```

La closure della Gate riceve sempre come primo argomento l'utente attualmente autenticato. Dal secondo argomento in poi passi eventuali informazioni aggiuntive come il modello di riferimento.

### Verificare i permessi con una Gate

In un controller, per verificare i permessi con una Gate usa `Gate::allows()` o `Gate::denies()`.

```php theme={null}
use Illuminate\Support\Facades\Gate;

public function update(Request $request, Post $post): RedirectResponse
{
    if (! Gate::allows('update-post', $post)) {
        abort(403);
    }

    // Logica di aggiornamento del post...

    return redirect('/posts');
}
```

### Lanciare eccezioni con Gate::authorize()

Per restituire automaticamente una risposta 403 in mancanza di permessi usa `Gate::authorize()`. Elimina la necessità di scrivere `abort(403)`.

```php theme={null}
public function update(Request $request, Post $post): RedirectResponse
{
    Gate::authorize('update-post', $post);

    // Se hai i permessi arrivi qui
    // Logica di aggiornamento del post...

    return redirect('/posts');
}
```

<Tip>
  `Gate::authorize()` lancia una `Illuminate\Auth\Access\AuthorizationException` in mancanza di permessi. Laravel la converte automaticamente in una risposta HTTP 403.
</Tip>

### Bypass amministratore (metodo before)

Se vuoi concedere tutti i permessi agli amministratori usa `Gate::before()`.

```php theme={null}
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    // $ability contiene il nome della gate in corso di verifica ('update-post', ecc.)
    Gate::before(function (User $user, string $ability) {
        if ($user->isAdministrator()) {
            return true;
        }
    });

    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
```

Se la closure di `before` restituisce un valore diverso da `null`, quel valore diventa la decisione finale. Se restituisce `null` o niente, si procede alla valutazione normale della Gate.

### @can / @cannot nei template Blade

Nei template le direttive `@can` e `@cannot` sono comode per usare le Gate.

```blade theme={null}
@can('update-post', $post)
    <a href="{{ route('posts.edit', $post) }}">Modifica</a>
@endcan

@cannot('update-post', $post)
    <p>Non hai i permessi per modificare questo post.</p>
@endcannot
```

## Policy

Le Policy raccolgono in una classe la logica di autorizzazione relativa a un modello specifico. Per gestire i permessi CRUD sul modello `Post`, le Policy sono più adatte delle Gate.

### Flusso di autorizzazione tramite Policy

```mermaid theme={null}
flowchart TD
    A["Richiesta HTTP"] --> B["Controller"]
    B --> C["Gate::authorize('update', $post)"]
    C --> D{"È definita PostPolicy::before()?"}
    D -->|"Sì"| E{"Valore restituito da before()"}
    E -->|"true / false"| F["Usa il risultato di before() come decisione finale"]
    E -->|"null"| G["Esegue PostPolicy::update(User, Post)"]
    D -->|"No"| G
    G --> H{"$user->id === $post->user_id?"}
    H -->|"true"| I["✓ Prosegui"]
    H -->|"false"| J["✗ AuthorizationException<br>→ 403 Forbidden"]
    F -->|"true"| I
    F -->|"false"| J
```

### Generare una Policy

Genera una classe Policy con il comando Artisan `make:policy`.

```shell theme={null}
php artisan make:policy PostPolicy
```

Per generare uno scheletro che include tutti i metodi CRUD corrispondenti a un modello, usa l'opzione `--model`.

```shell theme={null}
php artisan make:policy PostPolicy --model=Post
```

Viene generato `app/Policies/PostPolicy.php`.

### Rilevamento automatico di modelli e Policy

Di default Laravel rileva automaticamente le Policy secondo una convenzione di naming.

* Modello: `app/Models/Post.php`
* Policy: `app/Policies/PostPolicy.php`

Rispettando questa convenzione non è necessario registrare la Policy.

<Info>
  Se non segui la convenzione o vuoi registrarla manualmente, usa `Gate::policy()` nel metodo `boot` di `AppServiceProvider`.

  ```php theme={null}
  use App\Models\Post;
  use App\Policies\PostPolicy;
  use Illuminate\Support\Facades\Gate;

  Gate::policy(Post::class, PostPolicy::class);
  ```

  In Laravel 13 puoi anche registrarla in modo dichiarativo con l'attribute `#[UsePolicy]` sul modello.

  ```php theme={null}
  use App\Policies\PostPolicy;
  use Illuminate\Database\Eloquent\Attributes\UsePolicy;

  #[UsePolicy(PostPolicy::class)]
  class Post extends Model {}
  ```
</Info>

### Implementare i metodi di una Policy

Una Policy generata con `--model` contiene i metodi corrispondenti alle azioni CRUD standard.

```php theme={null}
<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    /**
     * Può visualizzare l'elenco dei post
     */
    public function viewAny(User $user): bool
    {
        return true; // Tutti gli utenti autenticati possono visualizzare
    }

    /**
     * Può visualizzare un post specifico
     */
    public function view(User $user, Post $post): bool
    {
        return true; // Tutti gli utenti autenticati possono visualizzare
    }

    /**
     * Può creare un post
     */
    public function create(User $user): bool
    {
        return true; // Tutti gli utenti autenticati possono creare
    }

    /**
     * Può aggiornare un post
     */
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id; // Solo il proprio post
    }

    /**
     * Può eliminare un post
     */
    public function delete(User $user, Post $post): bool
    {
        return $user->id === $post->user_id; // Solo il proprio post
    }
}
```

### Bypass amministratore (metodo before)

Anche nelle Policy puoi definire un metodo `before` per concedere tutti i permessi agli amministratori.

```php theme={null}
/**
 * Verifica preliminare eseguita prima degli altri metodi della Policy
 * $ability contiene il nome del metodo Policy ('update', 'delete', ecc.)
 */
public function before(User $user, string $ability): bool|null
{
    if ($user->isAdministrator()) {
        return true; // L'amministratore ha tutti i permessi
    }

    return null; // Restituendo null si passa al normale metodo della Policy
}
```

<Warning>
  Il metodo `before` viene invocato solo se la Policy contiene il metodo corrispondente. Se ad esempio manca `update`, `before` non viene chiamato.
</Warning>

### Ordine di esecuzione della callback before

```mermaid theme={null}
flowchart TD
    A["Inizio del controllo di autorizzazione<br>authorize('update', $post)"] --> B["Esegue PostPolicy::before()"]
    B --> C{"Il valore restituito è null?"}
    C -->|"Non null (true / false)"| D["Usa il risultato di before() come decisione finale"]
    C -->|"null"| E["Esegue il metodo Policy normale<br>update() / delete(), ecc."]
    E --> F{"Valore restituito dal metodo Policy"}
    F -->|"true"| G["✓ Accesso consentito"]
    F -->|"false"| H["✗ Accesso negato → 403"]
    D -->|"true (bypass amministratore)"| G
    D -->|"false"| H
```

## Usare le Policy nei controller

### Metodo authorize()

I controller Laravel dispongono dell'helper `authorize()` (se non usi il controller base, usa `Gate::authorize()`).

<Tabs>
  <Tab title="Gate::authorize()">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Gate;

    class PostController extends Controller
    {
        public function update(Request $request, Post $post): RedirectResponse
        {
            Gate::authorize('update', $post);

            // Logica di aggiornamento del post...

            return redirect()->route('posts.index');
        }

        public function store(Request $request): RedirectResponse
        {
            Gate::authorize('create', Post::class);

            // Logica di creazione del post...

            return redirect()->route('posts.index');
        }

        public function destroy(Post $post): RedirectResponse
        {
            Gate::authorize('delete', $post);

            $post->delete();

            return redirect()->route('posts.index');
        }
    }
    ```
  </Tab>

  <Tab title="User::can() / cannot()">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;

    class PostController extends Controller
    {
        public function update(Request $request, Post $post): RedirectResponse
        {
            if ($request->user()->cannot('update', $post)) {
                abort(403);
            }

            // Logica di aggiornamento del post...

            return redirect()->route('posts.index');
        }
    }
    ```
  </Tab>
</Tabs>

### Registrazione in blocco delle Policy RESTful con authorizeResource()

Chiamando `authorizeResource()` nel costruttore, i metodi della Policy corrispondenti alle azioni del controller vengono collegati automaticamente.

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Models\Post;

class PostController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }

    // A index(), show(), create(), store(), edit(), update(), destroy()
    // vengono applicati automaticamente i metodi Policy corrispondenti
}
```

Corrispondenza tra azioni del controller e metodi della Policy:

| Azione del controller | Metodo della Policy |
| --------------------- | ------------------- |
| `index`               | `viewAny`           |
| `show`                | `view`              |
| `create` / `store`    | `create`            |
| `edit` / `update`     | `update`            |
| `destroy`             | `delete`            |

<Tip>
  Con `authorizeResource()` non devi scrivere `authorize()` in ogni azione. Comodo con i controller di risorsa RESTful.
</Tip>

## Autorizzazione tramite middleware

Per effettuare il controllo di autorizzazione a livello di route usa il middleware `can`.

```php theme={null}
use App\Models\Post;

// Accessibile solo agli utenti con permesso di aggiornare il post
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->middleware('can:update,post');

// Accessibile solo agli utenti con permesso di creare post
Route::post('/posts', [PostController::class, 'store'])
    ->middleware('can:create,App\Models\Post');
```

Scrittura più concisa con il metodo `can`:

```php theme={null}
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->can('update', 'post');
```

## Usare le Policy nei template Blade

Una volta registrate le Policy, anche `@can` / `@cannot` in Blade usano automaticamente le Policy.

```blade theme={null}
{{-- Il pulsante di modifica del post viene mostrato solo agli utenti con i permessi --}}
@can('update', $post)
    <a href="{{ route('posts.edit', $post) }}" class="btn">Modifica</a>
@endcan

{{-- Lo stesso per il pulsante di eliminazione --}}
@can('delete', $post)
    <form method="POST" action="{{ route('posts.destroy', $post) }}">
        @csrf
        @method('DELETE')
        <button type="submit">Elimina</button>
    </form>
@endcan

{{-- Pulsante di creazione nuovo post --}}
@can('create', App\Models\Post::class)
    <a href="{{ route('posts.create') }}">Nuovo post</a>
@endcan
```

## Esempio pratico: gestione dei permessi degli articoli di blog

Esempio che implementa "solo l'autore può modificare e cancellare i propri articoli" in un'app blog.

<Steps>
  <Step title="Genera la Policy">
    ```shell theme={null}
    php artisan make:policy PostPolicy --model=Post
    ```
  </Step>

  <Step title="Implementa i metodi della Policy">
    ```php theme={null}
    <?php

    namespace App\Policies;

    use App\Models\Post;
    use App\Models\User;

    class PostPolicy
    {
        /**
         * Concedi tutti i permessi all'amministratore
         */
        public function before(User $user, string $ability): bool|null
        {
            if ($user->is_admin) {
                return true;
            }

            return null;
        }

        public function viewAny(User $user): bool
        {
            return true;
        }

        public function view(User $user, Post $post): bool
        {
            return true;
        }

        public function create(User $user): bool
        {
            return true;
        }

        public function update(User $user, Post $post): bool
        {
            return $user->id === $post->user_id;
        }

        public function delete(User $user, Post $post): bool
        {
            return $user->id === $post->user_id;
        }
    }
    ```
  </Step>

  <Step title="Aggiungi authorizeResource() al controller">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\View\View;

    class PostController extends Controller
    {
        public function __construct()
        {
            $this->authorizeResource(Post::class, 'post');
        }

        public function index(): View
        {
            $posts = Post::latest()->paginate(10);
            return view('posts.index', compact('posts'));
        }

        public function store(Request $request): RedirectResponse
        {
            $post = $request->user()->posts()->create(
                $request->validate([
                    'title' => ['required', 'string', 'max:255'],
                    'body'  => ['required', 'string'],
                ])
            );

            return redirect()->route('posts.show', $post);
        }

        public function update(Request $request, Post $post): RedirectResponse
        {
            $post->update(
                $request->validate([
                    'title' => ['required', 'string', 'max:255'],
                    'body'  => ['required', 'string'],
                ])
            );

            return redirect()->route('posts.show', $post);
        }

        public function destroy(Post $post): RedirectResponse
        {
            $post->delete();

            return redirect()->route('posts.index');
        }
    }
    ```
  </Step>

  <Step title="Aggiungi i controlli di permesso nel template Blade">
    ```blade theme={null}
    {{-- resources/views/posts/show.blade.php --}}
    <h1>{{ $post->title }}</h1>
    <p>{{ $post->body }}</p>
    <p>Autore: {{ $post->user->name }}</p>

    @can('update', $post)
        <a href="{{ route('posts.edit', $post) }}">Modifica</a>
    @endcan

    @can('delete', $post)
        <form method="POST" action="{{ route('posts.destroy', $post) }}">
            @csrf
            @method('DELETE')
            <button type="submit">Elimina</button>
        </form>
    @endcan
    ```
  </Step>
</Steps>

## Riepilogo

<AccordionGroup>
  <Accordion title="Come scegliere tra Gate e Policy">
    * **Gate**: verifiche di permessi semplici non legate a un modello. Accesso alla dashboard admin, modifica di impostazioni globali, ecc.
    * **Policy**: gestione dei permessi CRUD su un modello. Crei una Policy per ciascuna risorsa (`Post`, `Order`, `Comment`, ecc.).
  </Accordion>

  <Accordion title="Riepilogo delle API più usate">
    ```php theme={null}
    // Controllo con Gate
    Gate::allows('update-post', $post);      // true/false
    Gate::denies('update-post', $post);      // true/false
    Gate::authorize('update-post', $post);   // eccezione in caso di fallimento

    // Controllo dal modello utente
    $user->can('update', $post);     // true/false
    $user->cannot('update', $post);  // true/false

    // Controllo dal controller
    Gate::authorize('update', $post);        // 403 in caso di fallimento

    // Controllo in Blade
    @can('update', $post) ... @endcan
    @cannot('update', $post) ... @endcannot
    ```
  </Accordion>

  <Accordion title="Comandi Artisan più usati">
    ```shell theme={null}
    # Genera una Policy vuota
    php artisan make:policy PostPolicy

    # Genera con i metodi CRUD legati al modello
    php artisan make:policy PostPolicy --model=Post
    ```
  </Accordion>
</AccordionGroup>


## Related topics

- [Laravel Telescope](/it/telescope.md)
- [Cifratura (Encryption)](/it/encryption.md)
- [Laravel Horizon](/it/horizon.md)
- [Laravel Sentinel — indagine sul middleware di protezione delle rotte](/it/blog/sentinel-introduction.md)
- [Gestione degli errori](/it/error-handling.md)
