Attributi di Configurazione AutoPermissions
Il sistema AutoPermissions utilizza attributi PHP 8+ per configurare il comportamento di generazione e verificazione dei permessi. Ogni attributo ha uno scopo specifico e può essere utilizzato per personalizzare finemente il sistema.
L'attributo #[AutoPermissions] deve essere usato insieme a Laravel Policies per la verifica dei permessi. Il middleware automatico è stato rimosso in favore di un approccio più esplicito e testabile tramite $this->authorize() nei controller e BasePolicy per la verifica automatica dei permessi.
Attributo #[AutoPermissions]
L'attributo principale che attiva il sistema AutoPermissions su un controller.
Utilizzo
use App\Shared\Attributes\Permissions\AutoPermissions;
#[AutoPermissions]
class UserController extends Controller
{
// Tutti i metodi pubblici avranno permessi auto-generati
}
Parametri
| Parametro | Tipo | Default | Descrizione |
|---|---|---|---|
excludeMethods | array<string> | [] | Array di nomi metodi da escludere |
enabled | bool | true | Abilita/disabilita il sistema per questo controller |
Esempi Avanzati
Esclusione di Metodi Specifici
#[AutoPermissions(excludeMethods: ['index', 'show'])]
class UserController extends Controller
{
public function index() { } // ❌ Nessun permesso generato
public function show() { } // ❌ Nessun permesso generato
public function create() { } // ✅ Genera: shared.users.create
public function store() { } // ✅ Genera: shared.users.store
}
Disabilitazione Temporanea
#[AutoPermissions(enabled: false)]
class UserController extends Controller
{
// Nessun permesso verrà generato per questo controller
}
Configurazione Completa
#[AutoPermissions(
excludeMethods: ['publicMethod', 'guestAccess'],
enabled: true
)]
class ApiController extends Controller
{
public function publicMethod() { } // Accesso pubblico
public function guestAccess() { } // Accesso ospite
public function protectedData() { } // Richiede permesso
}
Attributo #[PermissionNaming]
Personalizza il naming delle risorse e permessi per un controller.
Utilizzo
use App\Shared\Attributes\Permissions\PermissionNaming;
#[PermissionNaming(resourceName: 'admin_users', moduleName: 'admin')]
class UserController extends Controller
{
public function index() { } // Genera: admin.admin_users.index
}
Parametri
| Parametro | Tipo | Richiesto | Descrizione |
|---|---|---|---|
resourceName | string | ✅ | Nome della risorsa (es: 'users', 'products') |
moduleName | string | ✅ | Nome del modulo (es: 'shared', 'mc') |
Regole di Validazione
- Caratteri consentiti: solo lettere minuscole, numeri e underscore (
a-z0-9_) - Lunghezza massima: 50 caratteri
- Non consentiti: underscore consecutivi (
__), underscore iniziale/finale - Formato: snake_case obbligatorio
Esempi Pratici
Naming Standard
#[PermissionNaming(resourceName: 'user_profiles', moduleName: 'shared')]
class ProfileController extends Controller
{
public function index() { } // shared.user_profiles.index
public function update() { } // shared.user_profiles.update
}
Con Modulo Specifico
#[PermissionNaming(resourceName: 'users', moduleName: 'admin')]
class AdminUserController extends Controller
{
public function index() { } // admin.users.index
public function delete() { } // admin.users.delete
}
Risoluzione Conflitti
// Controller API
#[PermissionNaming(resourceName: 'users', moduleName: 'api')]
class ApiUserController extends Controller
{
public function index() { } // api.users.index
}
// Controller Admin
#[PermissionNaming(resourceName: 'users', moduleName: 'admin')]
class AdminUserController extends Controller
{
public function index() { } // admin.users.index
}
Attributo #[CustomPermission]
Personalizza i metadati del permesso (titolo, descrizione, ordinamento) mantenendo l'azione uguale al nome del metodo.
L'azione del permesso è sempre il nome del metodo. #[CustomPermission] serve solo per personalizzare il titolo, la descrizione e l'ordinamento, non il nome dell'azione.
Utilizzo
use App\Shared\Attributes\Permissions\CustomPermission;
class UserController extends Controller
{
#[CustomPermission(title: 'Esportazione multipla utenti')]
public function exportUsers() { }
// Genera: shared.users.exportUsers
// Con titolo personalizzato: "Esportazione multipla utenti"
}
Parametri
| Parametro | Tipo | Richiesto | Descrizione |
|---|---|---|---|
title | string|null | ❌ | Titolo personalizzato del permesso (se null, usa auto-generazione) |
description | string|null | ❌ | Descrizione opzionale del permesso |
order | int|null | ❌ | Ordine per il sorting nell'interfaccia (0-9999) |
Regole di Validazione
- Title:
- Caratteri consentiti: lettere, numeri, spazi e caratteri di punteggiatura comuni
- Lunghezza massima: 255 caratteri
- Non consentiti: caratteri HTML pericolosi (
<>"') - Opzionale: se non specificato, viene usata l'auto-generazione
- Limitazione: solo un attributo
CustomPermissionper metodo - Order: deve essere un numero intero tra 0 e 9999 (numeri più bassi appaiono prima)
Esempi Avanzati
Titoli Descrittivi con Ordinamento
class DocumentController extends Controller
{
#[CustomPermission(
title: 'Visualizzare documento',
description: 'View document details',
order: 10
)]
public function show() { }
// Genera: shared.documents.show
Personalizzazione Titoli per Report
class ReportController extends Controller
{
#[CustomPermission(
title: 'Generare report PDF',
description: 'Generate PDF reports',
order: 1
)]
public function generatePdf() { }
// Genera: shared.reports.generatePdf
#[CustomPermission(
title: 'Programmare generazione automatica',
description: 'Schedule automatic report generation',
order: 99
)]
public function scheduleGeneration() { }
// Genera: shared.reports.scheduleGeneration
}
Attributo #[ExcludeFromPermissions]
Esclude metodi specifici dalla generazione automatica dei permessi.
Utilizzo
use App\Shared\Attributes\Permissions\ExcludeFromPermissions;
class UserController extends Controller
{
public function index() { } // ✅ Genera permesso
#[ExcludeFromPermissions]
public function healthCheck() { } // ❌ Nessun permesso
#[ExcludeFromPermissions(reason: 'Public endpoint')]
public function publicInfo() { } // ❌ Nessun permesso
}
Parametri
| Parametro | Tipo | Richiesto | Descrizione |
|---|---|---|---|
reason | string|null | ❌ | Motivo dell'esclusione (per documentazione) |
Casi d'Uso Comuni
Endpoint Pubblici
class ApiController extends Controller
{
#[ExcludeFromPermissions(reason: 'Public API endpoint')]
public function version() { }
#[ExcludeFromPermissions(reason: 'Health check endpoint')]
public function health() { }
public function users() { } // Richiede permesso
}
Metodi di Utility
class BaseController extends Controller
{
#[ExcludeFromPermissions(reason: 'Internal helper method')]
public function validateInput() { }
#[ExcludeFromPermissions(reason: 'Response formatting')]
public function formatResponse() { }
public function getData() { } // Richiede permesso
}
Sistema di Priorità per i Titoli
Il sistema AutoPermissions gestisce i titoli dei permessi con una logica di priorità intelligente:
Priorità dei Titoli
-
Titolo Personalizzato (massima priorità)
- Se specificato nell'attributo
#[CustomPermission(title: '...')] - Viene sempre utilizzato, sovrascrivendo qualsiasi altro titolo
- Se specificato nell'attributo
-
Titolo Auto-generato (priorità media)
- Se non è specificato un titolo personalizzato
- Utilizza le traduzioni dal file di lingua
lang/it/permissions.php - Formato:
{azione} {risorsa}(es: "Visualizzare utenti")
-
Nessun Titolo (priorità minima)
- Se entrambi i metodi falliscono
- Il campo
titlerimane vuoto
Esempi di Priorità
class UserController extends Controller
{
// ✅ Priorità 1: Titolo personalizzato
#[CustomPermission(title: 'Eliminazione multipla di utenti')]
public function deleteMultiple() { }
// Genera: shared.users.deleteMultiple
// Titolo: "Eliminazione multipla di utenti"
// ✅ Priorità 2: Titolo auto-generato
public function exportUsers() { }
// Genera: shared.users.exportUsers
// Titolo: "Esportare utenti" (dalle traduzioni)
}
Combinazione di Attributi
Gli attributi possono essere combinati per configurazioni complesse:
Esempio Completo
#[AutoPermissions(excludeMethods: ['health', 'version'])]
#[PermissionNaming(resourceName: 'api_users', moduleName: 'api')]
class ApiUserController extends Controller
{
// Escluso tramite AutoPermissions
public function health() { }
// Escluso tramite AutoPermissions
public function version() { }
// Escluso tramite attributo specifico
#[ExcludeFromPermissions(reason: 'Public documentation')]
public function docs() { }
// Permesso personalizzato
#[CustomPermission(
title: 'Operazioni multiple su utenti',
description: 'Esegue operazioni su più utenti contemporaneamente'
)]
public function bulkUpdate() { }
// Genera: api.api_users.bulkUpdate
// Permesso standard
public function index() { }
// Genera: api.api_users.index
}
Errori Comuni e Troubleshooting
Errore: Caratteri Non Validi
// ❌ ERRORE
#[PermissionNaming(resourceName: 'User-Profiles', moduleName: 'shared')]
// InvalidArgumentException: contains invalid characters
// ✅ CORRETTO
#[PermissionNaming(resourceName: 'user_profiles', moduleName: 'shared')]
Errore: Attributi Multipli
// ❌ ERRORE: Solo un CustomPermission per metodo
#[CustomPermission(title: 'Creare utente')]
#[CustomPermission(title: 'Salvare utente')]
public function createUser() { }
// ✅ CORRETTO
#[CustomPermission(title: 'Creare e salvare utente')]
public function createUser() { }
// Genera: shared.users.createUser
Errore: Titolo con Caratteri Non Validi
// ❌ ERRORE
#[CustomPermission(title: 'Eliminare <utente>')]
// InvalidArgumentException: contains potentially dangerous characters
// ✅ CORRETTO
#[CustomPermission(title: 'Eliminare utente')]
public function delete() { }
// Genera: shared.users.delete
Best Practices
1. Naming Consistente
// ✅ Usa convenzioni chiare
#[PermissionNaming(resourceName: 'user_documents', moduleName: 'admin')]
// ❌ Evita nomi ambigui
#[PermissionNaming(resourceName: 'docs', moduleName: 'a')]
2. Documentazione delle Esclusioni
// ✅ Sempre specifica il motivo
#[ExcludeFromPermissions(reason: 'Public health check endpoint')]
public function health() { }
// ❌ Evita esclusioni senza motivo
#[ExcludeFromPermissions]
public function someMethod() { }
3. Risoluzione Proattiva dei Conflitti
// ✅ Usa prefissi per evitare conflitti
#[PermissionNaming(resourceName: 'users', moduleName: 'admin')]
class AdminUserController { }
#[PermissionNaming(resourceName: 'users', moduleName: 'api')]
class ApiUserController { }
4. Ordinamento Logico dei Permessi
class UserController extends Controller
{
// ✅ Usa order per raggruppare logicamente
#[CustomPermission(order: 1)]
public function show() { } // Lettura
#[CustomPermission(order: 10)]
public function create() { } // Creazione
#[CustomPermission(order: 20)]
public function update() { } // Modifica
#[CustomPermission(order: 30)]
public function destroy() { } // Eliminazione
#[CustomPermission(order: 40)]
public function export() { } // Export
#[CustomPermission(order: 100)]
public function adminAccess() { } // Admin
// ❌ Evita order casuali
#[CustomPermission(order: 5)]
public function destroy() { } // Eliminazione prima della lettura
#[CustomPermission(order: 50)]
public function show() { } // Lettura dopo operazioni avanzate
}