Creare progetto Laravel con Spatie/Permissions + Filament

Oggi andiamo a realizzare un progetto con:

  • Laravel 12,
  • Laravel Breeze per gestire la login e registrazione degli utenti,
  • Spatie Permissions per i ruoli e i permessi degli utenti,
  • Filament Admin Panel per il backend,
  • Filament Shield per integrare i ruoli e permessi in Filament,
  • TailwindCSS per il frontend
# composer create-project laravel/laravel myapp
# mv myapp/* .
# mv myapp/.env .

Attenzione al punto finale delle 2 righe sopra, indica di spostare il contenuto della cartella myapp in quella in cui ci troviamo.

Adesso configuriamo il file .env con i dati relativi all’accesso al database e creiamo le tabelle con:

# php artisan migrate

Autenticazione

Installiamo Laravel Breeze perché un pacchetto leggero e basato su TailwindCSS:

# composer require laravel/breeze --dev
# php artisan breeze:install

Io qui ho risposto:

  • Which Breeze stack would you like to install? Blade with Alpine 
  • Would you like dark mode support? Yes
  • Which testing framework do you prefer? Pest
# npm install && npm run dev
# php artisan migrate

Permessi

Passiamo a Spatie/Permissions.

# composer require spatie/laravel-permission
# php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
# php artisan migrate

La prima riga installa il pacchetto per la gestione dei permessi, la seconda pubblica i file di configurazione config/permission.php e la migration per creare la tabella che memorizzerà queste impostazioni per gli utenti.

Modifichiamo il file app/Models/User.php per includere la gestione dei ruoli per l’utente:

// app/Models/User.php
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
    // ...
}

Creiamo quindi alcuni ruoli utente:

// database/seeders/DatabaseSeeder.php
use Spatie\Permission\Models\Role;

public function run(): void
{
    Role::create(['name' => 'admin']);
    Role::create(['name' => 'user']);
}

Poi popoliamo la tabella dei ruoli con quelli appena inseriti nel Seeder:

# php artisan db:seed

Filament Admin

E’ la volta del backend con l’installazione del pacchetto Filament:

# composer require filament/filament
# php artisan filament:install
# php artisan filament:install --panels

Abbiamo così installato il pannello /admin e procediamo creando un utente amministratore:

# php artisan make:filament-user

Diamo un nome, un’email e una password al nuovo utente, poi basta andare all’indirizzo del sito /admin/login per accedere alla dashboard del backend.

Collegamento Filament <-> Spatie Permissions

Avendo già degli utenti in Laravel (per ora in realtà uno solo…), dobbiamo insegnare a Filament di usare gli stessi utenti perché non vogliamo doppioni inutili. Modifichiamo il file app/Providers/Filament/AdminPanelProvider.php così:

<?php

namespace App\Providers\Filament;

use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\AuthenticateSession;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Pages\Dashboard;
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Support\Colors\Color;
use Filament\Widgets\AccountWidget;
use Filament\Widgets\FilamentInfoWidget;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->authGuard('web') // <-- Per usare gli stessi utenti di Laravel in Filament
            ->login()
            ->colors([
                'primary' => Color::Amber,
            ])
            ->discoverResources(in: app_path('Filament/Resources'), for: 'App\Filament\Resources')
            ->discoverPages(in: app_path('Filament/Pages'), for: 'App\Filament\Pages')
            ->pages([
                Dashboard::class,
            ])
            ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\Filament\Widgets')
            ->widgets([
                AccountWidget::class,
                FilamentInfoWidget::class,
            ])
            ->middleware([
                EncryptCookies::class,
                AddQueuedCookiesToResponse::class,
                StartSession::class,
                AuthenticateSession::class,
                ShareErrorsFromSession::class,
                VerifyCsrfToken::class,
                SubstituteBindings::class,
                DisableBladeIconComponents::class,
                DispatchServingFilamentEvent::class,
            ])
            ->authMiddleware([
                Authenticate::class,
            ]);
    }
}

Poi aggiungiamo al modello User.php la limitazione al pannello di Filament agli admin:

public function canAccessPanel(\Filament\Panel $panel): bool
{
    return $this->hasRole('admin');
}

Adesso sincronizziamo Spatie/Permission con Filament:

# composer require bezhansalleh/filament-shield

Consiglio di prendere visione della documentazione ufficiale:

FilamentShield

Poi prosegui in questo modo:

# php artisan shield:setup

Rispondendo alle domande e arrivando al termine dello script si dovrebbe aver installato tutto il necessario per gestire i ruoli da Filament!