emilsoftware-utilities 2.0.0-dev.36 → 2.0.0-dev.37

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.
Files changed (41) hide show
  1. package/dist/accessi-module/AccessiModule.js +9 -4
  2. package/dist/accessi-module/AccessiModule.js.map +1 -1
  3. package/dist/accessi-module/Console/console.css +7 -0
  4. package/dist/accessi-module/Console/console.js +54 -3
  5. package/dist/accessi-module/Console/console.js.map +1 -1
  6. package/dist/accessi-module/Console/generated/accessiApi.d.ts +11 -1
  7. package/dist/accessi-module/Console/generated/accessiApi.js +9 -1
  8. package/dist/accessi-module/Console/generated/accessiApi.js.map +1 -1
  9. package/dist/accessi-module/Console/generated/model/getSchemaResponse.d.ts +14 -0
  10. package/dist/accessi-module/Console/generated/model/getSchemaResponse.js +3 -0
  11. package/dist/accessi-module/Console/generated/model/getSchemaResponse.js.map +1 -0
  12. package/dist/accessi-module/Console/generated/model/index.d.ts +3 -0
  13. package/dist/accessi-module/Console/generated/model/index.js +3 -0
  14. package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
  15. package/dist/accessi-module/Console/generated/model/schemaDdlResult.d.ts +20 -0
  16. package/dist/accessi-module/Console/generated/model/schemaDdlResult.js +3 -0
  17. package/dist/accessi-module/Console/generated/model/schemaDdlResult.js.map +1 -0
  18. package/dist/accessi-module/Console/generated/model/schemaDdlSection.d.ts +12 -0
  19. package/dist/accessi-module/Console/generated/model/schemaDdlSection.js +9 -0
  20. package/dist/accessi-module/Console/generated/model/schemaDdlSection.js.map +1 -0
  21. package/dist/accessi-module/Console/index.html +6 -0
  22. package/dist/accessi-module/Console/wiki.js +2 -0
  23. package/dist/accessi-module/Console/wiki.js.map +1 -1
  24. package/dist/accessi-module/Controllers/SchemaController.d.ts +9 -0
  25. package/dist/accessi-module/Controllers/SchemaController.js +79 -0
  26. package/dist/accessi-module/Controllers/SchemaController.js.map +1 -0
  27. package/dist/accessi-module/Dtos/SchemaDtos.d.ts +19 -0
  28. package/dist/accessi-module/Dtos/SchemaDtos.js +84 -0
  29. package/dist/accessi-module/Dtos/SchemaDtos.js.map +1 -0
  30. package/dist/accessi-module/Dtos/index.d.ts +1 -0
  31. package/dist/accessi-module/Dtos/index.js +1 -0
  32. package/dist/accessi-module/Dtos/index.js.map +1 -1
  33. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.d.ts +36 -0
  34. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.js +125 -0
  35. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.js.map +1 -0
  36. package/dist/accessi-module/index.d.ts +2 -0
  37. package/dist/accessi-module/index.js +3 -1
  38. package/dist/accessi-module/index.js.map +1 -1
  39. package/dist/emilsoftware-utilities-2.0.0-dev.37.tgz +0 -0
  40. package/package.json +1 -1
  41. package/dist/emilsoftware-utilities-2.0.0-dev.36.tgz +0 -0
