From bc57d0dcd0e22090df62d9bb9a45cd2f36522370 Mon Sep 17 00:00:00 2001 From: Inext68 Date: Sat, 6 Jun 2026 23:19:55 +0200 Subject: [PATCH] final 1.2 --- .env | 68 ++++++++++ .gitignore | 1 - MEMORY.md | 126 +++++++------------ app/Http/Controllers/EmailController.php | 3 +- app/Http/Controllers/EventoController.php | 102 +-------------- app/Http/Controllers/GruppoController.php | 98 --------------- app/Http/Controllers/IndividuoController.php | 3 +- app/Models/Evento.php | 1 - database/install.sql | 9 +- install.php | 63 ++-------- resources/views/email/index.blade.php | 25 +--- resources/views/eventi/import.blade.php | 55 -------- resources/views/eventi/index.blade.php | 28 +---- resources/views/gruppi/import.blade.php | 64 ---------- resources/views/gruppi/index.blade.php | 3 - resources/views/individui/index.blade.php | 25 +--- routes/web.php | 5 - 17 files changed, 142 insertions(+), 537 deletions(-) create mode 100644 .env delete mode 100644 resources/views/eventi/import.blade.php delete mode 100644 resources/views/gruppi/import.blade.php diff --git a/.env b/.env new file mode 100644 index 00000000..677b8745 --- /dev/null +++ b/.env @@ -0,0 +1,68 @@ +APP_NAME=Glastree +APP_ENV=local +APP_KEY=base64:aWz7908H9c7s+it9uMTwb6pyUrpddyMclcuN9Kzv7Ao= +APP_DEBUG=true +APP_URL= +APP_PROTOCOL=https +FORCE_HTTPS=true +TRUSTED_PROXIES=* + +APP_LOCALE=it +APP_FALLBACK_LOCALE=it +APP_FAKER_LOCALE=it_IT + +APP_MAINTENANCE_DRIVER=file +# APP_MAINTENANCE_STORE=database + +# PHP_CLI_SERVER_WORKERS=4 + +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=localhost +DB_PORT=3306 +DB_DATABASE=glastree +DB_USERNAME=glastree +DB_PASSWORD=glastree + +SESSION_DRIVER=file +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=database + +CACHE_STORE=database +# CACHE_PREFIX= + +MEMCACHED_HOST=127.0.0.1 + +REDIS_CLIENT=phpredis +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_SCHEME=null +MAIL_HOST=127.0.0.1 +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +VITE_APP_NAME="${APP_NAME}" diff --git a/.gitignore b/.gitignore index ea618786..93b70897 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ glastree-image.tar -.env diff --git a/MEMORY.md b/MEMORY.md index a0b251a5..7d3f461d 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -1,91 +1,61 @@ # 🧠 MEMORY.md β€” Stato Progetto ## Goal -- Implementare 3 feature in Glastree Laravel 13: - 1. **Page-length selector** su pagine lista (Individui, Eventi, Email) - 2. **CSV import per gruppi** (stesso pattern import individui) - 3. **ICS import per eventi** (via sabre/vobject) +- Risolvere login non funzionante dopo fresh install (causa: tinker senza escaping + `2>/dev/null`) +- Sostituire tinker per creazione admin con PDO prepared statement + SQL file per schema ## Constraints & Preferences -- Laravel 13, PHP 8.4, AdminLTE 4, MySQL/MariaDB +- Laravel 13, PHP 8.4, AdminLTE 4, MySQL/MariaDB (install.sql solo MySQL) - Zero placeholder, zero TODO, codice funzionante -- Seguire pattern esistenti (individui import, controller conventions, view layouts) -- sabre/vobject giΓ  installato in composer.json (verificato funzionante in vendor/) -- UI in Italiano come da applicazione esistente +- CompatibilitΓ  cross-DB MySQL ↔ SQLite (fallback migration per SQLite) -## Verifica Finale β€” Tutto OK βœ… +## Progress +### Done +- **Creazione `database/install.sql`** β€” schema MySQL completo + seed data (~1059 righe): + - Tutte le 45 tabelle nello stato finale (consolidate da 58 migration) + - Seed: 119 diocesi, 54 comuni, 8 tipologie documenti, 8 tipologie eventi, 8 ruoli, 23 permessi Spatie, 2 ruoli Spatie, 3 role preset, 5 email folders, 1 riga app_settings + - **NON contiene l'admin** (creato via PDO da install.php) + - `SET FOREIGN_KEY_CHECKS=0` per ordine tabelle, riattivato alla fine +- **Riscritto `install.php`** β€” eliminata dipendenza da tinker per la creazione admin: + - Aggiunta funzione `createAdminUser()`: PDO prepared statement + `password_hash()` + Spatie role assignment + - Fresh Install Apache: importa `install.sql` via `mysql` CLI, poi crea admin via PDO + - Fresh Install Docker: copia `install.sql` nel container, importa via mysql CLI, crea admin via script PHP temporaneo con `var_export()` (safe) + - Restore: crea admin via PDO se non esiste + - Fallback SQLite: mantiene `php artisan migrate --seed` + tinker ma con `var_export()` per escaping + - Step 5 rinominato da "MIGRATION E SEED" a "SCHEMA DATABASE E DATI BASE" + - Step 6 usa PDO invece di tinker (MySQL) +- **Unified MySQL setup**: singolo tentativo PDO con `dbname` nel DSN β€” se fallisce (1044/1045/1049), passa automaticamente in root-mode: chiede password root, crea database + utente + GRANT ALL su `localhost` e `%` +- **Sostituito loop 30-retry** con connessione singola PDO (timeout 5s) +- **Fix parse error**: `\$adminName` β†’ `$adminName` in `var_export()` nel ramo SQLite +- **Fix composer**: rimosso `sudo -u www-data` da composer (causa git dubious ownership + permission denied), aggiunto `COMPOSER_ROOT_VERSION=dev-main`; `vendor` aggiunto al chown finale -| Controllo | Risultato | -|-----------|-----------| -| Syntax PHP tutti i file modificati | βœ… Nessun errore | -| Bilanciamento `{}` JS in tutte le views | βœ… Tutte bilanciate | -| Rotta `gruppi.import` GET | βœ… Registrata | -| Rotta `gruppi.import.store` POST | βœ… Registrata | -| Rotta `gruppi.template` GET | βœ… Registrata | -| Rotta `eventi.import` GET | βœ… Registrata | -| Rotta `eventi.import.store` POST | βœ… Registrata | -| View `gruppi/import.blade.php` | βœ… Creata | -| View `eventi/import.blade.php` | βœ… Creata | -| sabre/vobject loadabile | βœ… `Sabre\VObject\Reader` disponibile | +### In Progress +- *(nessuno)* -## Modifiche Effettuate - -### 1. Page-length selector (3 pagine) -**File modificati:** -- `app/Http/Controllers/IndividuoController.php:20` β€” `paginate(20)` β†’ `paginate($perPage)` con clamp `[10,20,25,50,100]`, default 20 -- `app/Http/Controllers/EventoController.php:48-49` β€” stessa logica, default 20 -- `app/Http/Controllers/EmailController.php:61-62` β€” stessa logica, default 20 -- `resources/views/individui/index.blade.php` β€” dropdown ` - @foreach([10, 20, 25, 50, 100] as $p) - - @endforeach - - @foreach(request()->except(['perPage', 'page']) as $key => $value) - @if(is_array($value)) - @foreach($value as $v) - - @endforeach - @else - - @endif - @endforeach - - -
- {{ $messages->links('vendor.pagination.simple-bootstrap-4') }} -
+ @endsection diff --git a/resources/views/eventi/import.blade.php b/resources/views/eventi/import.blade.php deleted file mode 100644 index f50306dd..00000000 --- a/resources/views/eventi/import.blade.php +++ /dev/null @@ -1,55 +0,0 @@ -@extends('layouts.adminlte') -@section('title', 'Importa Eventi') -@section('page_title', 'Importa Eventi da ICS') - -@section('content') -
-
-
-
-

