diff --git a/README.md b/README.md index b474bdf..b7c3698 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ CMS per portali captive: gestione di card informative, gallerie, flip-book e con 7. [Limiti di testo](#limiti-di-testo) 8. [Sicurezza degli input](#sicurezza-degli-input) 9. [Struttura dei dati (`data/`)](#struttura-dei-dati-data) -10. [Stato zero, rilasci e aggiornamenti del codice](#stato-zero-rilasci-e-aggiornamenti-del-codice) +10. [Stato zero e compatibilità tra versioni](#stato-zero-e-compatibilità-tra-versioni) 11. [Backup e ripristino](#backup-e-ripristino) 12. [Factory Preset (developer)](#factory-preset-developer) 13. [Font](#font) @@ -159,6 +159,7 @@ portal: { image: 25 MB, pdf: 20 MB, video: 1 GB, +font: 5 MB, ``` Per cambiare un qualunque limite: modifica il numero in `lib/config.ts` e ricostruisci. Il valore è condiviso tra interfaccia (contatore / `maxLength`), validazione server e check di upload — un solo punto di verità. @@ -275,7 +276,7 @@ Copiare via questa cartella = backup completo. Sostituirla = ripristino completo --- -## Stato zero, rilasci e aggiornamenti del codice +## Stato zero e compatibilità tra versioni ### Cosa costituisce lo "stato zero" Lo stato applicativo (i dati) è **solo** il contenuto di `data/`: `cards.txt`, `portals.txt`, `uploads/`, `fonts/`. Tutto il resto — codice sorgente, `node_modules`, e gli asset di default in `public/` (es. `hero-bg.jpg`, `logo.png`) — **non** fa parte dello stato dati: arriva con il rilascio del software. "Azzerare" il CPC significa quindi sostituire `data/` con uno stato noto. @@ -285,8 +286,8 @@ Lo stato applicativo (i dati) è **solo** il contenuto di `data/`: `cards.txt`, - **Aggiornamento del codice**: si sostituisce tutto **tranne** `data/`. I contenuti restano al loro posto. - Da CLI un reset conservativo è: `mv data data.old && `. È l'equivalente del `tar zxf` citato dal QA — vedi nota su ZIP vs tar nella sezione [Backup](#backup-e-ripristino). -### Compatibilità dei contenuti dopo un update del codice -I contenuti salvati da versioni precedenti continuano a funzionare: in lettura vengono adattati al volo (es. il vecchio `extraImages: string[]` viene convertito in `extraMedia: MediaItem[]` in [`lib/db.ts`](lib/db.ts)). **Convenzione per future modifiche di schema:** aggiungere il branch di migrazione nella lettura (`getCards`/`getPortals`), senza mai rcompattare i dati legacy in scrittura senza un fallback in lettura — così un archivio di contenuti vecchio resta sempre ripristinabile. +### Compatibilità dei contenuti tra versioni +I contenuti salvati da versioni precedenti continuano a funzionare: in lettura vengono adattati al volo (es. il vecchio `extraImages: string[]` viene convertito in `extraMedia: MediaItem[]` in [`lib/db.ts`](lib/db.ts)). **Convenzione per future modifiche di schema:** aggiungere il branch di migrazione nella lettura (`getCards`/`getPortals`), senza mai ricompattare i dati legacy in scrittura senza un fallback in lettura — così un archivio di contenuti vecchio resta sempre ripristinabile. La procedura operativa di aggiornamento è descritta in [Aggiornamento](#aggiornamento). ### Far accompagnare lo stato zero ai rilasci Per avere uno stato di partenza noto su ogni macchina nuova, includere nel pacchetto di rilascio un `factory/preset.zip` curato (vedi [Factory Preset](#factory-preset-developer)). Su una macchina nuova, il ripristino di quel preset porta allo stato zero ufficiale. @@ -298,8 +299,8 @@ Per avere uno stato di partenza noto su ogni macchina nuova, includere nel pacch Disponibile dall'admin in **Settings → Backup & Restore**. ### Dall'interfaccia -- **⬇ Save backup (ZIP)** — scarica `interceptor-backup-YYYYMMDD-hhmmss.zip` con card, configurazione, media e font (esclude i file temporanei). -- **⤴ Restore from ZIP** — carica uno zip; dopo conferma sovrascrive lo stato attuale e ricarica la pagina. La cartella `data/` precedente viene conservata come `data.bak-/` come rete di sicurezza. +- **Save backup (ZIP)** — scarica `interceptor-backup-YYYYMMDD-hhmmss.zip` con card, configurazione, media e font (esclude i file temporanei). +- **Restore from ZIP** — carica uno zip; dopo conferma sovrascrive lo stato attuale e ricarica la pagina. La cartella `data/` precedente viene conservata come `data.bak-/` come rete di sicurezza. ### Da riga di comando (Linux) @@ -324,7 +325,7 @@ Lo zip così prodotto è caricabile direttamente dal pulsante "Restore from ZIP" ## Factory Preset (developer) -Stato "di fabbrica" ripristinabile con un click. Pensato per preparare preset standard (es. banner + icona + una card di redirect) da distribuire a più macchine MajorNet. +Stato "di fabbrica" ripristinabile con un click. Pensato per preparare preset standard (es. banner + icona + una card di redirect) da distribuire a più MajorNet. **La sezione è sempre visibile in admin.** Il bottone "Factory Reset" e lo stato del preset corrente sono mostrati sempre (è un'operazione lecita per qualunque amministratore). Il bottone "Save as Factory Preset (dev)" — che riscrive il preset di fabbrica — è invece **gated** da `FACTORY_PRESET_SAVE_ENABLED = true` in `lib/config.ts` (default `false`): tienilo attivo solo sulla macchina di sviluppo dove prepari/aggiorni il preset. Gli endpoint API restano comunque attivi a prescindere dal flag. @@ -587,18 +588,18 @@ Apri il file vhost (quello con i segnaposto `@@@REDIRECT@@@`, `@@@DIRECTORY@@@`, L'amministratore è identificato dal **`preferred_username` Keycloak**, controllato nei `` Apache. Per gestire più amministratori: -1. **In Keycloak** (Admin Console → Users): crea/verifica gli utenti con gli username che vuoi promuovere ad admin (es. `admin`, `alice`, `bob`). Imposta le credenziali normalmente. +1. **In Keycloak** (Admin Console → Users): crea/verifica gli utenti con gli username che vuoi promuovere ad admin (es. `admin`, `pollutri`, `russi`). Imposta le credenziali normalmente. 2. **In Apache** (in tutti i blocchi ``, ``): usa un blocco **``** con **una riga `Require claim` per ogni username**: ```apache Require claim preferred_username:admin - Require claim preferred_username:alice - Require claim preferred_username:bob + Require claim preferred_username:pollutri + Require claim preferred_username:russi ``` 3. **Reload Apache**: `apachectl configtest && systemctl reload apache2`. -> ⚠ **Non usare la forma compatta `Require claim preferred_username:admin alice bob`** sulla stessa riga: su alcune versioni di `mod_auth_openidc` (incluse quelle in uso sui server MajorNet) il parser dei valori space-separated è buggy e finisce per accettare solo il primo username. Il blocco `` con una riga `Require claim` per username delega la OR-logic ad Apache (`mod_authz_core`) e funziona affidabilmente. Stesso schema anche dentro ``. +> ⚠ **Non usare la forma compatta `Require claim preferred_username:admin pollutri russi`** sulla stessa riga: su alcune versioni di `mod_auth_openidc` (incluse quelle in uso sui server MajorNet) il parser dei valori space-separated è buggy e finisce per accettare solo il primo username. Il blocco `` con una riga `Require claim` per username delega la OR-logic ad Apache (`mod_authz_core`) e funziona affidabilmente. Stesso schema anche dentro ``. **Rimuovere un admin**: togli la riga `Require claim preferred_username:` corrispondente da `` (e ricarica Apache), oppure disabilita l'utente direttamente in Keycloak. diff --git a/lib/config.ts b/lib/config.ts index 51d868a..1100d7a 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -7,7 +7,7 @@ export const BASE_PATH = '/cards'; export const EXTERNAL_LINK_ENABLED = true; -// Mostra il bottone "Salva stato attuale come Factory Preset" nell'admin. +// Mostra il bottone "Save as Factory Preset (dev)" nell'admin. // È una funzione developer: tienila a false in produzione, true solo sulla macchina // dove serve preparare/aggiornare il preset di fabbrica. // Il bottone "Factory Reset" e lo stato del preset restano comunque sempre visibili diff --git a/lib/validation.ts b/lib/validation.ts index 6d7ff98..b76cceb 100644 --- a/lib/validation.ts +++ b/lib/validation.ts @@ -9,7 +9,7 @@ const VALID_CARD_TYPES: readonly CardType[] = [ 'INFO_PAGE', 'EXTERNAL_LINK', 'IMAGE_GALLERY', - 'SERVICE_REQUEST', + 'SERVICE_REQUEST', // non esposto in admin né effettivamente utilizzato (vedi nota in types/index.ts) 'BOOK', 'FULLSCREEN_LOCK', ] as const; diff --git a/types/index.ts b/types/index.ts index 6139563..9a23165 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,3 +1,8 @@ +// NOTE: 'SERVICE_REQUEST' è presente nel type union ma non viene MAI esposto in admin +// (manca dal dropdown del Card Type) né mai emerso/utilizzato a runtime: nessuna card +// di questo tipo viene creata. Lo lasciamo per retro-compatibilità con eventuali +// cards.txt di vecchie installazioni che lo contenessero. Per rimuoverlo del tutto +// andrebbe tolto anche da VALID_CARD_TYPES in lib/validation.ts. export type CardType = 'INFO_PAGE' | 'EXTERNAL_LINK' | 'IMAGE_GALLERY' | 'SERVICE_REQUEST' | 'BOOK' | 'FULLSCREEN_LOCK'; export type MediaItem = {