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>
47 lines
2.2 KiB
SQL
47 lines
2.2 KiB
SQL
-- Migration 018: User preferences (Fase 4 / G12)
|
|
-- Data: 2026-05-29
|
|
--
|
|
-- Aggiunge a `users` colonne per preferenze:
|
|
-- - theme (light|dark|auto)
|
|
-- - timezone (default Europe/Rome — vedi CLAUDE.md sez. timezone)
|
|
-- - notif_email (notifiche via mail on/off)
|
|
-- - notif_inapp (notifiche in-app on/off)
|
|
--
|
|
-- Rollback:
|
|
-- ALTER TABLE users
|
|
-- DROP COLUMN notif_inapp, DROP COLUMN notif_email,
|
|
-- DROP COLUMN timezone, DROP COLUMN theme;
|
|
|
|
SET @c1 := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users' AND COLUMN_NAME='theme');
|
|
SET @s1 := IF(@c1 = 0,
|
|
'ALTER TABLE users ADD COLUMN theme ENUM(''light'',''dark'',''auto'') DEFAULT ''auto'' AFTER preferred_language',
|
|
'SELECT ''theme già presente — skip'' AS info'
|
|
);
|
|
PREPARE stmt FROM @s1; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @c2 := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users' AND COLUMN_NAME='timezone');
|
|
SET @s2 := IF(@c2 = 0,
|
|
'ALTER TABLE users ADD COLUMN timezone VARCHAR(64) DEFAULT ''Europe/Rome'' AFTER theme',
|
|
'SELECT ''timezone già presente — skip'' AS info'
|
|
);
|
|
PREPARE stmt FROM @s2; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @c3 := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users' AND COLUMN_NAME='notif_email');
|
|
SET @s3 := IF(@c3 = 0,
|
|
'ALTER TABLE users ADD COLUMN notif_email TINYINT(1) DEFAULT 1 AFTER timezone',
|
|
'SELECT ''notif_email già presente — skip'' AS info'
|
|
);
|
|
PREPARE stmt FROM @s3; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SET @c4 := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users' AND COLUMN_NAME='notif_inapp');
|
|
SET @s4 := IF(@c4 = 0,
|
|
'ALTER TABLE users ADD COLUMN notif_inapp TINYINT(1) DEFAULT 1 AFTER notif_email',
|
|
'SELECT ''notif_inapp già presente — skip'' AS info'
|
|
);
|
|
PREPARE stmt FROM @s4; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
|
SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT, COLUMN_COMMENT
|
|
FROM information_schema.COLUMNS
|
|
WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users'
|
|
AND COLUMN_NAME IN ('theme','timezone','notif_email','notif_inapp');
|