v1.7.21
Torna all'indiceVersione precedente pubblicata: 1.7.20 (1 ottobre 2026)
Backend: .NET 10 + IIS / Linux nginx
Frontend: Angular 21
Versione dedicata alla sicurezza e all'accesso ai dati. Chiude i risultati di una revisione di sicurezza completa del framework e porta OData allo stesso livello di permessi del CRUD. In sintesi:
enableCookieAuthenticationaccetta un terzo valore,"signed": cookie firmato dal server, più sessioni per utente, logout per singola sessione;- OData applica i permessi di route e colonna, i vincoli di riga dell'utente e scrive passando dal CRUD del framework;
- i token personali permettono di collegare Power BI, Excel e script agli endpoint OData;
- il flag "secure upload" delle colonne di upload torna a proteggere i file della colonna;
- modifica e cancellazione rispettano la restrizione per utente anche nel CRUD della UI;
- gli errori mostrano all'utente un messaggio tradotto con un codice di tracciamento, i dettagli tecnici solo al superadmin.
Le modifiche allo schema dei metadati si applicano da sole all'avvio. Le funzionalità sono state verificate con i test end-to-end su SQL Server, MySQL, PostgreSQL e Oracle, nelle tre modalità di enableCookieAuthentication.
🔐 Autenticazione e sessioni
- Tre modalità.
enableCookieAuthenticationvalefalse,trueo"signed". Confalsel'utente è quello dichiarato dal cookie del browser: solo per sviluppo. All'avvio un messaggio[security]lo segnala, l'editor AppSettings lo descrive e chiede conferma al salvataggio. Un valore non riconosciuto vale come"signed", con avviso nel log. "signed". Il server firma il cookiek-user(HMAC-SHA256, scadenza dentro la firma): un cookie modificato o scaduto vale come assente. Lo stesso utente può avere più sessioni aperte, ognuna con il proprio identificativo.- Logout e revoca. Il logout chiude solo la sessione da cui parte, anche per le copie del cookie. Il logout di un utente fatto da un amministratore, il reset e il cambio della password chiudono tutte le sessioni di quell'utente nella sua azienda.
- Durata massima. Con
signedSessionMaxLifetimeHours(default 24,0= nessun limite) una sessione firmata scade a quell'età dal login, anche se usata di continuo. - Chiave di firma.
cookie-signing-keysi genera al primo avvio e si salva inappsettings.json. All'avvio il log mostra l'impronta della chiave (mai la chiave) e avvisa se la chiave non è stata salvata. - Chiamate verificate sul server. Con
falseil cookie non porta più privilegi forgiati (amministratore, ruolo, azienda): l'utente viene riletto dal database.
🔗 OData
- Permessi. Ogni entity set richiede il permesso di lettura sulla route. Una colonna negata all'utente citata in
$select,$filter,$orderbyo$expandrisponde 403; altrimenti torna vuota. - Vincoli di riga. La query parte dalla stessa SELECT del CRUD con la restrizione per utente, ruolo o azienda, il filtro di default e la cancellazione logica.
$filter,$orderby,$skip,$tope$countsi applicano fuori e possono solo restringere:or 1 eq 1non allarga il risultato. $expand. Ammesso verso route leggibili senza vincoli di riga né cancellazione logica; negli altri casi 403.- Scritture.
POST,PATCHeDELETEpassano dainsertRecord,updateRecordedeleteRecord: permessi, colonne non modificabili, trigger, campi di logging, change log, workflow e cancellazione logica valgono come dalla UI. Una riga nascosta all'utente risponde 404. - Multi-azienda. La connessione dati è quella dell'azienda dell'utente, come nel CRUD.
- Discovery.
/odata,/odata/$metadatae/odata/openapi.jsonrichiedono la sessione. ConodataPublicMetadata=truetornano pubblici; i dati restano protetti. - Token personali. Con
apiTokensEnabled=trueogni utente crea dal menu utente ("Token API") tokenwuic_pat_…con nome, scadenza (default 90 giorni, massimoapiTokenMaxLifetimeDays) e permesso di sola lettura o anche scrittura. Valgono solo su/odata, con i permessi del proprietario. Power BI ed Excel li usano come password con credenziali "Basic"; gli script conAuthorization: Bearer. Il token si vede una volta sola; il superadmin vede e revoca quelli di tutti.
🛡️ Sicurezza
Hardening best-effort su tutta la superficie: controlli sui valori che finiscono nelle query (ordinamenti, operatori, aggregati, chiavi, filtri numerici) allineati sui quattro provider; percorsi di upload e report confinati nelle loro cartelle; funzioni di amministrazione (report designer, rimozione e scaffolding dei report, riordino colonne, restart, scaffold OData) riservate al superadmin verificato sul database; email dei workflow solo a chi può eseguire il workflow; dati di esempio degli strumenti per assistenti AI solo al superadmin e mai con colonne di credenziali; guardie sugli utenti e sui ruoli legate alla tabella, non al nome della route; chiave pubblica della licenza incorporata nel pacchetto.
📎 Upload
- "Secure upload" per colonna. I file di una colonna con
upload_securesi leggono solo con una sessione valida e con la colonna visibile all'utente, sia da/uploadsia da/api/UploadImage. I file delle altre colonne restano pubblici. Le colonne che salvano il file nel database sono protette da/api/UploadImage. - Nomi file. I nomi con punti interni (
fattura-acme.com.pdf) sono accettati; restano rifiutati i nomi con estensioni eseguibili dal server anche in mezzo (foto.aspx.png).
🚦 Errori
All'utente arriva un messaggio tradotto con un codice di tracciamento (pulsante "Copia codice" nel dialog di errore). Lo stesso codice è registrato con lo stack completo in _error__logs. SQL, stack e messaggi interni arrivano solo al superadmin. Le traduzioni dei messaggi di errore nuovi si aggiungono da sole all'avvio.
🐛 Bug fix degni di nota
- Restrizione per utente in modifica e cancellazione. La UPDATE e la DELETE del CRUD contenevano solo la chiave: conoscendo l'id, un utente poteva modificare la riga di un altro. Ora la riga deve essere fra quelle che l'utente vede, altrimenti 403
errors.auth.route_read_forbidden. - Filtro di default con filtri in OR. Con l'operatore OR il filtro di default della route spariva e la griglia mostrava le righe che doveva nascondere. Ora resta in AND.
- Oracle. Booleani scritti come 1/0 anche su colonne con tipo UI booleano, nei filtri e nei parametri delle stored; funzioni distinte dalle procedure nello schema giusto; OData sullo schema dei dati anche con l'utente
SYSTEM(prima errori ORA-00942 intermittenti). - PostgreSQL e Oracle. L'inserimento con chiave identity non inviata dal client non va più in errore; i report applicano permessi e filtri dell'utente come su SQL Server e MySQL.
- Primo avvio sotto IIS. La configurazione iniziale non restituisce più un 500 a installazione riuscita: le migration si completano al riavvio del worker.
- Spreadsheet e sincronizzazione. Con un filtro attivo modifica e cancellazione colpivano la riga sbagliata; la selezione oltre la pagina non raggiunge più i record delle pagine successive; il salvataggio batch del kanban e la sincronizzazione offline ritentano solo ciò che è fallito.
- Menu. La barra compare con le etichette già tradotte, senza mostrare per un istante le chiavi.
📦 Pacchetti aggiornati
| Package | Da | A |
|---|---|---|
WuicCore |
1.7.20 | 1.7.21 |
Wuic.Webcore |
1.7.20 | 1.7.21 |
WuicOData |
1.7.20 | 1.7.21 |
RuntimeEfCore |
1.7.20 | 1.7.21 |
Wuic.MySqlProvider |
1.7.20 | 1.7.21 |
Wuic.PostgresProvider |
1.7.20 | 1.7.21 |
Wuic.OracleProvider |
1.7.20 | 1.7.21 |
wuic-framework-lib (npm) |
1.7.20 | 1.7.21 |
🔧 Aggiornamenti operativi raccomandati per chi aggiorna
- Modalità del cookie: in produzione impostare
enableCookieAuthenticationa"signed"(otrue);falseè solo per sviluppo. - Più istanze dietro un bilanciatore: copiare la stessa
cookie-signing-keyin tutte le istanze; con chiavi diverse una sessione vale solo sull'istanza che l'ha creata. Verificare nel log che l'impronta coincida. - Client OData: i client che leggevano
$metadatasenza sessione devono autenticarsi, oppure impostareodataPublicMetadata=true. Le scritture OData ora eseguono trigger e logging del CRUD e, sulle route con cancellazione logica, impostano il flag invece di cancellare la riga. md_service_apply_default_filter: deprecato. Il filtro di default si applica sempre, anche via OData.- Licenza: l'override dell'impronta della macchina si imposta solo con la variabile d'ambiente
WUIC_LICENSE_MACHINE_FINGERPRINT; le chiavilicense-machine-fingerprint-overrideelicense-public-key-peminappsettings.jsonsono ignorate. - Token API: per collegare Power BI, Excel o script impostare
apiTokensEnabled=true(ed eventualmenteapiTokenMaxLifetimeDays) dall'editor AppSettings.