emilsoftware-utilities 2.0.0-dev.66 → 2.0.0-dev.67

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 (134) hide show
  1. package/dist/EmilsoftwareModule.d.ts +11 -3
  2. package/dist/EmilsoftwareModule.js +1 -1
  3. package/dist/EmilsoftwareModule.js.map +1 -1
  4. package/dist/accessi/client/index.d.ts +26 -0
  5. package/dist/accessi/client/index.js +49 -0
  6. package/dist/accessi/client/index.js.map +1 -0
  7. package/dist/accessi/console/index.d.ts +15 -0
  8. package/dist/accessi/console/index.js +25 -0
  9. package/dist/accessi/console/index.js.map +1 -0
  10. package/dist/accessi/contracts/dtos.d.ts +8 -0
  11. package/dist/accessi/contracts/dtos.js +25 -0
  12. package/dist/accessi/contracts/dtos.js.map +1 -0
  13. package/dist/accessi/contracts/index.d.ts +25 -0
  14. package/dist/accessi/contracts/index.js +28 -0
  15. package/dist/accessi/contracts/index.js.map +1 -0
  16. package/dist/accessi/openapi/index.d.ts +2 -0
  17. package/dist/accessi/openapi/index.js +19 -0
  18. package/dist/accessi/openapi/index.js.map +1 -0
  19. package/dist/accessi/resource-server/core.d.ts +6 -0
  20. package/dist/accessi/resource-server/core.js +23 -0
  21. package/dist/accessi/resource-server/core.js.map +1 -0
  22. package/dist/accessi/resource-server/errors.d.ts +10 -0
  23. package/dist/accessi/resource-server/errors.js +19 -0
  24. package/dist/accessi/resource-server/errors.js.map +1 -0
  25. package/dist/accessi/resource-server/express.d.ts +17 -0
  26. package/dist/accessi/resource-server/express.js +66 -0
  27. package/dist/accessi/resource-server/express.js.map +1 -0
  28. package/dist/accessi/resource-server/index.d.ts +3 -0
  29. package/dist/accessi/resource-server/index.js +20 -0
  30. package/dist/accessi/resource-server/index.js.map +1 -0
  31. package/dist/accessi/resource-server/introspection.d.ts +16 -0
  32. package/dist/accessi/resource-server/introspection.js +115 -0
  33. package/dist/accessi/resource-server/introspection.js.map +1 -0
  34. package/dist/accessi/resource-server/keys.d.ts +11 -0
  35. package/dist/accessi/resource-server/keys.js +22 -0
  36. package/dist/accessi/resource-server/keys.js.map +1 -0
  37. package/dist/accessi/resource-server/nest.d.ts +9 -0
  38. package/dist/accessi/resource-server/nest.js +62 -0
  39. package/dist/accessi/resource-server/nest.js.map +1 -0
  40. package/dist/accessi/resource-server/runtime.d.ts +27 -0
  41. package/dist/accessi/resource-server/runtime.js +128 -0
  42. package/dist/accessi/resource-server/runtime.js.map +1 -0
  43. package/dist/accessi/resource-server/token.d.ts +23 -0
  44. package/dist/accessi/resource-server/token.js +230 -0
  45. package/dist/accessi/resource-server/token.js.map +1 -0
  46. package/dist/accessi/resource-server/types.d.ts +78 -0
  47. package/dist/accessi/resource-server/types.js +3 -0
  48. package/dist/accessi/resource-server/types.js.map +1 -0
  49. package/dist/accessi/server/index.d.ts +10 -0
  50. package/dist/accessi/server/index.js +29 -0
  51. package/dist/accessi/server/index.js.map +1 -0
  52. package/dist/accessi/ui/index.d.ts +13 -0
  53. package/dist/accessi/ui/index.js +19 -0
  54. package/dist/accessi/ui/index.js.map +1 -0
  55. package/dist/accessi-module/AccessiModule.d.ts +25 -1
  56. package/dist/accessi-module/AccessiModule.js +2 -0
  57. package/dist/accessi-module/AccessiModule.js.map +1 -1
  58. package/dist/accessi-module/Console/accessiFetch.d.ts +4 -0
  59. package/dist/accessi-module/Console/accessiFetch.js +18 -4
  60. package/dist/accessi-module/Console/accessiFetch.js.map +1 -1
  61. package/dist/accessi-module/Console/console.js +114 -9
  62. package/dist/accessi-module/Console/console.js.map +1 -1
  63. package/dist/accessi-module/Console/generated/{accessiApi.d.ts → emilsoftware-utilities.d.ts} +11 -1
  64. package/dist/accessi-module/Console/generated/{accessiApi.js → emilsoftware-utilities.js} +10 -2
  65. package/dist/accessi-module/Console/generated/emilsoftware-utilities.js.map +1 -0
  66. package/dist/accessi-module/Console/generated/model/accessiIntrospectionResultDto.d.ts +16 -0
  67. package/dist/accessi-module/Console/generated/model/accessiIntrospectionResultDto.js +3 -0
  68. package/dist/accessi-module/Console/generated/model/accessiIntrospectionResultDto.js.map +1 -0
  69. package/dist/accessi-module/Console/generated/model/index.d.ts +3 -0
  70. package/dist/accessi-module/Console/generated/model/index.js +3 -0
  71. package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
  72. package/dist/accessi-module/Console/generated/model/introspectAccessiTokenRequest.d.ts +10 -0
  73. package/dist/accessi-module/Console/generated/model/introspectAccessiTokenRequest.js +9 -0
  74. package/dist/accessi-module/Console/generated/model/introspectAccessiTokenRequest.js.map +1 -0
  75. package/dist/accessi-module/Console/generated/model/introspectAccessiTokenResponse.d.ts +14 -0
  76. package/dist/accessi-module/Console/generated/model/introspectAccessiTokenResponse.js +3 -0
  77. package/dist/accessi-module/Console/generated/model/introspectAccessiTokenResponse.js.map +1 -0
  78. package/dist/accessi-module/Console/wiki.js +98 -3
  79. package/dist/accessi-module/Console/wiki.js.map +1 -1
  80. package/dist/accessi-module/Controllers/AccessiIntrospectionController.d.ts +17 -0
  81. package/dist/accessi-module/Controllers/AccessiIntrospectionController.js +93 -0
  82. package/dist/accessi-module/Controllers/AccessiIntrospectionController.js.map +1 -0
  83. package/dist/accessi-module/Dtos/IntrospectionDtos.d.ts +16 -0
  84. package/dist/accessi-module/Dtos/IntrospectionDtos.js +59 -0
  85. package/dist/accessi-module/Dtos/IntrospectionDtos.js.map +1 -0
  86. package/dist/accessi-module/Dtos/index.d.ts +1 -0
  87. package/dist/accessi-module/Dtos/index.js +1 -0
  88. package/dist/accessi-module/Dtos/index.js.map +1 -1
  89. package/dist/accessi-module/Services/AuthService/AuthService.d.ts +13 -0
  90. package/dist/accessi-module/Services/AuthService/AuthService.js +42 -10
  91. package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
  92. package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js +11 -4
  93. package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js.map +1 -1
  94. package/dist/accessi-module/database-updates/menuScopeSeed.d.ts +2 -2
  95. package/dist/accessi-module/database-updates/menuScopeSeed.js +101 -53
  96. package/dist/accessi-module/database-updates/menuScopeSeed.js.map +1 -1
  97. package/dist/accessi-module/database-updates/menuScopeSeeder.js +1 -1
  98. package/dist/accessi-module/database-updates/menuScopeSeeder.js.map +1 -1
  99. package/dist/accessi-module/index.d.ts +16 -3
  100. package/dist/accessi-module/index.js +15 -19
  101. package/dist/accessi-module/index.js.map +1 -1
  102. package/dist/accessi-module/jwt/jwt.strategy.js +5 -5
  103. package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
  104. package/dist/accessi-module/middleware/authenticateGen.js +5 -5
  105. package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
  106. package/dist/accessi-module/security/jwtTokenOptions.d.ts +15 -0
  107. package/dist/accessi-module/security/jwtTokenOptions.js +44 -0
  108. package/dist/accessi-module/security/jwtTokenOptions.js.map +1 -0
  109. package/dist/accessi-module/startupLog.d.ts +3 -2
  110. package/dist/accessi-module/startupLog.js +8 -4
  111. package/dist/accessi-module/startupLog.js.map +1 -1
  112. package/dist/allegati-module/index.js +2 -2
  113. package/dist/allegati-module/index.js.map +1 -1
  114. package/dist/angular-components/aree-disponibili/demo.html +4 -4
  115. package/dist/emilsoftware-utilities-2.0.0-dev.67.tgz +0 -0
  116. package/dist/index.d.ts +2 -1
  117. package/dist/index.js +2 -1
  118. package/dist/index.js.map +1 -1
  119. package/dist/initEmilsoftwareModule.d.ts +11 -1
  120. package/dist/initEmilsoftwareModule.js +11 -23
  121. package/dist/initEmilsoftwareModule.js.map +1 -1
  122. package/dist/openapi/OpenApiConfig.d.ts +68 -0
  123. package/dist/openapi/OpenApiConfig.js +157 -0
  124. package/dist/openapi/OpenApiConfig.js.map +1 -0
  125. package/dist/openapi/OpenApiMerge.d.ts +15 -0
  126. package/dist/openapi/OpenApiMerge.js +119 -0
  127. package/dist/openapi/OpenApiMerge.js.map +1 -0
  128. package/integration-prompt.md +481 -0
  129. package/package.json +88 -5
  130. package/dist/accessi-module/Console/generated/accessiApi.js.map +0 -1
  131. package/dist/emilsoftware-utilities-2.0.0-dev.66.tgz +0 -0
  132. package/dist/swagger/SwaggerConfig.d.ts +0 -8
  133. package/dist/swagger/SwaggerConfig.js +0 -41
  134. package/dist/swagger/SwaggerConfig.js.map +0 -1
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.createAccessiTokenVerifier = createAccessiTokenVerifier;
46
+ exports.verifyAccessiAccessToken = verifyAccessiAccessToken;
47
+ const crypto_1 = require("crypto");
48
+ const jwt = __importStar(require("jsonwebtoken"));
49
+ const contracts_1 = require("../contracts");
50
+ const errors_1 = require("./errors");
51
+ const keys_1 = require("./keys");
52
+ function isRecord(value) {
53
+ return typeof value === "object" && value !== null;
54
+ }
55
+ function extractUser(payload) {
56
+ const userData = isRecord(payload.userData) ? payload.userData : undefined;
57
+ const utente = isRecord(payload.utente)
58
+ ? payload.utente
59
+ : isRecord(userData === null || userData === void 0 ? void 0 : userData.utente)
60
+ ? userData.utente
61
+ : undefined;
62
+ return utente !== null && utente !== void 0 ? utente : {};
63
+ }
64
+ function defaultAlgorithms(options) {
65
+ if (options.algorithms && options.algorithms.length > 0)
66
+ return options.algorithms;
67
+ const algorithms = [];
68
+ if (options.secret || options.serverSecret)
69
+ algorithms.push("HS256");
70
+ if (options.publicKey || options.jwks) {
71
+ algorithms.push("RS256", "RS384", "RS512", "ES256", "ES384", "ES512");
72
+ }
73
+ return algorithms;
74
+ }
75
+ function algorithmFamily(algorithm) {
76
+ return algorithm.startsWith("HS") ? "hmac" : "asymmetric";
77
+ }
78
+ function fetchJwks(options) {
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ var _a, _b;
81
+ const fetchImpl = (_a = options.fetch) !== null && _a !== void 0 ? _a : globalThis.fetch;
82
+ if (typeof fetchImpl !== "function") {
83
+ throw (0, errors_1.accessiAuthError)(500, "AUTH_CONFIG_INVALID", "fetch non disponibile per caricare la JWKS.");
84
+ }
85
+ const controller = new AbortController();
86
+ const timeout = setTimeout(() => controller.abort(), (_b = options.timeoutMs) !== null && _b !== void 0 ? _b : 3000);
87
+ try {
88
+ const response = yield fetchImpl(options.url, {
89
+ method: "GET",
90
+ headers: { Accept: "application/json" },
91
+ signal: controller.signal,
92
+ });
93
+ if (!response.ok) {
94
+ throw (0, errors_1.accessiAuthError)(503, "AUTH_JWKS_UNAVAILABLE", `JWKS non disponibile (HTTP ${response.status}).`);
95
+ }
96
+ const payload = yield response.json();
97
+ if (!isRecord(payload) || !Array.isArray(payload.keys)) {
98
+ throw (0, errors_1.accessiAuthError)(503, "AUTH_JWKS_UNAVAILABLE", "Risposta JWKS non valida.");
99
+ }
100
+ return payload.keys.filter(isRecord);
101
+ }
102
+ catch (error) {
103
+ if (error && typeof error === "object" && "code" in error && "status" in error) {
104
+ throw error;
105
+ }
106
+ throw (0, errors_1.accessiAuthError)(503, "AUTH_JWKS_UNAVAILABLE", "JWKS non raggiungibile.");
107
+ }
108
+ finally {
109
+ clearTimeout(timeout);
110
+ }
111
+ });
112
+ }
113
+ function selectJwk(keys, kid, algorithm) {
114
+ const candidates = keys.filter((key) => {
115
+ const keyAlg = typeof key.alg === "string" ? key.alg : undefined;
116
+ const keyKid = typeof key.kid === "string" ? key.kid : undefined;
117
+ if (keyAlg && keyAlg !== algorithm)
118
+ return false;
119
+ if (kid && keyKid && keyKid !== kid)
120
+ return false;
121
+ return true;
122
+ });
123
+ const selected = candidates[0];
124
+ if (!selected) {
125
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_INVALID", "Chiave JWKS non trovata per il token.");
126
+ }
127
+ return selected;
128
+ }
129
+ /**
130
+ * Crea un verificatore locale riutilizzabile.
131
+ *
132
+ * Supporta HMAC, chiavi pubbliche PEM (RS ed ES) e JWKS remoto. La cache
133
+ * JWKS e legata all'istanza del verificatore.
134
+ */
135
+ function createAccessiTokenVerifier(options) {
136
+ var _a, _b;
137
+ const algorithms = defaultAlgorithms(options);
138
+ if (algorithms.length === 0) {
139
+ throw (0, errors_1.accessiAuthError)(500, "AUTH_CONFIG_INVALID", "Configurare almeno una tra jwt.secret, jwt.serverSecret, jwt.publicKey e jwt.jwks.");
140
+ }
141
+ const clockTolerance = (_a = options.clockToleranceSeconds) !== null && _a !== void 0 ? _a : 5;
142
+ const hmacSecret = (_b = options.secret) !== null && _b !== void 0 ? _b : (options.serverSecret ? (0, keys_1.deriveAccessiAccessSecret)(options.serverSecret) : undefined);
143
+ let jwksCache;
144
+ const getJwksKeys = () => __awaiter(this, void 0, void 0, function* () {
145
+ var _a;
146
+ if (!options.jwks)
147
+ return [];
148
+ if (jwksCache && jwksCache.expiresAt > Date.now())
149
+ return jwksCache.keys;
150
+ const keys = yield fetchJwks(options.jwks);
151
+ jwksCache = {
152
+ keys,
153
+ expiresAt: Date.now() + Math.max(1000, (_a = options.jwks.cacheTtlMs) !== null && _a !== void 0 ? _a : 300000),
154
+ };
155
+ return keys;
156
+ });
157
+ const verify = (token) => __awaiter(this, void 0, void 0, function* () {
158
+ const decoded = jwt.decode(token, { complete: true });
159
+ if (!decoded || typeof decoded === "string" || !isRecord(decoded.header)) {
160
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_INVALID", "Token JWT non valido.");
161
+ }
162
+ const algorithm = typeof decoded.header.alg === "string" ? decoded.header.alg : undefined;
163
+ if (!algorithm || !algorithms.includes(algorithm)) {
164
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_INVALID", "Algoritmo JWT non consentito.");
165
+ }
166
+ let key;
167
+ if (algorithmFamily(algorithm) === "hmac") {
168
+ if (!hmacSecret) {
169
+ throw (0, errors_1.accessiAuthError)(500, "AUTH_CONFIG_INVALID", "jwt.secret o jwt.serverSecret non configurato per token HS*.");
170
+ }
171
+ key = hmacSecret;
172
+ }
173
+ else if (options.publicKey) {
174
+ key = options.publicKey;
175
+ }
176
+ else if (options.jwks) {
177
+ const keys = yield getJwksKeys();
178
+ const kid = typeof decoded.header.kid === "string" ? decoded.header.kid : undefined;
179
+ key = (0, crypto_1.createPublicKey)({ key: selectJwk(keys, kid, algorithm), format: "jwk" })
180
+ .export({ type: "spki", format: "pem" });
181
+ }
182
+ else {
183
+ throw (0, errors_1.accessiAuthError)(500, "AUTH_CONFIG_INVALID", "jwt.publicKey/jwt.jwks non configurati.");
184
+ }
185
+ let verified;
186
+ try {
187
+ verified = jwt.verify(token, key, Object.assign(Object.assign(Object.assign({ algorithms: [algorithm] }, (options.issuer ? { issuer: options.issuer } : {})), (options.audience
188
+ ? { audience: options.audience }
189
+ : {})), { clockTolerance }));
190
+ }
191
+ catch (_a) {
192
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_INVALID", "Token non valido o scaduto.");
193
+ }
194
+ if (!isRecord(verified)) {
195
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_INVALID", "Payload JWT non valido.");
196
+ }
197
+ if (verified.typ !== "access") {
198
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_INVALID", "Il token non e un access token Accessi.");
199
+ }
200
+ const codiceUtente = (0, contracts_1.resolveCodiceUtenteFromTokenPayload)(verified);
201
+ if (!codiceUtente) {
202
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_USER_CODE_MISSING", "Token privo di un utente valido.");
203
+ }
204
+ return {
205
+ token,
206
+ payload: verified,
207
+ codiceUtente,
208
+ user: extractUser(verified),
209
+ };
210
+ });
211
+ return {
212
+ verify,
213
+ verifyAuthorizationHeader(header) {
214
+ return __awaiter(this, void 0, void 0, function* () {
215
+ const token = (0, contracts_1.extractAccessiBearerToken)(header);
216
+ if (!token) {
217
+ throw (0, errors_1.accessiAuthError)(401, "AUTH_TOKEN_MISSING", "Token Bearer mancante o malformato.");
218
+ }
219
+ return verify(token);
220
+ });
221
+ },
222
+ };
223
+ }
224
+ /** Converte un header `Authorization` in verifica del token, senza cache JWKS condivisa. */
225
+ function verifyAccessiAccessToken(header, options) {
226
+ return __awaiter(this, void 0, void 0, function* () {
227
+ return createAccessiTokenVerifier(options).verifyAuthorizationHeader(header);
228
+ });
229
+ }
230
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/accessi/resource-server/token.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwHA,gEAsGC;AAGD,4DAKC;AAtOD,mCAAyC;AAEzC,kDAAoC;AAEpC,4CAA8F;AAC9F,qCAA4C;AAC5C,iCAAmD;AAsBnD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,WAAW,CAAC,OAAgC;IACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QACrC,CAAC,CAAC,OAAO,CAAC,MAAM;QAChB,CAAC,CAAC,QAAQ,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,CAAC;YAC1B,CAAC,CAAC,QAAQ,CAAC,MAAM;YACjB,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAwC;IACjE,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC,UAAU,CAAC;IAEnF,MAAM,UAAU,GAA0B,EAAE,CAAC;IAC7C,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,YAAY;QAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrE,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACtC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB;IACxC,OAAO,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;AAC5D,CAAC;AAED,SAAe,SAAS,CACtB,OAA6D;;;QAE7D,MAAM,SAAS,GAAG,MAAA,OAAO,CAAC,KAAK,mCAAI,UAAU,CAAC,KAAK,CAAC;QACpD,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;YACpC,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,qBAAqB,EAAE,6CAA6C,CAAC,CAAC;QACpG,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,MAAA,OAAO,CAAC,SAAS,mCAAI,IAAI,CAAC,CAAC;QAChF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC5C,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;gBACvC,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAA,yBAAgB,EACpB,GAAG,EACH,uBAAuB,EACvB,8BAA8B,QAAQ,CAAC,MAAM,IAAI,CAClD,CAAC;YACJ,CAAC;YACD,MAAM,OAAO,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,uBAAuB,EAAE,2BAA2B,CAAC,CAAC;YACpF,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;gBAC/E,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,uBAAuB,EAAE,yBAAyB,CAAC,CAAC;QAClF,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CAAA;AAED,SAAS,SAAS,CAChB,IAAoC,EACpC,GAAuB,EACvB,SAAiB;IAEjB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,IAAI,MAAM,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACjD,IAAI,GAAG,IAAI,MAAM,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,uCAAuC,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,QAAiC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,0BAA0B,CAAC,OAAwC;;IACjF,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAA,yBAAgB,EACpB,GAAG,EACH,qBAAqB,EACrB,oFAAoF,CACrF,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,MAAA,OAAO,CAAC,qBAAqB,mCAAI,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,MAAA,OAAO,CAAC,MAAM,mCAC5B,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,IAAA,gCAAyB,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1F,IAAI,SAAqC,CAAC;IAE1C,MAAM,WAAW,GAAG,GAAkD,EAAE;;QACtE,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QAC7B,IAAI,SAAS,IAAI,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,SAAS,CAAC,IAAI,CAAC;QACzE,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3C,SAAS,GAAG;YACV,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAK,EAAE,MAAA,OAAO,CAAC,IAAI,CAAC,UAAU,mCAAI,MAAO,CAAC;SAC5E,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC,CAAA,CAAC;IAEF,MAAM,MAAM,GAAG,CAAO,KAAa,EAAqC,EAAE;QACxE,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACzE,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,uBAAuB,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAgC,CAAC,EAAE,CAAC;YACzE,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,+BAA+B,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,GAAe,CAAC;QACpB,IAAI,eAAe,CAAC,SAAS,CAAC,KAAK,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAA,yBAAgB,EACpB,GAAG,EACH,qBAAqB,EACrB,8DAA8D,CAC/D,CAAC;YACJ,CAAC;YACD,GAAG,GAAG,UAAU,CAAC;QACnB,CAAC;aAAM,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YAC7B,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC;QAC1B,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,WAAW,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;YACpF,GAAG,GAAG,IAAA,wBAAe,EAAC,EAAE,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;iBAC3E,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,qBAAqB,EAAE,yCAAyC,CAAC,CAAC;QAChG,CAAC;QAED,IAAI,QAAiB,CAAC;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,8CAC9B,UAAU,EAAE,CAAC,SAA0B,CAAC,IACrC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAClD,CAAC,OAAO,CAAC,QAAQ;gBAClB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAyC,EAAE;gBACjE,CAAC,CAAC,EAAE,CAAC,KACP,cAAc,IACd,CAAC;QACL,CAAC;QAAC,WAAM,CAAC;YACP,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,6BAA6B,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxB,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,yBAAyB,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,QAAQ,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,yCAAyC,CAAC,CAAC;QAC/F,CAAC;QAED,MAAM,YAAY,GAAG,IAAA,+CAAmC,EAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,wBAAwB,EAAE,kCAAkC,CAAC,CAAC;QAC5F,CAAC;QAED,OAAO;YACL,KAAK;YACL,OAAO,EAAE,QAAqC;YAC9C,YAAY;YACZ,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC;SAC5B,CAAC;IACJ,CAAC,CAAA,CAAC;IAEF,OAAO;QACL,MAAM;QACA,yBAAyB,CAAC,MAAe;;gBAC7C,MAAM,KAAK,GAAG,IAAA,qCAAyB,EAAC,MAAM,CAAC,CAAC;gBAChD,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,IAAA,yBAAgB,EAAC,GAAG,EAAE,oBAAoB,EAAE,qCAAqC,CAAC,CAAC;gBAC3F,CAAC;gBACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;SAAA;KACF,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,SAAsB,wBAAwB,CAC5C,MAAe,EACf,OAAwC;;QAExC,OAAO,0BAA0B,CAAC,OAAO,CAAC,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAC/E,CAAC;CAAA","sourcesContent":["import { createPublicKey } from \"crypto\";\nimport type { JsonWebKey } from \"crypto\";\nimport * as jwt from \"jsonwebtoken\";\nimport type { AccessiAccessTokenPayload } from \"../contracts\";\nimport { extractAccessiBearerToken, resolveCodiceUtenteFromTokenPayload } from \"../contracts\";\nimport { accessiAuthError } from \"./errors\";\nimport { deriveAccessiAccessSecret } from \"./keys\";\nimport type { AccessiJwtAlgorithm, AccessiResourceServerJwtOptions } from \"./types\";\n\n/** Esito della verifica locale di un access token. */\nexport interface AccessiTokenVerification {\n token: string;\n payload: AccessiAccessTokenPayload;\n codiceUtente: number;\n user: Record<string, unknown>;\n}\n\n/** Verificatore riutilizzabile: conserva la cache JWKS tra una richiesta e l'altra. */\nexport interface AccessiTokenVerifier {\n verify(token: string): Promise<AccessiTokenVerification>;\n verifyAuthorizationHeader(header: unknown): Promise<AccessiTokenVerification>;\n}\n\ninterface JwksCacheEntry {\n keys: Array<Record<string, unknown>>;\n expiresAt: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction extractUser(payload: Record<string, unknown>): Record<string, unknown> {\n const userData = isRecord(payload.userData) ? payload.userData : undefined;\n const utente = isRecord(payload.utente)\n ? payload.utente\n : isRecord(userData?.utente)\n ? userData.utente\n : undefined;\n return utente ?? {};\n}\n\nfunction defaultAlgorithms(options: AccessiResourceServerJwtOptions): AccessiJwtAlgorithm[] {\n if (options.algorithms && options.algorithms.length > 0) return options.algorithms;\n\n const algorithms: AccessiJwtAlgorithm[] = [];\n if (options.secret || options.serverSecret) algorithms.push(\"HS256\");\n if (options.publicKey || options.jwks) {\n algorithms.push(\"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\");\n }\n return algorithms;\n}\n\nfunction algorithmFamily(algorithm: string): \"hmac\" | \"asymmetric\" {\n return algorithm.startsWith(\"HS\") ? \"hmac\" : \"asymmetric\";\n}\n\nasync function fetchJwks(\n options: NonNullable<AccessiResourceServerJwtOptions[\"jwks\"]>,\n): Promise<Array<Record<string, unknown>>> {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== \"function\") {\n throw accessiAuthError(500, \"AUTH_CONFIG_INVALID\", \"fetch non disponibile per caricare la JWKS.\");\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n try {\n const response = await fetchImpl(options.url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n signal: controller.signal,\n });\n if (!response.ok) {\n throw accessiAuthError(\n 503,\n \"AUTH_JWKS_UNAVAILABLE\",\n `JWKS non disponibile (HTTP ${response.status}).`,\n );\n }\n const payload: unknown = await response.json();\n if (!isRecord(payload) || !Array.isArray(payload.keys)) {\n throw accessiAuthError(503, \"AUTH_JWKS_UNAVAILABLE\", \"Risposta JWKS non valida.\");\n }\n return payload.keys.filter(isRecord);\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && \"status\" in error) {\n throw error;\n }\n throw accessiAuthError(503, \"AUTH_JWKS_UNAVAILABLE\", \"JWKS non raggiungibile.\");\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction selectJwk(\n keys: Array<Record<string, unknown>>,\n kid: string | undefined,\n algorithm: string,\n): JsonWebKey {\n const candidates = keys.filter((key) => {\n const keyAlg = typeof key.alg === \"string\" ? key.alg : undefined;\n const keyKid = typeof key.kid === \"string\" ? key.kid : undefined;\n if (keyAlg && keyAlg !== algorithm) return false;\n if (kid && keyKid && keyKid !== kid) return false;\n return true;\n });\n const selected = candidates[0];\n if (!selected) {\n throw accessiAuthError(401, \"AUTH_TOKEN_INVALID\", \"Chiave JWKS non trovata per il token.\");\n }\n return selected as unknown as JsonWebKey;\n}\n\n/**\n * Crea un verificatore locale riutilizzabile.\n *\n * Supporta HMAC, chiavi pubbliche PEM (RS ed ES) e JWKS remoto. La cache\n * JWKS e legata all'istanza del verificatore.\n */\nexport function createAccessiTokenVerifier(options: AccessiResourceServerJwtOptions): AccessiTokenVerifier {\n const algorithms = defaultAlgorithms(options);\n if (algorithms.length === 0) {\n throw accessiAuthError(\n 500,\n \"AUTH_CONFIG_INVALID\",\n \"Configurare almeno una tra jwt.secret, jwt.serverSecret, jwt.publicKey e jwt.jwks.\",\n );\n }\n\n const clockTolerance = options.clockToleranceSeconds ?? 5;\n const hmacSecret = options.secret\n ?? (options.serverSecret ? deriveAccessiAccessSecret(options.serverSecret) : undefined);\n let jwksCache: JwksCacheEntry | undefined;\n\n const getJwksKeys = async (): Promise<Array<Record<string, unknown>>> => {\n if (!options.jwks) return [];\n if (jwksCache && jwksCache.expiresAt > Date.now()) return jwksCache.keys;\n const keys = await fetchJwks(options.jwks);\n jwksCache = {\n keys,\n expiresAt: Date.now() + Math.max(1_000, options.jwks.cacheTtlMs ?? 300_000),\n };\n return keys;\n };\n\n const verify = async (token: string): Promise<AccessiTokenVerification> => {\n const decoded = jwt.decode(token, { complete: true });\n if (!decoded || typeof decoded === \"string\" || !isRecord(decoded.header)) {\n throw accessiAuthError(401, \"AUTH_TOKEN_INVALID\", \"Token JWT non valido.\");\n }\n\n const algorithm = typeof decoded.header.alg === \"string\" ? decoded.header.alg : undefined;\n if (!algorithm || !algorithms.includes(algorithm as AccessiJwtAlgorithm)) {\n throw accessiAuthError(401, \"AUTH_TOKEN_INVALID\", \"Algoritmo JWT non consentito.\");\n }\n\n let key: jwt.Secret;\n if (algorithmFamily(algorithm) === \"hmac\") {\n if (!hmacSecret) {\n throw accessiAuthError(\n 500,\n \"AUTH_CONFIG_INVALID\",\n \"jwt.secret o jwt.serverSecret non configurato per token HS*.\",\n );\n }\n key = hmacSecret;\n } else if (options.publicKey) {\n key = options.publicKey;\n } else if (options.jwks) {\n const keys = await getJwksKeys();\n const kid = typeof decoded.header.kid === \"string\" ? decoded.header.kid : undefined;\n key = createPublicKey({ key: selectJwk(keys, kid, algorithm), format: \"jwk\" })\n .export({ type: \"spki\", format: \"pem\" });\n } else {\n throw accessiAuthError(500, \"AUTH_CONFIG_INVALID\", \"jwt.publicKey/jwt.jwks non configurati.\");\n }\n\n let verified: unknown;\n try {\n verified = jwt.verify(token, key, {\n algorithms: [algorithm as jwt.Algorithm],\n ...(options.issuer ? { issuer: options.issuer } : {}),\n ...(options.audience\n ? { audience: options.audience as jwt.VerifyOptions[\"audience\"] }\n : {}),\n clockTolerance,\n });\n } catch {\n throw accessiAuthError(401, \"AUTH_TOKEN_INVALID\", \"Token non valido o scaduto.\");\n }\n\n if (!isRecord(verified)) {\n throw accessiAuthError(401, \"AUTH_TOKEN_INVALID\", \"Payload JWT non valido.\");\n }\n if (verified.typ !== \"access\") {\n throw accessiAuthError(401, \"AUTH_TOKEN_INVALID\", \"Il token non e un access token Accessi.\");\n }\n\n const codiceUtente = resolveCodiceUtenteFromTokenPayload(verified);\n if (!codiceUtente) {\n throw accessiAuthError(401, \"AUTH_USER_CODE_MISSING\", \"Token privo di un utente valido.\");\n }\n\n return {\n token,\n payload: verified as AccessiAccessTokenPayload,\n codiceUtente,\n user: extractUser(verified),\n };\n };\n\n return {\n verify,\n async verifyAuthorizationHeader(header: unknown): Promise<AccessiTokenVerification> {\n const token = extractAccessiBearerToken(header);\n if (!token) {\n throw accessiAuthError(401, \"AUTH_TOKEN_MISSING\", \"Token Bearer mancante o malformato.\");\n }\n return verify(token);\n },\n };\n}\n\n/** Converte un header `Authorization` in verifica del token, senza cache JWKS condivisa. */\nexport async function verifyAccessiAccessToken(\n header: unknown,\n options: AccessiResourceServerJwtOptions,\n): Promise<AccessiTokenVerification> {\n return createAccessiTokenVerifier(options).verifyAuthorizationHeader(header);\n}\n"]}
@@ -0,0 +1,78 @@
1
+ import type { AccessiAuthorizationOptions, AccessiGrant, GrantsResult } from "../contracts";
2
+ /** Algoritmi JWT supportati dal resource server. */
3
+ export type AccessiJwtAlgorithm = "HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512";
4
+ /** Opzioni di verifica locale del JWT. Almeno una tra `secret`, `publicKey` e `jwks` e obbligatoria. */
5
+ export interface AccessiResourceServerJwtOptions {
6
+ /** Chiave HMAC gia derivata (access key). Alternativa a `serverSecret`. */
7
+ secret?: string;
8
+ /**
9
+ * Segreto Accessi grezzo (`ACCESSI_JWT_SECRET`).
10
+ *
11
+ * Il resource server deriva automaticamente la chiave access con la stessa
12
+ * KDF del server: e il modo consigliato quando si condivide il segreto HS256.
13
+ */
14
+ serverSecret?: string;
15
+ /** Chiave pubblica PEM per algoritmi RS ed ES. */
16
+ publicKey?: string | Buffer;
17
+ /** JWKS remoto per verificare token firmati con chiavi asimmetriche. */
18
+ jwks?: {
19
+ url: string;
20
+ cacheTtlMs?: number;
21
+ timeoutMs?: number;
22
+ fetch?: typeof fetch;
23
+ };
24
+ /** Default: HS256 con `secret`, altrimenti RS/ES con `publicKey`/`jwks`. */
25
+ algorithms?: AccessiJwtAlgorithm[];
26
+ /** Issuer atteso (`iss`). */
27
+ issuer?: string;
28
+ /** Audience attesa (`aud`). */
29
+ audience?: string | string[];
30
+ /** Tolleranza orologio in secondi. Default: 5. */
31
+ clockToleranceSeconds?: number;
32
+ }
33
+ /** Configurazione del client di introspection verso Accessi Service. */
34
+ export interface AccessiIntrospectionOptions {
35
+ /** URL completo, es. `https://accessi.example.com/api/accessi/auth/introspect`. */
36
+ url: string;
37
+ /** Service token Accessi con scope `accessi:introspect`. */
38
+ serviceToken: string;
39
+ /** TTL della cache locale dei risultati attivi. Default: 30000 ms. */
40
+ cacheTtlMs?: number;
41
+ /** Timeout HTTP. Default: 3000 ms. */
42
+ timeoutMs?: number;
43
+ /** Fetch iniettabile per test o runtime non-Node. */
44
+ fetch?: typeof fetch;
45
+ }
46
+ /** Risultato dell'introspection. */
47
+ export interface AccessiIntrospectionResult {
48
+ active: boolean;
49
+ user?: Record<string, unknown>;
50
+ codiceUtente?: number;
51
+ grants?: GrantsResult;
52
+ }
53
+ /** Modalita di autenticazione del resource server. */
54
+ export type AccessiResourceServerMode = "local" | "introspection";
55
+ /**
56
+ * Configurazione di un backend fratello che non possiede il database Accessi.
57
+ *
58
+ * - `mode: "local"` verifica il JWT con chiave locale e, se servono grant, usa
59
+ * l'introspection per leggerli.
60
+ * - `mode: "introspection"` delega la verifica del token ad Accessi Service.
61
+ */
62
+ export interface AccessiResourceServerOptions {
63
+ mode?: AccessiResourceServerMode;
64
+ jwt?: AccessiResourceServerJwtOptions;
65
+ introspection?: AccessiIntrospectionOptions;
66
+ /** Policy di autorizzazione opzionale applicata dopo l'autenticazione. */
67
+ authorization?: AccessiAuthorizationOptions;
68
+ }
69
+ /** Dati allegati alla request dopo l'autenticazione. */
70
+ export interface AccessiRequestContext {
71
+ token: string;
72
+ user: Record<string, unknown>;
73
+ codiceUtente?: number;
74
+ grants?: GrantsResult;
75
+ payload?: Record<string, unknown>;
76
+ }
77
+ /** Grant esposto per compatibilita con il middleware storico. */
78
+ export type AccessiRequestGrants = AccessiGrant[];
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/accessi/resource-server/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n AccessiAuthorizationOptions,\n AccessiGrant,\n GrantsResult,\n} from \"../contracts\";\n\n/** Algoritmi JWT supportati dal resource server. */\nexport type AccessiJwtAlgorithm =\n | \"HS256\"\n | \"HS384\"\n | \"HS512\"\n | \"RS256\"\n | \"RS384\"\n | \"RS512\"\n | \"ES256\"\n | \"ES384\"\n | \"ES512\";\n\n/** Opzioni di verifica locale del JWT. Almeno una tra `secret`, `publicKey` e `jwks` e obbligatoria. */\nexport interface AccessiResourceServerJwtOptions {\n /** Chiave HMAC gia derivata (access key). Alternativa a `serverSecret`. */\n secret?: string;\n /**\n * Segreto Accessi grezzo (`ACCESSI_JWT_SECRET`).\n *\n * Il resource server deriva automaticamente la chiave access con la stessa\n * KDF del server: e il modo consigliato quando si condivide il segreto HS256.\n */\n serverSecret?: string;\n /** Chiave pubblica PEM per algoritmi RS ed ES. */\n publicKey?: string | Buffer;\n /** JWKS remoto per verificare token firmati con chiavi asimmetriche. */\n jwks?: {\n url: string;\n cacheTtlMs?: number;\n timeoutMs?: number;\n fetch?: typeof fetch;\n };\n /** Default: HS256 con `secret`, altrimenti RS/ES con `publicKey`/`jwks`. */\n algorithms?: AccessiJwtAlgorithm[];\n /** Issuer atteso (`iss`). */\n issuer?: string;\n /** Audience attesa (`aud`). */\n audience?: string | string[];\n /** Tolleranza orologio in secondi. Default: 5. */\n clockToleranceSeconds?: number;\n}\n\n/** Configurazione del client di introspection verso Accessi Service. */\nexport interface AccessiIntrospectionOptions {\n /** URL completo, es. `https://accessi.example.com/api/accessi/auth/introspect`. */\n url: string;\n /** Service token Accessi con scope `accessi:introspect`. */\n serviceToken: string;\n /** TTL della cache locale dei risultati attivi. Default: 30000 ms. */\n cacheTtlMs?: number;\n /** Timeout HTTP. Default: 3000 ms. */\n timeoutMs?: number;\n /** Fetch iniettabile per test o runtime non-Node. */\n fetch?: typeof fetch;\n}\n\n/** Risultato dell'introspection. */\nexport interface AccessiIntrospectionResult {\n active: boolean;\n user?: Record<string, unknown>;\n codiceUtente?: number;\n grants?: GrantsResult;\n}\n\n/** Modalita di autenticazione del resource server. */\nexport type AccessiResourceServerMode = \"local\" | \"introspection\";\n\n/**\n * Configurazione di un backend fratello che non possiede il database Accessi.\n *\n * - `mode: \"local\"` verifica il JWT con chiave locale e, se servono grant, usa\n * l'introspection per leggerli.\n * - `mode: \"introspection\"` delega la verifica del token ad Accessi Service.\n */\nexport interface AccessiResourceServerOptions {\n mode?: AccessiResourceServerMode;\n jwt?: AccessiResourceServerJwtOptions;\n introspection?: AccessiIntrospectionOptions;\n /** Policy di autorizzazione opzionale applicata dopo l'autenticazione. */\n authorization?: AccessiAuthorizationOptions;\n}\n\n/** Dati allegati alla request dopo l'autenticazione. */\nexport interface AccessiRequestContext {\n token: string;\n user: Record<string, unknown>;\n codiceUtente?: number;\n grants?: GrantsResult;\n payload?: Record<string, unknown>;\n}\n\n/** Grant esposto per compatibilita con il middleware storico. */\nexport type AccessiRequestGrants = AccessiGrant[];\n"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Entry point server Accessi.
3
+ *
4
+ * Questo e l'unico entry point che puo importare database, SMTP, migrazioni,
5
+ * console e servizi Nest completi. I backend fratelli devono usare
6
+ * `accessi/resource-server` e `accessi/client`.
7
+ */
8
+ export * from "../../accessi-module";
9
+ export type { AccessiOptions as AccessiServerOptions } from "../../accessi-module";
10
+ export { createAccessiOptionsFromEnv, createCatalogScriptsOptionsFromEnv, } from "../../accessi-module/database-updates/accessiOptionsFromEnv";
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.createCatalogScriptsOptionsFromEnv = exports.createAccessiOptionsFromEnv = void 0;
18
+ /**
19
+ * Entry point server Accessi.
20
+ *
21
+ * Questo e l'unico entry point che puo importare database, SMTP, migrazioni,
22
+ * console e servizi Nest completi. I backend fratelli devono usare
23
+ * `accessi/resource-server` e `accessi/client`.
24
+ */
25
+ __exportStar(require("../../accessi-module"), exports);
26
+ var accessiOptionsFromEnv_1 = require("../../accessi-module/database-updates/accessiOptionsFromEnv");
27
+ Object.defineProperty(exports, "createAccessiOptionsFromEnv", { enumerable: true, get: function () { return accessiOptionsFromEnv_1.createAccessiOptionsFromEnv; } });
28
+ Object.defineProperty(exports, "createCatalogScriptsOptionsFromEnv", { enumerable: true, get: function () { return accessiOptionsFromEnv_1.createCatalogScriptsOptionsFromEnv; } });
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/accessi/server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;;;;;GAMG;AACH,uDAAqC;AAErC,qGAGqE;AAFnE,oIAAA,2BAA2B,OAAA;AAC3B,2IAAA,kCAAkC,OAAA","sourcesContent":["/**\n * Entry point server Accessi.\n *\n * Questo e l'unico entry point che puo importare database, SMTP, migrazioni,\n * console e servizi Nest completi. I backend fratelli devono usare\n * `accessi/resource-server` e `accessi/client`.\n */\nexport * from \"../../accessi-module\";\nexport type { AccessiOptions as AccessiServerOptions } from \"../../accessi-module\";\nexport {\n createAccessiOptionsFromEnv,\n createCatalogScriptsOptionsFromEnv,\n} from \"../../accessi-module/database-updates/accessiOptionsFromEnv\";\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Asset UI frameworkless pubblicati con il pacchetto.
3
+ *
4
+ * I componenti sono Web Components senza dipendenze runtime: vanno inclusi
5
+ * come `<script>` o copiati nel build dell'app. I percorsi sono relativi alla
6
+ * root del pacchetto distribuito (`dist/`).
7
+ */
8
+ export declare const ACCESSI_UI_ASSETS: {
9
+ readonly areeDisponibili: "angular-components/aree-disponibili/aree-disponibili.js";
10
+ };
11
+ export type AccessiUiComponent = keyof typeof ACCESSI_UI_ASSETS;
12
+ /** Restituisce il path dell'asset UI relativo a `dist/`. */
13
+ export declare function getAccessiUiAssetPath(component: AccessiUiComponent): string;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ACCESSI_UI_ASSETS = void 0;
4
+ exports.getAccessiUiAssetPath = getAccessiUiAssetPath;
5
+ /**
6
+ * Asset UI frameworkless pubblicati con il pacchetto.
7
+ *
8
+ * I componenti sono Web Components senza dipendenze runtime: vanno inclusi
9
+ * come `<script>` o copiati nel build dell'app. I percorsi sono relativi alla
10
+ * root del pacchetto distribuito (`dist/`).
11
+ */
12
+ exports.ACCESSI_UI_ASSETS = {
13
+ areeDisponibili: "angular-components/aree-disponibili/aree-disponibili.js",
14
+ };
15
+ /** Restituisce il path dell'asset UI relativo a `dist/`. */
16
+ function getAccessiUiAssetPath(component) {
17
+ return exports.ACCESSI_UI_ASSETS[component];
18
+ }
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/accessi/ui/index.ts"],"names":[],"mappings":";;;AAcA,sDAEC;AAhBD;;;;;;GAMG;AACU,QAAA,iBAAiB,GAAG;IAC/B,eAAe,EAAE,yDAAyD;CAClE,CAAC;AAIX,4DAA4D;AAC5D,SAAgB,qBAAqB,CAAC,SAA6B;IACjE,OAAO,yBAAiB,CAAC,SAAS,CAAC,CAAC;AACtC,CAAC","sourcesContent":["/**\n * Asset UI frameworkless pubblicati con il pacchetto.\n *\n * I componenti sono Web Components senza dipendenze runtime: vanno inclusi\n * come `<script>` o copiati nel build dell'app. I percorsi sono relativi alla\n * root del pacchetto distribuito (`dist/`).\n */\nexport const ACCESSI_UI_ASSETS = {\n areeDisponibili: \"angular-components/aree-disponibili/aree-disponibili.js\",\n} as const;\n\nexport type AccessiUiComponent = keyof typeof ACCESSI_UI_ASSETS;\n\n/** Restituisce il path dell'asset UI relativo a `dist/`. */\nexport function getAccessiUiAssetPath(component: AccessiUiComponent): string {\n return ACCESSI_UI_ASSETS[component];\n}\n"]}
@@ -6,10 +6,25 @@
6
6
  */
