@serve.zone/dcrouter 8.1.0 → 9.1.1
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_serve/bundle.js +1417 -992
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cache/classes.cache.cleaner.d.ts +47 -0
- package/dist_ts/cache/classes.cache.cleaner.js +130 -0
- package/dist_ts/cache/classes.cached.document.d.ts +76 -0
- package/dist_ts/cache/classes.cached.document.js +100 -0
- package/dist_ts/cache/classes.cachedb.d.ts +60 -0
- package/dist_ts/cache/classes.cachedb.js +126 -0
- package/dist_ts/cache/documents/classes.cached.email.d.ts +125 -0
- package/dist_ts/cache/documents/classes.cached.email.js +337 -0
- package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +119 -0
- package/dist_ts/cache/documents/classes.cached.ip.reputation.js +323 -0
- package/dist_ts/cache/documents/index.d.ts +2 -0
- package/dist_ts/cache/documents/index.js +3 -0
- package/dist_ts/cache/index.d.ts +4 -0
- package/dist_ts/cache/index.js +7 -0
- package/dist_ts/monitoring/classes.metricscache.d.ts +32 -0
- package/dist_ts/monitoring/classes.metricscache.js +63 -0
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +169 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +591 -0
- package/dist_ts/monitoring/index.d.ts +1 -0
- package/dist_ts/monitoring/index.js +2 -0
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +31 -0
- package/dist_ts/opsserver/handlers/admin.handler.js +180 -0
- package/dist_ts/opsserver/handlers/certificate.handler.d.ts +34 -0
- package/dist_ts/opsserver/handlers/certificate.handler.js +419 -0
- package/dist_ts/opsserver/handlers/config.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/config.handler.js +169 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +32 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.js +226 -0
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +17 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +215 -0
- package/dist_ts/opsserver/handlers/radius.handler.d.ts +8 -0
- package/dist_ts/opsserver/handlers/radius.handler.js +296 -0
- package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +8 -0
- package/dist_ts/opsserver/handlers/remoteingress.handler.js +154 -0
- package/dist_ts/opsserver/handlers/security.handler.d.ts +11 -0
- package/dist_ts/opsserver/handlers/security.handler.js +232 -0
- package/dist_ts/opsserver/handlers/stats.handler.d.ts +13 -0
- package/dist_ts/opsserver/handlers/stats.handler.js +400 -0
- package/dist_ts/security/classes.securitylogger.d.ts +140 -0
- package/dist_ts/security/classes.securitylogger.js +235 -0
- package/dist_ts/storage/classes.storagemanager.d.ts +82 -0
- package/dist_ts/storage/classes.storagemanager.js +344 -0
- package/dist_ts/storage/index.d.ts +1 -0
- package/dist_ts/storage/index.js +3 -0
- package/dist_ts_interfaces/requests/config.d.ts +77 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +1 -1
- package/dist_ts_web/elements/ops-dashboard.js +15 -5
- package/dist_ts_web/elements/ops-view-apitokens.js +8 -4
- package/dist_ts_web/elements/ops-view-config.d.ts +10 -8
- package/dist_ts_web/elements/ops-view-config.js +215 -297
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/opsserver/handlers/config.handler.ts +154 -72
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +1 -1
- package/ts_web/elements/ops-dashboard.ts +14 -4
- package/ts_web/elements/ops-view-apitokens.ts +7 -3
- package/ts_web/elements/ops-view-config.ts +237 -299
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
export declare class EmailOpsHandler {
|
|
4
|
+
private opsServerRef;
|
|
5
|
+
typedrouter: plugins.typedrequest.TypedRouter;
|
|
6
|
+
constructor(opsServerRef: OpsServer);
|
|
7
|
+
private registerHandlers;
|
|
8
|
+
/**
|
|
9
|
+
* Get all queue items mapped to catalog IEmail format
|
|
10
|
+
*/
|
|
11
|
+
private getAllQueueEmails;
|
|
12
|
+
/**
|
|
13
|
+
* Get a single email detail by ID
|
|
14
|
+
*/
|
|
15
|
+
private getEmailDetail;
|
|
16
|
+
/**
|
|
17
|
+
* Map a queue item to catalog IEmail format
|
|
18
|
+
*/
|
|
19
|
+
private mapQueueItemToEmail;
|
|
20
|
+
/**
|
|
21
|
+
* Map a queue item to catalog IEmailDetail format
|
|
22
|
+
*/
|
|
23
|
+
private mapQueueItemToEmailDetail;
|
|
24
|
+
/**
|
|
25
|
+
* Map queue status to catalog TEmailStatus
|
|
26
|
+
*/
|
|
27
|
+
private mapStatus;
|
|
28
|
+
/**
|
|
29
|
+
* Format byte size to human-readable string
|
|
30
|
+
*/
|
|
31
|
+
private formatSize;
|
|
32
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
3
|
+
export class EmailOpsHandler {
|
|
4
|
+
opsServerRef;
|
|
5
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
6
|
+
constructor(opsServerRef) {
|
|
7
|
+
this.opsServerRef = opsServerRef;
|
|
8
|
+
// Add this handler's router to the parent
|
|
9
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
10
|
+
this.registerHandlers();
|
|
11
|
+
}
|
|
12
|
+
registerHandlers() {
|
|
13
|
+
// Get All Emails Handler
|
|
14
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getAllEmails', async (dataArg) => {
|
|
15
|
+
const emails = this.getAllQueueEmails();
|
|
16
|
+
return { emails };
|
|
17
|
+
}));
|
|
18
|
+
// Get Email Detail Handler
|
|
19
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getEmailDetail', async (dataArg) => {
|
|
20
|
+
const email = this.getEmailDetail(dataArg.emailId);
|
|
21
|
+
return { email };
|
|
22
|
+
}));
|
|
23
|
+
// Resend Failed Email Handler
|
|
24
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('resendEmail', async (dataArg) => {
|
|
25
|
+
const emailServer = this.opsServerRef.dcRouterRef.emailServer;
|
|
26
|
+
if (!emailServer?.deliveryQueue) {
|
|
27
|
+
return { success: false, error: 'Email server not available' };
|
|
28
|
+
}
|
|
29
|
+
const queue = emailServer.deliveryQueue;
|
|
30
|
+
const item = queue.getItem(dataArg.emailId);
|
|
31
|
+
if (!item) {
|
|
32
|
+
return { success: false, error: 'Email not found in queue' };
|
|
33
|
+
}
|
|
34
|
+
if (item.status !== 'failed') {
|
|
35
|
+
return { success: false, error: `Email is not in failed state (current: ${item.status})` };
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const newQueueId = await queue.enqueue(item.processingResult, item.processingMode, item.route);
|
|
39
|
+
await queue.removeItem(dataArg.emailId);
|
|
40
|
+
return { success: true, newQueueId };
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: error instanceof Error ? error.message : 'Failed to resend email'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get all queue items mapped to catalog IEmail format
|
|
52
|
+
*/
|
|
53
|
+
getAllQueueEmails() {
|
|
54
|
+
const emailServer = this.opsServerRef.dcRouterRef.emailServer;
|
|
55
|
+
if (!emailServer?.deliveryQueue) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const queue = emailServer.deliveryQueue;
|
|
59
|
+
const queueMap = queue.queue;
|
|
60
|
+
if (!queueMap) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const emails = [];
|
|
64
|
+
for (const [id, item] of queueMap.entries()) {
|
|
65
|
+
emails.push(this.mapQueueItemToEmail(item));
|
|
66
|
+
}
|
|
67
|
+
// Sort by createdAt descending (newest first)
|
|
68
|
+
emails.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
69
|
+
return emails;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get a single email detail by ID
|
|
73
|
+
*/
|
|
74
|
+
getEmailDetail(emailId) {
|
|
75
|
+
const emailServer = this.opsServerRef.dcRouterRef.emailServer;
|
|
76
|
+
if (!emailServer?.deliveryQueue) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const queue = emailServer.deliveryQueue;
|
|
80
|
+
const item = queue.getItem(emailId);
|
|
81
|
+
if (!item) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return this.mapQueueItemToEmailDetail(item);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Map a queue item to catalog IEmail format
|
|
88
|
+
*/
|
|
89
|
+
mapQueueItemToEmail(item) {
|
|
90
|
+
const processingResult = item.processingResult;
|
|
91
|
+
let from = '';
|
|
92
|
+
let to = '';
|
|
93
|
+
let subject = '';
|
|
94
|
+
let messageId = '';
|
|
95
|
+
let size = '0 B';
|
|
96
|
+
if (processingResult) {
|
|
97
|
+
if (processingResult.email) {
|
|
98
|
+
from = processingResult.email.from || '';
|
|
99
|
+
to = (processingResult.email.to || [])[0] || '';
|
|
100
|
+
subject = processingResult.email.subject || '';
|
|
101
|
+
}
|
|
102
|
+
else if (processingResult.from) {
|
|
103
|
+
from = processingResult.from;
|
|
104
|
+
to = (processingResult.to || [])[0] || '';
|
|
105
|
+
subject = processingResult.subject || '';
|
|
106
|
+
}
|
|
107
|
+
// Try to get messageId
|
|
108
|
+
if (typeof processingResult.getMessageId === 'function') {
|
|
109
|
+
try {
|
|
110
|
+
messageId = processingResult.getMessageId() || '';
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
messageId = '';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Compute approximate size
|
|
117
|
+
const textLen = processingResult.text?.length || 0;
|
|
118
|
+
const htmlLen = processingResult.html?.length || 0;
|
|
119
|
+
let attachSize = 0;
|
|
120
|
+
if (typeof processingResult.getAttachmentsSize === 'function') {
|
|
121
|
+
try {
|
|
122
|
+
attachSize = processingResult.getAttachmentsSize() || 0;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
attachSize = 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
size = this.formatSize(textLen + htmlLen + attachSize);
|
|
129
|
+
}
|
|
130
|
+
// Map queue status to catalog TEmailStatus
|
|
131
|
+
const status = this.mapStatus(item.status);
|
|
132
|
+
const createdAt = item.createdAt instanceof Date ? item.createdAt.getTime() : item.createdAt;
|
|
133
|
+
return {
|
|
134
|
+
id: item.id,
|
|
135
|
+
direction: 'outbound',
|
|
136
|
+
status,
|
|
137
|
+
from,
|
|
138
|
+
to,
|
|
139
|
+
subject,
|
|
140
|
+
timestamp: new Date(createdAt).toISOString(),
|
|
141
|
+
messageId,
|
|
142
|
+
size,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Map a queue item to catalog IEmailDetail format
|
|
147
|
+
*/
|
|
148
|
+
mapQueueItemToEmailDetail(item) {
|
|
149
|
+
const base = this.mapQueueItemToEmail(item);
|
|
150
|
+
const processingResult = item.processingResult;
|
|
151
|
+
let toList = [];
|
|
152
|
+
let cc = [];
|
|
153
|
+
let headers = {};
|
|
154
|
+
let body = '';
|
|
155
|
+
if (processingResult) {
|
|
156
|
+
if (processingResult.email) {
|
|
157
|
+
toList = processingResult.email.to || [];
|
|
158
|
+
cc = processingResult.email.cc || [];
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
toList = processingResult.to || [];
|
|
162
|
+
cc = processingResult.cc || [];
|
|
163
|
+
}
|
|
164
|
+
headers = processingResult.headers || {};
|
|
165
|
+
body = processingResult.html || processingResult.text || '';
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
...base,
|
|
169
|
+
toList,
|
|
170
|
+
cc,
|
|
171
|
+
smtpLog: [],
|
|
172
|
+
connectionInfo: {
|
|
173
|
+
sourceIp: '',
|
|
174
|
+
sourceHostname: '',
|
|
175
|
+
destinationIp: '',
|
|
176
|
+
destinationPort: 0,
|
|
177
|
+
tlsVersion: '',
|
|
178
|
+
tlsCipher: '',
|
|
179
|
+
authenticated: false,
|
|
180
|
+
authMethod: '',
|
|
181
|
+
authUser: '',
|
|
182
|
+
},
|
|
183
|
+
authenticationResults: {
|
|
184
|
+
spf: 'none',
|
|
185
|
+
spfDomain: '',
|
|
186
|
+
dkim: 'none',
|
|
187
|
+
dkimDomain: '',
|
|
188
|
+
dmarc: 'none',
|
|
189
|
+
dmarcPolicy: '',
|
|
190
|
+
},
|
|
191
|
+
rejectionReason: item.status === 'failed' ? item.lastError : undefined,
|
|
192
|
+
bounceMessage: item.status === 'failed' ? item.lastError : undefined,
|
|
193
|
+
headers,
|
|
194
|
+
body,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Map queue status to catalog TEmailStatus
|
|
199
|
+
*/
|
|
200
|
+
mapStatus(queueStatus) {
|
|
201
|
+
switch (queueStatus) {
|
|
202
|
+
case 'pending':
|
|
203
|
+
case 'processing':
|
|
204
|
+
return 'pending';
|
|
205
|
+
case 'delivered':
|
|
206
|
+
return 'delivered';
|
|
207
|
+
case 'failed':
|
|
208
|
+
return 'bounced';
|
|
209
|
+
case 'deferred':
|
|
210
|
+
return 'deferred';
|
|
211
|
+
default:
|
|
212
|
+
return 'pending';
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Format byte size to human-readable string
|
|
217
|
+
*/
|
|
218
|
+
formatSize(bytes) {
|
|
219
|
+
if (bytes < 1024)
|
|
220
|
+
return `${bytes} B`;
|
|
221
|
+
if (bytes < 1024 * 1024)
|
|
222
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
223
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1haWwtb3BzLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvZW1haWwtb3BzLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLEtBQUssVUFBVSxNQUFNLGlDQUFpQyxDQUFDO0FBRTlELE1BQU0sT0FBTyxlQUFlO0lBR047SUFGYixXQUFXLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRTVELFlBQW9CLFlBQXVCO1FBQXZCLGlCQUFZLEdBQVosWUFBWSxDQUFXO1FBQ3pDLDBDQUEwQztRQUMxQyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFTyxnQkFBZ0I7UUFDdEIseUJBQXlCO1FBQ3pCLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUNuQyxjQUFjLEVBQ2QsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQ0YsQ0FDRixDQUFDO1FBRUYsMkJBQTJCO1FBQzNCLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUNuQyxnQkFBZ0IsRUFDaEIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FB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
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
export declare class LogsHandler {
|
|
4
|
+
private opsServerRef;
|
|
5
|
+
typedrouter: plugins.typedrequest.TypedRouter;
|
|
6
|
+
constructor(opsServerRef: OpsServer);
|
|
7
|
+
private registerHandlers;
|
|
8
|
+
private static mapLogLevel;
|
|
9
|
+
private static deriveCategory;
|
|
10
|
+
private getRecentLogs;
|
|
11
|
+
/**
|
|
12
|
+
* Add a log destination to the base logger that pushes entries
|
|
13
|
+
* to all connected ops_dashboard TypedSocket clients.
|
|
14
|
+
*/
|
|
15
|
+
private setupLogPushDestination;
|
|
16
|
+
private setupLogStream;
|
|
17
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
3
|
+
import { logBuffer, baseLogger } from '../../logger.js';
|
|
4
|
+
export class LogsHandler {
|
|
5
|
+
opsServerRef;
|
|
6
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
7
|
+
constructor(opsServerRef) {
|
|
8
|
+
this.opsServerRef = opsServerRef;
|
|
9
|
+
// Add this handler's router to the parent
|
|
10
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
11
|
+
this.registerHandlers();
|
|
12
|
+
this.setupLogPushDestination();
|
|
13
|
+
}
|
|
14
|
+
registerHandlers() {
|
|
15
|
+
// Get Recent Logs Handler
|
|
16
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getRecentLogs', async (dataArg, toolsArg) => {
|
|
17
|
+
const logs = await this.getRecentLogs(dataArg.level, dataArg.category, dataArg.limit || 100, dataArg.offset || 0, dataArg.search, dataArg.timeRange);
|
|
18
|
+
return {
|
|
19
|
+
logs,
|
|
20
|
+
total: logs.length, // TODO: Implement proper total count
|
|
21
|
+
hasMore: false, // TODO: Implement proper pagination
|
|
22
|
+
};
|
|
23
|
+
}));
|
|
24
|
+
// Get Log Stream Handler
|
|
25
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getLogStream', async (dataArg, toolsArg) => {
|
|
26
|
+
// Create a virtual stream for log streaming
|
|
27
|
+
const virtualStream = new plugins.typedrequest.VirtualStream();
|
|
28
|
+
// Set up log streaming
|
|
29
|
+
const streamLogs = this.setupLogStream(virtualStream, dataArg.filters?.level, dataArg.filters?.category, dataArg.follow);
|
|
30
|
+
// Start streaming
|
|
31
|
+
streamLogs.start();
|
|
32
|
+
// VirtualStream handles cleanup automatically
|
|
33
|
+
return {
|
|
34
|
+
logStream: virtualStream, // Cast to IVirtualStream interface
|
|
35
|
+
};
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
static mapLogLevel(smartlogLevel) {
|
|
39
|
+
switch (smartlogLevel) {
|
|
40
|
+
case 'silly':
|
|
41
|
+
case 'debug':
|
|
42
|
+
return 'debug';
|
|
43
|
+
case 'warn':
|
|
44
|
+
return 'warn';
|
|
45
|
+
case 'error':
|
|
46
|
+
return 'error';
|
|
47
|
+
default:
|
|
48
|
+
return 'info';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
static deriveCategory(zone, message) {
|
|
52
|
+
const msg = (message || '').toLowerCase();
|
|
53
|
+
if (msg.includes('[security:') || msg.includes('security'))
|
|
54
|
+
return 'security';
|
|
55
|
+
if (zone === 'email' || msg.includes('email') || msg.includes('smtp') || msg.includes('mta'))
|
|
56
|
+
return 'email';
|
|
57
|
+
if (zone === 'dns' || msg.includes('dns'))
|
|
58
|
+
return 'dns';
|
|
59
|
+
if (msg.includes('smtp'))
|
|
60
|
+
return 'smtp';
|
|
61
|
+
return 'system';
|
|
62
|
+
}
|
|
63
|
+
async getRecentLogs(level, category, limit = 100, offset = 0, search, timeRange) {
|
|
64
|
+
// Compute a timestamp cutoff from timeRange
|
|
65
|
+
let since;
|
|
66
|
+
if (timeRange) {
|
|
67
|
+
const rangeMs = {
|
|
68
|
+
'1h': 3600000,
|
|
69
|
+
'6h': 21600000,
|
|
70
|
+
'24h': 86400000,
|
|
71
|
+
'7d': 604800000,
|
|
72
|
+
'30d': 2592000000,
|
|
73
|
+
};
|
|
74
|
+
since = Date.now() - (rangeMs[timeRange] || 86400000);
|
|
75
|
+
}
|
|
76
|
+
// Map the UI level to smartlog levels for filtering
|
|
77
|
+
const smartlogLevels = level
|
|
78
|
+
? level === 'debug'
|
|
79
|
+
? ['debug', 'silly']
|
|
80
|
+
: level === 'info'
|
|
81
|
+
? ['info', 'ok', 'success', 'note', 'lifecycle']
|
|
82
|
+
: [level]
|
|
83
|
+
: undefined;
|
|
84
|
+
// Fetch a larger batch from buffer, then apply category filter client-side
|
|
85
|
+
const rawEntries = logBuffer.getEntries({
|
|
86
|
+
level: smartlogLevels,
|
|
87
|
+
search,
|
|
88
|
+
since,
|
|
89
|
+
limit: limit * 3, // over-fetch to compensate for category filtering
|
|
90
|
+
offset: 0,
|
|
91
|
+
});
|
|
92
|
+
// Map ILogPackage → UI log format and apply category filter
|
|
93
|
+
const mapped = [];
|
|
94
|
+
for (const pkg of rawEntries) {
|
|
95
|
+
const uiLevel = LogsHandler.mapLogLevel(pkg.level);
|
|
96
|
+
const uiCategory = LogsHandler.deriveCategory(pkg.context?.zone, pkg.message);
|
|
97
|
+
if (category && uiCategory !== category)
|
|
98
|
+
continue;
|
|
99
|
+
mapped.push({
|
|
100
|
+
timestamp: pkg.timestamp,
|
|
101
|
+
level: uiLevel,
|
|
102
|
+
category: uiCategory,
|
|
103
|
+
message: pkg.message,
|
|
104
|
+
metadata: pkg.data,
|
|
105
|
+
});
|
|
106
|
+
if (mapped.length >= limit)
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
return mapped;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Add a log destination to the base logger that pushes entries
|
|
113
|
+
* to all connected ops_dashboard TypedSocket clients.
|
|
114
|
+
*/
|
|
115
|
+
setupLogPushDestination() {
|
|
116
|
+
const opsServerRef = this.opsServerRef;
|
|
117
|
+
baseLogger.addLogDestination({
|
|
118
|
+
async handleLog(logPackage) {
|
|
119
|
+
// Access the TypedSocket server instance from OpsServer
|
|
120
|
+
const typedsocket = opsServerRef.server?.typedserver?.typedsocket;
|
|
121
|
+
if (!typedsocket)
|
|
122
|
+
return;
|
|
123
|
+
let connections;
|
|
124
|
+
try {
|
|
125
|
+
connections = await typedsocket.findAllTargetConnectionsByTag('role', 'ops_dashboard');
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (connections.length === 0)
|
|
131
|
+
return;
|
|
132
|
+
const entry = {
|
|
133
|
+
timestamp: logPackage.timestamp || Date.now(),
|
|
134
|
+
level: LogsHandler.mapLogLevel(logPackage.level),
|
|
135
|
+
category: LogsHandler.deriveCategory(logPackage.context?.zone, logPackage.message),
|
|
136
|
+
message: logPackage.message,
|
|
137
|
+
metadata: logPackage.data,
|
|
138
|
+
};
|
|
139
|
+
for (const conn of connections) {
|
|
140
|
+
try {
|
|
141
|
+
const push = typedsocket.createTypedRequest('pushLogEntry', conn);
|
|
142
|
+
push.fire({ entry }).catch(() => { }); // fire-and-forget
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// connection may have closed
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
setupLogStream(virtualStream, levelFilter, categoryFilter, follow = true) {
|
|
152
|
+
let intervalId = null;
|
|
153
|
+
let logIndex = 0;
|
|
154
|
+
const start = () => {
|
|
155
|
+
if (!follow) {
|
|
156
|
+
// Send existing logs and close
|
|
157
|
+
this.getRecentLogs(levelFilter?.[0], categoryFilter?.[0], 100, 0).then(logs => {
|
|
158
|
+
logs.forEach(log => {
|
|
159
|
+
const logData = JSON.stringify(log);
|
|
160
|
+
const encoder = new TextEncoder();
|
|
161
|
+
virtualStream.sendData(encoder.encode(logData));
|
|
162
|
+
});
|
|
163
|
+
// VirtualStream doesn't have end() method - it closes automatically
|
|
164
|
+
});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// For follow mode, simulate real-time log streaming
|
|
168
|
+
intervalId = setInterval(async () => {
|
|
169
|
+
const categories = ['smtp', 'dns', 'security', 'system', 'email'];
|
|
170
|
+
const levels = ['info', 'warn', 'error', 'debug'];
|
|
171
|
+
const mockCategory = categories[Math.floor(Math.random() * categories.length)];
|
|
172
|
+
const mockLevel = levels[Math.floor(Math.random() * levels.length)];
|
|
173
|
+
// Filter by requested criteria
|
|
174
|
+
if (levelFilter && !levelFilter.includes(mockLevel))
|
|
175
|
+
return;
|
|
176
|
+
if (categoryFilter && !categoryFilter.includes(mockCategory))
|
|
177
|
+
return;
|
|
178
|
+
const logEntry = {
|
|
179
|
+
timestamp: Date.now(),
|
|
180
|
+
level: mockLevel,
|
|
181
|
+
category: mockCategory,
|
|
182
|
+
message: `Real-time log ${logIndex++} from ${mockCategory}`,
|
|
183
|
+
metadata: {
|
|
184
|
+
requestId: plugins.uuid.v4(),
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
const logData = JSON.stringify(logEntry);
|
|
188
|
+
const encoder = new TextEncoder();
|
|
189
|
+
try {
|
|
190
|
+
await virtualStream.sendData(encoder.encode(logData));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Stream closed or errored — clean up to prevent interval leak
|
|
194
|
+
clearInterval(intervalId);
|
|
195
|
+
intervalId = null;
|
|
196
|
+
}
|
|
197
|
+
}, 2000); // Send a log every 2 seconds
|
|
198
|
+
// TODO: Hook into actual logger events
|
|
199
|
+
// logger.on('log', (logEntry) => {
|
|
200
|
+
// if (matchesCriteria(logEntry, level, service)) {
|
|
201
|
+
// virtualStream.sendData(formatLogEntry(logEntry));
|
|
202
|
+
// }
|
|
203
|
+
// });
|
|
204
|
+
};
|
|
205
|
+
const stop = () => {
|
|
206
|
+
if (intervalId) {
|
|
207
|
+
clearInterval(intervalId);
|
|
208
|
+
intervalId = null;
|
|
209
|
+
}
|
|
210
|
+
// TODO: Unhook from logger events
|
|
211
|
+
};
|
|
212
|
+
return { start, stop };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9ncy5oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvb3Bzc2VydmVyL2hhbmRsZXJzL2xvZ3MuaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV4RCxNQUFNLE9BQU8sV0FBVztJQUdGO0lBRmIsV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUU1RCxZQUFvQixZQUF1QjtRQUF2QixpQkFBWSxHQUFaLFlBQVksQ0FBVztRQUN6QywwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FDOUIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsZUFBZSxFQUNmLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDMUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUNuQyxPQUFPLENBQUMsS0FBSyxFQUNiLE9BQU8sQ0FBQyxRQUFRLEVBQ2hCLE9BQU8sQ0FBQyxLQUFLLElBQUksR0FBRyxFQUNwQixPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsRUFDbkIsT0FBTyxDQUFDLE1BQU0sRUFDZCxPQUFPLENBQUMsU0FBUyxDQUNsQixDQUFDO1lBRUYs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
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
export declare class RadiusHandler {
|
|
4
|
+
private opsServerRef;
|
|
5
|
+
typedrouter: plugins.typedrequest.TypedRouter;
|
|
6
|
+
constructor(opsServerRef: OpsServer);
|
|
7
|
+
private registerHandlers;
|
|
8
|
+
}
|