emilsoftware-utilities 2.0.0-dev.30 → 2.0.0-dev.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessi-module/Console/console.js +26 -17
- package/dist/accessi-module/Console/console.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/authenticatedUserPayloadDto.d.ts +1 -1
- package/dist/accessi-module/Console/generated/model/authenticatedUserPayloadDto.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/groupWithMenusEntity.d.ts +3 -1
- package/dist/accessi-module/Console/generated/model/groupWithMenusEntity.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/menuEntity.d.ts +2 -0
- package/dist/accessi-module/Console/generated/model/menuEntity.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/publicRegisterRequest.d.ts +0 -4
- package/dist/accessi-module/Console/generated/model/publicRegisterRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/registerRequest.d.ts +2 -6
- package/dist/accessi-module/Console/generated/model/registerRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/userDto.d.ts +5 -7
- package/dist/accessi-module/Console/generated/model/userDto.js.map +1 -1
- package/dist/accessi-module/Console/wiki.js +2 -0
- package/dist/accessi-module/Console/wiki.js.map +1 -1
- package/dist/accessi-module/Controllers/ConfiguratorController.js +2 -2
- package/dist/accessi-module/Controllers/ConfiguratorController.js.map +1 -1
- package/dist/accessi-module/Dtos/AuthenticatedUserPayloadDto.d.ts +1 -1
- package/dist/accessi-module/Dtos/AuthenticatedUserPayloadDto.js +1 -1
- package/dist/accessi-module/Dtos/AuthenticatedUserPayloadDto.js.map +1 -1
- package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.d.ts +1 -0
- package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js +9 -1
- package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js.map +1 -1
- package/dist/accessi-module/Dtos/GetMenusResponse.d.ts +1 -0
- package/dist/accessi-module/Dtos/GetMenusResponse.js +8 -0
- package/dist/accessi-module/Dtos/GetMenusResponse.js.map +1 -1
- package/dist/accessi-module/Dtos/PublicRegisterRequest.d.ts +1 -1
- package/dist/accessi-module/Dtos/PublicRegisterRequest.js +1 -1
- package/dist/accessi-module/Dtos/PublicRegisterRequest.js.map +1 -1
- package/dist/accessi-module/Dtos/RegisterRequest.d.ts +1 -3
- package/dist/accessi-module/Dtos/RegisterRequest.js +2 -22
- package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
- package/dist/accessi-module/Dtos/UserDto.d.ts +3 -4
- package/dist/accessi-module/Dtos/UserDto.js +9 -19
- package/dist/accessi-module/Dtos/UserDto.js.map +1 -1
- package/dist/accessi-module/Services/PermissionService/PermissionService.js +12 -9
- package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
- package/dist/accessi-module/Services/UserService/UserService.d.ts +1 -2
- package/dist/accessi-module/Services/UserService/UserService.js +26 -61
- package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
- package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +16 -0
- package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
- package/dist/accessi-module/database-updates/accessiSchema.d.ts +12 -1
- package/dist/accessi-module/database-updates/accessiSchema.js +24 -4
- package/dist/accessi-module/database-updates/accessiSchema.js.map +1 -1
- package/dist/accessi-module/security/accessControl.d.ts +2 -2
- package/dist/accessi-module/security/accessControl.js +2 -2
- package/dist/accessi-module/security/accessControl.js.map +1 -1
- package/dist/accessi-module/security/authenticatedToken.d.ts +1 -1
- package/dist/accessi-module/security/authenticatedToken.js +2 -2
- package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
- package/dist/emilsoftware-utilities-2.0.0-dev.32.tgz +0 -0
- package/package.json +1 -1
- package/dist/emilsoftware-utilities-2.0.0-dev.30.tgz +0 -0
|
@@ -1141,6 +1141,8 @@ POST /api/accessi/auth/confirm-reset-password/{token}
|
|
|
1141
1141
|
" body: JSON.stringify({ email, flagSuper: true }), // ignorato o negato",
|
|
1142
1142
|
"});"
|
|
1143
1143
|
].join("\n"), "Privilegi dal client"),
|
|
1144
|
+
note("info", `Campi di dominio`, `UTENTI_CONFIG contiene solo i flag di dominio Accessi: FLGSUPER, FLGADMIN, FLG2FATT (2FA), FLGPWDLESS (passwordless) e FLGPASSWORD (login locale). I flag applicativi legacy (FLGMOP, FLGPIANA, FLGADDETTI, FLGOSPITI, FLGPIANARFID, FLGCONTA, FLGCUBI, FLGCICLPASS, FLGDIPENDENTI, FLGINVENTARI) e le colonne applicative (CAUMOV, NUMMAC, RAGSOCCLI) sono stati rimossi dallo schema: i backend devono gestirli in tabelle proprie. ENABLEIA resta per l'assistente IA.`),
|
|
1145
|
+
note("info", `Gruppi menu e NOMECAMPO`, `Ogni gruppo menu puo dichiarare NOMECAMPO. get-groups-with-menus e get-menus espongono nomeCampo. Dopo la pulizia dello schema NOMECAMPO non deve piu puntare a colonne applicative rimosse.`),
|
|
1144
1146
|
note("info", `Campi estesi`, `extensionFieldsOptions allega colonne di tabelle applicative al profilo (per esempio la ragione sociale). Le colonne sono in whitelist: non costruirle mai da input HTTP.`)
|
|
1145
1147
|
]
|
|
1146
1148
|
},
|
|
@@ -1905,7 +1907,7 @@ function roleAssignmentEditor(roles, assignedRoles, groups) {
|
|
|
1905
1907
|
const assigned = (assignedRoles ?? []).some((current) => current.codiceRuolo === role.codiceRuolo);
|
|
1906
1908
|
const groupedMenus = groups.map((group) => ({ group, entries: group.menus.map((menu) => ({ menu, assignment: roleMenus.find((item) => item.codiceMenu === menu.codiceMenu) })).filter((entry) => entry.assignment) })).filter((entry) => entry.entries.length > 0);
|
|
1907
1909
|
const missingMenus = roleMenus.filter((item) => !catalogMenus.has(item.codiceMenu));
|
|
1908
|
-
return `<article class="role-assignment-card"><div class="role-assignment-heading"><label class="check"><input type="checkbox" name="role" value="${escapeHtml(role.codiceRuolo)}" ${assigned ? "checked" : ""}><span><strong>${escapeHtml(role.descrizioneRuolo)}</strong><small>Codice ruolo: ${escapeHtml(role.codiceRuolo)}</small></span></label><span class="role-menu-count">${roleMenus.length} menu</span></div><div class="role-permission-groups">${groupedMenus.map(({ group, entries }) => `<section class="role-permission-group"><div class="role-permission-group-heading"><strong>${escapeHtml(group.descrizioneGruppo)}</strong>${groupMetadata(group)}</div>${entries.map(({ menu, assignment }) => `<div class="role-permission-entry ${menu.enabled === false ? "is-disabled" : ""}"><div><strong>${escapeHtml(menu.descrizioneMenu)}</strong>${menuMetadata(menu)}</div><span class="permission-level">${escapeHtml(rolePermissionLevel(assignment?.tipoAbilitazione))}</span></div>`).join("")}</section>`).join("") || '<p class="form-help">Questo ruolo non contiene menu attivi nel catalogo.</p>'}${missingMenus.length ? `<section class="role-permission-group missing-role-menus"><strong>Menu non pi\
|
|
1910
|
+
return `<article class="role-assignment-card"><div class="role-assignment-heading"><label class="check"><input type="checkbox" name="role" value="${escapeHtml(role.codiceRuolo)}" ${assigned ? "checked" : ""}><span><strong>${escapeHtml(role.descrizioneRuolo)}</strong><small>Codice ruolo: ${escapeHtml(role.codiceRuolo)}</small></span></label><span class="role-menu-count">${roleMenus.length} menu</span></div><div class="role-permission-groups">${groupedMenus.map(({ group, entries }) => `<section class="role-permission-group"><div class="role-permission-group-heading"><strong>${escapeHtml(group.descrizioneGruppo)}</strong>${groupMetadata(group)}</div>${entries.map(({ menu, assignment }) => `<div class="role-permission-entry ${menu.enabled === false ? "is-disabled" : ""}"><div><strong>${escapeHtml(menu.descrizioneMenu)}</strong>${menuMetadata(menu)}</div><span class="permission-level">${escapeHtml(rolePermissionLevel(assignment?.tipoAbilitazione))}</span></div>`).join("")}</section>`).join("") || '<p class="form-help">Questo ruolo non contiene menu attivi nel catalogo.</p>'}${missingMenus.length ? `<section class="role-permission-group missing-role-menus"><strong>Menu non pi\xC3\xB9 presenti nel catalogo</strong>${missingMenus.map((menu) => `<div class="role-permission-entry"><div><strong>${escapeHtml(menu.codiceMenu)}</strong><p class="entity-note">Il menu \xC3\xA8 ancora associato al ruolo ma non \xC3\xA8 disponibile nel catalogo corrente.</p></div><span class="permission-level">${escapeHtml(rolePermissionLevel(menu.tipoAbilitazione))}</span></div>`).join("")}</section>` : ""}</div></article>`;
|
|
1909
1911
|
}).join("")}</div><button>Salva ruoli</button></form>`;
|
|
1910
1912
|
}
|
|
1911
1913
|
function roleOverview(role, groups) {
|
|
@@ -1915,7 +1917,7 @@ function roleOverview(role, groups) {
|
|
|
1915
1917
|
const tree = groups.map((group) => ({ group, entries: group.menus.filter((menu) => assignments.has(menu.codiceMenu)) })).filter((node) => node.entries.length > 0);
|
|
1916
1918
|
const orphans = roleMenus.filter((item) => !knownMenus.has(item.codiceMenu));
|
|
1917
1919
|
const groupNodes = tree.map(({ group, entries }) => `<li class="role-tree-group ${group.enabled === false ? "is-disabled" : ""}"><div class="role-tree-group-head"><strong>${escapeHtml(group.descrizioneGruppo)}</strong><span class="role-tree-count">${entries.length}</span></div><ul class="role-tree-menus">${entries.map((menu) => `<li class="role-tree-menu ${menu.enabled === false ? "is-disabled" : ""}"><span class="role-tree-menu-name">${escapeHtml(menu.descrizioneMenu)}</span><span class="permission-level">${escapeHtml(rolePermissionLevel(assignments.get(menu.codiceMenu)?.tipoAbilitazione))}</span></li>`).join("")}</ul></li>`).join("");
|
|
1918
|
-
const orphanNode = orphans.length ? `<li class="role-tree-group is-orphan"><div class="role-tree-group-head"><strong>Menu non pi\
|
|
1920
|
+
const orphanNode = orphans.length ? `<li class="role-tree-group is-orphan"><div class="role-tree-group-head"><strong>Menu non pi\xC3\xB9 nel catalogo</strong><span class="role-tree-count">${orphans.length}</span></div><ul class="role-tree-menus">${orphans.map((item) => `<li class="role-tree-menu"><span class="role-tree-menu-name"><code>${escapeHtml(item.codiceMenu)}</code></span><span class="permission-level">${escapeHtml(rolePermissionLevel(item.tipoAbilitazione))}</span></li>`).join("")}</ul></li>` : "";
|
|
1919
1921
|
return `<article class="role-card">
|
|
1920
1922
|
<div class="role-card-head">
|
|
1921
1923
|
<div class="role-card-title">
|
|
@@ -2042,11 +2044,11 @@ function federatedIdentityFields(providers) {
|
|
|
2042
2044
|
<label>Nota ${helpDot("sso-note")}<input name="note"><span class="form-help">Nota interna, non inviata al provider.</span></label>`;
|
|
2043
2045
|
}
|
|
2044
2046
|
function federatedIdentitySection(identities, providers) {
|
|
2045
|
-
return `<section class="user-editor-section sso-identity-section" data-user-panel="sso" role="tabpanel" aria-labelledby="user-tab-sso"><div class="section-heading"><div><p class="eyebrow">Autenticazione esterna</p><h3>Identit\
|
|
2047
|
+
return `<section class="user-editor-section sso-identity-section" data-user-panel="sso" role="tabpanel" aria-labelledby="user-tab-sso"><div class="section-heading"><div><p class="eyebrow">Autenticazione esterna</p><h3>Identit\xC3\xA0 SSO</h3></div><span class="muted">Collegamenti verificati dal backend</span></div><p class="form-help">Disabilita conserva lo storico; elimina rimuove il collegamento (l'utente resta).</p><div class="sso-identity-list">${identities.map((identity) => `<article class="sso-identity-item ${identity.active ? "" : "is-disabled"}"><div class="sso-identity-data"><strong>${escapeHtml(identity.provider)}</strong><dl class="entity-metadata"><div><dt>Subject</dt><dd>${escapeHtml(identity.subject)}</dd></div><div><dt>Stato</dt><dd>${identity.active ? "Abilitata" : "Disabilitata"}</dd></div></dl>${identity.note ? `<p class="entity-note"><strong>Nota</strong>${escapeHtml(identity.note)}</p>` : ""}</div><div class="sso-identity-actions"><button type="button" class="secondary" data-identity-toggle="${escapeHtml(identity.identityKey)}" data-active="${String(!identity.active)}">${identity.active ? "Disabilita" : "Abilita"}</button><button type="button" class="icon-button danger-button" data-identity-delete="${escapeHtml(identity.identityKey)}" aria-label="Elimina definitivamente il collegamento SSO ${escapeHtml(identity.provider)}" title="Elimina definitivamente il collegamento SSO"><span aria-hidden="true">🗑</span></button></div></article>`).join("") || '<p class="muted">Nessun collegamento SSO.</p>'}</div>${providers.some((provider) => provider.active) ? `<form id="link-sso" class="sso-link-form">${federatedIdentityFields(providers)}<button>Collega SSO verificato</button></form>` : '<p class="form-help">Non ci sono provider SSO attivi. Censiscine uno nella sezione SSO prima di creare collegamenti.</p>'}</section>`;
|
|
2046
2048
|
}
|
|
2047
2049
|
function userDetailTabs(hasSso) {
|
|
2048
2050
|
const tabs = [
|
|
2049
|
-
...hasSso ? [{ id: "sso", label: "Identit\
|
|
2051
|
+
...hasSso ? [{ id: "sso", label: "Identit\xC3\xA0 SSO" }] : [],
|
|
2050
2052
|
{ id: "profile", label: "Profilo e accesso" },
|
|
2051
2053
|
{ id: "roles", label: "Ruoli" },
|
|
2052
2054
|
{ id: "grants", label: "Grant diretti" }
|
|
@@ -2103,7 +2105,7 @@ function pageNumbers(current, total) {
|
|
|
2103
2105
|
return result2;
|
|
2104
2106
|
}
|
|
2105
2107
|
function pagerMarkup(totalPages) {
|
|
2106
|
-
const context = `<span class="pager-context">${usersTotal} utent${usersTotal === 1 ? "e" : "i"}${totalPages > 1 ? ` \xB7 pagina ${usersPage + 1} di ${totalPages}` : ""}</span>`;
|
|
2108
|
+
const context = `<span class="pager-context">${usersTotal} utent${usersTotal === 1 ? "e" : "i"}${totalPages > 1 ? ` \xC2\xB7 pagina ${usersPage + 1} di ${totalPages}` : ""}</span>`;
|
|
2107
2109
|
if (totalPages <= 1) {
|
|
2108
2110
|
return `<nav class="pager" aria-label="Paginazione utenti">${context}</nav>`;
|
|
2109
2111
|
}
|
|
@@ -2278,14 +2280,20 @@ async function showUsers() {
|
|
|
2278
2280
|
function authenticationPolicyFields(user) {
|
|
2279
2281
|
return `<fieldset><legend>Verifica dell'accesso (opzionale)</legend>
|
|
2280
2282
|
<label class="check"><input name="flagDueFattori" type="checkbox" ${user.flagDueFattori ? "checked" : ""}> Richiedi un codice via email (2FA) ${helpDot("user-2fa")}</label>
|
|
2281
|
-
<p class="form-help">Se attiva, il codice \
|
|
2283
|
+
<p class="form-help">Se attiva, il codice \xC3\xA8 richiesto dopo password o SSO.</p>
|
|
2282
2284
|
<label class="check"><input name="passwordlessLoginEnabled" type="checkbox" ${user.passwordlessLoginEnabled ? "checked" : ""} ${user.flagDueFattori ? "" : "disabled"}> Consenti accesso con il solo codice email ${helpDot("user-passwordless")}</label>
|
|
2283
2285
|
<p class="form-help">Accesso senza password (richiede il codice email).</p>
|
|
2284
2286
|
</fieldset>`;
|
|
2285
2287
|
}
|
|
2288
|
+
function applicationFlagFields(user) {
|
|
2289
|
+
const record = user;
|
|
2290
|
+
return `<fieldset><legend>Abilitazioni applicative</legend>
|
|
2291
|
+
<label class="check"><input name="enableIa" type="checkbox" ${record.enableIa ? "checked" : ""}> Assistente IA (ENABLEIA)</label>
|
|
2292
|
+
</fieldset>`;
|
|
2293
|
+
}
|
|
2286
2294
|
function showLocalUserForm() {
|
|
2287
2295
|
render(`<button id="back">Indietro</button><h2>Nuovo utente locale</h2><p class="muted">Viene inviata l'e-mail per impostare la password.</p>
|
|
2288
|
-
<form id="local-user"><label>Email ${helpDot("user-email")}<input name="email" type="email" required><span class="form-help">Identificativo di accesso; ricever\
|
|
2296
|
+
<form id="local-user"><label>Email ${helpDot("user-email")}<input name="email" type="email" required><span class="form-help">Identificativo di accesso; ricever\xC3\xA0 l'email per la password.</span></label><label>Nome ${helpDot("user-name")}<input name="nome"></label><label>Cognome ${helpDot("user-name")}<input name="cognome"></label><button>Crea utente</button></form>`);
|
|
2289
2297
|
byId("back").onclick = () => show("users");
|
|
2290
2298
|
const localUserForm = document.getElementById("local-user");
|
|
2291
2299
|
if (localUserForm) localUserForm.onsubmit = (event) => {
|
|
@@ -2302,7 +2310,7 @@ async function showSsoUserForm() {
|
|
|
2302
2310
|
if (!providers.some((provider) => provider.active)) {
|
|
2303
2311
|
throw new Error("Prima di creare un utente SSO, censisci e abilita almeno un provider SSO.");
|
|
2304
2312
|
}
|
|
2305
|
-
render(`<button id="back">Indietro</button><h2>Nuovo utente SSO</h2><p class="muted">Salva solo collegamenti gi\
|
|
2313
|
+
render(`<button id="back">Indietro</button><h2>Nuovo utente SSO</h2><p class="muted">Salva solo collegamenti gi\xC3\xA0 verificati dal backend.</p>
|
|
2306
2314
|
<form id="sso-user"><label>Email ${helpDot("user-email")}<input name="email" type="email" required><span class="form-help">Email di contatto e identificativo Accessi dell'utente.</span></label><label>Nome ${helpDot("user-name")}<input name="nome"></label><label>Cognome ${helpDot("user-name")}<input name="cognome"></label>${federatedIdentityFields(providers)}<label class="check"><input name="passwordLoginEnabled" type="checkbox"> Abilita anche la password locale ${helpDot("user-password-login")}</label><span class="form-help">Se disattivato, l'utente accede solo via SSO.</span><button>Crea utente SSO</button></form>`);
|
|
2307
2315
|
byId("back").onclick = () => show("ssoUsers");
|
|
2308
2316
|
const ssoUserForm = document.getElementById("sso-user");
|
|
@@ -2325,10 +2333,10 @@ async function showSsoUserForm() {
|
|
|
2325
2333
|
};
|
|
2326
2334
|
}
|
|
2327
2335
|
async function showSsoProviders() {
|
|
2328
|
-
if (!federatedAuthenticationAvailable) throw new Error("SSO non \
|
|
2336
|
+
if (!federatedAuthenticationAvailable) throw new Error("SSO non \xC3\xA8 abilitato in questa istanza Accessi.");
|
|
2329
2337
|
const providerList = result(await getFederatedProviders());
|
|
2330
2338
|
render(`<div class="toolbar"><button id="new-provider">Nuovo provider</button><button id="reload-providers" class="secondary">Aggiorna</button></div>
|
|
2331
|
-
<h2>Provider SSO</h2><p class="muted">La validazione di token, issuer e segreti resta nel backend. Un provider si elimina solo se nessuna identit\
|
|
2339
|
+
<h2>Provider SSO</h2><p class="muted">La validazione di token, issuer e segreti resta nel backend. Un provider si elimina solo se nessuna identit\xC3\xA0 \xC3\xA8 collegata.</p>
|
|
2332
2340
|
<div class="menu-table-wrap"><table><thead><tr><th>Provider</th><th>Descrizione</th><th>Stato</th><th></th></tr></thead><tbody>${providerList.map((provider) => `<tr class="${provider.active ? "" : "is-disabled"}"><td><code>${escapeHtml(provider.provider)}</code></td><td>${escapeHtml(provider.description)}</td><td>${provider.active ? "Attivo" : "Disabilitato"}</td><td class="row-actions"><button data-provider="${escapeHtml(provider.provider)}">Gestisci</button></td></tr>`).join("") || '<tr><td colspan="4" class="muted">Nessun provider censito.</td></tr>'}</tbody></table></div>`);
|
|
2333
2341
|
byId("new-provider").onclick = () => showProviderForm();
|
|
2334
2342
|
byId("reload-providers").onclick = () => handleAction(showSsoProviders);
|
|
@@ -2337,11 +2345,11 @@ async function showSsoProviders() {
|
|
|
2337
2345
|
});
|
|
2338
2346
|
}
|
|
2339
2347
|
async function showSsoUsers() {
|
|
2340
|
-
if (!federatedAuthenticationAvailable) throw new Error("SSO non \
|
|
2348
|
+
if (!federatedAuthenticationAvailable) throw new Error("SSO non \xC3\xA8 abilitato in questa istanza Accessi.");
|
|
2341
2349
|
const users = await loadUsers();
|
|
2342
2350
|
render(`<div class="toolbar"><button id="new-sso">Nuovo utente SSO</button><button id="reload-sso-users" class="secondary">Aggiorna</button></div>
|
|
2343
|
-
<h2>Utenti e identit\
|
|
2344
|
-
<div class="menu-table-wrap"><table><thead><tr><th>Utente</th><th>Accesso</th><th></th></tr></thead><tbody>${users.map(({ utente }) => `<tr><td>${escapeHtml(utente.email)}</td><td>${utente.passwordLoginEnabled === false ? "solo SSO" : "password e SSO"}</td><td class="row-actions"><button data-sso-user="${utente.codiceUtente}">Gestisci identit\
|
|
2351
|
+
<h2>Utenti e identit\xC3\xA0 SSO</h2><p class="muted">Gestisci i collegamenti provider/subject gi\xC3\xA0 verificati dal backend.</p>
|
|
2352
|
+
<div class="menu-table-wrap"><table><thead><tr><th>Utente</th><th>Accesso</th><th></th></tr></thead><tbody>${users.map(({ utente }) => `<tr><td>${escapeHtml(utente.email)}</td><td>${utente.passwordLoginEnabled === false ? "solo SSO" : "password e SSO"}</td><td class="row-actions"><button data-sso-user="${utente.codiceUtente}">Gestisci identit\xC3\xA0</button></td></tr>`).join("") || '<tr><td colspan="3" class="muted">Nessun utente.</td></tr>'}</tbody></table></div>`);
|
|
2345
2353
|
byId("new-sso").onclick = () => handleAction(showSsoUserForm);
|
|
2346
2354
|
byId("reload-sso-users").onclick = () => handleAction(showSsoUsers);
|
|
2347
2355
|
document.querySelectorAll("[data-sso-user]").forEach((button) => {
|
|
@@ -2420,7 +2428,7 @@ async function showUser(rawCode) {
|
|
|
2420
2428
|
const defaultUserTab = federatedAuthenticationAvailable ? "sso" : "profile";
|
|
2421
2429
|
render(`<div class="user-action-bar"><button id="back" type="button" class="secondary">Indietro</button><label class="inline-field">Stato registrazione ${helpDot("user-state")}<select id="user-state">${registrationStateOptions(user.statoRegistrazione)}</select></label><button id="save-state" type="button" class="secondary">Aggiorna stato</button><button id="disable-user" type="button" class="danger-button">Imposta stato eliminato</button>${helpDot("user-delete")}</div><div class="page-header"><div><p class="eyebrow">Utente ${codiceUtente}</p><h2>${escapeHtml(user.email)}</h2></div><span class="muted">Gestione profilo, ruoli e autorizzazioni</span></div>${userDetailTabs(federatedAuthenticationAvailable)}<div class="user-editor">
|
|
2422
2430
|
${identitySection}
|
|
2423
|
-
<form id="profile" data-user-panel="profile" role="tabpanel" aria-labelledby="user-tab-profile"><h3>Profilo e accesso</h3><label>Nome ${helpDot("user-name")}<input name="nome" value="${escapeHtml(user.nome)}"></label><label>Cognome ${helpDot("user-name")}<input name="cognome" value="${escapeHtml(user.cognome)}"></label><label>Email ${helpDot("user-email")}<input name="email" type="email" value="${escapeHtml(user.email)}" required><span class="form-help">Identificativo di accesso e recapito.</span></label>${federatedAuthenticationAvailable ? `<label class="check"><input name="passwordLoginEnabled" type="checkbox" ${user.passwordLoginEnabled !== false ? "checked" : ""}> Login con password ${helpDot("user-password-login")}</label><span class="form-help">Se disabilitato, il login con email e password restituisce un errore esplicito; restano valide le identit\
|
|
2431
|
+
<form id="profile" data-user-panel="profile" role="tabpanel" aria-labelledby="user-tab-profile"><h3>Profilo e accesso</h3><label>Nome ${helpDot("user-name")}<input name="nome" value="${escapeHtml(user.nome)}"></label><label>Cognome ${helpDot("user-name")}<input name="cognome" value="${escapeHtml(user.cognome)}"></label><label>Email ${helpDot("user-email")}<input name="email" type="email" value="${escapeHtml(user.email)}" required><span class="form-help">Identificativo di accesso e recapito.</span></label>${federatedAuthenticationAvailable ? `<label class="check"><input name="passwordLoginEnabled" type="checkbox" ${user.passwordLoginEnabled !== false ? "checked" : ""}> Login con password ${helpDot("user-password-login")}</label><span class="form-help">Se disabilitato, il login con email e password restituisce un errore esplicito; restano valide le identit\xC3\xA0 SSO attive.</span>` : ""}${authenticationPolicyFields(user)}${applicationFlagFields(user)}<button>Salva</button></form>
|
|
2424
2432
|
${roleAssignmentEditor(allRoles, userGrants.ruoli, menuGroups)}
|
|
2425
2433
|
${directGrantEditor(menuGroups, userGrants.abilitazioni)}
|
|
2426
2434
|
</div>`);
|
|
@@ -2459,6 +2467,7 @@ async function showUser(rawCode) {
|
|
|
2459
2467
|
cognome: values.cognome || void 0,
|
|
2460
2468
|
flagDueFattori: fields.has("flagDueFattori"),
|
|
2461
2469
|
passwordlessLoginEnabled: fields.has("passwordlessLoginEnabled"),
|
|
2470
|
+
enableIa: fields.has("enableIa"),
|
|
2462
2471
|
...federatedAuthenticationAvailable ? { passwordLoginEnabled: fields.has("passwordLoginEnabled") } : {}
|
|
2463
2472
|
});
|
|
2464
2473
|
if (codiceUtente === currentUser?.codiceUtente && (fields.has("flagDueFattori") !== Boolean(user.flagDueFattori) || fields.has("passwordlessLoginEnabled") !== Boolean(user.passwordlessLoginEnabled))) {
|
|
@@ -2514,7 +2523,7 @@ async function showUser(rawCode) {
|
|
|
2514
2523
|
});
|
|
2515
2524
|
document.querySelectorAll("[data-identity-delete]").forEach((button) => {
|
|
2516
2525
|
button.onclick = () => handleAction(async () => {
|
|
2517
|
-
if (!window.confirm("Eliminare definitivamente questo collegamento SSO? L\
|
|
2526
|
+
if (!window.confirm("Eliminare definitivamente questo collegamento SSO? L\xE2\u20AC\u2122utente Accessi non verr\xC3\xA0 eliminato.")) return;
|
|
2518
2527
|
await deleteFederatedIdentityPermanently(codiceUtente, button.dataset.identityDelete ?? "");
|
|
2519
2528
|
showNotice("Collegamento SSO eliminato definitivamente.");
|
|
2520
2529
|
await showUser(String(codiceUtente));
|
|
@@ -2650,7 +2659,7 @@ async function showMenuItems() {
|
|
|
2650
2659
|
async function showMenuTypes() {
|
|
2651
2660
|
const menuTypes = result(await getMenuTypes());
|
|
2652
2661
|
render(`<div class="toolbar"><button id="new-menu-type">Nuovo tipo menu</button><button id="reload-menu-types" class="secondary">Aggiorna</button></div>
|
|
2653
|
-
<h2>Tipi menu</h2><p class="form-help">Classificano i menu (es. amministrazione, operativit\
|
|
2662
|
+
<h2>Tipi menu</h2><p class="form-help">Classificano i menu (es. amministrazione, operativit\xC3\xA0). Un tipo si elimina solo se non \xC3\xA8 usato da alcun menu.</p>
|
|
2654
2663
|
${menuTypeTable(menuTypes)}`);
|
|
2655
2664
|
byId("new-menu-type").onclick = () => showMenuTypeForm();
|
|
2656
2665
|
byId("reload-menu-types").onclick = () => handleAction(showMenuTypes);
|
|
@@ -2868,7 +2877,7 @@ async function showServiceTokens(includeRevoked = false) {
|
|
|
2868
2877
|
});
|
|
2869
2878
|
}
|
|
2870
2879
|
function showServiceTokenForm() {
|
|
2871
|
-
render(`<button id="back" type="button" class="secondary">Indietro</button><h2>Nuovo token di servizio</h2><form id="token-form"><label>Descrizione ${helpDot("token-label")}<input name="label" required maxlength="100"><span class="form-help">Identifica l'integrazione, ad esempio "IA - produzione".</span></label><label>Scope ${helpDot("token-scopes")}<input name="scopes" placeholder="ia, chat"><span class="form-help">Separati da virgola (lettere, numeri, ':', '_', '-'). Definiscono cosa pu\
|
|
2880
|
+
render(`<button id="back" type="button" class="secondary">Indietro</button><h2>Nuovo token di servizio</h2><form id="token-form"><label>Descrizione ${helpDot("token-label")}<input name="label" required maxlength="100"><span class="form-help">Identifica l'integrazione, ad esempio "IA - produzione".</span></label><label>Scope ${helpDot("token-scopes")}<input name="scopes" placeholder="ia, chat"><span class="form-help">Separati da virgola (lettere, numeri, ':', '_', '-'). Definiscono cosa pu\xC3\xB2 fare il token.</span></label><label>Durata in giorni ${helpDot("token-ttl")}<input name="ttlDays" type="number" min="1" step="1"><span class="form-help">Opzionale. Lascia vuoto per un token senza scadenza.</span></label><button>Crea token</button></form>`);
|
|
2872
2881
|
byId("back").onclick = () => void show("tokens");
|
|
2873
2882
|
const form = document.getElementById("token-form");
|
|
2874
2883
|
if (form) form.onsubmit = (event) => {
|