netgescon-master/docs/06-SISTEMA-MULTI-RUOLO.md
Pikappa2 480e7eafbd 🎯 NETGESCON - Setup iniziale repository completo
📋 Commit iniziale con:
-  Documentazione unificata in docs/
-  Codice Laravel in netgescon-laravel/
-  Script automazione in scripts/
-  Configurazione sync rsync
-  Struttura organizzata e pulita

🔄 Versione: 2025.07.19-1644
🎯 Sistema pronto per Git distribuito
2025-07-19 16:44:47 +02:00

1063 lines
30 KiB
Markdown

# 6. SISTEMA MULTI-RUOLO - GUIDA COMPLETA
## 📋 **INDICE CAPITOLO**
- [6.1 Architettura Ruoli e Permessi](#61-architettura-ruoli-e-permessi)
- [6.2 Configurazione Spatie Permission](#62-configurazione-spatie-permission)
- [6.3 Modelli e Relazioni](#63-modelli-e-relazioni)
- [6.4 Seeder Ruoli e Permessi](#64-seeder-ruoli-e-permessi)
- [6.5 Middleware di Protezione](#65-middleware-di-protezione)
- [6.6 Controllers per Ruoli](#66-controllers-per-ruoli)
- [6.7 Dashboard Condizionali](#67-dashboard-condizionali)
- [6.8 Gestione Utenti](#68-gestione-utenti)
- [6.9 Esempi Pratici](#69-esempi-pratici)
---
## 6.1 Architettura Ruoli e Permessi
### Gerarchia Ruoli NetGescon
```
SuperAdmin
├── Accesso completo sistema
├── Gestione utenti e ruoli
├── Configurazione globale
├── Archivi base (comuni)
└── Monitoring e logs
Admin
├── Gestione completa stabili assegnati
├── CRUD completo tutti i dati
├── Contabilità e documenti
├── Comunicazioni condomini
└── Backup e reports
Amministratore
├── Gestione stabili assegnati
├── CRUD limitato (no delete critici)
├── Contabilità base
├── Documenti e comunicazioni
└── Reports stabili
Condomino
├── Visualizzazione dati personali
├── Documenti unità di proprietà
├── Comunicazioni con amministratore
├── Consultazione movimenti
└── Modifica profilo personale
```
### Matrice Permessi Dettagliata
```
FUNZIONALITÀ | SuperAdmin | Admin | Amministratore | Condomino
-----------------------|------------|-------|----------------|----------
Gestione Utenti | ✅ | ❌ | ❌ | ❌
Comuni Italiani | ✅ | ❌ | ❌ | ❌
Stabili (CRUD) | ✅ | ✅ | ✅ | ❌
Unità Immobiliari | ✅ | ✅ | ✅ | 👁️
Soggetti (CRUD) | ✅ | ✅ | ✅ | ❌
Documenti (Upload) | ✅ | ✅ | ✅ | ❌
Documenti (Download) | ✅ | ✅ | ✅ | ✅
Contabilità (CRUD) | ✅ | ✅ | ⚠️ | 👁️
Tickets (Gestione) | ✅ | ✅ | ✅ | 📝
Backup Sistema | ✅ | ✅ | ❌ | ❌
Reports Avanzati | ✅ | ✅ | ⚠️ | ❌
```
*Legenda: ✅ = Completo, ⚠️ = Limitato, 👁️ = Solo visualizzazione, 📝 = Creazione/Risposta, ❌ = Negato*
---
## 6.2 Configurazione Spatie Permission
### Installazione Package
```bash
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
```
### Configurazione
**File**: `config/permission.php`
```php
<?php
return [
'models' => [
'permission' => Spatie\Permission\Models\Permission::class,
'role' => Spatie\Permission\Models\Role::class,
],
'table_names' => [
'roles' => 'roles',
'permissions' => 'permissions',
'model_has_permissions' => 'model_has_permissions',
'model_has_roles' => 'model_has_roles',
'role_has_permissions' => 'role_has_permissions',
],
'column_names' => [
'role_pivot_key' => null,
'permission_pivot_key' => null,
'model_morph_key' => 'model_id',
'team_foreign_key' => 'team_id',
],
'register_permission_check_method' => true,
'teams' => false,
'use_passport_client_credentials' => false,
'display_permission_in_exception' => false,
'display_role_in_exception' => false,
'enable_wildcard_permission' => false,
'cache' => [
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
'key' => 'spatie.permission.cache',
'store' => 'default',
],
];
```
### Registrazione Middleware
**File**: `app/Http/Kernel.php`
```php
protected $routeMiddleware = [
// ...existing middleware...
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
```
---
## 6.3 Modelli e Relazioni
### Modello User Esteso
**File**: `app/Models/User.php`
```php
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasRoles, Notifiable;
protected $fillable = [
'name',
'email',
'password',
'is_active',
'last_login_at',
'profile_photo_path',
'phone',
'address',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'last_login_at' => 'datetime',
'is_active' => 'boolean',
];
// Relazioni
public function stabiliAmministrati()
{
return $this->hasMany(Stabile::class, 'amministratore_id');
}
public function unitaImmobiliari()
{
return $this->belongsToMany(UnitaImmobiliare::class, 'diritti_reali')
->withPivot('tipo_diritto', 'quota_proprieta', 'data_inizio', 'data_fine')
->withTimestamps();
}
public function tickets()
{
return $this->hasMany(Ticket::class);
}
// Helper methods
public function isSuperAdmin(): bool
{
return $this->hasRole('super-admin');
}
public function isAdmin(): bool
{
return $this->hasRole('admin');
}
public function isAmministratore(): bool
{
return $this->hasRole('amministratore');
}
public function isCondomino(): bool
{
return $this->hasRole('condomino');
}
public function canManageStabile(Stabile $stabile): bool
{
if ($this->isSuperAdmin()) {
return true;
}
if ($this->isAdmin() || $this->isAmministratore()) {
return $this->stabiliAmministrati()->where('id', $stabile->id)->exists();
}
return false;
}
public function canAccessUnita(UnitaImmobiliare $unita): bool
{
if ($this->isSuperAdmin()) {
return true;
}
if ($this->isAdmin() || $this->isAmministratore()) {
return $this->canManageStabile($unita->stabile);
}
if ($this->isCondomino()) {
return $this->unitaImmobiliari()->where('id', $unita->id)->exists();
}
return false;
}
public function getDisplayRoleName(): string
{
$roleNames = [
'super-admin' => 'Super Amministratore',
'admin' => 'Amministratore',
'amministratore' => 'Amministratore Condominio',
'condomino' => 'Condomino',
];
$role = $this->getRoleNames()->first();
return $roleNames[$role] ?? 'Utente';
}
public function getRoleColor(): string
{
$roleColors = [
'super-admin' => 'danger',
'admin' => 'primary',
'amministratore' => 'warning',
'condomino' => 'success',
];
$role = $this->getRoleNames()->first();
return $roleColors[$role] ?? 'secondary';
}
}
```
### Modello Stabile con Controlli Accesso
**File**: `app/Models/Stabile.php`
```php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Stabile extends Model
{
protected $fillable = [
'denominazione',
'indirizzo',
'comune_id',
'cap',
'codice_fiscale',
'partita_iva',
'amministratore_id',
'is_active',
'note',
];
protected $casts = [
'is_active' => 'boolean',
];
// Relazioni
public function amministratore(): BelongsTo
{
return $this->belongsTo(User::class, 'amministratore_id');
}
public function comune(): BelongsTo
{
return $this->belongsTo(ComuneItaliano::class, 'comune_id');
}
public function unitaImmobiliari(): HasMany
{
return $this->hasMany(UnitaImmobiliare::class);
}
public function documenti(): HasMany
{
return $this->hasMany(Documento::class);
}
public function tickets(): HasMany
{
return $this->hasMany(Ticket::class);
}
public function movimentiBancari(): HasMany
{
return $this->hasMany(MovimentoBancario::class);
}
// Scope per filtri di accesso
public function scopeAccessibleBy($query, User $user)
{
if ($user->isSuperAdmin()) {
return $query;
}
if ($user->isAdmin() || $user->isAmministratore()) {
return $query->where('amministratore_id', $user->id);
}
if ($user->isCondomino()) {
return $query->whereHas('unitaImmobiliari.soggetti', function($q) use ($user) {
$q->where('users.id', $user->id);
});
}
return $query->whereRaw('1 = 0'); // Nessun accesso
}
// Helper methods
public function getIndirizzoCompleto(): string
{
$indirizzo = $this->indirizzo;
if ($this->comune) {
$indirizzo .= ', ' . $this->comune->denominazione;
}
if ($this->cap) {
$indirizzo .= ' (' . $this->cap . ')';
}
return $indirizzo;
}
public function getTotalUnita(): int
{
return $this->unitaImmobiliari()->count();
}
public function getTotalMillesimi(): float
{
return $this->unitaImmobiliari()->sum('millesimi_proprieta');
}
}
```
---
## 6.4 Seeder Ruoli e Permessi
### Seeder Completo
**File**: `database/seeders/RolesAndPermissionsSeeder.php`
```php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RolesAndPermissionsSeeder extends Seeder
{
public function run(): void
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Definizione permessi organizzati per area
$permissions = [
// Gestione Utenti
'users.view',
'users.create',
'users.edit',
'users.delete',
'users.assign-roles',
'users.toggle-status',
// Gestione Stabili
'stabili.view',
'stabili.create',
'stabili.edit',
'stabili.delete',
'stabili.assign-admin',
// Gestione Unità Immobiliari
'unita.view',
'unita.create',
'unita.edit',
'unita.delete',
'unita.assign-soggetti',
// Gestione Soggetti
'soggetti.view',
'soggetti.create',
'soggetti.edit',
'soggetti.delete',
'soggetti.merge',
// Gestione Documenti
'documenti.view',
'documenti.upload',
'documenti.download',
'documenti.delete',
'documenti.share',
// Gestione Contabilità
'contabilita.view',
'contabilita.create',
'contabilita.edit',
'contabilita.delete',
'contabilita.reports',
'contabilita.export',
// Gestione Tickets
'tickets.view',
'tickets.create',
'tickets.edit',
'tickets.delete',
'tickets.assign',
'tickets.close',
// Configurazione Sistema
'system.config',
'system.backup',
'system.logs',
'system.maintenance',
// Archivi Base
'comuni.view',
'comuni.edit',
'comuni.import',
];
// Crea tutti i permessi
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
// Creazione ruoli
$superAdmin = Role::create(['name' => 'super-admin']);
$admin = Role::create(['name' => 'admin']);
$amministratore = Role::create(['name' => 'amministratore']);
$condomino = Role::create(['name' => 'condomino']);
// SuperAdmin: tutti i permessi
$superAdmin->givePermissionTo(Permission::all());
// Admin: tutti tranne configurazione sistema
$admin->givePermissionTo([
'stabili.view', 'stabili.create', 'stabili.edit', 'stabili.delete',
'unita.view', 'unita.create', 'unita.edit', 'unita.delete', 'unita.assign-soggetti',
'soggetti.view', 'soggetti.create', 'soggetti.edit', 'soggetti.delete', 'soggetti.merge',
'documenti.view', 'documenti.upload', 'documenti.download', 'documenti.delete', 'documenti.share',
'contabilita.view', 'contabilita.create', 'contabilita.edit', 'contabilita.delete', 'contabilita.reports', 'contabilita.export',
'tickets.view', 'tickets.create', 'tickets.edit', 'tickets.delete', 'tickets.assign', 'tickets.close',
'system.backup', 'system.logs',
]);
// Amministratore: gestione limitata
$amministratore->givePermissionTo([
'stabili.view', 'stabili.edit',
'unita.view', 'unita.create', 'unita.edit', 'unita.assign-soggetti',
'soggetti.view', 'soggetti.create', 'soggetti.edit',
'documenti.view', 'documenti.upload', 'documenti.download', 'documenti.share',
'contabilita.view', 'contabilita.create', 'contabilita.edit', 'contabilita.reports',
'tickets.view', 'tickets.create', 'tickets.edit', 'tickets.assign', 'tickets.close',
]);
// Condomino: solo visualizzazione e interazione limitata
$condomino->givePermissionTo([
'unita.view',
'documenti.view', 'documenti.download',
'contabilita.view',
'tickets.view', 'tickets.create',
]);
}
}
```
### Seeder Utenti Base
**File**: `database/seeders/UserSeeder.php`
```php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
class UserSeeder extends Seeder
{
public function run(): void
{
// SuperAdmin
$superAdmin = User::create([
'name' => 'Super Amministratore',
'email' => 'superadmin@netgescon.it',
'password' => Hash::make('password'),
'is_active' => true,
'email_verified_at' => now(),
]);
$superAdmin->assignRole('super-admin');
// Admin
$admin = User::create([
'name' => 'Amministratore Principale',
'email' => 'admin@netgescon.it',
'password' => Hash::make('password'),
'is_active' => true,
'email_verified_at' => now(),
]);
$admin->assignRole('admin');
// Amministratore Condominio
$amministratore = User::create([
'name' => 'Mario Rossi',
'email' => 'mario.rossi@netgescon.it',
'password' => Hash::make('password'),
'is_active' => true,
'email_verified_at' => now(),
]);
$amministratore->assignRole('amministratore');
// Condomino
$condomino = User::create([
'name' => 'Luigi Bianchi',
'email' => 'luigi.bianchi@netgescon.it',
'password' => Hash::make('password'),
'is_active' => true,
'email_verified_at' => now(),
]);
$condomino->assignRole('condomino');
}
}
```
---
## 6.5 Middleware di Protezione
### Middleware Personalizzato
**File**: `app/Http/Middleware/RoleAccessMiddleware.php`
```php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RoleAccessMiddleware
{
public function handle(Request $request, Closure $next, ...$roles)
{
if (!Auth::check()) {
return redirect()->route('login');
}
$user = Auth::user();
// Verifica se utente è attivo
if (!$user->is_active) {
Auth::logout();
return redirect()->route('login')
->with('error', 'Account disattivato. Contatta l\'amministratore.');
}
// Verifica ruoli
if (!$user->hasAnyRole($roles)) {
abort(403, 'Accesso non autorizzato per questo ruolo.');
}
// Aggiorna ultimo login
$user->update(['last_login_at' => now()]);
return $next($request);
}
}
```
### Middleware Permessi Specifici
**File**: `app/Http/Middleware/PermissionMiddleware.php`
```php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class PermissionMiddleware
{
public function handle(Request $request, Closure $next, $permission)
{
if (!Auth::check()) {
return redirect()->route('login');
}
$user = Auth::user();
if (!$user->can($permission)) {
if ($request->ajax()) {
return response()->json([
'error' => 'Permesso negato',
'message' => "Non hai i permessi per: {$permission}"
], 403);
}
abort(403, "Permesso negato: {$permission}");
}
return $next($request);
}
}
```
---
## 6.6 Controllers per Ruoli
### Controller SuperAdmin
**File**: `app/Http/Controllers/SuperAdmin/SuperAdminDashboardController.php`
```php
<?php
namespace App\Http\Controllers\SuperAdmin;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Stabile;
use App\Models\ComuneItaliano;
use App\Models\Ticket;
class SuperAdminDashboardController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'role:super-admin']);
}
public function index()
{
$stats = [
'users_total' => User::count(),
'users_active' => User::where('is_active', true)->count(),
'stabili_total' => Stabile::count(),
'stabili_active' => Stabile::where('is_active', true)->count(),
'comuni_loaded' => ComuneItaliano::count(),
'tickets_open' => Ticket::where('stato', 'aperto')->count(),
'users_by_role' => User::join('model_has_roles', 'users.id', '=', 'model_has_roles.model_id')
->join('roles', 'model_has_roles.role_id', '=', 'roles.id')
->selectRaw('roles.name, COUNT(*) as count')
->groupBy('roles.name')
->pluck('count', 'name')
->toArray(),
];
return view('superadmin.dashboard', [
'pageTitle' => 'Dashboard Super Amministratore',
'stats' => $stats,
]);
}
}
```
### Controller Admin
**File**: `app/Http/Controllers/Admin/AdminDashboardController.php`
```php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Stabile;
use App\Models\UnitaImmobiliare;
use App\Models\Documento;
use App\Models\Ticket;
use App\Models\MovimentoBancario;
use Illuminate\Support\Facades\Auth;
class AdminDashboardController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'role:admin|amministratore']);
}
public function index()
{
$user = Auth::user();
$stabiliIds = $user->stabiliAmministrati()->pluck('id');
$stats = [
'stabili_count' => $stabiliIds->count(),
'stabili_attivi' => $user->stabiliAmministrati()->where('is_active', true)->count(),
'unita_total' => UnitaImmobiliare::whereIn('stabile_id', $stabiliIds)->count(),
'documenti_count' => Documento::whereIn('stabile_id', $stabiliIds)->count(),
'documenti_mese' => Documento::whereIn('stabile_id', $stabiliIds)
->whereMonth('created_at', now()->month)
->count(),
'tickets_aperti' => Ticket::whereIn('stabile_id', $stabiliIds)
->where('stato', 'aperto')->count(),
'tickets_totali' => Ticket::whereIn('stabile_id', $stabiliIds)->count(),
'saldo_totale' => MovimentoBancario::whereIn('stabile_id', $stabiliIds)
->sum('importo'),
'condomini_count' => UnitaImmobiliare::whereIn('stabile_id', $stabiliIds)
->has('soggetti')->count(),
'proprietari_count' => UnitaImmobiliare::whereIn('stabile_id', $stabiliIds)
->whereHas('soggetti', function($q) {
$q->where('tipo_diritto', 'proprietario');
})->count(),
'movimenti_count' => MovimentoBancario::whereIn('stabile_id', $stabiliIds)->count(),
];
return view('admin.dashboard', [
'pageTitle' => 'Dashboard Amministrazione',
'stats' => $stats,
'user' => $user,
]);
}
}
```
### Controller Condomino
**File**: `app/Http/Controllers/Condomino/CondominoDashboardController.php`
```php
<?php
namespace App\Http\Controllers\Condomino;
use App\Http\Controllers\Controller;
use App\Models\UnitaImmobiliare;
use App\Models\Documento;
use App\Models\Ticket;
use App\Models\MovimentoBancario;
use Illuminate\Support\Facades\Auth;
class CondominoDashboardController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'role:condomino']);
}
public function index()
{
$user = Auth::user();
$unitaIds = $user->unitaImmobiliari()->pluck('unita_immobiliari.id');
$stabiliIds = $user->unitaImmobiliari()->pluck('stabile_id');
$stats = [
'unita_count' => $unitaIds->count(),
'documenti_count' => Documento::whereIn('stabile_id', $stabiliIds)->count(),
'tickets_aperti' => Ticket::where('user_id', $user->id)
->where('stato', 'aperto')->count(),
'tickets_totali' => Ticket::where('user_id', $user->id)->count(),
'movimenti_mese' => MovimentoBancario::whereIn('stabile_id', $stabiliIds)
->whereMonth('data_movimento', now()->month)
->count(),
];
$unita = $user->unitaImmobiliari()
->with(['stabile', 'stabile.comune'])
->get();
return view('condomino.dashboard', [
'pageTitle' => 'Area Condomino',
'stats' => $stats,
'unita' => $unita,
'user' => $user,
]);
}
}
```
---
## 6.7 Dashboard Condizionali
### Router Principale
**File**: `app/Http/Controllers/DashboardController.php`
```php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class DashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$user = Auth::user();
// Redirect in base al ruolo
if ($user->hasRole('super-admin')) {
return redirect()->route('superadmin.dashboard');
}
if ($user->hasAnyRole(['admin', 'amministratore'])) {
return redirect()->route('admin.dashboard');
}
if ($user->hasRole('condomino')) {
return redirect()->route('condomino.dashboard');
}
// Fallback per utenti senza ruolo
return view('dashboard.no-role', [
'pageTitle' => 'Accesso Negato',
'message' => 'Nessun ruolo assegnato. Contatta l\'amministratore.',
]);
}
}
```
---
## 6.8 Gestione Utenti
### Form Assegnazione Ruoli
**File**: `resources/views/superadmin/users/edit-roles.blade.php`
```blade
<form action="{{ route('superadmin.users.update-roles', $user) }}" method="POST">
@csrf
@method('PUT')
<div class="card">
<div class="card-header">
<h5>Gestione Ruoli: {{ $user->name }}</h5>
</div>
<div class="card-body">
<div class="row">
@foreach($roles as $role)
<div class="col-md-6 mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="roles[]" value="{{ $role->name }}"
id="role_{{ $role->id }}"
{{ $user->hasRole($role->name) ? 'checked' : '' }}>
<label class="form-check-label" for="role_{{ $role->id }}">
<strong>{{ $role->name }}</strong>
<small class="text-muted d-block">
{{ $roleDescriptions[$role->name] ?? '' }}
</small>
</label>
</div>
</div>
@endforeach
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save me-2"></i>Salva Ruoli
</button>
<a href="{{ route('superadmin.users.index') }}" class="btn btn-secondary">
<i class="fas fa-times me-2"></i>Annulla
</a>
</div>
</div>
</form>
```
### Controller Gestione Ruoli
**File**: `app/Http/Controllers/SuperAdmin/UserRoleController.php`
```php
<?php
namespace App\Http\Controllers\SuperAdmin;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
class UserRoleController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'role:super-admin']);
}
public function editRoles(User $user)
{
$roles = Role::all();
$roleDescriptions = [
'super-admin' => 'Accesso completo al sistema',
'admin' => 'Gestione completa stabili assegnati',
'amministratore' => 'Gestione limitata stabili assegnati',
'condomino' => 'Visualizzazione dati personali',
];
return view('superadmin.users.edit-roles', compact('user', 'roles', 'roleDescriptions'));
}
public function updateRoles(Request $request, User $user)
{
$request->validate([
'roles' => 'array',
'roles.*' => 'exists:roles,name',
]);
$user->syncRoles($request->get('roles', []));
return redirect()->route('superadmin.users.index')
->with('success', "Ruoli aggiornati per {$user->name}");
}
}
```
---
## 6.9 Esempi Pratici
### Verifica Permessi in Blade
```blade
@can('stabili.create')
<a href="{{ route('admin.stabili.create') }}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>Nuovo Stabile
</a>
@endcan
@role('super-admin')
<div class="alert alert-info">
<i class="fas fa-crown me-2"></i>
Modalità Super Amministratore attiva
</div>
@endrole
@hasrole('admin|amministratore')
<div class="card">
<div class="card-header">Pannello Gestione</div>
<!-- Contenuto per admin -->
</div>
@endhasrole
```
### Controllo Accesso in Controller
```php
public function show(Stabile $stabile)
{
$user = Auth::user();
// Verifica accesso al singolo stabile
if (!$user->canManageStabile($stabile)) {
abort(403, 'Non puoi accedere a questo stabile');
}
return view('admin.stabili.show', compact('stabile'));
}
```
### Policy per Modelli
**File**: `app/Policies/StabilePolicy.php`
```php
<?php
namespace App\Policies;
use App\Models\Stabile;
use App\Models\User;
class StabilePolicy
{
public function viewAny(User $user): bool
{
return $user->can('stabili.view');
}
public function view(User $user, Stabile $stabile): bool
{
return $user->can('stabili.view') && $user->canManageStabile($stabile);
}
public function create(User $user): bool
{
return $user->can('stabili.create');
}
public function update(User $user, Stabile $stabile): bool
{
return $user->can('stabili.edit') && $user->canManageStabile($stabile);
}
public function delete(User $user, Stabile $stabile): bool
{
return $user->can('stabili.delete') && $user->canManageStabile($stabile);
}
}
```
---
**📝 COMPLETATO: Capitolo 6 - Sistema Multi-Ruolo**
Questo capitolo fornisce una guida completa per:
- ✅ Configurare architettura ruoli e permessi
- ✅ Implementare Spatie Permission
- ✅ Creare modelli con controlli accesso
- ✅ Configurare seeder ruoli e permessi
- ✅ Implementare middleware protezione
- ✅ Creare controllers per ogni ruolo
- ✅ Gestire dashboard condizionali
- ✅ Amministrare utenti e ruoli
- ✅ Esempi pratici implementazione
**🔄 Prossimo capitolo: Database e Strutture Avanzate**