emilsoftware-utilities 2.0.0-dev.31 → 2.0.0-dev.33
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 +19 -46
- 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/createMenuGroupRequest.d.ts +0 -5
- package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/groupWithMenusEntity.d.ts +0 -2
- package/dist/accessi-module/Console/generated/model/groupWithMenusEntity.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/menuEntity.d.ts +0 -2
- package/dist/accessi-module/Console/generated/model/menuEntity.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/publicRegisterRequest.d.ts +0 -6
- package/dist/accessi-module/Console/generated/model/publicRegisterRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/registerRequest.d.ts +2 -8
- package/dist/accessi-module/Console/generated/model/registerRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.d.ts +0 -5
- package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/userDto.d.ts +3 -33
- package/dist/accessi-module/Console/generated/model/userDto.js.map +1 -1
- package/dist/accessi-module/Console/wiki.js +2 -2
- 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/CatalogDtos.d.ts +0 -2
- package/dist/accessi-module/Dtos/CatalogDtos.js +0 -14
- package/dist/accessi-module/Dtos/CatalogDtos.js.map +1 -1
- package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.d.ts +0 -1
- package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js +0 -8
- package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js.map +1 -1
- package/dist/accessi-module/Dtos/GetMenusResponse.d.ts +0 -1
- package/dist/accessi-module/Dtos/GetMenusResponse.js +0 -8
- 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 -4
- package/dist/accessi-module/Dtos/RegisterRequest.js +2 -31
- package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
- package/dist/accessi-module/Dtos/UserDto.d.ts +2 -17
- package/dist/accessi-module/Dtos/UserDto.js +4 -113
- package/dist/accessi-module/Dtos/UserDto.js.map +1 -1
- package/dist/accessi-module/Services/AuthService/AuthService.js +0 -2
- package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
- package/dist/accessi-module/Services/PermissionService/PermissionService.js +5 -13
- package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
- package/dist/accessi-module/Services/UserService/UserService.d.ts +1 -3
- package/dist/accessi-module/Services/UserService/UserService.js +19 -131
- package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
- package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +23 -0
- package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
- package/dist/accessi-module/database-updates/accessiSchema.d.ts +23 -1
- package/dist/accessi-module/database-updates/accessiSchema.js +29 -12
- 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.33.tgz +0 -0
- package/package.json +1 -1
- package/dist/emilsoftware-utilities-2.0.0-dev.31.tgz +0 -0
|
@@ -1141,8 +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", `
|
|
1145
|
-
note("info", `
|
|
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/colonne applicativi (FLGMOP, FLGPIANA, FLGADDETTI, FLGOSPITI, FLGPIANARFID, FLGCONTA, FLGCUBI, FLGCICLPASS, FLGDIPENDENTI, FLGINVENTARI, CAUMOV, NUMMAC, RAGSOCCLI, PAGDEF, ENABLEIA, CELLUTE e NOMECAMPO) sono stati rimossi: i backend devono gestirli in tabelle proprie. Il telefono canonico e UTENTI_CONFIG.CELLULARE.`),
|
|
1145
|
+
note("info", `Autorizzazioni`, `I gruppi/menu si abilitano tramite ABILITAZIONI, RUOLI_MNU e UTENTI_RUOLI. Il vecchio meccanismo NOMECAMPO (flag applicativo su UTENTI_CONFIG) e stato rimosso.`),
|
|
1146
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.`)
|
|
1147
1147
|
]
|
|
1148
1148
|
},
|
|
@@ -1907,7 +1907,7 @@ function roleAssignmentEditor(roles, assignedRoles, groups) {
|
|
|
1907
1907
|
const assigned = (assignedRoles ?? []).some((current) => current.codiceRuolo === role.codiceRuolo);
|
|
1908
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);
|
|
1909
1909
|
const missingMenus = roleMenus.filter((item) => !catalogMenus.has(item.codiceMenu));
|
|
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\
|
|
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>`;
|
|
1911
1911
|
}).join("")}</div><button>Salva ruoli</button></form>`;
|
|
1912
1912
|
}
|
|
1913
1913
|
function roleOverview(role, groups) {
|
|
@@ -1917,7 +1917,7 @@ function roleOverview(role, groups) {
|
|
|
1917
1917
|
const tree = groups.map((group) => ({ group, entries: group.menus.filter((menu) => assignments.has(menu.codiceMenu)) })).filter((node) => node.entries.length > 0);
|
|
1918
1918
|
const orphans = roleMenus.filter((item) => !knownMenus.has(item.codiceMenu));
|
|
1919
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("");
|
|
1920
|
-
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>` : "";
|
|
1921
1921
|
return `<article class="role-card">
|
|
1922
1922
|
<div class="role-card-head">
|
|
1923
1923
|
<div class="role-card-title">
|
|
@@ -2044,11 +2044,11 @@ function federatedIdentityFields(providers) {
|
|
|
2044
2044
|
<label>Nota ${helpDot("sso-note")}<input name="note"><span class="form-help">Nota interna, non inviata al provider.</span></label>`;
|
|
2045
2045
|
}
|
|
2046
2046
|
function federatedIdentitySection(identities, providers) {
|
|
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\
|
|
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>`;
|
|
2048
2048
|
}
|
|
2049
2049
|
function userDetailTabs(hasSso) {
|
|
2050
2050
|
const tabs = [
|
|
2051
|
-
...hasSso ? [{ id: "sso", label: "Identit\
|
|
2051
|
+
...hasSso ? [{ id: "sso", label: "Identit\xC3\xA0 SSO" }] : [],
|
|
2052
2052
|
{ id: "profile", label: "Profilo e accesso" },
|
|
2053
2053
|
{ id: "roles", label: "Ruoli" },
|
|
2054
2054
|
{ id: "grants", label: "Grant diretti" }
|
|
@@ -2105,7 +2105,7 @@ function pageNumbers(current, total) {
|
|
|
2105
2105
|
return result2;
|
|
2106
2106
|
}
|
|
2107
2107
|
function pagerMarkup(totalPages) {
|
|
2108
|
-
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>`;
|
|
2109
2109
|
if (totalPages <= 1) {
|
|
2110
2110
|
return `<nav class="pager" aria-label="Paginazione utenti">${context}</nav>`;
|
|
2111
2111
|
}
|
|
@@ -2280,35 +2280,14 @@ async function showUsers() {
|
|
|
2280
2280
|
function authenticationPolicyFields(user) {
|
|
2281
2281
|
return `<fieldset><legend>Verifica dell'accesso (opzionale)</legend>
|
|
2282
2282
|
<label class="check"><input name="flagDueFattori" type="checkbox" ${user.flagDueFattori ? "checked" : ""}> Richiedi un codice via email (2FA) ${helpDot("user-2fa")}</label>
|
|
2283
|
-
<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>
|
|
2284
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>
|
|
2285
2285
|
<p class="form-help">Accesso senza password (richiede il codice email).</p>
|
|
2286
2286
|
</fieldset>`;
|
|
2287
2287
|
}
|
|
2288
|
-
var APPLICATION_FLAGS = [
|
|
2289
|
-
["flagMop", "MOP"],
|
|
2290
|
-
["flagPiana", "Piana"],
|
|
2291
|
-
["flagAddetti", "Addetti"],
|
|
2292
|
-
["flagOspiti", "Ospiti"],
|
|
2293
|
-
["flagPianaRfid", "Piana RFID"],
|
|
2294
|
-
["flagConta", "Contabilit\xE0"],
|
|
2295
|
-
["flagCubi", "Cubi"],
|
|
2296
|
-
["flagCicliPass", "Cicli passivi"],
|
|
2297
|
-
["flagDipendenti", "Gestione dipendenti"],
|
|
2298
|
-
["flagInventari", "Gestione inventari"]
|
|
2299
|
-
];
|
|
2300
|
-
function applicationFlagFields(user) {
|
|
2301
|
-
const record = user;
|
|
2302
|
-
const checks = APPLICATION_FLAGS.map(([key, label]) => `<label class="check"><input name="${key}" type="checkbox" ${record[key] ? "checked" : ""}> ${label}</label>`).join("");
|
|
2303
|
-
return `<fieldset><legend>Abilitazioni applicative</legend>
|
|
2304
|
-
${checks}
|
|
2305
|
-
<label>Codice causale <input name="caumov" value="${escapeHtml(String(record.caumov ?? ""))}"></label>
|
|
2306
|
-
<label class="check"><input name="enableIa" type="checkbox" ${record.enableIa ? "checked" : ""}> Assistente IA (ENABLEIA)</label>
|
|
2307
|
-
</fieldset>`;
|
|
2308
|
-
}
|
|
2309
2288
|
function showLocalUserForm() {
|
|
2310
2289
|
render(`<button id="back">Indietro</button><h2>Nuovo utente locale</h2><p class="muted">Viene inviata l'e-mail per impostare la password.</p>
|
|
2311
|
-
<form id="local-user"><label>Email ${helpDot("user-email")}<input name="email" type="email" required><span class="form-help">Identificativo di accesso; ricever\
|
|
2290
|
+
<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>`);
|
|
2312
2291
|
byId("back").onclick = () => show("users");
|
|
2313
2292
|
const localUserForm = document.getElementById("local-user");
|
|
2314
2293
|
if (localUserForm) localUserForm.onsubmit = (event) => {
|
|
@@ -2325,7 +2304,7 @@ async function showSsoUserForm() {
|
|
|
2325
2304
|
if (!providers.some((provider) => provider.active)) {
|
|
2326
2305
|
throw new Error("Prima di creare un utente SSO, censisci e abilita almeno un provider SSO.");
|
|
2327
2306
|
}
|
|
2328
|
-
render(`<button id="back">Indietro</button><h2>Nuovo utente SSO</h2><p class="muted">Salva solo collegamenti gi\
|
|
2307
|
+
render(`<button id="back">Indietro</button><h2>Nuovo utente SSO</h2><p class="muted">Salva solo collegamenti gi\xC3\xA0 verificati dal backend.</p>
|
|
2329
2308
|
<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>`);
|
|
2330
2309
|
byId("back").onclick = () => show("ssoUsers");
|
|
2331
2310
|
const ssoUserForm = document.getElementById("sso-user");
|
|
@@ -2348,10 +2327,10 @@ async function showSsoUserForm() {
|
|
|
2348
2327
|
};
|
|
2349
2328
|
}
|
|
2350
2329
|
async function showSsoProviders() {
|
|
2351
|
-
if (!federatedAuthenticationAvailable) throw new Error("SSO non \
|
|
2330
|
+
if (!federatedAuthenticationAvailable) throw new Error("SSO non \xC3\xA8 abilitato in questa istanza Accessi.");
|
|
2352
2331
|
const providerList = result(await getFederatedProviders());
|
|
2353
2332
|
render(`<div class="toolbar"><button id="new-provider">Nuovo provider</button><button id="reload-providers" class="secondary">Aggiorna</button></div>
|
|
2354
|
-
<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\
|
|
2333
|
+
<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>
|
|
2355
2334
|
<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>`);
|
|
2356
2335
|
byId("new-provider").onclick = () => showProviderForm();
|
|
2357
2336
|
byId("reload-providers").onclick = () => handleAction(showSsoProviders);
|
|
@@ -2360,11 +2339,11 @@ async function showSsoProviders() {
|
|
|
2360
2339
|
});
|
|
2361
2340
|
}
|
|
2362
2341
|
async function showSsoUsers() {
|
|
2363
|
-
if (!federatedAuthenticationAvailable) throw new Error("SSO non \
|
|
2342
|
+
if (!federatedAuthenticationAvailable) throw new Error("SSO non \xC3\xA8 abilitato in questa istanza Accessi.");
|
|
2364
2343
|
const users = await loadUsers();
|
|
2365
2344
|
render(`<div class="toolbar"><button id="new-sso">Nuovo utente SSO</button><button id="reload-sso-users" class="secondary">Aggiorna</button></div>
|
|
2366
|
-
<h2>Utenti e identit\
|
|
2367
|
-
<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\
|
|
2345
|
+
<h2>Utenti e identit\xC3\xA0 SSO</h2><p class="muted">Gestisci i collegamenti provider/subject gi\xC3\xA0 verificati dal backend.</p>
|
|
2346
|
+
<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>`);
|
|
2368
2347
|
byId("new-sso").onclick = () => handleAction(showSsoUserForm);
|
|
2369
2348
|
byId("reload-sso-users").onclick = () => handleAction(showSsoUsers);
|
|
2370
2349
|
document.querySelectorAll("[data-sso-user]").forEach((button) => {
|
|
@@ -2443,7 +2422,7 @@ async function showUser(rawCode) {
|
|
|
2443
2422
|
const defaultUserTab = federatedAuthenticationAvailable ? "sso" : "profile";
|
|
2444
2423
|
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">
|
|
2445
2424
|
${identitySection}
|
|
2446
|
-
<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\
|
|
2425
|
+
<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)}<button>Salva</button></form>
|
|
2447
2426
|
${roleAssignmentEditor(allRoles, userGrants.ruoli, menuGroups)}
|
|
2448
2427
|
${directGrantEditor(menuGroups, userGrants.abilitazioni)}
|
|
2449
2428
|
</div>`);
|
|
@@ -2475,9 +2454,6 @@ async function showUser(rawCode) {
|
|
|
2475
2454
|
handleAction(async () => {
|
|
2476
2455
|
const values = formValues(eventForm(event));
|
|
2477
2456
|
const fields = new FormData(eventForm(event));
|
|
2478
|
-
const applicationFlags = Object.fromEntries(
|
|
2479
|
-
APPLICATION_FLAGS.map(([key]) => [key, fields.has(key)])
|
|
2480
|
-
);
|
|
2481
2457
|
await updateUtente(codiceUtente, {
|
|
2482
2458
|
codiceUtente,
|
|
2483
2459
|
email: values.email ?? "",
|
|
@@ -2485,9 +2461,6 @@ async function showUser(rawCode) {
|
|
|
2485
2461
|
cognome: values.cognome || void 0,
|
|
2486
2462
|
flagDueFattori: fields.has("flagDueFattori"),
|
|
2487
2463
|
passwordlessLoginEnabled: fields.has("passwordlessLoginEnabled"),
|
|
2488
|
-
caumov: values.caumov || void 0,
|
|
2489
|
-
enableIa: fields.has("enableIa"),
|
|
2490
|
-
...applicationFlags,
|
|
2491
2464
|
...federatedAuthenticationAvailable ? { passwordLoginEnabled: fields.has("passwordLoginEnabled") } : {}
|
|
2492
2465
|
});
|
|
2493
2466
|
if (codiceUtente === currentUser?.codiceUtente && (fields.has("flagDueFattori") !== Boolean(user.flagDueFattori) || fields.has("passwordlessLoginEnabled") !== Boolean(user.passwordlessLoginEnabled))) {
|
|
@@ -2543,7 +2516,7 @@ async function showUser(rawCode) {
|
|
|
2543
2516
|
});
|
|
2544
2517
|
document.querySelectorAll("[data-identity-delete]").forEach((button) => {
|
|
2545
2518
|
button.onclick = () => handleAction(async () => {
|
|
2546
|
-
if (!window.confirm("Eliminare definitivamente questo collegamento SSO? L\
|
|
2519
|
+
if (!window.confirm("Eliminare definitivamente questo collegamento SSO? L\xE2\u20AC\u2122utente Accessi non verr\xC3\xA0 eliminato.")) return;
|
|
2547
2520
|
await deleteFederatedIdentityPermanently(codiceUtente, button.dataset.identityDelete ?? "");
|
|
2548
2521
|
showNotice("Collegamento SSO eliminato definitivamente.");
|
|
2549
2522
|
await showUser(String(codiceUtente));
|
|
@@ -2679,7 +2652,7 @@ async function showMenuItems() {
|
|
|
2679
2652
|
async function showMenuTypes() {
|
|
2680
2653
|
const menuTypes = result(await getMenuTypes());
|
|
2681
2654
|
render(`<div class="toolbar"><button id="new-menu-type">Nuovo tipo menu</button><button id="reload-menu-types" class="secondary">Aggiorna</button></div>
|
|
2682
|
-
<h2>Tipi menu</h2><p class="form-help">Classificano i menu (es. amministrazione, operativit\
|
|
2655
|
+
<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>
|
|
2683
2656
|
${menuTypeTable(menuTypes)}`);
|
|
2684
2657
|
byId("new-menu-type").onclick = () => showMenuTypeForm();
|
|
2685
2658
|
byId("reload-menu-types").onclick = () => handleAction(showMenuTypes);
|
|
@@ -2897,7 +2870,7 @@ async function showServiceTokens(includeRevoked = false) {
|
|
|
2897
2870
|
});
|
|
2898
2871
|
}
|
|
2899
2872
|
function showServiceTokenForm() {
|
|
2900
|
-
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\
|
|
2873
|
+
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>`);
|
|
2901
2874
|
byId("back").onclick = () => void show("tokens");
|
|
2902
2875
|
const form = document.getElementById("token-form");
|
|
2903
2876
|
if (form) form.onsubmit = (event) => {
|