@@ -31,6 +31,8 @@ const AccessiConsoleController_1 = require("./Controllers/AccessiConsoleControll
31
31
  const ServiceTokenController_1 = require("./Controllers/ServiceTokenController");
32
32
  const ServiceTokenService_1 = require("./Services/ServiceTokenService/ServiceTokenService");
33
33
  const serviceTokenGuard_1 = require("./security/serviceTokenGuard");
34
+ const SchemaController_1 = require("./Controllers/SchemaController");
35
+ const SchemaExportService_1 = require("./Services/SchemaExportService/SchemaExportService");
34
36
  const emailConfiguration_1 = require("./security/emailConfiguration");
35
37
  let AccessiModule = AccessiModule_1 = class AccessiModule {
36
38
  /**
@@ -62,7 +64,8 @@ let AccessiModule = AccessiModule_1 = class AccessiModule {
62
64
  AccessiDatabaseUpdater_1.AccessiDatabaseUpdater,
63
65
  FederatedAuthService_1.FederatedAuthService,
64
66
  ServiceTokenService_1.ServiceTokenService,
65
- serviceTokenGuard_1.ServiceTokenGuard
67
+ serviceTokenGuard_1.ServiceTokenGuard,
68
+ SchemaExportService_1.SchemaExportService
66
69
  ],
67
70
  exports: [
68
71
  'ACCESSI_OPTIONS',
@@ -76,7 +79,8 @@ let AccessiModule = AccessiModule_1 = class AccessiModule {
76
79
  authenticateGen_1.AuthenticateGenService,
77
80
  FederatedAuthService_1.FederatedAuthService,
78
81
  ServiceTokenService_1.ServiceTokenService,
79
- serviceTokenGuard_1.ServiceTokenGuard
82
+ serviceTokenGuard_1.ServiceTokenGuard,
83
+ SchemaExportService_1.SchemaExportService
80
84
  ],
81
85
  };
82
86
  }
@@ -95,9 +99,10 @@ exports.AccessiModule = AccessiModule = AccessiModule_1 = __decorate([
95
99
  FederatedAuthController_1.FederatedAuthController,
96
100
  AccessiConsoleController_1.AccessiConsoleController,
97
101
  ServiceTokenController_1.ServiceTokenController,
102
+ SchemaController_1.SchemaController,
98
103
  ],
99
- providers: [AuthService_1.AuthService, TwoFactorService_1.TwoFactorService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService, AccessiDatabaseUpdater_1.AccessiDatabaseUpdater, FederatedAuthService_1.FederatedAuthService, ServiceTokenService_1.ServiceTokenService, serviceTokenGuard_1.ServiceTokenGuard],
100
- exports: [AuthService_1.AuthService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService, FederatedAuthService_1.FederatedAuthService, ServiceTokenService_1.ServiceTokenService, serviceTokenGuard_1.ServiceTokenGuard],
104
+ providers: [AuthService_1.AuthService, TwoFactorService_1.TwoFactorService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService, AccessiDatabaseUpdater_1.AccessiDatabaseUpdater, FederatedAuthService_1.FederatedAuthService, ServiceTokenService_1.ServiceTokenService, serviceTokenGuard_1.ServiceTokenGuard, SchemaExportService_1.SchemaExportService],
105
+ exports: [AuthService_1.AuthService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService, FederatedAuthService_1.FederatedAuthService, ServiceTokenService_1.ServiceTokenService, serviceTokenGuard_1.ServiceTokenGuard, SchemaExportService_1.SchemaExportService],
101
106
  })
102
107
  ], AccessiModule);
103
108
  //# sourceMappingURL=AccessiModule.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccessiModule.js","sourceRoot":"","sources":["../../src/accessi-module/AccessiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,mFAAgF;AAQhF,2CAA+D;AAC/D,oEAAiE;AACjE,uEAAoE;AACpE,sFAAmF;AACnF,oEAAiE;AACjE,mEAAgE;AAChE,iEAA8D;AAC9D,6EAA0E;AAC1E,iEAA8D;AAC9D,0EAAuE;AACvE,qEAAkE;AAClE,iFAA8E;AAC9E,4FAAyF;AACzF,qDAAoD;AACpD,kEAAsE;AACtE,sFAAmF;AACnF,gFAA6E;AAC7E,sFAAmF;AACnF,qFAAkF;AAClF,iFAA8E;AAC9E,4FAAyF;AACzF,oEAAiE;AACjE,sEAAsE;AAqL/D,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,OAAuB;QACpC,yFAAyF;QACzF,IAAA,0CAAqB,EAAC,OAAO,CAAC,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,QAAQ,EAAE,OAAO;iBAClB;gBACD,yBAAW;gBACX,mCAAgB;gBAChB,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;gBACtB,+CAAsB;gBACtB,2CAAoB;gBACpB,yCAAmB;gBACnB,qCAAiB;aAClB;YACD,OAAO,EAAE;gBACP,iBAAiB;gBACjB,yBAAW;gBACX,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;gBACtB,2CAAoB;gBACpB,yCAAmB;gBACnB,qCAAiB;aAClB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAhDY,sCAAa;wBAAb,aAAa;IAhBzB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,WAAW,EAAE;YACX,iCAAe;YACf,+BAAc;YACd,2CAAoB;YACpB,+BAAc;YACd,mCAAgB;YAChB,+CAAsB;YACtB,iDAAuB;YACvB,mDAAwB;YACxB,+CAAsB;SACvB;QACD,SAAS,EAAE,CAAC,yBAAW,EAAE,mCAAgB,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,EAAE,+CAAsB,EAAE,2CAAoB,EAAE,yCAAmB,EAAE,qCAAiB,CAAC;QAC1P,OAAO,EAAE,CAAC,yBAAW,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,EAAE,2CAAoB,EAAE,yCAAmB,EAAE,qCAAiB,CAAC;KAC/M,CAAC;GACW,aAAa,CAgDzB","sourcesContent":["import { TwoFactorService } from './Services/TwoFactorService/TwoFactorService';\n/**\n * Modulo che gestisce le operazioni di accesso degli utenti, incluse le rotte, il controller e il modello.\n *\n * @module AccessiModule\n * @author mttdev382\n */\nimport { Options } from 'node-firebird';\nimport { DynamicModule, Global, Module } from '@nestjs/common';\nimport { AuthService } from './Services/AuthService/AuthService';\nimport { EmailService } from './Services/EmailService/EmailService';\nimport { PermissionService } from './Services/PermissionService/PermissionService';\nimport { UserService } from './Services/UserService/UserService';\nimport { EmailController } from './Controllers/EmailController';\nimport { AuthController } from './Controllers/AuthController';\nimport { PermissionController } from './Controllers/PermissionController';\nimport { UserController } from './Controllers/UserController';\nimport { FiltriService } from './Services/FiltriService/FiltriService';\nimport { FiltriController } from './Controllers/FiltriController';\nimport { ConfiguratorController } from './Controllers/ConfiguratorController';\nimport { ConfiguratorService } from './Services/ConfiguratorService/ConfiguratorService';\nimport { JwtSimpleGuard } from './jwt/jwt.strategy';\nimport { AuthenticateGenService } from './middleware/authenticateGen';\nimport { AccessiDatabaseUpdater } from './database-updates/AccessiDatabaseUpdater';\nimport { FederatedAuthService } from './federated-auth/FederatedAuthService';\nimport { FederatedAuthController } from './federated-auth/FederatedAuthController';\nimport { AccessiConsoleController } from './Controllers/AccessiConsoleController';\nimport { ServiceTokenController } from './Controllers/ServiceTokenController';\nimport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nimport { ServiceTokenGuard } from './security/serviceTokenGuard';\nimport { assertEmailConfigured } from './security/emailConfiguration';\n\n/** JWT emesso da Accessi dopo un login locale o SSO. Non riutilizzare il segreto del provider SSO. */\nexport interface JwtOptions {\n /** Segreto simmetrico per firmare e verificare i JWT Accessi; deve essere unico per ambiente. */\n secret: string;\n /** Durata compatibile con `jsonwebtoken`, per esempio `24h` o `3600s`. */\n expiresIn: string;\n}\n\n/** Parametri SMTP usati esclusivamente per impostazione e reset della password. */\nexport interface EmailOptions {\n host: string;\n port: number;\n secure: boolean;\n requireTLS : boolean;\n tls: {\n rejectUnauthorized: boolean,\n }\n from: string;\n auth: {\n user: string;\n pass: string;\n };\n}\n\n/** Configura campi applicativi aggiuntivi restituiti insieme al profilo Accessi. */\nexport interface ExtensionFieldsOptions {\n /** Connessione al database contenente la tabella estesa. */\n databaseOptions: Options;\n /** Chiave con cui i dati saranno esposti nella risposta. */\n objectKey: string;\n /** Tabella applicativa contenente i dati estesi. */\n tableName: string;\n /** Colonne consentite; non valorizzarle mai con input HTTP. */\n tableFields: string[];\n /** Colonna correlata a `UTENTI.CODUTE`. */\n tableJoinFieldName: string;\n}\n\n/** Limite per una singola categoria di endpoint pubblici. */\nexport interface PublicAuthRateLimitRuleOptions {\n windowMs: number;\n maxAttempts: number;\n}\n\n/** Protezione in-memory degli endpoint pubblici. In cluster aggiungere un limite anche al gateway. */\nexport interface PublicAuthRateLimitOptions {\n enabled?: boolean;\n login?: PublicAuthRateLimitRuleOptions;\n register?: PublicAuthRateLimitRuleOptions;\n passwordResetEmail?: PublicAuthRateLimitRuleOptions;\n passwordResetConfirm?: PublicAuthRateLimitRuleOptions;\n getUserByToken?: PublicAuthRateLimitRuleOptions;\n twoFactorVerify?: PublicAuthRateLimitRuleOptions;\n twoFactorResend?: PublicAuthRateLimitRuleOptions;\n}\n\n/** Controls the legacy public username/password registration endpoint. Disabled by default. */\nexport interface PublicRegistrationOptions {\n /** Enables POST /accessi/user/register. Applications that used it before must opt in explicitly. */\n enabled?: boolean;\n}\n\n/** Configurazione dei token di servizio (macchina-a-macchina, senza utente). */\nexport interface ServiceTokenOptions {\n /** Abilita gli endpoint amministrativi dei service token. Default `true`. */\n enabled?: boolean;\n /** Durata predefinita in giorni quando non e indicata una scadenza esplicita. Default: nessuna scadenza. */\n defaultTtlDays?: number;\n}\n\n/** Cosa fare quando uno script gia applicato presenta un checksum diverso (file modificato). */\nexport type CatalogScriptChecksumPolicy = 'error' | 'warn' | 'reapply';\n\n/**\n * Catalog migrations applicative (menu, ruoli, tipi, cataloghi). Gli script `.sql` vivono nel\n * backend ospitante (versionati in repository) e vengono eseguiti da Accessi dopo la\n * riconciliazione dello schema. Ogni script e tracciato nella tabella `ACCESSI_CATALOG_SCRIPT`,\n * quindi viene applicato una sola volta per database (idempotenza lato DB).\n */\nexport interface CatalogScriptsOptions {\n /** Abilita l'esecuzione automatica al bootstrap. Default `false`. */\n enabled?: boolean;\n /** Cartella contenente gli script `.sql` (assoluta o relativa alla working directory). */\n folder: string;\n /** Cosa fare se il checksum di uno script applicato e cambiato. Default `error`. */\n onChecksumMismatch?: CatalogScriptChecksumPolicy;\n /** Se `true` (default) un errore interrompe l'esecuzione e non avanza allo script successivo. */\n stopOnError?: boolean;\n /** Globi/estensioni inclusi. Default: tutti i `.sql`. */\n include?: string[];\n /** Numero massimo di script eseguiti in un singolo run (protezione operativa). Default: illimitato. */\n maxScriptsPerRun?: number;\n /**\n * Permette statement DDL/schema negli script. Default `false`: le catalog migrations possono\n * modificare solo righe. Sconsigliato: lo schema e di competenza di `db:update:accessi`.\n */\n allowDdl?: boolean;\n}\n\n/**\n * Enables Accessi's provider-agnostic federated identity capability.\n *\n * Accessi never validates Azure, Google, Apple, SAML, or other provider tokens.\n * The hosting backend must validate its own SSO flow and pass only a verified\n * `{ provider, subject }` identity to FederatedAuthService.\n */\nexport interface FederatedAuthenticationOptions {\n /** Attiva le API SSO generiche; con `false` il comportamento password storico rimane invariato. */\n enabled?: boolean;\n /** @deprecated Schema management is centralized in autoUpdateDatabase. This legacy flag no longer starts separate SSO migrations. */\n autoUpdateSchema?: boolean;\n /** Allows a backend to create a user from a verified external identity without a master user. Default false. */\n allowSelfRegistration?: boolean;\n}\n\n/**\n * Configurazione completa del modulo Accessi, fornita esclusivamente dal backend ospitante.\n * Segreti JWT, SMTP, database e le configurazioni tecniche dei provider SSO non devono mai raggiungere il browser.\n */\nexport interface AccessiOptions {\n /** Connessione Firebird alla base dati Accessi. */\n databaseOptions: Options;\n /**\n * Basepath del sito es: 'http://www.il-mio-sito.it/nome-progetto(se c'è)'\n */\n confirmationEmailUrl: string;\n /**\n * Percorso della pagina di reset personalizzata es. http://localhost:4200/#/admin/reset-password\n * N.B si sostituisce al confirmationMailURl\n */\n customResetPage?: string;\n /** URL di ritorno della pagina standard di reset dopo il completamento. */\n confirmationEmailReturnUrl: string;\n /** Prefisso applicativo facoltativo trasmesso alla pagina standard di reset. */\n confirmationEmailPrefix?: string;\n /** Chiave riservata alla compatibilita e alla migrazione delle password legacy cifrate. */\n encryptionKey: string;\n /** Abilita gli utenti fittizi `admin` e `demo` solo fuori produzione. */\n mockDemoUser: boolean;\n /** Attiva il controllo della scadenza password durante il login locale. */\n passwordExpiration?: boolean;\n /** Giorni di validita della password; quando assente Accessi usa 90 giorni. */\n passwordExpirationDays?: number;\n /** Esegue al bootstrap la conversione non distruttiva delle password legacy. Default `true`. */\n legacyPasswordMigrationOnStartup?: boolean;\n /** Riconcilia lo schema al bootstrap (default `true`). Con `false` verifica comunque la compatibilita in sola lettura e blocca avvii incompatibili. */\n autoUpdateDatabase?: boolean;\n /** Parametri JWT dei token emessi da Accessi. */\n jwtOptions: JwtOptions;\n /** Parametri SMTP per reset e attivazione password. */\n emailOptions: EmailOptions;\n publicAuthRateLimit?: PublicAuthRateLimitOptions;\n /** Public local registration is deliberately opt-in. Existing applications must set enabled: true to retain it. */\n publicRegistration?: PublicRegistrationOptions;\n /** Optional provider-agnostic SSO support. Provider-specific configuration remains in the hosting backend. */\n federatedAuthentication?: FederatedAuthenticationOptions;\n extensionFieldsOptions?: ExtensionFieldsOptions[];\n /** Token di servizio per chiamate tecniche macchina-a-macchina. Abilitati di default. */\n serviceTokens?: ServiceTokenOptions;\n /** Catalog migrations applicative eseguite dopo la riconciliazione dello schema. */\n catalogScripts?: CatalogScriptsOptions;\n}\n\n@Global()\n@Module({\n controllers: [\n EmailController,\n AuthController,\n PermissionController,\n UserController,\n FiltriController,\n ConfiguratorController,\n FederatedAuthController,\n AccessiConsoleController,\n ServiceTokenController,\n ],\n providers: [AuthService, TwoFactorService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, AccessiDatabaseUpdater, FederatedAuthService, ServiceTokenService, ServiceTokenGuard],\n exports: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, FederatedAuthService, ServiceTokenService, ServiceTokenGuard],\n})\nexport class AccessiModule {\n /**\n * Registra Accessi nel contenitore Nest del backend ospitante.\n *\n * Usare questo metodo una sola volta nella composizione dell'applicazione. Per un backend\n * Express esistente usare invece `initializeAccessiModule`, che crea e monta l'host Nest interno.\n * La configurazione viene registrata con il token DI `ACCESSI_OPTIONS` ed e condivisa dai servizi.\n */\n static forRoot(options: AccessiOptions): DynamicModule {\n // Il servizio email e obbligatorio: reset password, 2FA e creazione utente ne dipendono.\n assertEmailConfigured(options);\n return {\n module: AccessiModule,\n providers: [\n {\n provide: 'ACCESSI_OPTIONS',\n useValue: options,\n },\n AuthService,\n TwoFactorService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService,\n AccessiDatabaseUpdater,\n FederatedAuthService,\n ServiceTokenService,\n ServiceTokenGuard\n ],\n exports: [\n 'ACCESSI_OPTIONS',\n AuthService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService,\n FederatedAuthService,\n ServiceTokenService,\n ServiceTokenGuard\n ],\n };\n }\n}\n"]}
1
+ {"version":3,"file":"AccessiModule.js","sourceRoot":"","sources":["../../src/accessi-module/AccessiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,mFAAgF;AAQhF,2CAA+D;AAC/D,oEAAiE;AACjE,uEAAoE;AACpE,sFAAmF;AACnF,oEAAiE;AACjE,mEAAgE;AAChE,iEAA8D;AAC9D,6EAA0E;AAC1E,iEAA8D;AAC9D,0EAAuE;AACvE,qEAAkE;AAClE,iFAA8E;AAC9E,4FAAyF;AACzF,qDAAoD;AACpD,kEAAsE;AACtE,sFAAmF;AACnF,gFAA6E;AAC7E,sFAAmF;AACnF,qFAAkF;AAClF,iFAA8E;AAC9E,4FAAyF;AACzF,oEAAiE;AACjE,qEAAkE;AAClE,4FAAyF;AACzF,sEAAsE;AAsL/D,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,OAAuB;QACpC,yFAAyF;QACzF,IAAA,0CAAqB,EAAC,OAAO,CAAC,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,QAAQ,EAAE,OAAO;iBAClB;gBACD,yBAAW;gBACX,mCAAgB;gBAChB,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;gBACtB,+CAAsB;gBACtB,2CAAoB;gBACpB,yCAAmB;gBACnB,qCAAiB;gBACjB,yCAAmB;aACpB;YACD,OAAO,EAAE;gBACP,iBAAiB;gBACjB,yBAAW;gBACX,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;gBACtB,2CAAoB;gBACpB,yCAAmB;gBACnB,qCAAiB;gBACjB,yCAAmB;aACpB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAlDY,sCAAa;wBAAb,aAAa;IAjBzB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,WAAW,EAAE;YACX,iCAAe;YACf,+BAAc;YACd,2CAAoB;YACpB,+BAAc;YACd,mCAAgB;YAChB,+CAAsB;YACtB,iDAAuB;YACvB,mDAAwB;YACxB,+CAAsB;YACtB,mCAAgB;SACjB;QACD,SAAS,EAAE,CAAC,yBAAW,EAAE,mCAAgB,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,EAAE,+CAAsB,EAAE,2CAAoB,EAAE,yCAAmB,EAAE,qCAAiB,EAAE,yCAAmB,CAAC;QAC/Q,OAAO,EAAE,CAAC,yBAAW,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,EAAE,2CAAoB,EAAE,yCAAmB,EAAE,qCAAiB,EAAE,yCAAmB,CAAC;KACpO,CAAC;GACW,aAAa,CAkDzB","sourcesContent":["import { TwoFactorService } from './Services/TwoFactorService/TwoFactorService';\n/**\n * Modulo che gestisce le operazioni di accesso degli utenti, incluse le rotte, il controller e il modello.\n *\n * @module AccessiModule\n * @author mttdev382\n */\nimport { Options } from 'node-firebird';\nimport { DynamicModule, Global, Module } from '@nestjs/common';\nimport { AuthService } from './Services/AuthService/AuthService';\nimport { EmailService } from './Services/EmailService/EmailService';\nimport { PermissionService } from './Services/PermissionService/PermissionService';\nimport { UserService } from './Services/UserService/UserService';\nimport { EmailController } from './Controllers/EmailController';\nimport { AuthController } from './Controllers/AuthController';\nimport { PermissionController } from './Controllers/PermissionController';\nimport { UserController } from './Controllers/UserController';\nimport { FiltriService } from './Services/FiltriService/FiltriService';\nimport { FiltriController } from './Controllers/FiltriController';\nimport { ConfiguratorController } from './Controllers/ConfiguratorController';\nimport { ConfiguratorService } from './Services/ConfiguratorService/ConfiguratorService';\nimport { JwtSimpleGuard } from './jwt/jwt.strategy';\nimport { AuthenticateGenService } from './middleware/authenticateGen';\nimport { AccessiDatabaseUpdater } from './database-updates/AccessiDatabaseUpdater';\nimport { FederatedAuthService } from './federated-auth/FederatedAuthService';\nimport { FederatedAuthController } from './federated-auth/FederatedAuthController';\nimport { AccessiConsoleController } from './Controllers/AccessiConsoleController';\nimport { ServiceTokenController } from './Controllers/ServiceTokenController';\nimport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nimport { ServiceTokenGuard } from './security/serviceTokenGuard';\nimport { SchemaController } from './Controllers/SchemaController';\nimport { SchemaExportService } from './Services/SchemaExportService/SchemaExportService';\nimport { assertEmailConfigured } from './security/emailConfiguration';\n\n/** JWT emesso da Accessi dopo un login locale o SSO. Non riutilizzare il segreto del provider SSO. */\nexport interface JwtOptions {\n /** Segreto simmetrico per firmare e verificare i JWT Accessi; deve essere unico per ambiente. */\n secret: string;\n /** Durata compatibile con `jsonwebtoken`, per esempio `24h` o `3600s`. */\n expiresIn: string;\n}\n\n/** Parametri SMTP usati esclusivamente per impostazione e reset della password. */\nexport interface EmailOptions {\n host: string;\n port: number;\n secure: boolean;\n requireTLS : boolean;\n tls: {\n rejectUnauthorized: boolean,\n }\n from: string;\n auth: {\n user: string;\n pass: string;\n };\n}\n\n/** Configura campi applicativi aggiuntivi restituiti insieme al profilo Accessi. */\nexport interface ExtensionFieldsOptions {\n /** Connessione al database contenente la tabella estesa. */\n databaseOptions: Options;\n /** Chiave con cui i dati saranno esposti nella risposta. */\n objectKey: string;\n /** Tabella applicativa contenente i dati estesi. */\n tableName: string;\n /** Colonne consentite; non valorizzarle mai con input HTTP. */\n tableFields: string[];\n /** Colonna correlata a `UTENTI.CODUTE`. */\n tableJoinFieldName: string;\n}\n\n/** Limite per una singola categoria di endpoint pubblici. */\nexport interface PublicAuthRateLimitRuleOptions {\n windowMs: number;\n maxAttempts: number;\n}\n\n/** Protezione in-memory degli endpoint pubblici. In cluster aggiungere un limite anche al gateway. */\nexport interface PublicAuthRateLimitOptions {\n enabled?: boolean;\n login?: PublicAuthRateLimitRuleOptions;\n register?: PublicAuthRateLimitRuleOptions;\n passwordResetEmail?: PublicAuthRateLimitRuleOptions;\n passwordResetConfirm?: PublicAuthRateLimitRuleOptions;\n getUserByToken?: PublicAuthRateLimitRuleOptions;\n twoFactorVerify?: PublicAuthRateLimitRuleOptions;\n twoFactorResend?: PublicAuthRateLimitRuleOptions;\n}\n\n/** Controls the legacy public username/password registration endpoint. Disabled by default. */\nexport interface PublicRegistrationOptions {\n /** Enables POST /accessi/user/register. Applications that used it before must opt in explicitly. */\n enabled?: boolean;\n}\n\n/** Configurazione dei token di servizio (macchina-a-macchina, senza utente). */\nexport interface ServiceTokenOptions {\n /** Abilita gli endpoint amministrativi dei service token. Default `true`. */\n enabled?: boolean;\n /** Durata predefinita in giorni quando non e indicata una scadenza esplicita. Default: nessuna scadenza. */\n defaultTtlDays?: number;\n}\n\n/** Cosa fare quando uno script gia applicato presenta un checksum diverso (file modificato). */\nexport type CatalogScriptChecksumPolicy = 'error' | 'warn' | 'reapply';\n\n/**\n * Catalog migrations applicative (menu, ruoli, tipi, cataloghi). Gli script `.sql` vivono nel\n * backend ospitante (versionati in repository) e vengono eseguiti da Accessi dopo la\n * riconciliazione dello schema. Ogni script e tracciato nella tabella `ACCESSI_CATALOG_SCRIPT`,\n * quindi viene applicato una sola volta per database (idempotenza lato DB).\n */\nexport interface CatalogScriptsOptions {\n /** Abilita l'esecuzione automatica al bootstrap. Default `false`. */\n enabled?: boolean;\n /** Cartella contenente gli script `.sql` (assoluta o relativa alla working directory). */\n folder: string;\n /** Cosa fare se il checksum di uno script applicato e cambiato. Default `error`. */\n onChecksumMismatch?: CatalogScriptChecksumPolicy;\n /** Se `true` (default) un errore interrompe l'esecuzione e non avanza allo script successivo. */\n stopOnError?: boolean;\n /** Globi/estensioni inclusi. Default: tutti i `.sql`. */\n include?: string[];\n /** Numero massimo di script eseguiti in un singolo run (protezione operativa). Default: illimitato. */\n maxScriptsPerRun?: number;\n /**\n * Permette statement DDL/schema negli script. Default `false`: le catalog migrations possono\n * modificare solo righe. Sconsigliato: lo schema e di competenza di `db:update:accessi`.\n */\n allowDdl?: boolean;\n}\n\n/**\n * Enables Accessi's provider-agnostic federated identity capability.\n *\n * Accessi never validates Azure, Google, Apple, SAML, or other provider tokens.\n * The hosting backend must validate its own SSO flow and pass only a verified\n * `{ provider, subject }` identity to FederatedAuthService.\n */\nexport interface FederatedAuthenticationOptions {\n /** Attiva le API SSO generiche; con `false` il comportamento password storico rimane invariato. */\n enabled?: boolean;\n /** @deprecated Schema management is centralized in autoUpdateDatabase. This legacy flag no longer starts separate SSO migrations. */\n autoUpdateSchema?: boolean;\n /** Allows a backend to create a user from a verified external identity without a master user. Default false. */\n allowSelfRegistration?: boolean;\n}\n\n/**\n * Configurazione completa del modulo Accessi, fornita esclusivamente dal backend ospitante.\n * Segreti JWT, SMTP, database e le configurazioni tecniche dei provider SSO non devono mai raggiungere il browser.\n */\nexport interface AccessiOptions {\n /** Connessione Firebird alla base dati Accessi. */\n databaseOptions: Options;\n /**\n * Basepath del sito es: 'http://www.il-mio-sito.it/nome-progetto(se c'è)'\n */\n confirmationEmailUrl: string;\n /**\n * Percorso della pagina di reset personalizzata es. http://localhost:4200/#/admin/reset-password\n * N.B si sostituisce al confirmationMailURl\n */\n customResetPage?: string;\n /** URL di ritorno della pagina standard di reset dopo il completamento. */\n confirmationEmailReturnUrl: string;\n /** Prefisso applicativo facoltativo trasmesso alla pagina standard di reset. */\n confirmationEmailPrefix?: string;\n /** Chiave riservata alla compatibilita e alla migrazione delle password legacy cifrate. */\n encryptionKey: string;\n /** Abilita gli utenti fittizi `admin` e `demo` solo fuori produzione. */\n mockDemoUser: boolean;\n /** Attiva il controllo della scadenza password durante il login locale. */\n passwordExpiration?: boolean;\n /** Giorni di validita della password; quando assente Accessi usa 90 giorni. */\n passwordExpirationDays?: number;\n /** Esegue al bootstrap la conversione non distruttiva delle password legacy. Default `true`. */\n legacyPasswordMigrationOnStartup?: boolean;\n /** Riconcilia lo schema al bootstrap (default `true`). Con `false` verifica comunque la compatibilita in sola lettura e blocca avvii incompatibili. */\n autoUpdateDatabase?: boolean;\n /** Parametri JWT dei token emessi da Accessi. */\n jwtOptions: JwtOptions;\n /** Parametri SMTP per reset e attivazione password. */\n emailOptions: EmailOptions;\n publicAuthRateLimit?: PublicAuthRateLimitOptions;\n /** Public local registration is deliberately opt-in. Existing applications must set enabled: true to retain it. */\n publicRegistration?: PublicRegistrationOptions;\n /** Optional provider-agnostic SSO support. Provider-specific configuration remains in the hosting backend. */\n federatedAuthentication?: FederatedAuthenticationOptions;\n extensionFieldsOptions?: ExtensionFieldsOptions[];\n /** Token di servizio per chiamate tecniche macchina-a-macchina. Abilitati di default. */\n serviceTokens?: ServiceTokenOptions;\n /** Catalog migrations applicative eseguite dopo la riconciliazione dello schema. */\n catalogScripts?: CatalogScriptsOptions;\n}\n\n@Global()\n@Module({\n controllers: [\n EmailController,\n AuthController,\n PermissionController,\n UserController,\n FiltriController,\n ConfiguratorController,\n FederatedAuthController,\n AccessiConsoleController,\n ServiceTokenController,\n SchemaController,\n ],\n providers: [AuthService, TwoFactorService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, AccessiDatabaseUpdater, FederatedAuthService, ServiceTokenService, ServiceTokenGuard, SchemaExportService],\n exports: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, FederatedAuthService, ServiceTokenService, ServiceTokenGuard, SchemaExportService],\n})\nexport class AccessiModule {\n /**\n * Registra Accessi nel contenitore Nest del backend ospitante.\n *\n * Usare questo metodo una sola volta nella composizione dell'applicazione. Per un backend\n * Express esistente usare invece `initializeAccessiModule`, che crea e monta l'host Nest interno.\n * La configurazione viene registrata con il token DI `ACCESSI_OPTIONS` ed e condivisa dai servizi.\n */\n static forRoot(options: AccessiOptions): DynamicModule {\n // Il servizio email e obbligatorio: reset password, 2FA e creazione utente ne dipendono.\n assertEmailConfigured(options);\n return {\n module: AccessiModule,\n providers: [\n {\n provide: 'ACCESSI_OPTIONS',\n useValue: options,\n },\n AuthService,\n TwoFactorService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService,\n AccessiDatabaseUpdater,\n FederatedAuthService,\n ServiceTokenService,\n ServiceTokenGuard,\n SchemaExportService\n ],\n exports: [\n 'ACCESSI_OPTIONS',\n AuthService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService,\n FederatedAuthService,\n ServiceTokenService,\n ServiceTokenGuard,\n SchemaExportService\n ],\n };\n }\n}\n"]}
@@ -626,3 +626,10 @@ article h3 { margin-bottom: var(--s2); }
626
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
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
628
  .markdown-code code { padding: 0; background: transparent; color: var(--ink); white-space: pre; }
629
+
630
+ /* Sezione SQL / schema */
631
+ .entity-summary { display: flex; flex-wrap: wrap; gap: var(--s3); padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-sunken); }
632
+ .entity-summary strong { color: var(--brand-strong); }
633
+ .sql-section { display: grid; gap: var(--s2); min-width: 0; }
634
+ .sql-section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
635
+ .sql-section-head h3 { margin: 0; color: var(--ink); }
@@ -727,6 +727,18 @@ var rotateServiceToken = async (tokenId, options) => {
727
727
  }
728
728
  );
729
729
  };
730
+ var getGetSchemaUrl = () => {
731
+ return `/api/accessi/schema`;
732
+ };
733
+ var getSchema = async (options) => {
734
+ return accessiFetch(
735
+ getGetSchemaUrl(),
736
+ {
737
+ ...options,
738
+ method: "GET"
739
+ }
740
+ );
741
+ };
730
742
 
731
743
  // src/accessi-module/Console/wiki.ts
732
744
  var p = (text) => ({ kind: "p", text });
@@ -1358,7 +1370,8 @@ POST /api/accessi/auth/confirm-reset-password/{token}
1358
1370
  `Filtri: filtri utente e tipi filtro.`,
1359
1371
  `Token di servizio: creazione, rotazione, revoca.`,
1360
1372
  `SSO: provider e identit\xE0.`,
1361
- `Wiki e Changelog: documentazione e novit\xE0 della libreria.`
1373
+ `Wiki e Changelog: documentazione e novit\xE0 della libreria.`,
1374
+ `SQL: esporta il DDL delle entit\xE0 Accessi (tabelle, generatori, FK, indici, check, trigger) per replicare il database.`
1362
1375
  ]),
