emilsoftware-utilities 2.0.0-dev.24 → 2.0.0-dev.25

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 (111) hide show
  1. package/README.MD +185 -182
  2. package/dist/ContractGenerator.js.map +1 -1
  3. package/dist/DailyFileTransport.js.map +1 -1
  4. package/dist/DatabaseUpdater.js +24 -24
  5. package/dist/DatabaseUpdater.js.map +1 -1
  6. package/dist/EmilsoftwareModule.js.map +1 -1
  7. package/dist/ExecutionTimeLogger.js.map +1 -1
  8. package/dist/Orm.js.map +1 -1
  9. package/dist/RoutesLoggerMiddleware.js.map +1 -1
  10. package/dist/Utilities.js.map +1 -1
  11. package/dist/accessi-module/AccessiModule.js.map +1 -1
  12. package/dist/accessi-module/Console/console.js.map +1 -1
  13. package/dist/accessi-module/Controllers/ConfiguratorController.js.map +1 -1
  14. package/dist/accessi-module/Controllers/FiltriController.js.map +1 -1
  15. package/dist/accessi-module/Controllers/PermissionController.js.map +1 -1
  16. package/dist/accessi-module/Controllers/UserController.js.map +1 -1
  17. package/dist/accessi-module/Dtos/Abilitazione.js.map +1 -1
  18. package/dist/accessi-module/Dtos/AbilitazioneMenu.js.map +1 -1
  19. package/dist/accessi-module/Dtos/AssignPermissionsToUserRequest.js.map +1 -1
  20. package/dist/accessi-module/Dtos/AssignRolesToUserRequest.js.map +1 -1
  21. package/dist/accessi-module/Dtos/BaseResponse.js.map +1 -1
  22. package/dist/accessi-module/Dtos/FiltriUtente.js.map +1 -1
  23. package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js.map +1 -1
  24. package/dist/accessi-module/Dtos/GetMenusResponse.js.map +1 -1
  25. package/dist/accessi-module/Dtos/GetRolesResponse.js.map +1 -1
  26. package/dist/accessi-module/Dtos/GetUsersResponse.js.map +1 -1
  27. package/dist/accessi-module/Dtos/LoginRequest.js.map +1 -1
  28. package/dist/accessi-module/Dtos/LoginResponse.js.map +1 -1
  29. package/dist/accessi-module/Dtos/Permission.js.map +1 -1
  30. package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
  31. package/dist/accessi-module/Dtos/Role.js.map +1 -1
  32. package/dist/accessi-module/Dtos/RuoliMenu.js.map +1 -1
  33. package/dist/accessi-module/Dtos/SetStatoRegistrazione.js.map +1 -1
  34. package/dist/accessi-module/Dtos/StatoRegistrazione.js.map +1 -1
  35. package/dist/accessi-module/Dtos/TipoAbilitazione.js.map +1 -1
  36. package/dist/accessi-module/Dtos/TipoFiltro.js.map +1 -1
  37. package/dist/accessi-module/Dtos/TokenResult.js.map +1 -1
  38. package/dist/accessi-module/Dtos/UpdateEnabledStatusRequest.js.map +1 -1
  39. package/dist/accessi-module/Dtos/UserDto.js.map +1 -1
  40. package/dist/accessi-module/Dtos/UserGrantsDto.js.map +1 -1
  41. package/dist/accessi-module/Dtos/index.js.map +1 -1
  42. package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
  43. package/dist/accessi-module/Services/ConfiguratorService/ConfiguratorService.js.map +1 -1
  44. package/dist/accessi-module/Services/EmailService/EmailService.js +11 -11
  45. package/dist/accessi-module/Services/EmailService/EmailService.js.map +1 -1
  46. package/dist/accessi-module/Services/FiltriService/FiltriService.js.map +1 -1
  47. package/dist/accessi-module/Services/PermissionService/PermissionService.js +118 -118
  48. package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
  49. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js +4 -4
  50. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js.map +1 -1
  51. package/dist/accessi-module/Services/UserService/UserService.js +72 -72
  52. package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
  53. package/dist/accessi-module/Views/reset-password.html +213 -213
  54. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.d.ts +1 -0
  55. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +56 -42
  56. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
  57. package/dist/accessi-module/database-updates/runAccessiDbUpdate.js.map +1 -1
  58. package/dist/accessi-module/index.js.map +1 -1
  59. package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
  60. package/dist/accessi-module/middleware/accessiRequirements.js.map +1 -1
  61. package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
  62. package/dist/accessi-module/security/accessControl.js.map +1 -1
  63. package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
  64. package/dist/accessi-module/security/passwordResetToken.js.map +1 -1
  65. package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
  66. package/dist/allegati-module/AllegatiModule.js.map +1 -1
  67. package/dist/allegati-module/Controllers/AllegatiController.js.map +1 -1
  68. package/dist/allegati-module/Dtos/AllegatoDto.js.map +1 -1
  69. package/dist/allegati-module/Dtos/BaseResponse.js.map +1 -1
  70. package/dist/allegati-module/Dtos/UploadSingleFileRequest.js.map +1 -1
  71. package/dist/allegati-module/Dtos/index.js.map +1 -1
  72. package/dist/allegati-module/Dtos/responses/DownloadAllegatoResponseDto.js.map +1 -1
  73. package/dist/allegati-module/Dtos/responses/GetListResponse.js.map +1 -1
  74. package/dist/allegati-module/Dtos/responses/UploadAllegatoResponseDto.js.map +1 -1
  75. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js +49 -49
  76. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js.map +1 -1
  77. package/dist/allegati-module/index.js.map +1 -1
  78. package/dist/autobind.js.map +1 -1
  79. package/dist/emilsoftware-utilities-2.0.0-dev.25.tgz +0 -0
  80. package/dist/firebird-compat.js.map +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/initEmilsoftwareModule.js.map +1 -1
  83. package/dist/swagger/SwaggerConfig.js.map +1 -1
  84. package/package.json +103 -103
  85. package/dist/accessi-module/Console/generated/model/abilitazioneMenuIcona.d.ts +0 -12
  86. package/dist/accessi-module/Console/generated/model/abilitazioneMenuIcona.js +0 -9
  87. package/dist/accessi-module/Console/generated/model/abilitazioneMenuIcona.js.map +0 -1
  88. package/dist/accessi-module/Console/generated/model/abilitazioneMenuNote.d.ts +0 -12
  89. package/dist/accessi-module/Console/generated/model/abilitazioneMenuNote.js +0 -9
  90. package/dist/accessi-module/Console/generated/model/abilitazioneMenuNote.js.map +0 -1
  91. package/dist/accessi-module/Console/generated/model/abilitazioneMenuPagina.d.ts +0 -12
  92. package/dist/accessi-module/Console/generated/model/abilitazioneMenuPagina.js +0 -9
  93. package/dist/accessi-module/Console/generated/model/abilitazioneMenuPagina.js.map +0 -1
  94. package/dist/accessi-module/Console/generated/model/abilitazioneMenuTipo.d.ts +0 -12
  95. package/dist/accessi-module/Console/generated/model/abilitazioneMenuTipo.js +0 -9
  96. package/dist/accessi-module/Console/generated/model/abilitazioneMenuTipo.js.map +0 -1
  97. package/dist/accessi-module/Console/generated/model/publicRegisterRequestCellulare.d.ts +0 -13
  98. package/dist/accessi-module/Console/generated/model/publicRegisterRequestCellulare.js +0 -9
  99. package/dist/accessi-module/Console/generated/model/publicRegisterRequestCellulare.js.map +0 -1
  100. package/dist/accessi-module/Console/generated/model/registerRequestCellulare.d.ts +0 -13
  101. package/dist/accessi-module/Console/generated/model/registerRequestCellulare.js +0 -9
  102. package/dist/accessi-module/Console/generated/model/registerRequestCellulare.js.map +0 -1
  103. package/dist/accessi-module/Console/generated/model/userDtoAvatar.d.ts +0 -13
  104. package/dist/accessi-module/Console/generated/model/userDtoAvatar.js +0 -9
  105. package/dist/accessi-module/Console/generated/model/userDtoAvatar.js.map +0 -1
  106. package/dist/accessi-module/Console/generated/model/userDtoCellulare.d.ts +0 -13
  107. package/dist/accessi-module/Console/generated/model/userDtoCellulare.js +0 -9
  108. package/dist/accessi-module/Console/generated/model/userDtoCellulare.js.map +0 -1
  109. package/dist/accessi-module/Console/openApiClient.d.ts +0 -34
  110. package/dist/accessi-module/Console/openApiClient.js +0 -111
  111. package/dist/accessi-module/Console/openApiClient.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"passwordResetToken.js","sourceRoot":"","sources":["../../../src/accessi-module/security/passwordResetToken.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,kDAOC;AAGD,4DAqBC;AAGD,4DAeC;AApED,kDAAoC;AACpC,mCAAoC;AAGpC,mHAAmH;AACtG,QAAA,iCAAiC,GAAG,IAAI,CAAC;AAUtD;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,OAAuB,EAAE,UAA6B,QAAQ;;IAChG,MAAM,MAAM,GAAG,CAAA,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,UAAU,0CAAE,MAAM,KAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACzE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,IAAA,mBAAU,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,eAAe,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxF,CAAC;AAED,oHAAoH;AACpH,SAAgB,wBAAwB,CACtC,YAAoB,EACpB,KAAa,EACb,MAAc,EACd,YAA0C,yCAAiC;IAE3E,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,CACb;QACE,KAAK;QACL,GAAG,EAAE,gBAAgB;KACtB,EACD,MAAM,EACN;QACE,OAAO,EAAE,GAAG,YAAY,EAAE;QAC1B,SAAS;KACV,CACF,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,SAAgB,wBAAwB,CACtC,KAAa,EACb,MAAc;IAEd,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,CAA8B,CAAC;IAClG,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,CAAC,CAAC;IAE1C,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,MAAK,gBAAgB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,IAAI,OAAO,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,CAAA,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC1J,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACL,YAAY;QACZ,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC;AACJ,CAAC","sourcesContent":["import * as jwt from 'jsonwebtoken';\r\nimport { createHmac } from 'crypto';\r\nimport type { AccessiOptions } from '../AccessiModule';\r\n\r\n/** Durata predefinita del token di reset. La monouso e garantita anche dal nonce persistito in `UTENTI.KEYREG`. */\nexport const DEFAULT_PASSWORD_RESET_EXPIRES_IN = '1h';\n\r\ninterface PasswordResetTokenPayload extends jwt.JwtPayload {\r\n nonce: string;\r\n typ: 'password-reset';\r\n}\r\n\r\n/** Scopo della chiave derivata: separa le chiavi di access token, reset password e 2FA. */\r\nexport type AccessiJwtPurpose = 'access' | 'reset' | '2fa';\r\n\r\n/**\r\n * Deriva una chiave JWT per scopo dal segreto configurato (key separation senza nuova configurazione).\r\n * Un leak della chiave di reset non compromette gli access token e viceversa.\r\n */\r\nexport function getAccessiJwtSecret(options: AccessiOptions, purpose: AccessiJwtPurpose = 'access'): string {\r\n const secret = options?.jwtOptions?.secret || process.env.ACC_JWT_SECRET;\r\n if (!secret) {\r\n throw new Error('JWT secret non configurato.');\r\n }\r\n\r\n return createHmac('sha256', secret).update(`accessi:jwt:${purpose}:v1`).digest('hex');\r\n}\n\r\n/** Crea un token firmato contenente solo codice utente e nonce; non inserire email o dati personali nelle claim. */\nexport function createPasswordResetToken(\n codiceUtente: number,\r\n nonce: string,\r\n secret: string,\r\n expiresIn: jwt.SignOptions['expiresIn'] = DEFAULT_PASSWORD_RESET_EXPIRES_IN,\r\n): string {\r\n if (!codiceUtente || !nonce) {\r\n throw new Error('Dati insufficienti per generare il reset token.');\r\n }\r\n\r\n return jwt.sign(\r\n {\r\n nonce,\r\n typ: 'password-reset',\r\n },\r\n secret,\r\n {\r\n subject: `${codiceUtente}`,\r\n expiresIn,\r\n },\r\n );\r\n}\r\n\r\n/** Verifica firma e scadenza, quindi restituisce i dati minimi necessari al reset. */\nexport function verifyPasswordResetToken(\n token: string,\r\n secret: string,\r\n): { codiceUtente: number; nonce: string } {\r\n const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] }) as PasswordResetTokenPayload;\r\n const codiceUtente = Number(decoded?.sub);\r\n\r\n if (decoded?.typ !== 'password-reset' || !Number.isSafeInteger(codiceUtente) || codiceUtente <= 0 || typeof decoded?.nonce !== 'string' || !decoded.nonce) {\n throw new Error('Token di reset non valido.');\r\n }\r\n\r\n return {\r\n codiceUtente,\r\n nonce: decoded.nonce,\r\n };\r\n}\r\n"]}
