emilsoftware-utilities 2.0.0-dev.46 → 2.0.0-dev.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Utilities.js
CHANGED
|
@@ -120,8 +120,7 @@ class RestUtilities {
|
|
|
120
120
|
static sendErrorMessage(res, error, tag = "[BASE ERROR]", status = 500) {
|
|
121
121
|
var _a, _b;
|
|
122
122
|
const rawMessage = error instanceof Error ? error.message : String(error !== null && error !== void 0 ? error : "");
|
|
123
|
-
// Logga SEMPRE l'errore reale lato server
|
|
124
|
-
// ma senza questo log gli errori 5xx risultano impossibili da diagnosticare.
|
|
123
|
+
// Logga SEMPRE l'errore reale lato server (con stack) per la diagnosi.
|
|
125
124
|
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
126
125
|
new Logger_1.Logger(tag || "[BASE ERROR]").error(rawMessage, ...(errorStack ? [errorStack] : []));
|
|
127
126
|
const errorWithResponse = error;
|
|
@@ -142,29 +141,43 @@ class RestUtilities {
|
|
|
142
141
|
const exceptionStatus = typeof (errorWithResponse === null || errorWithResponse === void 0 ? void 0 : errorWithResponse.getResponse) === "function"
|
|
143
142
|
? Number((_b = (_a = error).getStatus) === null || _b === void 0 ? void 0 : _b.call(_a))
|
|
144
143
|
: undefined;
|
|
144
|
+
const hasExceptionStatus = Number.isInteger(exceptionStatus) && exceptionStatus >= 400;
|
|
145
|
+
// Molti controller chiamano `sendErrorMessage(res, err)` anche per errori di input:
|
|
146
|
+
// riconosciamo i casi di validazione per non rispondere 500.
|
|
147
|
+
const looksLikeValidation = !hasExceptionStatus && !schemaError
|
|
148
|
+
&& /obbligatorio|obbligatoria|mancante|manca il parametro|non valido|non valida|required|missing|invalid input/i.test(rawMessage);
|
|
145
149
|
const effectiveStatus = schemaError
|
|
146
150
|
? 503
|
|
147
|
-
:
|
|
151
|
+
: hasExceptionStatus
|
|
148
152
|
? exceptionStatus
|
|
149
|
-
:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
153
|
+
: looksLikeValidation
|
|
154
|
+
? 400
|
|
155
|
+
: status;
|
|
156
|
+
// Codici GENERICI (questo helper non appartiene al modulo Accessi): i codici
|
|
157
|
+
// ACCESSI_* restano di competenza esclusiva del modulo Accessi.
|
|
158
|
+
const code = explicitCode !== null && explicitCode !== void 0 ? explicitCode : (schemaError
|
|
159
|
+
? "DATABASE_SCHEMA_OUTDATED"
|
|
160
|
+
: effectiveStatus === 401
|
|
161
|
+
? "UNAUTHORIZED"
|
|
162
|
+
: effectiveStatus === 403
|
|
163
|
+
? "FORBIDDEN"
|
|
164
|
+
: effectiveStatus === 400
|
|
165
|
+
? "VALIDATION_ERROR"
|
|
166
|
+
: effectiveStatus >= 500
|
|
167
|
+
? "INTERNAL_ERROR"
|
|
168
|
+
: "REQUEST_ERROR");
|
|
169
|
+
// Messaggio SEMPRE specifico: prima quello esplicito dell'eccezione, altrimenti il
|
|
170
|
+
// messaggio reale dell'errore. Il generico resta solo se non c'e' alcun testo.
|
|
171
|
+
const fallbackMessage = schemaError
|
|
172
|
+
? "Schema del database non aggiornato; eseguire la migrazione e riprovare."
|
|
173
|
+
: effectiveStatus === 401
|
|
174
|
+
? "Autenticazione non valida o scaduta."
|
|
175
|
+
: effectiveStatus === 403
|
|
176
|
+
? "Operazione non autorizzata."
|
|
177
|
+
: effectiveStatus >= 500
|
|
178
|
+
? "Errore interno del server."
|
|
179
|
+
: "Richiesta non valida.";
|
|
180
|
+
const message = explicitMessage !== null && explicitMessage !== void 0 ? explicitMessage : (rawMessage.trim() || fallbackMessage);
|
|
168
181
|
return res.status(effectiveStatus).send(Object.assign({ severity: "error", status: effectiveStatus, statusCode: StatusCode.Error, code,
|
|
169
182
|
message,
|
|
170
183
|
// Compatibilita: il campo storico resta presente, ma non espone SQL, stack o dati sensibili.
|
package/dist/Utilities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utilities.js","sourceRoot":"","sources":["../src/Utilities.ts"],"names":[],"mappings":";;;;;;AAqkBA,gCAOG;AA1kBH,qCAAkC;AAClC,oDAA4B;AAG5B,IAAY,UAIX;AAJD,WAAY,UAAU;IAClB,uCAAM,CAAA;IACN,iDAAW,CAAA;IACX,6CAAS,CAAA;AACb,CAAC,EAJW,UAAU,0BAAV,UAAU,QAIrB;AAED,MAAa,aAAa;IACtB;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAW,EAAE,WAAmB;QACpD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAAC,KAAW,EAAE,SAAkB,KAAK;QACrD,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;IAC7F,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,KAAW,EAAE,SAAkB,KAAK;QACjD,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7D,OAAO,MAAM;YACT,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;YAC7C,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,KAAW;QAC3B,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACrD,OAAO,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,gBAAgB;QACnB,MAAM,GAAG,GAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7D,OAAO,GAAG,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,IAAY;QACzB,MAAM,KAAK,GAAa,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;CACJ;AAnFD,sCAmFC;AAGD,MAAa,aAAa;IACtB;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,GAAa,EAAE,OAAe,EAAE,SAAiB,GAAG;QACrE,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YAC3B,QAAQ,EAAE,SAAS;YACnB,MAAM;YACN,UAAU,EAAE,UAAU,CAAC,EAAE;YACzB,OAAO;SACV,CAAC,CAAC;IACP,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAa,EAAE,KAAc,EAAE,MAAc,cAAc,EAAE,SAAiB,GAAG;;QACrG,MAAM,UAAU,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC;QAChF,4EAA4E;QAC5E,6EAA6E;QAC7E,MAAM,UAAU,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,IAAI,eAAM,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzF,MAAM,iBAAiB,GAAG,KAA2D,CAAC;QACtF,MAAM,iBAAiB,GAAG,OAAO,CAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,WAAW,CAAA,KAAK,UAAU;YAC1E,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE;YACjC,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,gBAAgB,GAAG,iBAAiB,IAAI,OAAO,iBAAiB,KAAK,QAAQ;YAC/E,CAAC,CAAC,iBAA6E;YAC/E,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,YAAY,GAAG,OAAO,CAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,IAAI,CAAA,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACpG,MAAM,eAAe,GAAG,OAAO,CAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,OAAO,CAAA,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7G,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,OAAO,CAAC;YAC5D,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC;YAC3F,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACtD,4FAA4F;QAC5F,wGAAwG;QACxG,MAAM,eAAe,GAAG,OAAO,CAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,WAAW,CAAA,KAAK,UAAU;YACxE,CAAC,CAAC,MAAM,CAAC,MAAA,MAAC,KAAsC,EAAC,SAAS,kDAAI,CAAC;YAC/D,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,eAAe,GAAG,WAAW;YAC/B,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,IAAK,eAA0B,IAAI,GAAG;gBACrE,CAAC,CAAE,eAA0B;gBAC7B,CAAC,CAAC,MAAM,CAAC;QACjB,MAAM,IAAI,GAAG,WAAW;YACpB,CAAC,CAAC,kCAAkC;YACpC,CAAC,CAAC,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,CAAC,eAAe,IAAI,GAAG;gBACrC,CAAC,CAAC,wBAAwB;gBAC1B,CAAC,CAAC,eAAe,KAAK,GAAG;oBACrB,CAAC,CAAC,sBAAsB;oBACxB,CAAC,CAAC,eAAe,KAAK,GAAG;wBACrB,CAAC,CAAC,mBAAmB;wBACrB,CAAC,CAAC,uBAAuB,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,WAAW;YACvB,CAAC,CAAC,+FAA+F;YACjG,CAAC,CAAC,eAAe,aAAf,eAAe,cAAf,eAAe,GAAI,CAAC,eAAe,IAAI,GAAG;gBACxC,CAAC,CAAC,oCAAoC;gBACtC,CAAC,CAAC,eAAe,KAAK,GAAG;oBACrB,CAAC,CAAC,sCAAsC;oBACxC,CAAC,CAAC,eAAe,KAAK,GAAG;wBACrB,CAAC,CAAC,6BAA6B;wBAC/B,CAAC,CAAC,UAAU,IAAI,uBAAuB,CAAC,CAAC;QAEzD,OAAO,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,iBACnC,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,UAAU,CAAC,KAAK,EAC5B,IAAI;YACJ,OAAO;YACP,6FAA6F;YAC7F,KAAK,EAAE,IAAI,IACR,CAAC,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,MAAM,EAAC,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAClE,CAAC;IACP,CAAC;IAED,2EAA2E;IAC3E,MAAM,CAAC,qBAAqB,CAAC,KAAc;QACvC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC;QAC7E,OAAO,kGAAkG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5H,CAAC;IAGD,MAAM,CAAC,gBAAgB,CAAC,GAAa;QACjC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACxB,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,UAAU,CAAC,KAAK;YAC5B,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,sBAAsB;YAC7B,OAAO,EAAE,sCAAsC;SAClD,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,sBAAsB,CAAC,GAAa;QACvC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACxB,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,UAAU,CAAC,KAAK;YAC5B,IAAI,EAAE,6BAA6B;YACnC,KAAK,EAAE,6BAA6B;YACpC,OAAO,EAAE,wBAAwB;SACpC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,GAAa;QACpC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACxB,QAAQ,EAAE,SAAS;YACnB,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,UAAU,CAAC,OAAO;YAC9B,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,kBAAkB;YACzB,OAAO,EAAE,6CAA6C;SACzD,CAAC,CAAA;IACN,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAa,EAAE,OAAgB,EAAE,WAA6B,EAAE,SAAiB,GAAG;QACxG,oEAAoE;QACpE,2EAA2E;QAC3E,mFAAmF;QACnF,MAAM,UAAU,GAAG,OAAO,WAAW,KAAK,QAAQ;YAC9C,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;QAC1E,IAAI,CAAC;YACD,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACzE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CACvD,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG;gBACb,MAAM,EAAE;oBACJ,SAAS,EAAE,GAAG;oBACd,gBAAgB,EAAE,EAAE;iBACvB;gBACD,MAAM,EAAE,iBAAiB;gBACzB,OAAO,EAAE,+BAA+B;aAC3C,CAAC;YACF,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACvD,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,eAAe,CAAC,GAAa,EAAE,eAAwB,EAAE,KAAa,EAAE,SAAiB,GAAG;QAC/F,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG;gBACb,MAAM,EAAE;oBACJ,SAAS,EAAE,GAAG;oBACd,gBAAgB,EAAE,EAAE;iBACvB;gBACD,GAAG,EAAE,EAAE;gBACP,EAAE,EAAG,eAAuD,aAAvD,eAAe,uBAAf,eAAe,CAA0C,EAAE;gBAChE,IAAI,EAAE,eAAe;gBACrB,KAAK,EAAE,KAAK;aACf,CAAC;YACF,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,oCAAoC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/F,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAAgB,EAAE,EAAE,SAAoB,EAAE;QAClE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE;YAC7B,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACzB,OAAO,GAAG,CAAC;YACf,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9B,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACP,CAAC;IAGM,MAAM,CAAC,sBAAsB,CAA8B,GAAY;QAC1E,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;YACxE,MAAM,MAAM,GAAG,GAA8B,CAAC;YAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAA4B,EAAE,GAAW,EAAE,EAAE;gBACvF,MAAM,YAAY,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,WAAC,OAAA,CAAC,MAAA,CAAC,CAAC,CAAC,CAAC,mCAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA,EAAA,CAAC,CAAC;gBAC7F,GAAG,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChC,OAAO,GAAG,CAAC;YACf,CAAC,EAAE,EAAE,CAAC,CAAC;YACP,OAAO,SAAc,CAAC;QAC1B,CAAC;QACD,OAAO,GAAQ,CAAC;IACpB,CAAC;CACJ;AAxND,sCAwNC;AAGD,MAAa,cAAc;IAGvB;;;;;;;;GAQD;IACQ,MAAM,CAAC,OAAO,CAAC,SAAiB,EAAE,GAAW,EAAE,iBAAiC,QAAQ;QAC3F,IAAI,CAAC;YACD,wDAAwD;YACxD,MAAM,MAAM,GAAG,gBAAM,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;YAEpF,mDAAmD;YACnD,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;gBAClC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;gBAChC,MAAM,CAAC,KAAK,EAAE;aACjB,CAAC,CAAC;YAEH,8CAA8C;YAC9C,OAAO,eAAe,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,yCAAyC;YACzC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,gCAAgC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,OAAO,CAAC,aAAqB,EAAE,GAAW;QACpD,IAAI,CAAC;YACD,0DAA0D;YAC1D,MAAM,QAAQ,GAAG,gBAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;YACxF,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAE/B,2BAA2B;YAC3B,IAAI,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC/D,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAElC,6BAA6B;YAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACxD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;YAEtD,OAAO,OAAO,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;;AA1DL,wCA2DC;AA1D2B,qBAAM,GAAG,IAAI,eAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AA4DrE,MAAa,iBAAiB;IAQlB,MAAM,CAAC,UAAU,CAAC,WAAmB,EAAE,MAAc;QACzD,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,IAAI,GAAG,gBAAM,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,gBAAM,CAAC,UAAU,CAChC,WAAW,EACX,IAAI,EACJ,EAAE,EACF;YACI,CAAC,EAAE,IAAI,CAAC,QAAQ;YAChB,CAAC,EAAE,IAAI,CAAC,QAAQ;YAChB,CAAC,EAAE,IAAI,CAAC,QAAQ;YAChB,MAAM,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC3B,CACJ,CAAC;QAEF,OAAO;YACH,MAAM;YACN,IAAI,CAAC,QAAQ;YACb,IAAI,CAAC,QAAQ;YACb,IAAI,CAAC,QAAQ;YACb,IAAI;YACJ,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;SAC7B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IAEO,MAAM,CAAC,SAAS,CAAC,KAAa,EAAE,MAAc;QAClD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;IACvE,CAAC;IAEO,MAAM,CAAC,SAAS,CACpB,cAAsB,EACtB,cAAsB;QAQtB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9E,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAEvB,IAAI,CAAC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACjG,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACzD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO;YACH,IAAI;YACJ,YAAY;YACZ,CAAC;YACD,CAAC;YACD,CAAC;SACJ,CAAC;IACN,CAAC;IAEO,MAAM,CAAC,YAAY,CAAC,WAAmB,EAAE,cAAsB,EAAE,cAAsB;QAC3F,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,UAAU,GAAG,gBAAM,CAAC,UAAU,CAChC,WAAW,EACX,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,YAAY,CAAC,MAAM,EAC9B;YACI,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,MAAM,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC3B,CACJ,CAAC;QAEF,OAAO,gBAAM,CAAC,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC;IACvE,CAAC;IAEM,MAAM,CAAC,YAAY,CAAC,aAAqB;QAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,CAAC;IAEM,MAAM,CAAC,2BAA2B,CAAC,uBAA+B;QACrE,OAAO,IAAI,CAAC,UAAU,CAAC,uBAAuB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC7E,CAAC;IAEM,MAAM,CAAC,cAAc,CAAC,KAAa;QACtC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC;IAEM,MAAM,CAAC,oBAAoB,CAAC,KAAa;QAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC1D,CAAC;IAED,iFAAiF;IAC1E,MAAM,CAAC,sBAAsB,CAAC,KAAa,EAAE,SAAiB;QACjE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAEvD,IAAI,WAAW,CAAC,MAAM,KAAK,eAAe,CAAC,MAAM,EAAE,CAAC;YAChD,mEAAmE;YACnE,gBAAM,CAAC,eAAe,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,OAAO,gBAAM,CAAC,eAAe,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAChE,CAAC;IAEM,MAAM,CAAC,cAAc,CAAC,aAAqB,EAAE,cAAsB;QACtE,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9E,CAAC;IAEM,MAAM,CAAC,6BAA6B,CACvC,uBAA+B,EAC/B,cAAsB;QAEtB,OAAO,IAAI,CAAC,YAAY,CAAC,uBAAuB,EAAE,cAAc,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/F,CAAC;;AAhJL,8CAiJC;AAhJ2B,6BAAW,GAAG,QAAQ,CAAC;AACvB,oCAAkB,GAAG,eAAe,CAAC;AACrC,0BAAQ,GAAG,KAAK,CAAC;AACjB,0BAAQ,GAAG,CAAC,CAAC;AACb,0BAAQ,GAAG,CAAC,CAAC;AACb,6BAAW,GAAG,EAAE,CAAC;AAiJ7C;;GAEG;AACH,MAAa,iBAAiB;IAC1B;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,MAAM,CAAC,YAAY,CACtB,IAAY,EACZ,IAAY,EACZ,QAAgB,EAChB,QAAQ,GAAG,QAAQ,EACnB,QAAQ,GAAG,WAAW;QAEtB,OAAO;YACH,IAAI,EAAoB,qDAAqD;YAC7E,IAAI,EAAoB,+CAA+C;YACvE,IAAI,EAAE,QAAQ,EAAU,4CAA4C;YACpE,QAAQ,EAAgB,4CAA4C;YACpE,QAAQ,EAAgB,4CAA4C;YACpE,cAAc,EAAE,KAAK,EAAG,kFAAkF;YAC1G,IAAI,EAAE,SAAS,EAAS,4DAA4D;YACpF,QAAQ,EAAE,MAAM,EAAQ,6DAA6D;YACrF,uBAAuB,EAAE,IAAI,EAAE,wEAAwE;YACvG,UAAU,EAAE,IAAI,EAAQ,sEAAsE;YAC9F,cAAc,EAAE,KAAK;YACrB,gBAAgB,EAAE,KAAK;YACvB,iBAAiB,EAAE,IAAI;SAC1B,CAAC;IACN,CAAC;CACJ;AA7CD,8CA6CC;AAED,MAAM,iBAAiB,GAAG,IAAI,eAAM,CAAC,YAAY,CAAC,CAAC;AAEnD,SAAgB,UAAU,CAAC,OAAe;IACtC,OAAO,UAAU,MAAc,EAAE,GAAY,EAAE,UAA+B;QAC5E,KAAK,MAAM,CAAC;QACZ,KAAK,GAAG,CAAC;QACT,KAAK,UAAU,CAAC;QAChB,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { Response } from 'express';\nimport { FirebirdOptions } from \"./firebird-compat\";\nimport { Logger } from \"./Logger\";\nimport crypto from \"crypto\";\n\n\nexport enum StatusCode {\n Ok = 0,\n Warning = 1,\n Error = 2,\n}\n\nexport class DateUtilities {\n /**\n * Pads a number with leading zeros to reach a specified length.\n * @param num - The number to pad.\n * @param totalLength - The total length of the resulting string.\n * @returns The padded string.\n */\n static addStartingZeros(num: number, totalLength: number): string {\n return String(num).padStart(totalLength, '0');\n }\n\n /**\n * Formats a Date object as a Moncler-style string.\n * @param dData - The date to format.\n * @param bAddMs - Whether to include milliseconds.\n * @returns The formatted date string.\n */\n static dateToMoncler(dData: Date, bAddMs: boolean = false): string {\n const yy = dData.getFullYear();\n const mm = this.addStartingZeros(dData.getMonth() + 1, 2);\n const dd = this.addStartingZeros(dData.getDate(), 2);\n const hh = this.addStartingZeros(dData.getHours(), 2);\n const nn = this.addStartingZeros(dData.getMinutes(), 2);\n const ss = this.addStartingZeros(dData.getSeconds(), 2);\n const ms = this.addStartingZeros(dData.getMilliseconds(), 3);\n return bAddMs ? `${yy}${mm}${dd}${hh}${nn}${ss}${ms}` : `${yy}${mm}${dd}${hh}${nn}${ss}`;\n }\n\n /**\n * Formats a Date object as a SQL-style string.\n * @param dData - The date to format.\n * @param bAddMs - Whether to include milliseconds.\n * @returns The formatted date string.\n */\n static dateToSql(dData: Date, bAddMs: boolean = false): string {\n const yy = dData.getFullYear();\n const mm = this.addStartingZeros(dData.getMonth() + 1, 2);\n const dd = this.addStartingZeros(dData.getDate(), 2);\n const hh = this.addStartingZeros(dData.getHours(), 2);\n const nn = this.addStartingZeros(dData.getMinutes(), 2);\n const ss = this.addStartingZeros(dData.getSeconds(), 2);\n const ms = this.addStartingZeros(dData.getMilliseconds(), 3);\n return bAddMs\n ? `${yy}-${mm}-${dd} ${hh}:${nn}:${ss}.${ms}`\n : `${yy}-${mm}-${dd} ${hh}:${nn}:${ss}`;\n }\n\n /**\n * Formats a Date object as a simple string (dd-MM-yyyy).\n * @param dData - The date to format.\n * @returns The formatted date string.\n */\n static dateToSimple(dData: Date): string {\n const yy = dData.getFullYear();\n const mm = this.addStartingZeros(dData.getMonth() + 1, 2);\n const dd = this.addStartingZeros(dData.getDate(), 2);\n return `${dd}-${mm}-${yy}`;\n }\n\n /**\n * Gets the current date and time as a formatted string.\n * @returns The current date and time in the format dd.MM.yyyy HH:mm:ss.\n */\n static getNowDateString(): string {\n const now: Date = new Date();\n const day = now.getDate().toString().padStart(2, \"0\");\n const month = (now.getMonth() + 1).toString().padStart(2, \"0\");\n const year = now.getFullYear();\n const hours = now.getHours().toString().padStart(2, \"0\");\n const minutes = now.getMinutes().toString().padStart(2, \"0\");\n const seconds = now.getSeconds().toString().padStart(2, \"0\");\n return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`;\n }\n\n /**\n * Parses a date string in the format dd/MM/yyyy into a Date object.\n * @param date - The date string to parse.\n * @returns A Date object.\n */\n static parseDate(date: string): Date {\n const parts: string[] = date.split(\"/\");\n return new Date(Number(parts[2]), Number(parts[1]) - 1, Number(parts[0]));\n }\n}\n\n\nexport class RestUtilities {\n /**\n * Sends an OK message as a response.\n * @param res - Express Response object.\n * @param message - The success message.\n * @param status - HTTP success status. Defaults to 200; pass 201 only after creating a resource.\n * @returns The Response object.\n */\n static sendOKMessage(res: Response, message: string, status: number = 200): Response {\n return res.status(status).send({\n severity: \"success\",\n status,\n statusCode: StatusCode.Ok,\n message,\n });\n }\n\n /**\n * Sends an error message as a response.\n * @param res - Express Response object.\n * @param error - The error to send.\n * @param tag - Optional tag for additional context.\n * @param status - HTTP status code (default: 500).\n * @returns The Response object.\n */\n static sendErrorMessage(res: Response, error: unknown, tag: string = \"[BASE ERROR]\", status: number = 500): Response {\n const rawMessage = error instanceof Error ? error.message : String(error ?? \"\");\n // Logga SEMPRE l'errore reale lato server: la risposta HTTP resta generica,\n // ma senza questo log gli errori 5xx risultano impossibili da diagnosticare.\n const errorStack = error instanceof Error ? error.stack : undefined;\n new Logger(tag || \"[BASE ERROR]\").error(rawMessage, ...(errorStack ? [errorStack] : []));\n const errorWithResponse = error as { getResponse?: () => unknown } | null | undefined;\n const exceptionResponse = typeof errorWithResponse?.getResponse === \"function\"\n ? errorWithResponse.getResponse()\n : undefined;\n const exceptionPayload = exceptionResponse && typeof exceptionResponse === \"object\"\n ? exceptionResponse as { code?: unknown; message?: unknown; details?: unknown }\n : undefined;\n const explicitCode = typeof exceptionPayload?.code === \"string\" ? exceptionPayload.code : undefined;\n const explicitMessage = typeof exceptionPayload?.message === \"string\" ? exceptionPayload.message : undefined;\n const explicitDetails = Array.isArray(exceptionPayload?.details)\n ? exceptionPayload.details.filter((detail): detail is string => typeof detail === \"string\")\n : undefined;\n const schemaError = this.isDatabaseSchemaError(error);\n // Per le HttpException lo status corretto e quello dell'eccezione (es. 400 di validazione),\n // anche quando il chiamante non lo passa esplicitamente. Lo status esplicito vale per gli altri errori.\n const exceptionStatus = typeof errorWithResponse?.getResponse === \"function\"\n ? Number((error as { getStatus?: () => number }).getStatus?.())\n : undefined;\n const effectiveStatus = schemaError\n ? 503\n : Number.isInteger(exceptionStatus) && (exceptionStatus as number) >= 400\n ? (exceptionStatus as number)\n : status;\n const code = schemaError\n ? \"ACCESSI_DATABASE_SCHEMA_OUTDATED\"\n : explicitCode ?? (effectiveStatus >= 500\n ? \"ACCESSI_INTERNAL_ERROR\"\n : effectiveStatus === 401\n ? \"ACCESSI_UNAUTHORIZED\"\n : effectiveStatus === 403\n ? \"ACCESSI_FORBIDDEN\"\n : \"ACCESSI_REQUEST_ERROR\");\n const message = schemaError\n ? \"Lo schema del database Accessi non e aggiornato. Eseguire la migrazione database e riprovare.\"\n : explicitMessage ?? (effectiveStatus >= 500\n ? \"Errore interno del modulo Accessi.\"\n : effectiveStatus === 401\n ? \"Autenticazione non valida o scaduta.\"\n : effectiveStatus === 403\n ? \"Operazione non autorizzata.\"\n : rawMessage || \"Richiesta non valida.\");\n\n return res.status(effectiveStatus).send({\n severity: \"error\",\n status: effectiveStatus,\n statusCode: StatusCode.Error,\n code,\n message,\n // Compatibilita: il campo storico resta presente, ma non espone SQL, stack o dati sensibili.\n error: code,\n ...(explicitDetails?.length ? { details: explicitDetails } : {}),\n });\n }\n\n /** Riconosce errori di metadata Firebird che richiedono una migrazione. */\n static isDatabaseSchemaError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n return /column unknown|table unknown|dynamic sql error|unsuccessful metadata update|invalid request blr/i.test(message);\n }\n\n\n static sendUnauthorized(res: Response): Response {\n return res.status(401).send({\n severity: \"error\",\n status: 401,\n statusCode: StatusCode.Error,\n code: \"ACCESSI_UNAUTHORIZED\",\n error: \"ACCESSI_UNAUTHORIZED\",\n message: \"Autenticazione non valida o scaduta.\",\n });\n }\n\n static sendInvalidCredentials(res: Response): Response {\n return res.status(401).send({\n severity: \"error\",\n status: 401,\n statusCode: StatusCode.Error,\n code: \"ACCESSI_INVALID_CREDENTIALS\",\n error: \"ACCESSI_INVALID_CREDENTIALS\",\n message: \"Credenziali non valide\",\n });\n }\n\n static sendPasswordExpired(res: Response): Response {\n return res.status(403).send({\n severity: \"warning\",\n status: 403,\n statusCode: StatusCode.Warning,\n code: \"PASSWORD_EXPIRED\",\n error: \"PASSWORD_EXPIRED\",\n message: \"Password scaduta. E' necessario aggiornarla\"\n })\n }\n\n /**\n * Sends a base response with a payload.\n * @param res - Express Response object.\n * @param payload - The payload to include in the response.\n * @param status - HTTP success status. Defaults to 200; pass 201 only after creating a resource.\n * @returns The Response object.\n */\n static sendBaseResponse(res: Response, payload: unknown, statusOrTag?: number | string, status: number = 200): Response {\n // Retro-compatibilita: molti controller passano un \"tag\" come terzo\n // argomento (es. sendBaseResponse(res, dati, 'clienti')). Il tag NON e uno\n // status HTTP: veniva ignorato nella firma storica e non deve rompere la risposta.\n const httpStatus = typeof statusOrTag === 'number'\n ? statusOrTag\n : (Number.isInteger(status) ? status : 200);\n const tag = typeof statusOrTag === 'string' ? statusOrTag : \"[UTILITIES]\";\n try {\n const normalizedPayload = JSON.parse(JSON.stringify(payload, (_key, value) =>\n typeof value === 'bigint' ? value.toString() : value\n ));\n const response = {\n Status: {\n errorCode: \"0\",\n errorDescription: \"\",\n },\n Result: normalizedPayload,\n Message: \"Dati recuperati con successo.\",\n };\n return res.status(httpStatus).send(response);\n } catch (error) {\n return this.sendErrorMessage(res, error, tag, 500);\n }\n }\n\n /**\n * Sends an execution message as a response.\n * @param res - Express Response object.\n * @param executionObject - The execution data.\n * @param title - The title of the response.\n * @param status - HTTP success status. Defaults to 200.\n * @returns The Response object.\n */\n static sendExecMessage(res: Response, executionObject: unknown, title: string, status: number = 200): Response {\n try {\n const response = {\n Status: {\n errorCode: \"0\",\n errorDescription: \"\",\n },\n Sql: \"\",\n ID: (executionObject as { id?: unknown } | null | undefined)?.id,\n data: executionObject,\n Title: title,\n };\n return res.status(status).send(response);\n } catch (error) {\n return this.sendErrorMessage(res, `Error sending execution message: ${error}`, title, 500);\n }\n }\n\n /**\n * Prints a SQL query with parameters replaced. Replacement is literal: values\n * containing `?` or `$&` no longer corrupt the output as in the legacy\n * `String.replace` implementation.\n * @param query - The SQL query.\n * @param params - The parameters to replace.\n * @returns The formatted query.\n */\n static printQueryWithParams(query: string = \"\", params: unknown[] = []): string {\n let index = 0;\n return query.replace(/\\?/g, () => {\n if (index >= params.length) {\n return \"?\";\n }\n const param = params[index++];\n return param === undefined || param === null ? \"NULL\" : String(param);\n });\n }\n\n\n public static convertKeysToCamelCase<T = Record<string, unknown>>(obj: unknown): T {\n if (obj !== null && typeof obj === \"object\" && obj.constructor === Object) {\n const source = obj as Record<string, unknown>;\n const converted = Object.keys(source).reduce((acc: Record<string, unknown>, key: string) => {\n const camelCaseKey = key.toLowerCase().replace(/_([a-z])/g, g => (g[1] ?? '').toUpperCase());\n acc[camelCaseKey] = source[key];\n return acc;\n }, {});\n return converted as T;\n }\n return obj as T;\n }\n}\n\n\nexport class CryptUtilities {\n private static readonly logger = new Logger(CryptUtilities.name);\n\n /**\n * Cifra un testo in chiaro usando l'algoritmo AES-128 in modalità ECB.\n * \n * @param plainText - Il testo in chiaro da cifrare.\n * @param key - La chiave di cifratura (16 byte per AES-128).\n * @param outputEncoding - Codifica del risultato cifrato (predefinito: \"base64\").\n * @returns Il testo cifrato codificato.\n * @throws Errore in caso di problemi durante la cifratura.\n */\n public static encrypt(plainData: string, key: string, outputEncoding: BufferEncoding = \"base64\"): string {\n try {\n // Crea un oggetto Cipher usando AES-128 in modalità ECB\n const cipher = crypto.createCipheriv(\"aes-128-ecb\", Buffer.from(key, \"utf8\"), null);\n\n // Cifra il testo in chiaro e finalizza il processo\n const encryptedBuffer = Buffer.concat([\n cipher.update(plainData, \"utf8\"),\n cipher.final(),\n ]);\n\n // Restituisce il risultato cifrato codificato\n return encryptedBuffer.toString(outputEncoding);\n } catch (error) {\n // Gestisce eventuali errori di cifratura\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Errore durante la cifratura: ${message}`);\n }\n }\n\n /**\n * Decifra un testo cifrato usando l'algoritmo AES-128 in modalità ECB.\n * \n * @param encryptedData - Il testo cifrato da decifrare.\n * @param key - La chiave di decifratura (16 byte per AES-128).\n * @returns Il testo decifrato o null in caso di errore.\n */\n public static decrypt(encryptedData: string, key: string): string | null {\n try {\n // Crea un oggetto Decipher usando AES-128 in modalità ECB\n const decipher = crypto.createDecipheriv(\"aes-128-ecb\", Buffer.from(key, \"utf8\"), null);\n decipher.setAutoPadding(false);\n\n // Decifra il testo cifrato\n let decoded = decipher.update(encryptedData, \"base64\", \"utf8\");\n decoded += decipher.final(\"utf8\");\n\n // Rimuove il padding manuale\n const lastChar = decoded.charCodeAt(decoded.length - 1);\n decoded = decoded.slice(0, decoded.length - lastChar);\n\n return decoded;\n } catch (error) {\n CryptUtilities.logger.error(\"Errore durante la decifratura:\", error);\n return null;\n }\n }\n}\n\nexport class PasswordUtilities {\n private static readonly HASH_PREFIX = \"scrypt\";\n private static readonly LEGACY_HASH_PREFIX = \"scrypt-legacy\";\n private static readonly SCRYPT_N = 16384;\n private static readonly SCRYPT_R = 8;\n private static readonly SCRYPT_P = 1;\n private static readonly SALT_LENGTH = 16;\n\n private static hashSecret(secretValue: string, prefix: string): string {\n if (typeof secretValue !== \"string\" || secretValue.length === 0) {\n throw new Error(\"Il valore da proteggere non puo essere vuoto.\");\n }\n const salt = crypto.randomBytes(this.SALT_LENGTH).toString(\"hex\");\n const derivedKey = crypto.scryptSync(\n secretValue,\n salt,\n 64,\n {\n N: this.SCRYPT_N,\n r: this.SCRYPT_R,\n p: this.SCRYPT_P,\n maxmem: 64 * 1024 * 1024,\n },\n );\n\n return [\n prefix,\n this.SCRYPT_N,\n this.SCRYPT_R,\n this.SCRYPT_P,\n salt,\n derivedKey.toString(\"hex\"),\n ].join(\"$\");\n }\n\n private static hasPrefix(value: string, prefix: string): boolean {\n return typeof value === \"string\" && value.startsWith(`${prefix}$`);\n }\n\n private static parseHash(\n storedPassword: string,\n expectedPrefix: string\n ): {\n salt: string;\n expectedHash: Buffer;\n N: number;\n r: number;\n p: number;\n } | null {\n if (!this.hasPrefix(storedPassword, expectedPrefix)) {\n return null;\n }\n\n const [, rawN, rawR, rawP, salt, expectedHashHex] = storedPassword.split(\"$\");\n const N = Number(rawN);\n const r = Number(rawR);\n const p = Number(rawP);\n\n if (!salt || !expectedHashHex || !Number.isFinite(N) || !Number.isFinite(r) || !Number.isFinite(p)) {\n return null;\n }\n\n const expectedHash = Buffer.from(expectedHashHex, \"hex\");\n if (expectedHash.length === 0) {\n return null;\n }\n\n return {\n salt,\n expectedHash,\n N,\n r,\n p,\n };\n }\n\n private static verifySecret(secretValue: string, storedPassword: string, expectedPrefix: string): boolean {\n if (typeof secretValue !== \"string\") {\n return false;\n }\n\n const parsedHash = this.parseHash(storedPassword, expectedPrefix);\n if (!parsedHash) {\n return false;\n }\n\n const derivedKey = crypto.scryptSync(\n secretValue,\n parsedHash.salt,\n parsedHash.expectedHash.length,\n {\n N: parsedHash.N,\n r: parsedHash.r,\n p: parsedHash.p,\n maxmem: 64 * 1024 * 1024,\n },\n );\n\n return crypto.timingSafeEqual(derivedKey, parsedHash.expectedHash);\n }\n\n public static hashPassword(plainPassword: string): string {\n return this.hashSecret(plainPassword, this.HASH_PREFIX);\n }\n\n public static hashLegacyEncryptedPassword(legacyEncryptedPassword: string): string {\n return this.hashSecret(legacyEncryptedPassword, this.LEGACY_HASH_PREFIX);\n }\n\n public static isPasswordHash(value: string): boolean {\n return this.hasPrefix(value, this.HASH_PREFIX);\n }\n\n public static isLegacyPasswordHash(value: string): boolean {\n return this.hasPrefix(value, this.LEGACY_HASH_PREFIX);\n }\n\n /** Confronto a tempo costante tra due stringhe (per dati legacy non hashati). */\n public static timingSafeStringEquals(value: string, candidate: string): boolean {\n if (typeof value !== \"string\" || typeof candidate !== \"string\") {\n return false;\n }\n\n const valueBuffer = Buffer.from(value, \"utf8\");\n const candidateBuffer = Buffer.from(candidate, \"utf8\");\n\n if (valueBuffer.length !== candidateBuffer.length) {\n // Confronta comunque per non rivelare la lunghezza tramite timing.\n crypto.timingSafeEqual(valueBuffer, valueBuffer);\n return false;\n }\n\n return crypto.timingSafeEqual(valueBuffer, candidateBuffer);\n }\n\n public static verifyPassword(plainPassword: string, storedPassword: string): boolean {\n return this.verifySecret(plainPassword, storedPassword, this.HASH_PREFIX);\n }\n\n public static verifyLegacyEncryptedPassword(\n legacyEncryptedPassword: string,\n storedPassword: string\n ): boolean {\n return this.verifySecret(legacyEncryptedPassword, storedPassword, this.LEGACY_HASH_PREFIX);\n }\n}\n\n\n\n\n\n/**\n * Utility class for managing database-related configurations and operations.\n */\nexport class DatabaseUtilities {\n /**\n * Creates a configuration object for connecting to a Firebird database.\n *\n * @param {string} host - The hostname or IP address of the database server.\n * @param {number} port - The port number on which the database server is running.\n * @param {string} database - The path or alias of the database to connect to.\n * @param {string} [username='SYSDBA'] - The username for authentication. Defaults to 'SYSDBA'.\n * @param {string} [password='masterkey'] - The password for authentication. Defaults to 'masterkey'.\n * @returns {Options} - The configuration object to use for establishing a Firebird database connection.\n *\n * @example\n * ```typescript\n * const options = DatabaseUtilities.createOption(\n * 'localhost',\n * 3050,\n * '/path/to/database.fdb',\n * 'myUsername',\n * 'myPassword'\n * );\n * ```\n */\n public static createOption(\n host: string,\n port: number,\n database: string,\n username = 'SYSDBA',\n password = 'masterkey'\n ): FirebirdOptions {\n return {\n host, // The hostname or IP address of the database server.\n port, // The port number used by the database server.\n user: username, // The username for database authentication.\n password, // The password for database authentication.\n database, // The path or alias of the target database.\n lowercase_keys: false, // Determines if the keys in query results should be in lowercase. Default: false.\n role: undefined, // The role for the database connection. Default: undefined.\n pageSize: 100000, // The page size for database transactions. Default: 100,000.\n retryConnectionInterval: 1000, // The interval (in ms) to retry a failed connection. Default: 1,000 ms.\n blobAsText: true, // Determines if BLOB fields should be treated as text. Default: true.\n connectTimeout: 15000,\n connectTimeoutMs: 15000,\n trimStringResults: true,\n };\n }\n}\n\nconst deprecationLogger = new Logger('Deprecated');\n\nexport function Deprecated(message: string) {\n return function (target: object, key?: string, descriptor?: PropertyDescriptor) {\n void target;\n void key;\n void descriptor;\n deprecationLogger.warning(`[DEPRECATED] ${message}`);\n };\n }\n"]}
|
|
1
|
+
{"version":3,"file":"Utilities.js","sourceRoot":"","sources":["../src/Utilities.ts"],"names":[],"mappings":"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","sourcesContent":["import { Response } from 'express';\nimport { FirebirdOptions } from \"./firebird-compat\";\nimport { Logger } from \"./Logger\";\nimport crypto from \"crypto\";\n\n\nexport enum StatusCode {\n Ok = 0,\n Warning = 1,\n Error = 2,\n}\n\nexport class DateUtilities {\n /**\n * Pads a number with leading zeros to reach a specified length.\n * @param num - The number to pad.\n * @param totalLength - The total length of the resulting string.\n * @returns The padded string.\n */\n static addStartingZeros(num: number, totalLength: number): string {\n return String(num).padStart(totalLength, '0');\n }\n\n /**\n * Formats a Date object as a Moncler-style string.\n * @param dData - The date to format.\n * @param bAddMs - Whether to include milliseconds.\n * @returns The formatted date string.\n */\n static dateToMoncler(dData: Date, bAddMs: boolean = false): string {\n const yy = dData.getFullYear();\n const mm = this.addStartingZeros(dData.getMonth() + 1, 2);\n const dd = this.addStartingZeros(dData.getDate(), 2);\n const hh = this.addStartingZeros(dData.getHours(), 2);\n const nn = this.addStartingZeros(dData.getMinutes(), 2);\n const ss = this.addStartingZeros(dData.getSeconds(), 2);\n const ms = this.addStartingZeros(dData.getMilliseconds(), 3);\n return bAddMs ? `${yy}${mm}${dd}${hh}${nn}${ss}${ms}` : `${yy}${mm}${dd}${hh}${nn}${ss}`;\n }\n\n /**\n * Formats a Date object as a SQL-style string.\n * @param dData - The date to format.\n * @param bAddMs - Whether to include milliseconds.\n * @returns The formatted date string.\n */\n static dateToSql(dData: Date, bAddMs: boolean = false): string {\n const yy = dData.getFullYear();\n const mm = this.addStartingZeros(dData.getMonth() + 1, 2);\n const dd = this.addStartingZeros(dData.getDate(), 2);\n const hh = this.addStartingZeros(dData.getHours(), 2);\n const nn = this.addStartingZeros(dData.getMinutes(), 2);\n const ss = this.addStartingZeros(dData.getSeconds(), 2);\n const ms = this.addStartingZeros(dData.getMilliseconds(), 3);\n return bAddMs\n ? `${yy}-${mm}-${dd} ${hh}:${nn}:${ss}.${ms}`\n : `${yy}-${mm}-${dd} ${hh}:${nn}:${ss}`;\n }\n\n /**\n * Formats a Date object as a simple string (dd-MM-yyyy).\n * @param dData - The date to format.\n * @returns The formatted date string.\n */\n static dateToSimple(dData: Date): string {\n const yy = dData.getFullYear();\n const mm = this.addStartingZeros(dData.getMonth() + 1, 2);\n const dd = this.addStartingZeros(dData.getDate(), 2);\n return `${dd}-${mm}-${yy}`;\n }\n\n /**\n * Gets the current date and time as a formatted string.\n * @returns The current date and time in the format dd.MM.yyyy HH:mm:ss.\n */\n static getNowDateString(): string {\n const now: Date = new Date();\n const day = now.getDate().toString().padStart(2, \"0\");\n const month = (now.getMonth() + 1).toString().padStart(2, \"0\");\n const year = now.getFullYear();\n const hours = now.getHours().toString().padStart(2, \"0\");\n const minutes = now.getMinutes().toString().padStart(2, \"0\");\n const seconds = now.getSeconds().toString().padStart(2, \"0\");\n return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`;\n }\n\n /**\n * Parses a date string in the format dd/MM/yyyy into a Date object.\n * @param date - The date string to parse.\n * @returns A Date object.\n */\n static parseDate(date: string): Date {\n const parts: string[] = date.split(\"/\");\n return new Date(Number(parts[2]), Number(parts[1]) - 1, Number(parts[0]));\n }\n}\n\n\nexport class RestUtilities {\n /**\n * Sends an OK message as a response.\n * @param res - Express Response object.\n * @param message - The success message.\n * @param status - HTTP success status. Defaults to 200; pass 201 only after creating a resource.\n * @returns The Response object.\n */\n static sendOKMessage(res: Response, message: string, status: number = 200): Response {\n return res.status(status).send({\n severity: \"success\",\n status,\n statusCode: StatusCode.Ok,\n message,\n });\n }\n\n /**\n * Sends an error message as a response.\n * @param res - Express Response object.\n * @param error - The error to send.\n * @param tag - Optional tag for additional context.\n * @param status - HTTP status code (default: 500).\n * @returns The Response object.\n */\n static sendErrorMessage(res: Response, error: unknown, tag: string = \"[BASE ERROR]\", status: number = 500): Response {\n const rawMessage = error instanceof Error ? error.message : String(error ?? \"\");\n // Logga SEMPRE l'errore reale lato server (con stack) per la diagnosi.\n const errorStack = error instanceof Error ? error.stack : undefined;\n new Logger(tag || \"[BASE ERROR]\").error(rawMessage, ...(errorStack ? [errorStack] : []));\n const errorWithResponse = error as { getResponse?: () => unknown } | null | undefined;\n const exceptionResponse = typeof errorWithResponse?.getResponse === \"function\"\n ? errorWithResponse.getResponse()\n : undefined;\n const exceptionPayload = exceptionResponse && typeof exceptionResponse === \"object\"\n ? exceptionResponse as { code?: unknown; message?: unknown; details?: unknown }\n : undefined;\n const explicitCode = typeof exceptionPayload?.code === \"string\" ? exceptionPayload.code : undefined;\n const explicitMessage = typeof exceptionPayload?.message === \"string\" ? exceptionPayload.message : undefined;\n const explicitDetails = Array.isArray(exceptionPayload?.details)\n ? exceptionPayload.details.filter((detail): detail is string => typeof detail === \"string\")\n : undefined;\n const schemaError = this.isDatabaseSchemaError(error);\n // Per le HttpException lo status corretto e quello dell'eccezione (es. 400 di validazione),\n // anche quando il chiamante non lo passa esplicitamente. Lo status esplicito vale per gli altri errori.\n const exceptionStatus = typeof errorWithResponse?.getResponse === \"function\"\n ? Number((error as { getStatus?: () => number }).getStatus?.())\n : undefined;\n const hasExceptionStatus = Number.isInteger(exceptionStatus) && (exceptionStatus as number) >= 400;\n // Molti controller chiamano `sendErrorMessage(res, err)` anche per errori di input:\n // riconosciamo i casi di validazione per non rispondere 500.\n const looksLikeValidation = !hasExceptionStatus && !schemaError\n && /obbligatorio|obbligatoria|mancante|manca il parametro|non valido|non valida|required|missing|invalid input/i.test(rawMessage);\n const effectiveStatus = schemaError\n ? 503\n : hasExceptionStatus\n ? (exceptionStatus as number)\n : looksLikeValidation\n ? 400\n : status;\n // Codici GENERICI (questo helper non appartiene al modulo Accessi): i codici\n // ACCESSI_* restano di competenza esclusiva del modulo Accessi.\n const code = explicitCode ?? (schemaError\n ? \"DATABASE_SCHEMA_OUTDATED\"\n : effectiveStatus === 401\n ? \"UNAUTHORIZED\"\n : effectiveStatus === 403\n ? \"FORBIDDEN\"\n : effectiveStatus === 400\n ? \"VALIDATION_ERROR\"\n : effectiveStatus >= 500\n ? \"INTERNAL_ERROR\"\n : \"REQUEST_ERROR\");\n // Messaggio SEMPRE specifico: prima quello esplicito dell'eccezione, altrimenti il\n // messaggio reale dell'errore. Il generico resta solo se non c'e' alcun testo.\n const fallbackMessage = schemaError\n ? \"Schema del database non aggiornato; eseguire la migrazione e riprovare.\"\n : effectiveStatus === 401\n ? \"Autenticazione non valida o scaduta.\"\n : effectiveStatus === 403\n ? \"Operazione non autorizzata.\"\n : effectiveStatus >= 500\n ? \"Errore interno del server.\"\n : \"Richiesta non valida.\";\n const message = explicitMessage ?? (rawMessage.trim() || fallbackMessage);\n\n return res.status(effectiveStatus).send({\n severity: \"error\",\n status: effectiveStatus,\n statusCode: StatusCode.Error,\n code,\n message,\n // Compatibilita: il campo storico resta presente, ma non espone SQL, stack o dati sensibili.\n error: code,\n ...(explicitDetails?.length ? { details: explicitDetails } : {}),\n });\n }\n\n /** Riconosce errori di metadata Firebird che richiedono una migrazione. */\n static isDatabaseSchemaError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n return /column unknown|table unknown|dynamic sql error|unsuccessful metadata update|invalid request blr/i.test(message);\n }\n\n\n static sendUnauthorized(res: Response): Response {\n return res.status(401).send({\n severity: \"error\",\n status: 401,\n statusCode: StatusCode.Error,\n code: \"ACCESSI_UNAUTHORIZED\",\n error: \"ACCESSI_UNAUTHORIZED\",\n message: \"Autenticazione non valida o scaduta.\",\n });\n }\n\n static sendInvalidCredentials(res: Response): Response {\n return res.status(401).send({\n severity: \"error\",\n status: 401,\n statusCode: StatusCode.Error,\n code: \"ACCESSI_INVALID_CREDENTIALS\",\n error: \"ACCESSI_INVALID_CREDENTIALS\",\n message: \"Credenziali non valide\",\n });\n }\n\n static sendPasswordExpired(res: Response): Response {\n return res.status(403).send({\n severity: \"warning\",\n status: 403,\n statusCode: StatusCode.Warning,\n code: \"PASSWORD_EXPIRED\",\n error: \"PASSWORD_EXPIRED\",\n message: \"Password scaduta. E' necessario aggiornarla\"\n })\n }\n\n /**\n * Sends a base response with a payload.\n * @param res - Express Response object.\n * @param payload - The payload to include in the response.\n * @param status - HTTP success status. Defaults to 200; pass 201 only after creating a resource.\n * @returns The Response object.\n */\n static sendBaseResponse(res: Response, payload: unknown, statusOrTag?: number | string, status: number = 200): Response {\n // Retro-compatibilita: molti controller passano un \"tag\" come terzo\n // argomento (es. sendBaseResponse(res, dati, 'clienti')). Il tag NON e uno\n // status HTTP: veniva ignorato nella firma storica e non deve rompere la risposta.\n const httpStatus = typeof statusOrTag === 'number'\n ? statusOrTag\n : (Number.isInteger(status) ? status : 200);\n const tag = typeof statusOrTag === 'string' ? statusOrTag : \"[UTILITIES]\";\n try {\n const normalizedPayload = JSON.parse(JSON.stringify(payload, (_key, value) =>\n typeof value === 'bigint' ? value.toString() : value\n ));\n const response = {\n Status: {\n errorCode: \"0\",\n errorDescription: \"\",\n },\n Result: normalizedPayload,\n Message: \"Dati recuperati con successo.\",\n };\n return res.status(httpStatus).send(response);\n } catch (error) {\n return this.sendErrorMessage(res, error, tag, 500);\n }\n }\n\n /**\n * Sends an execution message as a response.\n * @param res - Express Response object.\n * @param executionObject - The execution data.\n * @param title - The title of the response.\n * @param status - HTTP success status. Defaults to 200.\n * @returns The Response object.\n */\n static sendExecMessage(res: Response, executionObject: unknown, title: string, status: number = 200): Response {\n try {\n const response = {\n Status: {\n errorCode: \"0\",\n errorDescription: \"\",\n },\n Sql: \"\",\n ID: (executionObject as { id?: unknown } | null | undefined)?.id,\n data: executionObject,\n Title: title,\n };\n return res.status(status).send(response);\n } catch (error) {\n return this.sendErrorMessage(res, `Error sending execution message: ${error}`, title, 500);\n }\n }\n\n /**\n * Prints a SQL query with parameters replaced. Replacement is literal: values\n * containing `?` or `$&` no longer corrupt the output as in the legacy\n * `String.replace` implementation.\n * @param query - The SQL query.\n * @param params - The parameters to replace.\n * @returns The formatted query.\n */\n static printQueryWithParams(query: string = \"\", params: unknown[] = []): string {\n let index = 0;\n return query.replace(/\\?/g, () => {\n if (index >= params.length) {\n return \"?\";\n }\n const param = params[index++];\n return param === undefined || param === null ? \"NULL\" : String(param);\n });\n }\n\n\n public static convertKeysToCamelCase<T = Record<string, unknown>>(obj: unknown): T {\n if (obj !== null && typeof obj === \"object\" && obj.constructor === Object) {\n const source = obj as Record<string, unknown>;\n const converted = Object.keys(source).reduce((acc: Record<string, unknown>, key: string) => {\n const camelCaseKey = key.toLowerCase().replace(/_([a-z])/g, g => (g[1] ?? '').toUpperCase());\n acc[camelCaseKey] = source[key];\n return acc;\n }, {});\n return converted as T;\n }\n return obj as T;\n }\n}\n\n\nexport class CryptUtilities {\n private static readonly logger = new Logger(CryptUtilities.name);\n\n /**\n * Cifra un testo in chiaro usando l'algoritmo AES-128 in modalità ECB.\n * \n * @param plainText - Il testo in chiaro da cifrare.\n * @param key - La chiave di cifratura (16 byte per AES-128).\n * @param outputEncoding - Codifica del risultato cifrato (predefinito: \"base64\").\n * @returns Il testo cifrato codificato.\n * @throws Errore in caso di problemi durante la cifratura.\n */\n public static encrypt(plainData: string, key: string, outputEncoding: BufferEncoding = \"base64\"): string {\n try {\n // Crea un oggetto Cipher usando AES-128 in modalità ECB\n const cipher = crypto.createCipheriv(\"aes-128-ecb\", Buffer.from(key, \"utf8\"), null);\n\n // Cifra il testo in chiaro e finalizza il processo\n const encryptedBuffer = Buffer.concat([\n cipher.update(plainData, \"utf8\"),\n cipher.final(),\n ]);\n\n // Restituisce il risultato cifrato codificato\n return encryptedBuffer.toString(outputEncoding);\n } catch (error) {\n // Gestisce eventuali errori di cifratura\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Errore durante la cifratura: ${message}`);\n }\n }\n\n /**\n * Decifra un testo cifrato usando l'algoritmo AES-128 in modalità ECB.\n * \n * @param encryptedData - Il testo cifrato da decifrare.\n * @param key - La chiave di decifratura (16 byte per AES-128).\n * @returns Il testo decifrato o null in caso di errore.\n */\n public static decrypt(encryptedData: string, key: string): string | null {\n try {\n // Crea un oggetto Decipher usando AES-128 in modalità ECB\n const decipher = crypto.createDecipheriv(\"aes-128-ecb\", Buffer.from(key, \"utf8\"), null);\n decipher.setAutoPadding(false);\n\n // Decifra il testo cifrato\n let decoded = decipher.update(encryptedData, \"base64\", \"utf8\");\n decoded += decipher.final(\"utf8\");\n\n // Rimuove il padding manuale\n const lastChar = decoded.charCodeAt(decoded.length - 1);\n decoded = decoded.slice(0, decoded.length - lastChar);\n\n return decoded;\n } catch (error) {\n CryptUtilities.logger.error(\"Errore durante la decifratura:\", error);\n return null;\n }\n }\n}\n\nexport class PasswordUtilities {\n private static readonly HASH_PREFIX = \"scrypt\";\n private static readonly LEGACY_HASH_PREFIX = \"scrypt-legacy\";\n private static readonly SCRYPT_N = 16384;\n private static readonly SCRYPT_R = 8;\n private static readonly SCRYPT_P = 1;\n private static readonly SALT_LENGTH = 16;\n\n private static hashSecret(secretValue: string, prefix: string): string {\n if (typeof secretValue !== \"string\" || secretValue.length === 0) {\n throw new Error(\"Il valore da proteggere non puo essere vuoto.\");\n }\n const salt = crypto.randomBytes(this.SALT_LENGTH).toString(\"hex\");\n const derivedKey = crypto.scryptSync(\n secretValue,\n salt,\n 64,\n {\n N: this.SCRYPT_N,\n r: this.SCRYPT_R,\n p: this.SCRYPT_P,\n maxmem: 64 * 1024 * 1024,\n },\n );\n\n return [\n prefix,\n this.SCRYPT_N,\n this.SCRYPT_R,\n this.SCRYPT_P,\n salt,\n derivedKey.toString(\"hex\"),\n ].join(\"$\");\n }\n\n private static hasPrefix(value: string, prefix: string): boolean {\n return typeof value === \"string\" && value.startsWith(`${prefix}$`);\n }\n\n private static parseHash(\n storedPassword: string,\n expectedPrefix: string\n ): {\n salt: string;\n expectedHash: Buffer;\n N: number;\n r: number;\n p: number;\n } | null {\n if (!this.hasPrefix(storedPassword, expectedPrefix)) {\n return null;\n }\n\n const [, rawN, rawR, rawP, salt, expectedHashHex] = storedPassword.split(\"$\");\n const N = Number(rawN);\n const r = Number(rawR);\n const p = Number(rawP);\n\n if (!salt || !expectedHashHex || !Number.isFinite(N) || !Number.isFinite(r) || !Number.isFinite(p)) {\n return null;\n }\n\n const expectedHash = Buffer.from(expectedHashHex, \"hex\");\n if (expectedHash.length === 0) {\n return null;\n }\n\n return {\n salt,\n expectedHash,\n N,\n r,\n p,\n };\n }\n\n private static verifySecret(secretValue: string, storedPassword: string, expectedPrefix: string): boolean {\n if (typeof secretValue !== \"string\") {\n return false;\n }\n\n const parsedHash = this.parseHash(storedPassword, expectedPrefix);\n if (!parsedHash) {\n return false;\n }\n\n const derivedKey = crypto.scryptSync(\n secretValue,\n parsedHash.salt,\n parsedHash.expectedHash.length,\n {\n N: parsedHash.N,\n r: parsedHash.r,\n p: parsedHash.p,\n maxmem: 64 * 1024 * 1024,\n },\n );\n\n return crypto.timingSafeEqual(derivedKey, parsedHash.expectedHash);\n }\n\n public static hashPassword(plainPassword: string): string {\n return this.hashSecret(plainPassword, this.HASH_PREFIX);\n }\n\n public static hashLegacyEncryptedPassword(legacyEncryptedPassword: string): string {\n return this.hashSecret(legacyEncryptedPassword, this.LEGACY_HASH_PREFIX);\n }\n\n public static isPasswordHash(value: string): boolean {\n return this.hasPrefix(value, this.HASH_PREFIX);\n }\n\n public static isLegacyPasswordHash(value: string): boolean {\n return this.hasPrefix(value, this.LEGACY_HASH_PREFIX);\n }\n\n /** Confronto a tempo costante tra due stringhe (per dati legacy non hashati). */\n public static timingSafeStringEquals(value: string, candidate: string): boolean {\n if (typeof value !== \"string\" || typeof candidate !== \"string\") {\n return false;\n }\n\n const valueBuffer = Buffer.from(value, \"utf8\");\n const candidateBuffer = Buffer.from(candidate, \"utf8\");\n\n if (valueBuffer.length !== candidateBuffer.length) {\n // Confronta comunque per non rivelare la lunghezza tramite timing.\n crypto.timingSafeEqual(valueBuffer, valueBuffer);\n return false;\n }\n\n return crypto.timingSafeEqual(valueBuffer, candidateBuffer);\n }\n\n public static verifyPassword(plainPassword: string, storedPassword: string): boolean {\n return this.verifySecret(plainPassword, storedPassword, this.HASH_PREFIX);\n }\n\n public static verifyLegacyEncryptedPassword(\n legacyEncryptedPassword: string,\n storedPassword: string\n ): boolean {\n return this.verifySecret(legacyEncryptedPassword, storedPassword, this.LEGACY_HASH_PREFIX);\n }\n}\n\n\n\n\n\n/**\n * Utility class for managing database-related configurations and operations.\n */\nexport class DatabaseUtilities {\n /**\n * Creates a configuration object for connecting to a Firebird database.\n *\n * @param {string} host - The hostname or IP address of the database server.\n * @param {number} port - The port number on which the database server is running.\n * @param {string} database - The path or alias of the database to connect to.\n * @param {string} [username='SYSDBA'] - The username for authentication. Defaults to 'SYSDBA'.\n * @param {string} [password='masterkey'] - The password for authentication. Defaults to 'masterkey'.\n * @returns {Options} - The configuration object to use for establishing a Firebird database connection.\n *\n * @example\n * ```typescript\n * const options = DatabaseUtilities.createOption(\n * 'localhost',\n * 3050,\n * '/path/to/database.fdb',\n * 'myUsername',\n * 'myPassword'\n * );\n * ```\n */\n public static createOption(\n host: string,\n port: number,\n database: string,\n username = 'SYSDBA',\n password = 'masterkey'\n ): FirebirdOptions {\n return {\n host, // The hostname or IP address of the database server.\n port, // The port number used by the database server.\n user: username, // The username for database authentication.\n password, // The password for database authentication.\n database, // The path or alias of the target database.\n lowercase_keys: false, // Determines if the keys in query results should be in lowercase. Default: false.\n role: undefined, // The role for the database connection. Default: undefined.\n pageSize: 100000, // The page size for database transactions. Default: 100,000.\n retryConnectionInterval: 1000, // The interval (in ms) to retry a failed connection. Default: 1,000 ms.\n blobAsText: true, // Determines if BLOB fields should be treated as text. Default: true.\n connectTimeout: 15000,\n connectTimeoutMs: 15000,\n trimStringResults: true,\n };\n }\n}\n\nconst deprecationLogger = new Logger('Deprecated');\n\nexport function Deprecated(message: string) {\n return function (target: object, key?: string, descriptor?: PropertyDescriptor) {\n void target;\n void key;\n void descriptor;\n deprecationLogger.warning(`[DEPRECATED] ${message}`);\n };\n }\n"]}
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|