1363
1376
  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.`),
1364
1377
  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.`),
@@ -1418,6 +1431,7 @@ POST /api/accessi/auth/confirm-reset-password/{token}
1418
1431
  ["Filtri", "GET filtri/tipi, POST/PUT/DELETE filtri/tipi[/:tipFil], GET/POST filtri/utente"],
1419
1432
  ["SSO", "GET/POST federated-auth/providers, PATCH/DELETE providers/:provider, GET/POST users/:codiceUtente/identities, POST users, PATCH users/:codiceUtente/password-login"],
1420
1433
  ["Token", "POST/GET service-token, DELETE service-token/:tokenId, POST service-token/:tokenId/rotate"],
1434
+ ["Schema", "GET schema (DDL completo + entit\xE0 presenti, solo admin)"],
1421
1435
  ["Console", "GET console, console/:view, console/:view/:sub, console/assets/:file"]
1422
1436
  ]
1423
1437
  )
@@ -1875,7 +1889,8 @@ var routeSegment = {
1875
1889
  ssoUsers: "sso/utenti",
1876
1890
  tokens: "token-di-servizio",
1877
1891
  wiki: "wiki",
1878
- changelog: "changelog"
1892
+ changelog: "changelog",
1893
+ sql: "sql"
1879
1894
  };
