@serve.zone/dcrouter 5.0.2 → 5.0.3
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 +30539 -0
- package/dist_serve/bundle.js.map +7 -0
- package/dist_serve/index.html +1 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- 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 +125 -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/classes.dcrouter.d.ts +276 -0
- package/dist_ts/classes.dcrouter.js +1033 -0
- package/dist_ts/config/index.d.ts +1 -0
- package/dist_ts/config/index.js +3 -0
- package/dist_ts/config/validator.d.ts +104 -0
- package/dist_ts/config/validator.js +152 -0
- package/dist_ts/errors/base.errors.d.ts +224 -0
- package/dist_ts/errors/base.errors.js +320 -0
- package/dist_ts/errors/error-handler.d.ts +98 -0
- package/dist_ts/errors/error-handler.js +282 -0
- package/dist_ts/errors/error.codes.d.ts +115 -0
- package/dist_ts/errors/error.codes.js +136 -0
- package/dist_ts/errors/index.d.ts +54 -0
- package/dist_ts/errors/index.js +136 -0
- package/dist_ts/errors/reputation.errors.d.ts +183 -0
- package/dist_ts/errors/reputation.errors.js +292 -0
- package/dist_ts/index.d.ts +6 -0
- package/dist_ts/index.js +9 -0
- package/dist_ts/logger.d.ts +17 -0
- package/dist_ts/logger.js +76 -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 +112 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +446 -0
- package/dist_ts/monitoring/index.d.ts +1 -0
- package/dist_ts/monitoring/index.js +2 -0
- package/dist_ts/opsserver/classes.opsserver.d.ts +22 -0
- package/dist_ts/opsserver/classes.opsserver.js +56 -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/config.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/config.handler.js +67 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +12 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.js +219 -0
- package/dist_ts/opsserver/handlers/index.d.ts +7 -0
- package/dist_ts/opsserver/handlers/index.js +8 -0
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +122 -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/security.handler.d.ts +11 -0
- package/dist_ts/opsserver/handlers/security.handler.js +217 -0
- package/dist_ts/opsserver/handlers/stats.handler.d.ts +13 -0
- package/dist_ts/opsserver/handlers/stats.handler.js +366 -0
- package/dist_ts/opsserver/helpers/guards.d.ts +25 -0
- package/dist_ts/opsserver/helpers/guards.js +41 -0
- package/dist_ts/opsserver/index.d.ts +1 -0
- package/dist_ts/opsserver/index.js +2 -0
- package/dist_ts/paths.d.ts +14 -0
- package/dist_ts/paths.js +39 -0
- package/dist_ts/plugins.d.ts +78 -0
- package/dist_ts/plugins.js +112 -0
- package/dist_ts/radius/classes.accounting.manager.d.ts +218 -0
- package/dist_ts/radius/classes.accounting.manager.js +417 -0
- package/dist_ts/radius/classes.radius.server.d.ts +171 -0
- package/dist_ts/radius/classes.radius.server.js +385 -0
- package/dist_ts/radius/classes.vlan.manager.d.ts +128 -0
- package/dist_ts/radius/classes.vlan.manager.js +272 -0
- package/dist_ts/radius/index.d.ts +13 -0
- package/dist_ts/radius/index.js +14 -0
- package/dist_ts/security/classes.contentscanner.d.ts +160 -0
- package/dist_ts/security/classes.contentscanner.js +637 -0
- package/dist_ts/security/classes.ipreputationchecker.d.ts +150 -0
- package/dist_ts/security/classes.ipreputationchecker.js +512 -0
- package/dist_ts/security/classes.securitylogger.d.ts +140 -0
- package/dist_ts/security/classes.securitylogger.js +235 -0
- package/dist_ts/security/index.d.ts +3 -0
- package/dist_ts/security/index.js +4 -0
- package/dist_ts/sms/classes.smsservice.d.ts +15 -0
- package/dist_ts/sms/classes.smsservice.js +72 -0
- package/dist_ts/sms/config/sms.config.d.ts +93 -0
- package/dist_ts/sms/config/sms.config.js +2 -0
- package/dist_ts/sms/config/sms.schema.d.ts +5 -0
- package/dist_ts/sms/config/sms.schema.js +121 -0
- package/dist_ts/sms/index.d.ts +1 -0
- package/dist_ts/sms/index.js +2 -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/data/auth.d.ts +8 -0
- package/dist_ts_interfaces/data/auth.js +2 -0
- package/dist_ts_interfaces/data/index.d.ts +2 -0
- package/dist_ts_interfaces/data/index.js +3 -0
- package/dist_ts_interfaces/data/stats.d.ts +120 -0
- package/dist_ts_interfaces/data/stats.js +2 -0
- package/{ts_interfaces/index.ts → dist_ts_interfaces/index.d.ts} +1 -5
- package/dist_ts_interfaces/index.js +8 -0
- package/{ts_interfaces/plugins.ts → dist_ts_interfaces/plugins.d.ts} +1 -5
- package/dist_ts_interfaces/plugins.js +4 -0
- package/dist_ts_interfaces/requests/admin.d.ts +31 -0
- package/dist_ts_interfaces/requests/admin.js +3 -0
- package/dist_ts_interfaces/requests/combined.stats.d.ts +24 -0
- package/dist_ts_interfaces/requests/combined.stats.js +2 -0
- package/dist_ts_interfaces/requests/config.d.ts +13 -0
- package/dist_ts_interfaces/requests/config.js +3 -0
- package/dist_ts_interfaces/requests/email-ops.d.ts +139 -0
- package/dist_ts_interfaces/requests/email-ops.js +3 -0
- package/{ts_interfaces/requests/index.ts → dist_ts_interfaces/requests/index.d.ts} +1 -1
- package/dist_ts_interfaces/requests/index.js +8 -0
- package/dist_ts_interfaces/requests/logs.d.ts +34 -0
- package/dist_ts_interfaces/requests/logs.js +4 -0
- package/dist_ts_interfaces/requests/radius.d.ts +268 -0
- package/dist_ts_interfaces/requests/radius.js +3 -0
- package/dist_ts_interfaces/requests/stats.d.ts +131 -0
- package/dist_ts_interfaces/requests/stats.js +4 -0
- package/dist_ts_web/00_commitinfo_data.d.ts +8 -0
- package/dist_ts_web/00_commitinfo_data.js +9 -0
- package/dist_ts_web/appstate.d.ts +96 -0
- package/dist_ts_web/appstate.js +587 -0
- package/dist_ts_web/elements/index.d.ts +8 -0
- package/dist_ts_web/elements/index.js +9 -0
- package/dist_ts_web/elements/ops-dashboard.d.ts +23 -0
- package/dist_ts_web/elements/ops-dashboard.js +271 -0
- package/dist_ts_web/elements/ops-view-config.d.ts +17 -0
- package/dist_ts_web/elements/ops-view-config.js +414 -0
- package/dist_ts_web/elements/ops-view-emails.d.ts +44 -0
- package/dist_ts_web/elements/ops-view-emails.js +880 -0
- package/dist_ts_web/elements/ops-view-logs.d.ts +13 -0
- package/dist_ts_web/elements/ops-view-logs.js +249 -0
- package/dist_ts_web/elements/ops-view-network.d.ts +65 -0
- package/dist_ts_web/elements/ops-view-network.js +579 -0
- package/dist_ts_web/elements/ops-view-overview.d.ts +14 -0
- package/dist_ts_web/elements/ops-view-overview.js +344 -0
- package/dist_ts_web/elements/ops-view-security.d.ts +21 -0
- package/dist_ts_web/elements/ops-view-security.js +568 -0
- package/dist_ts_web/elements/shared/css.d.ts +1 -0
- package/dist_ts_web/elements/shared/css.js +10 -0
- package/dist_ts_web/elements/shared/index.d.ts +2 -0
- package/dist_ts_web/elements/shared/index.js +3 -0
- package/dist_ts_web/elements/shared/ops-sectionheading.d.ts +5 -0
- package/dist_ts_web/elements/shared/ops-sectionheading.js +82 -0
- package/dist_ts_web/index.d.ts +1 -0
- package/dist_ts_web/index.js +10 -0
- package/dist_ts_web/plugins.d.ts +4 -0
- package/dist_ts_web/plugins.js +7 -0
- package/dist_ts_web/router.d.ts +25 -0
- package/dist_ts_web/router.js +165 -0
- package/package.json +14 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/.dockerignore +0 -1
- package/.gitea/workflows/docker_nottags.yaml +0 -71
- package/.gitea/workflows/docker_tags.yaml +0 -106
- package/.playwright-mcp/dcrouter-scrollbar-issue.png +0 -0
- package/.playwright-mcp/page-2026-02-01T23-10-23-737Z.png +0 -0
- package/.playwright-mcp/page-2026-02-01T23-11-19-449Z.png +0 -0
- package/.playwright-mcp/page-2026-02-01T23-12-03-126Z.png +0 -0
- package/.playwright-mcp/page-2026-02-01T23-12-15-576Z.png +0 -0
- package/.vscode/launch.json +0 -11
- package/.vscode/settings.json +0 -26
- package/Dockerfile +0 -46
- package/changelog.md +0 -350
- package/cli.child.js +0 -4
- package/cli.child.ts +0 -4
- package/cli.ts.js +0 -5
- package/html/index.html +0 -121
- package/test/readme.md +0 -443
- package/test/test.config.md +0 -175
- package/test/test.contentscanner.ts +0 -265
- package/test/test.dcrouter.email.ts +0 -159
- package/test/test.dns-server-config.ts +0 -140
- package/test/test.dns-socket-handler.ts +0 -148
- package/test/test.errors.ts +0 -274
- package/test/test.ipreputationchecker.ts +0 -179
- package/test/test.jwt-auth.ts +0 -131
- package/test/test.opsserver-api.ts +0 -84
- package/test/test.protected-endpoint.ts +0 -120
- package/test/test.storagemanager.ts +0 -289
- package/test_watch/devserver.ts +0 -35
- package/ts_interfaces/data/auth.ts +0 -8
- package/ts_interfaces/data/index.ts +0 -2
- package/ts_interfaces/data/stats.ts +0 -131
- package/ts_interfaces/readme.md +0 -205
- package/ts_interfaces/requests/admin.ts +0 -46
- package/ts_interfaces/requests/combined.stats.ts +0 -25
- package/ts_interfaces/requests/config.ts +0 -18
- package/ts_interfaces/requests/email-ops.ts +0 -239
- package/ts_interfaces/requests/logs.ts +0 -44
- package/ts_interfaces/requests/radius.ts +0 -329
- package/ts_interfaces/requests/stats.ts +0 -162
- package/ts_interfaces/tspublish.json +0 -3
- package/tsconfig.json +0 -12
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
2
|
-
import { ContentScanner, ThreatCategory } from '../ts/security/classes.contentscanner.js';
|
|
3
|
-
import { Email } from '@push.rocks/smartmta';
|
|
4
|
-
|
|
5
|
-
// Test instantiation
|
|
6
|
-
tap.test('ContentScanner - should be instantiable', async () => {
|
|
7
|
-
const scanner = ContentScanner.getInstance({
|
|
8
|
-
scanBody: true,
|
|
9
|
-
scanSubject: true,
|
|
10
|
-
scanAttachments: true
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
expect(scanner).toBeTruthy();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
// Test singleton pattern
|
|
17
|
-
tap.test('ContentScanner - should use singleton pattern', async () => {
|
|
18
|
-
const scanner1 = ContentScanner.getInstance();
|
|
19
|
-
const scanner2 = ContentScanner.getInstance();
|
|
20
|
-
|
|
21
|
-
// Both instances should be the same object
|
|
22
|
-
expect(scanner1 === scanner2).toEqual(true);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// Test clean email can be correctly distinguished from high-risk email
|
|
26
|
-
tap.test('ContentScanner - should distinguish between clean and suspicious emails', async () => {
|
|
27
|
-
// Create an instance with a higher minimum threat score
|
|
28
|
-
const scanner = new ContentScanner({
|
|
29
|
-
minThreatScore: 50 // Higher threshold to consider clean
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// Create a truly clean email with no potentially sensitive data patterns
|
|
33
|
-
const cleanEmail = new Email({
|
|
34
|
-
from: 'sender@example.com',
|
|
35
|
-
to: 'recipient@example.com',
|
|
36
|
-
subject: 'Project Update',
|
|
37
|
-
text: 'The project is on track. Let me know if you have questions.',
|
|
38
|
-
html: '<p>The project is on track. Let me know if you have questions.</p>'
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Create a highly suspicious email
|
|
42
|
-
const suspiciousEmail = new Email({
|
|
43
|
-
from: 'admin@bank-fake.com',
|
|
44
|
-
to: 'victim@example.com',
|
|
45
|
-
subject: 'URGENT: Your account needs verification now!',
|
|
46
|
-
text: 'Click here to verify your account or it will be suspended: https://bit.ly/12345',
|
|
47
|
-
html: '<p>Click here to verify your account or it will be suspended: <a href="https://bit.ly/12345">click here</a></p>'
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Test both emails
|
|
51
|
-
const cleanResult = await scanner.scanEmail(cleanEmail);
|
|
52
|
-
const suspiciousResult = await scanner.scanEmail(suspiciousEmail);
|
|
53
|
-
|
|
54
|
-
console.log('Clean vs Suspicious results:', {
|
|
55
|
-
cleanScore: cleanResult.threatScore,
|
|
56
|
-
suspiciousScore: suspiciousResult.threatScore
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Verify the scanner can distinguish between them
|
|
60
|
-
// Suspicious email should have a significantly higher score
|
|
61
|
-
expect(suspiciousResult.threatScore > cleanResult.threatScore + 40).toEqual(true);
|
|
62
|
-
|
|
63
|
-
// Verify clean email scans all expected elements
|
|
64
|
-
expect(cleanResult.scannedElements.length > 0).toEqual(true);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Test phishing detection in subject
|
|
68
|
-
tap.test('ContentScanner - should detect phishing in subject', async () => {
|
|
69
|
-
// Create a dedicated scanner for this test
|
|
70
|
-
const scanner = new ContentScanner({
|
|
71
|
-
scanSubject: true,
|
|
72
|
-
scanBody: true,
|
|
73
|
-
scanAttachments: false,
|
|
74
|
-
customRules: []
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const email = new Email({
|
|
78
|
-
from: 'security@bank-account-verify.com',
|
|
79
|
-
to: 'victim@example.com',
|
|
80
|
-
subject: 'URGENT: Verify your bank account details immediately',
|
|
81
|
-
text: 'Your account will be suspended. Please verify your details.',
|
|
82
|
-
html: '<p>Your account will be suspended. Please verify your details.</p>'
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const result = await scanner.scanEmail(email);
|
|
86
|
-
|
|
87
|
-
console.log('Phishing email scan result:', result);
|
|
88
|
-
|
|
89
|
-
// We only care that it detected something suspicious
|
|
90
|
-
expect(result.threatScore >= 20).toEqual(true);
|
|
91
|
-
|
|
92
|
-
// Check if any threat was detected (specific type may vary)
|
|
93
|
-
expect(result.threatType).toBeTruthy();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Test malware indicators in body
|
|
97
|
-
tap.test('ContentScanner - should detect malware indicators in body', async () => {
|
|
98
|
-
const scanner = ContentScanner.getInstance();
|
|
99
|
-
|
|
100
|
-
const email = new Email({
|
|
101
|
-
from: 'invoice@company.com',
|
|
102
|
-
to: 'recipient@example.com',
|
|
103
|
-
subject: 'Your invoice',
|
|
104
|
-
text: 'Please see the attached invoice. You need to enable macros to view this document properly.',
|
|
105
|
-
html: '<p>Please see the attached invoice. You need to enable macros to view this document properly.</p>'
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const result = await scanner.scanEmail(email);
|
|
109
|
-
|
|
110
|
-
expect(result.isClean).toEqual(false);
|
|
111
|
-
expect(result.threatType === ThreatCategory.MALWARE || result.threatType).toBeTruthy();
|
|
112
|
-
expect(result.threatScore >= 30).toEqual(true);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Test suspicious link detection
|
|
116
|
-
tap.test('ContentScanner - should detect suspicious links', async () => {
|
|
117
|
-
const scanner = ContentScanner.getInstance();
|
|
118
|
-
|
|
119
|
-
const email = new Email({
|
|
120
|
-
from: 'newsletter@example.com',
|
|
121
|
-
to: 'recipient@example.com',
|
|
122
|
-
subject: 'Weekly Newsletter',
|
|
123
|
-
text: 'Check our latest offer at https://bit.ly/2x3F5 and https://t.co/abc123',
|
|
124
|
-
html: '<p>Check our latest offer at <a href="https://bit.ly/2x3F5">here</a> and <a href="https://t.co/abc123">here</a></p>'
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
const result = await scanner.scanEmail(email);
|
|
128
|
-
|
|
129
|
-
expect(result.isClean).toEqual(false);
|
|
130
|
-
expect(result.threatType).toEqual(ThreatCategory.SUSPICIOUS_LINK);
|
|
131
|
-
expect(result.threatScore >= 30).toEqual(true);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// Test script injection detection
|
|
135
|
-
tap.test('ContentScanner - should detect script injection', async () => {
|
|
136
|
-
const scanner = ContentScanner.getInstance();
|
|
137
|
-
|
|
138
|
-
const email = new Email({
|
|
139
|
-
from: 'newsletter@example.com',
|
|
140
|
-
to: 'recipient@example.com',
|
|
141
|
-
subject: 'Newsletter',
|
|
142
|
-
text: 'Check our website',
|
|
143
|
-
html: '<p>Check our website</p><script>document.cookie="session="+localStorage.getItem("token");</script>'
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
const result = await scanner.scanEmail(email);
|
|
147
|
-
|
|
148
|
-
expect(result.isClean).toEqual(false);
|
|
149
|
-
expect(result.threatType).toEqual(ThreatCategory.XSS);
|
|
150
|
-
expect(result.threatScore >= 40).toEqual(true);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
// Test executable attachment detection
|
|
154
|
-
tap.test('ContentScanner - should detect executable attachments', async () => {
|
|
155
|
-
const scanner = ContentScanner.getInstance();
|
|
156
|
-
|
|
157
|
-
const email = new Email({
|
|
158
|
-
from: 'sender@example.com',
|
|
159
|
-
to: 'recipient@example.com',
|
|
160
|
-
subject: 'Software Update',
|
|
161
|
-
text: 'Please install the attached software update.',
|
|
162
|
-
attachments: [{
|
|
163
|
-
filename: 'update.exe',
|
|
164
|
-
content: Buffer.from('MZ...fake executable content...'),
|
|
165
|
-
contentType: 'application/octet-stream'
|
|
166
|
-
}]
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
const result = await scanner.scanEmail(email);
|
|
170
|
-
|
|
171
|
-
expect(result.isClean).toEqual(false);
|
|
172
|
-
expect(result.threatType).toEqual(ThreatCategory.EXECUTABLE);
|
|
173
|
-
expect(result.threatScore >= 70).toEqual(true);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
// Test macro document detection
|
|
177
|
-
tap.test('ContentScanner - should detect macro documents', async () => {
|
|
178
|
-
// Create a mock Office document with macro indicators
|
|
179
|
-
const fakeDocContent = Buffer.from('Document content...vbaProject.bin...Auto_Open...DocumentOpen...Microsoft VBA...');
|
|
180
|
-
|
|
181
|
-
const scanner = ContentScanner.getInstance();
|
|
182
|
-
|
|
183
|
-
const email = new Email({
|
|
184
|
-
from: 'sender@example.com',
|
|
185
|
-
to: 'recipient@example.com',
|
|
186
|
-
subject: 'Financial Report',
|
|
187
|
-
text: 'Please review the attached financial report.',
|
|
188
|
-
attachments: [{
|
|
189
|
-
filename: 'report.docm',
|
|
190
|
-
content: fakeDocContent,
|
|
191
|
-
contentType: 'application/vnd.ms-word.document.macroEnabled.12'
|
|
192
|
-
}]
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const result = await scanner.scanEmail(email);
|
|
196
|
-
|
|
197
|
-
expect(result.isClean).toEqual(false);
|
|
198
|
-
expect(result.threatType).toEqual(ThreatCategory.MALICIOUS_MACRO);
|
|
199
|
-
expect(result.threatScore >= 60).toEqual(true);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// Test compound threat detection (multiple indicators)
|
|
203
|
-
tap.test('ContentScanner - should detect compound threats', async () => {
|
|
204
|
-
const scanner = ContentScanner.getInstance();
|
|
205
|
-
|
|
206
|
-
const email = new Email({
|
|
207
|
-
from: 'security@bank-verify.com',
|
|
208
|
-
to: 'victim@example.com',
|
|
209
|
-
subject: 'URGENT: Verify your account details immediately',
|
|
210
|
-
text: 'Your account will be suspended unless you verify your details at https://bit.ly/2x3F5',
|
|
211
|
-
html: '<p>Your account will be suspended unless you verify your details <a href="https://bit.ly/2x3F5">here</a>.</p>',
|
|
212
|
-
attachments: [{
|
|
213
|
-
filename: 'verification.exe',
|
|
214
|
-
content: Buffer.from('MZ...fake executable content...'),
|
|
215
|
-
contentType: 'application/octet-stream'
|
|
216
|
-
}]
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const result = await scanner.scanEmail(email);
|
|
220
|
-
|
|
221
|
-
expect(result.isClean).toEqual(false);
|
|
222
|
-
expect(result.threatScore > 70).toEqual(true); // Should have a high score due to multiple threats
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// Test custom rules
|
|
226
|
-
tap.test('ContentScanner - should apply custom rules', async () => {
|
|
227
|
-
// Create a scanner with custom rules
|
|
228
|
-
const scanner = new ContentScanner({
|
|
229
|
-
customRules: [
|
|
230
|
-
{
|
|
231
|
-
pattern: /CUSTOM_PATTERN_FOR_TESTING/,
|
|
232
|
-
type: ThreatCategory.CUSTOM_RULE,
|
|
233
|
-
score: 50,
|
|
234
|
-
description: 'Custom pattern detected'
|
|
235
|
-
}
|
|
236
|
-
]
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const email = new Email({
|
|
240
|
-
from: 'sender@example.com',
|
|
241
|
-
to: 'recipient@example.com',
|
|
242
|
-
subject: 'Test Custom Rule',
|
|
243
|
-
text: 'This message contains CUSTOM_PATTERN_FOR_TESTING that should be detected.'
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
const result = await scanner.scanEmail(email);
|
|
247
|
-
|
|
248
|
-
expect(result.isClean).toEqual(false);
|
|
249
|
-
expect(result.threatType).toEqual(ThreatCategory.CUSTOM_RULE);
|
|
250
|
-
expect(result.threatScore >= 50).toEqual(true);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Test threat level classification
|
|
254
|
-
tap.test('ContentScanner - should classify threat levels correctly', async () => {
|
|
255
|
-
expect(ContentScanner.getThreatLevel(10)).toEqual('none');
|
|
256
|
-
expect(ContentScanner.getThreatLevel(25)).toEqual('low');
|
|
257
|
-
expect(ContentScanner.getThreatLevel(50)).toEqual('medium');
|
|
258
|
-
expect(ContentScanner.getThreatLevel(80)).toEqual('high');
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
tap.test('stop', async () => {
|
|
262
|
-
await tap.stopForcefully();
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
export default tap.start();
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
2
|
-
import * as plugins from '../ts/plugins.js';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
import { DcRouter, type IDcRouterOptions } from '../ts/classes.dcrouter.js';
|
|
6
|
-
import type { IUnifiedEmailServerOptions } from '@push.rocks/smartmta';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
tap.test('DcRouter class - Custom email port configuration', async () => {
|
|
10
|
-
// Define custom port mapping
|
|
11
|
-
const customPortMapping: Record<number, number> = {
|
|
12
|
-
25: 11025, // Custom SMTP port mapping
|
|
13
|
-
587: 11587, // Custom submission port mapping
|
|
14
|
-
465: 11465, // Custom SMTPS port mapping
|
|
15
|
-
2525: 12525 // Additional custom port
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// Create a custom email configuration using smartmta interfaces
|
|
19
|
-
const emailConfig: IUnifiedEmailServerOptions = {
|
|
20
|
-
ports: [25, 587, 465, 2525],
|
|
21
|
-
hostname: 'mail.example.com',
|
|
22
|
-
maxMessageSize: 50 * 1024 * 1024, // 50MB
|
|
23
|
-
domains: [
|
|
24
|
-
{
|
|
25
|
-
domain: 'example.com',
|
|
26
|
-
dnsMode: 'external-dns',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
domain: 'example.org',
|
|
30
|
-
dnsMode: 'external-dns',
|
|
31
|
-
}
|
|
32
|
-
],
|
|
33
|
-
routes: [
|
|
34
|
-
{
|
|
35
|
-
name: 'forward-example-com',
|
|
36
|
-
match: {
|
|
37
|
-
recipients: '*@example.com',
|
|
38
|
-
},
|
|
39
|
-
action: {
|
|
40
|
-
type: 'forward',
|
|
41
|
-
forward: {
|
|
42
|
-
host: 'mail1.example.com',
|
|
43
|
-
port: 25,
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: 'deliver-example-org',
|
|
49
|
-
match: {
|
|
50
|
-
recipients: '*@example.org',
|
|
51
|
-
},
|
|
52
|
-
action: {
|
|
53
|
-
type: 'deliver',
|
|
54
|
-
process: {
|
|
55
|
-
dkim: true,
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// Create DcRouter options with custom email port configuration
|
|
63
|
-
const options: IDcRouterOptions = {
|
|
64
|
-
emailConfig,
|
|
65
|
-
emailPortConfig: {
|
|
66
|
-
portMapping: customPortMapping,
|
|
67
|
-
portSettings: {
|
|
68
|
-
2525: {
|
|
69
|
-
terminateTls: false,
|
|
70
|
-
routeName: 'custom-smtp-route'
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
tls: {
|
|
75
|
-
contactEmail: 'test@example.com'
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// Create DcRouter instance
|
|
80
|
-
const router = new DcRouter(options);
|
|
81
|
-
|
|
82
|
-
// Verify the options are correctly set
|
|
83
|
-
expect(router.options.emailPortConfig).toBeTruthy();
|
|
84
|
-
expect(router.options.emailPortConfig!.portMapping).toEqual(customPortMapping);
|
|
85
|
-
|
|
86
|
-
// Test the generateEmailRoutes method
|
|
87
|
-
if (typeof (router as any)['generateEmailRoutes'] === 'function') {
|
|
88
|
-
const routes = (router as any)['generateEmailRoutes'](emailConfig);
|
|
89
|
-
|
|
90
|
-
// Verify that all ports are configured
|
|
91
|
-
expect(routes.length).toBeGreaterThan(0);
|
|
92
|
-
|
|
93
|
-
// Check the custom port configuration
|
|
94
|
-
const customPortRoute = routes.find((r: any) => {
|
|
95
|
-
const ports = r.match.ports;
|
|
96
|
-
return ports === 2525 || (Array.isArray(ports) && (ports as number[]).includes(2525));
|
|
97
|
-
});
|
|
98
|
-
expect(customPortRoute).toBeTruthy();
|
|
99
|
-
expect(customPortRoute?.name).toEqual('custom-smtp-route');
|
|
100
|
-
expect(customPortRoute?.action.targets[0].port).toEqual(12525);
|
|
101
|
-
|
|
102
|
-
// Check standard port mappings
|
|
103
|
-
const smtpRoute = routes.find((r: any) => {
|
|
104
|
-
const ports = r.match.ports;
|
|
105
|
-
return ports === 25 || (Array.isArray(ports) && (ports as number[]).includes(25));
|
|
106
|
-
});
|
|
107
|
-
expect(smtpRoute?.action.targets[0].port).toEqual(11025);
|
|
108
|
-
|
|
109
|
-
const submissionRoute = routes.find((r: any) => {
|
|
110
|
-
const ports = r.match.ports;
|
|
111
|
-
return ports === 587 || (Array.isArray(ports) && (ports as number[]).includes(587));
|
|
112
|
-
});
|
|
113
|
-
expect(submissionRoute?.action.targets[0].port).toEqual(11587);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
tap.test('DcRouter class - Email config with domains and routes', async () => {
|
|
118
|
-
// Create a basic email configuration
|
|
119
|
-
const emailConfig: IUnifiedEmailServerOptions = {
|
|
120
|
-
ports: [2525],
|
|
121
|
-
hostname: 'mail.example.com',
|
|
122
|
-
domains: [],
|
|
123
|
-
routes: []
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// Create DcRouter options
|
|
127
|
-
const options: IDcRouterOptions = {
|
|
128
|
-
emailConfig,
|
|
129
|
-
tls: {
|
|
130
|
-
contactEmail: 'test@example.com'
|
|
131
|
-
},
|
|
132
|
-
cacheConfig: {
|
|
133
|
-
enabled: false,
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
// Create DcRouter instance
|
|
138
|
-
const router = new DcRouter(options);
|
|
139
|
-
|
|
140
|
-
// Start the router to initialize email services
|
|
141
|
-
await router.start();
|
|
142
|
-
|
|
143
|
-
// Verify unified email server was initialized
|
|
144
|
-
expect(router.emailServer).toBeTruthy();
|
|
145
|
-
|
|
146
|
-
// Stop the router
|
|
147
|
-
await router.stop();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// Final clean-up test
|
|
151
|
-
tap.test('clean up after tests', async () => {
|
|
152
|
-
// No-op
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
tap.test('stop', async () => {
|
|
156
|
-
await tap.stopForcefully();
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
export default tap.start();
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Test DNS server configuration and record registration
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
8
|
-
import * as plugins from '../ts/plugins.js';
|
|
9
|
-
|
|
10
|
-
// Test DNS configuration
|
|
11
|
-
const testDnsConfig = {
|
|
12
|
-
udpPort: 5353, // Use non-privileged port for testing
|
|
13
|
-
httpsPort: 8443,
|
|
14
|
-
httpsKey: './test/fixtures/test-key.pem',
|
|
15
|
-
httpsCert: './test/fixtures/test-cert.pem',
|
|
16
|
-
dnssecZone: 'test.example.com',
|
|
17
|
-
records: [
|
|
18
|
-
{ name: 'test.example.com', type: 'A', value: '192.168.1.1' },
|
|
19
|
-
{ name: 'mail.test.example.com', type: 'A', value: '192.168.1.2' },
|
|
20
|
-
{ name: 'test.example.com', type: 'MX', value: '10 mail.test.example.com' },
|
|
21
|
-
{ name: 'test.example.com', type: 'TXT', value: 'v=spf1 a:mail.test.example.com ~all' },
|
|
22
|
-
{ name: 'test.example.com', type: 'NS', value: 'ns1.test.example.com' },
|
|
23
|
-
{ name: 'ns1.test.example.com', type: 'A', value: '192.168.1.1' }
|
|
24
|
-
]
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
tap.test('DNS server configuration - should extract records correctly', async () => {
|
|
28
|
-
const { records, ...dnsServerOptions } = testDnsConfig;
|
|
29
|
-
|
|
30
|
-
expect(dnsServerOptions.udpPort).toEqual(5353);
|
|
31
|
-
expect(dnsServerOptions.httpsPort).toEqual(8443);
|
|
32
|
-
expect(dnsServerOptions.dnssecZone).toEqual('test.example.com');
|
|
33
|
-
expect(records).toBeArray();
|
|
34
|
-
expect(records.length).toEqual(6);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
tap.test('DNS server configuration - should handle record parsing', async () => {
|
|
38
|
-
const parseDnsRecordData = (type: string, value: string): any => {
|
|
39
|
-
switch (type) {
|
|
40
|
-
case 'A':
|
|
41
|
-
return value;
|
|
42
|
-
case 'MX':
|
|
43
|
-
const [priority, exchange] = value.split(' ');
|
|
44
|
-
return { priority: parseInt(priority), exchange };
|
|
45
|
-
case 'TXT':
|
|
46
|
-
return value;
|
|
47
|
-
case 'NS':
|
|
48
|
-
return value;
|
|
49
|
-
default:
|
|
50
|
-
return value;
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// Test A record parsing
|
|
55
|
-
const aRecord = parseDnsRecordData('A', '192.168.1.1');
|
|
56
|
-
expect(aRecord).toEqual('192.168.1.1');
|
|
57
|
-
|
|
58
|
-
// Test MX record parsing
|
|
59
|
-
const mxRecord = parseDnsRecordData('MX', '10 mail.test.example.com');
|
|
60
|
-
expect(mxRecord).toHaveProperty('priority', 10);
|
|
61
|
-
expect(mxRecord).toHaveProperty('exchange', 'mail.test.example.com');
|
|
62
|
-
|
|
63
|
-
// Test TXT record parsing
|
|
64
|
-
const txtRecord = parseDnsRecordData('TXT', 'v=spf1 a:mail.test.example.com ~all');
|
|
65
|
-
expect(txtRecord).toEqual('v=spf1 a:mail.test.example.com ~all');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
tap.test('DNS server configuration - should group records by domain', async () => {
|
|
69
|
-
const records = testDnsConfig.records;
|
|
70
|
-
const recordsByDomain = new Map<string, typeof records>();
|
|
71
|
-
|
|
72
|
-
for (const record of records) {
|
|
73
|
-
const pattern = record.name.includes('*') ? record.name : `*.${record.name}`;
|
|
74
|
-
if (!recordsByDomain.has(pattern)) {
|
|
75
|
-
recordsByDomain.set(pattern, []);
|
|
76
|
-
}
|
|
77
|
-
recordsByDomain.get(pattern)!.push(record);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Check grouping
|
|
81
|
-
expect(recordsByDomain.size).toBeGreaterThan(0);
|
|
82
|
-
|
|
83
|
-
// Verify each group has records
|
|
84
|
-
for (const [pattern, domainRecords] of recordsByDomain) {
|
|
85
|
-
expect(domainRecords.length).toBeGreaterThan(0);
|
|
86
|
-
console.log(`Pattern: ${pattern}, Records: ${domainRecords.length}`);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
tap.test('DNS server configuration - should extract unique record types', async () => {
|
|
91
|
-
const records = testDnsConfig.records;
|
|
92
|
-
const recordTypes = [...new Set(records.map(r => r.type))];
|
|
93
|
-
|
|
94
|
-
expect(recordTypes).toContain('A');
|
|
95
|
-
expect(recordTypes).toContain('MX');
|
|
96
|
-
expect(recordTypes).toContain('TXT');
|
|
97
|
-
expect(recordTypes).toContain('NS');
|
|
98
|
-
|
|
99
|
-
console.log('Unique record types:', recordTypes.join(', '));
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
tap.test('DNS server - mock handler registration', async () => {
|
|
103
|
-
// Mock DNS server for testing
|
|
104
|
-
const mockDnsServer = {
|
|
105
|
-
handlers: new Map<string, any>(),
|
|
106
|
-
registerHandler: function(pattern: string, types: string[], handler: Function) {
|
|
107
|
-
this.handlers.set(pattern, { types, handler });
|
|
108
|
-
console.log(`Registered handler for pattern: ${pattern}, types: ${types.join(', ')}`);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
// Simulate record registration
|
|
113
|
-
const records = testDnsConfig.records;
|
|
114
|
-
const recordsByDomain = new Map<string, typeof records>();
|
|
115
|
-
|
|
116
|
-
for (const record of records) {
|
|
117
|
-
const pattern = record.name.includes('*') ? record.name : `*.${record.name}`;
|
|
118
|
-
if (!recordsByDomain.has(pattern)) {
|
|
119
|
-
recordsByDomain.set(pattern, []);
|
|
120
|
-
}
|
|
121
|
-
recordsByDomain.get(pattern)!.push(record);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Register handlers
|
|
125
|
-
for (const [domainPattern, domainRecords] of recordsByDomain) {
|
|
126
|
-
const recordTypes = [...new Set(domainRecords.map(r => r.type))];
|
|
127
|
-
mockDnsServer.registerHandler(domainPattern, recordTypes, (question: any) => {
|
|
128
|
-
const matchingRecord = domainRecords.find(
|
|
129
|
-
r => r.name === question.name && r.type === question.type
|
|
130
|
-
);
|
|
131
|
-
return matchingRecord || null;
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
expect(mockDnsServer.handlers.size).toBeGreaterThan(0);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
tap.start({
|
|
139
|
-
throwOnError: true
|
|
140
|
-
});
|