@futdevpro/nts-dynamo 1.15.20 → 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 +6 -6
- package/build/_modules/logs/_models/file-log-entry.interface.d.ts +14 -0
- package/build/_modules/logs/_models/file-log-entry.interface.d.ts.map +1 -0
- package/build/_modules/logs/_models/file-log-entry.interface.js +3 -0
- package/build/_modules/logs/_models/file-log-entry.interface.js.map +1 -0
- package/build/_modules/logs/_models/file-log-read-result.interface.d.ts +36 -0
- package/build/_modules/logs/_models/file-log-read-result.interface.d.ts.map +1 -0
- package/build/_modules/logs/_models/file-log-read-result.interface.js +3 -0
- package/build/_modules/logs/_models/file-log-read-result.interface.js.map +1 -0
- package/build/_modules/logs/file-log.service.d.ts +46 -0
- package/build/_modules/logs/file-log.service.d.ts.map +1 -1
- package/build/_modules/logs/file-log.service.js +178 -0
- package/build/_modules/logs/file-log.service.js.map +1 -1
- package/build/_modules/logs/file-logs.controller.d.ts +41 -0
- package/build/_modules/logs/file-logs.controller.d.ts.map +1 -0
- package/build/_modules/logs/file-logs.controller.js +139 -0
- package/build/_modules/logs/file-logs.controller.js.map +1 -0
- package/build/_modules/logs/get-file-logs-routing-module.util.d.ts +32 -0
- package/build/_modules/logs/get-file-logs-routing-module.util.d.ts.map +1 -0
- package/build/_modules/logs/get-file-logs-routing-module.util.js +38 -0
- package/build/_modules/logs/get-file-logs-routing-module.util.js.map +1 -0
- package/build/_modules/logs/index.d.ts +4 -0
- package/build/_modules/logs/index.d.ts.map +1 -1
- package/build/_modules/logs/index.js +5 -1
- package/build/_modules/logs/index.js.map +1 -1
- 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/logs/_models/file-log-entry.interface.ts +13 -0
- package/src/_modules/logs/_models/file-log-read-result.interface.ts +37 -0
- package/src/_modules/logs/file-log.service.spec.ts +139 -0
- package/src/_modules/logs/file-log.service.ts +183 -0
- package/src/_modules/logs/file-logs.controller.spec.ts +245 -0
- package/src/_modules/logs/file-logs.controller.ts +165 -0
- package/src/_modules/logs/get-file-logs-routing-module.util.ts +51 -0
- package/src/_modules/logs/index.ts +7 -0
- package/src/_modules/server/errors/errors.controller.spec.ts +70 -0
- package/src/_modules/server/errors/errors.controller.ts +102 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
|
|
3
|
+
import { DyFM_HttpCallType } from '@futdevpro/fsm-dynamo';
|
|
4
|
+
|
|
5
|
+
import { DyNTS_Controller } from '../../_services/route/controller.service';
|
|
6
|
+
import { DyNTS_Endpoint_Params } from '../../_models/control-models/endpoint-params.control-model';
|
|
7
|
+
|
|
8
|
+
import { DyNTS_FileLog_Entry } from './_models/file-log-entry.interface';
|
|
9
|
+
import { DyNTS_FileLog_ReadResult, DyNTS_FileLog_ReadOptions } from './_models/file-log-read-result.interface';
|
|
10
|
+
import { DyNTS_FileLog_Service } from './file-log.service';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Config a `DyNTS_FileLogs_Controller`-hez (opcionalis auth pre-process).
|
|
15
|
+
*/
|
|
16
|
+
export interface DyNTS_FileLogsController_Config {
|
|
17
|
+
/**
|
|
18
|
+
* Opcionalis auth pre-process — ha megadod, a controller-en levo endpointok
|
|
19
|
+
* vedettek. Tipikusan: `DyNTS_AdminApiKey_AuthService.getInstance().verify`.
|
|
20
|
+
*/
|
|
21
|
+
authPreProcess?: (req: Request, res: Response) => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* NTS File Logs Controller — endpointok a `DyNTS_FileLog_Service` altal irt
|
|
27
|
+
* log fajl-ok lekeresehez.
|
|
28
|
+
*
|
|
29
|
+
* **Endpoint-ok:**
|
|
30
|
+
* GET /list — log fajlok listazasa (basename, sizeBytes, mtimeMs, isCurrent)
|
|
31
|
+
* GET /file/:filename — egy fajl olvasasa, line-based: ?tail=N | ?head=N | ?rangeStart=A&rangeEnd=B
|
|
32
|
+
*
|
|
33
|
+
* **Mount-olas (host app):**
|
|
34
|
+
* app.use(DyNTS_getFileLogsRoutingModule({
|
|
35
|
+
* authPreProcess: adminAuth.verify, // opcionalis
|
|
36
|
+
* route: '/admin/file-logs', // default '/file-logs'
|
|
37
|
+
* }));
|
|
38
|
+
*
|
|
39
|
+
* **Status code-ok:**
|
|
40
|
+
* 200 — sikeres response (lehet ures lista is)
|
|
41
|
+
* 400 — invalid query parameter (tail/head/range)
|
|
42
|
+
* 401 — auth pre-process throw-ol DyFM_Error(401)
|
|
43
|
+
* 404 — fajl nem letezik vagy nem megfelelo nev (whitelist failure / path traversal kiserlet)
|
|
44
|
+
* 503 — a DyNTS_FileLog_Service nincs install-olva (vagy file_log.enabled=false)
|
|
45
|
+
*/
|
|
46
|
+
export class DyNTS_FileLogs_Controller extends DyNTS_Controller {
|
|
47
|
+
|
|
48
|
+
private static config: DyNTS_FileLogsController_Config = {};
|
|
49
|
+
|
|
50
|
+
static configure(config: DyNTS_FileLogsController_Config): void {
|
|
51
|
+
DyNTS_FileLogs_Controller.config = config;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static getInstance(): DyNTS_FileLogs_Controller {
|
|
55
|
+
return DyNTS_FileLogs_Controller.getSingletonInstance();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private readonly fileLogService: DyNTS_FileLog_Service = DyNTS_FileLog_Service.getInstance();
|
|
59
|
+
|
|
60
|
+
setupEndpoints(): void {
|
|
61
|
+
const preProcesses: ((req: Request, res: Response) => Promise<void>)[] = [];
|
|
62
|
+
if (DyNTS_FileLogs_Controller.config.authPreProcess) {
|
|
63
|
+
preProcesses.push(DyNTS_FileLogs_Controller.config.authPreProcess);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.endpoints = [
|
|
67
|
+
// GET /list — fajllista
|
|
68
|
+
new DyNTS_Endpoint_Params({
|
|
69
|
+
name: 'listFileLogs',
|
|
70
|
+
type: DyFM_HttpCallType.get,
|
|
71
|
+
endpoint: '/list',
|
|
72
|
+
preProcesses: preProcesses,
|
|
73
|
+
logRequest: false,
|
|
74
|
+
tasks: [
|
|
75
|
+
async (req: Request, res: Response): Promise<void> => {
|
|
76
|
+
if (!this.fileLogService.isInstalled()) {
|
|
77
|
+
res.status(503).send({
|
|
78
|
+
error: 'FileLog service is not installed.',
|
|
79
|
+
hint: 'Set DyNTS_global_settings.log_settings.file_log.enabled = true and call DyNTS_FileLog_Service.getInstance().install() at server startup.',
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const files: DyNTS_FileLog_Entry[] = this.fileLogService.listLogFiles();
|
|
85
|
+
const totalSizeBytes: number = files.reduce(
|
|
86
|
+
(acc: number, f: DyNTS_FileLog_Entry): number => acc + f.sizeBytes, 0,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
res.send({
|
|
90
|
+
count: files.length,
|
|
91
|
+
totalSizeBytes: totalSizeBytes,
|
|
92
|
+
files: files,
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
}),
|
|
97
|
+
|
|
98
|
+
// GET /file/:filename — egy fajl olvasasa tail / head / range modban
|
|
99
|
+
new DyNTS_Endpoint_Params({
|
|
100
|
+
name: 'readFileLog',
|
|
101
|
+
type: DyFM_HttpCallType.get,
|
|
102
|
+
endpoint: '/file/:filename',
|
|
103
|
+
preProcesses: preProcesses,
|
|
104
|
+
logRequest: false,
|
|
105
|
+
tasks: [
|
|
106
|
+
async (req: Request, res: Response): Promise<void> => {
|
|
107
|
+
if (!this.fileLogService.isInstalled()) {
|
|
108
|
+
res.status(503).send({
|
|
109
|
+
error: 'FileLog service is not installed.',
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const filename: string = req.params.filename;
|
|
115
|
+
const options: DyNTS_FileLog_ReadOptions = {};
|
|
116
|
+
|
|
117
|
+
// Mod prioritas: range > head > tail. Csak a megadott mezo aktivalja az adott modot.
|
|
118
|
+
if (req.query.rangeStart !== undefined && req.query.rangeEnd !== undefined) {
|
|
119
|
+
const start: number = parseInt(req.query.rangeStart as string, 10);
|
|
120
|
+
const end: number = parseInt(req.query.rangeEnd as string, 10);
|
|
121
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || start < 1 || end < start) {
|
|
122
|
+
res.status(400).send({ error: 'Invalid rangeStart/rangeEnd query parameters' });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
options.rangeStart = start;
|
|
126
|
+
options.rangeEnd = end;
|
|
127
|
+
} else if (req.query.head !== undefined) {
|
|
128
|
+
const head: number = parseInt(req.query.head as string, 10);
|
|
129
|
+
if (!Number.isFinite(head) || head < 1) {
|
|
130
|
+
res.status(400).send({ error: 'Invalid head query parameter' });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
options.head = head;
|
|
134
|
+
} else if (req.query.tail !== undefined) {
|
|
135
|
+
const tail: number = parseInt(req.query.tail as string, 10);
|
|
136
|
+
if (!Number.isFinite(tail) || tail < 1) {
|
|
137
|
+
res.status(400).send({ error: 'Invalid tail query parameter' });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
options.tail = tail;
|
|
141
|
+
}
|
|
142
|
+
// egyik query mezo sincs → service alapertelmezett tail (200)
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const result: DyNTS_FileLog_ReadResult = this.fileLogService.readLogFile(filename, options);
|
|
146
|
+
res.send(result);
|
|
147
|
+
} catch (err: unknown) {
|
|
148
|
+
const msg: string = err instanceof Error ? err.message : String(err);
|
|
149
|
+
if (msg === 'FileLog service not installed') {
|
|
150
|
+
res.status(503).send({ error: msg });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (msg === 'invalid filename' || msg === 'file not found') {
|
|
154
|
+
res.status(404).send({ error: msg, filename: filename });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Egyeb hibak (pl. FS read failure) — 500
|
|
158
|
+
res.status(500).send({ error: msg });
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
}),
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { DyNTS_RoutingModule_Settings } from '../../_models/interfaces/routing-module-settings.interface';
|
|
2
|
+
import { DyNTS_RoutingModule } from '../../_services/route/routing-module.service';
|
|
3
|
+
|
|
4
|
+
import { DyNTS_FileLogs_Controller, DyNTS_FileLogsController_Config } from './file-logs.controller';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Config a `DyNTS_getFileLogsRoutingModule()`-hoz.
|
|
9
|
+
*/
|
|
10
|
+
export interface DyNTS_FileLogsRoutingModule_Config extends DyNTS_FileLogsController_Config {
|
|
11
|
+
/** Route prefix. Default: `/file-logs`. */
|
|
12
|
+
route?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Letrehoz egy routing module-t a `DyNTS_FileLogs_Controller`-rel.
|
|
18
|
+
*
|
|
19
|
+
* **Hasznalat (auth nelkul, fejlesztoi env):**
|
|
20
|
+
* ```ts
|
|
21
|
+
* app.use(DyNTS_getFileLogsRoutingModule());
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* **Hasznalat (admin API key auth-tal — javasolt produkcios env-re):**
|
|
25
|
+
* ```ts
|
|
26
|
+
* const adminAuth = DyNTS_AdminApiKey_AuthService.getInstance();
|
|
27
|
+
* app.use(DyNTS_getFileLogsRoutingModule({
|
|
28
|
+
* authPreProcess: adminAuth.verify,
|
|
29
|
+
* route: '/admin/file-logs', // opcionalis override
|
|
30
|
+
* }));
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* **Elofeltetel:** `DyNTS_FileLog_Service.getInstance().install()` lefutott
|
|
34
|
+
* a szerver startup-on (es a `log_settings.file_log.enabled = true`).
|
|
35
|
+
* Egyebkent a controller endpointjai 503-at adnak.
|
|
36
|
+
*/
|
|
37
|
+
export function DyNTS_getFileLogsRoutingModule(
|
|
38
|
+
config?: DyNTS_FileLogsRoutingModule_Config,
|
|
39
|
+
): DyNTS_RoutingModule {
|
|
40
|
+
// Controller config atadasa (static — getInstance() elott)
|
|
41
|
+
if (config) {
|
|
42
|
+
DyNTS_FileLogs_Controller.configure({ authPreProcess: config.authPreProcess });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const settings: DyNTS_RoutingModule_Settings = {
|
|
46
|
+
route: config?.route ?? '/file-logs',
|
|
47
|
+
controllers: [DyNTS_FileLogs_Controller.getInstance()],
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return new DyNTS_RoutingModule(settings);
|
|
51
|
+
}
|
|
@@ -2,3 +2,10 @@ export { DyNTS_Logs_Service } from './logs.service';
|
|
|
2
2
|
export { DyNTS_Logs_Controller, DyNTS_LogsController_Config } from './logs.controller';
|
|
3
3
|
export { DyNTS_getLogsRoutingModule } from './get-logs-routing-module.util';
|
|
4
4
|
export { DyNTS_FileLog_Service } from './file-log.service';
|
|
5
|
+
export { DyNTS_FileLogs_Controller, DyNTS_FileLogsController_Config } from './file-logs.controller';
|
|
6
|
+
export {
|
|
7
|
+
DyNTS_getFileLogsRoutingModule,
|
|
8
|
+
DyNTS_FileLogsRoutingModule_Config,
|
|
9
|
+
} from './get-file-logs-routing-module.util';
|
|
10
|
+
export { DyNTS_FileLog_Entry } from './_models/file-log-entry.interface';
|
|
11
|
+
export { DyNTS_FileLog_ReadResult, DyNTS_FileLog_ReadOptions } from './_models/file-log-read-result.interface';
|
|
@@ -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({
|