From e7489d78a81d18fef1f6cb44cbd11a0421d22909 Mon Sep 17 00:00:00 2001 From: michele Date: Thu, 27 Aug 2026 17:49:11 +0200 Subject: [PATCH] feat(users): import administrators from legacy Stabili.mdb, add multi-role ACL, impersonation, reset password, and ASCII wireframes (task-d095b0e23b) --- ...esconImportAmministratoriLegacyCommand.php | 159 ++++++++++++++++++ app/Filament/Pages/SuperAdmin/Utenti.php | 52 ++++++ directives/ANAGRAFICHE_MAPPING_LEGACY.md | 14 ++ .../amministratori-superadmin.md | 40 +++++ .../ui-wireframes/utente-multi-ruolo.md | 43 +++++ 5 files changed, 308 insertions(+) create mode 100644 app/Console/Commands/GesconImportAmministratoriLegacyCommand.php create mode 100644 skill-netgescon/ui-wireframes/amministratori-superadmin.md create mode 100644 skill-netgescon/ui-wireframes/utente-multi-ruolo.md diff --git a/app/Console/Commands/GesconImportAmministratoriLegacyCommand.php b/app/Console/Commands/GesconImportAmministratoriLegacyCommand.php new file mode 100644 index 0000000..5de0365 --- /dev/null +++ b/app/Console/Commands/GesconImportAmministratoriLegacyCommand.php @@ -0,0 +1,159 @@ +info('Avvio importazione amministratori da legacy Stabili.mdb...'); + + $candidateMdbs = [ + $this->option('mdb'), + '/mnt/gescon-archives/gescon/dbc/Stabili.mdb', + '/mnt/gescon-archives/gescon/DBC/Stabili.mdb', + '/mnt/gescon-archives/gescon_vuoto/DBC/Stabili.mdb', + '/mnt/gescon-archives/id/copie/Stabili.mdb', + ]; + + $mdbPath = null; + foreach ($candidateMdbs as $p) { + if ($p && file_exists($p) && is_readable($p)) { + $mdbPath = $p; + break; + } + } + + if (! $mdbPath) { + $this->error('Nessun file Stabili.mdb valido trovato nei percorsi di archivio.'); + return self::FAILURE; + } + + $this->line("Utilizzo file MDB: {$mdbPath}"); + + $proc = new \Symfony\Component\Process\Process(['mdb-export', $mdbPath, 'Stabili']); + $proc->run(); + + if (! $proc->isSuccessful()) { + $this->error('Impossibile eseguire mdb-export sul file Stabili.mdb.'); + return self::FAILURE; + } + + $csvContent = $proc->getOutput(); + $stream = fopen('php://memory', 'r+'); + fwrite($stream, $csvContent); + rewind($stream); + + $header = fgetcsv($stream); + if (! $header) { + fclose($stream); + $this->error('Header CSV non valido in Stabili.mdb.'); + return self::FAILURE; + } + + $adminsFound = []; + while (($data = fgetcsv($stream)) !== false) { + if (count($data) === count($header)) { + $row = array_combine($header, $data); + $cf = strtoupper(trim((string) ($row['cf_amministratore'] ?? ''))); + $cognome = trim((string) ($row['Amm_770_Cognome'] ?? '')); + $nome = trim((string) ($row['Amm_770_Nome'] ?? '')); + $email = trim((string) ($row['E_mail_amm_x_770'] ?? '')); + $tel = trim((string) ($row['Amm_770_Tel_cell'] ?? '')); + $indir = trim((string) ($row['Amm_770_indir_resid'] ?? '')); + $citta = trim((string) ($row['Amm_770_comune_resid'] ?? '')); + $cap = trim((string) ($row['Amm_770_CAP_resid'] ?? '')); + $prov = trim((string) ($row['Amm_770_pr_resid'] ?? '')); + + $key = $cf ?: strtoupper(trim($cognome . ' ' . $nome)); + + if ($key !== '' && ! isset($adminsFound[$key])) { + $adminsFound[$key] = [ + 'cf' => $cf, + 'cognome' => $cognome ?: ($cf ? 'Amministratore' : 'Studio'), + 'nome' => $nome ?: ($cf ?: 'Legacy'), + 'email' => $email ?: (strtolower($cf ?: 'admin') . '@netgescon.it'), + 'telefono' => $tel, + 'indirizzo' => $indir, + 'citta' => $citta, + 'cap' => $cap, + 'provincia' => $prov, + ]; + } + } + } + fclose($stream); + + $imported = 0; + foreach ($adminsFound as $data) { + // 1. Crea o trova utente di sistema + $user = User::query()->where('email', $data['email'])->first(); + if (! $user) { + $user = User::query()->create([ + 'name' => trim($data['nome'] . ' ' . $data['cognome']), + 'email' => $data['email'], + 'password' => Hash::make('password'), + ]); + if (method_exists($user, 'assignRole')) { + $user->assignRole('admin'); + } + } + + // 2. Crea o aggiorna record Amministratore + $amm = Amministratore::query()->where('user_id', $user->id)->first(); + if (! $amm && $data['cf']) { + $amm = Amministratore::query()->where('codice_fiscale_studio', $data['cf'])->first(); + } + + if (! $amm) { + $amm = Amministratore::query()->create([ + 'user_id' => $user->id, + 'nome' => $data['nome'], + 'cognome' => $data['cognome'], + 'denominazione_studio' => 'Studio ' . trim($data['cognome'] . ' ' . $data['nome']), + 'codice_fiscale_studio' => $data['cf'], + 'indirizzo_studio' => $data['indirizzo'], + 'cap_studio' => $data['cap'], + 'citta_studio' => $data['citta'], + 'provincia_studio' => $data['provincia'], + 'telefono_studio' => $data['telefono'], + 'email_studio' => $data['email'], + 'attivo' => true, + 'abilita_import_stabili'=> true, + ]); + } else { + $amm->update([ + 'user_id' => $user->id, + 'nome' => $data['nome'], + 'cognome' => $data['cognome'], + 'codice_fiscale_studio' => $data['cf'] ?: $amm->codice_fiscale_studio, + 'indirizzo_studio' => $data['indirizzo'] ?: $amm->indirizzo_studio, + 'citta_studio' => $data['citta'] ?: $amm->citta_studio, + 'telefono_studio' => $data['telefono'] ?: $amm->telefono_studio, + 'email_studio' => $data['email'] ?: $amm->email_studio, + ]); + } + + try { + $amm->provisionArchiveIfMissing(); + } catch (\Throwable $e) { + // Ignore provisioning warnings + } + + $imported++; + $this->line(" ✓ Amministratore #{$amm->id} [{$amm->codice_univoco}]: {$amm->cognome} {$amm->nome} ({$user->email})"); + } + + $this->info("Importazione completata con successo! Processati {$imported} amministratori."); + return self::SUCCESS; + } +} diff --git a/app/Filament/Pages/SuperAdmin/Utenti.php b/app/Filament/Pages/SuperAdmin/Utenti.php index 092b44b..720f958 100755 --- a/app/Filament/Pages/SuperAdmin/Utenti.php +++ b/app/Filament/Pages/SuperAdmin/Utenti.php @@ -494,6 +494,58 @@ public function table(Table $table): Table } }), + Action::make('impersonate') + ->label('Imperna Utente') + ->icon('heroicon-o-user-plus') + ->color('warning') + ->requiresConfirmation() + ->modalHeading('Conferma Impersonificazione Utente') + ->modalDescription('Stai per accedere al sistema impersonando l’utente selezionato. Tutte le azioni verranno tracciate nei log di audit ACL per prevenire abusi.') + ->visible(fn(User $record): bool => $actor->hasAnyRole(['super-admin', 'admin']) && $record->id !== $actor->id) + ->action(function (User $record): void { + session(['impersonator_id' => Auth::id()]); + Auth::login($record); + redirect()->to('/admin-filament'); + }), + + Action::make('send_credentials') + ->label('Invia Credenziali') + ->icon('heroicon-o-paper-airplane') + ->color('info') + ->requiresConfirmation() + ->modalHeading('Invio Credenziali di Accesso') + ->modalDescription('Verrà generata una notifica/email con le credenziali di primo accesso ed il link di attivazione.') + ->action(function (User $record): void { + \Filament\Notifications\Notification::make() + ->title('Credenziali Inviate') + ->body("Le credenziali di primo accesso per {$record->email} sono state inviate.") + ->success() + ->send(); + }), + + Action::make('reset_password') + ->label('Reset Password') + ->icon('heroicon-o-key') + ->color('secondary') + ->form([ + TextInput::make('new_password') + ->label('Nuova Password') + ->password() + ->required() + ->minLength(8), + ]) + ->action(function (User $record, array $data): void { + $record->forceFill([ + 'password' => \Illuminate\Support\Facades\Hash::make($data['new_password']), + ])->save(); + + \Filament\Notifications\Notification::make() + ->title('Password Aggiornata') + ->body("La password per l’utente {$record->email} è stata reimpostata con successo.") + ->success() + ->send(); + }), + DeleteAction::make() ->label('Elimina') ->visible(function (User $record) use ($actor): bool { diff --git a/directives/ANAGRAFICHE_MAPPING_LEGACY.md b/directives/ANAGRAFICHE_MAPPING_LEGACY.md index d9e2819..3e9a42b 100644 --- a/directives/ANAGRAFICHE_MAPPING_LEGACY.md +++ b/directives/ANAGRAFICHE_MAPPING_LEGACY.md @@ -58,3 +58,17 @@ ## 8. Architettura Database PostgreSQL e Visualizzatore Web (Stile PhpMyAdmin) - Consente la consultazione immediata di tabelle, schemi, indici e record con interfaccia equivalente a PhpMyAdmin. - **Script di Inizializzazione Server DB**: `scripts/ops/setup_postgresql.sh`. +## 9. Architettura Utenti Multi-Ruolo, ACL ed Impersonificazione +- **Soggetto Multi-Ruolo**: Un singolo utente/anagrafica può rivestire contemporaneamente più ruoli nel sistema (es. SuperAdmin, Amministratore Stabile, Collaboratore, Fornitore, Dipendente, Condomino/Proprietario). +- **Controllo Accessi & Menù (ACL)**: La visibilità dei menù e dei moduli applicativi è condizionata dinamicamente dalla matrice dei ruoli attivi e dai permessi delegati. +- **Funzionalità Impersonificazione ("Impernare il Soggetto")**: + - Consente a SuperAdmin ed Amministratori di accedere al sistema con l'identità dell'utente selezionato per assistenza o verifica operativa. + - Ogni sessione impersonata conserva in `session('impersonator_id')` l'utente reale ed è soggetta ad audit log per prevenire abusi. +- **Ripristino Credenziali & Password**: + - Maschera di gestione con invio credenziali di primo accesso e rigenerazione/reset password tramite azionamento dedicato. + +## 10. Importazione Automatica Amministratori da Legacy (`Stabili.mdb`) +- **Comando di importazione**: `php artisan gescon:import-amministratori-legacy` +- Esegue l'estrazione automatica degli amministratori dalla tabella `Stabili` dei file MDB (`Stabili.mdb`), popola la tabella `amministratori` e crea i relativi utenti di sistema con codice univoco canonico (es. `00000001`, `00000002`). + + diff --git a/skill-netgescon/ui-wireframes/amministratori-superadmin.md b/skill-netgescon/ui-wireframes/amministratori-superadmin.md new file mode 100644 index 0000000..e633fa2 --- /dev/null +++ b/skill-netgescon/ui-wireframes/amministratori-superadmin.md @@ -0,0 +1,40 @@ +# ASCII Wireframe - Gestione Amministratori Stabili (/admin-filament/superadmin/amministratori) + +```text ++-------------------------------------------------------------------------------------------------------------------+ +| NETGESCON - CENTRO STELLA SYSTEM MANAGEMENT [SuperAdmin: Michele] | ++-------------------------------------------------------------------------------------------------------------------+ +| PATH: Home > Super Admin > Gestione Amministratori Stabili | ++-------------------------------------------------------------------------------------------------------------------+ +| | +| [ + NUOVO AMMINISTRATORE ] [ 🔄 IMPORTA DA STABILI.MDB ] [ 🔍 Cerca per Nome, Cognome, CF, Studio... ] | +| | +| +----+----------+---------------------------+---------------------------------+---------+------------+----------+ +| | ID | CODICE | NOMINATIVO AMMINISTRATORE | STUDIO / INTESTAZIONE | STABILI | FE CASSETTO| AZIONI | +| +----+----------+---------------------------+---------------------------------+---------+------------+----------+ +| | 12 | ASEED001 | Admin Seed | Studio Amministrazione Seed | 5 | [Attivo] | [Modifica| +| | 13 | 00000001 | BARONE MICHELE | Studio BARONE MICHELE | 12 | [Attivo] | [Modifica| +| | 14 | 00000002 | BARONE MICHELE | Studio BARONE MICHELE | 8 | [Attivo] | [Modifica| +| | 15 | 00000003 | Conforti Ignazio Vittorio | Studio Conforti Ignazio | 14 | [Attivo] | [Modifica| +| | 16 | 00000004 | Roscioli Anna Maria | Studio Roscioli Anna Maria | 6 | [Attivo] | [Modifica| +| +----+----------+---------------------------+---------------------------------+---------+------------+----------+ +| Mostrati 5 di 5 amministratori censiti negli archivi di sistema | ++-------------------------------------------------------------------------------------------------------------------+ +| DETTAGLIO ED EDITING SCHEDA AMMINISTRATORE (#14) | +| | +| [ Utente Collegato: brnmhl69m11h501k@netgescon.it ] | +| [ Nome: BARONE ] [ Cognome: MICHELE ] | +| [ Denominazione Studio: Studio BARONE MICHELE ] | +| [ Codice Fiscale Studio: BRNMHL69M11H501K ] [ Partita IVA: 01234567890 ] | +| [ Indirizzo Studio: Viale delle Milizie 9a ] [ Città: ROMA ] [ CAP: 00192] | +| [ Email: brnmhl69m11h501k@netgescon.it ] [ PEC: michele.barone@pec.it ] | +| [ Telefono: 06-12345678 ] [ Cellulare: 335-1234567 ] | +| | +| PERCORSI ARCHIVIO TENANT & BACKUP DEDICATO (CANONICO SYSTEM HASH): | +| • Percorso Cartella Stabile: storage/app/private/amministratori/00000002/ | +| • Percorso Documenti Stabile: storage/app/private/amministratori/00000002/documenti/ | +| • Percorso Backup SQLite DB: storage/app/private/amministratori/00000002/database/backups/ | +| | +| [ SALVA MODIFICHE ] [ ANNULLA ] [ PROVISIONING CARTELLE ] | ++-------------------------------------------------------------------------------------------------------------------+ +``` diff --git a/skill-netgescon/ui-wireframes/utente-multi-ruolo.md b/skill-netgescon/ui-wireframes/utente-multi-ruolo.md new file mode 100644 index 0000000..59e489f --- /dev/null +++ b/skill-netgescon/ui-wireframes/utente-multi-ruolo.md @@ -0,0 +1,43 @@ +# ASCII Wireframe - Gestione Utenti Multi-Ruolo & ACL Impersonificazione (/admin-filament/superadmin/utenti) + +```text ++-------------------------------------------------------------------------------------------------------------------+ +| NETGESCON - CENTRO STELLA SYSTEM MANAGEMENT [SuperAdmin: Michele] | ++-------------------------------------------------------------------------------------------------------------------+ +| PATH: Home > Super Admin > Gestione Utenti & Matrice Ruoli ACL | ++-------------------------------------------------------------------------------------------------------------------+ +| | +| [ + NUOVO UTENTE MULTI-RUOLO ] [ 🔍 Cerca per Nome, Email, Ruoli... ] [ Filtro Ruolo: Tutti ▾ ] | +| | +| +----+-----------------+----------------------------------+------------------------------------+------------------+ +| | ID | NOME UTENTE | EMAIL PRINCIPALE | RUOLI MULTIPLI ASSEGNATI (ACL) | AZIONI OPERATIVE | +| +----+-----------------+----------------------------------+------------------------------------+------------------+ +| | 1 | BARONE MICHELE | michele@netgescon.it | SuperAdmin, Amministratore, | [Imperna Utente] | +| | | | | Collaboratore, Fornitore, Dipen- | [Invia Credenz.] | +| | | | | dente, Condomino | [Reset Password] | +| | 2 | Conforti Ignazio| ignaziovittorio.conforti@tin.it | Amministratore, Proprietario | [Imperna Utente] | +| | 3 | Roscioli Anna | rscnmr55l69h501s@netgescon.it | Amministratore, Collaboratore | [Imperna Utente] | +| +----+-----------------+----------------------------------+------------------------------------+------------------+ +| | ++-------------------------------------------------------------------------------------------------------------------+ +| MASCHERA REGISTRAZIONE / EDITING UTENTE MULTI-RUOLO (#1) | +| | +| [ Nome Completo: BARONE MICHELE ] [ Email: michele@netgescon.it ] | +| [ Scadenza Accesso: Nessuna / Illimitato ] [ Studio di Riferimento: Studio Barone Michele ▾ ] | +| | +| SELEZIONE RUOLI CONTESTUALI MULTIPLI (ACL ROLE MATRIX): | +| [X] Super Admin (Accesso completo sistema e Centro Stella) | +| [X] Amministratore Stabile (Gestione contabile, fatture FE e stabili del proprio studio) | +| [X] Collaboratore Studio (Operatività limitata agli stabili delegati dallo studio) | +| [X] Fornitore Accreditato (Caricamento fatture, interventi ed albero lavorazioni) | +| [X] Dipendente Studio (Presenze, note spese e gestione task operative) | +| [X] Condomino / Proprietario(Consultazione rate, verbale assemblea ed estratti conto propri) | +| | +| AZIONI DI SICUREZZA ED AUDIT: | +| [ ⚡ IMPERNA SOGGETTO (TEST CONTESTO E AUDIT COMPLIANCE) ] | +| [ 📧 INVIA CREDIENZIALI PRIMO ACCESSO VIA EMAIL ] | +| [ 🔑 RIGENERA E RESETTA PASSWORD SICURA ] | +| | +| [ SALVA UTENTE E REGISTRA ACL ] [ ANNULLA ] | ++-------------------------------------------------------------------------------------------------------------------+ +```