7
7
  import { Options } from 'node-firebird';
8
8
  import { DynamicModule } from '@nestjs/common';
9
+ import type { LoggerService } from '@nestjs/common';
10
+ import type { OpenApiSetupOptions } from '../openapi/OpenApiConfig';
11
+ import type { AccessiAccessTokenAlgorithm } from './security/jwtTokenOptions';
9
12
  /** JWT emesso da Accessi dopo un login locale o SSO. Non riutilizzare il segreto del provider SSO. */
10
13
  export interface JwtOptions {
11
14
  /** Segreto simmetrico per firmare e verificare i JWT Accessi; deve essere unico per ambiente. */
12
15
  secret: string;
16
+ /** Issuer (`iss`) opzionale degli access token. Consigliato in una topologia multi-servizio. */
17
+ issuer?: string;
18
+ /** Audience (`aud`) opzionale degli access token. */
19
+ audience?: string | string[];
20
+ /** Algoritmo degli access token. Default `HS256` per retrocompatibilita. */
21
+ algorithm?: AccessiAccessTokenAlgorithm;
22
+ /** Chiave privata PEM per RS/ES. Obbligatoria quando `algorithm` non e HS*. */
23
+ privateKey?: string;
24
+ /** Chiave pubblica PEM per la verifica RS/ES. */
25
+ publicKey?: string;
26
+ /** Key id pubblicato nella JWKS, per rotazione chiavi. */
27
+ keyId?: string;
13
28
  /** Durata compatibile con `jsonwebtoken`, per esempio `24h` o `3600s`. */
14
29
  expiresIn: string;
15
30
  }
