@futdevpro/nts-dynamo 1.15.82 → 1.15.83
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/.dynamo/logs/cicd-pipeline/output.log +1753 -1829
- package/.dynamo/logs/cicd-pipeline/status.json +39 -39
- package/build/_modules/server/errors/errors.controller.d.ts +15 -0
- package/build/_modules/server/errors/errors.controller.d.ts.map +1 -1
- package/build/_modules/server/errors/errors.controller.js +39 -12
- package/build/_modules/server/errors/errors.controller.js.map +1 -1
- package/build/_modules/server/server-status/server-status.controller.d.ts +8 -0
- package/build/_modules/server/server-status/server-status.controller.d.ts.map +1 -1
- package/build/_modules/server/server-status/server-status.controller.js +25 -5
- package/build/_modules/server/server-status/server-status.controller.js.map +1 -1
- package/package.json +1 -1
- package/src/_modules/server/errors/errors.controller.spec.ts +48 -29
- package/src/_modules/server/errors/errors.controller.ts +38 -12
- package/src/_modules/server/server-status/server-status.controller.spec.ts +42 -35
- package/src/_modules/server/server-status/server-status.controller.ts +24 -5
|
@@ -145,6 +145,32 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
145
145
|
return protectedNames.includes(endpointName) ? [cfg.authPreProcess] : [];
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
/**
|
|
149
|
+
* FR-263 (2026-06-26) — LAZY, REQUEST-IDŐBEN kiértékelt guard-wrapper.
|
|
150
|
+
*
|
|
151
|
+
* GYÖKÉR-OK: a `setupEndpoints()` a controller ELSŐ konstrukciójakor fut, ami a built-in
|
|
152
|
+
* error-controllernél a host-app `configure()`-ja ELŐTT történhet (a framework korán példányosítja
|
|
153
|
+
* a singletont). Ilyenkor a `getPreProcessesFor()` még az ÜRES configot olvasta → a guard SOHA nem
|
|
154
|
+
* kötődött → az admin error-read endpoint-ok (`get-range`, `get-paged`, …) token nélkül **200**-at
|
|
155
|
+
* adtak vissza, kiszivárogtatva a belső error-logot (info-disclosure). A 39 másik (controller-szinten
|
|
156
|
+
* HARDCODE-olt) guard azért működött, mert nem függ a `configure()` időzítésétől.
|
|
157
|
+
*
|
|
158
|
+
* FIX: a `preProcesses` egy wrapper, ami a configot KÉRÉS-IDŐBEN olvassa (`getPreProcessesFor`), így
|
|
159
|
+
* a `configure()` SORREND-FÜGGETLEN — bármikor hívható az első kérés előtt. A 401-et a VALÓDI guard
|
|
160
|
+
* küldi; `res.headersSent`-re leállunk (nincs dupla-send), és nem-védett endpointnál no-op (átenged).
|
|
161
|
+
*/
|
|
162
|
+
protected lazyPreProcessesFor(endpointName: string): ((req: Request, res: Response) => Promise<void>)[] {
|
|
163
|
+
return [
|
|
164
|
+
async (req: Request, res: Response): Promise<void> => {
|
|
165
|
+
const guards: ((req: Request, res: Response) => Promise<void>)[] = this.getPreProcessesFor(endpointName);
|
|
166
|
+
for (const guard of guards) {
|
|
167
|
+
if (res.headersSent) { return; }
|
|
168
|
+
await guard(req, res);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
|
|
148
174
|
setupEndpoints(): void {
|
|
149
175
|
/* if (!this.getErrorDataService) {
|
|
150
176
|
throw new DyFM_Error({
|
|
@@ -165,7 +191,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
165
191
|
name: 'logError',
|
|
166
192
|
type: DyFM_HttpCallType.post,
|
|
167
193
|
endpoint: '/error/log',
|
|
168
|
-
preProcesses: this.
|
|
194
|
+
preProcesses: this.lazyPreProcessesFor('logError'),
|
|
169
195
|
tasks: [
|
|
170
196
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
171
197
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -184,7 +210,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
184
210
|
name: 'newError',
|
|
185
211
|
type: DyFM_HttpCallType.post,
|
|
186
212
|
endpoint: '/error/new',
|
|
187
|
-
preProcesses: this.
|
|
213
|
+
preProcesses: this.lazyPreProcessesFor('newError'),
|
|
188
214
|
tasks: [
|
|
189
215
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
190
216
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -204,7 +230,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
204
230
|
name: 'markErrorDone',
|
|
205
231
|
type: DyFM_HttpCallType.get,
|
|
206
232
|
endpoint: '/error/mark-done/:errorId',
|
|
207
|
-
preProcesses: this.
|
|
233
|
+
preProcesses: this.lazyPreProcessesFor('markErrorDone'),
|
|
208
234
|
tasks: [
|
|
209
235
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
210
236
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -224,7 +250,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
224
250
|
name: 'markAllErrorDone',
|
|
225
251
|
type: DyFM_HttpCallType.get,
|
|
226
252
|
endpoint: '/error/mark-all-done',
|
|
227
|
-
preProcesses: this.
|
|
253
|
+
preProcesses: this.lazyPreProcessesFor('markAllErrorDone'),
|
|
228
254
|
tasks: [
|
|
229
255
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
230
256
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -244,7 +270,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
244
270
|
name: 'recordFixAttempt',
|
|
245
271
|
type: DyFM_HttpCallType.post,
|
|
246
272
|
endpoint: '/error/:errorId/fix-attempt',
|
|
247
|
-
preProcesses: this.
|
|
273
|
+
preProcesses: this.lazyPreProcessesFor('recordFixAttempt'),
|
|
248
274
|
tasks: [
|
|
249
275
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
250
276
|
const errorId: string = req.params.errorId;
|
|
@@ -274,7 +300,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
274
300
|
name: 'resolveError',
|
|
275
301
|
type: DyFM_HttpCallType.post,
|
|
276
302
|
endpoint: '/error/:errorId/resolve',
|
|
277
|
-
preProcesses: this.
|
|
303
|
+
preProcesses: this.lazyPreProcessesFor('resolveError'),
|
|
278
304
|
tasks: [
|
|
279
305
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
280
306
|
const errorId: string = req.params.errorId;
|
|
@@ -321,7 +347,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
321
347
|
name: 'getErrors',
|
|
322
348
|
type: DyFM_HttpCallType.get,
|
|
323
349
|
endpoint: '/error/get-range/:range',
|
|
324
|
-
preProcesses: this.
|
|
350
|
+
preProcesses: this.lazyPreProcessesFor('getErrors'),
|
|
325
351
|
tasks: [
|
|
326
352
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
327
353
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -342,7 +368,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
342
368
|
name: 'getErrorsPaged',
|
|
343
369
|
type: DyFM_HttpCallType.get,
|
|
344
370
|
endpoint: '/error/get-paged/:range/:pageSize/:pageIndex',
|
|
345
|
-
preProcesses: this.
|
|
371
|
+
preProcesses: this.lazyPreProcessesFor('getErrorsPaged'),
|
|
346
372
|
tasks: [
|
|
347
373
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
348
374
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -374,7 +400,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
374
400
|
name: 'getErrorsByCategoryPaged',
|
|
375
401
|
type: DyFM_HttpCallType.get,
|
|
376
402
|
endpoint: '/error/get-by-category/:category/:range/:pageSize/:pageIndex',
|
|
377
|
-
preProcesses: this.
|
|
403
|
+
preProcesses: this.lazyPreProcessesFor('getErrorsByCategoryPaged'),
|
|
378
404
|
tasks: [
|
|
379
405
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
380
406
|
const error_CS: T_Error_ControlService = this.getError_ControlService({ issuer });
|
|
@@ -403,7 +429,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
403
429
|
name: 'getErrorsByStatusPaged',
|
|
404
430
|
type: DyFM_HttpCallType.get,
|
|
405
431
|
endpoint: '/error/get-by-status/:status/:range/:pageSize/:pageIndex',
|
|
406
|
-
preProcesses: this.
|
|
432
|
+
preProcesses: this.lazyPreProcessesFor('getErrorsByStatusPaged'),
|
|
407
433
|
tasks: [
|
|
408
434
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
409
435
|
const error_CS: T_Error_ControlService = this.getError_ControlService({ issuer });
|
|
@@ -432,7 +458,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
432
458
|
name: 'getLastErrors',
|
|
433
459
|
type: DyFM_HttpCallType.get,
|
|
434
460
|
endpoint: '/error/get-last-paged/:range/:pageSize/:pageIndex',
|
|
435
|
-
preProcesses: this.
|
|
461
|
+
preProcesses: this.lazyPreProcessesFor('getLastErrors'),
|
|
436
462
|
tasks: [
|
|
437
463
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
438
464
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -464,7 +490,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
464
490
|
name: 'searchErrors',
|
|
465
491
|
type: DyFM_HttpCallType.get,
|
|
466
492
|
endpoint: '/error/search',
|
|
467
|
-
preProcesses: this.
|
|
493
|
+
preProcesses: this.lazyPreProcessesFor('searchErrors'),
|
|
468
494
|
tasks: [
|
|
469
495
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
470
496
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -172,62 +172,69 @@ describe('| DyNTS_ServerStatus_Controller', () => {
|
|
|
172
172
|
DyNTS_ServerStatus_Controller._resetAuthConfigForTesting();
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
// FR-263 — a guard request-idoben fut (lazy wrapper). "Gated-e egy endpoint" = a wrapper
|
|
176
|
+
// meghivasa lefuttatja-e a configured authPreProcess-t. A counter-t a teszt-spy lepteti.
|
|
177
|
+
let guardCalls: number = 0;
|
|
178
|
+
const spyAuth = async (): Promise<void> => { guardCalls++; };
|
|
179
|
+
const runGuard = async (c: any, name: string): Promise<void> => {
|
|
180
|
+
const ep: any = c.endpoints.find((e: any) => e.name === name);
|
|
181
|
+
await ep?.preProcesses?.[0]?.({} as any, { headersSent: false } as any);
|
|
178
182
|
};
|
|
183
|
+
beforeEach((): void => { guardCalls = 0; });
|
|
179
184
|
|
|
180
|
-
it('| default:
|
|
185
|
+
it('| default (no config): a wrapper jelen van, de egy keres NEM hiv guardot (nyitva marad)', async (): Promise<void> => {
|
|
181
186
|
controller.setupEndpoints();
|
|
182
187
|
for (const ep of controller.endpoints) {
|
|
183
|
-
|
|
184
|
-
expect(pre === undefined || pre.length === 0).toBe(true);
|
|
188
|
+
await (ep as any).preProcesses?.[0]?.({} as any, { headersSent: false } as any); // no-op, nem dob
|
|
185
189
|
}
|
|
190
|
+
expect(guardCalls).toBe(0);
|
|
186
191
|
});
|
|
187
192
|
|
|
188
|
-
it('| configure({ authPreProcess }) →
|
|
189
|
-
|
|
190
|
-
DyNTS_ServerStatus_Controller.configure({ authPreProcess: fakeAuth });
|
|
193
|
+
it('| configure({ authPreProcess }) → CSAK getErrorStatistics-en fut a guard, a status-vegpontokon NEM', async (): Promise<void> => {
|
|
194
|
+
DyNTS_ServerStatus_Controller.configure({ authPreProcess: spyAuth });
|
|
191
195
|
const c: any = new (TestServerStatusController as any)();
|
|
192
196
|
c.setupEndpoints();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
expect(
|
|
200
|
-
expect(preCount(c, 'getServerStatusForClient')).toBe(0);
|
|
197
|
+
await runGuard(c, 'getErrorStatistics');
|
|
198
|
+
expect(guardCalls).withContext('admin-adat → gated').toBe(1);
|
|
199
|
+
guardCalls = 0;
|
|
200
|
+
for (const name of ['getServerStatus', 'getServerHealth', 'getServerReadiness', 'getServerStatusForClient']) {
|
|
201
|
+
await runGuard(c, name);
|
|
202
|
+
}
|
|
203
|
+
expect(guardCalls).withContext('status-probak SOHA nem gated').toBe(0);
|
|
201
204
|
});
|
|
202
205
|
|
|
203
|
-
it('| a status-vegpontokat
|
|
204
|
-
const fakeAuth = async (): Promise<void> => { /* noop */ };
|
|
206
|
+
it('| a status-vegpontokat explicit protectedEndpoints-lista SEM gate-eli (PUBLIC_PROBE kizart)', async (): Promise<void> => {
|
|
205
207
|
DyNTS_ServerStatus_Controller.configure({
|
|
206
|
-
authPreProcess:
|
|
208
|
+
authPreProcess: spyAuth,
|
|
207
209
|
protectedEndpoints: [ 'getServerHealth', 'getServerReadiness', 'getServerStatusForClient', 'getServerStatus', 'getErrorStatistics' ],
|
|
208
210
|
});
|
|
209
211
|
const c: any = new (TestServerStatusController as any)();
|
|
210
212
|
c.setupEndpoints();
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
expect(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
expect(preCount(c, 'getErrorStatistics')).toBe(1);
|
|
213
|
+
for (const name of ['getServerStatus', 'getServerHealth', 'getServerReadiness', 'getServerStatusForClient']) {
|
|
214
|
+
await runGuard(c, name);
|
|
215
|
+
}
|
|
216
|
+
expect(guardCalls).withContext('status-probak kizartak meg explicit listan is').toBe(0);
|
|
217
|
+
await runGuard(c, 'getErrorStatistics');
|
|
218
|
+
expect(guardCalls).withContext('getErrorStatistics gated').toBe(1);
|
|
218
219
|
});
|
|
219
220
|
|
|
220
|
-
it('| protectedEndpoints subset →
|
|
221
|
-
|
|
222
|
-
DyNTS_ServerStatus_Controller.configure({
|
|
223
|
-
authPreProcess: fakeAuth,
|
|
224
|
-
protectedEndpoints: [ 'getErrorStatistics' ],
|
|
225
|
-
});
|
|
221
|
+
it('| protectedEndpoints subset → getErrorStatistics gated, getServerStatus NEM', async (): Promise<void> => {
|
|
222
|
+
DyNTS_ServerStatus_Controller.configure({ authPreProcess: spyAuth, protectedEndpoints: [ 'getErrorStatistics' ] });
|
|
226
223
|
const c: any = new (TestServerStatusController as any)();
|
|
227
224
|
c.setupEndpoints();
|
|
225
|
+
await runGuard(c, 'getErrorStatistics');
|
|
226
|
+
expect(guardCalls).toBe(1);
|
|
227
|
+
guardCalls = 0;
|
|
228
|
+
await runGuard(c, 'getServerStatus');
|
|
229
|
+
expect(guardCalls).toBe(0);
|
|
230
|
+
});
|
|
228
231
|
|
|
229
|
-
|
|
230
|
-
|
|
232
|
+
it('| FR-263 ORDER-INDEPENDENCE: setupEndpoints() ELOTT epitett endpoint is enforce-olja a guardot', async (): Promise<void> => {
|
|
233
|
+
const c: any = new (TestServerStatusController as any)();
|
|
234
|
+
c.setupEndpoints(); // config NELKUL (korai framework-konstrukcio szimulacioja)
|
|
235
|
+
DyNTS_ServerStatus_Controller.configure({ authPreProcess: spyAuth }); // configure UTANA
|
|
236
|
+
await runGuard(c, 'getErrorStatistics');
|
|
237
|
+
expect(guardCalls).withContext('guard runs despite configure() AFTER setupEndpoints').toBe(1);
|
|
231
238
|
});
|
|
232
239
|
|
|
233
240
|
it('| getAuthConfig() returns the active config', (): void => {
|
|
@@ -151,6 +151,25 @@ export abstract class DyNTS_ServerStatus_Controller<
|
|
|
151
151
|
return protectedNames.includes(endpointName) ? [cfg.authPreProcess] : [];
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* FR-263 (2026-06-26) — LAZY, REQUEST-IDŐBEN kiértékelt guard-wrapper (lásd a DyNTS_Errors_Controller
|
|
156
|
+
* azonos fixét). A `setupEndpoints()` a host-app `configure()`-ja ELŐTT futhat (korai singleton-
|
|
157
|
+
* konstrukció) → a guard ürès configgal kötődött → a `getServerStatus`/`getErrorStatistics` admin-adat
|
|
158
|
+
* token nélkül 200-at adott (info-disclosure). A wrapper a configot KÉRÉS-IDŐBEN olvassa → sorrend-
|
|
159
|
+
* független. A 401-et a valódi guard küldi; `headersSent`-re leállunk; nem-védett endpointnál no-op.
|
|
160
|
+
*/
|
|
161
|
+
protected lazyPreProcessesFor(endpointName: string): ((req: Request, res: Response) => Promise<void>)[] {
|
|
162
|
+
return [
|
|
163
|
+
async (req: Request, res: Response): Promise<void> => {
|
|
164
|
+
const guards: ((req: Request, res: Response) => Promise<void>)[] = this.getPreProcessesFor(endpointName);
|
|
165
|
+
for (const guard of guards) {
|
|
166
|
+
if (res.headersSent) { return; }
|
|
167
|
+
await guard(req, res);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
|
|
154
173
|
setupEndpoints(): void {
|
|
155
174
|
/* if (!this.getServerService) {
|
|
156
175
|
throw new DyFM_Error({
|
|
@@ -173,7 +192,7 @@ export abstract class DyNTS_ServerStatus_Controller<
|
|
|
173
192
|
name: 'getServerStatus',
|
|
174
193
|
type: DyFM_HttpCallType.get,
|
|
175
194
|
endpoint: '/status',
|
|
176
|
-
preProcesses: this.
|
|
195
|
+
preProcesses: this.lazyPreProcessesFor('getServerStatus'),
|
|
177
196
|
tasks: [
|
|
178
197
|
async (req: Request, res: Response, issuer: string): Promise<void> => {
|
|
179
198
|
res.send(
|
|
@@ -187,7 +206,7 @@ export abstract class DyNTS_ServerStatus_Controller<
|
|
|
187
206
|
name: 'getServerHealth',
|
|
188
207
|
type: DyFM_HttpCallType.get,
|
|
189
208
|
endpoint: '/health',
|
|
190
|
-
preProcesses: this.
|
|
209
|
+
preProcesses: this.lazyPreProcessesFor('getServerHealth'),
|
|
191
210
|
tasks: [
|
|
192
211
|
async (req: Request, res: Response, issuer: string): Promise<void> => {
|
|
193
212
|
res.send(
|
|
@@ -203,7 +222,7 @@ export abstract class DyNTS_ServerStatus_Controller<
|
|
|
203
222
|
name: 'getServerReadiness',
|
|
204
223
|
type: DyFM_HttpCallType.get,
|
|
205
224
|
endpoint: '/readiness',
|
|
206
|
-
preProcesses: this.
|
|
225
|
+
preProcesses: this.lazyPreProcessesFor('getServerReadiness'),
|
|
207
226
|
tasks: [
|
|
208
227
|
async (req: Request, res: Response, issuer: string): Promise<void> => {
|
|
209
228
|
const readiness: DyNTS_DbReadiness = await this.server_CS.checkDbReadiness();
|
|
@@ -217,7 +236,7 @@ export abstract class DyNTS_ServerStatus_Controller<
|
|
|
217
236
|
name: 'getServerStatusForClient',
|
|
218
237
|
type: DyFM_HttpCallType.get,
|
|
219
238
|
endpoint: '/status/:version',
|
|
220
|
-
preProcesses: this.
|
|
239
|
+
preProcesses: this.lazyPreProcessesFor('getServerStatusForClient'),
|
|
221
240
|
tasks: [
|
|
222
241
|
async (req: Request, res: Response, issuer: string): Promise<void> => {
|
|
223
242
|
|
|
@@ -232,7 +251,7 @@ export abstract class DyNTS_ServerStatus_Controller<
|
|
|
232
251
|
name: 'getErrorStatistics',
|
|
233
252
|
type: DyFM_HttpCallType.get,
|
|
234
253
|
endpoint: '/statistics/error/:range',
|
|
235
|
-
preProcesses: this.
|
|
254
|
+
preProcesses: this.lazyPreProcessesFor('getErrorStatistics'),
|
|
236
255
|
tasks: [
|
|
237
256
|
async (req: Request, res: Response, issuer: string) : Promise<void> => {
|
|
238
257
|
|