Carica file ICS

-
-
-
- @csrf -
- - - - Il file deve essere in formato ICS (iCalendar). - -
- - - Annulla - -
-
-
-
-
-
-
-

Informazioni

-
-
-
Campi importati:
-
    -
  • SUMMARY β†’ Nome evento (obbligatorio)
  • -
  • DESCRIPTION β†’ Descrizione
  • -
  • DTSTART β†’ Data/Ora inizio
  • -
  • DTEND β†’ Durata
  • -
  • LOCATION β†’ Luogo
  • -
  • UID β†’ ID esterno (per evitare duplicati)
  • -
-

- - Gli eventi con UID giΓ  presente nel sistema verranno saltati automaticamente. -

-
-
-
-
-@endsection diff --git a/resources/views/eventi/index.blade.php b/resources/views/eventi/index.blade.php index 8350387b..457b86d1 100644 --- a/resources/views/eventi/index.blade.php +++ b/resources/views/eventi/index.blade.php @@ -34,9 +34,6 @@ $canDeleteEventi = Auth::user()->canDelete('eventi'); @endif @if($canWriteEventi) - - Importa ICS - Nuovo Evento @@ -250,29 +247,8 @@ $canDeleteEventi = Auth::user()->canDelete('eventi'); - diff --git a/resources/views/gruppi/import.blade.php b/resources/views/gruppi/import.blade.php deleted file mode 100644 index ffde25f9..00000000 --- a/resources/views/gruppi/import.blade.php +++ /dev/null @@ -1,64 +0,0 @@ -@extends('layouts.adminlte') -@section('title', 'Importa Gruppi') -@section('page_title', 'Importa Gruppi da CSV') - -@section('content') -
-
-
-
-

