add OAUth2.0

This commit is contained in:
2026-06-15 11:14:35 +02:00
parent 7973a94498
commit 69f4d6a602
32 changed files with 1126 additions and 51 deletions
+103 -1
View File
@@ -291,8 +291,11 @@ if (!empty($contatto['individuo_id'])) { create }
```
## Prossimi Passi
- [DONE] ... (existing items)
- Verificare end-to-end su remote: tutte le nuove mass action, mailing list con contatti senza email, ricerca multi-tag
- Test end-to-end OAuth con credenziali Google reali (configurare Google Cloud Console, registrare callback URI, ottenere refresh token)
- Verificare EmailSetting::isOauth() integration in email sync flow
- Verificare StorageRepositoryService::buildGoogleDrive() OAuth fallback con repos esistenti
- Verificare GoogleCalendarSyncService::buildClient() OAuth fallback con connessioni esistenti
- [DONE] Fix performance: spostata query `VistaReport::where(...)->get()` da `@php` nel partial `table-settings.blade.php` a tutti i 5 controller (prima veniva eseguita 1 query per ogni pagina load per ogni entity, anche senza mai aprire la modale)
- [DONE] Rimosse vecchie modal legacy (`#saveVistaModal`, `#colonneModal`, `#vistaListModal`) da `individui` e `gruppi` — duplicate rispetto al nuovo modal unificato
- [DONE] Rimosse vecchie funzioni JS (`saveVista()`, `toggleColumn()`, `showSaveVistaModal()`) da `individui` e `gruppi`
@@ -380,3 +383,102 @@ if (!empty($contatto['individuo_id'])) { create }
**Fix**:
1. `VistaReportController@update` (linea 101-103): aggiunto `if ($request->expectsJson()) { return response()->json([...]); }` — così il fetch riceve JSON 200, non un redirect 302.
2. Fetch headers in `table-settings.blade.php`: aggiunto `'Accept': 'application/json'` — necessario perché `expectsJson()` controlla l'header `Accept`, non `Content-Type`.
## 2026-06-15 — Centralized Google OAuth 2.0 System (Gmail, Drive, Calendar)
**Obiettivo**: Implementare autenticazione OAuth 2.0 centralizzata per Gmail (IMAP/SMTP), Google Drive e Google Calendar come alternativa opzionale all'auth con password, con revoca per-servizio.
### Files Creati
- **Enum** `app/Enums/GoogleService.php` — 3 casi (Gmail, Drive, Calendar) con scope/label/icon/hexColor
- **Migration 1** `2026_06_15_000001_create_google_oauth_connections_table.php` — tabella google_oauth_connections
- **Migration 2** `2026_06_15_000002_add_auth_method_to_email_settings_table.php` — auth_method a email_settings
- **Model** `app/Models/GoogleOAuthConnection.php` — encrypted field accessor/mutator
- **Service** `app/Services/GoogleOAuthService.php` — full OAuth flow methods
- **Controller** `app/Http/Controllers/GoogleOAuthController.php` — connect/callback/revoke/status
- **Routes** in `routes/web.php` — 4 nuove route
- **View** `resources/views/google-oauth/status.blade.php`
### Problemi Risolti
1. Filesystem permission: directory 755 (www-data). Script PHP via Apache da storage/app/public/
2. routes/web.php root:root 644 -> rename trick
3. authorize() method conflict -> rinominato in connect()
### Architettura
- Fallback pattern: Drive/Calendar provano OAuth centralizzata, poi config esistente
- Per-service revoca: record separato per servizio (unique su service)
- Single callback URI: /auth/google/callback, routing via state
- Token encryption: AES-256-CBC + APP_KEY
### Completato
1.**EmailSetting model** (`app/Models/EmailSetting.php`): `auth_method` in ``, `isOauth()` method, `getOAuthAccessToken()` via `GoogleOAuthService`, `getDecryptedPassword()` returns OAuth token when isOauth, `getDecryptedSmtpPassword()` same, `getImapClient()` returns null for OAuth, `testConnection()` has OAuth path via Webklex\PHPIMAP
2.**EmailController** (`app/Http/Controllers/EmailController.php`): `syncEmails()` redirects to `syncEmailsViaOAuth()`, `connectImap()` redirects to `connectOAuthImap()`, `sendViaImap()` appends `auth_mode=xoauth2` to DSN, added `processWebklexMessage()` helper
3.**StorageRepositoryService** (`app/Services/StorageRepositoryService.php`): `buildGoogleDrive()` tries `GoogleOAuthService::buildClient(GoogleService::Drive)` first, falls back to config. Same for `readGoogleDriveFile()` and `checkGoogleDriveApiStatus()`
4.**GoogleCalendarSyncService** (`app/Services/GoogleCalendarSyncService.php`): `buildClient()` tries `GoogleOAuthService::buildClient(GoogleService::Calendar)` first, falls back to config
5.**Tab Google Services** in `resources/views/impostazioni/index.blade.php` — nav tab + tab-pane with Connect/Revoke per service (Gmail, Drive, Calendar), status badges, alert linking to email tab. Added `auth_method` select in email IMAP tab
6.**Test end-to-end** — requires user to configure Google Cloud Console (OAuth consent screen, callback URI) and provide credentials
### Files Modified
- `app/Models/EmailSetting.php` — OAuth-aware auth_method, decrypt overrides, IMAP client
- `app/Http/Controllers/EmailController.php` — OAuth sync/send/connect paths
- `app/Services/StorageRepositoryService.php` — Drive OAuth fallback
- `app/Services/GoogleCalendarSyncService.php` — Calendar OAuth fallback
- `resources/views/impostazioni/index.blade.php` — Google Services tab + auth_method select
### Bug Fix
- **2026-06-15 — Variable interpolation in str_replace**: In `apply_all_mods.php`, the second argument to `str_replace()` used double quotes, causing PHP to interpolate $fileId, $service, $googleMimeType, $originalBasename as empty strings. Result: method signature `exportGoogleDriveDoc` lost all parameter variable names. Fixed by running a second script that used `preg_replace` to restore the signature. (file -> app/Services/StorageRepositoryService.php)
### Pre-Production Review Fixes
**2026-06-15 — 4 criticità risolte prima del deploy**
| # | Problema | File | Fix |
|---|----------|------|-----|
| 1 | Credenziali Google vuote | `GoogleOAuthService.php:createClient()` | Sostituito `setAuthConfig([client_id:'']` con `setClientId(config(...))`, `setClientSecret(config(...))`, `setRedirectUri(...)`. Rimossi 4 import inutilizzati |
| 2 | Route name errato | `google-oauth/status.blade.php:55` | `google.oauth.connect``google.oauth.authorize` |
| 3 | Metodo inesistente `description()` | `google-oauth/status.blade.php:43` | Sostituito con `label() . ' - ' . scope()`. Layout cambiato da `layouts.app` a `layouts.adminlte` |
| 4 | `auth_method` select mancante | `impostazioni/index.blade.php` | Inserito `<select name="auth_method">` all'inizio del card-body in `#email-imap` |
| — | `GOOGLE_CLIENT_ID`/`GOOGLE_CLIENT_SECRET` mancanti | `config/services.php`, `.env.example` | Aggiunte sezione google in services.php con `env()`, variabili a `.env.example` |
| — | Istruzioni aggiornamento mancanti | `build-dist.sh` | Aggiunta sezione "AGGIORNAMENTO (SERVER ESISTENTE)" con backup, migrate, env vars |
### Files Review Round
- `app/Services/GoogleOAuthService.php` — createClient() legge da config, import puliti
- `resources/views/google-oauth/status.blade.php` — route, description, layout fix
- `resources/views/impostazioni/index.blade.php` — auth_method select
- `config/services.php` — sezione google
- `.env.example` — GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
- `build-dist.sh` — update instructions
### 2026-06-15 — Cleanup: file inutilizzati, codice morto e import superflui
**File eliminati (7 backup .bak):**
- `MEMORY.md.bak`, `EmailController.php.bak`, `web.php.bak`, `web.php.bak2`
- `index.blade.php.bak` (141 KB), `build-dist.sh.bak`, `.env.example.bak`
- Directory vuota `tests/Feature/Auth/`
**Metodi morti rimossi (3):**
| Metodo | File | Motivo |
|--------|------|--------|
| `create()` | `DocumentoController.php` | Nessuna route registrata, view inesistente |
| `index()` | `StorageRepositoryController.php` | Nessuna route GET, view inesistente |
| `downloadMigrationScript()` | `BackupController.php` | Nessuna route, view inesistente |
**Import superflui rimossi (20):**
- `EmailController.php`: `GoogleService`, `GoogleOAuthService`, `Crypt` (non usati direttamente, logica passa da `EmailSetting` model)
- `BackupController.php`: `JsonResponse` (usato dal metodo rimosso)
- `StorageRepositoryController.php`: `View` (usato dal metodo rimosso)
- `GruppoMembroController.php`: `Individuo`, `Ruolo`
- `HomeController.php`: `Notifica`
- `ImpostazioniController.php`: `Crypt`
- `AuthController.php`: `EmailSetting`, `Address`
- `IndividuoController.php`: `Contatto`
- `AppSetting.php`: `File`
- `EmailAttachment.php`: `Storage`
- `Evento.php`: `HasMany`
- `ExportHelpPdf.php`: `Storage`
- `BackupService.php`: `Notifica`, `Crypt`, `Storage`
- `AuthServiceProvider.php`: `Route`
**Verifica:** Tutti i 14 file modificati passano `php -l`