1.0.5 fix first login after install .php

This commit is contained in:
2026-06-03 11:59:44 +02:00
parent 25168debc0
commit fcbb6fb061
13 changed files with 191 additions and 70 deletions
+49 -46
View File
@@ -1,36 +1,32 @@
# 🧠 MEMORY.md — Stato Progetto
## Goal
- Correggere tutti i bug critici identificati nell'applicazione Glastree
- Implementare nuove funzionalità richieste: cancellazione account email, fix firma editor, sincronizzazione calendario con Google Calendar / CalDAV
- Fix login after fresh install (user created via installer can't authenticate)
- Cross-DB compatibility (MySQL ↔ SQLite) for all migrations
## Constraints & Preferences
- Laravel 13, PHP 8.4, AdminLTE 4, MySQL/MariaDB
- Laravel 13, PHP 8.4, AdminLTE 3, MySQL/MariaDB/SQLite
- Comandi Artisan da terminale, nessun wizard web
- Script PHP CLI per installazione interattiva
- Zero placeholder, zero TODO, codice funzionante
- Compatibilità cross-DB MySQL ↔ SQLite
## Progress
### Done
- **Cancellata cache Laravel** (`php artisan optimize:clear`)
- **Fix BUG CRITICO 3** `IndividuoController::update()` (riga 216): avvolto `$individuo->contatti()->delete()` dentro `if ($request->has('contatti'))`.
- **Fix BUG CRITICO 1** `individui/edit.blade.php`: convertiti 4 form annidati in pulsanti `type="button"` + `fetch()` AJAX
- **Fix BUG CRITICO 2** `gruppi/edit.blade.php`: convertiti 3 form annidati in pulsanti `type="button"` + `fetch()` AJAX
- **Fix BUG CRITICO 4** `gruppi/show.blade.php`: flash messages spostati dentro `@section('content')`
- **Fix BUG CRITICO 5/6** `eventi/show.blade.php`: rimossi div extra, XSS escape in confirm()
- **Fix BUG CRITICO 7/8** `ImpostazioniController.php`: use Documento + JSON_CONTAINS → PHP
- **Fix BUG CRITICO 9** `ReportController.php`: `$contatto->email``$contatto->valore`
- **Fix BUG CRITICO 10** `DocumentoController.php`: morph injection prevention in massUpdate()
- **NUOVA FEATURE Cancellazione account email**: Aggiunto metodo `destroy()` in `EmailSettingsController`, rotta `DELETE /impostazioni/email`, pulsante "Elimina Configurazione" in entrambe le viste (admin dedicata e unificata)
- **FIX Doppia barra icone firma**: Cambiata la guardia di `createEditor()` e `initSignatureEditor()` da `container.querySelector('.ql-toolbar')` (che non funziona perché Quill crea la toolbar come sibling, non child) a flag `quillEditorInstance` in entrambe le viste
- **NUOVA FEATURE Sincronizzazione calendario**: Implementata sincronizzazione con Google Calendar e CalDAV (Infomaniak/NextCloud):
- Migration `create_calendario_connessioni_table` + `add_uid_esterno_to_eventi_table`
- Model `CalendarioConnessione` con encrypt/decrypt config
- Service `CalDavService` (PROPFIND, REPORT, calendar-query, PUT)
- Service `GoogleCalendarSyncService` (Google Calendar API v3)
- Controller `CalendarioConnessioneController` (CRUD + test + sync + reorder)
- Routes RESTful per calendario-connessioni
- UI nella tab "Calendario" delle impostazioni unificate con tabella, modale CRUD, pulsanti test/sync/elimina, Sortable drag&drop
- Installati pacchetti: `sabre/vobject`, `google/apiclient`
- **Fix RedirectResponse type error**: aggiunto `use Illuminate\Http\RedirectResponse;` in `EmailSettingsController.php`
- **Fix UrlGenerationException in sender routes**: sostituito `route('impostazioni.sender.update', '') + id` con `'__ID__'.replace('__ID__', id)` in `admin/email-settings/index.blade.php` (stessa correzione per `impostazioni.sender.test`)
- **Fix Messaggi email visibili dopo eliminazione configurazione**: `destroy()` ora cancella sempre allegati su disco, cartelle email (cascata messaggi/allegati) e poi le impostazioni. Risolto bug che faceva uscire subito se `EmailSetting::first()` era null
- **Fix Tab guida Installazione/Backup/Docker non funzionanti**: rimosso `</div>` di chiusura `tab-content` prematuro (linea 290) in `help/index.blade.php` — i tre tab-pane erano fuori dal container
- **Guida aggiornata rimosso wizard web installer**: sostituiti tutti i riferimenti alla cartella `installer/` con comandi Artisan in `help/index.blade.php` e `help/pdf.blade.php`. Passi 3-6 semplificati in un unico `php install.php`
- **Script install.sh rimosso**, sostituito da **`install.php`** (PHP CLI interattivo): modalità Apache/Docker/Restore, preflight, `.env` + `APP_KEY`, `CREATE DATABASE IF NOT EXISTS`, composer, `package:discover`, `migrate --seed`, admin via tinker, asset npm, permessi. Docker build + admin nel container
- **Fix Migration `app_settings` mancante**: creata `2026_05_15_000001_create_app_settings_table.php` con tutte le colonne. Aggiornate 4 migration alter esistenti con guardie `Schema::hasTable()` + `Schema::hasColumn()`. Aggiunto `Schema::hasTable()` in `AppSetting::getSetting()` per evitare eccezioni su DB fresco
- **Fix Database non creato durante install**: `install.php` ora esegue `CREATE DATABASE IF NOT EXISTS`
- **Fix Remember checkbox mancante `name`**: aggiunto `name="remember"` al checkbox "Ricordami" in `resources/views/auth/login.blade.php`
- **Fix Admin via tinker senza `is_admin`/`permissions`**: tutti e 3 i tinker script in `install.php` ora impostano `is_admin = true`, `status = 'active'`, `permissions` completo (tutti i moduli a livello FULL)
- **Fix `2>/dev/null` rimosso da tinker/artisan commands**: `install.php` non sopprime più stderr su `tinker --execute`, `package:discover`, `storage:link`, `chown`, `cp`. Eventuali errori ora sono visibili all'utente
- **Fix Controllo permessi sessione**: aggiunto check esplicito `is_writable(storage/framework/sessions/)` in `install.php` con warning su potenziale errore 419 CSRF
- **Fix Migrations non cross-DB**: convertiti `enum()` a `string(50)` in tutte le migration delle tabelle `documenti` (create + alter) per compatibilità MySQL/SQLite. Rimossa raw SQL `ALTER TABLE MODIFY COLUMN`. Aggiunto `dropIndex()` prima di `dropColumn('ruolo_id')` in `change_ruolo_to_multi.php` per compatibilità SQLite
- **Fix ExampleTest**: aggiornato per matchare comportamento reale (root `/` fa redirect 302 a login)
- **Nuovo test Login**: `tests/Feature/Auth/LoginTest.php` con 5 test: seeded admin login, custom admin login, wrong password, suspended user, login page loads
### In Progress
- *(nessuno)*
@@ -39,32 +35,39 @@
- *(nessuno)*
## Key Decisions
- Per i form annidati si è scelto l'approccio `type="button"` + `fetch()` AJAX
- Per la cancellazione account email si usa `EmailSetting::first()->delete()` con verifica esistenza
- Per il fix Quill: variabile flag `quillEditorInstance` invece di `container.querySelector('.ql-toolbar')` perché Quill inserisce `.ql-toolbar` come elemento sibling, non child
- Per CalDAV: usato Guzzle (già in Laravel) per HTTP + `sabre/vobject` per parsing iCal
- Per Google Calendar: usato `google/apiclient` con OAuth 2.0 (refresh token)
- La sync può essere bidirezionale, solo import o solo export
- I campi sensibili delle connessioni calendario sono criptati con `Crypt`
- Script installazione in PHP CLI invece di bash: usa direttamente API Laravel/PDO, gestione errori con try/catch, readline per input, nessun problema di sintassi shell
- Migrazione `app_settings`: unica migration `Schema::create()` con tutte le colonne + guardie `hasColumn()` nelle alter esistenti invece di modificare i timestamp
- Cleanup email: eseguito sempre (anche se `EmailSetting` già cancellato) per gestire stato orfano
- `enum()` rimosso a livello DB in favore di `string()` + validazione app-level (consistente con AGENTS.md)
- `dropIndex()` esplicito prima di `dropColumn()` per compatibilità SQLite
## Next Steps
- *(nessuno)*
## Critical Context
- Le connessioni calendario supportano: Google Calendar, CalDAV (NextCloud, Infomaniak, Synology)
- La direzione di sync è configurabile per ogni connessione
- Le password/refresh token sono automaticamente criptati all salvataggio via `encryptAndSetConfig()`
- Il campo `uid_esterno` sugli eventi traccia la corrispondenza con eventi remoti
- `DatabaseSeeder` crea admin `admin@glastree.local / password` con `is_admin=true`, `status='active'`
- `User` model ha `'password' => 'hashed'` cast: nessun doppio hashing con `bcrypt()` + `save()`
- `Auth::attempt()` usa `Hash::check()` che ignora il cast `hashed`
- `SESSION_DRIVER=file` in produzione richiede permessi di scrittura su `storage/framework/sessions/`
- `APP_ENV=production` + `APP_DEBUG=false` nascondono errori 419 (CSRF) e 500
- Test PHPUnit usano SQLite `:memory:` — tutte le migration devono essere cross-DB compatibili
- SQLite non supporta: `ALTER TABLE MODIFY COLUMN`, `ENUM` type, `dropColumn` su colonne con indici
## Relevant Files
- `app/Http/Controllers/Admin/EmailSettingsController.php`: +destroy() method
- `app/Http/Controllers/CalendarioConnessioneController.php`: NEW CRUD + test + sync
- `app/Models/CalendarioConnessione.php`: NEW model con encrypt config
- `app/Services/CalDavService.php`: NEW CalDAV sync
- `app/Services/GoogleCalendarSyncService.php`: NEW Google Calendar sync
- `app/Http/Controllers/ImpostazioniController.php`: +calendarioConnessioni in index()
- `resources/views/admin/email-settings/index.blade.php`: +delete button, fix Quill guard
- `resources/views/impostazioni/index.blade.php`: +delete button, fix Quill guard, +calendario tab UI, +calendario modal, +JS funcs
- `routes/web.php`: +email destroy route, +calendario-connessioni routes
- `database/migrations/2026_06_02_000001_create_calendario_connessioni_table.php`: NEW
- `database/migrations/2026_06_02_000002_add_uid_esterno_to_eventi_table.php`: NEW
- `install.php`: installer interattivo — Apache/Docker/Restore, tinker scripts admin (3 modalità)
- `resources/views/auth/login.blade.php`: fix `name="remember"` sul checkbox "Ricordami"
- `app/Http/Controllers/Auth/AuthController.php`: `login()` controlla `$user->status === 'suspended'`
- `app/Models/User.php`: cast `'password' => 'hashed'`, metodi isSuperAdmin/isActive
- `database/seeders/DatabaseSeeder.php`: crea admin di default
- `tests/Feature/Auth/LoginTest.php`: NEW — 5 test di login
- `app/Http/Controllers/Admin/EmailSettingsController.php`: fix destroy cleanup
- `resources/views/admin/email-settings/index.blade.php`: fix route sender update/test
- `database/migrations/2026_05_12_000002_change_ruolo_to_multi.php`: fix dropIndex + dropColumn
- `database/migrations/*documenti*`: fix enum → string (5 migration)
- `database/migrations/2026_05_15_000001_create_app_settings_table.php`: NEW
- `database/migrations/2026_05_16_000001_add_logo_path_to_app_settings.php`: guardie hasColumn
- `database/migrations/2026_05_16_000002_add_app_config_to_app_settings.php`: guardie hasColumn
- `database/migrations/2026_05_27_000003_add_documenti_storage_to_app_settings.php`: guardie hasColumn
- `database/migrations/2026_06_01_100155_add_backup_settings_to_app_settings.php`: guardie hasColumn
- `resources/views/help/index.blade.php`: fix tab-pane chiusura, rimosso wizard web installer
- `resources/views/help/pdf.blade.php`: rimosso wizard web installer