Implementazione completa del progetto allineamento alla suite Evix (TRPG/lg231),
basato sul doc canonico docs/GAP_TRPG_NIS2_ALIGNMENT.md (5 fasi, 18 gap).
Version 1.0.0 → 1.5.0
Fase 1 — SSO Federation (v1.1.0)
- Migration 015_sso_columns: users.sso_identity_id + password_version
- application/services/SsoHelper.php (client SSO dual-mode, cURL nativo, zero deps)
- AuthController::login() + changePassword() conditional SSO (SSO_MODE=local default)
Fase 2 — Multi-device Sessions (v1.2.0)
- Migration 016_active_sessions: tabella + refresh_tokens.session_jti
- BaseController::requireAuth() verifica jti + last_activity throttle + parseDeviceLabel
- login() genera jti, logout/changePassword revoca selettiva
- GET/DELETE /auth/sessions[/{id}]
- UI settings.html tab Sicurezza con lista device + revoca
Fase 3 — Password Reset + Tenant Switcher (v1.3.0)
- Migration 017_password_reset_tokens (TTL 30min, single-use)
- POST /auth/forgot-password (risposta opaca) + reset-password
- Pagine forgot-password.html + reset-password.html (con strength bar)
- EmailService::sendPasswordReset
- POST /auth/switchContext con rotazione JWT + organization_id claim
- Dropdown tenant in sidebar esposto a tutti gli utenti con ≥2 org
Fase 4 — Impersonate + Preferences + Versioning UI (v1.4.0)
- POST /auth/impersonate (super_admin o consulente stesso firm, TTL 1h, audit)
- Migration 018_user_preferences: users.theme/timezone/notif_email/notif_inapp
- GET/PUT /auth/preferences
- Sidebar footer mostra versione + changelog modal su click
Fase 5 — Branding white-label + Auth-gate (v1.5.0)
- Migration 019_firm_branding (logo/colori/brand_name per consulting firm)
- BrandingController GET /branding/current (auth opzionale) + PUT
- common.js auto-applica CSS variables al boot
- public/js/auth-gate.js (gate password client-side per docs riservati, da TRPG)
Skip motivati:
- G15 demo login: simulator esistenti coprono
- G18 refactor controllers: rinviato (~5gg, valore tecnico solo)
Cron sync SSO: AgileHub Ticket #220 aperto a team AGILEHUB per estendere
sso-password-sync.sh al DB nis2_agile_db. Prerequisito per switch SSO_MODE=dual.
Backup files: tutti i file modificati hanno .bak.pre-{fase}-{ts} sia in DEV
sia in /var/www/nis2-agile/.backups/ su Hetzner (rollback ready).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
38 lines
2.3 KiB
JavaScript
38 lines
2.3 KiB
JavaScript
/**
|
|
* Auth gate per documenti tecnici NIS2 Agile (adattato da TRPG, Fase 5 / G17).
|
|
* Protezione lato client (non crittografica) — scopo: evitare visualizzazione casuale.
|
|
* Caricare nel <head> PRIMA di qualsiasi altro script o CSS.
|
|
*
|
|
* Password di default: Nis2Agile2026!@
|
|
* Override per-pagina: aggiungere data-pw="..." allo script tag, es:
|
|
* <script src="/js/auth-gate.js" data-pw="Angelo@2026!"></script>
|
|
* La session key è derivata dalla pw, quindi pagine con pw diverse non condividono sessione.
|
|
*/
|
|
(function(){
|
|
var DEFAULT_PW = 'Nis2Agile2026!@';
|
|
var scriptTag = document.currentScript || (function(){
|
|
var all = document.getElementsByTagName('script');
|
|
for (var i = 0; i < all.length; i++) if (all[i].src && all[i].src.indexOf('auth-gate.js') !== -1) return all[i];
|
|
return null;
|
|
})();
|
|
var EXPECTED = (scriptTag && scriptTag.getAttribute('data-pw')) || DEFAULT_PW;
|
|
var keySuffix = '';
|
|
try { keySuffix = btoa(EXPECTED).replace(/=/g, '').slice(0, 10); } catch (e) { keySuffix = String(EXPECTED.length); }
|
|
var KEY = 'nis2_tech_auth_' + keySuffix;
|
|
if (sessionStorage.getItem(KEY) === 'ok') return;
|
|
var pwd = prompt('Documento riservato — inserisci password:');
|
|
if (pwd === EXPECTED) {
|
|
sessionStorage.setItem(KEY, 'ok');
|
|
return;
|
|
}
|
|
try { window.stop(); } catch (e) {}
|
|
document.documentElement.innerHTML = '<head><meta charset="UTF-8"><title>Accesso riservato</title></head>'
|
|
+ '<body style="background:#0F172A;color:#fff;font-family:system-ui,-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;">'
|
|
+ '<div style="text-align:center;padding:40px;max-width:420px;">'
|
|
+ '<div style="font-size:3rem;margin-bottom:20px;">🔒</div>'
|
|
+ '<h1 style="font-size:1.5rem;margin:0 0 12px;">Accesso riservato</h1>'
|
|
+ '<p style="color:#94A3B8;font-size:.95rem;line-height:1.6;margin:0 0 24px;">Questo documento richiede autenticazione. Contatta il team Agile Software per ottenere la password.</p>'
|
|
+ '<button onclick="location.reload()" style="padding:10px 24px;background:#3B82F6;color:#fff;border:none;border-radius:6px;font-size:.9rem;cursor:pointer;">Riprova</button>'
|
|
+ '</div></body>';
|
|
})();
|