Carica file CSV

-
-
-
- @csrf -
- - - - Il file deve essere in formato CSV con separatore virgola. - -
- - - Annulla - -
-
-
-
-
-
-
-

Template

-
-
-

Scarica il template CSV per l'importazione:

- - Scarica Template - -
-
-
-
-

Formato CSV

-
-
-
Campi:
-
    -
  • nome (obbligatorio)
  • -
  • descrizione
  • -
  • parent_id (ID del gruppo padre)
  • -
  • diocesi_id (ID della diocesi)
  • -
  • indirizzo_incontro
  • -
  • cap_incontro
  • -
  • cittΓ _incontro
  • -
  • sigla_provincia_incontro (2 lettere)
  • -
-
-
-
-
-@endsection diff --git a/resources/views/gruppi/index.blade.php b/resources/views/gruppi/index.blade.php index 291f50af..26417039 100644 --- a/resources/views/gruppi/index.blade.php +++ b/resources/views/gruppi/index.blade.php @@ -55,9 +55,6 @@ $visibleColumnsJson = json_encode($visibleColumns); Salva Vista @if($canWriteGruppi) - - Importa - Nuovo Gruppo diff --git a/resources/views/individui/index.blade.php b/resources/views/individui/index.blade.php index a789ff6e..ff8b1392 100644 --- a/resources/views/individui/index.blade.php +++ b/resources/views/individui/index.blade.php @@ -220,29 +220,8 @@ $canDeleteIndividui = Auth::user()->canDelete('individui'); @endif @if($individui->count() > 0) - diff --git a/routes/web.php b/routes/web.php index 2c59f998..d2a3304b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -87,9 +87,6 @@ Route::patch('gruppi/{gruppo}/membri/{individuo}', [GruppoMembroController::clas Route::delete('gruppi/{gruppo}/membri/{individuo}', [GruppoMembroController::class, 'destroy'])->middleware('auth'); // Gruppi specific routes (MUST be before resource route) -Route::get('gruppi/import', [GruppoController::class, 'import'])->middleware('auth')->name('gruppi.import'); -Route::post('gruppi/import', [GruppoController::class, 'importStore'])->middleware('auth')->name('gruppi.import.store'); -Route::get('gruppi/template', [GruppoController::class, 'downloadTemplate'])->middleware('auth')->name('gruppi.template'); Route::get('gruppi/all', [GruppoController::class, 'allGruppi'])->middleware('auth'); Route::get('gruppi/{gruppo}/individui-email', [GruppoController::class, 'individuiEmail'])->middleware('auth'); @@ -100,8 +97,6 @@ Route::delete('gruppi/{gruppo}/avatar', [\App\Http\Controllers\GruppoAvatarContr Route::resource('gruppi', GruppoController::class)->middleware('auth'); Route::get('eventi/calendar', [EventoController::class, 'calendar'])->name('eventi.calendar')->middleware('auth'); Route::get('eventi/calendar/events', [EventoController::class, 'calendarEvents'])->name('eventi.calendar.events')->middleware('auth'); -Route::get('eventi/import', [EventoController::class, 'importIcs'])->middleware('auth')->name('eventi.import'); -Route::post('eventi/import', [EventoController::class, 'importIcsStore'])->middleware('auth')->name('eventi.import.store'); Route::get('eventi/{evento}/export-ics', [EventoController::class, 'exportIcs'])->name('eventi.export-ics')->middleware('auth'); Route::post('eventi/export-ics', [EventoController::class, 'exportSelectedIcs'])->name('eventi.export-selected-ics')->middleware('auth'); Route::post('eventi/mass-elimina', [EventoController::class, 'massElimina'])->middleware('auth');