1
+ {"version":3,"file":"passwordResetToken.js","sourceRoot":"","sources":["../../../src/accessi-module/security/passwordResetToken.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,kDAOC;AAGD,4DAqBC;AAGD,4DAeC;AApED,kDAAoC;AACpC,mCAAoC;AAGpC,mHAAmH;AACtG,QAAA,iCAAiC,GAAG,IAAI,CAAC;AAUtD;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,OAAuB,EAAE,UAA6B,QAAQ;;IAChG,MAAM,MAAM,GAAG,CAAA,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,UAAU,0CAAE,MAAM,KAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACzE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,IAAA,mBAAU,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,eAAe,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxF,CAAC;AAED,oHAAoH;AACpH,SAAgB,wBAAwB,CACtC,YAAoB,EACpB,KAAa,EACb,MAAc,EACd,YAA0C,yCAAiC;IAE3E,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,CACb;QACE,KAAK;QACL,GAAG,EAAE,gBAAgB;KACtB,EACD,MAAM,EACN;QACE,OAAO,EAAE,GAAG,YAAY,EAAE;QAC1B,SAAS;KACV,CACF,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,SAAgB,wBAAwB,CACtC,KAAa,EACb,MAAc;IAEd,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,CAA8B,CAAC;IAClG,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,CAAC,CAAC;IAE1C,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,MAAK,gBAAgB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,IAAI,OAAO,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,CAAA,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC1J,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACL,YAAY;QACZ,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC;AACJ,CAAC","sourcesContent":["import * as jwt from 'jsonwebtoken';\nimport { createHmac } from 'crypto';\nimport type { AccessiOptions } from '../AccessiModule';\n\n/** Durata predefinita del token di reset. La monouso e garantita anche dal nonce persistito in `UTENTI.KEYREG`. */\nexport const DEFAULT_PASSWORD_RESET_EXPIRES_IN = '1h';\n\ninterface PasswordResetTokenPayload extends jwt.JwtPayload {\n nonce: string;\n typ: 'password-reset';\n}\n\n/** Scopo della chiave derivata: separa le chiavi di access token, reset password e 2FA. */\nexport type AccessiJwtPurpose = 'access' | 'reset' | '2fa';\n\n/**\n * Deriva una chiave JWT per scopo dal segreto configurato (key separation senza nuova configurazione).\n * Un leak della chiave di reset non compromette gli access token e viceversa.\n */\nexport function getAccessiJwtSecret(options: AccessiOptions, purpose: AccessiJwtPurpose = 'access'): string {\n const secret = options?.jwtOptions?.secret || process.env.ACC_JWT_SECRET;\n if (!secret) {\n throw new Error('JWT secret non configurato.');\n }\n\n return createHmac('sha256', secret).update(`accessi:jwt:${purpose}:v1`).digest('hex');\n}\n\n/** Crea un token firmato contenente solo codice utente e nonce; non inserire email o dati personali nelle claim. */\nexport function createPasswordResetToken(\n codiceUtente: number,\n nonce: string,\n secret: string,\n expiresIn: jwt.SignOptions['expiresIn'] = DEFAULT_PASSWORD_RESET_EXPIRES_IN,\n): string {\n if (!codiceUtente || !nonce) {\n throw new Error('Dati insufficienti per generare il reset token.');\n }\n\n return jwt.sign(\n {\n nonce,\n typ: 'password-reset',\n },\n secret,\n {\n subject: `${codiceUtente}`,\n expiresIn,\n },\n );\n}\n\n/** Verifica firma e scadenza, quindi restituisce i dati minimi necessari al reset. */\nexport function verifyPasswordResetToken(\n token: string,\n secret: string,\n): { codiceUtente: number; nonce: string } {\n const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] }) as PasswordResetTokenPayload;\n const codiceUtente = Number(decoded?.sub);\n\n if (decoded?.typ !== 'password-reset' || !Number.isSafeInteger(codiceUtente) || codiceUtente <= 0 || typeof decoded?.nonce !== 'string' || !decoded.nonce) {\n throw new Error('Token di reset non valido.');\n }\n\n return {\n codiceUtente,\n nonce: decoded.nonce,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"publicAuthRateLimit.js","sourceRoot":"","sources":["../../../src/accessi-module/security/publicAuthRateLimit.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpStatus } from '@nestjs/common';\r\nimport { Request, Response } from 'express';\r\nimport { RestUtilities } from '../../Utilities';\r\nimport type { AccessiOptions, PublicAuthRateLimitRuleOptions } from '../AccessiModule';\r\n\r\nexport type PublicAuthRateLimitScope =\r\n | 'login'\r\n | 'twoFactorVerify'\r\n | 'twoFactorResend'\r\n | 'register'\r\n | 'passwordResetEmail'\r\n | 'passwordResetConfirm'\r\n | 'getUserByToken';\r\n\r\ntype RateLimitBucket = {\r\n count: number;\r\n resetAt: number;\r\n lastSeenAt: number;\r\n};\r\n\r\ntype RateLimitDecision = {\r\n allowed: boolean;\r\n retryAfterSeconds: number;\r\n};\r\n\r\nconst DEFAULT_PUBLIC_AUTH_RATE_LIMITS: Record<\r\n PublicAuthRateLimitScope,\r\n PublicAuthRateLimitRuleOptions\r\n> = {\r\n login: { windowMs: 15 * 60 * 1000, maxAttempts: 10 },\r\n twoFactorVerify: { windowMs: 15 * 60 * 1000, maxAttempts: 20 },\r\n twoFactorResend: { windowMs: 15 * 60 * 1000, maxAttempts: 5 },\r\n register: { windowMs: 60 * 60 * 1000, maxAttempts: 5 },\r\n passwordResetEmail: { windowMs: 60 * 60 * 1000, maxAttempts: 5 },\r\n passwordResetConfirm: { windowMs: 15 * 60 * 1000, maxAttempts: 10 },\r\n getUserByToken: { windowMs: 5 * 60 * 1000, maxAttempts: 30 },\r\n};\r\n\r\nconst RATE_LIMIT_BUCKETS = new Map<string, RateLimitBucket>();\r\nconst MAX_TRACKED_BUCKETS = 20000;\r\nconst MAX_WINDOW_MS = Math.max(\r\n ...Object.values(DEFAULT_PUBLIC_AUTH_RATE_LIMITS).map((rule) => rule.windowMs),\r\n);\r\n\r\nfunction getRule(\r\n options: AccessiOptions,\r\n scope: PublicAuthRateLimitScope,\r\n): PublicAuthRateLimitRuleOptions {\r\n const configuredRule = options.publicAuthRateLimit?.[scope];\r\n\r\n if (\r\n configuredRule &&\r\n Number.isFinite(configuredRule.windowMs) &&\r\n configuredRule.windowMs > 0 &&\r\n Number.isFinite(configuredRule.maxAttempts) &&\r\n configuredRule.maxAttempts > 0\r\n ) {\r\n return {\r\n windowMs: Math.trunc(configuredRule.windowMs),\r\n maxAttempts: Math.trunc(configuredRule.maxAttempts),\r\n };\r\n }\r\n\r\n return DEFAULT_PUBLIC_AUTH_RATE_LIMITS[scope];\r\n}\r\n\r\nfunction normalizeIdentifier(identifier: string): string | null {\r\n if (typeof identifier !== 'string') {\r\n return null;\r\n }\r\n\r\n const normalized = identifier.trim().toLowerCase();\r\n return normalized === '' ? null : normalized;\r\n}\r\n\r\nfunction pruneRateLimitBuckets(now: number): void {\r\n if (RATE_LIMIT_BUCKETS.size < MAX_TRACKED_BUCKETS) {\r\n return;\r\n }\r\n\r\n for (const [key, bucket] of RATE_LIMIT_BUCKETS.entries()) {\r\n if (bucket.resetAt <= now || bucket.lastSeenAt <= now - MAX_WINDOW_MS * 2) {\r\n RATE_LIMIT_BUCKETS.delete(key);\r\n }\r\n\r\n if (RATE_LIMIT_BUCKETS.size < MAX_TRACKED_BUCKETS) {\r\n return;\r\n }\r\n }\r\n}\r\n\r\n/** Mantiene il numero di bucket sotto la soglia, scartando i meno recenti. */\r\nfunction enforceBucketCap(): void {\r\n while (RATE_LIMIT_BUCKETS.size >= MAX_TRACKED_BUCKETS) {\r\n let oldestKey: string | undefined;\r\n let oldestSeen = Number.POSITIVE_INFINITY;\r\n\r\n for (const [key, bucket] of RATE_LIMIT_BUCKETS.entries()) {\r\n if (bucket.lastSeenAt < oldestSeen) {\r\n oldestSeen = bucket.lastSeenAt;\r\n oldestKey = key;\r\n }\r\n }\r\n\r\n if (oldestKey === undefined) {\r\n return;\r\n }\r\n\r\n RATE_LIMIT_BUCKETS.delete(oldestKey);\r\n }\r\n}\r\n\r\nfunction consumeBucket(\r\n bucketKey: string,\r\n rule: PublicAuthRateLimitRuleOptions,\r\n now: number,\r\n): number | null {\r\n const existingBucket = RATE_LIMIT_BUCKETS.get(bucketKey);\r\n if (!existingBucket || existingBucket.resetAt <= now) {\r\n enforceBucketCap();\r\n RATE_LIMIT_BUCKETS.set(bucketKey, {\r\n count: 1,\r\n resetAt: now + rule.windowMs,\r\n lastSeenAt: now,\r\n });\r\n return null;\r\n }\r\n\r\n existingBucket.lastSeenAt = now;\r\n if (existingBucket.count >= rule.maxAttempts) {\r\n return Math.max(1, Math.ceil((existingBucket.resetAt - now) / 1000));\r\n }\r\n\r\n existingBucket.count += 1;\r\n return null;\r\n}\r\n\r\nexport function checkPublicAuthRateLimit(\r\n options: AccessiOptions,\r\n scope: PublicAuthRateLimitScope,\r\n req: Request,\r\n identifiers: string[] = [],\r\n): RateLimitDecision {\r\n if (options.publicAuthRateLimit?.enabled === false) {\r\n return { allowed: true, retryAfterSeconds: 0 };\r\n }\r\n\r\n const rule = getRule(options, scope);\r\n const now = Date.now();\r\n pruneRateLimitBuckets(now);\r\n\r\n const ipAddress =\r\n normalizeIdentifier(req.ip ?? req.socket?.remoteAddress ?? 'unknown') ?? 'unknown';\r\n\r\n // Consuma prima il bucket per IP: se gia bloccato non crea bucket per soggetto,\r\n // evitando crescita di memoria con identificatori sempre diversi.\r\n const ipRetryAfterSeconds = consumeBucket(`${scope}|ip|${ipAddress}`, rule, now);\r\n if (ipRetryAfterSeconds) {\r\n return { allowed: false, retryAfterSeconds: ipRetryAfterSeconds };\r\n }\r\n\r\n let retryAfterSeconds = 0;\r\n for (const identifier of identifiers) {\r\n const normalizedIdentifier = normalizeIdentifier(identifier);\r\n if (!normalizedIdentifier) {\r\n continue;\r\n }\r\n\r\n const bucketRetryAfterSeconds = consumeBucket(\r\n `${scope}|ip-subject|${ipAddress}|${normalizedIdentifier}`,\r\n rule,\r\n now,\r\n );\r\n if (bucketRetryAfterSeconds) {\r\n retryAfterSeconds = Math.max(retryAfterSeconds, bucketRetryAfterSeconds);\r\n }\r\n }\r\n\r\n if (retryAfterSeconds > 0) {\r\n return {\r\n allowed: false,\r\n retryAfterSeconds,\r\n };\r\n }\r\n\r\n return { allowed: true, retryAfterSeconds: 0 };\r\n}\r\n\r\nexport function sendPublicAuthRateLimitExceeded(\r\n res: Response,\r\n retryAfterSeconds: number,\r\n): Response {\r\n res.setHeader('Retry-After', String(retryAfterSeconds));\r\n return RestUtilities.sendErrorMessage(\r\n res,\r\n 'Troppi tentativi. Riprova piu tardi.',\r\n 'PublicAuthRateLimit',\r\n HttpStatus.TOO_MANY_REQUESTS,\r\n );\r\n}\r\n"]}
1
+ {"version":3,"file":"publicAuthRateLimit.js","sourceRoot":"","sources":["../../../src/accessi-module/security/publicAuthRateLimit.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpStatus } from '@nestjs/common';\nimport { Request, Response } from 'express';\nimport { RestUtilities } from '../../Utilities';\nimport type { AccessiOptions, PublicAuthRateLimitRuleOptions } from '../AccessiModule';\n\nexport type PublicAuthRateLimitScope =\n | 'login'\n | 'twoFactorVerify'\n | 'twoFactorResend'\n | 'register'\n | 'passwordResetEmail'\n | 'passwordResetConfirm'\n | 'getUserByToken';\n\ntype RateLimitBucket = {\n count: number;\n resetAt: number;\n lastSeenAt: number;\n};\n\ntype RateLimitDecision = {\n allowed: boolean;\n retryAfterSeconds: number;\n};\n\nconst DEFAULT_PUBLIC_AUTH_RATE_LIMITS: Record<\n PublicAuthRateLimitScope,\n PublicAuthRateLimitRuleOptions\n> = {\n login: { windowMs: 15 * 60 * 1000, maxAttempts: 10 },\n twoFactorVerify: { windowMs: 15 * 60 * 1000, maxAttempts: 20 },\n twoFactorResend: { windowMs: 15 * 60 * 1000, maxAttempts: 5 },\n register: { windowMs: 60 * 60 * 1000, maxAttempts: 5 },\n passwordResetEmail: { windowMs: 60 * 60 * 1000, maxAttempts: 5 },\n passwordResetConfirm: { windowMs: 15 * 60 * 1000, maxAttempts: 10 },\n getUserByToken: { windowMs: 5 * 60 * 1000, maxAttempts: 30 },\n};\n\nconst RATE_LIMIT_BUCKETS = new Map<string, RateLimitBucket>();\nconst MAX_TRACKED_BUCKETS = 20000;\nconst MAX_WINDOW_MS = Math.max(\n ...Object.values(DEFAULT_PUBLIC_AUTH_RATE_LIMITS).map((rule) => rule.windowMs),\n);\n\nfunction getRule(\n options: AccessiOptions,\n scope: PublicAuthRateLimitScope,\n): PublicAuthRateLimitRuleOptions {\n const configuredRule = options.publicAuthRateLimit?.[scope];\n\n if (\n configuredRule &&\n Number.isFinite(configuredRule.windowMs) &&\n configuredRule.windowMs > 0 &&\n Number.isFinite(configuredRule.maxAttempts) &&\n configuredRule.maxAttempts > 0\n ) {\n return {\n windowMs: Math.trunc(configuredRule.windowMs),\n maxAttempts: Math.trunc(configuredRule.maxAttempts),\n };\n }\n\n return DEFAULT_PUBLIC_AUTH_RATE_LIMITS[scope];\n}\n\nfunction normalizeIdentifier(identifier: string): string | null {\n if (typeof identifier !== 'string') {\n return null;\n }\n\n const normalized = identifier.trim().toLowerCase();\n return normalized === '' ? null : normalized;\n}\n\nfunction pruneRateLimitBuckets(now: number): void {\n if (RATE_LIMIT_BUCKETS.size < MAX_TRACKED_BUCKETS) {\n return;\n }\n\n for (const [key, bucket] of RATE_LIMIT_BUCKETS.entries()) {\n if (bucket.resetAt <= now || bucket.lastSeenAt <= now - MAX_WINDOW_MS * 2) {\n RATE_LIMIT_BUCKETS.delete(key);\n }\n\n if (RATE_LIMIT_BUCKETS.size < MAX_TRACKED_BUCKETS) {\n return;\n }\n }\n}\n\n/** Mantiene il numero di bucket sotto la soglia, scartando i meno recenti. */\nfunction enforceBucketCap(): void {\n while (RATE_LIMIT_BUCKETS.size >= MAX_TRACKED_BUCKETS) {\n let oldestKey: string | undefined;\n let oldestSeen = Number.POSITIVE_INFINITY;\n\n for (const [key, bucket] of RATE_LIMIT_BUCKETS.entries()) {\n if (bucket.lastSeenAt < oldestSeen) {\n oldestSeen = bucket.lastSeenAt;\n oldestKey = key;\n }\n }\n\n if (oldestKey === undefined) {\n return;\n }\n\n RATE_LIMIT_BUCKETS.delete(oldestKey);\n }\n}\n\nfunction consumeBucket(\n bucketKey: string,\n rule: PublicAuthRateLimitRuleOptions,\n now: number,\n): number | null {\n const existingBucket = RATE_LIMIT_BUCKETS.get(bucketKey);\n if (!existingBucket || existingBucket.resetAt <= now) {\n enforceBucketCap();\n RATE_LIMIT_BUCKETS.set(bucketKey, {\n count: 1,\n resetAt: now + rule.windowMs,\n lastSeenAt: now,\n });\n return null;\n }\n\n existingBucket.lastSeenAt = now;\n if (existingBucket.count >= rule.maxAttempts) {\n return Math.max(1, Math.ceil((existingBucket.resetAt - now) / 1000));\n }\n\n existingBucket.count += 1;\n return null;\n}\n\nexport function checkPublicAuthRateLimit(\n options: AccessiOptions,\n scope: PublicAuthRateLimitScope,\n req: Request,\n identifiers: string[] = [],\n): RateLimitDecision {\n if (options.publicAuthRateLimit?.enabled === false) {\n return { allowed: true, retryAfterSeconds: 0 };\n }\n\n const rule = getRule(options, scope);\n const now = Date.now();\n pruneRateLimitBuckets(now);\n\n const ipAddress =\n normalizeIdentifier(req.ip ?? req.socket?.remoteAddress ?? 'unknown') ?? 'unknown';\n\n // Consuma prima il bucket per IP: se gia bloccato non crea bucket per soggetto,\n // evitando crescita di memoria con identificatori sempre diversi.\n const ipRetryAfterSeconds = consumeBucket(`${scope}|ip|${ipAddress}`, rule, now);\n if (ipRetryAfterSeconds) {\n return { allowed: false, retryAfterSeconds: ipRetryAfterSeconds };\n }\n\n let retryAfterSeconds = 0;\n for (const identifier of identifiers) {\n const normalizedIdentifier = normalizeIdentifier(identifier);\n if (!normalizedIdentifier) {\n continue;\n }\n\n const bucketRetryAfterSeconds = consumeBucket(\n `${scope}|ip-subject|${ipAddress}|${normalizedIdentifier}`,\n rule,\n now,\n );\n if (bucketRetryAfterSeconds) {\n retryAfterSeconds = Math.max(retryAfterSeconds, bucketRetryAfterSeconds);\n }\n }\n\n if (retryAfterSeconds > 0) {\n return {\n allowed: false,\n retryAfterSeconds,\n };\n }\n\n return { allowed: true, retryAfterSeconds: 0 };\n}\n\nexport function sendPublicAuthRateLimitExceeded(\n res: Response,\n retryAfterSeconds: number,\n): Response {\n res.setHeader('Retry-After', String(retryAfterSeconds));\n return RestUtilities.sendErrorMessage(\n res,\n 'Troppi tentativi. Riprova piu tardi.',\n 'PublicAuthRateLimit',\n HttpStatus.TOO_MANY_REQUESTS,\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AllegatiModule.js","sourceRoot":"","sources":["../../src/allegati-module/AllegatiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA+D;AAG/D,sCAAmC;AACnC,gFAA6E;AAC7E,yEAAsE;AACtE,sFAAmF;AAsB5E,IAAM,cAAc,sBAApB,MAAM,cAAc;IAEvB,MAAM,CAAC,OAAO,CAAC,OAAwB;QACnC,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,gBAAc,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,oBAAoB,MAAK,KAAK,EAAE,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,yJAAyJ,CAAC,CAAC;QAC9K,CAAC;aAAM,IAAI,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,SAAS,CAAA,EAAE,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,kLAAkL,CAAC,CAAC;QACrM,CAAC;QAED,OAAO;YACH,MAAM,EAAE,gBAAc;YACtB,SAAS,EAAE;gBACP;oBACI,OAAO,EAAE,kBAAkB;oBAC3B,QAAQ,EAAE,OAAO;iBACpB;gBACD,iCAAe;gBACf,uDAA0B;aAC7B;YACD,OAAO,EAAE,CAAC,kBAAkB,EAAE,iCAAe,CAAC;SACjD,CAAC;IACN,CAAC;CACJ,CAAA;AAvBY,wCAAc;yBAAd,cAAc;IAN1B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACJ,WAAW,EAAE,CAAC,uCAAkB,CAAC;QACjC,SAAS,EAAE,CAAC,iCAAe,EAAE,uDAA0B,CAAC;QACxD,OAAO,EAAE,CAAC,iCAAe,CAAC;KAC7B,CAAC;GACW,cAAc,CAuB1B","sourcesContent":["import { DynamicModule, Global, Module } from \"@nestjs/common\";\r\nimport { Request } from \"express\";\r\nimport { Options } from \"node-firebird\";\r\nimport { Logger } from \"../Logger\";\r\nimport { AllegatiService } from \"./Services/AllegatiService/AllegatiService\";\r\nimport { AllegatiController } from \"./Controllers/AllegatiController\";\r\nimport { AllegatiAuthorizationGuard } from \"./security/allegatiAuthorizationGuard\";\r\n\r\nexport interface AllegatiOptions {\r\n databaseOptions: Options;\r\n /**\r\n * Guard applicato a ogni richiesta dei controller Allegati.\r\n * Se definito e restituisce `false`, la richiesta viene rifiutata con 403.\r\n */\r\n authorize?: (request: Request) => boolean | Promise<boolean>;\r\n /**\r\n * Sicurezza by default: se `authorize` non e configurato, le richieste vengono rifiutate con 403.\r\n * Impostare `false` per ripristinare il comportamento storico (endpoint aperti) durante la migrazione.\r\n */\r\n requireAuthorization?: boolean;\r\n}\r\n\r\n@Global()\r\n@Module({\r\n controllers: [AllegatiController],\r\n providers: [AllegatiService, AllegatiAuthorizationGuard],\r\n exports: [AllegatiService],\r\n})\r\nexport class AllegatiModule {\r\n\r\n static forRoot(options: AllegatiOptions): DynamicModule {\r\n const logger = new Logger(AllegatiModule.name);\r\n if (options?.requireAuthorization === false) {\r\n logger.warning('Allegati con requireAuthorization: false: gli endpoint sono accessibili senza controllo di autorizzazione. Configurare authorize e rimuovere l opt-out.');\r\n } else if (!options?.authorize) {\r\n logger.error('Allegati senza authorize: tutte le richieste saranno rifiutate con 403. Configurare allegatiOptions.authorize (oppure requireAuthorization: false per il comportamento storico).');\r\n }\r\n\r\n return {\r\n module: AllegatiModule,\r\n providers: [\r\n {\r\n provide: 'ALLEGATI_OPTIONS',\r\n useValue: options,\r\n },\r\n AllegatiService,\r\n AllegatiAuthorizationGuard,\r\n ],\r\n exports: ['ALLEGATI_OPTIONS', AllegatiService],\r\n };\r\n }\r\n}\n"]}
1
+ {"version":3,"file":"AllegatiModule.js","sourceRoot":"","sources":["../../src/allegati-module/AllegatiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA+D;AAG/D,sCAAmC;AACnC,gFAA6E;AAC7E,yEAAsE;AACtE,sFAAmF;AAsB5E,IAAM,cAAc,sBAApB,MAAM,cAAc;IAEvB,MAAM,CAAC,OAAO,CAAC,OAAwB;QACnC,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,gBAAc,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,oBAAoB,MAAK,KAAK,EAAE,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,yJAAyJ,CAAC,CAAC;QAC9K,CAAC;aAAM,IAAI,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,SAAS,CAAA,EAAE,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,kLAAkL,CAAC,CAAC;QACrM,CAAC;QAED,OAAO;YACH,MAAM,EAAE,gBAAc;YACtB,SAAS,EAAE;gBACP;oBACI,OAAO,EAAE,kBAAkB;oBAC3B,QAAQ,EAAE,OAAO;iBACpB;gBACD,iCAAe;gBACf,uDAA0B;aAC7B;YACD,OAAO,EAAE,CAAC,kBAAkB,EAAE,iCAAe,CAAC;SACjD,CAAC;IACN,CAAC;CACJ,CAAA;AAvBY,wCAAc;yBAAd,cAAc;IAN1B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACJ,WAAW,EAAE,CAAC,uCAAkB,CAAC;QACjC,SAAS,EAAE,CAAC,iCAAe,EAAE,uDAA0B,CAAC;QACxD,OAAO,EAAE,CAAC,iCAAe,CAAC;KAC7B,CAAC;GACW,cAAc,CAuB1B","sourcesContent":["import { DynamicModule, Global, Module } from \"@nestjs/common\";\nimport { Request } from \"express\";\nimport { Options } from \"node-firebird\";\nimport { Logger } from \"../Logger\";\nimport { AllegatiService } from \"./Services/AllegatiService/AllegatiService\";\nimport { AllegatiController } from \"./Controllers/AllegatiController\";\nimport { AllegatiAuthorizationGuard } from \"./security/allegatiAuthorizationGuard\";\n\nexport interface AllegatiOptions {\n databaseOptions: Options;\n /**\n * Guard applicato a ogni richiesta dei controller Allegati.\n * Se definito e restituisce `false`, la richiesta viene rifiutata con 403.\n */\n authorize?: (request: Request) => boolean | Promise<boolean>;\n /**\n * Sicurezza by default: se `authorize` non e configurato, le richieste vengono rifiutate con 403.\n * Impostare `false` per ripristinare il comportamento storico (endpoint aperti) durante la migrazione.\n */\n requireAuthorization?: boolean;\n}\n\n@Global()\n@Module({\n controllers: [AllegatiController],\n providers: [AllegatiService, AllegatiAuthorizationGuard],\n exports: [AllegatiService],\n})\nexport class AllegatiModule {\n\n static forRoot(options: AllegatiOptions): DynamicModule {\n const logger = new Logger(AllegatiModule.name);\n if (options?.requireAuthorization === false) {\n logger.warning('Allegati con requireAuthorization: false: gli endpoint sono accessibili senza controllo di autorizzazione. Configurare authorize e rimuovere l opt-out.');\n } else if (!options?.authorize) {\n logger.error('Allegati senza authorize: tutte le richieste saranno rifiutate con 403. Configurare allegatiOptions.authorize (oppure requireAuthorization: false per il comportamento storico).');\n }\n\n return {\n module: AllegatiModule,\n providers: [\n {\n provide: 'ALLEGATI_OPTIONS',\n useValue: options,\n },\n AllegatiService,\n AllegatiAuthorizationGuard,\n ],\n exports: ['ALLEGATI_OPTIONS', AllegatiService],\n };\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AllegatiController.js","sourceRoot":"","sources":["../../../src/allegati-module/Controllers/AllegatiController.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApiBody, ApiConsumes, ApiResponse, ApiQuery} from \"@nestjs/swagger\";\r\n\r\nimport { Controller, Post, Get, Delete, Param, UploadedFiles, UseGuards, UseInterceptors, BadRequestException, Body, Response, Query, Res, Patch } from \"@nestjs/common\";\r\nimport { FilesInterceptor } from \"@nestjs/platform-express\";\r\nimport { AllegatiAuthorizationGuard } from \"../security/allegatiAuthorizationGuard\";\r\nimport { AllegatiService } from \"../Services/AllegatiService/AllegatiService\";\r\nimport {UploadAllegatoResponseDto} from \"../Dtos/responses/UploadAllegatoResponseDto\";\r\nimport {AllegatoDto} from \"../Dtos/AllegatoDto\";\r\nimport {DownloadAllegatoResponseDto} from \"../Dtos/responses/DownloadAllegatoResponseDto\";\r\nimport { UploadSingleFileRequest } from \"../Dtos/UploadSingleFileRequest\";\r\nimport { RestUtilities } from \"../../Utilities\";\r\nimport { Logger } from \"../../Logger\";\r\nimport e from \"express\";\r\n\r\n@UseGuards(AllegatiAuthorizationGuard)\r\n@Controller('allegati')\r\nexport class AllegatiController {\r\n private readonly logger = new Logger(AllegatiController.name);\r\n\r\n constructor(private readonly allegatiService: AllegatiService) {}\r\n\r\n @Post('upload')\r\n @UseInterceptors(FilesInterceptor('file', 1, { limits: { fileSize: 90 * 1024 * 1024, files: 1 } }))\r\n @ApiConsumes('multipart/form-data')\r\n @ApiResponse({ status: 201, description: 'File caricato con successo.', type: UploadAllegatoResponseDto })\r\n @ApiBody({\r\n description: 'File e metadati per l\\'upload di un allegato',\r\n required: true,\r\n schema: {\r\n type: 'object',\r\n properties: {\r\n file: {\r\n type: 'string',\r\n format: 'binary',\r\n },\r\n codice: { type: 'integer', example: 1 },\r\n tipoCodice: { type: 'string', example: 'CF' },\r\n ordine: { type: 'string', example: '1' },\r\n descrizioneAllegato: { type: 'string', example: 'Documento di identità' },\r\n dataInizioValidita: { type: 'string', format: 'date', example: '2024-01-01' },\r\n dataFineValidita: { type: 'string', format: 'date', example: '2025-01-01' },\r\n idTipoAllegato: { type: 'integer', example: 3 },\r\n riferimentoDocumento: { type: 'string', example: 'PRAT-2024-0001' }\r\n },\r\n },\r\n })\r\n async upload(\r\n @UploadedFiles() files: Express.Multer.File[],\r\n @Body() uploadRequest: UploadSingleFileRequest\r\n ): Promise<UploadAllegatoResponseDto> {\r\n if (!files || files.length === 0) {\r\n throw new BadRequestException('Nessun file fornito');\r\n }\r\n if (files.length > 1) {\r\n throw new BadRequestException('Questo endpoint accetta un solo file alla volta');\r\n }\r\n const file = files[0];\r\n if (!file) {\r\n throw new BadRequestException('Nessun file fornito');\r\n }\r\n return await this.allegatiService.uploadFile(file, uploadRequest);\r\n }\r\n\r\n @Get(':id')\r\n @ApiResponse({ status: 200, description: 'File scaricato con successo.', type: DownloadAllegatoResponseDto })\r\n async download(@Param('id') id: number): Promise<DownloadAllegatoResponseDto> {\r\n return await this.allegatiService.downloadFile(id);\r\n }\r\n\r\n @Get(':id/download')\r\n @ApiResponse({ status: 200, description: 'File scaricato con successo.' })\r\n async downloadFile(\r\n @Param('id') id: number,\r\n @Res() res: e.Response\r\n ): Promise<void> {\r\n try {\r\n const file = await this.allegatiService.downloadFile(id);\r\n \r\n // Convert base64 to buffer in chunks; Buffer.concat evita i NUL finali del prealloc.\r\n const chunkSize = 1024 * 1024; // 1MB chunks\r\n const base64Content = file.contentBase64;\r\n const chunks: Buffer[] = [];\r\n for (let i = 0; i < base64Content.length; i += chunkSize) {\r\n const chunk = base64Content.slice(i, i + chunkSize);\r\n chunks.push(Buffer.from(chunk, 'base64'));\r\n }\r\n const buffer = Buffer.concat(chunks);\r\n\r\n // Set headers for file download; filename* (RFC 5987) per i nomi non ASCII.\r\n const asciiName = file.filename.replace(/[^\\x20-\\x7e]/g, '_').replace(/[\"\\\\]/g, '_');\r\n res.setHeader('Content-Type', file.mimetype ?? 'application/octet-stream');\r\n res.setHeader('Content-Disposition', `attachment; filename=\"${asciiName}\"; filename*=UTF-8''${encodeURIComponent(file.filename)}`);\r\n res.setHeader('Content-Length', buffer.length);\r\n \r\n res.status(200).end(buffer);\r\n } catch (error) {\r\n this.logger.error('[AllegatiController] downloadFile - Errore:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n @Delete(':id')\r\n @ApiResponse({ status: 200, description: 'File eliminato con successo.' })\r\n async delete(@Param('id') id: number, @Response() res: e.Response) {\r\n await this.allegatiService.deleteFile(id);\r\n return RestUtilities.sendOKMessage(res, \"File eliminato con successo\");\r\n }\r\n\r\n @Get()\r\n @ApiResponse({ status: 200, description: 'Lista degli allegati.', type: [AllegatoDto] })\r\n @ApiQuery({ name: 'tipcod', required: false, description: 'Filtra per tipo codice' })\r\n @ApiQuery({ name: 'codice', required: false, description: 'Filtra per codice' })\r\n @ApiQuery({ name: 'docrif', required: false, description: 'Filtra per riferimento documento' })\r\n @ApiQuery({ name: 'idxtipoall', required: false, description: 'Filtra per tipo allegato', type: Number })\r\n async list(\r\n @Query('tipcod') tipcod?: string,\r\n @Query('codice') codice?: number,\r\n @Query('docrif') docrif?: string,\r\n @Query('idxtipoall') idxtipoall?: number\r\n ): Promise<AllegatoDto[]> {\r\n return await this.allegatiService.listFiles({\r\n tipcod,\r\n codice,\r\n docrif,\r\n idxtipoall: idxtipoall ? Number(idxtipoall) : undefined\r\n });\r\n }\r\n\r\n @Post('search')\r\n@ApiResponse({ status: 200, description: 'Ricerca allegati per campi.' })\r\nasync searchByFields(@Body() body: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }) {\r\n return await this.allegatiService.findByFields(body);\r\n}\r\n\r\n@Post('get-by-fields')\r\n@ApiResponse({ status: 200, description: 'Ottieni un allegato per campi.' })\r\nasync getOneByFields(@Body() body: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }) {\r\n return await this.allegatiService.getOneByFields(body);\r\n}\r\n\r\n@Patch('update-fields/:id')\r\n@ApiResponse({ status: 200, description: 'Aggiorna i campi di un allegato.' })\r\nasync updateFieldsById(\r\n @Param('id') id: number,\r\n @Body() body: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }\r\n) {\r\n await this.allegatiService.updateFieldsById(Number(id), body);\r\n return { message: 'Aggiornamento completato' };\r\n}\r\n}"]}
1
+ {"version":3,"file":"AllegatiController.js","sourceRoot":"","sources":["../../../src/allegati-module/Controllers/AllegatiController.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApiBody, ApiConsumes, ApiResponse, ApiQuery} from \"@nestjs/swagger\";\n\nimport { Controller, Post, Get, Delete, Param, UploadedFiles, UseGuards, UseInterceptors, BadRequestException, Body, Response, Query, Res, Patch } from \"@nestjs/common\";\nimport { FilesInterceptor } from \"@nestjs/platform-express\";\nimport { AllegatiAuthorizationGuard } from \"../security/allegatiAuthorizationGuard\";\nimport { AllegatiService } from \"../Services/AllegatiService/AllegatiService\";\nimport {UploadAllegatoResponseDto} from \"../Dtos/responses/UploadAllegatoResponseDto\";\nimport {AllegatoDto} from \"../Dtos/AllegatoDto\";\nimport {DownloadAllegatoResponseDto} from \"../Dtos/responses/DownloadAllegatoResponseDto\";\nimport { UploadSingleFileRequest } from \"../Dtos/UploadSingleFileRequest\";\nimport { RestUtilities } from \"../../Utilities\";\nimport { Logger } from \"../../Logger\";\nimport e from \"express\";\n\n@UseGuards(AllegatiAuthorizationGuard)\n@Controller('allegati')\nexport class AllegatiController {\n private readonly logger = new Logger(AllegatiController.name);\n\n constructor(private readonly allegatiService: AllegatiService) {}\n\n @Post('upload')\n @UseInterceptors(FilesInterceptor('file', 1, { limits: { fileSize: 90 * 1024 * 1024, files: 1 } }))\n @ApiConsumes('multipart/form-data')\n @ApiResponse({ status: 201, description: 'File caricato con successo.', type: UploadAllegatoResponseDto })\n @ApiBody({\n description: 'File e metadati per l\\'upload di un allegato',\n required: true,\n schema: {\n type: 'object',\n properties: {\n file: {\n type: 'string',\n format: 'binary',\n },\n codice: { type: 'integer', example: 1 },\n tipoCodice: { type: 'string', example: 'CF' },\n ordine: { type: 'string', example: '1' },\n descrizioneAllegato: { type: 'string', example: 'Documento di identità' },\n dataInizioValidita: { type: 'string', format: 'date', example: '2024-01-01' },\n dataFineValidita: { type: 'string', format: 'date', example: '2025-01-01' },\n idTipoAllegato: { type: 'integer', example: 3 },\n riferimentoDocumento: { type: 'string', example: 'PRAT-2024-0001' }\n },\n },\n })\n async upload(\n @UploadedFiles() files: Express.Multer.File[],\n @Body() uploadRequest: UploadSingleFileRequest\n ): Promise<UploadAllegatoResponseDto> {\n if (!files || files.length === 0) {\n throw new BadRequestException('Nessun file fornito');\n }\n if (files.length > 1) {\n throw new BadRequestException('Questo endpoint accetta un solo file alla volta');\n }\n const file = files[0];\n if (!file) {\n throw new BadRequestException('Nessun file fornito');\n }\n return await this.allegatiService.uploadFile(file, uploadRequest);\n }\n\n @Get(':id')\n @ApiResponse({ status: 200, description: 'File scaricato con successo.', type: DownloadAllegatoResponseDto })\n async download(@Param('id') id: number): Promise<DownloadAllegatoResponseDto> {\n return await this.allegatiService.downloadFile(id);\n }\n\n @Get(':id/download')\n @ApiResponse({ status: 200, description: 'File scaricato con successo.' })\n async downloadFile(\n @Param('id') id: number,\n @Res() res: e.Response\n ): Promise<void> {\n try {\n const file = await this.allegatiService.downloadFile(id);\n \n // Convert base64 to buffer in chunks; Buffer.concat evita i NUL finali del prealloc.\n const chunkSize = 1024 * 1024; // 1MB chunks\n const base64Content = file.contentBase64;\n const chunks: Buffer[] = [];\n for (let i = 0; i < base64Content.length; i += chunkSize) {\n const chunk = base64Content.slice(i, i + chunkSize);\n chunks.push(Buffer.from(chunk, 'base64'));\n }\n const buffer = Buffer.concat(chunks);\n\n // Set headers for file download; filename* (RFC 5987) per i nomi non ASCII.\n const asciiName = file.filename.replace(/[^\\x20-\\x7e]/g, '_').replace(/[\"\\\\]/g, '_');\n res.setHeader('Content-Type', file.mimetype ?? 'application/octet-stream');\n res.setHeader('Content-Disposition', `attachment; filename=\"${asciiName}\"; filename*=UTF-8''${encodeURIComponent(file.filename)}`);\n res.setHeader('Content-Length', buffer.length);\n \n res.status(200).end(buffer);\n } catch (error) {\n this.logger.error('[AllegatiController] downloadFile - Errore:', error);\n throw error;\n }\n }\n\n @Delete(':id')\n @ApiResponse({ status: 200, description: 'File eliminato con successo.' })\n async delete(@Param('id') id: number, @Response() res: e.Response) {\n await this.allegatiService.deleteFile(id);\n return RestUtilities.sendOKMessage(res, \"File eliminato con successo\");\n }\n\n @Get()\n @ApiResponse({ status: 200, description: 'Lista degli allegati.', type: [AllegatoDto] })\n @ApiQuery({ name: 'tipcod', required: false, description: 'Filtra per tipo codice' })\n @ApiQuery({ name: 'codice', required: false, description: 'Filtra per codice' })\n @ApiQuery({ name: 'docrif', required: false, description: 'Filtra per riferimento documento' })\n @ApiQuery({ name: 'idxtipoall', required: false, description: 'Filtra per tipo allegato', type: Number })\n async list(\n @Query('tipcod') tipcod?: string,\n @Query('codice') codice?: number,\n @Query('docrif') docrif?: string,\n @Query('idxtipoall') idxtipoall?: number\n ): Promise<AllegatoDto[]> {\n return await this.allegatiService.listFiles({\n tipcod,\n codice,\n docrif,\n idxtipoall: idxtipoall ? Number(idxtipoall) : undefined\n });\n }\n\n @Post('search')\n@ApiResponse({ status: 200, description: 'Ricerca allegati per campi.' })\nasync searchByFields(@Body() body: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }) {\n return await this.allegatiService.findByFields(body);\n}\n\n@Post('get-by-fields')\n@ApiResponse({ status: 200, description: 'Ottieni un allegato per campi.' })\nasync getOneByFields(@Body() body: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }) {\n return await this.allegatiService.getOneByFields(body);\n}\n\n@Patch('update-fields/:id')\n@ApiResponse({ status: 200, description: 'Aggiorna i campi di un allegato.' })\nasync updateFieldsById(\n @Param('id') id: number,\n @Body() body: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }\n) {\n await this.allegatiService.updateFieldsById(Number(id), body);\n return { message: 'Aggiornamento completato' };\n}\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AllegatoDto.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/AllegatoDto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAA6E;AAE7E,MAAa,WAAW;CAgGvB;AAhGD,kCAgGC;AAzFG;IALC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,2BAA2B;QACxC,OAAO,EAAE,CAAC;KACb,CAAC;IACD,IAAA,0BAAQ,GAAE;;uCACC;AAQZ;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,kCAAkC;QAC/C,OAAO,EAAE,eAAe;KAC3B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;6CACtC;AAQlB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oBAAoB;QACjC,OAAO,EAAE,iBAAiB;KAC7B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;6CACtC;AAQlB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,6CAA6C;QAC1D,OAAO,EAAE,sBAAsB;KAClC,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC;;+CACzC;AAQpB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qBAAqB;QAClC,OAAO,EAAE,GAAG;KACf,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;2CACG;AAQhB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,IAAI;KAChB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;+CACO;AAQpB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,8EAA8E;QAC3F,OAAO,EAAE,GAAG;KACf,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;2CACG;AAQhB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,8BAA8B;KAC1C,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;wDACgB;AAQ7B;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,uCAAuC;QACpD,OAAO,EAAE,YAAY;KACxB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;uDACe;AAQ5B;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,YAAY;KACxB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;qDACa;AAQ1B;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,CAAC;KACb,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;mDACW;AAQxB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oDAAoD;QACjE,OAAO,EAAE,gBAAgB;KAC5B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;yDACiB","sourcesContent":["import { ApiProperty } from \"@nestjs/swagger\";\r\nimport { IsString, IsNotEmpty, IsNumber, IsOptional } from \"class-validator\";\r\n\r\nexport class AllegatoDto {\r\n\r\n @ApiProperty({\r\n description: 'ID univoco dell\\'allegato',\r\n example: 1,\r\n })\r\n @IsNumber()\r\n id!: number;\r\n\r\n @ApiProperty({\r\n description: 'Nome originale del file caricato',\r\n example: 'documento.pdf',\r\n })\r\n @IsString()\r\n @IsNotEmpty({ message: \"Il nome file è obbligatorio.\" })\r\n filename!: string;\r\n\r\n @ApiProperty({\r\n description: 'Tipo MIME del file',\r\n example: 'application/pdf',\r\n })\r\n @IsString()\r\n @IsNotEmpty({ message: \"Il tipo MIME è obbligatorio.\" })\r\n mimetype!: string;\r\n\r\n @ApiProperty({\r\n description: 'Data di caricamento del file in formato ISO',\r\n example: '2025-04-27T12:00:00Z',\r\n })\r\n @IsString()\r\n @IsNotEmpty({ message: \"La data di upload è obbligatoria.\" })\r\n uploadDate!: string;\r\n\r\n @ApiProperty({\r\n description: 'Codice incrementale',\r\n example: '1',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n codice?: string;\r\n\r\n @ApiProperty({\r\n description: 'Tipo del codice fornito',\r\n example: 'CF',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n tipoCodice?: string;\r\n\r\n @ApiProperty({\r\n description: 'Numero o valore usato per ordinare o identificare la sequenza degli allegati',\r\n example: '1',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n ordine?: string;\r\n\r\n @ApiProperty({\r\n description: 'Descrizione testuale dell\\'allegato',\r\n example: 'Documento di identità fronte',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n descrizioneAllegato?: string;\r\n\r\n @ApiProperty({\r\n description: 'Data di inizio validità del documento',\r\n example: '2024-01-01',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n dataInizioValidita?: string;\r\n\r\n @ApiProperty({\r\n description: 'Data di fine validità del documento',\r\n example: '2025-01-01',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n dataFineValidita?: string;\r\n\r\n @ApiProperty({\r\n description: 'ID del tipo di allegato',\r\n example: 3,\r\n })\r\n @IsNumber()\r\n @IsOptional()\r\n idTipoAllegato?: number;\r\n\r\n @ApiProperty({\r\n description: 'Riferimento esterno o identificativo del documento',\r\n example: 'PRAT-2024-0001',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n riferimentoDocumento?: string;\r\n}"]}
1
+ {"version":3,"file":"AllegatoDto.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/AllegatoDto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAA6E;AAE7E,MAAa,WAAW;CAgGvB;AAhGD,kCAgGC;AAzFG;IALC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,2BAA2B;QACxC,OAAO,EAAE,CAAC;KACb,CAAC;IACD,IAAA,0BAAQ,GAAE;;uCACC;AAQZ;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,kCAAkC;QAC/C,OAAO,EAAE,eAAe;KAC3B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;6CACtC;AAQlB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oBAAoB;QACjC,OAAO,EAAE,iBAAiB;KAC7B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;6CACtC;AAQlB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,6CAA6C;QAC1D,OAAO,EAAE,sBAAsB;KAClC,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC;;+CACzC;AAQpB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qBAAqB;QAClC,OAAO,EAAE,GAAG;KACf,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;2CACG;AAQhB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,IAAI;KAChB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;+CACO;AAQpB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,8EAA8E;QAC3F,OAAO,EAAE,GAAG;KACf,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;2CACG;AAQhB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,8BAA8B;KAC1C,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;wDACgB;AAQ7B;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,uCAAuC;QACpD,OAAO,EAAE,YAAY;KACxB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;uDACe;AAQ5B;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,YAAY;KACxB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;qDACa;AAQ1B;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,CAAC;KACb,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;mDACW;AAQxB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oDAAoD;QACjE,OAAO,EAAE,gBAAgB;KAC5B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;yDACiB","sourcesContent":["import { ApiProperty } from \"@nestjs/swagger\";\nimport { IsString, IsNotEmpty, IsNumber, IsOptional } from \"class-validator\";\n\nexport class AllegatoDto {\n\n @ApiProperty({\n description: 'ID univoco dell\\'allegato',\n example: 1,\n })\n @IsNumber()\n id!: number;\n\n @ApiProperty({\n description: 'Nome originale del file caricato',\n example: 'documento.pdf',\n })\n @IsString()\n @IsNotEmpty({ message: \"Il nome file è obbligatorio.\" })\n filename!: string;\n\n @ApiProperty({\n description: 'Tipo MIME del file',\n example: 'application/pdf',\n })\n @IsString()\n @IsNotEmpty({ message: \"Il tipo MIME è obbligatorio.\" })\n mimetype!: string;\n\n @ApiProperty({\n description: 'Data di caricamento del file in formato ISO',\n example: '2025-04-27T12:00:00Z',\n })\n @IsString()\n @IsNotEmpty({ message: \"La data di upload è obbligatoria.\" })\n uploadDate!: string;\n\n @ApiProperty({\n description: 'Codice incrementale',\n example: '1',\n })\n @IsString()\n @IsOptional()\n codice?: string;\n\n @ApiProperty({\n description: 'Tipo del codice fornito',\n example: 'CF',\n })\n @IsString()\n @IsOptional()\n tipoCodice?: string;\n\n @ApiProperty({\n description: 'Numero o valore usato per ordinare o identificare la sequenza degli allegati',\n example: '1',\n })\n @IsString()\n @IsOptional()\n ordine?: string;\n\n @ApiProperty({\n description: 'Descrizione testuale dell\\'allegato',\n example: 'Documento di identità fronte',\n })\n @IsString()\n @IsOptional()\n descrizioneAllegato?: string;\n\n @ApiProperty({\n description: 'Data di inizio validità del documento',\n example: '2024-01-01',\n })\n @IsString()\n @IsOptional()\n dataInizioValidita?: string;\n\n @ApiProperty({\n description: 'Data di fine validità del documento',\n example: '2025-01-01',\n })\n @IsString()\n @IsOptional()\n dataFineValidita?: string;\n\n @ApiProperty({\n description: 'ID del tipo di allegato',\n example: 3,\n })\n @IsNumber()\n @IsOptional()\n idTipoAllegato?: number;\n\n @ApiProperty({\n description: 'Riferimento esterno o identificativo del documento',\n example: 'PRAT-2024-0001',\n })\n @IsString()\n @IsOptional()\n riferimentoDocumento?: string;\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"BaseResponse.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/BaseResponse.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,yDAAyC;AACzC,qDAAqE;AAErE,MAAa,MAAM;CAQlB;AARD,wBAQC;AALC;IAFC,IAAA,qBAAW,EAAC,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;IAC/E,IAAA,0BAAQ,GAAE;;yCACQ;AAInB;IAFC,IAAA,qBAAW,EAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC;IACvF,IAAA,0BAAQ,GAAE;;gDACe;AAG5B,MAAsB,YAAY;CAMjC;AAND,oCAMC;AADC;IAJC,IAAA,qBAAW,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7B,IAAA,gCAAc,GAAE;IAChB,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,0BAAQ,GAAE;8BACF,MAAM;4CAAC","sourcesContent":["import { ApiProperty } from '@nestjs/swagger';\r\nimport { Type } from 'class-transformer';\r\nimport { IsObject, IsString, ValidateNested } from 'class-validator';\r\n\r\nexport class Status {\r\n @ApiProperty({ example: '0', description: 'Codice di errore, \"0\" se tutto ok' })\r\n @IsString()\r\n errorCode!: string;\r\n\r\n @ApiProperty({ example: 'Success', description: 'Descrizione dell\\'errore o successo' })\r\n @IsString()\r\n errorDescription!: string;\r\n}\r\n\r\nexport abstract class BaseResponse {\r\n @ApiProperty({ type: Status })\r\n @ValidateNested()\r\n @Type(() => Status)\r\n @IsObject()\r\n Status!: Status;\r\n}\r\n"]}
1
+ {"version":3,"file":"BaseResponse.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/BaseResponse.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,yDAAyC;AACzC,qDAAqE;AAErE,MAAa,MAAM;CAQlB;AARD,wBAQC;AALC;IAFC,IAAA,qBAAW,EAAC,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;IAC/E,IAAA,0BAAQ,GAAE;;yCACQ;AAInB;IAFC,IAAA,qBAAW,EAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC;IACvF,IAAA,0BAAQ,GAAE;;gDACe;AAG5B,MAAsB,YAAY;CAMjC;AAND,oCAMC;AADC;IAJC,IAAA,qBAAW,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7B,IAAA,gCAAc,GAAE;IAChB,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,0BAAQ,GAAE;8BACF,MAAM;4CAAC","sourcesContent":["import { ApiProperty } from '@nestjs/swagger';\nimport { Type } from 'class-transformer';\nimport { IsObject, IsString, ValidateNested } from 'class-validator';\n\nexport class Status {\n @ApiProperty({ example: '0', description: 'Codice di errore, \"0\" se tutto ok' })\n @IsString()\n errorCode!: string;\n\n @ApiProperty({ example: 'Success', description: 'Descrizione dell\\'errore o successo' })\n @IsString()\n errorDescription!: string;\n}\n\nexport abstract class BaseResponse {\n @ApiProperty({ type: Status })\n @ValidateNested()\n @Type(() => Status)\n @IsObject()\n Status!: Status;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"UploadSingleFileRequest.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/UploadSingleFileRequest.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAE9C,MAAa,uBAAuB;CAsDnC;AAtDD,0DAsDC;AAjDC;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,wFAAwF;QACrG,OAAO,EAAE,kBAAkB;KAC5B,CAAC;;uDACc;AAMhB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,iDAAiD;QAC9D,OAAO,EAAE,IAAI;KACd,CAAC;;2DACkB;AAMpB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,8EAA8E;QAC3F,OAAO,EAAE,GAAG;KACb,CAAC;;uDACc;AAMhB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE,8BAA8B;KACxC,CAAC;;oEAC2B;AAM7B;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,kCAAkC;QAC/C,OAAO,EAAE,wBAAwB;KAClC,CAAC;;yDACgB;AAMlB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,YAAY;KACtB,CAAC;;mEAC0B;AAM5B;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,mDAAmD;QAChE,OAAO,EAAE,YAAY;KACtB,CAAC;;iEACwB;AAM1B;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,CAAC;KACX,CAAC;;+DACsB;AAMxB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,yEAAyE;QACtF,OAAO,EAAE,gBAAgB;KAC1B,CAAC;;qEAC4B","sourcesContent":["import { ApiProperty } from '@nestjs/swagger';\r\n\r\nexport class UploadSingleFileRequest {\r\n @ApiProperty({\r\n description: 'Codice identificativo del soggetto o dell’entità (es. codice fiscale, matricola, ecc.)',\r\n example: 'RSSMRA85M01H501Z',\r\n })\r\n codice!: string;\r\n\r\n @ApiProperty({\r\n description: 'Tipo del codice fornito (es. CF, PI, MATRICOLA)',\r\n example: 'CF',\r\n })\r\n tipoCodice!: string;\r\n\r\n @ApiProperty({\r\n description: 'Numero o valore usato per ordinare o identificare la sequenza degli allegati',\r\n example: '1',\r\n })\r\n ordine!: string;\r\n\r\n @ApiProperty({\r\n description: 'Descrizione testuale dell’allegato',\r\n example: 'Documento di identità fronte',\r\n })\r\n descrizioneAllegato!: string;\r\n\r\n @ApiProperty({\r\n description: 'Nome del file originale caricato',\r\n example: 'documento_identita.pdf',\r\n })\r\n nomeFile!: string;\r\n\r\n @ApiProperty({\r\n description: 'Data di inizio validità del documento (formato ISO)',\r\n example: '2024-01-01',\r\n })\r\n dataInizioValidita!: string;\r\n\r\n @ApiProperty({\r\n description: 'Data di fine validità del documento (formato ISO)',\r\n example: '2025-01-01',\r\n })\r\n dataFineValidita!: string;\r\n\r\n @ApiProperty({\r\n description: 'ID del tipo di allegato secondo tabella master (FK)',\r\n example: 3,\r\n })\r\n idTipoAllegato!: number;\r\n\r\n @ApiProperty({\r\n description: 'Riferimento esterno o identificativo del documento (es. numero pratica)',\r\n example: 'PRAT-2024-0001',\r\n })\r\n riferimentoDocumento!: string;\r\n}\r\n"]}
1
+ {"version":3,"file":"UploadSingleFileRequest.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/UploadSingleFileRequest.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAE9C,MAAa,uBAAuB;CAsDnC;AAtDD,0DAsDC;AAjDC;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,wFAAwF;QACrG,OAAO,EAAE,kBAAkB;KAC5B,CAAC;;uDACc;AAMhB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,iDAAiD;QAC9D,OAAO,EAAE,IAAI;KACd,CAAC;;2DACkB;AAMpB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,8EAA8E;QAC3F,OAAO,EAAE,GAAG;KACb,CAAC;;uDACc;AAMhB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE,8BAA8B;KACxC,CAAC;;oEAC2B;AAM7B;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,kCAAkC;QAC/C,OAAO,EAAE,wBAAwB;KAClC,CAAC;;yDACgB;AAMlB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,YAAY;KACtB,CAAC;;mEAC0B;AAM5B;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,mDAAmD;QAChE,OAAO,EAAE,YAAY;KACtB,CAAC;;iEACwB;AAM1B;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,CAAC;KACX,CAAC;;+DACsB;AAMxB;IAJC,IAAA,qBAAW,EAAC;QACX,WAAW,EAAE,yEAAyE;QACtF,OAAO,EAAE,gBAAgB;KAC1B,CAAC;;qEAC4B","sourcesContent":["import { ApiProperty } from '@nestjs/swagger';\n\nexport class UploadSingleFileRequest {\n @ApiProperty({\n description: 'Codice identificativo del soggetto o dell’entità (es. codice fiscale, matricola, ecc.)',\n example: 'RSSMRA85M01H501Z',\n })\n codice!: string;\n\n @ApiProperty({\n description: 'Tipo del codice fornito (es. CF, PI, MATRICOLA)',\n example: 'CF',\n })\n tipoCodice!: string;\n\n @ApiProperty({\n description: 'Numero o valore usato per ordinare o identificare la sequenza degli allegati',\n example: '1',\n })\n ordine!: string;\n\n @ApiProperty({\n description: 'Descrizione testuale dell’allegato',\n example: 'Documento di identità fronte',\n })\n descrizioneAllegato!: string;\n\n @ApiProperty({\n description: 'Nome del file originale caricato',\n example: 'documento_identita.pdf',\n })\n nomeFile!: string;\n\n @ApiProperty({\n description: 'Data di inizio validità del documento (formato ISO)',\n example: '2024-01-01',\n })\n dataInizioValidita!: string;\n\n @ApiProperty({\n description: 'Data di fine validità del documento (formato ISO)',\n example: '2025-01-01',\n })\n dataFineValidita!: string;\n\n @ApiProperty({\n description: 'ID del tipo di allegato secondo tabella master (FK)',\n example: 3,\n })\n idTipoAllegato!: number;\n\n @ApiProperty({\n description: 'Riferimento esterno o identificativo del documento (es. numero pratica)',\n example: 'PRAT-2024-0001',\n })\n riferimentoDocumento!: string;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0EAAwD;AACxD,wEAAsD","sourcesContent":["export * from \"./AllegatoDto\";\r\nexport * from \"./responses/DownloadAllegatoResponseDto\";\r\nexport * from \"./responses/UploadAllegatoResponseDto\";\r\n\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/allegati-module/Dtos/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0EAAwD;AACxD,wEAAsD","sourcesContent":["export * from \"./AllegatoDto\";\nexport * from \"./responses/DownloadAllegatoResponseDto\";\nexport * from \"./responses/UploadAllegatoResponseDto\";\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"DownloadAllegatoResponseDto.js","sourceRoot":"","sources":["../../../../src/allegati-module/Dtos/responses/DownloadAllegatoResponseDto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAAmE;AAEnE,MAAa,2BAA2B;CAwBvC;AAxBD,kEAwBC;AAjBG;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,2BAA2B;QACxC,OAAO,EAAE,oDAAoD;KAChE,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;kEACjC;AAQvB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,eAAe;KAC3B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;6DACtC;AAQlB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oBAAoB;QACjC,OAAO,EAAE,iBAAiB;KAC7B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;6DACK","sourcesContent":["import { ApiProperty } from \"@nestjs/swagger\";\r\nimport { IsString, IsNotEmpty, IsOptional } from \"class-validator\";\r\n\r\nexport class DownloadAllegatoResponseDto {\r\n @ApiProperty({\r\n description: 'Contenuto base64 del file',\r\n example: 'JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PAovVGl0bGUgKP7...',\r\n })\r\n @IsString()\r\n @IsNotEmpty({ message: \"Il contenuto è obbligatorio.\" })\r\n contentBase64!: string;\r\n\r\n @ApiProperty({\r\n description: 'Nome originale del file',\r\n example: 'documento.pdf',\r\n })\r\n @IsString()\r\n @IsNotEmpty({ message: \"Il nome file è obbligatorio.\" })\r\n filename!: string;\r\n\r\n @ApiProperty({\r\n description: 'Tipo MIME del file',\r\n example: 'application/pdf',\r\n })\r\n @IsString()\r\n @IsOptional()\r\n mimetype?: string;\r\n}"]}
1
+ {"version":3,"file":"DownloadAllegatoResponseDto.js","sourceRoot":"","sources":["../../../../src/allegati-module/Dtos/responses/DownloadAllegatoResponseDto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAAmE;AAEnE,MAAa,2BAA2B;CAwBvC;AAxBD,kEAwBC;AAjBG;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,2BAA2B;QACxC,OAAO,EAAE,oDAAoD;KAChE,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;kEACjC;AAQvB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,yBAAyB;QACtC,OAAO,EAAE,eAAe;KAC3B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;6DACtC;AAQlB;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oBAAoB;QACjC,OAAO,EAAE,iBAAiB;KAC7B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;6DACK","sourcesContent":["import { ApiProperty } from \"@nestjs/swagger\";\nimport { IsString, IsNotEmpty, IsOptional } from \"class-validator\";\n\nexport class DownloadAllegatoResponseDto {\n @ApiProperty({\n description: 'Contenuto base64 del file',\n example: 'JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PAovVGl0bGUgKP7...',\n })\n @IsString()\n @IsNotEmpty({ message: \"Il contenuto è obbligatorio.\" })\n contentBase64!: string;\n\n @ApiProperty({\n description: 'Nome originale del file',\n example: 'documento.pdf',\n })\n @IsString()\n @IsNotEmpty({ message: \"Il nome file è obbligatorio.\" })\n filename!: string;\n\n @ApiProperty({\n description: 'Tipo MIME del file',\n example: 'application/pdf',\n })\n @IsString()\n @IsOptional()\n mimetype?: string;\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"GetListResponse.js","sourceRoot":"","sources":["../../../../src/allegati-module/Dtos/responses/GetListResponse.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAE9C,yDAAyC;AACzC,qDAAiD;AACjD,kDAA+C;AAC/C,gDAA6C;AAE7C,MAAa,eAAgB,SAAQ,2BAAY;CAKhD;AALD,0CAKC;AADC;IAHC,IAAA,qBAAW,EAAC,EAAE,IAAI,EAAE,CAAC,yBAAW,CAAC,EAAE,CAAC;IACpC,IAAA,gCAAc,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,yBAAW,CAAC;;+CACD","sourcesContent":["import { ApiProperty } from '@nestjs/swagger';\r\n\r\nimport { Type } from 'class-transformer';\r\nimport { ValidateNested } from 'class-validator';\r\nimport { BaseResponse } from '../BaseResponse';\r\nimport { AllegatoDto } from '../AllegatoDto';\r\n\r\nexport class GetListResponse extends BaseResponse {\r\n @ApiProperty({ type: [AllegatoDto] })\r\n @ValidateNested({ each: true })\r\n @Type(() => AllegatoDto)\r\n Result!: AllegatoDto[];\r\n}\r\n"]}
1
+ {"version":3,"file":"GetListResponse.js","sourceRoot":"","sources":["../../../../src/allegati-module/Dtos/responses/GetListResponse.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAE9C,yDAAyC;AACzC,qDAAiD;AACjD,kDAA+C;AAC/C,gDAA6C;AAE7C,MAAa,eAAgB,SAAQ,2BAAY;CAKhD;AALD,0CAKC;AADC;IAHC,IAAA,qBAAW,EAAC,EAAE,IAAI,EAAE,CAAC,yBAAW,CAAC,EAAE,CAAC;IACpC,IAAA,gCAAc,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,yBAAW,CAAC;;+CACD","sourcesContent":["import { ApiProperty } from '@nestjs/swagger';\n\nimport { Type } from 'class-transformer';\nimport { ValidateNested } from 'class-validator';\nimport { BaseResponse } from '../BaseResponse';\nimport { AllegatoDto } from '../AllegatoDto';\n\nexport class GetListResponse extends BaseResponse {\n @ApiProperty({ type: [AllegatoDto] })\n @ValidateNested({ each: true })\n @Type(() => AllegatoDto)\n Result!: AllegatoDto[];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"UploadAllegatoResponseDto.js","sourceRoot":"","sources":["../../../../src/allegati-module/Dtos/responses/UploadAllegatoResponseDto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAAiE;AAEjE,MAAa,yBAAyB;CAerC;AAfD,8DAeC;AATG;IALC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,+BAA+B;QAC5C,OAAO,EAAE,EAAE;KACd,CAAC;IACD,IAAA,0BAAQ,GAAE;;qDACC;AAQZ;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,mBAAmB;QAChC,OAAO,EAAE,gBAAgB;KAC5B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;2DACtC","sourcesContent":["import { ApiProperty } from \"@nestjs/swagger\";\r\nimport { IsNumber, IsString, IsNotEmpty } from \"class-validator\";\r\n\r\nexport class UploadAllegatoResponseDto {\r\n @ApiProperty({\r\n description: 'ID assegnato al file caricato',\r\n example: 42,\r\n })\r\n @IsNumber()\r\n id!: number;\r\n\r\n @ApiProperty({\r\n description: 'Nome file salvato',\r\n example: 'preventivo.pdf',\r\n })\r\n @IsString()\r\n @IsNotEmpty({ message: \"Il nome file è obbligatorio.\" })\r\n filename!: string;\r\n}"]}
1
+ {"version":3,"file":"UploadAllegatoResponseDto.js","sourceRoot":"","sources":["../../../../src/allegati-module/Dtos/responses/UploadAllegatoResponseDto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAAiE;AAEjE,MAAa,yBAAyB;CAerC;AAfD,8DAeC;AATG;IALC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,+BAA+B;QAC5C,OAAO,EAAE,EAAE;KACd,CAAC;IACD,IAAA,0BAAQ,GAAE;;qDACC;AAQZ;IANC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,mBAAmB;QAChC,OAAO,EAAE,gBAAgB;KAC5B,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC;;2DACtC","sourcesContent":["import { ApiProperty } from \"@nestjs/swagger\";\nimport { IsNumber, IsString, IsNotEmpty } from \"class-validator\";\n\nexport class UploadAllegatoResponseDto {\n @ApiProperty({\n description: 'ID assegnato al file caricato',\n example: 42,\n })\n @IsNumber()\n id!: number;\n\n @ApiProperty({\n description: 'Nome file salvato',\n example: 'preventivo.pdf',\n })\n @IsString()\n @IsNotEmpty({ message: \"Il nome file è obbligatorio.\" })\n filename!: string;\n}"]}
@@ -160,12 +160,12 @@ let AllegatiService = AllegatiService_1 = class AllegatiService {
160
160
  const chunk = file.buffer.slice(i, i + chunkSize);
161
161
  base64Content += chunk.toString('base64');
162
162
  }
163
- const insertQuery = `
164
- INSERT INTO ALLEGATI (
165
- CODICE, TIPCOD, ORDINE, DESALL, NOMEFILE,
166
- DADATAVAL, ADATAVAL, ALLEGATO, IDXTIPOALL, DATMODIF, DOCRIF
167
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)
168
- RETURNING IDXALL
163
+ const insertQuery = `
164
+ INSERT INTO ALLEGATI (
165
+ CODICE, TIPCOD, ORDINE, DESALL, NOMEFILE,
166
+ DADATAVAL, ADATAVAL, ALLEGATO, IDXTIPOALL, DATMODIF, DOCRIF
167
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)
168
+ RETURNING IDXALL
169
169
  `;
170
170
  const params = [
171
171
  uploadSingleFileRequest.codice,
@@ -204,10 +204,10 @@ let AllegatiService = AllegatiService_1 = class AllegatiService {
204
204
  ensureTableExists() {
205
205
  return __awaiter(this, void 0, void 0, function* () {
206
206
  try {
207
- const query = `
208
- SELECT RDB$RELATION_NAME
209
- FROM RDB$RELATIONS
210
- WHERE RDB$RELATION_NAME = 'ALLEGATI'
207
+ const query = `
208
+ SELECT RDB$RELATION_NAME
209
+ FROM RDB$RELATIONS
210
+ WHERE RDB$RELATION_NAME = 'ALLEGATI'
211
211
  `;
212
212
  const result = yield Orm_1.Orm.query(this.allegatiOptions.databaseOptions, query);
213
213
  if (!result || result.length === 0) {
@@ -227,13 +227,13 @@ let AllegatiService = AllegatiService_1 = class AllegatiService {
227
227
  if (!id || id <= 0) {
228
228
  throw new common_1.BadRequestException('ID allegato non valido');
229
229
  }
230
- const query = `
231
- SELECT
232
- ALLEGATO as content,
233
- NOMEFILE as filename,
234
- IDXTIPOALL as idTipoAllegato
235
- FROM ALLEGATI
236
- WHERE IDXALL = ?
230
+ const query = `
231
+ SELECT
232
+ ALLEGATO as content,
233
+ NOMEFILE as filename,
234
+ IDXTIPOALL as idTipoAllegato
235
+ FROM ALLEGATI
236
+ WHERE IDXALL = ?
237
237
  `;
238
238
  const results = yield Orm_1.Orm.query(this.allegatiOptions.databaseOptions, query, [id]);
239
239
  if (!results || results.length === 0) {
@@ -329,22 +329,22 @@ let AllegatiService = AllegatiService_1 = class AllegatiService {
329
329
  params.push(filters.idxtipoall);
330
330
  }
331
331
  }
332
- const query = `
333
- SELECT
334
- IDXALL as id,
335
- NOMEFILE as filename,
336
- 'application/octet-stream' as mimetype,
337
- DATMODIF as uploadDate,
338
- CODICE as codice,
339
- TIPCOD as tipoCodice,
340
- ORDINE as ordine,
341
- DESALL as descrizioneAllegato,
342
- DADATAVAL as dataInizioValidita,
343
- ADATAVAL as dataFineValidita,
344
- IDXTIPOALL as idTipoAllegato,
345
- DOCRIF as riferimentoDocumento
346
- FROM ALLEGATI
347
- ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}
332
+ const query = `
333
+ SELECT
334
+ IDXALL as id,
335
+ NOMEFILE as filename,
336
+ 'application/octet-stream' as mimetype,
337
+ DATMODIF as uploadDate,
338
+ CODICE as codice,
339
+ TIPCOD as tipoCodice,
340
+ ORDINE as ordine,
341
+ DESALL as descrizioneAllegato,
342
+ DADATAVAL as dataInizioValidita,
343
+ ADATAVAL as dataFineValidita,
344
+ IDXTIPOALL as idTipoAllegato,
345
+ DOCRIF as riferimentoDocumento
346
+ FROM ALLEGATI
347
+ ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}
348
348
  `;
349
349
  const results = yield Orm_1.Orm.query(this.allegatiOptions.databaseOptions, query, params);
350
350
  if (!results) {
@@ -385,22 +385,22 @@ let AllegatiService = AllegatiService_1 = class AllegatiService {
385
385
  whereConditions.push('IDXTIPOALL = ?');
386
386
  params.push(fields.idxtipoall);
387
387
  }
388
- const query = `
389
- SELECT
390
- IDXALL as id,
391
- NOMEFILE as filename,
392
- 'application/octet-stream' as mimetype,
393
- DATMODIF as uploadDate,
394
- CODICE as codice,
395
- TIPCOD as tipoCodice,
396
- ORDINE as ordine,
397
- DESALL as descrizioneAllegato,
398
- DADATAVAL as dataInizioValidita,
399
- ADATAVAL as dataFineValidita,
400
- IDXTIPOALL as idTipoAllegato,
401
- DOCRIF as riferimentoDocumento
402
- FROM ALLEGATI
403
- ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}
388
+ const query = `
389
+ SELECT
390
+ IDXALL as id,
391
+ NOMEFILE as filename,
392
+ 'application/octet-stream' as mimetype,
393
+ DATMODIF as uploadDate,
394
+ CODICE as codice,
395
+ TIPCOD as tipoCodice,
396
+ ORDINE as ordine,
397
+ DESALL as descrizioneAllegato,
398
+ DADATAVAL as dataInizioValidita,
399
+ ADATAVAL as dataFineValidita,
400
+ IDXTIPOALL as idTipoAllegato,
401
+ DOCRIF as riferimentoDocumento
402
+ FROM ALLEGATI
403
+ ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}
404
404
  `;
405
405
  const results = yield Orm_1.Orm.query(this.allegatiOptions.databaseOptions, query, params);
406
406
  if (!results) {
@@ -1 +1 @@
1
- {"version":3,"file":"AllegatiService.js","sourceRoot":"","sources":["../../../../src/allegati-module/Services/AllegatiService/AllegatiService.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable, NotFoundException, BadRequestException, InternalServerErrorException, OnModuleInit } from \"@nestjs/common\";\r\nimport { autobind } from \"../../../autobind\";\r\nimport { Logger } from \"../../../Logger\";\r\nimport { Orm } from \"../../../Orm\";\r\nimport { AllegatiOptions } from \"../../AllegatiModule\";\r\nimport { UploadAllegatoResponseDto, DownloadAllegatoResponseDto, AllegatoDto} from \"../../Dtos\";\r\nimport { UploadSingleFileRequest } from \"../../Dtos/UploadSingleFileRequest\";\r\n\r\nexport class AllegatiError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode: number = 500\r\n ) {\r\n super(message);\r\n this.name = 'AllegatiError';\r\n }\r\n}\r\n\r\n@autobind\r\n@Injectable()\r\nexport class AllegatiService implements OnModuleInit {\r\n private readonly logger = new Logger(AllegatiService.name);\r\n private readonly MAX_FILE_SIZE = 90 * 1024 * 1024; // 90MB\r\n private readonly ALLOWED_MIME_TYPES = [\r\n 'application/pdf',\r\n 'image/jpeg',\r\n 'image/png',\r\n 'application/msword',\r\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n 'application/vnd.ms-excel',\r\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\r\n ];\r\n\r\n constructor(@Inject('ALLEGATI_OPTIONS') private readonly allegatiOptions: AllegatiOptions) {}\r\n\r\n /** Verifica la tabella ALLEGATI all'avvio (attesa da Nest, senza promise floating). */\r\n async onModuleInit(): Promise<void> {\r\n try {\r\n await this.ensureTableExists();\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] Errore verifica tabella ALLEGATI:', error);\r\n }\r\n }\r\n\r\n private toAllegatoDto(row: Record<string, unknown>): AllegatoDto {\r\n const optionalString = (value: unknown): string | undefined => value === undefined || value === null ? undefined : String(value);\r\n const optionalNumber = (value: unknown): number | undefined => value === undefined || value === null ? undefined : Number(value);\r\n\r\n return {\r\n id: Number(row.ID ?? row.id),\r\n filename: String(row.FILENAME ?? row.filename ?? ''),\r\n mimetype: String(row.MIMETYPE ?? row.mimetype ?? ''),\r\n uploadDate: String(row.UPLOADDATE ?? row.uploadDate ?? ''),\r\n codice: optionalString(row.CODICE ?? row.codice),\r\n tipoCodice: optionalString(row.TIPOCODICE ?? row.tipoCodice),\r\n ordine: optionalString(row.ORDINE ?? row.ordine),\r\n descrizioneAllegato: optionalString(row.DESCRIZIONEALLEGATO ?? row.descrizioneAllegato),\r\n dataInizioValidita: optionalString(row.DATAINIZIOVALIDITA ?? row.dataInizioValidita),\r\n dataFineValidita: optionalString(row.DATAFINEVALIDITA ?? row.dataFineValidita),\r\n idTipoAllegato: optionalNumber(row.IDTIPOALLEGATO ?? row.idTipoAllegato),\r\n riferimentoDocumento: optionalString(row.RIFERIMENTODOCUMENTO ?? row.riferimentoDocumento),\r\n };\r\n }\r\n\r\n private validateFile(file: Express.Multer.File): void {\r\n if (!file) {\r\n throw new BadRequestException('Nessun file fornito');\r\n }\r\n\r\n if (file.size > this.MAX_FILE_SIZE) {\r\n throw new BadRequestException(`File troppo grande. Dimensione massima consentita: ${this.MAX_FILE_SIZE / (1024 * 1024)}MB`);\r\n }\r\n\r\n if (!this.ALLOWED_MIME_TYPES.includes(file.mimetype)) {\r\n throw new BadRequestException(`Tipo di file non consentito. Tipi consentiti: ${this.ALLOWED_MIME_TYPES.join(', ')}`);\r\n }\r\n\r\n // Il mimetype dichiarato dal client e falsificabile: verifica i magic byte reali.\r\n if (!this.hasValidSignature(file)) {\r\n throw new BadRequestException('Il contenuto del file non corrisponde al tipo dichiarato.');\r\n }\r\n }\r\n\r\n private hasValidSignature(file: Express.Multer.File): boolean {\r\n const buffer = file?.buffer;\r\n if (!buffer || buffer.length < 4) {\r\n return false;\r\n }\r\n\r\n const startsWith = (...bytes: number[]): boolean => bytes.every((byte, index) => buffer[index] === byte);\r\n\r\n switch (file.mimetype) {\r\n case 'application/pdf':\r\n return startsWith(0x25, 0x50, 0x44, 0x46);\r\n case 'image/jpeg':\r\n return startsWith(0xff, 0xd8, 0xff);\r\n case 'image/png':\r\n return startsWith(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a);\r\n case 'application/msword':\r\n case 'application/vnd.ms-excel':\r\n return startsWith(0xd0, 0xcf, 0x11, 0xe0);\r\n case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':\r\n case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':\r\n // DOCX/XLSX sono archivi ZIP.\r\n return startsWith(0x50, 0x4b, 0x03, 0x04)\r\n || startsWith(0x50, 0x4b, 0x05, 0x06)\r\n || startsWith(0x50, 0x4b, 0x07, 0x08);\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n private sanitizeFilename(name: unknown): string {\r\n const raw = typeof name === 'string' ? name : '';\r\n const base = raw.replace(/\\\\/g, '/').split('/').pop() ?? '';\r\n const cleaned = base.replace(/[\\u0000-\\u001f\\u007f<>:\"|?*]/g, '_').trim();\r\n return cleaned.slice(0, 255) || 'allegato';\r\n }\r\n\r\n\r\n async getAttachmentTypes(): Promise<Array<Record<string, unknown>>> {\r\n try {\r\n const query = `SELECT IDXTIPOALL as id, DESCRIZIONE as description FROM TIPOALL`;\r\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query);\r\n \r\n if (!results) {\r\n throw new InternalServerErrorException('Errore durante il recupero dei tipi di allegato');\r\n }\r\n\r\n return results;\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] getAttachmentTypes - Errore:', error);\r\n if (error instanceof InternalServerErrorException) {\r\n throw error;\r\n }\r\n throw new InternalServerErrorException('Errore durante il recupero dei tipi di allegato');\r\n }\r\n }\r\n async uploadFile(file: Express.Multer.File, uploadSingleFileRequest: UploadSingleFileRequest): Promise<UploadAllegatoResponseDto> {\r\n try {\r\n this.validateFile(file);\r\n\r\n // Convert buffer to base64 in chunks to avoid memory issues\r\n const chunkSize = 1024 * 1024; // 1MB chunks\r\n let base64Content = '';\r\n for (let i = 0; i < file.buffer.length; i += chunkSize) {\r\n const chunk = file.buffer.slice(i, i + chunkSize);\r\n base64Content += chunk.toString('base64');\r\n }\r\n\r\n const insertQuery = `\r\n INSERT INTO ALLEGATI (\r\n CODICE, TIPCOD, ORDINE, DESALL, NOMEFILE,\r\n DADATAVAL, ADATAVAL, ALLEGATO, IDXTIPOALL, DATMODIF, DOCRIF\r\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)\r\n RETURNING IDXALL\r\n `;\r\n\r\n const params = [\r\n uploadSingleFileRequest.codice,\r\n uploadSingleFileRequest.tipoCodice,\r\n uploadSingleFileRequest.ordine,\r\n uploadSingleFileRequest.descrizioneAllegato,\r\n this.sanitizeFilename(file.originalname),\r\n uploadSingleFileRequest.dataInizioValidita,\r\n uploadSingleFileRequest.dataFineValidita,\r\n base64Content,\r\n uploadSingleFileRequest.idTipoAllegato,\r\n uploadSingleFileRequest.riferimentoDocumento\r\n ];\r\n\r\n const result = await Orm.query(this.allegatiOptions.databaseOptions, insertQuery, params);\r\n // node-firebird restituisce le righe di INSERT ... RETURNING come array; il fallback\r\n // copre le versioni/driver che restituiscono un singolo oggetto.\r\n const inserted = (Array.isArray(result) ? result[0] : result) as Record<string, unknown> | undefined;\r\n const insertedId = inserted?.IDXALL ?? inserted?.idxall;\r\n\r\n if (insertedId === undefined || insertedId === null) {\r\n throw new InternalServerErrorException('Errore durante il salvataggio del file');\r\n }\r\n\r\n return {\r\n id: Number(insertedId),\r\n filename: this.sanitizeFilename(file.originalname),\r\n };\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] uploadFile - Errore:', error);\r\n if (error instanceof BadRequestException || error instanceof InternalServerErrorException) {\r\n throw error;\r\n }\r\n throw new InternalServerErrorException('Errore durante il caricamento del file');\r\n }\r\n }\r\n\r\n async ensureTableExists(): Promise<void> {\r\n try {\r\n const query = `\r\n SELECT RDB$RELATION_NAME \r\n FROM RDB$RELATIONS \r\n WHERE RDB$RELATION_NAME = 'ALLEGATI'\r\n `;\r\n const result = await Orm.query(this.allegatiOptions.databaseOptions, query);\r\n \r\n if (!result || result.length === 0) {\r\n throw new Error('Tabella ALLEGATI non trovata nel database');\r\n }\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] Errore verifica tabella ALLEGATI:', error);\r\n throw new InternalServerErrorException('Errore durante la verifica della tabella ALLEGATI');\r\n }\r\n }\r\n\r\n async downloadFile(id: number): Promise<DownloadAllegatoResponseDto> {\r\n try {\r\n if (!id || id <= 0) {\r\n throw new BadRequestException('ID allegato non valido');\r\n }\r\n\r\n const query = `\r\n SELECT \r\n ALLEGATO as content,\r\n NOMEFILE as filename,\r\n IDXTIPOALL as idTipoAllegato\r\n FROM ALLEGATI \r\n WHERE IDXALL = ?\r\n `;\r\n \r\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query, [id]);\r\n \r\n if (!results || results.length === 0) {\r\n throw new NotFoundException(`Allegato con ID ${id} non trovato`);\r\n }\r\n\r\n const result = results[0];\r\n const content = result?.CONTENT ?? result?.content;\r\n const filename = result?.FILENAME ?? result?.filename;\r\n\r\n if (typeof content !== 'string' || content.length === 0) {\r\n throw new InternalServerErrorException('Contenuto file non disponibile');\r\n }\r\n\r\n if (typeof filename !== 'string' || filename.length === 0) {\r\n throw new InternalServerErrorException('Nome file non disponibile');\r\n }\r\n\r\n const mimetype = this.detectMimeType(filename);\r\n \r\n return {\r\n contentBase64: content,\r\n filename,\r\n mimetype\r\n };\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] downloadFile - Errore:', error);\r\n if (error instanceof BadRequestException || \r\n error instanceof NotFoundException || \r\n error instanceof InternalServerErrorException) {\r\n throw error;\r\n }\r\n throw new InternalServerErrorException('Errore durante il download del file');\r\n }\r\n }\r\n\r\n private detectMimeType(filename: string): string {\r\n const extension = filename.split('.').pop()?.toLowerCase();\r\n const mimeTypes: { [key: string]: string } = {\r\n 'pdf': 'application/pdf',\r\n 'jpg': 'image/jpeg',\r\n 'jpeg': 'image/jpeg',\r\n 'png': 'image/png',\r\n 'doc': 'application/msword',\r\n 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n 'xls': 'application/vnd.ms-excel',\r\n 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\r\n };\r\n return mimeTypes[extension || ''] || 'application/octet-stream';\r\n }\r\n\r\n async deleteFile(id: number): Promise<void> {\r\n try {\r\n if (!id || id <= 0) {\r\n throw new BadRequestException('ID allegato non valido');\r\n }\r\n\r\n const checkQuery = `SELECT IDXALL FROM ALLEGATI WHERE IDXALL = ?`;\r\n const checkResult = await Orm.query(this.allegatiOptions.databaseOptions, checkQuery, [id]);\r\n \r\n if (!checkResult || checkResult.length === 0) {\r\n throw new NotFoundException(`Allegato con ID ${id} non trovato`);\r\n }\r\n\r\n const query = `DELETE FROM ALLEGATI WHERE IDXALL = ?`;\r\n await Orm.execute(this.allegatiOptions.databaseOptions, query, [id]);\r\n \r\n \r\n } catch (error) {\r\n this.logger.error('[AllegatiService] deleteFile - Errore:', error);\r\n if (error instanceof BadRequestException || \r\n error instanceof NotFoundException || \r\n error instanceof InternalServerErrorException) {\r\n throw error;\r\n }\r\n throw new InternalServerErrorException('Errore durante la cancellazione del file');\r\n }\r\n }\r\n\r\n async listFiles(filters?: { \r\n tipcod?: string;\r\n codice?: number;\r\n docrif?: string;\r\n idxtipoall?: number;\r\n }): Promise<AllegatoDto[]> {\r\n try {\r\n const whereConditions: string[] = [];\r\n const params: unknown[] = [];\r\n\r\n if (filters) {\r\n if (filters.tipcod) {\r\n whereConditions.push('TIPCOD = ?');\r\n params.push(filters.tipcod);\r\n }\r\n if (filters.codice) {\r\n whereConditions.push('CODICE = ?');\r\n params.push(filters.codice);\r\n }\r\n if (filters.docrif) {\r\n whereConditions.push('DOCRIF = ?');\r\n params.push(filters.docrif);\r\n }\r\n if (filters.idxtipoall !== undefined) {\r\n whereConditions.push('IDXTIPOALL = ?');\r\n params.push(filters.idxtipoall);\r\n }\r\n }\r\n\r\n const query = `\r\n SELECT \r\n IDXALL as id,\r\n NOMEFILE as filename,\r\n 'application/octet-stream' as mimetype,\r\n DATMODIF as uploadDate,\r\n CODICE as codice,\r\n TIPCOD as tipoCodice,\r\n ORDINE as ordine,\r\n DESALL as descrizioneAllegato,\r\n DADATAVAL as dataInizioValidita,\r\n ADATAVAL as dataFineValidita,\r\n IDXTIPOALL as idTipoAllegato,\r\n DOCRIF as riferimentoDocumento\r\n FROM ALLEGATI\r\n ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}\r\n `;\r\n\r\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query, params);\r\n \r\n if (!results) {\r\n throw new InternalServerErrorException('Errore durante il recupero della lista dei file');\r\n }\r\n\r\n return results.map((r: Record<string, unknown>) => this.toAllegatoDto(r));\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] listFiles - Errore:', error);\r\n if (error instanceof InternalServerErrorException) {\r\n throw error;\r\n }\r\n throw new InternalServerErrorException('Errore durante il recupero della lista dei file');\r\n }\r\n }\r\n\r\n /**\r\n * Find allegati by a combination of tipcod, codice, docrif, idxtipoall\r\n */\r\n async findByFields(fields: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }): Promise<AllegatoDto[]> {\r\n try {\r\n const whereConditions: string[] = [];\r\n const params: unknown[] = [];\r\n if (fields.tipcod) {\r\n whereConditions.push('TIPCOD = ?');\r\n params.push(fields.tipcod);\r\n }\r\n if (fields.codice) {\r\n whereConditions.push('CODICE = ?');\r\n params.push(fields.codice);\r\n }\r\n if (fields.docrif) {\r\n whereConditions.push('DOCRIF = ?');\r\n params.push(fields.docrif);\r\n }\r\n if (fields.idxtipoall !== undefined) {\r\n whereConditions.push('IDXTIPOALL = ?');\r\n params.push(fields.idxtipoall);\r\n }\r\n const query = `\r\n SELECT \r\n IDXALL as id,\r\n NOMEFILE as filename,\r\n 'application/octet-stream' as mimetype,\r\n DATMODIF as uploadDate,\r\n CODICE as codice,\r\n TIPCOD as tipoCodice,\r\n ORDINE as ordine,\r\n DESALL as descrizioneAllegato,\r\n DADATAVAL as dataInizioValidita,\r\n ADATAVAL as dataFineValidita,\r\n IDXTIPOALL as idTipoAllegato,\r\n DOCRIF as riferimentoDocumento\r\n FROM ALLEGATI\r\n ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}\r\n `;\r\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query, params);\r\n if (!results) {\r\n throw new InternalServerErrorException('Errore durante la ricerca degli allegati');\r\n }\r\n return results.map((r: Record<string, unknown>) => this.toAllegatoDto(r));\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] findByFields - Errore:', error);\r\n throw new InternalServerErrorException('Errore durante la ricerca degli allegati');\r\n }\r\n }\r\n\r\n /**\r\n * Update tipcod, codice, docrif, idxtipoall for a given allegato by id\r\n */\r\n async updateFieldsById(id: number, fields: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }): Promise<void> {\r\n try {\r\n if (!id || id <= 0) {\r\n throw new BadRequestException('ID allegato non valido');\r\n }\r\n const updates: string[] = [];\r\n const params: unknown[] = [];\r\n if (fields.tipcod !== undefined) {\r\n updates.push('TIPCOD = ?');\r\n params.push(fields.tipcod);\r\n }\r\n if (fields.codice !== undefined) {\r\n updates.push('CODICE = ?');\r\n params.push(fields.codice);\r\n }\r\n if (fields.docrif !== undefined) {\r\n updates.push('DOCRIF = ?');\r\n params.push(fields.docrif);\r\n }\r\n if (fields.idxtipoall !== undefined) {\r\n updates.push('IDXTIPOALL = ?');\r\n params.push(fields.idxtipoall);\r\n }\r\n if (updates.length === 0) {\r\n throw new BadRequestException('Nessun campo da aggiornare');\r\n }\r\n const query = `UPDATE ALLEGATI SET ${updates.join(', ')} WHERE IDXALL = ?`;\r\n params.push(id);\r\n const result = await Orm.execute(this.allegatiOptions.databaseOptions, query, params);\r\n if (!result) {\r\n throw new InternalServerErrorException('Errore durante l\\'aggiornamento del file');\r\n }\r\n } catch (error) {\r\n this.logger.error('[AllegatiService] updateFieldsById - Errore:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Get a single allegato by fields (returns the first match)\r\n */\r\n async getOneByFields(fields: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }): Promise<AllegatoDto | null> {\r\n const results = await this.findByFields(fields);\r\n return results.length > 0 ? (results[0] ?? null) : null;\r\n }\r\n\r\n}\r\n"]}
1
+ {"version":3,"file":"AllegatiService.js","sourceRoot":"","sources":["../../../../src/allegati-module/Services/AllegatiService/AllegatiService.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable, NotFoundException, BadRequestException, InternalServerErrorException, OnModuleInit } from \"@nestjs/common\";\nimport { autobind } from \"../../../autobind\";\nimport { Logger } from \"../../../Logger\";\nimport { Orm } from \"../../../Orm\";\nimport { AllegatiOptions } from \"../../AllegatiModule\";\nimport { UploadAllegatoResponseDto, DownloadAllegatoResponseDto, AllegatoDto} from \"../../Dtos\";\nimport { UploadSingleFileRequest } from \"../../Dtos/UploadSingleFileRequest\";\n\nexport class AllegatiError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode: number = 500\n ) {\n super(message);\n this.name = 'AllegatiError';\n }\n}\n\n@autobind\n@Injectable()\nexport class AllegatiService implements OnModuleInit {\n private readonly logger = new Logger(AllegatiService.name);\n private readonly MAX_FILE_SIZE = 90 * 1024 * 1024; // 90MB\n private readonly ALLOWED_MIME_TYPES = [\n 'application/pdf',\n 'image/jpeg',\n 'image/png',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n ];\n\n constructor(@Inject('ALLEGATI_OPTIONS') private readonly allegatiOptions: AllegatiOptions) {}\n\n /** Verifica la tabella ALLEGATI all'avvio (attesa da Nest, senza promise floating). */\n async onModuleInit(): Promise<void> {\n try {\n await this.ensureTableExists();\n } catch (error) {\n this.logger.error('[AllegatiService] Errore verifica tabella ALLEGATI:', error);\n }\n }\n\n private toAllegatoDto(row: Record<string, unknown>): AllegatoDto {\n const optionalString = (value: unknown): string | undefined => value === undefined || value === null ? undefined : String(value);\n const optionalNumber = (value: unknown): number | undefined => value === undefined || value === null ? undefined : Number(value);\n\n return {\n id: Number(row.ID ?? row.id),\n filename: String(row.FILENAME ?? row.filename ?? ''),\n mimetype: String(row.MIMETYPE ?? row.mimetype ?? ''),\n uploadDate: String(row.UPLOADDATE ?? row.uploadDate ?? ''),\n codice: optionalString(row.CODICE ?? row.codice),\n tipoCodice: optionalString(row.TIPOCODICE ?? row.tipoCodice),\n ordine: optionalString(row.ORDINE ?? row.ordine),\n descrizioneAllegato: optionalString(row.DESCRIZIONEALLEGATO ?? row.descrizioneAllegato),\n dataInizioValidita: optionalString(row.DATAINIZIOVALIDITA ?? row.dataInizioValidita),\n dataFineValidita: optionalString(row.DATAFINEVALIDITA ?? row.dataFineValidita),\n idTipoAllegato: optionalNumber(row.IDTIPOALLEGATO ?? row.idTipoAllegato),\n riferimentoDocumento: optionalString(row.RIFERIMENTODOCUMENTO ?? row.riferimentoDocumento),\n };\n }\n\n private validateFile(file: Express.Multer.File): void {\n if (!file) {\n throw new BadRequestException('Nessun file fornito');\n }\n\n if (file.size > this.MAX_FILE_SIZE) {\n throw new BadRequestException(`File troppo grande. Dimensione massima consentita: ${this.MAX_FILE_SIZE / (1024 * 1024)}MB`);\n }\n\n if (!this.ALLOWED_MIME_TYPES.includes(file.mimetype)) {\n throw new BadRequestException(`Tipo di file non consentito. Tipi consentiti: ${this.ALLOWED_MIME_TYPES.join(', ')}`);\n }\n\n // Il mimetype dichiarato dal client e falsificabile: verifica i magic byte reali.\n if (!this.hasValidSignature(file)) {\n throw new BadRequestException('Il contenuto del file non corrisponde al tipo dichiarato.');\n }\n }\n\n private hasValidSignature(file: Express.Multer.File): boolean {\n const buffer = file?.buffer;\n if (!buffer || buffer.length < 4) {\n return false;\n }\n\n const startsWith = (...bytes: number[]): boolean => bytes.every((byte, index) => buffer[index] === byte);\n\n switch (file.mimetype) {\n case 'application/pdf':\n return startsWith(0x25, 0x50, 0x44, 0x46);\n case 'image/jpeg':\n return startsWith(0xff, 0xd8, 0xff);\n case 'image/png':\n return startsWith(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a);\n case 'application/msword':\n case 'application/vnd.ms-excel':\n return startsWith(0xd0, 0xcf, 0x11, 0xe0);\n case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':\n case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':\n // DOCX/XLSX sono archivi ZIP.\n return startsWith(0x50, 0x4b, 0x03, 0x04)\n || startsWith(0x50, 0x4b, 0x05, 0x06)\n || startsWith(0x50, 0x4b, 0x07, 0x08);\n default:\n return false;\n }\n }\n\n private sanitizeFilename(name: unknown): string {\n const raw = typeof name === 'string' ? name : '';\n const base = raw.replace(/\\\\/g, '/').split('/').pop() ?? '';\n const cleaned = base.replace(/[\\u0000-\\u001f\\u007f<>:\"|?*]/g, '_').trim();\n return cleaned.slice(0, 255) || 'allegato';\n }\n\n\n async getAttachmentTypes(): Promise<Array<Record<string, unknown>>> {\n try {\n const query = `SELECT IDXTIPOALL as id, DESCRIZIONE as description FROM TIPOALL`;\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query);\n \n if (!results) {\n throw new InternalServerErrorException('Errore durante il recupero dei tipi di allegato');\n }\n\n return results;\n } catch (error) {\n this.logger.error('[AllegatiService] getAttachmentTypes - Errore:', error);\n if (error instanceof InternalServerErrorException) {\n throw error;\n }\n throw new InternalServerErrorException('Errore durante il recupero dei tipi di allegato');\n }\n }\n async uploadFile(file: Express.Multer.File, uploadSingleFileRequest: UploadSingleFileRequest): Promise<UploadAllegatoResponseDto> {\n try {\n this.validateFile(file);\n\n // Convert buffer to base64 in chunks to avoid memory issues\n const chunkSize = 1024 * 1024; // 1MB chunks\n let base64Content = '';\n for (let i = 0; i < file.buffer.length; i += chunkSize) {\n const chunk = file.buffer.slice(i, i + chunkSize);\n base64Content += chunk.toString('base64');\n }\n\n const insertQuery = `\n INSERT INTO ALLEGATI (\n CODICE, TIPCOD, ORDINE, DESALL, NOMEFILE,\n DADATAVAL, ADATAVAL, ALLEGATO, IDXTIPOALL, DATMODIF, DOCRIF\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)\n RETURNING IDXALL\n `;\n\n const params = [\n uploadSingleFileRequest.codice,\n uploadSingleFileRequest.tipoCodice,\n uploadSingleFileRequest.ordine,\n uploadSingleFileRequest.descrizioneAllegato,\n this.sanitizeFilename(file.originalname),\n uploadSingleFileRequest.dataInizioValidita,\n uploadSingleFileRequest.dataFineValidita,\n base64Content,\n uploadSingleFileRequest.idTipoAllegato,\n uploadSingleFileRequest.riferimentoDocumento\n ];\n\n const result = await Orm.query(this.allegatiOptions.databaseOptions, insertQuery, params);\n // node-firebird restituisce le righe di INSERT ... RETURNING come array; il fallback\n // copre le versioni/driver che restituiscono un singolo oggetto.\n const inserted = (Array.isArray(result) ? result[0] : result) as Record<string, unknown> | undefined;\n const insertedId = inserted?.IDXALL ?? inserted?.idxall;\n\n if (insertedId === undefined || insertedId === null) {\n throw new InternalServerErrorException('Errore durante il salvataggio del file');\n }\n\n return {\n id: Number(insertedId),\n filename: this.sanitizeFilename(file.originalname),\n };\n } catch (error) {\n this.logger.error('[AllegatiService] uploadFile - Errore:', error);\n if (error instanceof BadRequestException || error instanceof InternalServerErrorException) {\n throw error;\n }\n throw new InternalServerErrorException('Errore durante il caricamento del file');\n }\n }\n\n async ensureTableExists(): Promise<void> {\n try {\n const query = `\n SELECT RDB$RELATION_NAME \n FROM RDB$RELATIONS \n WHERE RDB$RELATION_NAME = 'ALLEGATI'\n `;\n const result = await Orm.query(this.allegatiOptions.databaseOptions, query);\n \n if (!result || result.length === 0) {\n throw new Error('Tabella ALLEGATI non trovata nel database');\n }\n } catch (error) {\n this.logger.error('[AllegatiService] Errore verifica tabella ALLEGATI:', error);\n throw new InternalServerErrorException('Errore durante la verifica della tabella ALLEGATI');\n }\n }\n\n async downloadFile(id: number): Promise<DownloadAllegatoResponseDto> {\n try {\n if (!id || id <= 0) {\n throw new BadRequestException('ID allegato non valido');\n }\n\n const query = `\n SELECT \n ALLEGATO as content,\n NOMEFILE as filename,\n IDXTIPOALL as idTipoAllegato\n FROM ALLEGATI \n WHERE IDXALL = ?\n `;\n \n const results = await Orm.query(this.allegatiOptions.databaseOptions, query, [id]);\n \n if (!results || results.length === 0) {\n throw new NotFoundException(`Allegato con ID ${id} non trovato`);\n }\n\n const result = results[0];\n const content = result?.CONTENT ?? result?.content;\n const filename = result?.FILENAME ?? result?.filename;\n\n if (typeof content !== 'string' || content.length === 0) {\n throw new InternalServerErrorException('Contenuto file non disponibile');\n }\n\n if (typeof filename !== 'string' || filename.length === 0) {\n throw new InternalServerErrorException('Nome file non disponibile');\n }\n\n const mimetype = this.detectMimeType(filename);\n \n return {\n contentBase64: content,\n filename,\n mimetype\n };\n } catch (error) {\n this.logger.error('[AllegatiService] downloadFile - Errore:', error);\n if (error instanceof BadRequestException || \n error instanceof NotFoundException || \n error instanceof InternalServerErrorException) {\n throw error;\n }\n throw new InternalServerErrorException('Errore durante il download del file');\n }\n }\n\n private detectMimeType(filename: string): string {\n const extension = filename.split('.').pop()?.toLowerCase();\n const mimeTypes: { [key: string]: string } = {\n 'pdf': 'application/pdf',\n 'jpg': 'image/jpeg',\n 'jpeg': 'image/jpeg',\n 'png': 'image/png',\n 'doc': 'application/msword',\n 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'xls': 'application/vnd.ms-excel',\n 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n };\n return mimeTypes[extension || ''] || 'application/octet-stream';\n }\n\n async deleteFile(id: number): Promise<void> {\n try {\n if (!id || id <= 0) {\n throw new BadRequestException('ID allegato non valido');\n }\n\n const checkQuery = `SELECT IDXALL FROM ALLEGATI WHERE IDXALL = ?`;\n const checkResult = await Orm.query(this.allegatiOptions.databaseOptions, checkQuery, [id]);\n \n if (!checkResult || checkResult.length === 0) {\n throw new NotFoundException(`Allegato con ID ${id} non trovato`);\n }\n\n const query = `DELETE FROM ALLEGATI WHERE IDXALL = ?`;\n await Orm.execute(this.allegatiOptions.databaseOptions, query, [id]);\n \n \n } catch (error) {\n this.logger.error('[AllegatiService] deleteFile - Errore:', error);\n if (error instanceof BadRequestException || \n error instanceof NotFoundException || \n error instanceof InternalServerErrorException) {\n throw error;\n }\n throw new InternalServerErrorException('Errore durante la cancellazione del file');\n }\n }\n\n async listFiles(filters?: { \n tipcod?: string;\n codice?: number;\n docrif?: string;\n idxtipoall?: number;\n }): Promise<AllegatoDto[]> {\n try {\n const whereConditions: string[] = [];\n const params: unknown[] = [];\n\n if (filters) {\n if (filters.tipcod) {\n whereConditions.push('TIPCOD = ?');\n params.push(filters.tipcod);\n }\n if (filters.codice) {\n whereConditions.push('CODICE = ?');\n params.push(filters.codice);\n }\n if (filters.docrif) {\n whereConditions.push('DOCRIF = ?');\n params.push(filters.docrif);\n }\n if (filters.idxtipoall !== undefined) {\n whereConditions.push('IDXTIPOALL = ?');\n params.push(filters.idxtipoall);\n }\n }\n\n const query = `\n SELECT \n IDXALL as id,\n NOMEFILE as filename,\n 'application/octet-stream' as mimetype,\n DATMODIF as uploadDate,\n CODICE as codice,\n TIPCOD as tipoCodice,\n ORDINE as ordine,\n DESALL as descrizioneAllegato,\n DADATAVAL as dataInizioValidita,\n ADATAVAL as dataFineValidita,\n IDXTIPOALL as idTipoAllegato,\n DOCRIF as riferimentoDocumento\n FROM ALLEGATI\n ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}\n `;\n\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query, params);\n \n if (!results) {\n throw new InternalServerErrorException('Errore durante il recupero della lista dei file');\n }\n\n return results.map((r: Record<string, unknown>) => this.toAllegatoDto(r));\n } catch (error) {\n this.logger.error('[AllegatiService] listFiles - Errore:', error);\n if (error instanceof InternalServerErrorException) {\n throw error;\n }\n throw new InternalServerErrorException('Errore durante il recupero della lista dei file');\n }\n }\n\n /**\n * Find allegati by a combination of tipcod, codice, docrif, idxtipoall\n */\n async findByFields(fields: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }): Promise<AllegatoDto[]> {\n try {\n const whereConditions: string[] = [];\n const params: unknown[] = [];\n if (fields.tipcod) {\n whereConditions.push('TIPCOD = ?');\n params.push(fields.tipcod);\n }\n if (fields.codice) {\n whereConditions.push('CODICE = ?');\n params.push(fields.codice);\n }\n if (fields.docrif) {\n whereConditions.push('DOCRIF = ?');\n params.push(fields.docrif);\n }\n if (fields.idxtipoall !== undefined) {\n whereConditions.push('IDXTIPOALL = ?');\n params.push(fields.idxtipoall);\n }\n const query = `\n SELECT \n IDXALL as id,\n NOMEFILE as filename,\n 'application/octet-stream' as mimetype,\n DATMODIF as uploadDate,\n CODICE as codice,\n TIPCOD as tipoCodice,\n ORDINE as ordine,\n DESALL as descrizioneAllegato,\n DADATAVAL as dataInizioValidita,\n ADATAVAL as dataFineValidita,\n IDXTIPOALL as idTipoAllegato,\n DOCRIF as riferimentoDocumento\n FROM ALLEGATI\n ${whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''}\n `;\n const results = await Orm.query(this.allegatiOptions.databaseOptions, query, params);\n if (!results) {\n throw new InternalServerErrorException('Errore durante la ricerca degli allegati');\n }\n return results.map((r: Record<string, unknown>) => this.toAllegatoDto(r));\n } catch (error) {\n this.logger.error('[AllegatiService] findByFields - Errore:', error);\n throw new InternalServerErrorException('Errore durante la ricerca degli allegati');\n }\n }\n\n /**\n * Update tipcod, codice, docrif, idxtipoall for a given allegato by id\n */\n async updateFieldsById(id: number, fields: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }): Promise<void> {\n try {\n if (!id || id <= 0) {\n throw new BadRequestException('ID allegato non valido');\n }\n const updates: string[] = [];\n const params: unknown[] = [];\n if (fields.tipcod !== undefined) {\n updates.push('TIPCOD = ?');\n params.push(fields.tipcod);\n }\n if (fields.codice !== undefined) {\n updates.push('CODICE = ?');\n params.push(fields.codice);\n }\n if (fields.docrif !== undefined) {\n updates.push('DOCRIF = ?');\n params.push(fields.docrif);\n }\n if (fields.idxtipoall !== undefined) {\n updates.push('IDXTIPOALL = ?');\n params.push(fields.idxtipoall);\n }\n if (updates.length === 0) {\n throw new BadRequestException('Nessun campo da aggiornare');\n }\n const query = `UPDATE ALLEGATI SET ${updates.join(', ')} WHERE IDXALL = ?`;\n params.push(id);\n const result = await Orm.execute(this.allegatiOptions.databaseOptions, query, params);\n if (!result) {\n throw new InternalServerErrorException('Errore durante l\\'aggiornamento del file');\n }\n } catch (error) {\n this.logger.error('[AllegatiService] updateFieldsById - Errore:', error);\n throw error;\n }\n }\n\n /**\n * Get a single allegato by fields (returns the first match)\n */\n async getOneByFields(fields: { tipcod?: string; codice?: number; docrif?: string; idxtipoall?: number }): Promise<AllegatoDto | null> {\n const results = await this.findByFields(fields);\n return results.length > 0 ? (results[0] ?? null) : null;\n }\n\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/allegati-module/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,4DAqBC;AA1BD,uCAA2C;AAC3C,+DAA0D;AAC1D,qDAAmE;AACnE,sCAAmC;AAEnC,SAAsB,wBAAwB,CAAC,GAAgB,EAAE,OAAwB;;QACrF,MAAM,MAAM,GAAW,IAAI,eAAM,CAAC,0BAA0B,CAAC,CAAC;QAC9D,IAAI,CAAC;YACD,MAAM,mBAAmB,GAAG,IAAI,iCAAc,CAAC,GAAG,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,+BAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE;gBAC3F,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE;gBAC3B,OAAO,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YAEH,2DAA2D;YAC3D,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QAEzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YAC5D,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CAAA;AAED,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,yCAAuB,CAAC,yFAAyF","sourcesContent":["import { Application } from \"express\";\r\nimport { NestFactory } from \"@nestjs/core\";\r\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\r\nimport { AllegatiModule, AllegatiOptions } from \"./AllegatiModule\";\r\nimport { Logger } from \"../Logger\";\r\n\r\nexport async function initializeAllegatiModule(app: Application, options: AllegatiOptions) {\r\n const logger: Logger = new Logger(\"initializeAllegatiModule\");\r\n try {\r\n const nestExpressInstance = new ExpressAdapter(app);\r\n const nestApp = await NestFactory.create(AllegatiModule.forRoot(options), nestExpressInstance, {\r\n bufferLogs: true\r\n });\r\n\r\n nestApp.enableCors();\r\n\r\n nestApp.setGlobalPrefix('api', {\r\n exclude: ['/swagger', '/swagger/(.*)']\r\n });\r\n\r\n // Note: Swagger setup is now handled by the unified module\r\n await nestApp.init();\r\n\r\n } catch (error) {\r\n logger.error(\"Errore in initialize AllegatiModule:\", error);\r\n throw error;\r\n }\r\n}\r\n\r\nexport { AllegatiModule } from \"./AllegatiModule\";\r\nexport * from \"./Dtos\"; // per esportare automaticamente i DTOs tipo AllegatoDto, UploadAllegatoResponseDto, etc."]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/allegati-module/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,4DAqBC;AA1BD,uCAA2C;AAC3C,+DAA0D;AAC1D,qDAAmE;AACnE,sCAAmC;AAEnC,SAAsB,wBAAwB,CAAC,GAAgB,EAAE,OAAwB;;QACrF,MAAM,MAAM,GAAW,IAAI,eAAM,CAAC,0BAA0B,CAAC,CAAC;QAC9D,IAAI,CAAC;YACD,MAAM,mBAAmB,GAAG,IAAI,iCAAc,CAAC,GAAG,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,+BAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE;gBAC3F,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE;gBAC3B,OAAO,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YAEH,2DAA2D;YAC3D,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QAEzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YAC5D,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CAAA;AAED,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,yCAAuB,CAAC,yFAAyF","sourcesContent":["import { Application } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { AllegatiModule, AllegatiOptions } from \"./AllegatiModule\";\nimport { Logger } from \"../Logger\";\n\nexport async function initializeAllegatiModule(app: Application, options: AllegatiOptions) {\n const logger: Logger = new Logger(\"initializeAllegatiModule\");\n try {\n const nestExpressInstance = new ExpressAdapter(app);\n const nestApp = await NestFactory.create(AllegatiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n\n nestApp.enableCors();\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n // Note: Swagger setup is now handled by the unified module\n await nestApp.init();\n\n } catch (error) {\n logger.error(\"Errore in initialize AllegatiModule:\", error);\n throw error;\n }\n}\n\nexport { AllegatiModule } from \"./AllegatiModule\";\nexport * from \"./Dtos\"; // per esportare automaticamente i DTOs tipo AllegatoDto, UploadAllegatoResponseDto, etc."]}