emilsoftware-utilities 2.0.0-dev.32 → 2.0.0-dev.34
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.css +10 -0
- package/dist/accessi-module/Console/console.js +102 -19
- package/dist/accessi-module/Console/console.js.map +1 -1
- package/dist/accessi-module/Console/generated/accessiApi.d.ts +2 -2
- package/dist/accessi-module/Console/generated/accessiApi.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 -2
- package/dist/accessi-module/Console/generated/model/publicRegisterRequest.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/registerRequest.d.ts +0 -2
- 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 +0 -4
- package/dist/accessi-module/Console/generated/model/userDto.js.map +1 -1
- package/dist/accessi-module/Console/index.html +6 -0
- package/dist/accessi-module/Console/wiki.js +7 -4
- package/dist/accessi-module/Console/wiki.js.map +1 -1
- package/dist/accessi-module/Controllers/ConfiguratorController.d.ts +1 -3
- package/dist/accessi-module/Controllers/ConfiguratorController.js +4 -17
- package/dist/accessi-module/Controllers/ConfiguratorController.js.map +1 -1
- package/dist/accessi-module/Controllers/FiltriController.js +4 -4
- package/dist/accessi-module/Controllers/FiltriController.js.map +1 -1
- package/dist/accessi-module/Controllers/PermissionController.js +14 -14
- package/dist/accessi-module/Controllers/PermissionController.js.map +1 -1
- package/dist/accessi-module/Controllers/ServiceTokenController.js +1 -1
- package/dist/accessi-module/Controllers/ServiceTokenController.js.map +1 -1
- package/dist/accessi-module/Controllers/UserController.js +8 -8
- package/dist/accessi-module/Controllers/UserController.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/RegisterRequest.d.ts +0 -1
- package/dist/accessi-module/Dtos/RegisterRequest.js +0 -9
- package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
- package/dist/accessi-module/Dtos/UserDto.d.ts +0 -2
- package/dist/accessi-module/Dtos/UserDto.js +0 -16
- 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 +0 -3
- package/dist/accessi-module/Services/UserService/UserService.js +2 -41
- package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
- package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +7 -0
- package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
- package/dist/accessi-module/database-updates/accessiSchema.d.ts +13 -2
- package/dist/accessi-module/database-updates/accessiSchema.js +15 -7
- package/dist/accessi-module/database-updates/accessiSchema.js.map +1 -1
- package/dist/accessi-module/federated-auth/FederatedAuthController.js +15 -15
- package/dist/accessi-module/federated-auth/FederatedAuthController.js.map +1 -1
- package/dist/accessi-module/security/accessControl.d.ts +11 -2
- package/dist/accessi-module/security/accessControl.js +28 -4
- package/dist/accessi-module/security/accessControl.js.map +1 -1
- package/dist/emilsoftware-utilities-2.0.0-dev.34.tgz +0 -0
- package/package.json +2 -2
- package/dist/emilsoftware-utilities-2.0.0-dev.32.tgz +0 -0
|
@@ -616,3 +616,13 @@ article h3 { margin-bottom: var(--s2); }
|
|
|
616
616
|
@media (prefers-reduced-motion: reduce) {
|
|
617
617
|
*, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
|
|
618
618
|
}
|
|
619
|
+
|
|
620
|
+
/* Changelog / markdown body */
|
|
621
|
+
.markdown-body h1 { margin: 0 0 var(--s3); font-size: 1.55rem; color: var(--ink); }
|
|
622
|
+
.markdown-body h2 { margin: var(--s5) 0 var(--s2); padding-top: var(--s3); border-top: 1px solid var(--line); font-size: 1.2rem; color: var(--ink); }
|
|
623
|
+
.markdown-body h3 { margin: var(--s4) 0 var(--s2); font-size: 1rem; color: var(--ink-2); }
|
|
624
|
+
.markdown-body h4 { margin: var(--s3) 0 var(--s1); font-size: .95rem; color: var(--ink-2); }
|
|
625
|
+
.markdown-body strong { color: var(--ink); }
|
|
626
|
+
.markdown-body code { padding: 1px 5px; border-radius: var(--r-sm); color: var(--brand-strong); background: var(--brand-soft); font-family: var(--font-mono); font-size: .92em; }
|
|
627
|
+
.markdown-code { margin: 0; padding: var(--s4); overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
|
|
628
|
+
.markdown-code code { padding: 0; background: transparent; color: var(--ink); white-space: pre; }
|
|
@@ -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", `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
|
|
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
|
},
|
|
@@ -1315,16 +1315,19 @@ POST /api/accessi/auth/confirm-reset-password/{token}
|
|
|
1315
1315
|
title: "Console amministrativa",
|
|
1316
1316
|
summary: "Accesso, sezioni e che cosa si pu\xF2 fare.",
|
|
1317
1317
|
blocks: [
|
|
1318
|
-
p(`La console \xE8 servita dal modulo su /api/accessi/console
|
|
1318
|
+
p(`La console \xE8 servita dal modulo su /api/accessi/console. Non ha stato proprio: ogni azione chiama le API protette con il JWT dell'utente connesso.`),
|
|
1319
1319
|
list([
|
|
1320
1320
|
`Utenti: elenco, creazione locale o SSO, profilo, ruoli, grant diretti, stato, 2FA.`,
|
|
1321
1321
|
`Ruoli e grant: CRUD dei ruoli con l'albero delle abilitazioni.`,
|
|
1322
1322
|
`Menu e gruppi: CRUD di gruppi, menu e tipi menu.`,
|
|
1323
1323
|
`Filtri: filtri utente e tipi filtro.`,
|
|
1324
1324
|
`Token di servizio: creazione, rotazione, revoca.`,
|
|
1325
|
-
`SSO: provider e identit\xE0
|
|
1325
|
+
`SSO: provider e identit\xE0.`,
|
|
1326
|
+
`Wiki e Changelog: documentazione e novit\xE0 della libreria.`
|
|
1326
1327
|
]),
|
|
1327
|
-
note("info", `
|
|
1328
|
+
note("info", `Superutente (FLGSUPER)`, `Riceve TUTTE le abilitazioni al livello massimo (30) dopo il login. In console vede solo la sezione Utenti e gestisce utenti, ruoli e grant.`),
|
|
1329
|
+
note("info", `Admin (FLGADMIN)`, `Accede a tutta la console (catalogo, token, SSO, utenti) ma NON conferisce abilitazioni: i menu restano quelli assegnati via ABILITAZIONI/RUOLI_MNU.`),
|
|
1330
|
+
note("info", `Accesso`, `Apri /api/accessi/console e accedi con un utente con FLGSUPER o FLGADMIN. Le sezioni sono raggiungibili anche tramite deep link (per esempio /api/accessi/console/menu-e-gruppi/menu).`)
|
|
1328
1331
|
]
|
|
1329
1332
|
},
|
|
1330
1333
|
// -------------------------------------------------------------------------
|
|
@@ -1463,6 +1466,9 @@ function buildAiDigest() {
|
|
|
1463
1466
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1464
1467
|
}
|
|
1465
1468
|
|
|
1469
|
+
// src/accessi-module/Console/changelog.md
|
|
1470
|
+
var changelog_default = "# Changelog Accessi\n\nNovit\xE0 e modifiche rilevanti della libreria `emilsoftware-utilities` (modulo Accessi).\n\n## 2.0.0-dev.33\n\n### Cambiamenti\n- Rimosse le logiche applicative residue dallo schema Accessi:\n - `MENU_GRP.NOMECAMPO`\n - `UTENTI.ENABLEIA`\n - `UTENTI_CONFIG.PAGDEF`\n - `UTENTI.CELLUTE`\n- Telefono canonico: `UTENTI_CONFIG.CELLULARE` (allargato a `VARCHAR(30)`).\n- Migrazione automatica: copia `UTENTI.CELLUTE` \u2192 `UTENTI_CONFIG.CELLULARE`, poi `DROP` delle colonne obsolete.\n- Ruoli chiariti:\n - `FLGSUPER`: superutente, riceve **tutte** le abilitazioni al livello massimo (30) dopo il login; in console vede **solo** la sezione **Utenti**.\n - `FLGADMIN`: accede a **tutta** la console (catalogo, token, SSO, utenti) ma **non** influisce sulle abilitazioni.\n- Aggiunta la sezione **Changelog** in console (sotto la Wiki).\n\n### Note\n- `FILTRI` e `FILTRI_TIPO` restano invariati (piano di migrazione futuro).\n- I backend che usavano i campi rimossi devono gestirli in tabelle proprie.\n\n## 2.0.0-dev.32\n\n### Cambiamenti\n- Rimosso il supporto ai flag applicativi in `UTENTI_CONFIG`: `FLGMOP`, `FLGPIANA`, `FLGADDETTI`, `FLGOSPITI`, `FLGPIANARFID`, `FLGCONTA`, `FLGCUBI`, `FLGCICLPASS`, `FLGDIPENDENTI`, `FLGINVENTARI`, `CAUMOV`, `NUMMAC`, `RAGSOCCLI`.\n- Rinominata la colonna `FLGADMINCONFIG` in `FLGADMIN` (con copia dei valori e `DROP`).\n\n## 2.0.0-dev.31\n\n### Aggiunte\n- Esposizione dei servizi Accessi all'host Express (`getAccessiModuleServices`) per delegare login, SSO e token senza reimplementarli.\n\n### Correzioni\n- `UserService.getUsers`: filtri estesi (`codiceUtente[]`, `numRep[]`, `codDipendente`, `cellulare`, `tipFil`, `flagSuper`).\n\n## 2.0.0-dev.24\n\n### Cambiamenti (breaking)\n- Chiavi JWT derivate per scopo (`access`, `reset`, `2fa`) e claim `typ` obbligatorio: gli access token precedenti non sono pi\xF9 validi.\n- Endpoint Allegati protetti di default.\n- Pool di connessioni attivo di default (`poolSize` 5).\n\n### Aggiunte\n- Service token macchina-a-macchina (gestione, guard, console).\n- CRUD completo dei cataloghi dalla console Accessi.\n- Supporto Firebird 2.5 nel migrator e nei test di integrazione.\n";
|
|
1471
|
+
|
|
1466
1472
|
// src/accessi-module/Console/help.ts
|
|
1467
1473
|
var p2 = (text) => ({ kind: "p", text });
|
|
1468
1474
|
var list2 = (items) => ({ kind: "list", items });
|
|
@@ -1833,7 +1839,8 @@ var routeSegment = {
|
|
|
1833
1839
|
ssoProviders: "sso/provider",
|
|
1834
1840
|
ssoUsers: "sso/utenti",
|
|
1835
1841
|
tokens: "token-di-servizio",
|
|
1836
|
-
wiki: "wiki"
|
|
1842
|
+
wiki: "wiki",
|
|
1843
|
+
changelog: "changelog"
|
|
1837
1844
|
};
|
|
1838
1845
|
var routeView = Object.fromEntries(Object.entries(routeSegment).map(([view, segment]) => [segment, view]));
|
|
1839
1846
|
var parentDefaultView = {
|
|
@@ -2022,6 +2029,10 @@ function viewFromLocation() {
|
|
|
2022
2029
|
return routeView[decoded] ?? parentDefaultView[decoded] ?? "users";
|
|
2023
2030
|
}
|
|
2024
2031
|
async function navigate(view, replace = false) {
|
|
2032
|
+
if (!isViewAllowed(view)) {
|
|
2033
|
+
view = "users";
|
|
2034
|
+
replace = true;
|
|
2035
|
+
}
|
|
2025
2036
|
const destination = routePath(view);
|
|
2026
2037
|
if (window.location.pathname !== destination) {
|
|
2027
2038
|
window.history[replace ? "replaceState" : "pushState"]({ view }, "", destination);
|
|
@@ -2029,8 +2040,26 @@ async function navigate(view, replace = false) {
|
|
|
2029
2040
|
if (view === "users") usersPage = 0;
|
|
2030
2041
|
await show(view);
|
|
2031
2042
|
}
|
|
2032
|
-
function
|
|
2033
|
-
if (!currentUser?.flagSuper
|
|
2043
|
+
function requireConsoleAccess() {
|
|
2044
|
+
if (!currentUser?.flagSuper && !currentUser?.flagAdmin) {
|
|
2045
|
+
throw new Error("La console richiede un superutente o un admin Accessi.");
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
function isViewAllowed(view) {
|
|
2049
|
+
if (!currentUser) return false;
|
|
2050
|
+
if (currentUser.flagAdmin) return true;
|
|
2051
|
+
return view === "users";
|
|
2052
|
+
}
|
|
2053
|
+
function applyRoleNavigation() {
|
|
2054
|
+
document.querySelectorAll("#nav [data-view]").forEach((link) => {
|
|
2055
|
+
const view = link.dataset.view;
|
|
2056
|
+
const item = link.closest("li") ?? link;
|
|
2057
|
+
item.hidden = !isViewAllowed(view);
|
|
2058
|
+
});
|
|
2059
|
+
document.querySelectorAll("#nav details[data-nav-group]").forEach((branch) => {
|
|
2060
|
+
const hasVisible = Array.from(branch.querySelectorAll("[data-view]")).some((link) => !link.closest("li").hidden);
|
|
2061
|
+
branch.hidden = !hasVisible;
|
|
2062
|
+
});
|
|
2034
2063
|
}
|
|
2035
2064
|
function formValues(form) {
|
|
2036
2065
|
return Object.fromEntries(new FormData(form).entries());
|
|
@@ -2234,9 +2263,11 @@ async function bootstrap() {
|
|
|
2234
2263
|
if (!token) throw new Error("Inserisci le credenziali amministrative.");
|
|
2235
2264
|
const payload = result(await getUserByToken({ token }));
|
|
2236
2265
|
currentUser = payload.userData;
|
|
2237
|
-
|
|
2266
|
+
requireConsoleAccess();
|
|
2267
|
+
applyRoleNavigation();
|
|
2238
2268
|
await detectFederatedAuthentication();
|
|
2239
|
-
|
|
2269
|
+
const roleLabel = currentUser.flagSuper && currentUser.flagAdmin ? "super + admin" : currentUser.flagAdmin ? "admin" : "superutente";
|
|
2270
|
+
byId("who").textContent = `${currentUser.email} - ${roleLabel}`;
|
|
2240
2271
|
byId("sso-navigation").hidden = !federatedAuthenticationAvailable;
|
|
2241
2272
|
finishBoot("console");
|
|
2242
2273
|
await navigate(viewFromLocation(), window.location.pathname === consoleBasePath);
|
|
@@ -2285,12 +2316,6 @@ function authenticationPolicyFields(user) {
|
|
|
2285
2316
|
<p class="form-help">Accesso senza password (richiede il codice email).</p>
|
|
2286
2317
|
</fieldset>`;
|
|
2287
2318
|
}
|
|
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
|
-
}
|
|
2294
2319
|
function showLocalUserForm() {
|
|
2295
2320
|
render(`<button id="back">Indietro</button><h2>Nuovo utente locale</h2><p class="muted">Viene inviata l'e-mail per impostare la password.</p>
|
|
2296
2321
|
<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>`);
|
|
@@ -2428,7 +2453,7 @@ async function showUser(rawCode) {
|
|
|
2428
2453
|
const defaultUserTab = federatedAuthenticationAvailable ? "sso" : "profile";
|
|
2429
2454
|
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">
|
|
2430
2455
|
${identitySection}
|
|
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)}
|
|
2456
|
+
<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>
|
|
2432
2457
|
${roleAssignmentEditor(allRoles, userGrants.ruoli, menuGroups)}
|
|
2433
2458
|
${directGrantEditor(menuGroups, userGrants.abilitazioni)}
|
|
2434
2459
|
</div>`);
|
|
@@ -2467,7 +2492,6 @@ async function showUser(rawCode) {
|
|
|
2467
2492
|
cognome: values.cognome || void 0,
|
|
2468
2493
|
flagDueFattori: fields.has("flagDueFattori"),
|
|
2469
2494
|
passwordlessLoginEnabled: fields.has("passwordlessLoginEnabled"),
|
|
2470
|
-
enableIa: fields.has("enableIa"),
|
|
2471
2495
|
...federatedAuthenticationAvailable ? { passwordLoginEnabled: fields.has("passwordLoginEnabled") } : {}
|
|
2472
2496
|
});
|
|
2473
2497
|
if (codiceUtente === currentUser?.codiceUtente && (fields.has("flagDueFattori") !== Boolean(user.flagDueFattori) || fields.has("passwordlessLoginEnabled") !== Boolean(user.passwordlessLoginEnabled))) {
|
|
@@ -3007,6 +3031,64 @@ async function showWiki(sectionId) {
|
|
|
3007
3031
|
showNotice("Documentazione per AI copiata negli appunti.");
|
|
3008
3032
|
});
|
|
3009
3033
|
}
|
|
3034
|
+
function inlineMarkdown(text) {
|
|
3035
|
+
return escapeHtml(text).replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>").replace(/`([^`]+)`/g, "<code>$1</code>");
|
|
3036
|
+
}
|
|
3037
|
+
function renderMarkdown(markdown) {
|
|
3038
|
+
const lines = markdown.replace(/\r\n/g, "\n").split("\n");
|
|
3039
|
+
const html = [];
|
|
3040
|
+
let inList = false;
|
|
3041
|
+
let inCode = false;
|
|
3042
|
+
const closeList = () => {
|
|
3043
|
+
if (inList) {
|
|
3044
|
+
html.push("</ul>");
|
|
3045
|
+
inList = false;
|
|
3046
|
+
}
|
|
3047
|
+
};
|
|
3048
|
+
for (const line of lines) {
|
|
3049
|
+
if (line.startsWith("```")) {
|
|
3050
|
+
closeList();
|
|
3051
|
+
html.push(inCode ? "</code></pre>" : '<pre class="markdown-code"><code>');
|
|
3052
|
+
inCode = !inCode;
|
|
3053
|
+
continue;
|
|
3054
|
+
}
|
|
3055
|
+
if (inCode) {
|
|
3056
|
+
html.push(escapeHtml(line));
|
|
3057
|
+
continue;
|
|
3058
|
+
}
|
|
3059
|
+
const heading = /^(#{1,4})\s+(.*)$/.exec(line);
|
|
3060
|
+
if (heading) {
|
|
3061
|
+
closeList();
|
|
3062
|
+
const level = (heading[1] ?? "").length;
|
|
3063
|
+
html.push(`<h${level}>${inlineMarkdown(heading[2] ?? "")}</h${level}>`);
|
|
3064
|
+
continue;
|
|
3065
|
+
}
|
|
3066
|
+
const bullet = /^\s*[-*]\s+(.*)$/.exec(line);
|
|
3067
|
+
if (bullet) {
|
|
3068
|
+
if (!inList) {
|
|
3069
|
+
html.push("<ul>");
|
|
3070
|
+
inList = true;
|
|
3071
|
+
}
|
|
3072
|
+
html.push(`<li>${inlineMarkdown(bullet[1] ?? "")}</li>`);
|
|
3073
|
+
continue;
|
|
3074
|
+
}
|
|
3075
|
+
if (line.trim() === "") {
|
|
3076
|
+
closeList();
|
|
3077
|
+
continue;
|
|
3078
|
+
}
|
|
3079
|
+
closeList();
|
|
3080
|
+
html.push(`<p>${inlineMarkdown(line)}</p>`);
|
|
3081
|
+
}
|
|
3082
|
+
if (inCode) html.push("</code></pre>");
|
|
3083
|
+
closeList();
|
|
3084
|
+
return html.join("");
|
|
3085
|
+
}
|
|
3086
|
+
async function showChangelog() {
|
|
3087
|
+
render(`<div class="wiki"><article class="wiki-content markdown-body">
|
|
3088
|
+
<header class="wiki-section-head"><h2>Changelog</h2><p>Novita e modifiche rilevanti del modulo Accessi.</p></header>
|
|
3089
|
+
${renderMarkdown(changelog_default)}
|
|
3090
|
+
</article></div>`);
|
|
3091
|
+
}
|
|
3010
3092
|
async function show(view) {
|
|
3011
3093
|
try {
|
|
3012
3094
|
showNotice("");
|
|
@@ -3021,7 +3103,8 @@ async function show(view) {
|
|
|
3021
3103
|
ssoProviders: showSsoProviders,
|
|
3022
3104
|
ssoUsers: showSsoUsers,
|
|
3023
3105
|
tokens: showServiceTokens,
|
|
3024
|
-
wiki: showWiki
|
|
3106
|
+
wiki: showWiki,
|
|
3107
|
+
changelog: showChangelog
|
|
3025
3108
|
};
|
|
3026
3109
|
setActiveNavigation(view);
|
|
3027
3110
|
const renderView = views[view];
|