| @@ -6,43 +6,92 @@ CMS per portali captive: gestione di card informative, gallerie, flip-book e con | |||||
| ## Indice | ## Indice | ||||
| 1. [Avvio](#avvio) | |||||
| 2. [Configurazione (`lib/config.ts`)](#configurazione-libconfigts) | |||||
| 3. [Tipi di card](#tipi-di-card) | |||||
| 4. [File consentiti negli upload](#file-consentiti-negli-upload) | |||||
| 5. [Limiti di testo](#limiti-di-testo) | |||||
| 6. [Sicurezza degli input](#sicurezza-degli-input) | |||||
| 7. [Struttura dei dati (`data/`)](#struttura-dei-dati-data) | |||||
| 8. [Stato zero, rilasci e aggiornamenti del codice](#stato-zero-rilasci-e-aggiornamenti-del-codice) | |||||
| 9. [Backup e ripristino](#backup-e-ripristino) | |||||
| 10. [Factory Preset (developer)](#factory-preset-developer) | |||||
| 11. [Font](#font) | |||||
| 12. [Deploy sotto sotto-percorso (basePath) dietro Apache](#deploy-sotto-sotto-percorso-basepath-dietro-apache) | |||||
| 13. [Protezione dell'amministrazione (Keycloak) e routing](#protezione-dellamministrazione-keycloak-e-routing) | |||||
| 14. [Prerequisiti di sistema](#prerequisiti-di-sistema) | |||||
| 1. [Prerequisiti di sistema](#prerequisiti-di-sistema) | |||||
| 2. [Avvio](#avvio) | |||||
| 3. [Configurazione (`lib/config.ts`)](#configurazione-libconfigts) | |||||
| 4. [Tipi di card](#tipi-di-card) | |||||
| 5. [File consentiti negli upload](#file-consentiti-negli-upload) | |||||
| 6. [Limiti di testo](#limiti-di-testo) | |||||
| 7. [Sicurezza degli input](#sicurezza-degli-input) | |||||
| 8. [Struttura dei dati (`data/`)](#struttura-dei-dati-data) | |||||
| 9. [Stato zero, rilasci e aggiornamenti del codice](#stato-zero-rilasci-e-aggiornamenti-del-codice) | |||||
| 10. [Backup e ripristino](#backup-e-ripristino) | |||||
| 11. [Factory Preset (developer)](#factory-preset-developer) | |||||
| 12. [Font](#font) | |||||
| 13. [Deploy sotto sotto-percorso (basePath) dietro Apache](#deploy-sotto-sotto-percorso-basepath-dietro-apache) | |||||
| 14. [Protezione dell'amministrazione (Keycloak) e routing](#protezione-dellamministrazione-keycloak-e-routing) | |||||
| 15. [Risoluzione problemi](#risoluzione-problemi) | 15. [Risoluzione problemi](#risoluzione-problemi) | ||||
| --- | --- | ||||
| ## Prerequisiti di sistema | |||||
| Sul server servono alcuni binari di sistema (richiamati direttamente, non via npm): | |||||
| | Binario | A cosa serve | Se manca | | |||||
| |---|---|---| | |||||
| | `ffmpeg` | Transcodifica video non compatibili | Upload video che richiedono ricodifica → `503` | | |||||
| | `ffprobe` | Riconoscimento codec video | Come sopra | | |||||
| | `zip` | Creazione backup / preset | Pulsanti "Save backup (ZIP)" e "Save as Factory Preset (dev)" → `503` | | |||||
| | `unzip` | Ripristino backup / factory reset | Pulsanti di ripristino → `503` | | |||||
| Verifica su server: | |||||
| ```bash | |||||
| which ffmpeg ffprobe zip unzip | |||||
| ``` | |||||
| Se mancano, installali con il gestore pacchetti del sistema (i nomi dei pacchetti sono `ffmpeg`, `zip`, `unzip`). | |||||
| --- | |||||
| ## Avvio | ## Avvio | ||||
| **Sviluppo:** | |||||
| **Installazione:** | |||||
| ```bash | ```bash | ||||
| mkdri -p /data/service/captive-portal-cms | |||||
| mkdir -p /data/service/captive-portal-cms | |||||
| cd /data/service/captive-portal-cms | cd /data/service/captive-portal-cms | ||||
| git clone https://git.afasystems.it/pollutri/captive-portal-cms.git | git clone https://git.afasystems.it/pollutri/captive-portal-cms.git | ||||
| cd captive-portal-cms | cd captive-portal-cms | ||||
| npm install | npm install | ||||
| npm run build | npm run build | ||||
| ``` | |||||
| **In fase di sviluppo avviarlo con:** | |||||
| ```bash | |||||
| npm run dev | npm run dev | ||||
| ``` | ``` | ||||
| Con `BASE_PATH = '/cards'` (default) apri [http://localhost:3000/cards](http://localhost:3000/cards) (portale pubblico) e [http://localhost:3000/cards/admin](http://localhost:3000/cards/admin) (amministrazione). Le URL "nude" `/` e `/admin` reindirizzano automaticamente a quelle prefissate. Con `BASE_PATH = ''` l'app gira sulla radice (`/` e `/admin`). | Con `BASE_PATH = '/cards'` (default) apri [http://localhost:3000/cards](http://localhost:3000/cards) (portale pubblico) e [http://localhost:3000/cards/admin](http://localhost:3000/cards/admin) (amministrazione). Le URL "nude" `/` e `/admin` reindirizzano automaticamente a quelle prefissate. Con `BASE_PATH = ''` l'app gira sulla radice (`/` e `/admin`). | ||||
| **Produzione:** | |||||
| **In produzione avviarlo con:** | |||||
| ```bash | ```bash | ||||
| /conf/etc/rc.d/rc.custom start | /conf/etc/rc.d/rc.custom start | ||||
| ``` | ``` | ||||
| **Esempio di rc.custom per CPC:** | |||||
| ```bash | |||||
| . /etc/mnvars | |||||
| . /etc/mnsuper.conf | |||||
| . $MN_rcconfig | |||||
| BIN="xxxxx" | |||||
| return=$rc_done | |||||
| case "$1" in | |||||
| start) | |||||
| cd /data/service/captive-portal-cms/captive-portal-cms && npm start & | |||||
| ;; | |||||
| stop) | |||||
| fuser -k 3000/tcp | |||||
| ;; | |||||
| restart) | |||||
| $0 stop && $0 start || return=$rc_failed | |||||
| ;; | |||||
| *) | |||||
| echo "Usage: $0 {start|stop|restart}" | |||||
| exit 1 | |||||
| esac | |||||
| ``` | |||||
| > **Server offline:** la macchina di produzione non ha accesso a internet. NON eseguire `npm install` lì. Installa le dipendenze su una macchina con internet (stesso OS, Linux), poi copia l'intera cartella `node_modules` sul server insieme al progetto buildato. Sul server basta `npm run build` (se `node_modules` è presente) + `npm start`. | > **Server offline:** la macchina di produzione non ha accesso a internet. NON eseguire `npm install` lì. Installa le dipendenze su una macchina con internet (stesso OS, Linux), poi copia l'intera cartella `node_modules` sul server insieme al progetto buildato. Sul server basta `npm run build` (se `node_modules` è presente) + `npm start`. | ||||
| ### Prerequisiti per la produzione | ### Prerequisiti per la produzione | ||||
| @@ -346,7 +395,7 @@ L'autorizzazione **non** è gestita dall'app Next ma da **Apache `mod_auth_openi | |||||
| 1. Apri l'**Admin Console** di Keycloak. | 1. Apri l'**Admin Console** di Keycloak. | ||||
| 2. Seleziona il realm del captive portal (es. `interceptor1`). | 2. Seleziona il realm del captive portal (es. `interceptor1`). | ||||
| 3. **Users** → verifica che esista un utente con username **`admin`** (o crea l'utente se non c'è: bottone **Add user** → Username: `admin` → **Create** → imposta una password dal tab **Credentials**). | |||||
| 3. **Users** → verifica che esista un utente con username **`admin`** (o crea l'utente se non c'è: dall'amministrazione majornet). | |||||
| 4. Per più amministratori, NON è necessario fare nulla in Keycloak: basta aggiungere altri username alla whitelist Apache (vedi punto B). Crea solo gli utenti Keycloak corrispondenti. | 4. Per più amministratori, NON è necessario fare nulla in Keycloak: basta aggiungere altri username alla whitelist Apache (vedi punto B). Crea solo gli utenti Keycloak corrispondenti. | ||||
| 5. *(Verifica opzionale)* **Clients** → `interceptor1-client` → tab **Client scopes** → **Evaluate** → scegli l'utente → **Generated ID token** → controlla che il claim `preferred_username` valga `admin`. Quel claim è incluso di default nei token Keycloak. | 5. *(Verifica opzionale)* **Clients** → `interceptor1-client` → tab **Client scopes** → **Evaluate** → scegli l'utente → **Generated ID token** → controlla che il claim `preferred_username` valga `admin`. Quel claim è incluso di default nei token Keycloak. | ||||
| @@ -451,7 +500,7 @@ L'amministratore è identificato dal **`preferred_username` Keycloak**, controll | |||||
| 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`, `alice`, `bob`). Imposta le credenziali normalmente. | ||||
| 2. **In Apache** (in tutti i blocchi `<Location "/cards/admin">`, `<Location "/cards/api/...">`): elenca gli username separati da spazi sulla riga `Require claim`: | 2. **In Apache** (in tutti i blocchi `<Location "/cards/admin">`, `<Location "/cards/api/...">`): elenca gli username separati da spazi sulla riga `Require claim`: | ||||
| ```apache | ```apache | ||||
| Require claim preferred_username:admin alice bob | |||||
| Require claim preferred_username:admin pollutri russi | |||||
| ``` | ``` | ||||
| (I valori multipli sono in OR — passa chiunque abbia uno di quegli username.) | (I valori multipli sono in OR — passa chiunque abbia uno di quegli username.) | ||||
| 3. **Reload Apache**: `apachectl configtest && systemctl reload apache2`. | 3. **Reload Apache**: `apachectl configtest && systemctl reload apache2`. | ||||
| @@ -481,24 +530,6 @@ A quel punto, ogni nuovo admin si gestisce solo in Keycloak (assegnando/rimuoven | |||||
| ### Pagine inesistenti → redirect alla home | ### Pagine inesistenti → redirect alla home | ||||
| Qualsiasi percorso non corrispondente a una pagina o API reale del progetto **non mostra una schermata d'errore**: viene reindirizzato alla home. È gestito lato Next da una rotta catch-all ([app/[...not_found]/page.tsx](app/%5B...not_found%5D/page.tsx)) che esegue `redirect('/')`. Le rotte reali (`/`, `/admin`, `/api/*`) hanno priorità; solo i path inesistenti finiscono lì. Le API inesistenti restano `404` (il redirect riguarda le pagine). | Qualsiasi percorso non corrispondente a una pagina o API reale del progetto **non mostra una schermata d'errore**: viene reindirizzato alla home. È gestito lato Next da una rotta catch-all ([app/[...not_found]/page.tsx](app/%5B...not_found%5D/page.tsx)) che esegue `redirect('/')`. Le rotte reali (`/`, `/admin`, `/api/*`) hanno priorità; solo i path inesistenti finiscono lì. Le API inesistenti restano `404` (il redirect riguarda le pagine). | ||||
| ## Prerequisiti di sistema | |||||
| Sul server servono alcuni binari di sistema (richiamati direttamente, non via npm): | |||||
| | Binario | A cosa serve | Se manca | | |||||
| |---|---|---| | |||||
| | `ffmpeg` | Transcodifica video non compatibili | Upload video che richiedono ricodifica → `503` | | |||||
| | `ffprobe` | Riconoscimento codec video | Come sopra | | |||||
| | `zip` | Creazione backup / preset | Pulsanti "Save backup (ZIP)" e "Save as Factory Preset (dev)" → `503` | | |||||
| | `unzip` | Ripristino backup / factory reset | Pulsanti di ripristino → `503` | | |||||
| Verifica su server: | |||||
| ```bash | |||||
| which ffmpeg ffprobe zip unzip | |||||
| ``` | |||||
| Se mancano, installali con il gestore pacchetti del sistema (i nomi dei pacchetti sono `ffmpeg`, `zip`, `unzip`). | |||||
| --- | |||||
| ## Risoluzione problemi | ## Risoluzione problemi | ||||