1880
1895
  var routeView = Object.fromEntries(Object.entries(routeSegment).map(([view, segment]) => [segment, view]));
1881
1896
  var parentDefaultView = {
@@ -3124,6 +3139,41 @@ async function showChangelog() {
3124
3139
  ${renderMarkdown(changelog_default)}
3125
3140
  </article></div>`);
3126
3141
  }
3142
+ function downloadTextFile(fileName, content) {
3143
+ const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
3144
+ const url = URL.createObjectURL(blob);
3145
+ const anchor = document.createElement("a");
3146
+ anchor.href = url;
3147
+ anchor.download = fileName;
3148
+ document.body.appendChild(anchor);
3149
+ anchor.click();
3150
+ anchor.remove();
3151
+ URL.revokeObjectURL(url);
3152
+ }
3153
+ async function showSql() {
3154
+ const schema = result(await getSchema());
3155
+ const copy = (text, notice) => () => handleAction(async () => {
3156
+ await navigator.clipboard.writeText(text);
3157
+ showNotice(notice);
3158
+ });
3159
+ render(`<div class="toolbar"><button id="sql-copy-all">Copia tutto</button><button id="sql-download" class="secondary">Scarica .sql</button><button id="sql-reload" class="secondary">Aggiorna</button></div>
3160
+ <h2>SQL dello schema</h2>
3161
+ <p class="form-help">DDL generato dallo schema Accessi <strong>${escapeHtml(schema.version)}</strong>. Usalo per creare le entita su una nuova installazione (database vuoto).</p>
3162
+ <div class="entity-summary">
3163
+ <span><strong>${schema.presentTables.length}</strong> tabelle presenti</span>
3164
+ <span><strong>${schema.presentGenerators.length}</strong> generatori</span>
3165
+ <span><strong>${schema.extraTables.length}</strong> tabelle extra fuori schema Accessi</span>
3166
+ </div>
3167
+ ${schema.extraTables.length ? `<p class="form-help">Tabelle presenti non gestite da Accessi: <code>${schema.extraTables.map((name) => escapeHtml(name)).join(", ")}</code></p>` : ""}
3168
+ ${schema.sections.map((section) => `<section class="sql-section"><div class="sql-section-head"><h3>${escapeHtml(section.title)}</h3><button type="button" class="secondary" data-sql-copy="${escapeHtml(section.id)}">Copia sezione</button></div><pre class="markdown-code"><code>${escapeHtml(section.sql)}</code></pre></section>`).join("")}`);
3169
+ byId("sql-copy-all").onclick = copy(schema.script, "Script SQL completo copiato.");
3170
+ byId("sql-download").onclick = () => downloadTextFile(`accessi-schema-${schema.version}.sql`, schema.script);
3171
+ byId("sql-reload").onclick = () => handleAction(showSql);
3172
+ document.querySelectorAll("[data-sql-copy]").forEach((button) => {
3173
+ const section = schema.sections.find((entry) => entry.id === button.dataset.sqlCopy);
3174
+ if (section) button.onclick = copy(section.sql, `Sezione "${section.title}" copiata.`);
3175
+ });
3176
+ }
3127
3177
  async function show(view) {
3128
3178
  try {
3129
3179
  showNotice("");
@@ -3139,7 +3189,8 @@ async function show(view) {
3139
3189
  ssoUsers: showSsoUsers,
3140
3190
  tokens: showServiceTokens,
3141
3191
  wiki: showWiki,
3142
- changelog: showChangelog
3192
+ changelog: showChangelog,
3193
+ sql: showSql
3143
3194
  };
3144
3195
  setActiveNavigation(view);
3145
3196
  const renderView = views[view];