fix mailing an email
This commit is contained in:
@@ -26,6 +26,20 @@ App gestionale Laravel 13 con AdminLTE 4 per gestione Persone e Gruppi.
|
||||
- **2026-06-17**: Google OAuth 2.0 unificato (revert Socialite, unified OAuth per Email/Drive/Calendar, XOAUTH2 SMTP+IMAP, UI impostazioni)
|
||||
- **2026-06-17**: Fix CalendarioConnessione — `encryptAndSetConfig()` perdeva campi sensibili in edit, `is_active` checkbox senza hidden fallback, query duplicata nella view
|
||||
- **2026-06-18**: Fix import CSV — `declare(strict_types=1)` mancante in IndividuoController, header check assente, Log::warning() su errori; fix freeze server (set_time_limit, session_write_close, DB::transaction, fgetcsv length illimitato) in GruppoController e IndividuoController
|
||||
- **2026-06-23**: Email compose: firma spostata dopo il corpo; Mailing list: aggiunto `sender_account_id` (mittente predefinito salvato in creazione, usato all'invio come fallback)
|
||||
- **2026-06-23**: Fix formati nome: responsabili gruppi e individui email ora mostrano "Nome Cognome"; mailing list edit: aggiunto pulsante "Rimuovi selezionati"
|
||||
- **2026-06-22**: Aggiunto supporto Email Mittente Ufficiale (from_email/from_name) per invio con indirizzo diverso dalle credenziali SMTP/IMAP
|
||||
- Migration: `from_email`, `from_name` columns su `email_settings`
|
||||
- `EmailSetting`: metodi `getEffectiveFromAddress()`, `getEffectiveFromName()`, `getEffectiveReplyTo()`
|
||||
- Tutti i metodi di invio (`sendViaImap`, `sendViaSystem`, `sendPasswordResetNotification`, `storeDraft`, `storeSentMessage`, `testSmtp`) ora usano `getEffectiveFromAddress()`/`getEffectiveFromName()` per il mittente
|
||||
- Reply-To automatico impostato su `from_email` quando disponibile
|
||||
- UI: nuovi campi "Email Mittente Ufficiale" e "Nome Mittente Ufficiale" in entrambe le pagine impostazioni email
|
||||
- **2026-06-22**: Backup system enhancements:
|
||||
- `BackupService::run()` ora accetta `$options` (include_files, include_env) per override temporanei senza persistere su DB
|
||||
- `BackupRunCommand --no-files/--no-env` non salva più permanentemente la configurazione (era un bug)
|
||||
- `manifest.json` ora include `included_components` array (database, env, files)
|
||||
- Vista backup: badge .env (grigio) e Files (giallo) nella colonna "Contenuto" basati sul manifest
|
||||
- `run()` restituisce `steps` array; mostrato in flash message (controller) e output (command)
|
||||
- **2026-06-18**: Diagnose script (`diagnose.php`), .env.example aggiornato (SESSION_SECURE_COOKIE, FORCE_HTTPS, TRUSTED_PROXIES), build-dist.sh aggiornato con passo diagnose
|
||||
|
||||
## Funzionalità Implementate
|
||||
@@ -751,3 +765,328 @@ Aggiunte variabili mancanti:
|
||||
### Verifica
|
||||
- `php -l diagnose.php`: OK
|
||||
- `php diagnose.php`: eseguito con 58/68 check superati su server locale
|
||||
|
||||
## 2026-06-19 — Fix 419: Duplicated middleware + session env vars + diagnose.php fixes
|
||||
|
||||
### Problema
|
||||
`POST /login` restituiva **419 Page Expired** su HTTP. La causa era doppia:
|
||||
|
||||
1. **Critico — Middleware duplicato in `bootstrap/app.php`**: `EncryptCookies`, `AddQueuedCookiesToResponse`, `StartSession`, `ShareErrorsFromSession` erano appesi al web group via `$middleware->web(append: [...])`. Questi middleware sono **già attivi di default** in Laravel 13. Appenderli una seconda volta causava doppia crittografia/decrittografia dei cookie di sessione → session ID corrotto → token CSRF non riconosciuto → 419.
|
||||
2. **`SESSION_SECURE_COOKIE` non impostato** nel `.env` — con `APP_URL=https` + `FORCE_HTTPS=true`, Laravel impostava il flag `Secure` sul cookie di sessione. Poiché il server serviva solo HTTP, il browser non inviava il cookie → session persa → 419.
|
||||
|
||||
### Fix apportati
|
||||
|
||||
**`bootstrap/app.php`** (righe 22-27):
|
||||
- Rimosso l'intero blocco `$middleware->web(append: [...])` che duplicava EncryptCookies, AddQueuedCookiesToResponse, StartSession, ShareErrorsFromSession.
|
||||
- Sostituito con commento esplicativo per prevenire future reintroduzioni.
|
||||
|
||||
**`.env`**:
|
||||
- Aggiunto `SESSION_SECURE_COOKIE=false` — impedisce il flag Secure su HTTP
|
||||
- Aggiunto `SESSION_SAME_SITE=lax` — esplicito per consistenza cross-protocol
|
||||
- Cambiato `APP_URL` da HTTPS a HTTP (ambiente locale senza HTTPS)
|
||||
- Cambiato `APP_PROTOCOL` da `https` a `http`
|
||||
- Cambiato `FORCE_HTTPS` da `true` a `false`
|
||||
- Cambiato `TRUSTED_PROXIES` da `*` a CIDR espliciti
|
||||
|
||||
**`diagnose.php`** — 4 bug fix:
|
||||
1. **`unlink()` senza `file_exists()`** nelle linee 863 e 900: causava PHP Warning quando curl non creava il cookie jar (es. HTTPS non raggiungibile). Aggiunto `file_exists($cookieJar) && unlink($cookieJar)`.
|
||||
2. **Regex middleware duplicato non matchava array multi-riga**: il pattern `[^\]]*` non matcha newline. Sostituito con `(.+?)` con flag `s`. Classe name extraction semplificata a `([a-zA-Z]+)::class`.
|
||||
3. **`CURLOPT_COOKIEJAR` non funzionante** in questo ambiente (curl 8.14.1 + PHP 8.4 — il file non viene creato da `curl_close()`). Riscritto `testCsrfLogin()` per parsare manualmente gli header `Set-Cookie` dalla prima risposta e reinviarli via `CURLOPT_COOKIE` nella POST. Eliminata dipendenza da `COOKIEJAR`/`COOKIEFILE`.
|
||||
4. Aggiunto verbose debug per codici HTTP POST anomali (≠ 302/200).
|
||||
|
||||
### Risultato finale
|
||||
```
|
||||
✅ Passed: 63
|
||||
⚠️ Warnings: 8 (upload/post_max_size, engine opzionali mancanti)
|
||||
❌ Failed: 1 (spazio disco 94.6% — server admin)
|
||||
```
|
||||
- Test CSRF: ✅ POST login → HTTP 302 (nessun 419)
|
||||
- Solo il disco (94.6%) è critico — non risolvibile via script.
|
||||
|
||||
### File modificati
|
||||
- `bootstrap/app.php` — rimosso middleware web duplicato
|
||||
- `.env` — aggiunte SESSION_SECURE_COOKIE, SESSION_SAME_SITE; APP_URL/APP_PROTOCOL/FORCE_HTTPS adeguati
|
||||
- `diagnose.php` — fix unlink warning, regex middleware multi-line, CSRF test manual-cookie, verbose debug
|
||||
|
||||
## 2026-06-19 — diagnose.php: storage false positivo + ForceHttps registration check
|
||||
|
||||
### Fix 1 — Storage permission false positive
|
||||
**Problema**: `diagnose.php` segnava 15 storage directory come ❌ NON SCRIVIBILE quando `php diagnose.php` veniva eseguito da CLI (utente `opencode`). Le directory sono di proprietà `www-data:www-data` con permessi `775`, quindi il web server **può** scrivere — il falso positivo generava confusione.
|
||||
|
||||
**Diagnosi**:
|
||||
- CLI esegue come `opencode` → `is_writable()` controlla i permessi "other" (5 = r-x) → `false`
|
||||
- Web server esegue come `www-data` → owner `rwx` → `true`
|
||||
- Questo è normale su server condivisi/Debian standard
|
||||
|
||||
**Fix** (`diagnose.php:659-660`):
|
||||
- Aggiunto `elseif ($owner === WEB_USER && in_array($perms, ['775', '777', '755', '770']))`
|
||||
- Se il proprietario è `www-data` e permessi sono `775`/`777`/`755`/`770`, mostra ⚠️ **warning** invece di ❌ **fail**, con messaggio "NON scrivibile da CLI ma WEB server sì"
|
||||
- Altrimenti mostra fail come prima
|
||||
|
||||
### Fix 2 — ForceHttps registration check
|
||||
**Problema**: Il controllo ForceHttps usava `str_contains($appContent, 'ForceHttps')` che matchava anche il semplice `use App\Http\Middleware\ForceHttps` (import), segnando ✅ "registrato" anche quando il middleware non era attivo in alcun gruppo.
|
||||
|
||||
**Stato attuale**: `ForceHttps::class` è **importato** ma **non registrato** in nessun middleware group (`$middleware->append()`, `->web()`, ecc.) in `bootstrap/app.php`.
|
||||
|
||||
**Fix** (`diagnose.php:871-879`):
|
||||
- Sostituito con `preg_match('/\$middleware\s*->\s*\w+\s*\(.*?ForceHttps::class/s', $appContent)`
|
||||
- 3 stati:
|
||||
1. ✅ `"registrato correttamente"` — se ForceHttps::class è argomento di una chiamata `$middleware->xxx()`
|
||||
2. ⚠️ `"IMPORTATO ma NON registrato"` — se la stringa ForceHttps esiste (use import) ma non in una chiamata
|
||||
3. ⚠️ `"NON presente"` — se ForceHttps non esiste nel file
|
||||
|
||||
### Verifica
|
||||
- `php -l diagnose.php`: No syntax errors detected
|
||||
- `php diagnose.php` su locale: ForceHttps ora segnala ⚠️ "IMPORTATO ma NON registrato" (corretto)
|
||||
|
||||
### File modificati
|
||||
- `diagnose.php` — storage false positive + ForceHttps registration check
|
||||
|
||||
## 2026-06-22 — build-dist.sh: genera post-deploy.sh per upgrade/install automatico
|
||||
|
||||
**Obiettivo**: Includere nell'archivio di distribuzione uno script `post-deploy.sh` che esegue controllo e setup dell'installazione sul server target, sia per fresh install che per upgrade.
|
||||
|
||||
### Cosa è stato fatto
|
||||
|
||||
**`build-dist.sh`** riscritto:
|
||||
- Prima del `tar`, genera `post-deploy.sh` (heredoc) e lo include nell'archivio
|
||||
- Dopo il `tar`, `post-deploy.sh` viene rimosso localmente (non sporca la working dir)
|
||||
- Istruzioni finali aggiornate: mostrano i tre comandi principali
|
||||
|
||||
**`post-deploy.sh`** (generato, non versionato):
|
||||
Tre modalità d'uso:
|
||||
|
||||
| Comando | Cosa fa |
|
||||
|---------|---------|
|
||||
| `bash post-deploy.sh check` | Diagnostica stato installazione: migration pendenti, permessi directory, symlink, cache. Nessuna modifica. |
|
||||
| `bash post-deploy.sh upgrade` | Check + upgrade esistente: crea directory, permessi, symlink, `migrate --force`, `key:generate` (se mancante), cache clear, verifica finale. Chiede conferma prima di eseguire. |
|
||||
| `bash post-deploy.sh install` | Fresh install completo: come upgrade + copia `.env.example → .env` con pausa per modifica utente. |
|
||||
| `bash post-deploy.sh upgrade --yes` | Batch mode (nessuna conferma richiesta) |
|
||||
|
||||
Fasi upgrade (8 step): directory → .gitignore → permessi → symlink → migrazioni → key → cache → diagnose
|
||||
Fasi install (9 step): come upgrade + setup .env con pausa interattiva
|
||||
|
||||
### Vantaggi
|
||||
- **Idempotente**: `migrate --force` esegue solo migration pendenti
|
||||
- **Sicuro**: modalità `check` non modifica nulla
|
||||
- **Interattivo**: chiede conferma prima di azioni distruttive
|
||||
- **Batch**: `--yes` per automazione CI/CD
|
||||
- **Compatibile**: integra `diagnose.php` già esistente (check + fix)
|
||||
- **Autopulente**: `post-deploy.sh` non resta nella working dir di build
|
||||
|
||||
### Verifica
|
||||
- `bash -n build-dist.sh`: syntax OK
|
||||
- `bash -n post-deploy.sh`: syntax OK
|
||||
- `bash post-deploy.sh check`: eseguito correttamente
|
||||
- `tar tzf glastree-*.tar.gz | grep post-deploy`: presente nell'archivio
|
||||
- `rm -f post-deploy.sh` dopo tar: pulizia OK
|
||||
|
||||
## 2026-06-22 — Estensione Gruppi: contatti propri + diocesi multiple
|
||||
|
||||
**Obiettivo**: Aggiungere contatti (email, telefono) ai gruppi e supportare assegnazione di più diocesi.
|
||||
|
||||
### Cosa è stato fatto
|
||||
|
||||
**Migration** (2 nuove tabelle):
|
||||
- `2026_06_22_000002_create_gruppo_contatti_table.php` — `gruppo_contatti` con: id, gruppo_id (FK cascade), tipo, valore, etichetta, is_primary, timestamps
|
||||
- `2026_06_22_000003_create_diocesi_gruppo_table.php` — pivot `diocesi_gruppo` con: id, gruppo_id (FK cascade), diocesi_id (FK cascade), unique(gruppo_id, diocesi_id)
|
||||
|
||||
**Model `GruppoContatto.php`** (nuovo):
|
||||
- `$table = 'gruppo_contatti'`, fillable: gruppo_id, tipo, valore, etichetta, is_primary
|
||||
- `gruppo()`: BelongsTo Gruppo
|
||||
|
||||
**Model `Gruppo.php`**:
|
||||
- `diocesi()`: cambiata da `BelongsTo` a `BelongsToMany` via `diocesi_gruppo`
|
||||
- `gruppoContatti()`: nuova `HasMany` relation
|
||||
- Accessor `getEmailPrimariaAttribute()`: primo contatto email (is_primary preferito)
|
||||
- Accessor `getTelefonoPrimarioAttribute()`: primo contatto telefono/cellulare (is_primary preferito)
|
||||
- `$appends`: già presente `email_primaria`, `telefono_primario` (invariato)
|
||||
- `$fillable`: `diocesi_id` mantenuto (nullable) per backward compat con import CSV
|
||||
|
||||
**Model `Diocesi.php`**:
|
||||
- `gruppi()`: cambiata da `HasMany` a `BelongsToMany` via `diocesi_gruppo`
|
||||
|
||||
**`GruppoController.php`**:
|
||||
- `store()`/`update()`: validazione cambiata da `diocesi_id` (nullable|exists) a `diocesi_ids` (nullable|array|exists)
|
||||
- `store()`/`update()`: nuova validazione `contatti` array con tipo (in:email,telefono,cellulare), valore, etichetta, is_primary
|
||||
- `store()`: crea contatti dopo create; sync diocesi
|
||||
- `update()`: cancella+ricrea contatti se presenti; sync diocesi (o detach se assenti)
|
||||
- `edit()`: eager-load `gruppoContatti`, passa `$selectedDiocesiIds`
|
||||
- `show()`: eager-load `gruppoContatti`
|
||||
- `index()`: eager-load `gruppoContatti`
|
||||
- `create()`: invariato (passa già `$diocesi`)
|
||||
|
||||
**`ReportController.php`**:
|
||||
- 4 occorrenze `$g->diocesi?->nome` → collection pattern `$g->diocesi->count() > 0 ? $g->diocesi->pluck('nome')->implode(', ') : '-'`
|
||||
|
||||
**View `gruppi/create.blade.php`**:
|
||||
- Select diocesi: cambiato da single `select name="diocesi_id"` a multiple `select name="diocesi_ids[]" class="select2-multi"`
|
||||
- Aggiunta card "Contatti del Gruppo" con tabella inline (tipo select, valore input, etichetta, checkbox primario, elimina)
|
||||
- Select2 CSS/JS caricati via CDN
|
||||
|
||||
**View `gruppi/edit.blade.php`**:
|
||||
- Stessa modifica diocesi → Select2 multi con `$selectedDiocesiIds` pre-selezionati
|
||||
- Aggiunta card "Contatti del Gruppo" con righe pre-popolate da `$gruppo->gruppoContatti`
|
||||
- Select2 CSS/JS caricati via CDN
|
||||
|
||||
**View `gruppi/show.blade.php`**:
|
||||
- Diocesi: da `$gruppo->diocesi?->nome` a collection implode
|
||||
- Aggiunte righe Email/Telefono (da accessor) e "Altri Contatti" nella card info
|
||||
|
||||
**View `gruppi/index.blade.php`**:
|
||||
- Diocesi: da `$gruppo->diocesi?->nome` a collection implode
|
||||
- Telefono/Email: da hardcoded `-` a `$gruppo->telefono_primario` / `$gruppo->email_primaria`
|
||||
|
||||
**View `gruppi/partials/tree-item.blade.php`**:
|
||||
- Diocesi: da `$gruppo->diocesi?->nome` a collection implode
|
||||
|
||||
**View `individui/show.blade.php` + `individui/edit.blade.php`**:
|
||||
- Diocesi nei gruppi dell'individuo: da `$gruppo->diocesi?->nome` a collection implode
|
||||
|
||||
### Backward compatibility
|
||||
- Colonna `diocesi_id` su `gruppi` mantenuta (nullable) per import CSV
|
||||
- CSV import (`importStore()`) usa ancora `diocesi_id` → singola diocesi
|
||||
- `$fillable` include ancora `diocesi_id`
|
||||
- Nessuna modifica a `Individuo` o `Contatto` esistenti
|
||||
|
||||
### Verifica
|
||||
- `php -l` su tutti i file modificati: OK
|
||||
- Migrations eseguite: ✅
|
||||
- Relazioni verificate: `diocesi()` BelongsToMany, `gruppoContatti()` HasMany, `email_primaria`/`telefono_primario` accessors funzionanti
|
||||
|
||||
## 2026-06-22 — Fix produzione: 500 pagina gruppi (migration pending + autoloader stale)
|
||||
|
||||
**Problema**: Dopo deploy su server produzione (`192.168.222.177`):
|
||||
- Migration `diocesi_gruppo` non eseguita (PENDING)
|
||||
- `GruppoContatto.php` non nell'autoloader (`composer dump-autoload` non eseguito)
|
||||
- `storage/logs/laravel.log` non scrivibile da www-data
|
||||
- 3 migration pre-esistenti non marcate come "ran" (google_oauth_connections, add_auth_method, add_google_id) — tabelle/colonne già esistenti ma migration record mancanti → bloccavano `migrate --force`
|
||||
|
||||
**Fix**:
|
||||
1. `sudo chmod -R 775 storage bootstrap/cache` — permessi
|
||||
2. `sudo usermod -a -G www-data opencode` — utente CLI nel gruppo www-data
|
||||
3. Inseriti manualmente 3 migration record mancanti in `migrations` table (già eseguite in passato ma mai registrate)
|
||||
4. `php artisan migrate --force` — eseguita `2026_06_22_000003_create_diocesi_gruppo_table`
|
||||
5. `composer dump-autoload` — autoloader rigenerato (41464 classi)
|
||||
6. `php artisan view:clear && php artisan route:clear && php artisan config:clear`
|
||||
|
||||
**Risultato**:
|
||||
- `class_exists(App\Models\GruppoContatto)` → ✅
|
||||
- `gruppi` page HTTP 200 (after login redirect 302) — 500 risolto
|
||||
- Tutte le migration marked as Ran (batch 40-42)
|
||||
- Views/routes/config cache pulite
|
||||
|
||||
**Lezione**: `build-dist.sh` fa `composer install --no-scripts` che non rigenera autoloader ottimizzato per il target. `post-deploy.sh upgrade` dovrebbe includere `composer dump-autoload` (o almeno `composer install --no-dev --optimize-autoloader`).
|
||||
|
||||
## 2026-06-22 — Fix: Select2 search field visibile sotto le diocesi selezionate
|
||||
|
||||
**Problema**: In create/edit gruppi, il `<textarea class="select2-search__field">` creato da Select2 in modalità multiple era visibile sotto i tag delle diocesi selezionate, con altezza 65px (ereditata da Bootstrap form-control).
|
||||
|
||||
**Causa**:
|
||||
1. `allowClear: true` in Select2 multiple mode non serve (ogni tag ha già la X per rimuoverlo) e causa conflitti di rendering
|
||||
2. Bootstrap 4 applica `height: 65px` al textarea del search field
|
||||
3. Nessun CSS specifico per normalizzare il search field inline
|
||||
|
||||
**Fix**:
|
||||
1. Rimosso `allowClear: true` da entrambi i file (`create.blade.php`, `edit.blade.php`)
|
||||
2. Aggiunto CSS per normalizzare `height: 28px`, `border: none`, `background: transparent`, `width: auto` con `min-width: 30px`
|
||||
|
||||
**File modificati**:
|
||||
- `resources/views/gruppi/create.blade.php` — rimosso allowClear, aggiunto CSS search field
|
||||
- `resources/views/gruppi/edit.blade.php` — rimosso allowClear, aggiunto CSS search field
|
||||
|
||||
## 2026-06-23 — Fix: Select2 counter rimosso (utente vuole vedere tutti i nomi)
|
||||
|
||||
**Problema**: Il `templateSelection` con counter mostrava "5 diocesi selezionate" invece dei nomi.
|
||||
|
||||
**Fix**: Rimosso l'intero blocco `templateSelection` da entrambi create/edit. Ogni diocesi selezionata mostra ora il proprio nome.
|
||||
|
||||
**File modificati**:
|
||||
- `resources/views/gruppi/create.blade.php` — rimosso templateSelection
|
||||
- `resources/views/gruppi/edit.blade.php` — rimosso templateSelection
|
||||
|
||||
## 2026-06-23 — Fix: DiocesiSeeder + build-dist.sh per deploy
|
||||
|
||||
**Problema**: La tabella `diocesi` con 225 record importati da ODS non veniva popolata sul server target dopo deploy. Il seeder `DiocesiSeeder.php` aveva solo ~100 nomi obsoleti/inaccurati (es. "Mongolia", "Donegal", "Tirana").
|
||||
|
||||
**Fix**:
|
||||
1. **`DiocesiSeeder.php`** riscritto completamente:
|
||||
- 225 nomi corretti (Arcidiocesi/Diocesi/Sede/Patriarcato/Abbazia/Eparachia)
|
||||
- Encoding: 7 nomi con mojibake da ODS fixati via `where('id', ...)->update()` (Trinità, Cefalù, Città, Forlì, Mondovì, Nardò, Perugia-Città)
|
||||
- Apostrofo: "Val d Elsa" → "Val d'Elsa"
|
||||
- `declare(strict_types=1)` aggiunto
|
||||
- `firstOrCreate` per idempotenza
|
||||
2. **`build-dist.sh`** (`post-deploy.sh` generato):
|
||||
- Upgrade: aggiunto step `[6/10] Seed diocesi` dopo migrazioni (rinumerati da [1-5/9] → [1-10/10])
|
||||
- Install: aggiunto step `[9/11] Seed diocesi` dopo migrazioni (rinumerato da [1-8/10] → [1-11/11])
|
||||
- Usa `--force` per bypassare conferma in produzione
|
||||
|
||||
**File modificati**:
|
||||
- `database/seeders/DiocesiSeeder.php` — riscritto con 225 nomi + fix encoding
|
||||
- `build-dist.sh` — aggiunto step seed diocesi in upgrade/install
|
||||
|
||||
## 2026-06-23 — Fix 419: SESSION_DRIVER=database + diagnose CSRF su IP locale
|
||||
|
||||
**Problema**: Accesso via IP di rete locale (`http://192.168.222.174`) poteva causare 419 Page Expired. Sessione su file vulnerabile a permessi/LOCK del filesystem.
|
||||
|
||||
**Fix**:
|
||||
1. **`SESSION_DRIVER=database`**: cambiato da `file` a `database`. La sessione su DB non soffre di:
|
||||
- Permessi filesystem errati
|
||||
- Lock concorrente su file
|
||||
- Pulizia sessioni scadute lottery-based
|
||||
2. **Migration `2026_06_23_000001_create_sessions_table.php`**: con guard `Schema::hasTable` per idempotenza cross-DB
|
||||
3. **`diagnose.php`**: aggiunto test CSRF su IP locale automatico. Rileva `hostname -I` ed esegue POST login → verifica 419 su `http://<lan-ip>/login`
|
||||
4. **`.env` e `.env.example`**: `SESSION_DRIVER=file` → `SESSION_DRIVER=database`
|
||||
5. Vecchi file di sessione in `storage/framework/sessions/` eliminati
|
||||
|
||||
**Risultato**:
|
||||
- diagnose.php: `✅ HTTP: POST login → HTTP 302 (nessun 419)`
|
||||
- diagnose.php: `✅ LOCAL IP: POST login → HTTP 302 (nessun 419)`
|
||||
- Sessioni persistono in tabella `sessions` (DB) invece di file
|
||||
|
||||
**File modificati**:
|
||||
- `database/migrations/2026_06_23_000001_create_sessions_table.php` (nuovo)
|
||||
- `.env` — SESSION_DRIVER=database
|
||||
- `.env.example` — SESSION_DRIVER=database
|
||||
- `diagnose.php` — test CSRF su IP locale
|
||||
|
||||
## 2026-06-23 — Email compose: firma dopo corpo + Mailing list: mittente e firma
|
||||
|
||||
**Obiettivo**: Spostare la select firma dopo il corpo email nella pagina di composizione email. Aggiungere mittente predefinito (`sender_account_id`) alle mailing list (salvato in creazione/edit, usato come fallback all'invio).
|
||||
|
||||
### Cosa è stato fatto
|
||||
|
||||
**Migration** (`2026_06_23_000002_add_sender_account_id_to_mailing_lists_table.php`):
|
||||
- Aggiunta colonna `sender_account_id` (FK → sender_accounts, nullOnDelete) a `mailing_lists`
|
||||
|
||||
**Model `MailingList.php`**:
|
||||
- `sender_account_id` aggiunto a `$fillable`
|
||||
- `senderAccount()`: nuova relazione BelongsTo → `SenderAccount`
|
||||
|
||||
**Controller `MailingListController.php`**:
|
||||
- `create()`: passa `$senderAccounts` (SenderAccount::active()->get()) alla view
|
||||
- `edit()`: passa `$senderAccounts` alla view, eager-load `senderAccount`
|
||||
- `store()`: validazione `sender_account_id` nullable|exists, salvato in create
|
||||
- `update()`: validazione `sender_account_id` nullable|exists, salvato in update
|
||||
|
||||
**View `mailing-liste/create.blade.php`**:
|
||||
- Aggiunto select per `sender_account_id` dopo il select firma
|
||||
|
||||
**View `mailing-liste/edit.blade.php`**:
|
||||
- Aggiunto select per `sender_account_id` dopo il select firma, con `selected` se uguale a `$mailingList->sender_account_id`
|
||||
|
||||
**View `email/compose.blade.php`**:
|
||||
- Spostato blocco firma (prima del body) → dopo il textarea body (prima della sezione allegati)
|
||||
|
||||
**Controller `MailingController.php`**:
|
||||
- `invia()`: fallback a `$lista->senderAccount` se `mittente_id` non fornito esplicitamente (stesso pattern del firma_id fallback già esistente)
|
||||
- `invioElabora()`: fallback a `mittente_id`/`firma_id` dalla mailing list se non forniti esplicitamente (solo quando una singola lista è selezionata)
|
||||
|
||||
**File modificati**:
|
||||
- `database/migrations/2026_06_23_000002_add_sender_account_id_to_mailing_lists_table.php` (nuovo)
|
||||
- `app/Models/MailingList.php` — fillable + senderAccount relazione
|
||||
- `app/Http/Controllers/MailingListController.php` — sender_account in create/edit/store/update
|
||||
- `app/Http/Controllers/MailingController.php` — fallback mittente/firma da mailing list
|
||||
- `resources/views/email/compose.blade.php` — firma spostata dopo il body
|
||||
- `resources/views/mailing-liste/create.blade.php` — select mittente aggiunto
|
||||
- `resources/views/mailing-liste/edit.blade.php` — select mittente aggiunto
|
||||
|
||||
Reference in New Issue
Block a user