Files
DevEnv nis2-agileandClaude Opus 4.8 4dfab2a391 [FORMAZIONE] Avatar di prodotto — mappa-logica COMPLETA (22 viste) + SELETTORI_DEMO + tassonomia corso + fix kb.js
Deliverable formazione-first (DESIGN_AVATAR_FORMAZIONE / product-demo-complete):
- docs/mappa-logica/01..22_*.md: tutte le viste app V2 mappate (formato canonico standard §2),
  selettori VERIFICATI sul DOM reale, endpoint verificati su api.js/script, gate ruolo dai controller
- docs/mappa-logica/SELETTORI_DEMO.md: registry canonico (22 viste, 131 visualizzazione + 89 azioni)
  + worklist consolidata 132 id stabili da aggiungere (modifiche chirurgiche future)
- docs/formazione/TASSONOMIA_CORSO_NIS2.{md,json}: 10 moduli / 28 lezioni / ~7h45, prerequisiti+durate,
  esame con soglia 80%, sandbox 'prova tu' org 996002
- fix kb.js: ingest scope=ORG ora invia organization_id (prima 422 KB_ORG_REQUIRED) — bug trovato da A2

Prodotto con 4 trittici di agenti (A1 esecutore -> A2 revisore -> A3 controllore avversariale):
A2: ~14 correzioni (cross-ref, gate ruolo, comportamenti); A3 PASS: 38 selettori campionati 0 rotti,
18 endpoint reali, 0 violazioni normative (Allegati 3/4, IS-4, '1 mese', PII.* interna), 9 claim verificati.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:50:19 +02:00

4.7 KiB
Raw Permalink Blame History

MAPPA-LOGICA · Gestione Utenti (admin)

⟦ INIZIO · U-ADMIN-USERS · Videata "Gestione Utenti" (admin) ⟧ File: public/admin/users.html · URL: /admin/users.html · Scopo: elenco paginato di tutti gli utenti della piattaforma con ruolo, organizzazioni di appartenenza, ultimo login; attivazione/disattivazione account e impersonificazione (login come l'utente per 1 ora) · Profili: solo super_admin (check api.getMe(): se role !== 'super_admin' notifica "Accesso non autorizzato." e redirect a ../dashboard.html dopo 1,5s, righe 181-193)

• U-ADMIN-USERS.1 — Header pagina e breadcrumb Mostra: titolo "Gestione Utenti" + badge rosso "Super Admin"; breadcrumb "Amministrazione › Utenti" Azioni: click "Amministrazione" → torna a ../admin/index.html Dati da: nessuna Confine: header.content-header (riga 132) e nav.admin-breadcrumb[aria-label="Percorso di navigazione"] (riga 141), entrambi senza id

• U-ADMIN-USERS.2 — Tabella utenti Mostra: tabella con colonne: Nome, Email, Ruolo (badge colorato; etichette: Super Admin, Amministratore, Compliance Manager, Membro CDA, Auditor, Dipendente), Organizzazioni (tag multipli, "-" se nessuna), Ultimo Login (data/ora oppure "Mai"), Attivo (toggle switch), Data Creazione, Azioni (bottone "Impersonate"). Spinner durante il caricamento (aria-live="polite" sul contenitore); stato vuoto "Nessun utente trovato / Gli utenti registrati appariranno qui."; errori "Errore nel caricamento" / "Errore di connessione". Azioni: vedi U-ADMIN-USERS.3 (toggle) e U-ADMIN-USERS.4 (impersonate) Dati da: GET /api/admin/users?page={n} (campi per riga: full_name, email, role, organizations lista CSV, last_login_at, is_active, created_at, id; pagination: total, per_page default 20, page) Confine: #users-container (riga 150); tabella generata dinamicamente da renderUsers senza id

• U-ADMIN-USERS.3 — Toggle "Attivo" per utente Mostra: interruttore on/off per riga (verde = attivo); disabilitato per gli utenti super_admin; con etichette ARIA accessibili ("Attiva/Disattiva utente {email}") e focus visibile WCAG Azioni: cambio stato → toggleUserActive(userId, checked): PUT con {is_active: 1|0}; al successo notifica "Utente attivato/disattivato con successo."; in caso di errore notifica e ricarica la pagina corrente per resettare lo stato Dati da: PUT /api/admin/users/{userId} (body {is_active}) Confine: label.active-toggle con input[type=checkbox] per riga (generati in JS, righe 286-290 del sorgente; senza id — selezionabili solo per posizione di riga)

• U-ADMIN-USERS.4 — Azione "Impersonate" Mostra: bottone "Impersonate" con icona scambio e tooltip "Entra come questo utente per 1 ora"; visibile solo per utenti NON super_admin e attivi ("-" negli altri casi) Azioni: click → confirm('Entrare come {email} per 1 ora?...'); se confermato POST con {user_id}; al successo salva la sessione originale in sessionStorage (nis2_impersonate_origin_token, nis2_impersonate_origin_refresh, nis2_impersonate_target_email), sostituisce il token con quello impersonato (senza refresh token) e naviga a ../dashboard.html; il ritorno alla propria sessione avviene col logout Dati da: POST /api/auth/impersonate (risposta: data.access_token) Confine: bottoni button.btn.btn-secondary.btn-sm con onclick="impersonateUser(...)" generati in JS (riga 295 del sorgente; senza id)

• U-ADMIN-USERS.5 — Paginazione Mostra: se più pagine: "Visualizzati {start}-{end} di {total} utenti" + bottoni "« Precedente" / "Successivo »" (disabilitati ai bordi); se una sola pagina: "Totale: {n} utente/i" Azioni: "Precedente"/"Successivo" → loadUsers(page±1) ricarica la tabella Dati da: GET /api/admin/users?page={n} Confine: .pagination dentro #users-container (generata dinamicamente, righe 314-336 del sorgente; senza id)

• U-ADMIN-USERS.6 — Sidebar di navigazione Mostra: sidebar Bootstrap Italia condivisa (iniettata da loadSidebar() di ../js/common-bi.js) Azioni: navigazione app Dati da: nessuna Confine: #sidebar (riga 129)

⟦ FINE · U-ADMIN-USERS ⟧

ID STABILI MANCANTI (da aggiungere)

Elemento Riga Id proposto
Header pagina 132 nis2-admin-users-header
Breadcrumb 141 nis2-admin-users-breadcrumb
Tabella utenti (generata in JS) 240-242 nis2-admin-users-table
Toggle attivo per riga (input checkbox) 288 nis2-admin-users-toggle-{userId}
Bottone "Impersonate" per riga 295 nis2-admin-users-impersonate-{userId}
Bottone paginazione "Precedente" 321 nis2-admin-users-prev
Bottone paginazione "Successivo" 324 nis2-admin-users-next