emilsoftware-utilities 2.0.0-dev.67 → 2.0.0-dev.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessi/resource-server/errors.d.ts +1 -1
- package/dist/accessi/resource-server/errors.js.map +1 -1
- package/dist/accessi/resource-server/express.js +21 -0
- package/dist/accessi/resource-server/express.js.map +1 -1
- package/dist/accessi/resource-server/nest.js +13 -0
- package/dist/accessi/resource-server/nest.js.map +1 -1
- package/dist/accessi/resource-server/runtime.js +11 -1
- package/dist/accessi/resource-server/runtime.js.map +1 -1
- package/dist/accessi/resource-server/types.d.ts +7 -0
- package/dist/accessi/resource-server/types.js.map +1 -1
- package/dist/accessi/server/index.d.ts +1 -0
- package/dist/accessi/server/index.js +1 -0
- package/dist/accessi/server/index.js.map +1 -1
- package/dist/accessi/server/standalone.d.ts +41 -0
- package/dist/accessi/server/standalone.js +264 -0
- package/dist/accessi/server/standalone.js.map +1 -0
- package/dist/accessi-module/AccessiModule.d.ts +53 -2
- package/dist/accessi-module/AccessiModule.js +5 -2
- package/dist/accessi-module/AccessiModule.js.map +1 -1
- package/dist/accessi-module/Console/accessiFetch.d.ts +5 -0
- package/dist/accessi-module/Console/accessiFetch.js +7 -4
- package/dist/accessi-module/Console/accessiFetch.js.map +1 -1
- package/dist/accessi-module/Console/console.js +21 -7
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.d.ts +31 -1
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.js +28 -3
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/exchangeFederatedIdentityRequest.d.ts +12 -0
- package/dist/accessi-module/Console/generated/model/exchangeFederatedIdentityRequest.js +9 -0
- package/dist/accessi-module/Console/generated/model/exchangeFederatedIdentityRequest.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/federatedAuthenticationResultDto.d.ts +15 -0
- package/dist/accessi-module/Console/generated/model/federatedAuthenticationResultDto.js +3 -0
- package/dist/accessi-module/Console/generated/model/federatedAuthenticationResultDto.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/federatedExchangeResponse.d.ts +14 -0
- package/dist/accessi-module/Console/generated/model/federatedExchangeResponse.js +3 -0
- package/dist/accessi-module/Console/generated/model/federatedExchangeResponse.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/index.d.ts +6 -0
- package/dist/accessi-module/Console/generated/model/index.js +6 -0
- package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/loginResult.d.ts +2 -0
- package/dist/accessi-module/Console/generated/model/loginResult.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/refreshTokenRequest.d.ts +10 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenRequest.js +9 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenRequest.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResponse.d.ts +14 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResponse.js +3 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResponse.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResult.d.ts +13 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResult.js +3 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResult.js.map +1 -0
- package/dist/accessi-module/Console/wiki.js +16 -3
- package/dist/accessi-module/Console/wiki.js.map +1 -1
- package/dist/accessi-module/Controllers/AccessiConsoleController.d.ts +6 -1
- package/dist/accessi-module/Controllers/AccessiConsoleController.js +24 -1
- package/dist/accessi-module/Controllers/AccessiConsoleController.js.map +1 -1
- package/dist/accessi-module/Controllers/AuthController.d.ts +3 -1
- package/dist/accessi-module/Controllers/AuthController.js +90 -8
- package/dist/accessi-module/Controllers/AuthController.js.map +1 -1
- package/dist/accessi-module/Controllers/ConsoleEntryController.d.ts +2 -0
- package/dist/accessi-module/Controllers/ConsoleEntryController.js +11 -3
- package/dist/accessi-module/Controllers/ConsoleEntryController.js.map +1 -1
- package/dist/accessi-module/Controllers/EmailController.js +1 -1
- package/dist/accessi-module/Controllers/EmailController.js.map +1 -1
- package/dist/accessi-module/Controllers/UserController.js +1 -1
- package/dist/accessi-module/Controllers/UserController.js.map +1 -1
- package/dist/accessi-module/Dtos/FederatedExchangeDtos.d.ts +21 -0
- package/dist/accessi-module/Dtos/FederatedExchangeDtos.js +74 -0
- package/dist/accessi-module/Dtos/FederatedExchangeDtos.js.map +1 -0
- package/dist/accessi-module/Dtos/LoginResponse.d.ts +1 -0
- package/dist/accessi-module/Dtos/LoginResponse.js +6 -0
- package/dist/accessi-module/Dtos/LoginResponse.js.map +1 -1
- package/dist/accessi-module/Dtos/RefreshTokenDtos.d.ts +12 -0
- package/dist/accessi-module/Dtos/RefreshTokenDtos.js +50 -0
- package/dist/accessi-module/Dtos/RefreshTokenDtos.js.map +1 -0
- package/dist/accessi-module/Dtos/index.d.ts +2 -0
- package/dist/accessi-module/Dtos/index.js +2 -0
- package/dist/accessi-module/Dtos/index.js.map +1 -1
- package/dist/accessi-module/Services/AuthService/AuthService.d.ts +14 -0
- package/dist/accessi-module/Services/AuthService/AuthService.js +99 -6
- package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
- package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js +8 -16
- package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js.map +1 -1
- package/dist/accessi-module/federated-auth/FederatedAuthExchangeController.d.ts +15 -0
- package/dist/accessi-module/federated-auth/FederatedAuthExchangeController.js +85 -0
- package/dist/accessi-module/federated-auth/FederatedAuthExchangeController.js.map +1 -0
- package/dist/accessi-module/federated-auth/FederatedAuthService.js +7 -1
- package/dist/accessi-module/federated-auth/FederatedAuthService.js.map +1 -1
- package/dist/accessi-module/index.d.ts +17 -1
- package/dist/accessi-module/index.js +71 -5
- package/dist/accessi-module/index.js.map +1 -1
- package/dist/accessi-module/jwt/jwt.strategy.js +4 -0
- package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
- package/dist/accessi-module/middleware/authenticateGen.js +4 -0
- package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
- package/dist/accessi-module/security/audit.d.ts +7 -0
- package/dist/accessi-module/security/audit.js +14 -0
- package/dist/accessi-module/security/audit.js.map +1 -0
- package/dist/accessi-module/security/authenticatedToken.d.ts +1 -1
- package/dist/accessi-module/security/authenticatedToken.js +3 -3
- package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
- package/dist/accessi-module/security/consoleEntry.d.ts +58 -11
- package/dist/accessi-module/security/consoleEntry.js +181 -31
- package/dist/accessi-module/security/consoleEntry.js.map +1 -1
- package/dist/accessi-module/security/edgeRateLimit.d.ts +33 -0
- package/dist/accessi-module/security/edgeRateLimit.js +81 -0
- package/dist/accessi-module/security/edgeRateLimit.js.map +1 -0
- package/dist/accessi-module/security/jwks.d.ts +33 -0
- package/dist/accessi-module/security/jwks.js +83 -0
- package/dist/accessi-module/security/jwks.js.map +1 -0
- package/dist/accessi-module/security/jwksBootstrap.d.ts +15 -0
- package/dist/accessi-module/security/jwksBootstrap.js +44 -0
- package/dist/accessi-module/security/jwksBootstrap.js.map +1 -0
- package/dist/accessi-module/security/jwtTokenOptions.d.ts +9 -2
- package/dist/accessi-module/security/jwtTokenOptions.js +18 -4
- package/dist/accessi-module/security/jwtTokenOptions.js.map +1 -1
- package/dist/accessi-module/security/passwordResetToken.d.ts +1 -1
- package/dist/accessi-module/security/passwordResetToken.js.map +1 -1
- package/dist/accessi-module/security/publicAuthRateLimit.d.ts +9 -7
- package/dist/accessi-module/security/publicAuthRateLimit.js +55 -78
- package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
- package/dist/accessi-module/security/rateLimitStore.d.ts +34 -0
- package/dist/accessi-module/security/rateLimitStore.js +145 -0
- package/dist/accessi-module/security/rateLimitStore.js.map +1 -0
- package/dist/accessi-module/security/refreshTokenRotation.d.ts +40 -0
- package/dist/accessi-module/security/refreshTokenRotation.js +91 -0
- package/dist/accessi-module/security/refreshTokenRotation.js.map +1 -0
- package/dist/accessi-module/security/serviceTokenGuard.d.ts +3 -1
- package/dist/accessi-module/security/serviceTokenGuard.js +11 -6
- package/dist/accessi-module/security/serviceTokenGuard.js.map +1 -1
- package/dist/accessi-module/security/serviceTokenRateLimit.d.ts +5 -4
- package/dist/accessi-module/security/serviceTokenRateLimit.js +33 -29
- package/dist/accessi-module/security/serviceTokenRateLimit.js.map +1 -1
- package/dist/accessi-module/security/sessionRevocation.d.ts +52 -0
- package/dist/accessi-module/security/sessionRevocation.js +124 -0
- package/dist/accessi-module/security/sessionRevocation.js.map +1 -0
- package/dist/accessi-module/security/validateOptions.d.ts +19 -0
- package/dist/accessi-module/security/validateOptions.js +115 -0
- package/dist/accessi-module/security/validateOptions.js.map +1 -0
- package/dist/emilsoftware-utilities-2.0.0-dev.69.tgz +0 -0
- package/dist/initEmilsoftwareModule.js +39 -3
- package/dist/initEmilsoftwareModule.js.map +1 -1
- package/dist/scripts/startAccessiService.d.ts +1 -0
- package/dist/scripts/startAccessiService.js +11 -0
- package/dist/scripts/startAccessiService.js.map +1 -0
- package/docs/accessi-openapi-fingerprint.json +190 -0
- package/docs/gateway-rate-limit.md +98 -0
- package/docs/standalone-service.md +176 -0
- package/integration-prompt.md +299 -8
- package/package.json +11 -5
- package/dist/emilsoftware-utilities-2.0.0-dev.67.tgz +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AccessiOptions } from '../AccessiModule';
|
|
2
|
+
/**
|
|
3
|
+
* Revoca delle sessioni per utente.
|
|
4
|
+
*
|
|
5
|
+
* La revoca e un timestamp: un token con `iat` precedente al cutoff viene
|
|
6
|
+
* rifiutato. I token emessi dopo il cutoff restano validi. La granularita di
|
|
7
|
+
* `iat` e in secondi, quindi un token emesso nello stesso secondo della revoca
|
|
8
|
+
* puo sopravvivere: e una finestra massima di 1 secondo.
|
|
9
|
+
*/
|
|
10
|
+
export interface SessionRevocationStore {
|
|
11
|
+
revokeUser(codiceUtente: number, revokedAtMs: number): Promise<void>;
|
|
12
|
+
getUserRevocation(codiceUtente: number): Promise<number | null>;
|
|
13
|
+
/** Health check opzionale per readiness del servizio. */
|
|
14
|
+
healthCheck?(): Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
export interface SessionRevocationOptions {
|
|
17
|
+
/** Default: disabilitata se non viene fornito uno store. */
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
/** Store condiviso (es. Redis) per invalidare le sessioni tra istanze. */
|
|
20
|
+
store?: SessionRevocationStore;
|
|
21
|
+
/** TTL delle chiavi Redis. Default: 365 giorni. */
|
|
22
|
+
ttlMs?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface MemorySessionRevocationStore extends SessionRevocationStore {
|
|
25
|
+
clear(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare function createMemorySessionRevocationStore(): MemorySessionRevocationStore;
|
|
28
|
+
export interface SessionRevocationRedisClient {
|
|
29
|
+
eval(script: string, numKeys: number, ...args: Array<string | number>): Promise<unknown>;
|
|
30
|
+
}
|
|
31
|
+
export interface RedisSessionRevocationStoreOptions {
|
|
32
|
+
client: SessionRevocationRedisClient;
|
|
33
|
+
/** Default: `accessi:revoked-user:`. */
|
|
34
|
+
keyPrefix?: string;
|
|
35
|
+
/** Default: 365 giorni. */
|
|
36
|
+
ttlMs?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Store Redis per la revoca sessioni.
|
|
40
|
+
*
|
|
41
|
+
* `revokeUser` scrive un timestamp con TTL; `getUserRevocation` lo legge.
|
|
42
|
+
* Il TTL deve essere maggiore della durata massima dei token.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createRedisSessionRevocationStore(options: RedisSessionRevocationStoreOptions): SessionRevocationStore;
|
|
45
|
+
/** Store di default in memoria, usato quando `sessionRevocation.store` non e configurato ma la revoca e abilitata. */
|
|
46
|
+
export declare function getSessionRevocationStore(options: AccessiOptions): SessionRevocationStore | undefined;
|
|
47
|
+
/** True se il token e stato emesso prima dell'ultima revoca sessioni dell'utente. */
|
|
48
|
+
export declare function isAccessiTokenRevoked(options: AccessiOptions, payload: Record<string, unknown>, codiceUtente: number): Promise<boolean>;
|
|
49
|
+
/** Revoca tutte le sessioni dell'utente. Richiede uno store configurato. */
|
|
50
|
+
export declare function revokeAccessiUserSessions(options: AccessiOptions, codiceUtente: number, revokedAtMs?: number): Promise<void>;
|
|
51
|
+
/** Solo per test: azzera lo store in memoria di default. */
|
|
52
|
+
export declare function clearDefaultSessionRevocations(): void;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createMemorySessionRevocationStore = createMemorySessionRevocationStore;
|
|
13
|
+
exports.createRedisSessionRevocationStore = createRedisSessionRevocationStore;
|
|
14
|
+
exports.getSessionRevocationStore = getSessionRevocationStore;
|
|
15
|
+
exports.isAccessiTokenRevoked = isAccessiTokenRevoked;
|
|
16
|
+
exports.revokeAccessiUserSessions = revokeAccessiUserSessions;
|
|
17
|
+
exports.clearDefaultSessionRevocations = clearDefaultSessionRevocations;
|
|
18
|
+
const REVOKE_USER_SCRIPT = "if tonumber(ARGV[2]) > 0 then return redis.call('SET', KEYS[1], ARGV[1], 'PX', ARGV[2]) else return redis.call('SET', KEYS[1], ARGV[1]) end";
|
|
19
|
+
const GET_USER_SCRIPT = "return redis.call('GET', KEYS[1])";
|
|
20
|
+
function createMemorySessionRevocationStore() {
|
|
21
|
+
const revokedAt = new Map();
|
|
22
|
+
return {
|
|
23
|
+
revokeUser(codiceUtente, timestamp) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
revokedAt.set(codiceUtente, timestamp);
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
getUserRevocation(codiceUtente) {
|
|
29
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
var _a;
|
|
31
|
+
return (_a = revokedAt.get(codiceUtente)) !== null && _a !== void 0 ? _a : null;
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
healthCheck() {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
return true;
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
clear() {
|
|
40
|
+
revokedAt.clear();
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Store Redis per la revoca sessioni.
|
|
46
|
+
*
|
|
47
|
+
* `revokeUser` scrive un timestamp con TTL; `getUserRevocation` lo legge.
|
|
48
|
+
* Il TTL deve essere maggiore della durata massima dei token.
|
|
49
|
+
*/
|
|
50
|
+
function createRedisSessionRevocationStore(options) {
|
|
51
|
+
var _a, _b;
|
|
52
|
+
if (!(options === null || options === void 0 ? void 0 : options.client) || typeof options.client.eval !== 'function') {
|
|
53
|
+
throw new Error('Redis session revocation store: client.eval non configurato.');
|
|
54
|
+
}
|
|
55
|
+
const keyPrefix = ((_a = options.keyPrefix) !== null && _a !== void 0 ? _a : 'accessi:revoked-user:').replace(/:+$/, ':');
|
|
56
|
+
const ttlMs = Math.max(0, Math.trunc((_b = options.ttlMs) !== null && _b !== void 0 ? _b : 365 * 24 * 60 * 60 * 1000));
|
|
57
|
+
return {
|
|
58
|
+
revokeUser(codiceUtente, revokedAtMs) {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
yield options.client.eval(REVOKE_USER_SCRIPT, 1, `${keyPrefix}${codiceUtente}`, String(revokedAtMs), ttlMs);
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
getUserRevocation(codiceUtente) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
const value = yield options.client.eval(GET_USER_SCRIPT, 1, `${keyPrefix}${codiceUtente}`);
|
|
66
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
67
|
+
return null;
|
|
68
|
+
const timestamp = Number(value);
|
|
69
|
+
return Number.isFinite(timestamp) ? timestamp : null;
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
healthCheck() {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
try {
|
|
75
|
+
const result = yield options.client.eval("return redis.call('PING')", 0);
|
|
76
|
+
return String(result).toUpperCase() === 'PONG';
|
|
77
|
+
}
|
|
78
|
+
catch (_a) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const defaultMemoryStore = createMemorySessionRevocationStore();
|
|
86
|
+
/** Store di default in memoria, usato quando `sessionRevocation.store` non e configurato ma la revoca e abilitata. */
|
|
87
|
+
function getSessionRevocationStore(options) {
|
|
88
|
+
var _a, _b, _c;
|
|
89
|
+
if (((_a = options.sessionRevocation) === null || _a === void 0 ? void 0 : _a.enabled) === false)
|
|
90
|
+
return undefined;
|
|
91
|
+
if ((_b = options.sessionRevocation) === null || _b === void 0 ? void 0 : _b.store)
|
|
92
|
+
return options.sessionRevocation.store;
|
|
93
|
+
return ((_c = options.sessionRevocation) === null || _c === void 0 ? void 0 : _c.enabled) === true ? defaultMemoryStore : undefined;
|
|
94
|
+
}
|
|
95
|
+
/** True se il token e stato emesso prima dell'ultima revoca sessioni dell'utente. */
|
|
96
|
+
function isAccessiTokenRevoked(options, payload, codiceUtente) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
const store = getSessionRevocationStore(options);
|
|
99
|
+
if (!store)
|
|
100
|
+
return false;
|
|
101
|
+
const issuedAt = Number(payload.iat);
|
|
102
|
+
if (!Number.isFinite(issuedAt))
|
|
103
|
+
return true;
|
|
104
|
+
const revokedAt = yield store.getUserRevocation(codiceUtente);
|
|
105
|
+
if (revokedAt === null)
|
|
106
|
+
return false;
|
|
107
|
+
return issuedAt < Math.floor(revokedAt / 1000);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/** Revoca tutte le sessioni dell'utente. Richiede uno store configurato. */
|
|
111
|
+
function revokeAccessiUserSessions(options_1, codiceUtente_1) {
|
|
112
|
+
return __awaiter(this, arguments, void 0, function* (options, codiceUtente, revokedAtMs = Date.now()) {
|
|
113
|
+
const store = getSessionRevocationStore(options);
|
|
114
|
+
if (!store) {
|
|
115
|
+
throw new Error('Session revocation store non configurato.');
|
|
116
|
+
}
|
|
117
|
+
yield store.revokeUser(codiceUtente, revokedAtMs);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/** Solo per test: azzera lo store in memoria di default. */
|
|
121
|
+
function clearDefaultSessionRevocations() {
|
|
122
|
+
defaultMemoryStore.clear();
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=sessionRevocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionRevocation.js","sourceRoot":"","sources":["../../../src/accessi-module/security/sessionRevocation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccessiOptions } from '../AccessiModule';\n\n/**\n * Revoca delle sessioni per utente.\n *\n * La revoca e un timestamp: un token con `iat` precedente al cutoff viene\n * rifiutato. I token emessi dopo il cutoff restano validi. La granularita di\n * `iat` e in secondi, quindi un token emesso nello stesso secondo della revoca\n * puo sopravvivere: e una finestra massima di 1 secondo.\n */\nexport interface SessionRevocationStore {\n revokeUser(codiceUtente: number, revokedAtMs: number): Promise<void>;\n getUserRevocation(codiceUtente: number): Promise<number | null>;\n /** Health check opzionale per readiness del servizio. */\n healthCheck?(): Promise<boolean>;\n}\n\nexport interface SessionRevocationOptions {\n /** Default: disabilitata se non viene fornito uno store. */\n enabled?: boolean;\n /** Store condiviso (es. Redis) per invalidare le sessioni tra istanze. */\n store?: SessionRevocationStore;\n /** TTL delle chiavi Redis. Default: 365 giorni. */\n ttlMs?: number;\n}\n\nexport interface MemorySessionRevocationStore extends SessionRevocationStore {\n clear(): void;\n}\n\nconst REVOKE_USER_SCRIPT =\n \"if tonumber(ARGV[2]) > 0 then return redis.call('SET', KEYS[1], ARGV[1], 'PX', ARGV[2]) else return redis.call('SET', KEYS[1], ARGV[1]) end\";\nconst GET_USER_SCRIPT = \"return redis.call('GET', KEYS[1])\";\n\nexport function createMemorySessionRevocationStore(): MemorySessionRevocationStore {\n const revokedAt = new Map<number, number>();\n return {\n async revokeUser(codiceUtente, timestamp) {\n revokedAt.set(codiceUtente, timestamp);\n },\n async getUserRevocation(codiceUtente) {\n return revokedAt.get(codiceUtente) ?? null;\n },\n async healthCheck() {\n return true;\n },\n clear() {\n revokedAt.clear();\n },\n };\n}\n\nexport interface SessionRevocationRedisClient {\n eval(script: string, numKeys: number, ...args: Array<string | number>): Promise<unknown>;\n}\n\nexport interface RedisSessionRevocationStoreOptions {\n client: SessionRevocationRedisClient;\n /** Default: `accessi:revoked-user:`. */\n keyPrefix?: string;\n /** Default: 365 giorni. */\n ttlMs?: number;\n}\n\n/**\n * Store Redis per la revoca sessioni.\n *\n * `revokeUser` scrive un timestamp con TTL; `getUserRevocation` lo legge.\n * Il TTL deve essere maggiore della durata massima dei token.\n */\nexport function createRedisSessionRevocationStore(\n options: RedisSessionRevocationStoreOptions,\n): SessionRevocationStore {\n if (!options?.client || typeof options.client.eval !== 'function') {\n throw new Error('Redis session revocation store: client.eval non configurato.');\n }\n\n const keyPrefix = (options.keyPrefix ?? 'accessi:revoked-user:').replace(/:+$/, ':');\n const ttlMs = Math.max(0, Math.trunc(options.ttlMs ?? 365 * 24 * 60 * 60 * 1000));\n\n return {\n async revokeUser(codiceUtente, revokedAtMs) {\n await options.client.eval(\n REVOKE_USER_SCRIPT,\n 1,\n `${keyPrefix}${codiceUtente}`,\n String(revokedAtMs),\n ttlMs,\n );\n },\n\n async getUserRevocation(codiceUtente) {\n const value = await options.client.eval(\n GET_USER_SCRIPT,\n 1,\n `${keyPrefix}${codiceUtente}`,\n );\n if (typeof value !== 'string' && typeof value !== 'number') return null;\n const timestamp = Number(value);\n return Number.isFinite(timestamp) ? timestamp : null;\n },\n\n async healthCheck() {\n try {\n const result = await options.client.eval(\"return redis.call('PING')\", 0);\n return String(result).toUpperCase() === 'PONG';\n } catch {\n return false;\n }\n },\n };\n}\n\nconst defaultMemoryStore = createMemorySessionRevocationStore();\n\n/** Store di default in memoria, usato quando `sessionRevocation.store` non e configurato ma la revoca e abilitata. */\nexport function getSessionRevocationStore(options: AccessiOptions): SessionRevocationStore | undefined {\n if (options.sessionRevocation?.enabled === false) return undefined;\n if (options.sessionRevocation?.store) return options.sessionRevocation.store;\n return options.sessionRevocation?.enabled === true ? defaultMemoryStore : undefined;\n}\n\n/** True se il token e stato emesso prima dell'ultima revoca sessioni dell'utente. */\nexport async function isAccessiTokenRevoked(\n options: AccessiOptions,\n payload: Record<string, unknown>,\n codiceUtente: number,\n): Promise<boolean> {\n const store = getSessionRevocationStore(options);\n if (!store) return false;\n\n const issuedAt = Number(payload.iat);\n if (!Number.isFinite(issuedAt)) return true;\n\n const revokedAt = await store.getUserRevocation(codiceUtente);\n if (revokedAt === null) return false;\n\n return issuedAt < Math.floor(revokedAt / 1000);\n}\n\n/** Revoca tutte le sessioni dell'utente. Richiede uno store configurato. */\nexport async function revokeAccessiUserSessions(\n options: AccessiOptions,\n codiceUtente: number,\n revokedAtMs: number = Date.now(),\n): Promise<void> {\n const store = getSessionRevocationStore(options);\n if (!store) {\n throw new Error('Session revocation store non configurato.');\n }\n await store.revokeUser(codiceUtente, revokedAtMs);\n}\n\n/** Solo per test: azzera lo store in memoria di default. */\nexport function clearDefaultSessionRevocations(): void {\n defaultMemoryStore.clear();\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AccessiOptions } from '../AccessiModule';
|
|
2
|
+
export interface AccessiOptionsValidationIssue {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface AccessiOptionsValidationResult {
|
|
7
|
+
errors: AccessiOptionsValidationIssue[];
|
|
8
|
+
warnings: AccessiOptionsValidationIssue[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Validazione fail-fast della configurazione Accessi.
|
|
12
|
+
*
|
|
13
|
+
* `createAccessiService` usa `assertValidAccessiOptions`; i bootstrap esistenti
|
|
14
|
+
* possono usare `validateAccessiOptions` per loggare warning senza rompere il
|
|
15
|
+
* comportamento storico.
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateAccessiOptions(options: AccessiOptions): AccessiOptionsValidationResult;
|
|
18
|
+
/** Lancia un errore aggregato se la configurazione non e valida. */
|
|
19
|
+
export declare function assertValidAccessiOptions(options: AccessiOptions): void;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateAccessiOptions = validateAccessiOptions;
|
|
4
|
+
exports.assertValidAccessiOptions = assertValidAccessiOptions;
|
|
5
|
+
function isHttpUrl(value) {
|
|
6
|
+
if (!value)
|
|
7
|
+
return false;
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(value);
|
|
10
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
11
|
+
}
|
|
12
|
+
catch (_a) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function positive(value) {
|
|
17
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validazione fail-fast della configurazione Accessi.
|
|
21
|
+
*
|
|
22
|
+
* `createAccessiService` usa `assertValidAccessiOptions`; i bootstrap esistenti
|
|
23
|
+
* possono usare `validateAccessiOptions` per loggare warning senza rompere il
|
|
24
|
+
* comportamento storico.
|
|
25
|
+
*/
|
|
26
|
+
function validateAccessiOptions(options) {
|
|
27
|
+
var _a, _b, _c, _d;
|
|
28
|
+
const errors = [];
|
|
29
|
+
const warnings = [];
|
|
30
|
+
const addError = (code, message) => errors.push({ code, message });
|
|
31
|
+
const addWarning = (code, message) => warnings.push({ code, message });
|
|
32
|
+
if (!(options === null || options === void 0 ? void 0 : options.databaseOptions)) {
|
|
33
|
+
addError('ACCESSI_DB_OPTIONS_MISSING', 'databaseOptions e obbligatorio.');
|
|
34
|
+
}
|
|
35
|
+
const jwt = options === null || options === void 0 ? void 0 : options.jwtOptions;
|
|
36
|
+
const secret = (jwt === null || jwt === void 0 ? void 0 : jwt.secret) || process.env.ACC_JWT_SECRET;
|
|
37
|
+
if (!secret) {
|
|
38
|
+
addError('ACCESSI_JWT_SECRET_MISSING', 'jwtOptions.secret e obbligatorio.');
|
|
39
|
+
}
|
|
40
|
+
else if (secret.length < 32) {
|
|
41
|
+
addWarning('ACCESSI_JWT_SECRET_WEAK', 'jwtOptions.secret dovrebbe avere almeno 32 caratteri.');
|
|
42
|
+
}
|
|
43
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.expiresIn)) {
|
|
44
|
+
addError('ACCESSI_JWT_EXPIRES_MISSING', 'jwtOptions.expiresIn e obbligatorio.');
|
|
45
|
+
}
|
|
46
|
+
const algorithm = (_a = jwt === null || jwt === void 0 ? void 0 : jwt.algorithm) !== null && _a !== void 0 ? _a : 'HS256';
|
|
47
|
+
if (algorithm.startsWith('HS')) {
|
|
48
|
+
if ((jwt === null || jwt === void 0 ? void 0 : jwt.privateKey) || (jwt === null || jwt === void 0 ? void 0 : jwt.publicKey)) {
|
|
49
|
+
addWarning('ACCESSI_JWT_ASYMMETRIC_KEYS_WITH_HMAC', 'Sono configurate chiavi asimmetriche ma algorithm e HS256: verranno ignorate.');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.privateKey)) {
|
|
54
|
+
addError('ACCESSI_JWT_PRIVATE_KEY_MISSING', `jwtOptions.privateKey e obbligatoria per ${algorithm}.`);
|
|
55
|
+
}
|
|
56
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.publicKey) && !(jwt === null || jwt === void 0 ? void 0 : jwt.privateKey)) {
|
|
57
|
+
addError('ACCESSI_JWT_PUBLIC_KEY_MISSING', `jwtOptions.publicKey e obbligatoria per ${algorithm}.`);
|
|
58
|
+
}
|
|
59
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.keyId)) {
|
|
60
|
+
addWarning('ACCESSI_JWT_KEY_ID_MISSING', 'jwtOptions.keyId e consigliato per la rotazione JWKS.');
|
|
61
|
+
}
|
|
62
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.jwksPath)) {
|
|
63
|
+
addWarning('ACCESSI_JWKS_PATH_DEFAULT', 'jwksPath non configurato: verra usato accessi/.well-known/jwks.json.');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.issuer)) {
|
|
67
|
+
addWarning('ACCESSI_JWT_ISSUER_MISSING', 'jwtOptions.issuer e consigliato in multi-servizio.');
|
|
68
|
+
}
|
|
69
|
+
if (!(jwt === null || jwt === void 0 ? void 0 : jwt.audience)) {
|
|
70
|
+
addWarning('ACCESSI_JWT_AUDIENCE_MISSING', 'jwtOptions.audience e consigliato in multi-servizio.');
|
|
71
|
+
}
|
|
72
|
+
if (!(options === null || options === void 0 ? void 0 : options.encryptionKey)) {
|
|
73
|
+
addError('ACCESSI_ENCRYPTION_KEY_MISSING', 'encryptionKey e obbligatoria.');
|
|
74
|
+
}
|
|
75
|
+
else if (options.encryptionKey.length < 16) {
|
|
76
|
+
addWarning('ACCESSI_ENCRYPTION_KEY_WEAK', 'encryptionKey dovrebbe avere almeno 16 caratteri.');
|
|
77
|
+
}
|
|
78
|
+
if (!isHttpUrl(options === null || options === void 0 ? void 0 : options.confirmationEmailUrl)) {
|
|
79
|
+
addWarning('ACCESSI_CONFIRMATION_URL_INVALID', 'confirmationEmailUrl dovrebbe essere un URL http/https.');
|
|
80
|
+
}
|
|
81
|
+
if (!isHttpUrl(options === null || options === void 0 ? void 0 : options.confirmationEmailReturnUrl)) {
|
|
82
|
+
addWarning('ACCESSI_CONFIRMATION_RETURN_URL_INVALID', 'confirmationEmailReturnUrl dovrebbe essere un URL http/https.');
|
|
83
|
+
}
|
|
84
|
+
if ((options === null || options === void 0 ? void 0 : options.publicBaseUrl) && !isHttpUrl(options.publicBaseUrl)) {
|
|
85
|
+
addWarning('ACCESSI_PUBLIC_BASE_URL_INVALID', 'publicBaseUrl dovrebbe essere un URL http/https.');
|
|
86
|
+
}
|
|
87
|
+
if (((_b = options === null || options === void 0 ? void 0 : options.publicAuthRateLimit) === null || _b === void 0 ? void 0 : _b.login) && !positive(options.publicAuthRateLimit.login.windowMs)) {
|
|
88
|
+
addError('ACCESSI_RATE_LIMIT_WINDOW_INVALID', 'publicAuthRateLimit.login.windowMs deve essere positivo.');
|
|
89
|
+
}
|
|
90
|
+
if (((_c = options === null || options === void 0 ? void 0 : options.publicAuthRateLimit) === null || _c === void 0 ? void 0 : _c.login) && !positive(options.publicAuthRateLimit.login.maxAttempts)) {
|
|
91
|
+
addError('ACCESSI_RATE_LIMIT_ATTEMPTS_INVALID', 'publicAuthRateLimit.login.maxAttempts deve essere positivo.');
|
|
92
|
+
}
|
|
93
|
+
if (options === null || options === void 0 ? void 0 : options.edgeRateLimit) {
|
|
94
|
+
if (options.edgeRateLimit.windowMs !== undefined && !positive(options.edgeRateLimit.windowMs)) {
|
|
95
|
+
addError('ACCESSI_EDGE_RATE_LIMIT_WINDOW_INVALID', 'edgeRateLimit.windowMs deve essere positivo.');
|
|
96
|
+
}
|
|
97
|
+
if (options.edgeRateLimit.maxAttempts !== undefined && !positive(options.edgeRateLimit.maxAttempts)) {
|
|
98
|
+
addError('ACCESSI_EDGE_RATE_LIMIT_ATTEMPTS_INVALID', 'edgeRateLimit.maxAttempts deve essere positivo.');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (((_d = options === null || options === void 0 ? void 0 : options.consoleEntry) === null || _d === void 0 ? void 0 : _d.ttlMs) !== undefined && !positive(options.consoleEntry.ttlMs)) {
|
|
102
|
+
addError('ACCESSI_CONSOLE_ENTRY_TTL_INVALID', 'consoleEntry.ttlMs deve essere positivo.');
|
|
103
|
+
}
|
|
104
|
+
return { errors, warnings };
|
|
105
|
+
}
|
|
106
|
+
/** Lancia un errore aggregato se la configurazione non e valida. */
|
|
107
|
+
function assertValidAccessiOptions(options) {
|
|
108
|
+
const result = validateAccessiOptions(options);
|
|
109
|
+
if (result.errors.length === 0)
|
|
110
|
+
return;
|
|
111
|
+
throw new Error(`Configurazione Accessi non valida:\n${result.errors
|
|
112
|
+
.map((issue) => `- ${issue.code}: ${issue.message}`)
|
|
113
|
+
.join('\n')}`);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=validateOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateOptions.js","sourceRoot":"","sources":["../../../src/accessi-module/security/validateOptions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccessiOptions } from '../AccessiModule';\n\nexport interface AccessiOptionsValidationIssue {\n code: string;\n message: string;\n}\n\nexport interface AccessiOptionsValidationResult {\n errors: AccessiOptionsValidationIssue[];\n warnings: AccessiOptionsValidationIssue[];\n}\n\nfunction isHttpUrl(value: string | undefined): boolean {\n if (!value) return false;\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction positive(value: number | undefined): boolean {\n return typeof value === 'number' && Number.isFinite(value) && value > 0;\n}\n\n/**\n * Validazione fail-fast della configurazione Accessi.\n *\n * `createAccessiService` usa `assertValidAccessiOptions`; i bootstrap esistenti\n * possono usare `validateAccessiOptions` per loggare warning senza rompere il\n * comportamento storico.\n */\nexport function validateAccessiOptions(options: AccessiOptions): AccessiOptionsValidationResult {\n const errors: AccessiOptionsValidationIssue[] = [];\n const warnings: AccessiOptionsValidationIssue[] = [];\n\n const addError = (code: string, message: string) => errors.push({ code, message });\n const addWarning = (code: string, message: string) => warnings.push({ code, message });\n\n if (!options?.databaseOptions) {\n addError('ACCESSI_DB_OPTIONS_MISSING', 'databaseOptions e obbligatorio.');\n }\n\n const jwt = options?.jwtOptions;\n const secret = jwt?.secret || process.env.ACC_JWT_SECRET;\n if (!secret) {\n addError('ACCESSI_JWT_SECRET_MISSING', 'jwtOptions.secret e obbligatorio.');\n } else if (secret.length < 32) {\n addWarning('ACCESSI_JWT_SECRET_WEAK', 'jwtOptions.secret dovrebbe avere almeno 32 caratteri.');\n }\n\n if (!jwt?.expiresIn) {\n addError('ACCESSI_JWT_EXPIRES_MISSING', 'jwtOptions.expiresIn e obbligatorio.');\n }\n\n const algorithm = jwt?.algorithm ?? 'HS256';\n if (algorithm.startsWith('HS')) {\n if (jwt?.privateKey || jwt?.publicKey) {\n addWarning(\n 'ACCESSI_JWT_ASYMMETRIC_KEYS_WITH_HMAC',\n 'Sono configurate chiavi asimmetriche ma algorithm e HS256: verranno ignorate.',\n );\n }\n } else {\n if (!jwt?.privateKey) {\n addError('ACCESSI_JWT_PRIVATE_KEY_MISSING', `jwtOptions.privateKey e obbligatoria per ${algorithm}.`);\n }\n if (!jwt?.publicKey && !jwt?.privateKey) {\n addError('ACCESSI_JWT_PUBLIC_KEY_MISSING', `jwtOptions.publicKey e obbligatoria per ${algorithm}.`);\n }\n if (!jwt?.keyId) {\n addWarning('ACCESSI_JWT_KEY_ID_MISSING', 'jwtOptions.keyId e consigliato per la rotazione JWKS.');\n }\n if (!jwt?.jwksPath) {\n addWarning(\n 'ACCESSI_JWKS_PATH_DEFAULT',\n 'jwksPath non configurato: verra usato accessi/.well-known/jwks.json.',\n );\n }\n }\n\n if (!jwt?.issuer) {\n addWarning('ACCESSI_JWT_ISSUER_MISSING', 'jwtOptions.issuer e consigliato in multi-servizio.');\n }\n if (!jwt?.audience) {\n addWarning('ACCESSI_JWT_AUDIENCE_MISSING', 'jwtOptions.audience e consigliato in multi-servizio.');\n }\n\n if (!options?.encryptionKey) {\n addError('ACCESSI_ENCRYPTION_KEY_MISSING', 'encryptionKey e obbligatoria.');\n } else if (options.encryptionKey.length < 16) {\n addWarning('ACCESSI_ENCRYPTION_KEY_WEAK', 'encryptionKey dovrebbe avere almeno 16 caratteri.');\n }\n\n if (!isHttpUrl(options?.confirmationEmailUrl)) {\n addWarning('ACCESSI_CONFIRMATION_URL_INVALID', 'confirmationEmailUrl dovrebbe essere un URL http/https.');\n }\n if (!isHttpUrl(options?.confirmationEmailReturnUrl)) {\n addWarning('ACCESSI_CONFIRMATION_RETURN_URL_INVALID', 'confirmationEmailReturnUrl dovrebbe essere un URL http/https.');\n }\n if (options?.publicBaseUrl && !isHttpUrl(options.publicBaseUrl)) {\n addWarning('ACCESSI_PUBLIC_BASE_URL_INVALID', 'publicBaseUrl dovrebbe essere un URL http/https.');\n }\n\n if (options?.publicAuthRateLimit?.login && !positive(options.publicAuthRateLimit.login.windowMs)) {\n addError('ACCESSI_RATE_LIMIT_WINDOW_INVALID', 'publicAuthRateLimit.login.windowMs deve essere positivo.');\n }\n if (options?.publicAuthRateLimit?.login && !positive(options.publicAuthRateLimit.login.maxAttempts)) {\n addError('ACCESSI_RATE_LIMIT_ATTEMPTS_INVALID', 'publicAuthRateLimit.login.maxAttempts deve essere positivo.');\n }\n if (options?.edgeRateLimit) {\n if (options.edgeRateLimit.windowMs !== undefined && !positive(options.edgeRateLimit.windowMs)) {\n addError('ACCESSI_EDGE_RATE_LIMIT_WINDOW_INVALID', 'edgeRateLimit.windowMs deve essere positivo.');\n }\n if (options.edgeRateLimit.maxAttempts !== undefined && !positive(options.edgeRateLimit.maxAttempts)) {\n addError('ACCESSI_EDGE_RATE_LIMIT_ATTEMPTS_INVALID', 'edgeRateLimit.maxAttempts deve essere positivo.');\n }\n }\n if (options?.consoleEntry?.ttlMs !== undefined && !positive(options.consoleEntry.ttlMs)) {\n addError('ACCESSI_CONSOLE_ENTRY_TTL_INVALID', 'consoleEntry.ttlMs deve essere positivo.');\n }\n\n return { errors, warnings };\n}\n\n/** Lancia un errore aggregato se la configurazione non e valida. */\nexport function assertValidAccessiOptions(options: AccessiOptions): void {\n const result = validateAccessiOptions(options);\n if (result.errors.length === 0) return;\n throw new Error(\n `Configurazione Accessi non valida:\\n${result.errors\n .map((issue) => `- ${issue.code}: ${issue.message}`)\n .join('\\n')}`,\n );\n}\n"]}
|
|
Binary file
|
|
@@ -24,6 +24,8 @@ const accessiRuntime_1 = require("./accessi-module/accessiRuntime");
|
|
|
24
24
|
const startupLog_1 = require("./accessi-module/startupLog");
|
|
25
25
|
const accessiValidation_1 = require("./accessi-module/security/accessiValidation");
|
|
26
26
|
const AccessiHttpExceptionFilter_1 = require("./accessi-module/security/AccessiHttpExceptionFilter");
|
|
27
|
+
const jwks_1 = require("./accessi-module/security/jwks");
|
|
28
|
+
const edgeRateLimit_1 = require("./accessi-module/security/edgeRateLimit");
|
|
27
29
|
/**
|
|
28
30
|
* Initializes the unified module that combines Accessi and Allegati functionality
|
|
29
31
|
* @param app Express application instance
|
|
@@ -32,7 +34,7 @@ const AccessiHttpExceptionFilter_1 = require("./accessi-module/security/AccessiH
|
|
|
32
34
|
*/
|
|
33
35
|
function initEmilsoftwareModule(app, options) {
|
|
34
36
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
var _a;
|
|
37
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
36
38
|
const logger = new Logger_1.Logger(initEmilsoftwareModule.name);
|
|
37
39
|
if (options === null || options === void 0 ? void 0 : options.accessiOptions) {
|
|
38
40
|
(0, authenticateGen_1.beginAccessiAuthInitialization)();
|
|
@@ -46,18 +48,52 @@ function initEmilsoftwareModule(app, options) {
|
|
|
46
48
|
// Precedenza: EmilsoftwareOptions.openapi > AccessiOptions.openapi > default.
|
|
47
49
|
const resolvedOpenApi = (0, OpenApiConfig_1.resolveAccessiOpenApiOptions)((_a = options === null || options === void 0 ? void 0 : options.accessiOptions) === null || _a === void 0 ? void 0 : _a.openapi, options === null || options === void 0 ? void 0 : options.openapi);
|
|
48
50
|
const nestHostApp = (0, express_1.default)();
|
|
51
|
+
if (((_c = (_b = options === null || options === void 0 ? void 0 : options.accessiOptions) === null || _b === void 0 ? void 0 : _b.http) === null || _c === void 0 ? void 0 : _c.trustProxy) !== undefined) {
|
|
52
|
+
app.set('trust proxy', options.accessiOptions.http.trustProxy);
|
|
53
|
+
nestHostApp.set('trust proxy', options.accessiOptions.http.trustProxy);
|
|
54
|
+
}
|
|
55
|
+
const jwksPath = (options === null || options === void 0 ? void 0 : options.accessiOptions)
|
|
56
|
+
? (0, jwks_1.getAccessiJwksPath)(options.accessiOptions)
|
|
57
|
+
: undefined;
|
|
49
58
|
const isNestRoute = (path) => path === "/api" ||
|
|
50
59
|
path.startsWith("/api/") ||
|
|
51
|
-
(0, OpenApiConfig_1.isOpenApiRequestPath)(path, resolvedOpenApi)
|
|
60
|
+
(0, OpenApiConfig_1.isOpenApiRequestPath)(path, resolvedOpenApi) ||
|
|
61
|
+
(jwksPath !== undefined && path === jwksPath);
|
|
62
|
+
const edgeRateLimit = ((_d = options === null || options === void 0 ? void 0 : options.accessiOptions) === null || _d === void 0 ? void 0 : _d.edgeRateLimit)
|
|
63
|
+
? (0, edgeRateLimit_1.createAccessiEdgeRateLimitMiddleware)(Object.assign(Object.assign({}, options.accessiOptions.edgeRateLimit), { match: (_e = options.accessiOptions.edgeRateLimit.match) !== null && _e !== void 0 ? _e : ((path) => isNestRoute(path)) }))
|
|
64
|
+
: undefined;
|
|
65
|
+
if (edgeRateLimit) {
|
|
66
|
+
app.use(edgeRateLimit);
|
|
67
|
+
}
|
|
68
|
+
if (((_g = (_f = options === null || options === void 0 ? void 0 : options.accessiOptions) === null || _f === void 0 ? void 0 : _f.http) === null || _g === void 0 ? void 0 : _g.securityHeaders) !== false) {
|
|
69
|
+
app.use((req, res, next) => {
|
|
70
|
+
if (!isNestRoute(req.path)) {
|
|
71
|
+
return next();
|
|
72
|
+
}
|
|
73
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
74
|
+
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
|
|
75
|
+
res.setHeader('Referrer-Policy', 'no-referrer');
|
|
76
|
+
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
|
|
77
|
+
return next();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
52
80
|
app.use((req, res, next) => {
|
|
53
81
|
if (!isNestRoute(req.path)) {
|
|
54
82
|
return next();
|
|
55
83
|
}
|
|
56
84
|
return nestHostApp(req, res, next);
|
|
57
85
|
});
|
|
86
|
+
if (options === null || options === void 0 ? void 0 : options.accessiOptions) {
|
|
87
|
+
(0, jwks_1.setupAccessiJwks)(app, options.accessiOptions);
|
|
88
|
+
if (jwksPath) {
|
|
89
|
+
logger.info(`JWKS accessi disponibile su: ${jwksPath}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
58
92
|
const nestExpressInstance = new platform_express_1.ExpressAdapter(nestHostApp);
|
|
59
93
|
const nestApp = yield core_1.NestFactory.create(EmilsoftwareModule_1.EmilsoftwareModule.forRoot(options), nestExpressInstance, Object.assign({ bufferLogs: (options === null || options === void 0 ? void 0 : options.bufferLogs) !== false }, ((options === null || options === void 0 ? void 0 : options.logger) ? { logger: options.logger } : {})));
|
|
60
|
-
|
|
94
|
+
if (((_j = (_h = options === null || options === void 0 ? void 0 : options.accessiOptions) === null || _h === void 0 ? void 0 : _h.http) === null || _j === void 0 ? void 0 : _j.cors) !== false) {
|
|
95
|
+
nestApp.enableCors((_l = (_k = options === null || options === void 0 ? void 0 : options.accessiOptions) === null || _k === void 0 ? void 0 : _k.http) === null || _l === void 0 ? void 0 : _l.cors);
|
|
96
|
+
}
|
|
61
97
|
if (options === null || options === void 0 ? void 0 : options.accessiOptions) {
|
|
62
98
|
// Keep the Accessi API contract identical for standalone and unified bootstraps.
|
|
63
99
|
nestApp.useGlobalPipes((0, accessiValidation_1.createAccessiValidationPipe)());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initEmilsoftwareModule.js","sourceRoot":"","sources":["../src/initEmilsoftwareModule.ts"],"names":[],"mappings":"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","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport type { INestApplication } from \"@nestjs/common\";\nimport type { OpenAPIObject } from \"@nestjs/swagger\";\nimport {\n buildOpenApiExcludePaths,\n isOpenApiRequestPath,\n resolveAccessiOpenApiOptions,\n setupOpenApi\n} from \"./openapi/OpenApiConfig\";\nimport { Logger } from \"./Logger\";\nimport { EmilsoftwareModule, EmilsoftwareOptions } from \"./EmilsoftwareModule\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./accessi-module/middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessi-module/accessiRuntime\";\nimport { logAccessiStartup } from \"./accessi-module/startupLog\";\nimport { createAccessiValidationPipe } from './accessi-module/security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './accessi-module/security/AccessiHttpExceptionFilter';\n\n/** Esito del bootstrap del modulo unificato. */\nexport interface EmilsoftwareModuleInitializationResult {\n /** Sotto-app Nest che serve Accessi, Allegati e la documentazione. */\n nestApp: INestApplication;\n /** Documento OpenAPI generato, mergiabile nel documento unico dell'host. */\n document: OpenAPIObject;\n}\n\n/**\n * Initializes the unified module that combines Accessi and Allegati functionality\n * @param app Express application instance\n * @param options Configuration options for both modules\n * @returns Il sotto-app Nest e il documento OpenAPI generato.\n */\nexport async function initEmilsoftwareModule(\n app: Application,\n options: EmilsoftwareOptions\n): Promise<EmilsoftwareModuleInitializationResult> {\n const logger: Logger = new Logger(initEmilsoftwareModule.name);\n if (options?.accessiOptions) {\n beginAccessiAuthInitialization();\n }\n\n try {\n // Isolate Nest on a dedicated Express instance and dispatch only module routes.\n // This keeps pre-existing routes/middlewares on the host app untouched.\n // Prefisso OpenAPI configurabile (default `accessi/openapi`), cosi' piu'\n // documentazioni possono convivere (backend su `/openapi`, moduli sotto\n // `/<modulo>/openapi`).\n // Precedenza: EmilsoftwareOptions.openapi > AccessiOptions.openapi > default.\n const resolvedOpenApi = resolveAccessiOpenApiOptions(\n options?.accessiOptions?.openapi,\n options?.openapi\n );\n\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api\" ||\n path.startsWith(\"/api/\") ||\n isOpenApiRequestPath(path, resolvedOpenApi);\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n const nestApp = await NestFactory.create(EmilsoftwareModule.forRoot(options), nestExpressInstance, {\n bufferLogs: options?.bufferLogs !== false,\n ...(options?.logger ? { logger: options.logger } : {})\n });\n\n nestApp.enableCors();\n if (options?.accessiOptions) {\n // Keep the Accessi API contract identical for standalone and unified bootstraps.\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n }\n\n nestApp.setGlobalPrefix('api', {\n exclude: buildOpenApiExcludePaths(resolvedOpenApi)\n });\n\n // Documentazione OpenAPI del modulo unificato (Accessi + Allegati).\n const document = setupOpenApi(nestApp, resolvedOpenApi);\n\n await nestApp.init();\n if (options?.accessiOptions) {\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n logAccessiStartup(options.accessiOptions, resolvedOpenApi);\n }\n\n logger.info(\"Emilsoftware module initialized successfully\");\n\n return { nestApp, document };\n } catch (error) {\n if (options?.accessiOptions) {\n failAccessiAuthInitialization(error);\n }\n logger.error(\"Error initializing Emilsoftware Module:\", error);\n throw error;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"initEmilsoftwareModule.js","sourceRoot":"","sources":["../src/initEmilsoftwareModule.ts"],"names":[],"mappings":"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","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport type { INestApplication } from \"@nestjs/common\";\nimport type { OpenAPIObject } from \"@nestjs/swagger\";\nimport {\n buildOpenApiExcludePaths,\n isOpenApiRequestPath,\n resolveAccessiOpenApiOptions,\n setupOpenApi\n} from \"./openapi/OpenApiConfig\";\nimport { Logger } from \"./Logger\";\nimport { EmilsoftwareModule, EmilsoftwareOptions } from \"./EmilsoftwareModule\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./accessi-module/middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessi-module/accessiRuntime\";\nimport { logAccessiStartup } from \"./accessi-module/startupLog\";\nimport { createAccessiValidationPipe } from './accessi-module/security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './accessi-module/security/AccessiHttpExceptionFilter';\nimport { getAccessiJwksPath, setupAccessiJwks } from './accessi-module/security/jwks';\nimport { createAccessiEdgeRateLimitMiddleware } from './accessi-module/security/edgeRateLimit';\n\n/** Esito del bootstrap del modulo unificato. */\nexport interface EmilsoftwareModuleInitializationResult {\n /** Sotto-app Nest che serve Accessi, Allegati e la documentazione. */\n nestApp: INestApplication;\n /** Documento OpenAPI generato, mergiabile nel documento unico dell'host. */\n document: OpenAPIObject;\n}\n\n/**\n * Initializes the unified module that combines Accessi and Allegati functionality\n * @param app Express application instance\n * @param options Configuration options for both modules\n * @returns Il sotto-app Nest e il documento OpenAPI generato.\n */\nexport async function initEmilsoftwareModule(\n app: Application,\n options: EmilsoftwareOptions\n): Promise<EmilsoftwareModuleInitializationResult> {\n const logger: Logger = new Logger(initEmilsoftwareModule.name);\n if (options?.accessiOptions) {\n beginAccessiAuthInitialization();\n }\n\n try {\n // Isolate Nest on a dedicated Express instance and dispatch only module routes.\n // This keeps pre-existing routes/middlewares on the host app untouched.\n // Prefisso OpenAPI configurabile (default `accessi/openapi`), cosi' piu'\n // documentazioni possono convivere (backend su `/openapi`, moduli sotto\n // `/<modulo>/openapi`).\n // Precedenza: EmilsoftwareOptions.openapi > AccessiOptions.openapi > default.\n const resolvedOpenApi = resolveAccessiOpenApiOptions(\n options?.accessiOptions?.openapi,\n options?.openapi\n );\n\n const nestHostApp = express();\n if (options?.accessiOptions?.http?.trustProxy !== undefined) {\n app.set('trust proxy', options.accessiOptions.http.trustProxy);\n nestHostApp.set('trust proxy', options.accessiOptions.http.trustProxy);\n }\n const jwksPath = options?.accessiOptions\n ? getAccessiJwksPath(options.accessiOptions)\n : undefined;\n const isNestRoute = (path: string) =>\n path === \"/api\" ||\n path.startsWith(\"/api/\") ||\n isOpenApiRequestPath(path, resolvedOpenApi) ||\n (jwksPath !== undefined && path === jwksPath);\n const edgeRateLimit = options?.accessiOptions?.edgeRateLimit\n ? createAccessiEdgeRateLimitMiddleware({\n ...options.accessiOptions.edgeRateLimit,\n match: options.accessiOptions.edgeRateLimit.match ?? ((path) => isNestRoute(path)),\n })\n : undefined;\n if (edgeRateLimit) {\n app.use(edgeRateLimit);\n }\n if (options?.accessiOptions?.http?.securityHeaders !== false) {\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'SAMEORIGIN');\n res.setHeader('Referrer-Policy', 'no-referrer');\n res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');\n return next();\n });\n }\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n return nestHostApp(req, res, next);\n });\n\n if (options?.accessiOptions) {\n setupAccessiJwks(app, options.accessiOptions);\n if (jwksPath) {\n logger.info(`JWKS accessi disponibile su: ${jwksPath}`);\n }\n }\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n const nestApp = await NestFactory.create(EmilsoftwareModule.forRoot(options), nestExpressInstance, {\n bufferLogs: options?.bufferLogs !== false,\n ...(options?.logger ? { logger: options.logger } : {})\n });\n\n if (options?.accessiOptions?.http?.cors !== false) {\n nestApp.enableCors(options?.accessiOptions?.http?.cors);\n }\n if (options?.accessiOptions) {\n // Keep the Accessi API contract identical for standalone and unified bootstraps.\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n }\n\n nestApp.setGlobalPrefix('api', {\n exclude: buildOpenApiExcludePaths(resolvedOpenApi)\n });\n\n // Documentazione OpenAPI del modulo unificato (Accessi + Allegati).\n const document = setupOpenApi(nestApp, resolvedOpenApi);\n\n await nestApp.init();\n if (options?.accessiOptions) {\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n logAccessiStartup(options.accessiOptions, resolvedOpenApi);\n }\n\n logger.info(\"Emilsoftware module initialized successfully\");\n\n return { nestApp, document };\n } catch (error) {\n if (options?.accessiOptions) {\n failAccessiAuthInitialization(error);\n }\n logger.error(\"Error initializing Emilsoftware Module:\", error);\n throw error;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const server_1 = require("../accessi/server");
|
|
4
|
+
const Logger_1 = require("../Logger");
|
|
5
|
+
(0, server_1.startAccessiService)().catch((error) => {
|
|
6
|
+
new Logger_1.Logger('startAccessiService').error('Avvio Accessi Service fallito:', error instanceof Error
|
|
7
|
+
? { name: error.name, message: error.message, stack: error.stack }
|
|
8
|
+
: { error: String(error) });
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=startAccessiService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startAccessiService.js","sourceRoot":"","sources":["../../src/scripts/startAccessiService.ts"],"names":[],"mappings":";;AAAA,8CAAwD;AACxD,sCAAmC;AAEnC,IAAA,4BAAmB,GAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC7C,IAAI,eAAM,CAAC,qBAAqB,CAAC,CAAC,KAAK,CACrC,gCAAgC,EAChC,KAAK,YAAY,KAAK;QACpB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;QAClE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAC7B,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["import { startAccessiService } from '../accessi/server';\nimport { Logger } from '../Logger';\n\nstartAccessiService().catch((error: unknown) => {\n new Logger('startAccessiService').error(\n 'Avvio Accessi Service fallito:',\n error instanceof Error\n ? { name: error.name, message: error.message, stack: error.stack }\n : { error: String(error) },\n );\n process.exitCode = 1;\n});\n"]}
|