emilsoftware-utilities 2.0.0-dev.55 → 2.0.0-dev.57
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/README.MD +14 -0
- package/dist/accessi-module/Console/console.css +10 -1
- package/dist/accessi-module/Console/console.js +100 -7
- package/dist/accessi-module/Console/console.js.map +1 -1
- package/dist/accessi-module/Console/generated/accessiApi.d.ts +11 -1
- package/dist/accessi-module/Console/generated/accessiApi.js +10 -2
- package/dist/accessi-module/Console/generated/accessiApi.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/index.d.ts +3 -0
- package/dist/accessi-module/Console/generated/model/index.js +3 -0
- package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/loginAsRequest.d.ts +10 -0
- package/dist/accessi-module/Console/generated/model/loginAsRequest.js +9 -0
- package/dist/accessi-module/Console/generated/model/loginAsRequest.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/loginAsResponse.d.ts +14 -0
- package/dist/accessi-module/Console/generated/model/loginAsResponse.js +3 -0
- package/dist/accessi-module/Console/generated/model/loginAsResponse.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/loginAsResult.d.ts +16 -0
- package/dist/accessi-module/Console/generated/model/loginAsResult.js +9 -0
- package/dist/accessi-module/Console/generated/model/loginAsResult.js.map +1 -0
- package/dist/accessi-module/Console/help.js +17 -0
- package/dist/accessi-module/Console/help.js.map +1 -1
- package/dist/accessi-module/Console/wiki.js +18 -2
- package/dist/accessi-module/Console/wiki.js.map +1 -1
- package/dist/accessi-module/Controllers/UserController.d.ts +2 -0
- package/dist/accessi-module/Controllers/UserController.js +49 -0
- package/dist/accessi-module/Controllers/UserController.js.map +1 -1
- package/dist/accessi-module/Dtos/LoginAsDtos.d.ts +15 -0
- package/dist/accessi-module/Dtos/LoginAsDtos.js +65 -0
- package/dist/accessi-module/Dtos/LoginAsDtos.js.map +1 -0
- package/dist/accessi-module/Dtos/index.d.ts +1 -0
- package/dist/accessi-module/Dtos/index.js +1 -0
- package/dist/accessi-module/Dtos/index.js.map +1 -1
- package/dist/accessi-module/Services/AuthService/AuthService.d.ts +16 -1
- package/dist/accessi-module/Services/AuthService/AuthService.js +28 -8
- package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
- package/dist/accessi-module/Services/PermissionService/PermissionService.js +14 -12
- package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
- package/dist/accessi-module/index.d.ts +1 -0
- package/dist/accessi-module/index.js +5 -1
- package/dist/accessi-module/index.js.map +1 -1
- package/dist/accessi-module/security/authenticatedToken.d.ts +6 -0
- package/dist/accessi-module/security/authenticatedToken.js +13 -0
- package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
- package/dist/accessi-module/security/loginAs.d.ts +10 -0
- package/dist/accessi-module/security/loginAs.js +47 -0
- package/dist/accessi-module/security/loginAs.js.map +1 -0
- package/dist/emilsoftware-utilities-2.0.0-dev.57.tgz +0 -0
- package/package.json +1 -1
- package/dist/emilsoftware-utilities-2.0.0-dev.55.tgz +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessi-module/index.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 { AccessiModule, AccessiOptions } from \"./AccessiModule\";\nimport { Logger } from \"../Logger\";\nimport { AuthService } from \"./Services/AuthService/AuthService\";\nimport { setupSwagger } from \"../swagger/SwaggerConfig\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessiRuntime\";\nimport { logAccessiStartup } from \"./startupLog\";\nimport { createAccessiValidationPipe } from './security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './security/AccessiHttpExceptionFilter';\nimport { assertEmailConfigured } from './security/emailConfiguration';\n\nfunction describeDatabaseTarget(options: AccessiOptions): string {\n const dbOptions = options.databaseOptions as {\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n };\n\n return `${dbOptions.host ?? \"?\"}:${dbOptions.port ?? \"?\"} -> ${dbOptions.database ?? \"?\"} as ${dbOptions.user ?? \"?\"}`;\n}\n\n/**\n * Monta il modulo Accessi in un'applicazione Express gia esistente.\n *\n * Il bootstrap crea un host Nest isolato per le rotte `/api/accessi`, inizializza Swagger,\n * validazione ed error handler, quindi rende disponibile `authorizeAccessi` al resto dell'app.\n * Attendere questa Promise prima di aprire la porta HTTP: durante il bootstrap il middleware\n * restituisce `ACCESSI_AUTH_INITIALIZING` invece di autorizzare richieste parzialmente inizializzate.\n *\n * @param app Applicazione Express ospitante. Non viene sostituita ne vengono intercettate rotte estranee ad Accessi.\n * @param options Configurazione riservata del modulo; proviene normalmente da variabili d'ambiente o secret manager.\n */\nexport async function initializeAccessiModule(app: Application, options: AccessiOptions): Promise<void> {\n // Il servizio email e obbligatorio: reset password, 2FA e creazione utente ne dipendono.\n assertEmailConfigured(options);\n const logger: Logger = new Logger(\"initializeAccessiModule\");\n beginAccessiAuthInitialization();\n const startedAt = performance.now();\n\n try {\n logger.info(\"Inizializzazione modulo accessi avviata.\");\n logger.info(`Target database accessi: ${describeDatabaseTarget(options)}`);\n logger.info(\n `Configurazione accessi: autoUpdateDatabase=${options.autoUpdateDatabase !== false}, legacyPasswordMigrationOnStartup=${options.legacyPasswordMigrationOnStartup !== false}`\n );\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api/accessi\" ||\n path.startsWith(\"/api/accessi/\") ||\n path === \"/accessi/openapi\" ||\n path.startsWith(\"/accessi/openapi/\") ||\n path === \"/accessi/openapi.json\" ||\n path === \"/accessi/openapi-json\";\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n\n const nestApp = await NestFactory.create(AccessiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n logger.info(\"Applicazione Nest accessi creata.\");\n\n nestApp.enableCors({ exposedHeaders: ['X-Total-Count'] });\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/accessi/openapi', '/accessi/openapi/(.*)']\n });\n\n setupSwagger(nestApp, {\n swaggerPath: \"accessi/openapi\",\n swaggerJsonPath: \"accessi/openapi.json\",\n title: \"Accessi API Documentation\",\n description: \"API del modulo accessi\",\n });\n logger.info(\"Avvio init del modulo accessi.\");\n await nestApp.init();\n logger.info(\"Init del modulo accessi completata.\");\n if (options.legacyPasswordMigrationOnStartup !== false) {\n logger.info(\"Avvio migrazione password legacy accessi.\");\n const passwordMigrationService = nestApp.get(AuthService);\n await passwordMigrationService.migrateLegacyEncryptedPasswords();\n logger.info(\"Migrazione password legacy accessi completata.\");\n }\n\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n logAccessiStartup(options);\n const elapsedMs = performance.now() - startedAt;\n logger.info(`Accessi initialized. Tempo totale bootstrap: ${elapsedMs.toFixed(2)} ms`);\n\n } catch (error) {\n failAccessiAuthInitialization(error);\n logger.error(\n \"Errore in initialize AccessiModule:\",\n error instanceof Error\n ? { name: error.name, message: error.message, stack: error.stack }\n : { error: String(error) }\n );\n throw error;\n }\n}\n\nexport { AccessiModule } from \"./AccessiModule\";\nexport { AccessiDatabaseUpdater } from \"./database-updates/AccessiDatabaseUpdater\";\nexport type { AccessiOptions, EmailOptions, JwtOptions, ExtensionFieldsOptions, PublicAuthRateLimitOptions, PublicAuthRateLimitRuleOptions } from \"./AccessiModule\";\nexport type { PublicRegistrationOptions, FederatedAuthenticationOptions, ServiceTokenOptions } from \"./AccessiModule\";\nexport type { CatalogScriptsOptions, CatalogScriptChecksumPolicy } from \"./AccessiModule\";\nexport {\n AccessiCatalogMigrator,\n applyCatalogScripts,\n listPendingCatalogScripts,\n splitSqlStatements,\n analyzeCatalogScript,\n leadingStatementKeyword,\n computeCatalogScriptChecksum,\n discoverCatalogScripts\n} from \"./database-updates/AccessiCatalogMigrator\";\nexport type { CatalogMigrationReport, CatalogScriptMigration } from \"./database-updates/AccessiCatalogMigrator\";\nexport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nexport type {\n ServiceTokenMetadata,\n IssuedServiceToken,\n VerifiedServiceToken,\n IssueServiceTokenInput\n} from './Services/ServiceTokenService/ServiceTokenService';\nexport { SchemaExportService } from './Services/SchemaExportService/SchemaExportService';\nexport type { SchemaDdlResult, SchemaDdlSection, SchemaEntitiesResult } from './Services/SchemaExportService/SchemaExportService';\nexport { AdminBootstrapService } from './Services/AdminBootstrapService/AdminBootstrapService';\nexport type { BootstrapAdminResult } from './Services/AdminBootstrapService/AdminBootstrapService';\nexport {\n getOrCreateAdminBootstrapToken,\n getAdminBootstrapToken,\n clearAdminBootstrapToken,\n isValidAdminBootstrapToken\n} from './security/adminBootstrap';\nexport { ServiceTokenGuard, RequireServiceTokenScopes, getAccessiServiceToken } from './security/serviceTokenGuard';\nexport { assertEmailConfigured, isEmailConfigured, AccessiEmailNotConfiguredError, ACCESSI_EMAIL_NOT_CONFIGURED } from './security/emailConfiguration';\nexport { FederatedAuthService } from './federated-auth/FederatedAuthService';\nexport type { FederatedAuthenticationResult, FederatedIdentity, FederatedProvider, VerifiedFederatedIdentity } from './federated-auth/FederatedAuthTypes';\nexport * from \"./Dtos\";\nexport {\n authorizeAccessi,\n authenticateGen\n} from \"./middleware/authenticateGen\";\nexport { accessiRequirement } from \"./middleware/accessiRequirements\";\nexport {\n registerAccessiModuleServices,\n getAccessiModuleServices,\n ACCESSI_MODULE_SERVICES_LOCALS_KEY\n} from \"./accessiRuntime\";\nexport type { AccessiModuleServices } from \"./accessiRuntime\";\nexport type {\n AccessiAuthorizationOptions,\n AccessiRequirementNode,\n AccessiCustomRequirementContext,\n AccessiCustomRequirementHandler\n} from \"./middleware/accessiRequirements\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessi-module/index.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 { AccessiModule, AccessiOptions } from \"./AccessiModule\";\nimport { Logger } from \"../Logger\";\nimport { AuthService } from \"./Services/AuthService/AuthService\";\nimport { setupSwagger } from \"../swagger/SwaggerConfig\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessiRuntime\";\nimport { logAccessiStartup } from \"./startupLog\";\nimport { createAccessiValidationPipe } from './security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './security/AccessiHttpExceptionFilter';\nimport { assertEmailConfigured } from './security/emailConfiguration';\n\nfunction describeDatabaseTarget(options: AccessiOptions): string {\n const dbOptions = options.databaseOptions as {\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n };\n\n return `${dbOptions.host ?? \"?\"}:${dbOptions.port ?? \"?\"} -> ${dbOptions.database ?? \"?\"} as ${dbOptions.user ?? \"?\"}`;\n}\n\n/**\n * Monta il modulo Accessi in un'applicazione Express gia esistente.\n *\n * Il bootstrap crea un host Nest isolato per le rotte `/api/accessi`, inizializza Swagger,\n * validazione ed error handler, quindi rende disponibile `authorizeAccessi` al resto dell'app.\n * Attendere questa Promise prima di aprire la porta HTTP: durante il bootstrap il middleware\n * restituisce `ACCESSI_AUTH_INITIALIZING` invece di autorizzare richieste parzialmente inizializzate.\n *\n * @param app Applicazione Express ospitante. Non viene sostituita ne vengono intercettate rotte estranee ad Accessi.\n * @param options Configurazione riservata del modulo; proviene normalmente da variabili d'ambiente o secret manager.\n */\nexport async function initializeAccessiModule(app: Application, options: AccessiOptions): Promise<void> {\n // Il servizio email e obbligatorio: reset password, 2FA e creazione utente ne dipendono.\n assertEmailConfigured(options);\n const logger: Logger = new Logger(\"initializeAccessiModule\");\n beginAccessiAuthInitialization();\n const startedAt = performance.now();\n\n try {\n logger.info(\"Inizializzazione modulo accessi avviata.\");\n logger.info(`Target database accessi: ${describeDatabaseTarget(options)}`);\n logger.info(\n `Configurazione accessi: autoUpdateDatabase=${options.autoUpdateDatabase !== false}, legacyPasswordMigrationOnStartup=${options.legacyPasswordMigrationOnStartup !== false}`\n );\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api/accessi\" ||\n path.startsWith(\"/api/accessi/\") ||\n path === \"/accessi/openapi\" ||\n path.startsWith(\"/accessi/openapi/\") ||\n path === \"/accessi/openapi.json\" ||\n path === \"/accessi/openapi-json\";\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n\n const nestApp = await NestFactory.create(AccessiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n logger.info(\"Applicazione Nest accessi creata.\");\n\n nestApp.enableCors({ exposedHeaders: ['X-Total-Count'] });\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/accessi/openapi', '/accessi/openapi/(.*)']\n });\n\n setupSwagger(nestApp, {\n swaggerPath: \"accessi/openapi\",\n swaggerJsonPath: \"accessi/openapi.json\",\n title: \"Accessi API Documentation\",\n description: \"API del modulo accessi\",\n });\n logger.info(\"Avvio init del modulo accessi.\");\n await nestApp.init();\n logger.info(\"Init del modulo accessi completata.\");\n if (options.legacyPasswordMigrationOnStartup !== false) {\n logger.info(\"Avvio migrazione password legacy accessi.\");\n const passwordMigrationService = nestApp.get(AuthService);\n await passwordMigrationService.migrateLegacyEncryptedPasswords();\n logger.info(\"Migrazione password legacy accessi completata.\");\n }\n\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n logAccessiStartup(options);\n const elapsedMs = performance.now() - startedAt;\n logger.info(`Accessi initialized. Tempo totale bootstrap: ${elapsedMs.toFixed(2)} ms`);\n\n } catch (error) {\n failAccessiAuthInitialization(error);\n logger.error(\n \"Errore in initialize AccessiModule:\",\n error instanceof Error\n ? { name: error.name, message: error.message, stack: error.stack }\n : { error: String(error) }\n );\n throw error;\n }\n}\n\nexport { AccessiModule } from \"./AccessiModule\";\nexport { AccessiDatabaseUpdater } from \"./database-updates/AccessiDatabaseUpdater\";\nexport type { AccessiOptions, EmailOptions, JwtOptions, ExtensionFieldsOptions, PublicAuthRateLimitOptions, PublicAuthRateLimitRuleOptions } from \"./AccessiModule\";\nexport type { PublicRegistrationOptions, FederatedAuthenticationOptions, ServiceTokenOptions } from \"./AccessiModule\";\nexport type { CatalogScriptsOptions, CatalogScriptChecksumPolicy } from \"./AccessiModule\";\nexport {\n AccessiCatalogMigrator,\n applyCatalogScripts,\n listPendingCatalogScripts,\n splitSqlStatements,\n analyzeCatalogScript,\n leadingStatementKeyword,\n computeCatalogScriptChecksum,\n discoverCatalogScripts\n} from \"./database-updates/AccessiCatalogMigrator\";\nexport type { CatalogMigrationReport, CatalogScriptMigration } from \"./database-updates/AccessiCatalogMigrator\";\nexport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nexport type {\n ServiceTokenMetadata,\n IssuedServiceToken,\n VerifiedServiceToken,\n IssueServiceTokenInput\n} from './Services/ServiceTokenService/ServiceTokenService';\nexport { SchemaExportService } from './Services/SchemaExportService/SchemaExportService';\nexport type { SchemaDdlResult, SchemaDdlSection, SchemaEntitiesResult } from './Services/SchemaExportService/SchemaExportService';\nexport { AdminBootstrapService } from './Services/AdminBootstrapService/AdminBootstrapService';\nexport type { BootstrapAdminResult } from './Services/AdminBootstrapService/AdminBootstrapService';\nexport {\n getOrCreateAdminBootstrapToken,\n getAdminBootstrapToken,\n clearAdminBootstrapToken,\n isValidAdminBootstrapToken\n} from './security/adminBootstrap';\nexport { ServiceTokenGuard, RequireServiceTokenScopes, getAccessiServiceToken } from './security/serviceTokenGuard';\nexport { assertEmailConfigured, isEmailConfigured, AccessiEmailNotConfiguredError, ACCESSI_EMAIL_NOT_CONFIGURED } from './security/emailConfiguration';\nexport { buildLoginAsUrl, LOGIN_AS_QUERY_PARAM, LOGIN_AS_TOKEN_TTL_SECONDS } from './security/loginAs';\nexport { FederatedAuthService } from './federated-auth/FederatedAuthService';\nexport type { FederatedAuthenticationResult, FederatedIdentity, FederatedProvider, VerifiedFederatedIdentity } from './federated-auth/FederatedAuthTypes';\nexport * from \"./Dtos\";\nexport {\n authorizeAccessi,\n authenticateGen\n} from \"./middleware/authenticateGen\";\nexport { accessiRequirement } from \"./middleware/accessiRequirements\";\nexport {\n registerAccessiModuleServices,\n getAccessiModuleServices,\n ACCESSI_MODULE_SERVICES_LOCALS_KEY\n} from \"./accessiRuntime\";\nexport type { AccessiModuleServices } from \"./accessiRuntime\";\nexport type {\n AccessiAuthorizationOptions,\n AccessiRequirementNode,\n AccessiCustomRequirementContext,\n AccessiCustomRequirementHandler\n} from \"./middleware/accessiRequirements\";\n"]}
|
|
@@ -19,6 +19,12 @@ export declare function resolveCodiceUtenteFromTokenPayload(decoded: unknown): n
|
|
|
19
19
|
* `tokenPayload` conserva il payload verificato originale per audit o integrazioni che ne abbiano necessita.
|
|
20
20
|
*/
|
|
21
21
|
export declare function buildAuthenticatedTokenPayload(decoded: unknown, utente: AccessiAuthenticatedUserSnapshot): Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Riconosce i token emessi dalla console per l'accesso temporaneo "Login as".
|
|
24
|
+
* L'attore ha gia completato l'autenticazione amministrativa, quindi il token
|
|
25
|
+
* non richiede un ulteriore codice email anche se il target ha la 2FA attiva.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isLoginAsTokenPayload(decoded: unknown): boolean;
|
|
22
28
|
/** Enabling 2FA invalidates sessions which have not completed the required verification. */
|
|
23
29
|
export declare function isAccessiTokenAllowedForUser(decoded: unknown, user: AccessiAuthenticatedUserSnapshot): boolean;
|
|
24
30
|
/** Un JWT puo essere usato soltanto da utenti nello stato confermato, indipendentemente dalla sua scadenza. */
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.extractAccessiBearerToken = extractAccessiBearerToken;
|
|
4
4
|
exports.resolveCodiceUtenteFromTokenPayload = resolveCodiceUtenteFromTokenPayload;
|
|
5
5
|
exports.buildAuthenticatedTokenPayload = buildAuthenticatedTokenPayload;
|
|
6
|
+
exports.isLoginAsTokenPayload = isLoginAsTokenPayload;
|
|
6
7
|
exports.isAccessiTokenAllowedForUser = isAccessiTokenAllowedForUser;
|
|
7
8
|
exports.isAuthenticatedUserEnabledForJwt = isAuthenticatedUserEnabledForJwt;
|
|
8
9
|
const StatoRegistrazione_1 = require("../Dtos/StatoRegistrazione");
|
|
@@ -48,10 +49,22 @@ function buildAuthenticatedTokenPayload(decoded, utente) {
|
|
|
48
49
|
const normalizedUser = Object.assign(Object.assign({}, utente), { flagSuper: normalizeBooleanFlag(utente.flagSuper), flagAdmin: normalizeBooleanFlag(utente.flagAdmin), flagDueFattori: normalizeBooleanFlag(utente.flagDueFattori), passwordlessLoginEnabled: normalizeBooleanFlag(utente.passwordlessLoginEnabled) });
|
|
49
50
|
return Object.assign(Object.assign({}, basePayload), { codiceUtente: normalizedUser.codiceUtente, email: normalizedUser.email, statoRegistrazione: normalizedUser.statoRegistrazione, flagSuper: normalizedUser.flagSuper, flagAdmin: normalizedUser.flagAdmin, flagDueFattori: normalizedUser.flagDueFattori, passwordlessLoginEnabled: normalizedUser.passwordlessLoginEnabled, passwordLoginEnabled: normalizedUser.passwordLoginEnabled, utente: normalizedUser, userData: Object.assign(Object.assign({}, userData), { utente: normalizedUser }), tokenPayload: decoded });
|
|
50
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Riconosce i token emessi dalla console per l'accesso temporaneo "Login as".
|
|
54
|
+
* L'attore ha gia completato l'autenticazione amministrativa, quindi il token
|
|
55
|
+
* non richiede un ulteriore codice email anche se il target ha la 2FA attiva.
|
|
56
|
+
*/
|
|
57
|
+
function isLoginAsTokenPayload(decoded) {
|
|
58
|
+
if (!isRecord(decoded) || decoded.loginAs !== true)
|
|
59
|
+
return false;
|
|
60
|
+
return Array.isArray(decoded.amr) && decoded.amr.includes('login_as');
|
|
61
|
+
}
|
|
51
62
|
/** Enabling 2FA invalidates sessions which have not completed the required verification. */
|
|
52
63
|
function isAccessiTokenAllowedForUser(decoded, user) {
|
|
53
64
|
if (!isRecord(decoded))
|
|
54
65
|
return false;
|
|
66
|
+
if (isLoginAsTokenPayload(decoded))
|
|
67
|
+
return true;
|
|
55
68
|
const methods = Array.isArray(decoded.amr) ? decoded.amr : [];
|
|
56
69
|
if (user.flagDueFattori && !methods.includes('otp'))
|
|
57
70
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticatedToken.js","sourceRoot":"","sources":["../../../src/accessi-module/security/authenticatedToken.ts"],"names":[],"mappings":";;AAuBA,8DAGC;AAGD,kFAmBC;AAMD,wEAgCC;AAGD,
|
|
1
|
+
{"version":3,"file":"authenticatedToken.js","sourceRoot":"","sources":["../../../src/accessi-module/security/authenticatedToken.ts"],"names":[],"mappings":"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","sourcesContent":["import { StatoRegistrazione } from '../Dtos/StatoRegistrazione';\n\n/** Stato autorevole minimo riletto dal database per ogni verifica JWT. */\nexport interface AccessiAuthenticatedUserSnapshot {\n codiceUtente: number;\n email?: string;\n statoRegistrazione: StatoRegistrazione;\n flagSuper: boolean;\n flagAdmin: boolean;\n flagDueFattori?: boolean;\n passwordlessLoginEnabled?: boolean;\n passwordLoginEnabled?: boolean;\n}\n\nfunction normalizeBooleanFlag(value: unknown): boolean {\n return value === true || value === 1 || value === '1';\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Shared, strict Bearer parsing for the Nest guard and Express middleware. */\nexport function extractAccessiBearerToken(header: unknown): string | undefined {\n if (typeof header !== 'string') return undefined;\n return /^Bearer[ \\t]+([^\\s]+)$/i.exec(header.trim())?.[1];\n}\n\n/** Estrae il codice utente sia dai JWT Accessi moderni sia dai payload legacy compatibili. */\nexport function resolveCodiceUtenteFromTokenPayload(decoded: unknown): number | undefined {\n // `typ` obbligatorio: un token senza tipo non e un access token Accessi.\n if (!isRecord(decoded) || decoded.typ !== 'access') {\n return undefined;\n }\n\n const userData = isRecord(decoded.userData) ? decoded.userData : undefined;\n const utente = isRecord(decoded.utente)\n ? decoded.utente\n : isRecord(userData?.utente)\n ? userData.utente\n : undefined;\n\n const codiceUtente = Number(utente?.codiceUtente ?? decoded.codiceUtente);\n if (!Number.isSafeInteger(codiceUtente) || codiceUtente <= 0) {\n return undefined;\n }\n\n return codiceUtente;\n}\n\n/**\n * Mantiene le claim estranee al modulo ma sovrascrive il profilo con valori correnti e autorevoli dal database.\n * `tokenPayload` conserva il payload verificato originale per audit o integrazioni che ne abbiano necessita.\n */\nexport function buildAuthenticatedTokenPayload(\n decoded: unknown,\n utente: AccessiAuthenticatedUserSnapshot,\n): Record<string, unknown> {\n const basePayload = isRecord(decoded) ? { ...decoded } : {};\n const userData = isRecord(basePayload.userData) ? { ...basePayload.userData } : {};\n\n const normalizedUser = {\n ...utente,\n flagSuper: normalizeBooleanFlag(utente.flagSuper),\n flagAdmin: normalizeBooleanFlag(utente.flagAdmin),\n flagDueFattori: normalizeBooleanFlag(utente.flagDueFattori),\n passwordlessLoginEnabled: normalizeBooleanFlag(utente.passwordlessLoginEnabled),\n };\n\n return {\n ...basePayload,\n codiceUtente: normalizedUser.codiceUtente,\n email: normalizedUser.email,\n statoRegistrazione: normalizedUser.statoRegistrazione,\n flagSuper: normalizedUser.flagSuper,\n flagAdmin: normalizedUser.flagAdmin,\n flagDueFattori: normalizedUser.flagDueFattori,\n passwordlessLoginEnabled: normalizedUser.passwordlessLoginEnabled,\n passwordLoginEnabled: normalizedUser.passwordLoginEnabled,\n utente: normalizedUser,\n userData: {\n ...userData,\n utente: normalizedUser,\n },\n tokenPayload: decoded,\n };\n}\n\n/**\n * Riconosce i token emessi dalla console per l'accesso temporaneo \"Login as\".\n * L'attore ha gia completato l'autenticazione amministrativa, quindi il token\n * non richiede un ulteriore codice email anche se il target ha la 2FA attiva.\n */\nexport function isLoginAsTokenPayload(decoded: unknown): boolean {\n if (!isRecord(decoded) || decoded.loginAs !== true) return false;\n return Array.isArray(decoded.amr) && decoded.amr.includes('login_as');\n}\n\n/** Enabling 2FA invalidates sessions which have not completed the required verification. */\nexport function isAccessiTokenAllowedForUser(decoded: unknown, user: AccessiAuthenticatedUserSnapshot): boolean {\n if (!isRecord(decoded)) return false;\n if (isLoginAsTokenPayload(decoded)) return true;\n const methods = Array.isArray(decoded.amr) ? decoded.amr : [];\n if (user.flagDueFattori && !methods.includes('otp')) return false;\n if (methods.includes('passwordless') && (!user.flagDueFattori || !user.passwordlessLoginEnabled)) return false;\n return true;\n}\n\n/** Un JWT puo essere usato soltanto da utenti nello stato confermato, indipendentemente dalla sua scadenza. */\nexport function isAuthenticatedUserEnabledForJwt(\n utente: AccessiAuthenticatedUserSnapshot | null | undefined,\n): utente is AccessiAuthenticatedUserSnapshot {\n return utente?.statoRegistrazione === StatoRegistrazione.CONF;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Durata massima del token di impersonazione: deve restare molto breve. */
|
|
2
|
+
export declare const LOGIN_AS_TOKEN_TTL_SECONDS: number;
|
|
3
|
+
/** Nome del query parameter usato dalle applicazioni per consumare il token. */
|
|
4
|
+
export declare const LOGIN_AS_QUERY_PARAM = "loginAsToken";
|
|
5
|
+
/**
|
|
6
|
+
* Combina l'URL dell'applicazione con il token di accesso temporaneo.
|
|
7
|
+
* Accetta solo URL assoluti http/https: evita schemi come javascript: o data:
|
|
8
|
+
* che verrebbero restituiti alla console come link cliccabile.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildLoginAsUrl(targetUrl: string, token: string): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LOGIN_AS_QUERY_PARAM = exports.LOGIN_AS_TOKEN_TTL_SECONDS = void 0;
|
|
4
|
+
exports.buildLoginAsUrl = buildLoginAsUrl;
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
/** Durata massima del token di impersonazione: deve restare molto breve. */
|
|
7
|
+
exports.LOGIN_AS_TOKEN_TTL_SECONDS = 5 * 60;
|
|
8
|
+
/** Nome del query parameter usato dalle applicazioni per consumare il token. */
|
|
9
|
+
exports.LOGIN_AS_QUERY_PARAM = 'loginAsToken';
|
|
10
|
+
/**
|
|
11
|
+
* Combina l'URL dell'applicazione con il token di accesso temporaneo.
|
|
12
|
+
* Accetta solo URL assoluti http/https: evita schemi come javascript: o data:
|
|
13
|
+
* che verrebbero restituiti alla console come link cliccabile.
|
|
14
|
+
*/
|
|
15
|
+
function buildLoginAsUrl(targetUrl, token) {
|
|
16
|
+
if (typeof targetUrl !== 'string' || targetUrl.trim() === '') {
|
|
17
|
+
throw new common_1.BadRequestException({
|
|
18
|
+
code: 'ACCESSI_LOGIN_AS_INVALID_URL',
|
|
19
|
+
message: 'Indica l URL dell applicazione a cui accedere.',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
if (typeof token !== 'string' || token.trim() === '') {
|
|
23
|
+
throw new common_1.BadRequestException({
|
|
24
|
+
code: 'ACCESSI_LOGIN_AS_INVALID_TOKEN',
|
|
25
|
+
message: 'Token di accesso temporaneo non valido.',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = new URL(targetUrl.trim());
|
|
31
|
+
}
|
|
32
|
+
catch (_a) {
|
|
33
|
+
throw new common_1.BadRequestException({
|
|
34
|
+
code: 'ACCESSI_LOGIN_AS_INVALID_URL',
|
|
35
|
+
message: 'L URL deve essere assoluto e valido, per esempio https://app.example.com.',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
39
|
+
throw new common_1.BadRequestException({
|
|
40
|
+
code: 'ACCESSI_LOGIN_AS_INVALID_URL',
|
|
41
|
+
message: 'L URL deve usare http o https.',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
parsed.searchParams.set(exports.LOGIN_AS_QUERY_PARAM, token);
|
|
45
|
+
return parsed.toString();
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=loginAs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loginAs.js","sourceRoot":"","sources":["../../../src/accessi-module/security/loginAs.ts"],"names":[],"mappings":";;;AAaA,0CAiCC;AA9CD,2CAAqD;AAErD,4EAA4E;AAC/D,QAAA,0BAA0B,GAAG,CAAC,GAAG,EAAE,CAAC;AAEjD,gFAAgF;AACnE,QAAA,oBAAoB,GAAG,cAAc,CAAC;AAEnD;;;;GAIG;AACH,SAAgB,eAAe,CAAC,SAAiB,EAAE,KAAa;IAC9D,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7D,MAAM,IAAI,4BAAmB,CAAC;YAC5B,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE,gDAAgD;SAC1D,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,4BAAmB,CAAC;YAC5B,IAAI,EAAE,gCAAgC;YACtC,OAAO,EAAE,yCAAyC;SACnD,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IAAC,WAAM,CAAC;QACP,MAAM,IAAI,4BAAmB,CAAC;YAC5B,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE,2EAA2E;SACrF,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,4BAAmB,CAAC;YAC5B,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE,gCAAgC;SAC1C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,4BAAoB,EAAE,KAAK,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { BadRequestException } from '@nestjs/common';\n\n/** Durata massima del token di impersonazione: deve restare molto breve. */\nexport const LOGIN_AS_TOKEN_TTL_SECONDS = 5 * 60;\n\n/** Nome del query parameter usato dalle applicazioni per consumare il token. */\nexport const LOGIN_AS_QUERY_PARAM = 'loginAsToken';\n\n/**\n * Combina l'URL dell'applicazione con il token di accesso temporaneo.\n * Accetta solo URL assoluti http/https: evita schemi come javascript: o data:\n * che verrebbero restituiti alla console come link cliccabile.\n */\nexport function buildLoginAsUrl(targetUrl: string, token: string): string {\n if (typeof targetUrl !== 'string' || targetUrl.trim() === '') {\n throw new BadRequestException({\n code: 'ACCESSI_LOGIN_AS_INVALID_URL',\n message: 'Indica l URL dell applicazione a cui accedere.',\n });\n }\n if (typeof token !== 'string' || token.trim() === '') {\n throw new BadRequestException({\n code: 'ACCESSI_LOGIN_AS_INVALID_TOKEN',\n message: 'Token di accesso temporaneo non valido.',\n });\n }\n\n let parsed: URL;\n try {\n parsed = new URL(targetUrl.trim());\n } catch {\n throw new BadRequestException({\n code: 'ACCESSI_LOGIN_AS_INVALID_URL',\n message: 'L URL deve essere assoluto e valido, per esempio https://app.example.com.',\n });\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new BadRequestException({\n code: 'ACCESSI_LOGIN_AS_INVALID_URL',\n message: 'L URL deve usare http o https.',\n });\n }\n\n parsed.searchParams.set(LOGIN_AS_QUERY_PARAM, token);\n return parsed.toString();\n}\n"]}
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|