@futdevpro/nts-dynamo 1.15.21 → 1.15.23
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/__documentations/2026-05-17-static-client-serving-howto.md +144 -0
- package/_specifications/BACKLOG.md +4 -4
- package/build/_modules/server/errors/errors.controller.d.ts +64 -0
- package/build/_modules/server/errors/errors.controller.d.ts.map +1 -1
- package/build/_modules/server/errors/errors.controller.js +66 -0
- package/build/_modules/server/errors/errors.controller.js.map +1 -1
- package/package.json +1 -1
- package/src/_modules/server/errors/errors.controller.spec.ts +70 -0
- package/src/_modules/server/errors/errors.controller.ts +102 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Static client serving — how-to
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-05-17
|
|
4
|
+
**Backlog:** [BL-20260417-001](../_specifications/BACKLOG.md) — DyNTS-kliens kiszolgálás képesség
|
|
5
|
+
**Status:** ✅ done (audit + docs)
|
|
6
|
+
|
|
7
|
+
## TL;DR
|
|
8
|
+
|
|
9
|
+
A `DyNTS_App_Server` MÁR most ki tudja szolgálni a klienst (SPA-kat, statikus
|
|
10
|
+
oldalakat) az API route-ok mellett ugyanazon a hoszton. Az implementáció
|
|
11
|
+
2026-03-30 óta (commit `8ffe535`) része a frameworknek; a BL-20260417-001
|
|
12
|
+
backlog entry post-dated a fejlesztést. Ez a how-to a meglévő capability-t
|
|
13
|
+
dokumentálja.
|
|
14
|
+
|
|
15
|
+
## Konfigurációs felület
|
|
16
|
+
|
|
17
|
+
A static client serving akkor aktiválódik, ha a `DyNTS_App_Server`
|
|
18
|
+
subclass-od `getStaticClientSettings()`-et override-olja és egy
|
|
19
|
+
[`DyNTS_StaticClient_Settings`](../src/_models/interfaces/static-client-settings.interface.ts)
|
|
20
|
+
objektumot ad vissza:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { DyNTS_StaticClient_Settings } from '@futdevpro/nts-dynamo';
|
|
24
|
+
|
|
25
|
+
export interface DyNTS_StaticClient_Settings {
|
|
26
|
+
root: string; // a static fájlok mappája (abszolút v. cwd-relatív)
|
|
27
|
+
fallbackPath?: string; // SPA fallback (pl. 'index.html')
|
|
28
|
+
assetCacheMaxAge?: number; // asset Cache-Control max-age (sec)
|
|
29
|
+
assetCacheImmutable?: boolean; // 'immutable' direktíva (Angular hashed fájlokra)
|
|
30
|
+
fallbackCacheMaxAge?: number; // fallback file Cache-Control max-age (sec)
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Példa subclass (Angular SPA)
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import path from 'path';
|
|
38
|
+
import { DyNTS_App_Server, DyNTS_StaticClient_Settings } from '@futdevpro/nts-dynamo';
|
|
39
|
+
|
|
40
|
+
export class MyApp_Server extends DyNTS_App_Server {
|
|
41
|
+
// ... egyéb override-ok (getAppParams, getPortSettings, getApiBasePath, stb.) ...
|
|
42
|
+
|
|
43
|
+
override getStaticClientSettings(): DyNTS_StaticClient_Settings | undefined {
|
|
44
|
+
return {
|
|
45
|
+
// Az Angular `dist/<app-name>` mappa abszolút path-ja
|
|
46
|
+
root: path.resolve(__dirname, '../../client/dist/my-app'),
|
|
47
|
+
|
|
48
|
+
// SPA — minden ismeretlen route a kliens-routerre megy
|
|
49
|
+
fallbackPath: 'index.html',
|
|
50
|
+
|
|
51
|
+
// Hashed assetek (Angular alapból ad nekik hash-et) — 1 év, immutable
|
|
52
|
+
assetCacheMaxAge: 31_536_000,
|
|
53
|
+
assetCacheImmutable: true,
|
|
54
|
+
|
|
55
|
+
// index.html-t SOHA ne cache-elje a böngésző (deploy után friss kell)
|
|
56
|
+
fallbackCacheMaxAge: 0,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Mit csinál a framework a háttérben
|
|
63
|
+
|
|
64
|
+
A `DyNTS_App_Server.mountStaticClient()` ([app.server.ts ~1421-1484](../src/_services/server/app.server.ts))
|
|
65
|
+
ezt automatikusan beállítja az API route-ok regisztrációja UTÁN:
|
|
66
|
+
|
|
67
|
+
1. **`Express.static(root)` middleware** mount a `/` alatt. Ha `assetCacheMaxAge`
|
|
68
|
+
meg van adva, `setHeaders` callback-en keresztül beállítja a `Cache-Control:
|
|
69
|
+
max-age=<N>[, immutable]` header-t.
|
|
70
|
+
2. **SPA fallback** (ha `fallbackPath` adott): minden ismeretlen GET kérésre
|
|
71
|
+
`res.sendFile(fallbackPath)` + `Cache-Control: max-age=<fallbackCacheMaxAge>`.
|
|
72
|
+
3. **Default 404** (ha `fallbackPath` hiányzik): a beépített
|
|
73
|
+
[`DyNTS_defaultNotFoundPageHtml`](../src/_collections/default-not-found-page.const.ts)
|
|
74
|
+
kerül kiszolgálásra `status: 404` + `Content-Type: text/html`.
|
|
75
|
+
4. **HTTP + HTTPS** mindkettő: a flow azonos a `this.openExpress` és
|
|
76
|
+
`this.secureExpress` instance-ekhez (ha mindkettő be van állítva).
|
|
77
|
+
|
|
78
|
+
## Config matrix — mikor melyik mezőt használd
|
|
79
|
+
|
|
80
|
+
| Use case | `root` | `fallbackPath` | `assetCacheMaxAge` | `assetCacheImmutable` | `fallbackCacheMaxAge` |
|
|
81
|
+
|---|---|---|---|---|---|
|
|
82
|
+
| **SPA** (Angular, React) hashed assetekkel | ✅ kötelező | `'index.html'` | `31_536_000` (1 év) | `true` | `0` (mindig friss) |
|
|
83
|
+
| **SPA** dev mode (rebuild gyakori) | ✅ | `'index.html'` | `0` | `false` | `0` |
|
|
84
|
+
| **Statikus oldal** (nincs SPA-router) | ✅ | hagyd ki | `3600` (1 óra) vagy ahogy jó | `false` | n/a |
|
|
85
|
+
| **Csak API** (nincs frontend) | NE override-old a `getStaticClientSettings()`-et — akkor `undefined`-ot ad vissza és a `mountStaticClient` early-return-öl | | | | |
|
|
86
|
+
|
|
87
|
+
## Asset + fallback cache stratégia (SPA)
|
|
88
|
+
|
|
89
|
+
A két mező együttes használata az **alapja az Angular/React deploy-friendly caching**-nek:
|
|
90
|
+
|
|
91
|
+
- **Hashed assetek** (`main.<hash>.js`, `styles.<hash>.css`, stb.) ÉLETBEN nem
|
|
92
|
+
változnak — biztonságosan `immutable` + 1 év max-age. A böngésző sose kérdezi
|
|
93
|
+
meg újra a szerverről, amíg a HTML egy új hash-elt nevet nem hivatkozik be.
|
|
94
|
+
- **`index.html`** a "katalógus" ami a hashed assetekre mutat. Deploy után
|
|
95
|
+
AZONNAL friss kell legyen, különben a kliens régi assetekre hivatkozó régi
|
|
96
|
+
index.html-t kap → 404-ek a már nem létező hashed nevekre.
|
|
97
|
+
→ `fallbackCacheMaxAge: 0` (no-cache).
|
|
98
|
+
|
|
99
|
+
Az `assetCacheMaxAge` undefined-ja default (Express.static alapértelmezett) cache
|
|
100
|
+
viselkedést hagy meg — production deploy-okra mindig explicit állítsd be.
|
|
101
|
+
|
|
102
|
+
## Integration test minta
|
|
103
|
+
|
|
104
|
+
A meglévő integration test fixture ([`DyNTS_AppIntegrationTest_Mock`](../src/_modules/mock/app-integration-test.mock.ts)) +
|
|
105
|
+
spec ([app-extended.integration.spec.ts](../src/_modules/socket/app-extended.integration.spec.ts))
|
|
106
|
+
mutatja a teljes flow-t:
|
|
107
|
+
|
|
108
|
+
- A spec `beforeAll`-ban létrehoz egy temp dir-t, kitölti pár static fájllal,
|
|
109
|
+
beállítja a mock `integrationStaticRoot` static property-jét, majd elindítja
|
|
110
|
+
az appot.
|
|
111
|
+
- A spec asszertálja:
|
|
112
|
+
- `started === true` (az app HTTP listenert kapott)
|
|
113
|
+
- GET nemlétező path → `404` + a default not-found HTML kiszolgálva
|
|
114
|
+
- GET `/index.html` → `200` + a temp dir-ben található static content
|
|
115
|
+
- GET `/api/test-0/test-base`, `/api/test-0/test-simple` → API kiszolgálva (az API
|
|
116
|
+
route-ok ELŐBB regisztráltak, mint a static fallback)
|
|
117
|
+
- `afterAll`-ban leállítja az appot és kitakarítja a temp dir-t.
|
|
118
|
+
|
|
119
|
+
## Edge case-ek + gotchák
|
|
120
|
+
|
|
121
|
+
- **Mounting sorrend:** a `mountStaticClient` az `_routingModules` regisztráció
|
|
122
|
+
UTÁN fut, így az API route-ok prioritást élveznek. Tehát a `/api/...` mindig
|
|
123
|
+
az API-hoz megy, akkor is, ha a static root-ban véletlenül lenne `api/`
|
|
124
|
+
almappa.
|
|
125
|
+
- **`fallbackPath` relatív** a `root`-hoz képest (`sendFile(fallbackPath, { root })`).
|
|
126
|
+
- **Default 404 HTML:** szándékosan minimalista (`DyNTS_defaultNotFoundPageHtml`),
|
|
127
|
+
hogy ne ütközzön a kliens stílusával. Ha custom 404-et akarsz, add meg a
|
|
128
|
+
`fallbackPath`-t (az SPA-router majd kezelje belül a "page not found"-ot).
|
|
129
|
+
- **CSP / security header-ek:** a `mountStaticClient` NEM állít be CSP-t —
|
|
130
|
+
ha kell, használj `helmet` middleware-t az API route-ok elé.
|
|
131
|
+
|
|
132
|
+
## Releváns kód- és test-fájlok
|
|
133
|
+
|
|
134
|
+
- [`src/_services/server/app.server.ts`](../src/_services/server/app.server.ts) — `mountStaticClient()` private + `getStaticClientSettings?()` opt-in override
|
|
135
|
+
- [`src/_models/interfaces/static-client-settings.interface.ts`](../src/_models/interfaces/static-client-settings.interface.ts) — config interface
|
|
136
|
+
- [`src/_collections/default-fallback-cache-max-age.const.ts`](../src/_collections/default-fallback-cache-max-age.const.ts) — default `0` (no-cache)
|
|
137
|
+
- [`src/_collections/default-not-found-page.const.ts`](../src/_collections/default-not-found-page.const.ts) — default 404 HTML
|
|
138
|
+
- [`src/_modules/mock/app-integration-test.mock.ts`](../src/_modules/mock/app-integration-test.mock.ts) — integration test fixture mintaként
|
|
139
|
+
- [`__documentations/nts-integration-tests-2026-03-17.md`](./nts-integration-tests-2026-03-17.md) — első integration test bevezetése a unified host behavior-ra
|
|
140
|
+
|
|
141
|
+
## Kapcsolódó backlog entry-k
|
|
142
|
+
|
|
143
|
+
- **BL-20260420-001..004** (dynamo-nts) — `DyNTS_FileLog_Service` + admin endpoints. Mind ✅ done.
|
|
144
|
+
- BL-20260417-001 (ez) — a kliens kiszolgálási képesség. ✅ done — implementáció már része a frameworknek; ez a doc a hivatkozás.
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
> - IDs: unique, format BL-YYYYMMDD-### (increment ###).
|
|
16
16
|
|
|
17
17
|
- [FEATURE] (BL-20260417-001) Dynamo NTS kliens kiszolgálás képesség
|
|
18
|
-
status:
|
|
18
|
+
status: ✅ done
|
|
19
19
|
priority: medium
|
|
20
20
|
source: user
|
|
21
21
|
area: backend
|
|
22
|
-
details: Alkalmassá kell tenni a Dynamo NTS-t, hogy kiszolgálja a klienst (frontend/client-side serving)
|
|
22
|
+
details: Alkalmassá kell tenni a Dynamo NTS-t, hogy kiszolgálja a klienst (frontend/client-side serving). Audit eredménye (2026-05-17): a capability MÁR implementálva van 2026-03-30 óta (commit 8ffe535) — DyNTS_App_Server.mountStaticClient() + getStaticClientSettings?() opt-in override + DyNTS_StaticClient_Settings interface (root, fallbackPath, assetCacheMaxAge, assetCacheImmutable, fallbackCacheMaxAge). Featureset: Express.static mount /-en az API route-ok után, SPA fallback sendFile-lal, asset+fallback Cache-Control (Angular hashed fájl optimalizálásra), default 404 HTML ha nincs fallbackPath, mindkét http/https express-en mount. Integration test megvan (app-extended.integration.spec.ts + app-integration-test.mock.ts). How-to doc: __documentations/2026-05-17-static-client-serving-howto.md (config matrix + example subclass + cache stratégia + edge case-ek).
|
|
23
23
|
|
|
24
24
|
- [FEATURE] (BL-20260420-001) Átfogó file-based log kezelési rendszer
|
|
25
25
|
status: ✅ done
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
details: A BL-20260420-001 file-based log rendszerre épülve egy új endpoint, amin keresztül le lehet kérni a szerverről a kiírt log file-ok tartalmát (pl. paged / range / tail módon). Implementálva (2026-05-17): DyNTS_FileLogs_Controller (GET /list + GET /file/:filename) + DyNTS_getFileLogsRoutingModule() factory + DyNTS_FileLog_Service bővítés (listLogFiles, readLogFile, getCurrentLogFilename). Olvasási módok: tail / head / range (max 10000 sor). Safeguards: filename whitelist regex prefix-szel, path traversal védelem (resolvedPath + sep ellenőrzés), 503/404/400 helyes status code-ok. Auth opt-in: `DyNTS_getFileLogsRoutingModule({ authPreProcess: adminAuth.verify })`. Default route /file-logs. 38/38 FileLog spec (24 service + 14 controller) + 1175/0 full suite + smoke 4/4 verifikálva.
|
|
44
44
|
|
|
45
45
|
- [IMPROVEMENT] (BL-20260420-004) Errors endpointok opcionális admin API key védelme
|
|
46
|
-
status:
|
|
46
|
+
status: ✅ done
|
|
47
47
|
priority: medium
|
|
48
48
|
source: user
|
|
49
49
|
area: backend
|
|
50
|
-
details: A BL-20260420-002 admin API key auth réteget opcionálisan rá kell tudni húzni a meglévő DyNTS_Errors_Controller endpointjaira (errors.controller.ts) is, hogy érzékeny error-listázó / kezelő endpointok admin auth mögé kerülhessenek.
|
|
50
|
+
details: A BL-20260420-002 admin API key auth réteget opcionálisan rá kell tudni húzni a meglévő DyNTS_Errors_Controller endpointjaira (errors.controller.ts) is, hogy érzékeny error-listázó / kezelő endpointok admin auth mögé kerülhessenek. Implementálva (2026-05-17): static `DyNTS_Errors_Controller.configure({ authPreProcess?, protectedEndpoints? })` — opt-in, default = no auth (backwards compatible). `authPreProcess` jelenléte esetén default mind a 8 endpoint védett, vagy `protectedEndpoints` subset-tel fine-grained kontroll. `getAuthConfig()` + `_resetAuthConfigForTesting()` segéd-fnk-ek. Per-endpoint `preProcesses: this.getPreProcessesFor(name)` thread-elve mind a 8 endpoint-konstrukcióba. 16/16 errors controller spec (11 régi backwards-compat + 5 új retrofit) + 1180/0 full suite + smoke 3/3 (default, full, subset).
|
|
@@ -1,7 +1,36 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
1
2
|
import { DyFM_Error, DyFM_Errors } from '@futdevpro/fsm-dynamo';
|
|
2
3
|
import { DyNTS_Controller } from '../../../_services/route/controller.service';
|
|
3
4
|
import { DyNTS_Endpoint_Params } from '../../../_models/control-models/endpoint-params.control-model';
|
|
4
5
|
import { DyNTS_Errors_ControlService } from './errors.control-service';
|
|
6
|
+
/**
|
|
7
|
+
* Auth retrofit config a `DyNTS_Errors_Controller`-hez. Opt-in — ha az
|
|
8
|
+
* `authPreProcess` nincs megadva, a controller a regi (auth nelkuli)
|
|
9
|
+
* viselkedest tartja.
|
|
10
|
+
*
|
|
11
|
+
* **Subclass-szintu konfiguracio:** az `authConfig` static, igy az abstract
|
|
12
|
+
* osztaly minden subclass-a kozott OSZTOTT. Ha tobb subclass-od van kulonbozo
|
|
13
|
+
* policy-val, hivd a `configure()`-t a megfelelo subclasson — TypeScript a
|
|
14
|
+
* static field-eket per-class hatarozza meg.
|
|
15
|
+
*/
|
|
16
|
+
export interface DyNTS_ErrorsController_AuthConfig {
|
|
17
|
+
/**
|
|
18
|
+
* Pre-process fuggveny ami minden vedett endpoint elott fut. Tipikusan:
|
|
19
|
+
* `DyNTS_AdminApiKey_AuthService.getInstance().verify`.
|
|
20
|
+
*
|
|
21
|
+
* Ha hianyzik vagy `undefined`, a controller NEM ad hozza auth-ot semelyik
|
|
22
|
+
* endpoint-hoz (regi viselkedes, opt-in safety).
|
|
23
|
+
*/
|
|
24
|
+
authPreProcess?: (req: Request, res: Response) => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Vedett endpoint nevek listaja. Ha hianyzik, az osszes 8 endpoint vedett
|
|
27
|
+
* (`authPreProcess` jelenleteben).
|
|
28
|
+
*
|
|
29
|
+
* Endpoint nevek: 'logError', 'newError', 'markErrorDone', 'markAllErrorDone',
|
|
30
|
+
* 'getErrors', 'getErrorsPaged', 'getLastErrors', 'searchErrors'.
|
|
31
|
+
*/
|
|
32
|
+
protectedEndpoints?: string[];
|
|
33
|
+
}
|
|
5
34
|
/**
|
|
6
35
|
* Endpoints:
|
|
7
36
|
*
|
|
@@ -31,6 +60,41 @@ export declare abstract class DyNTS_Errors_Controller<T_Error extends DyFM_Error
|
|
|
31
60
|
issuer: string;
|
|
32
61
|
}): T_Error_ControlService;
|
|
33
62
|
protected readonly additionalEndpoints: DyNTS_Endpoint_Params[];
|
|
63
|
+
/**
|
|
64
|
+
* Static auth config — opt-in retrofit. Default ures objektum → NO auth
|
|
65
|
+
* (a meglevo integraciok valtoznatlan viselkedessel folytatodnak).
|
|
66
|
+
*/
|
|
67
|
+
protected static authConfig: DyNTS_ErrorsController_AuthConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Static config setter. Hivhato barmikor a szerver startup-jan az endpoint
|
|
70
|
+
* registration ELOTT.
|
|
71
|
+
*
|
|
72
|
+
* Use case (host app):
|
|
73
|
+
* ```ts
|
|
74
|
+
* const adminAuth = DyNTS_AdminApiKey_AuthService.getInstance();
|
|
75
|
+
* DyNTS_Errors_Controller.configure({ authPreProcess: adminAuth.verify });
|
|
76
|
+
* // vagy fine-grained:
|
|
77
|
+
* DyNTS_Errors_Controller.configure({
|
|
78
|
+
* authPreProcess: adminAuth.verify,
|
|
79
|
+
* protectedEndpoints: ['markAllErrorDone', 'logError'],
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
static configure(config: DyNTS_ErrorsController_AuthConfig): void;
|
|
84
|
+
/**
|
|
85
|
+
* Aktualis auth config olvasasa (test/diagnosztika celokra).
|
|
86
|
+
*/
|
|
87
|
+
static getAuthConfig(): DyNTS_ErrorsController_AuthConfig;
|
|
88
|
+
/**
|
|
89
|
+
* Test-only: visszaallitja az auth config-ot ures objektumra. Production code NE hivja.
|
|
90
|
+
*/
|
|
91
|
+
static _resetAuthConfigForTesting(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Vissza-adja az adott endpoint-hoz tartozo `preProcesses` array-t.
|
|
94
|
+
* Ha az auth NINCS configurolva (default) vagy az endpoint nincs a
|
|
95
|
+
* `protectedEndpoints` listan, ures array-t ad vissza.
|
|
96
|
+
*/
|
|
97
|
+
protected getPreProcessesFor(endpointName: string): ((req: Request, res: Response) => Promise<void>)[];
|
|
34
98
|
setupEndpoints(): void;
|
|
35
99
|
}
|
|
36
100
|
//# sourceMappingURL=errors.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.controller.d.ts","sourceRoot":"","sources":["../../../../src/_modules/server/errors/errors.controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.controller.d.ts","sourceRoot":"","sources":["../../../../src/_modules/server/errors/errors.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAc,UAAU,EAAqB,WAAW,EAAqB,MAAM,uBAAuB,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+DAA+D,CAAC;AACtG,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAIvE;;;;;;;;;GASG;AACH,MAAM,WAAW,iCAAiC;IAChD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAcD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,8BAAsB,uBAAuB,CAC3C,OAAO,SAAS,UAAU,EAC1B,QAAQ,SAAS,WAAW,CAAC,OAAO,CAAC,EACrC,sBAAsB,SAAS,2BAA2B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAC7E,SAAQ,gBAAgB;IAOxB,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CACxC,GAAG,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACtC,sBAAsB;IACzB,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,CAAM;IAErE;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,iCAAiC,CAAM;IAEpE;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,iCAAiC,GAAG,IAAI;IAIjE;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,iCAAiC;IAIzD;;OAEG;IACH,MAAM,CAAC,0BAA0B,IAAI,IAAI;IAIzC;;;;OAIG;IACH,SAAS,CAAC,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE;IAOtG,cAAc,IAAI,IAAI;CA6NvB"}
|
|
@@ -5,6 +5,16 @@ const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
|
|
|
5
5
|
const controller_service_1 = require("../../../_services/route/controller.service");
|
|
6
6
|
const endpoint_params_control_model_1 = require("../../../_models/control-models/endpoint-params.control-model");
|
|
7
7
|
const global_settings_const_1 = require("../../../_collections/global-settings.const");
|
|
8
|
+
/**
|
|
9
|
+
* Az osszes built-in endpoint neve — a `configure({ protectedEndpoints })`
|
|
10
|
+
* default-jat es a config validacio-t segiti.
|
|
11
|
+
*/
|
|
12
|
+
const ALL_ENDPOINT_NAMES = [
|
|
13
|
+
'logError', 'newError',
|
|
14
|
+
'markErrorDone', 'markAllErrorDone',
|
|
15
|
+
'getErrors', 'getErrorsPaged', 'getLastErrors',
|
|
16
|
+
'searchErrors',
|
|
17
|
+
];
|
|
8
18
|
/**
|
|
9
19
|
* Endpoints:
|
|
10
20
|
*
|
|
@@ -33,6 +43,54 @@ const global_settings_const_1 = require("../../../_collections/global-settings.c
|
|
|
33
43
|
//
|
|
34
44
|
class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
35
45
|
additionalEndpoints = [];
|
|
46
|
+
/**
|
|
47
|
+
* Static auth config — opt-in retrofit. Default ures objektum → NO auth
|
|
48
|
+
* (a meglevo integraciok valtoznatlan viselkedessel folytatodnak).
|
|
49
|
+
*/
|
|
50
|
+
static authConfig = {};
|
|
51
|
+
/**
|
|
52
|
+
* Static config setter. Hivhato barmikor a szerver startup-jan az endpoint
|
|
53
|
+
* registration ELOTT.
|
|
54
|
+
*
|
|
55
|
+
* Use case (host app):
|
|
56
|
+
* ```ts
|
|
57
|
+
* const adminAuth = DyNTS_AdminApiKey_AuthService.getInstance();
|
|
58
|
+
* DyNTS_Errors_Controller.configure({ authPreProcess: adminAuth.verify });
|
|
59
|
+
* // vagy fine-grained:
|
|
60
|
+
* DyNTS_Errors_Controller.configure({
|
|
61
|
+
* authPreProcess: adminAuth.verify,
|
|
62
|
+
* protectedEndpoints: ['markAllErrorDone', 'logError'],
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
static configure(config) {
|
|
67
|
+
DyNTS_Errors_Controller.authConfig = config;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Aktualis auth config olvasasa (test/diagnosztika celokra).
|
|
71
|
+
*/
|
|
72
|
+
static getAuthConfig() {
|
|
73
|
+
return DyNTS_Errors_Controller.authConfig;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Test-only: visszaallitja az auth config-ot ures objektumra. Production code NE hivja.
|
|
77
|
+
*/
|
|
78
|
+
static _resetAuthConfigForTesting() {
|
|
79
|
+
DyNTS_Errors_Controller.authConfig = {};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Vissza-adja az adott endpoint-hoz tartozo `preProcesses` array-t.
|
|
83
|
+
* Ha az auth NINCS configurolva (default) vagy az endpoint nincs a
|
|
84
|
+
* `protectedEndpoints` listan, ures array-t ad vissza.
|
|
85
|
+
*/
|
|
86
|
+
getPreProcessesFor(endpointName) {
|
|
87
|
+
const cfg = DyNTS_Errors_Controller.authConfig;
|
|
88
|
+
if (!cfg.authPreProcess) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
const protectedNames = cfg.protectedEndpoints ?? ALL_ENDPOINT_NAMES;
|
|
92
|
+
return protectedNames.includes(endpointName) ? [cfg.authPreProcess] : [];
|
|
93
|
+
}
|
|
36
94
|
setupEndpoints() {
|
|
37
95
|
/* if (!this.getErrorDataService) {
|
|
38
96
|
throw new DyFM_Error({
|
|
@@ -51,6 +109,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
51
109
|
name: 'logError',
|
|
52
110
|
type: fsm_dynamo_1.DyFM_HttpCallType.post,
|
|
53
111
|
endpoint: '/error/log',
|
|
112
|
+
preProcesses: this.getPreProcessesFor('logError'),
|
|
54
113
|
tasks: [
|
|
55
114
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
56
115
|
const error_CS = this.getError_ControlService({
|
|
@@ -67,6 +126,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
67
126
|
name: 'newError',
|
|
68
127
|
type: fsm_dynamo_1.DyFM_HttpCallType.post,
|
|
69
128
|
endpoint: '/error/new',
|
|
129
|
+
preProcesses: this.getPreProcessesFor('newError'),
|
|
70
130
|
tasks: [
|
|
71
131
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
72
132
|
const error_CS = this.getError_ControlService({
|
|
@@ -83,6 +143,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
83
143
|
name: 'markErrorDone',
|
|
84
144
|
type: fsm_dynamo_1.DyFM_HttpCallType.get,
|
|
85
145
|
endpoint: '/error/mark-done/:errorId',
|
|
146
|
+
preProcesses: this.getPreProcessesFor('markErrorDone'),
|
|
86
147
|
tasks: [
|
|
87
148
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
88
149
|
const error_CS = this.getError_ControlService({
|
|
@@ -99,6 +160,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
99
160
|
name: 'markAllErrorDone',
|
|
100
161
|
type: fsm_dynamo_1.DyFM_HttpCallType.get,
|
|
101
162
|
endpoint: '/error/mark-all-done',
|
|
163
|
+
preProcesses: this.getPreProcessesFor('markAllErrorDone'),
|
|
102
164
|
tasks: [
|
|
103
165
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
104
166
|
const error_CS = this.getError_ControlService({
|
|
@@ -134,6 +196,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
134
196
|
name: 'getErrors',
|
|
135
197
|
type: fsm_dynamo_1.DyFM_HttpCallType.get,
|
|
136
198
|
endpoint: '/error/get-range/:range',
|
|
199
|
+
preProcesses: this.getPreProcessesFor('getErrors'),
|
|
137
200
|
tasks: [
|
|
138
201
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
139
202
|
const error_CS = this.getError_ControlService({
|
|
@@ -147,6 +210,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
147
210
|
name: 'getErrorsPaged',
|
|
148
211
|
type: fsm_dynamo_1.DyFM_HttpCallType.get,
|
|
149
212
|
endpoint: '/error/get-paged/:range/:pageSize/:pageIndex',
|
|
213
|
+
preProcesses: this.getPreProcessesFor('getErrorsPaged'),
|
|
150
214
|
tasks: [
|
|
151
215
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
152
216
|
const error_CS = this.getError_ControlService({
|
|
@@ -167,6 +231,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
167
231
|
name: 'getLastErrors',
|
|
168
232
|
type: fsm_dynamo_1.DyFM_HttpCallType.get,
|
|
169
233
|
endpoint: '/error/get-last-paged/:range/:pageSize/:pageIndex',
|
|
234
|
+
preProcesses: this.getPreProcessesFor('getLastErrors'),
|
|
170
235
|
tasks: [
|
|
171
236
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
172
237
|
const error_CS = this.getError_ControlService({
|
|
@@ -187,6 +252,7 @@ class DyNTS_Errors_Controller extends controller_service_1.DyNTS_Controller {
|
|
|
187
252
|
name: 'searchErrors',
|
|
188
253
|
type: fsm_dynamo_1.DyFM_HttpCallType.get,
|
|
189
254
|
endpoint: '/error/search',
|
|
255
|
+
preProcesses: this.getPreProcessesFor('searchErrors'),
|
|
190
256
|
tasks: [
|
|
191
257
|
async (req, res, issuer = 'unknown-issuer') => {
|
|
192
258
|
const error_CS = this.getError_ControlService({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.controller.js","sourceRoot":"","sources":["../../../../src/_modules/server/errors/errors.controller.ts"],"names":[],"mappings":";;;AAGA,sDAAkH;AAClH,oFAA+E;AAC/E,iHAAsG;AAEtG,uFAAoF;
|
|
1
|
+
{"version":3,"file":"errors.controller.js","sourceRoot":"","sources":["../../../../src/_modules/server/errors/errors.controller.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -161,5 +161,75 @@ describe('| DyNTS_Errors_Controller', () => {
|
|
|
161
161
|
}).toThrow();
|
|
162
162
|
});
|
|
163
163
|
});
|
|
164
|
+
|
|
165
|
+
describe('| opt-in admin auth retrofit (BL-20260420-004)', (): void => {
|
|
166
|
+
afterEach((): void => {
|
|
167
|
+
DyNTS_Errors_Controller._resetAuthConfigForTesting();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('| default: NO preProcesses on any endpoint (backwards compatible)', (): void => {
|
|
171
|
+
controller.setupEndpoints();
|
|
172
|
+
for (const ep of controller.endpoints) {
|
|
173
|
+
const pre: any = (ep as any).preProcesses;
|
|
174
|
+
// Ures array vagy undefined elfogadhato — fontos hogy NE legyen auth
|
|
175
|
+
expect(pre === undefined || pre.length === 0).toBe(true);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('| configure({ authPreProcess }) → mind a 8 endpoint kap preProcesses-t', (): void => {
|
|
180
|
+
const fakeAuth = async (): Promise<void> => { /* noop */ };
|
|
181
|
+
DyNTS_Errors_Controller.configure({ authPreProcess: fakeAuth });
|
|
182
|
+
// Uj controller instance kell — a setupEndpoints olvassa a static config-ot
|
|
183
|
+
const c = new (TestErrorsController as any)();
|
|
184
|
+
c.setupEndpoints();
|
|
185
|
+
|
|
186
|
+
const builtIn: string[] = [
|
|
187
|
+
'logError', 'newError',
|
|
188
|
+
'markErrorDone', 'markAllErrorDone',
|
|
189
|
+
'getErrors', 'getErrorsPaged', 'getLastErrors',
|
|
190
|
+
'searchErrors',
|
|
191
|
+
];
|
|
192
|
+
for (const name of builtIn) {
|
|
193
|
+
const ep: any = c.endpoints.find((e: any) => e.name === name);
|
|
194
|
+
expect(ep).withContext(`endpoint ${name} missing`).toBeDefined();
|
|
195
|
+
const pre: any = (ep as any).preProcesses;
|
|
196
|
+
expect(pre.length).withContext(`endpoint ${name} preProcesses`).toBe(1);
|
|
197
|
+
expect(pre[0]).toBe(fakeAuth);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('| configure({ authPreProcess, protectedEndpoints: subset }) → csak a megadott neveken aktiv', (): void => {
|
|
202
|
+
const fakeAuth = async (): Promise<void> => { /* noop */ };
|
|
203
|
+
DyNTS_Errors_Controller.configure({
|
|
204
|
+
authPreProcess: fakeAuth,
|
|
205
|
+
protectedEndpoints: ['markAllErrorDone', 'logError'],
|
|
206
|
+
});
|
|
207
|
+
const c = new (TestErrorsController as any)();
|
|
208
|
+
c.setupEndpoints();
|
|
209
|
+
|
|
210
|
+
const markAll: any = c.endpoints.find((e: any) => e.name === 'markAllErrorDone');
|
|
211
|
+
const log: any = c.endpoints.find((e: any) => e.name === 'logError');
|
|
212
|
+
const getErrors: any = c.endpoints.find((e: any) => e.name === 'getErrors');
|
|
213
|
+
|
|
214
|
+
expect((markAll as any).preProcesses.length).toBe(1);
|
|
215
|
+
expect((log as any).preProcesses.length).toBe(1);
|
|
216
|
+
expect((getErrors as any).preProcesses?.length ?? 0).toBe(0);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('| getAuthConfig() returns the active config', (): void => {
|
|
220
|
+
const fakeAuth = async (): Promise<void> => { /* noop */ };
|
|
221
|
+
DyNTS_Errors_Controller.configure({ authPreProcess: fakeAuth, protectedEndpoints: ['logError'] });
|
|
222
|
+
const cfg = DyNTS_Errors_Controller.getAuthConfig();
|
|
223
|
+
expect(cfg.authPreProcess).toBe(fakeAuth);
|
|
224
|
+
expect(cfg.protectedEndpoints).toEqual(['logError']);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('| _resetAuthConfigForTesting() clears the config', (): void => {
|
|
228
|
+
DyNTS_Errors_Controller.configure({ authPreProcess: async (): Promise<void> => { /* noop */ } });
|
|
229
|
+
DyNTS_Errors_Controller._resetAuthConfigForTesting();
|
|
230
|
+
const cfg = DyNTS_Errors_Controller.getAuthConfig();
|
|
231
|
+
expect(cfg.authPreProcess).toBeUndefined();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
164
234
|
});
|
|
165
235
|
|
|
@@ -7,6 +7,49 @@ import { DyNTS_Endpoint_Params } from '../../../_models/control-models/endpoint-
|
|
|
7
7
|
import { DyNTS_Errors_ControlService } from './errors.control-service';
|
|
8
8
|
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
9
9
|
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Auth retrofit config a `DyNTS_Errors_Controller`-hez. Opt-in — ha az
|
|
13
|
+
* `authPreProcess` nincs megadva, a controller a regi (auth nelkuli)
|
|
14
|
+
* viselkedest tartja.
|
|
15
|
+
*
|
|
16
|
+
* **Subclass-szintu konfiguracio:** az `authConfig` static, igy az abstract
|
|
17
|
+
* osztaly minden subclass-a kozott OSZTOTT. Ha tobb subclass-od van kulonbozo
|
|
18
|
+
* policy-val, hivd a `configure()`-t a megfelelo subclasson — TypeScript a
|
|
19
|
+
* static field-eket per-class hatarozza meg.
|
|
20
|
+
*/
|
|
21
|
+
export interface DyNTS_ErrorsController_AuthConfig {
|
|
22
|
+
/**
|
|
23
|
+
* Pre-process fuggveny ami minden vedett endpoint elott fut. Tipikusan:
|
|
24
|
+
* `DyNTS_AdminApiKey_AuthService.getInstance().verify`.
|
|
25
|
+
*
|
|
26
|
+
* Ha hianyzik vagy `undefined`, a controller NEM ad hozza auth-ot semelyik
|
|
27
|
+
* endpoint-hoz (regi viselkedes, opt-in safety).
|
|
28
|
+
*/
|
|
29
|
+
authPreProcess?: (req: Request, res: Response) => Promise<void>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Vedett endpoint nevek listaja. Ha hianyzik, az osszes 8 endpoint vedett
|
|
33
|
+
* (`authPreProcess` jelenleteben).
|
|
34
|
+
*
|
|
35
|
+
* Endpoint nevek: 'logError', 'newError', 'markErrorDone', 'markAllErrorDone',
|
|
36
|
+
* 'getErrors', 'getErrorsPaged', 'getLastErrors', 'searchErrors'.
|
|
37
|
+
*/
|
|
38
|
+
protectedEndpoints?: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Az osszes built-in endpoint neve — a `configure({ protectedEndpoints })`
|
|
44
|
+
* default-jat es a config validacio-t segiti.
|
|
45
|
+
*/
|
|
46
|
+
const ALL_ENDPOINT_NAMES: string[] = [
|
|
47
|
+
'logError', 'newError',
|
|
48
|
+
'markErrorDone', 'markAllErrorDone',
|
|
49
|
+
'getErrors', 'getErrorsPaged', 'getLastErrors',
|
|
50
|
+
'searchErrors',
|
|
51
|
+
];
|
|
52
|
+
|
|
10
53
|
/**
|
|
11
54
|
* Endpoints:
|
|
12
55
|
*
|
|
@@ -49,6 +92,57 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
49
92
|
): T_Error_ControlService;
|
|
50
93
|
protected readonly additionalEndpoints: DyNTS_Endpoint_Params[] = [];
|
|
51
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Static auth config — opt-in retrofit. Default ures objektum → NO auth
|
|
97
|
+
* (a meglevo integraciok valtoznatlan viselkedessel folytatodnak).
|
|
98
|
+
*/
|
|
99
|
+
protected static authConfig: DyNTS_ErrorsController_AuthConfig = {};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Static config setter. Hivhato barmikor a szerver startup-jan az endpoint
|
|
103
|
+
* registration ELOTT.
|
|
104
|
+
*
|
|
105
|
+
* Use case (host app):
|
|
106
|
+
* ```ts
|
|
107
|
+
* const adminAuth = DyNTS_AdminApiKey_AuthService.getInstance();
|
|
108
|
+
* DyNTS_Errors_Controller.configure({ authPreProcess: adminAuth.verify });
|
|
109
|
+
* // vagy fine-grained:
|
|
110
|
+
* DyNTS_Errors_Controller.configure({
|
|
111
|
+
* authPreProcess: adminAuth.verify,
|
|
112
|
+
* protectedEndpoints: ['markAllErrorDone', 'logError'],
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
static configure(config: DyNTS_ErrorsController_AuthConfig): void {
|
|
117
|
+
DyNTS_Errors_Controller.authConfig = config;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Aktualis auth config olvasasa (test/diagnosztika celokra).
|
|
122
|
+
*/
|
|
123
|
+
static getAuthConfig(): DyNTS_ErrorsController_AuthConfig {
|
|
124
|
+
return DyNTS_Errors_Controller.authConfig;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Test-only: visszaallitja az auth config-ot ures objektumra. Production code NE hivja.
|
|
129
|
+
*/
|
|
130
|
+
static _resetAuthConfigForTesting(): void {
|
|
131
|
+
DyNTS_Errors_Controller.authConfig = {};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Vissza-adja az adott endpoint-hoz tartozo `preProcesses` array-t.
|
|
136
|
+
* Ha az auth NINCS configurolva (default) vagy az endpoint nincs a
|
|
137
|
+
* `protectedEndpoints` listan, ures array-t ad vissza.
|
|
138
|
+
*/
|
|
139
|
+
protected getPreProcessesFor(endpointName: string): ((req: Request, res: Response) => Promise<void>)[] {
|
|
140
|
+
const cfg: DyNTS_ErrorsController_AuthConfig = DyNTS_Errors_Controller.authConfig;
|
|
141
|
+
if (!cfg.authPreProcess) { return []; }
|
|
142
|
+
const protectedNames: string[] = cfg.protectedEndpoints ?? ALL_ENDPOINT_NAMES;
|
|
143
|
+
return protectedNames.includes(endpointName) ? [cfg.authPreProcess] : [];
|
|
144
|
+
}
|
|
145
|
+
|
|
52
146
|
setupEndpoints(): void {
|
|
53
147
|
/* if (!this.getErrorDataService) {
|
|
54
148
|
throw new DyFM_Error({
|
|
@@ -69,6 +163,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
69
163
|
name: 'logError',
|
|
70
164
|
type: DyFM_HttpCallType.post,
|
|
71
165
|
endpoint: '/error/log',
|
|
166
|
+
preProcesses: this.getPreProcessesFor('logError'),
|
|
72
167
|
tasks: [
|
|
73
168
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
74
169
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -87,6 +182,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
87
182
|
name: 'newError',
|
|
88
183
|
type: DyFM_HttpCallType.post,
|
|
89
184
|
endpoint: '/error/new',
|
|
185
|
+
preProcesses: this.getPreProcessesFor('newError'),
|
|
90
186
|
tasks: [
|
|
91
187
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
92
188
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -106,6 +202,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
106
202
|
name: 'markErrorDone',
|
|
107
203
|
type: DyFM_HttpCallType.get,
|
|
108
204
|
endpoint: '/error/mark-done/:errorId',
|
|
205
|
+
preProcesses: this.getPreProcessesFor('markErrorDone'),
|
|
109
206
|
tasks: [
|
|
110
207
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
111
208
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -125,6 +222,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
125
222
|
name: 'markAllErrorDone',
|
|
126
223
|
type: DyFM_HttpCallType.get,
|
|
127
224
|
endpoint: '/error/mark-all-done',
|
|
225
|
+
preProcesses: this.getPreProcessesFor('markAllErrorDone'),
|
|
128
226
|
tasks: [
|
|
129
227
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer'): Promise<void> => {
|
|
130
228
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -164,6 +262,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
164
262
|
name: 'getErrors',
|
|
165
263
|
type: DyFM_HttpCallType.get,
|
|
166
264
|
endpoint: '/error/get-range/:range',
|
|
265
|
+
preProcesses: this.getPreProcessesFor('getErrors'),
|
|
167
266
|
tasks: [
|
|
168
267
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
169
268
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -184,6 +283,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
184
283
|
name: 'getErrorsPaged',
|
|
185
284
|
type: DyFM_HttpCallType.get,
|
|
186
285
|
endpoint: '/error/get-paged/:range/:pageSize/:pageIndex',
|
|
286
|
+
preProcesses: this.getPreProcessesFor('getErrorsPaged'),
|
|
187
287
|
tasks: [
|
|
188
288
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
189
289
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -215,6 +315,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
215
315
|
name: 'getLastErrors',
|
|
216
316
|
type: DyFM_HttpCallType.get,
|
|
217
317
|
endpoint: '/error/get-last-paged/:range/:pageSize/:pageIndex',
|
|
318
|
+
preProcesses: this.getPreProcessesFor('getLastErrors'),
|
|
218
319
|
tasks: [
|
|
219
320
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
220
321
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|
|
@@ -246,6 +347,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
246
347
|
name: 'searchErrors',
|
|
247
348
|
type: DyFM_HttpCallType.get,
|
|
248
349
|
endpoint: '/error/search',
|
|
350
|
+
preProcesses: this.getPreProcessesFor('searchErrors'),
|
|
249
351
|
tasks: [
|
|
250
352
|
async (req: Request, res: Response, issuer: string = 'unknown-issuer') : Promise<void> => {
|
|
251
353
|
const error_CS: T_Error_ControlService = this.getError_ControlService({
|