@@ -178,8 +193,17 @@ export interface AccessiOptions {
178
193
  systemSeeds?: SystemSeedsOptions;
179
194
  /** Bootstrap del primo admin tramite token casuale stampato a ogni avvio. */
180
195
  adminBootstrap?: AdminBootstrapOptions;
181
- /** Base URL pubblica usata solo per loggare gli indirizzi (console, swagger, API). */
196
+ /** Base URL pubblica usata solo per loggare gli indirizzi (console, OpenAPI, API). */
182
197
  publicBaseUrl?: string;
198
+ /**
199
+ * Documentazione OpenAPI del modulo. Default invariati:
200
+ * UI `accessi/openapi`, JSON `accessi/openapi.json`.
201
+ */
202
+ openapi?: OpenApiSetupOptions;
203
+ /** Logger Nest usato dal sotto-app Accessi. Se assente Nest usa il proprio logger. */
204
+ logger?: LoggerService;
205
+ /** Buffer dei log di bootstrap del sotto-app. Default `true` (comportamento storico). */
206
+ bufferLogs?: boolean;
183
207
  }
184
208
  export declare class AccessiModule {
185
209
  /**
@@ -33,6 +33,7 @@ const ServiceTokenController_1 = require("./Controllers/ServiceTokenController")
33
33
  const ServiceTokenService_1 = require("./Services/ServiceTokenService/ServiceTokenService");
34
34
  const serviceTokenGuard_1 = require("./security/serviceTokenGuard");
35
35
  const SchemaController_1 = require("./Controllers/SchemaController");
36
+ const AccessiIntrospectionController_1 = require("./Controllers/AccessiIntrospectionController");
36
37
  const SchemaExportService_1 = require("./Services/SchemaExportService/SchemaExportService");
37
38
  const AdminBootstrapService_1 = require("./Services/AdminBootstrapService/AdminBootstrapService");
38
39
  const emailConfiguration_1 = require("./security/emailConfiguration");
@@ -101,6 +102,7 @@ exports.AccessiModule = AccessiModule = AccessiModule_1 = __decorate([
101
102
  ConsoleEntryController_1.ConsoleEntryController,
102
103
  ServiceTokenController_1.ServiceTokenController,
103
104
  SchemaController_1.SchemaController,
105
+ AccessiIntrospectionController_1.AccessiIntrospectionController,
104
106
  ],
105
107
  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, AdminBootstrapService_1.AdminBootstrapService],
106
108
  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, AdminBootstrapService_1.AdminBootstrapService],
@@ -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,iFAA8E;AAC9E,4FAAyF;AACzF,oEAAiE;AACjE,qEAAkE;AAClE,4FAAyF;AACzF,kGAA+F;AAC/F,sEAAsE;AAgN/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,EAAE,yCAAmB,EAAE,6CAAqB;aAAC;YAChE,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,EAAE,yCAAmB,EAAE,6CAAqB;aAAC;SACjE,CAAC;IACJ,CAAC;CACF,CAAA;AA9CY,sCAAa;wBAAb,aAAa;IAlBzB,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,+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,EAAE,6CAAqB,CAAC;QACtS,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,EAAE,6CAAqB,CAAC;KAC3P,CAAC;GACW,aAAa,CA8CzB","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 { ConsoleEntryController } from './Controllers/ConsoleEntryController';\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 { AdminBootstrapService } from './Services/AdminBootstrapService/AdminBootstrapService';\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 adminBootstrap?: PublicAuthRateLimitRuleOptions;\n consoleEntry?: PublicAuthRateLimitRuleOptions;\n}\n\n/**\n * Bootstrap del primo admin. Se abilitato, Accessi genera un token casuale a ogni avvio del\n * processo, lo stampa nel log e lo accetta sull'endpoint pubblico `POST /accessi/auth/bootstrap-admin`.\n * Serve a creare il primo utente admin senza email di conferma e senza un admin gia esistente.\n */\nexport interface AdminBootstrapOptions {\n /** Abilita il bootstrap admin. Default `false`. */\n enabled?: boolean;\n /** Crea l'utente come superutente oltre che admin. Default `true`. */\n superUser?: boolean;\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 SystemSeedsOptions {\n /** `false` disabilita il seed automatico, ad esempio per ambienti gestiti manualmente. */\n enabled?: boolean;\n}\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 /** Seed di sistema eseguiti dopo la riconciliazione dello schema. Default: abilitati. */\n systemSeeds?: SystemSeedsOptions;\n /** Bootstrap del primo admin tramite token casuale stampato a ogni avvio. */\n adminBootstrap?: AdminBootstrapOptions;\n /** Base URL pubblica usata solo per loggare gli indirizzi (console, swagger, API). */\n publicBaseUrl?: string;\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 ConsoleEntryController,\n ServiceTokenController,\n SchemaController,\n ],\n providers: [AuthService, TwoFactorService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, AccessiDatabaseUpdater, FederatedAuthService, ServiceTokenService, ServiceTokenGuard, SchemaExportService, AdminBootstrapService],\n exports: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, FederatedAuthService, ServiceTokenService, ServiceTokenGuard, SchemaExportService, AdminBootstrapService],\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, SchemaExportService, AdminBootstrapService],\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, SchemaExportService, AdminBootstrapService],\n };\n }\n}\n"]}
1
+ {"version":3,"file":"AccessiModule.js","sourceRoot":"","sources":["../../src/accessi-module/AccessiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,mFAAgF;AAQhF,2CAA+D;AAI/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,iFAA8E;AAC9E,4FAAyF;AACzF,oEAAiE;AACjE,qEAAkE;AAClE,iGAA8F;AAC9F,4FAAyF;AACzF,kGAA+F;AAC/F,sEAAsE;AAsO/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,EAAE,yCAAmB,EAAE,6CAAqB;aAAC;YAChE,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,EAAE,yCAAmB,EAAE,6CAAqB;aAAC;SACjE,CAAC;IACJ,CAAC;CACF,CAAA;AA9CY,sCAAa;wBAAb,aAAa;IAnBzB,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,+CAAsB;YACtB,mCAAgB;YAChB,+DAA8B;SAC/B;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,EAAE,6CAAqB,CAAC;QACtS,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,EAAE,6CAAqB,CAAC;KAC3P,CAAC;GACW,aAAa,CA8CzB","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 type { LoggerService } from '@nestjs/common';\nimport type { OpenApiSetupOptions } from '../openapi/OpenApiConfig';\nimport type { AccessiAccessTokenAlgorithm } from './security/jwtTokenOptions';\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 { ConsoleEntryController } from './Controllers/ConsoleEntryController';\nimport { ServiceTokenController } from './Controllers/ServiceTokenController';\nimport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nimport { ServiceTokenGuard } from './security/serviceTokenGuard';\nimport { SchemaController } from './Controllers/SchemaController';\nimport { AccessiIntrospectionController } from './Controllers/AccessiIntrospectionController';\nimport { SchemaExportService } from './Services/SchemaExportService/SchemaExportService';\nimport { AdminBootstrapService } from './Services/AdminBootstrapService/AdminBootstrapService';\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 /** Issuer (`iss`) opzionale degli access token. Consigliato in una topologia multi-servizio. */\n issuer?: string;\n /** Audience (`aud`) opzionale degli access token. */\n audience?: string | string[];\n /** Algoritmo degli access token. Default `HS256` per retrocompatibilita. */\n algorithm?: AccessiAccessTokenAlgorithm;\n /** Chiave privata PEM per RS/ES. Obbligatoria quando `algorithm` non e HS*. */\n privateKey?: string;\n /** Chiave pubblica PEM per la verifica RS/ES. */\n publicKey?: string;\n /** Key id pubblicato nella JWKS, per rotazione chiavi. */\n keyId?: 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 adminBootstrap?: PublicAuthRateLimitRuleOptions;\n consoleEntry?: PublicAuthRateLimitRuleOptions;\n}\n\n/**\n * Bootstrap del primo admin. Se abilitato, Accessi genera un token casuale a ogni avvio del\n * processo, lo stampa nel log e lo accetta sull'endpoint pubblico `POST /accessi/auth/bootstrap-admin`.\n * Serve a creare il primo utente admin senza email di conferma e senza un admin gia esistente.\n */\nexport interface AdminBootstrapOptions {\n /** Abilita il bootstrap admin. Default `false`. */\n enabled?: boolean;\n /** Crea l'utente come superutente oltre che admin. Default `true`. */\n superUser?: boolean;\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 SystemSeedsOptions {\n /** `false` disabilita il seed automatico, ad esempio per ambienti gestiti manualmente. */\n enabled?: boolean;\n}\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 /** Seed di sistema eseguiti dopo la riconciliazione dello schema. Default: abilitati. */\n systemSeeds?: SystemSeedsOptions;\n /** Bootstrap del primo admin tramite token casuale stampato a ogni avvio. */\n adminBootstrap?: AdminBootstrapOptions;\n /** Base URL pubblica usata solo per loggare gli indirizzi (console, OpenAPI, API). */\n publicBaseUrl?: string;\n /**\n * Documentazione OpenAPI del modulo. Default invariati:\n * UI `accessi/openapi`, JSON `accessi/openapi.json`.\n */\n openapi?: OpenApiSetupOptions;\n /** Logger Nest usato dal sotto-app Accessi. Se assente Nest usa il proprio logger. */\n logger?: LoggerService;\n /** Buffer dei log di bootstrap del sotto-app. Default `true` (comportamento storico). */\n bufferLogs?: boolean;\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 ConsoleEntryController,\n ServiceTokenController,\n SchemaController,\n AccessiIntrospectionController,\n ],\n providers: [AuthService, TwoFactorService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, AccessiDatabaseUpdater, FederatedAuthService, ServiceTokenService, ServiceTokenGuard, SchemaExportService, AdminBootstrapService],\n exports: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, FederatedAuthService, ServiceTokenService, ServiceTokenGuard, SchemaExportService, AdminBootstrapService],\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, SchemaExportService, AdminBootstrapService],\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, SchemaExportService, AdminBootstrapService],\n };\n }\n}\n"]}
@@ -9,6 +9,10 @@ export declare class AccessiRequestError extends Error {
9
9
  }
10
10
  /** Imposta il JWT usato da tutte le funzioni generate da Orval. */
11
11
  export declare function setAccessiConsoleToken(token: string | null): void;
12
+ /** Prefissa le chiamate relative del client generato (es. `https://accessi.example.com`). */
13
+ export declare function setAccessiFetchBaseUrl(url: string | null): void;
14
+ /** Token provider per client esterni alla console (server-to-server o frontend). */
15
+ export declare function setAccessiFetchTokenProvider(provider: (() => string | null | Promise<string | null>) | null): void;
12
16
  /**
13
17
  * Trasporto comune del client Orval: aggiunge il Bearer token e converte le
14
18
  * risposte di errore Accessi in Error JavaScript leggibili dalla console.