📋 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
1063 lines
30 KiB
Markdown
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**
|