@serve.zone/dcrouter 17.1.4 → 17.1.6
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/deno.json +1 -1
- package/dist_serve/bundle.js +559 -559
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.js +9 -3
- package/dist_ts/db/documents/classes.ip-intelligence.doc.d.ts +10 -0
- package/dist_ts/db/documents/classes.ip-intelligence.doc.js +63 -1
- package/dist_ts/dns/classes.dns-server-runtime.d.ts +1 -0
- package/dist_ts/dns/classes.dns-server-runtime.js +8 -4
- package/dist_ts/dns/manager.dns.js +23 -6
- package/dist_ts/email/classes.email-domain.manager.js +27 -15
- package/dist_ts/email/classes.mail-dns-sync.d.ts +19 -2
- package/dist_ts/email/classes.mail-dns-sync.js +158 -32
- package/dist_ts/email/index.d.ts +1 -0
- package/dist_ts/email/index.js +2 -1
- package/dist_ts/email/mail-dns-status.d.ts +5 -0
- package/dist_ts/email/mail-dns-status.js +31 -0
- package/dist_ts/monitoring/classes.metricscache.d.ts +2 -0
- package/dist_ts/monitoring/classes.metricscache.js +28 -6
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +10 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +99 -31
- package/dist_ts/opsserver/handlers/security.handler.js +24 -6
- package/dist_ts/opsserver/handlers/stats.handler.js +2 -3
- package/dist_ts/remoteingress/classes.hub-lifecycle.js +2 -2
- package/dist_ts/security/classes.security-policy-manager.d.ts +17 -0
- package/dist_ts/security/classes.security-policy-manager.js +171 -26
- package/dist_ts_interfaces/requests/stats.d.ts +7 -0
- package/dist_ts_migrations/index.js +395 -9
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate/network.js +11 -2
- package/dist_ts_web/appstate/ui.js +1 -8
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +11 -2
- package/ts/db/documents/classes.ip-intelligence.doc.ts +75 -0
- package/ts/dns/classes.dns-server-runtime.ts +9 -3
- package/ts/dns/manager.dns.ts +22 -5
- package/ts/email/classes.email-domain.manager.ts +23 -16
- package/ts/email/classes.mail-dns-sync.ts +172 -38
- package/ts/email/index.ts +1 -0
- package/ts/email/mail-dns-status.ts +35 -0
- package/ts/monitoring/classes.metricscache.ts +36 -8
- package/ts/monitoring/classes.metricsmanager.ts +113 -32
- package/ts/opsserver/handlers/security.handler.ts +35 -6
- package/ts/opsserver/handlers/stats.handler.ts +1 -2
- package/ts/remoteingress/classes.hub-lifecycle.ts +3 -1
- package/ts/security/classes.security-policy-manager.ts +193 -26
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate/network.ts +12 -1
- package/ts_web/appstate/ui.ts +0 -9
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/dcrouter',
|
|
6
|
-
version: '17.1.
|
|
6
|
+
version: '17.1.6',
|
|
7
7
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViLzAwX2NvbW1pdGluZm9fZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixJQUFJLEVBQUUsc0JBQXNCO0lBQzVCLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLFdBQVcsRUFBRSwwRUFBMEU7Q0FDeEYsQ0FBQSJ9
|
|
@@ -3,6 +3,8 @@ import * as interfaces from '../../dist_ts_interfaces/index.js';
|
|
|
3
3
|
import { appState } from './shared.js';
|
|
4
4
|
import { getActionContext } from './login.js';
|
|
5
5
|
import { runBackgroundRefresh } from './shared.js';
|
|
6
|
+
const IP_INTELLIGENCE_REFRESH_INTERVAL_MS = 60_000;
|
|
7
|
+
let lastIpIntelligenceRefreshAt = 0;
|
|
6
8
|
export const networkStatePart = await appState.getStatePart('network', {
|
|
7
9
|
connections: [],
|
|
8
10
|
connectionsByIP: {},
|
|
@@ -25,9 +27,16 @@ export const networkStatePart = await appState.getStatePart('network', {
|
|
|
25
27
|
error: null,
|
|
26
28
|
}, 'soft');
|
|
27
29
|
export function refreshNetworkIpIntelligence(identity, ipAddresses) {
|
|
28
|
-
const ips = [...new Set(ipAddresses.filter(Boolean))]
|
|
30
|
+
const ips = [...new Set(ipAddresses.map((ip) => ip.trim()).filter(Boolean))]
|
|
31
|
+
.sort()
|
|
32
|
+
.slice(0, 100);
|
|
29
33
|
if (ips.length === 0)
|
|
30
34
|
return;
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
if (now - lastIpIntelligenceRefreshAt < IP_INTELLIGENCE_REFRESH_INTERVAL_MS) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
lastIpIntelligenceRefreshAt = now;
|
|
31
40
|
runBackgroundRefresh('networkIpIntelligence', 'IP intelligence refresh failed:', async () => {
|
|
32
41
|
const intelligenceRequest = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'listIpIntelligence');
|
|
33
42
|
const intelligenceResponse = await intelligenceRequest.fire({
|
|
@@ -119,4 +128,4 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
|
|
|
119
128
|
}
|
|
120
129
|
});
|
|
121
130
|
// ============================================================================
|
|
122
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
131
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29yay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzX3dlYi9hcHBzdGF0ZS9uZXR3b3JrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sOEJBQThCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRW5ELE1BQU0sbUNBQW1DLEdBQUcsTUFBTSxDQUFDO0FBQ25ELElBQUksMkJBQTJCLEdBQUcsQ0FBQyxDQUFDO0FBd0JwQyxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLFFBQVEsQ0FBQyxZQUFZLENBQ3pELFNBQVMsRUFDVDtJQUNFLFdBQVcsRUFBRSxFQUFFO0lBQ2YsZUFBZSxFQUFFLEVBQUU7SUFDbkIsY0FBYyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLENBQUMsRUFBRTtJQUM3RCxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUU7SUFDN0IsTUFBTSxFQUFFLEVBQUU7SUFDVixpQkFBaUIsRUFBRSxFQUFFO0lBQ3JCLE9BQU8sRUFBRSxFQUFFO0lBQ1gsY0FBYyxFQUFFLEVBQUU7SUFDbEIsY0FBYyxFQUFFLEVBQUU7SUFDbEIsY0FBYyxFQUFFLEVBQUU7SUFDbEIsaUJBQWlCLEVBQUUsRUFBRTtJQUNyQixpQkFBaUIsRUFBRSxDQUFDO0lBQ3BCLGFBQWEsRUFBRSxDQUFDO0lBQ2hCLFFBQVEsRUFBRSxFQUFFO0lBQ1osaUJBQWlCLEVBQUUsSUFBSTtJQUN2QixnQkFBZ0IsRUFBRSxJQUFJO0lBQ3RCLFdBQVcsRUFBRSxD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
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { appState } from './shared.js';
|
|
2
|
-
import { networkStatePart, fetchNetworkStatsAction } from './network.js';
|
|
3
2
|
import { certificateStatePart, fetchCertificateOverviewAction } from './certificates.js';
|
|
4
3
|
// Determine initial view from URL path
|
|
5
4
|
const getInitialView = () => {
|
|
@@ -34,12 +33,6 @@ export const toggleAutoRefreshAction = uiStatePart.createAction(async (statePart
|
|
|
34
33
|
// Set Active View Action
|
|
35
34
|
export const setActiveViewAction = uiStatePart.createAction(async (statePartArg, viewName) => {
|
|
36
35
|
const currentState = statePartArg.getState();
|
|
37
|
-
// If switching to network view, ensure we fetch network data
|
|
38
|
-
if (viewName === 'network' && currentState.activeView !== 'network') {
|
|
39
|
-
setTimeout(() => {
|
|
40
|
-
networkStatePart.dispatchAction(fetchNetworkStatsAction, null);
|
|
41
|
-
}, 100);
|
|
42
|
-
}
|
|
43
36
|
// If switching to the Domains group, ensure we fetch certificate data
|
|
44
37
|
// (Certificates is a subview of Domains).
|
|
45
38
|
if (viewName === 'domains' && currentState.activeView !== 'domains') {
|
|
@@ -52,4 +45,4 @@ export const setActiveViewAction = uiStatePart.createAction(async (statePartArg,
|
|
|
52
45
|
activeView: viewName,
|
|
53
46
|
};
|
|
54
47
|
});
|
|
55
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvYXBwc3RhdGUvdWkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQVd6Rix1Q0FBdUM7QUFDdkMsTUFBTSxjQUFjLEdBQUcsR0FBVyxFQUFFO0lBQ2xDLE1BQU0sSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM1RSxNQUFNLFVBQVUsR0FBRyxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzdGLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pELE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QixPQUFPLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0FBQ3ZELENBQUMsQ0FBQztBQUVGLCtEQUErRDtBQUMvRCxNQUFNLGlCQUFpQixHQUFHLEdBQWtCLEVBQUU7SUFDNUMsTUFBTSxJQUFJLEdBQUcsT0FBTyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0lBQzVFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pELE9BQU8sUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQztBQUM3QixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsWUFBWSxDQUNwRCxJQUFJLEVBQ0o7SUFDRSxVQUFVLEVBQUUsY0FBYyxFQUFFO0lBQzVCLGFBQWEsRUFBRSxpQkFBaUIsRUFBRTtJQUNsQyxnQkFBZ0IsRUFBRSxLQUFLO0lBQ3ZCLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLGVBQWUsRUFBRSxJQUFJLEVBQUUsV0FBVztJQUNsQyxLQUFLLEVBQUUsT0FBTztDQUNmLENBQ0YsQ0FBQztBQUVGLDZCQUE2QjtBQUM3QixNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxXQUFXLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxZQUFZLEVBQXFCLEVBQUU7SUFDeEcsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBQzlDLE9BQU87UUFDTCxHQUFHLFlBQVk7UUFDZixXQUFXLEVBQUUsQ0FBQyxZQUFZLENBQUMsV0FBVztLQUN2QyxDQUFDO0FBQ0osQ0FBQyxDQUFDLENBQUM7QUFFSCx5QkFBeUI7QUFDekIsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsV0FBVyxDQUFDLFlBQVksQ0FBUyxLQUFLLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBcUIsRUFBRTtJQUN0SCxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFHLENBQUM7SUFFOUMsc0VBQXNFO0lBQ3RFLDBDQUEwQztJQUMxQyxJQUFJLFFBQVEsS0FBSyxTQUFTLElBQUksWUFBWSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNwRSxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2Qsb0JBQW9CLENBQUMsY0FBYyxDQUFDLDhCQUE4QixFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzVFLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNWLENBQUM7SUFFRCxPQUFPO1FBQ0wsR0FBRyxZQUFZO1FBQ2YsVUFBVSxFQUFFLFFBQVE7S0FDckIsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/dcrouter",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "17.1.
|
|
4
|
+
"version": "17.1.6",
|
|
5
5
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@push.rocks/smartbucket": "^4.6.1",
|
|
41
41
|
"@push.rocks/smartchallenge": "^1.1.0",
|
|
42
42
|
"@push.rocks/smartdata": "^7.3.1",
|
|
43
|
-
"@push.rocks/smartdb": "^2.13.
|
|
43
|
+
"@push.rocks/smartdb": "^2.13.2",
|
|
44
44
|
"@push.rocks/smartdns": "^7.12.1",
|
|
45
45
|
"@push.rocks/smartfs": "^1.6.0",
|
|
46
46
|
"@push.rocks/smartguard": "^3.1.2",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@push.rocks/smartnetwork": "^4.8.0",
|
|
54
54
|
"@push.rocks/smartpath": "^6.0.0",
|
|
55
55
|
"@push.rocks/smartpromise": "^4.2.4",
|
|
56
|
-
"@push.rocks/smartproxy": "^27.
|
|
56
|
+
"@push.rocks/smartproxy": "^27.18.0",
|
|
57
57
|
"@push.rocks/smartradius": "^1.3.0",
|
|
58
58
|
"@push.rocks/smartrequest": "^5.0.4",
|
|
59
59
|
"@push.rocks/smartrx": "^3.0.12",
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.dcrouter.ts
CHANGED
|
@@ -590,7 +590,9 @@ export class DcRouter {
|
|
|
590
590
|
.withStart(async () => {
|
|
591
591
|
this.remoteIngressManager = new RemoteIngressManager();
|
|
592
592
|
this.remoteIngressManager.setHubPublicIps([this.options.publicIp]);
|
|
593
|
-
this.remoteIngressManager.setOnEdgesChanged((reason) =>
|
|
593
|
+
this.remoteIngressManager.setOnEdgesChanged((reason) => (
|
|
594
|
+
this.mailDnsSync.requestEdgeEligibilityCheck(reason)
|
|
595
|
+
));
|
|
594
596
|
await this.remoteIngressManager.initialize();
|
|
595
597
|
})
|
|
596
598
|
.withStop(async () => {
|
|
@@ -816,10 +818,17 @@ export class DcRouter {
|
|
|
816
818
|
// Mail DNS reconciliation starts last: it needs persistence, provider
|
|
817
819
|
// state, the SMTP DKIM creator, and live tunnel topology. Earlier events
|
|
818
820
|
// only mark the reconciler dirty and are consumed here.
|
|
821
|
+
const mailDnsSyncDependencies = [
|
|
822
|
+
'DnsManager', 'EmailDomainManager', 'EmailServer', 'RemoteIngress',
|
|
823
|
+
];
|
|
824
|
+
if (this.options.dnsNsDomains?.length && this.options.dnsScopes?.length) {
|
|
825
|
+
mailDnsSyncDependencies.push('DnsServer');
|
|
826
|
+
}
|
|
827
|
+
|
|
819
828
|
this.serviceManager.addService(
|
|
820
829
|
new plugins.taskbuffer.Service('MailDnsSync')
|
|
821
830
|
.optional()
|
|
822
|
-
.dependsOn(
|
|
831
|
+
.dependsOn(...mailDnsSyncDependencies)
|
|
823
832
|
.withStart(async () => {
|
|
824
833
|
await this.mailDnsSync.start();
|
|
825
834
|
})
|
|
@@ -102,4 +102,79 @@ export class IpIntelligenceDoc extends plugins.smartdata.SmartDataDbDoc<IpIntell
|
|
|
102
102
|
public static async findAll(): Promise<IpIntelligenceDoc[]> {
|
|
103
103
|
return await IpIntelligenceDoc.getInstances({});
|
|
104
104
|
}
|
|
105
|
+
|
|
106
|
+
public static async findRecent(options: {
|
|
107
|
+
ipAddresses?: string[];
|
|
108
|
+
limit: number;
|
|
109
|
+
}): Promise<IpIntelligenceDoc[]> {
|
|
110
|
+
if (!Number.isSafeInteger(options.limit) || options.limit <= 0) {
|
|
111
|
+
throw new Error('IpIntelligenceDoc.findRecent requires a positive integer limit');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const filter = options.ipAddresses
|
|
115
|
+
? { ipAddress: { $in: options.ipAddresses } }
|
|
116
|
+
: {};
|
|
117
|
+
const collection = (IpIntelligenceDoc as typeof IpIntelligenceDoc & {
|
|
118
|
+
collection: plugins.smartdata.SmartdataCollection<IpIntelligenceDoc>;
|
|
119
|
+
}).collection;
|
|
120
|
+
const cursor = await collection.getCursor(
|
|
121
|
+
filter,
|
|
122
|
+
IpIntelligenceDoc as unknown as typeof plugins.smartdata.SmartDataDbDoc,
|
|
123
|
+
);
|
|
124
|
+
cursor.mongodbCursor.sort({ lastSeenAt: -1, _id: -1 });
|
|
125
|
+
cursor.mongodbCursor.limit(options.limit);
|
|
126
|
+
try {
|
|
127
|
+
return await cursor.toArray();
|
|
128
|
+
} finally {
|
|
129
|
+
await cursor.close();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public static async countAll(): Promise<number> {
|
|
134
|
+
return await DcRouterDb.getInstance()
|
|
135
|
+
.getDb()
|
|
136
|
+
.mongoDb
|
|
137
|
+
.collection('IpIntelligenceDoc')
|
|
138
|
+
.countDocuments({});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public static async findOldestIds(options: {
|
|
142
|
+
lastSeenBefore?: number;
|
|
143
|
+
limit: number;
|
|
144
|
+
}): Promise<unknown[]> {
|
|
145
|
+
if (!Number.isSafeInteger(options.limit) || options.limit <= 0) {
|
|
146
|
+
throw new Error('IpIntelligenceDoc.findOldestIds requires a positive integer limit');
|
|
147
|
+
}
|
|
148
|
+
const collection = DcRouterDb.getInstance()
|
|
149
|
+
.getDb()
|
|
150
|
+
.mongoDb
|
|
151
|
+
.collection('IpIntelligenceDoc');
|
|
152
|
+
const filter = options.lastSeenBefore === undefined
|
|
153
|
+
? {}
|
|
154
|
+
: { lastSeenAt: { $lt: options.lastSeenBefore } };
|
|
155
|
+
const cursor = collection
|
|
156
|
+
.find(filter, { projection: { _id: 1 } })
|
|
157
|
+
.sort({ lastSeenAt: 1, _id: 1 })
|
|
158
|
+
.limit(options.limit);
|
|
159
|
+
try {
|
|
160
|
+
const rows = await cursor.toArray();
|
|
161
|
+
return rows.map((row) => row._id);
|
|
162
|
+
} finally {
|
|
163
|
+
await cursor.close();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public static async deleteByDocumentIds(documentIds: unknown[]): Promise<number> {
|
|
168
|
+
if (documentIds.length === 0) return 0;
|
|
169
|
+
if (documentIds.length > 500 || documentIds.some((id) => id === undefined || id === null)) {
|
|
170
|
+
throw new Error('IpIntelligenceDoc.deleteByDocumentIds requires 1 to 500 document ids');
|
|
171
|
+
}
|
|
172
|
+
const deleteFilter: Record<string, any> = { _id: { $in: documentIds } };
|
|
173
|
+
const result = await DcRouterDb.getInstance()
|
|
174
|
+
.getDb()
|
|
175
|
+
.mongoDb
|
|
176
|
+
.collection('IpIntelligenceDoc')
|
|
177
|
+
.deleteMany(deleteFilter);
|
|
178
|
+
return result.deletedCount;
|
|
179
|
+
}
|
|
105
180
|
}
|
|
@@ -150,9 +150,7 @@ export class DnsServerRuntime {
|
|
|
150
150
|
|
|
151
151
|
// Hand the DnsServer to DnsManager so DB-backed local records on
|
|
152
152
|
// dcrouter-hosted domains get registered too.
|
|
153
|
-
|
|
154
|
-
await this.dcRouterRef.dnsManager.attachDnsServer(dnsServer);
|
|
155
|
-
}
|
|
153
|
+
await this.attachDnsServer(dnsServer);
|
|
156
154
|
} catch (error) {
|
|
157
155
|
dnsServer.removeAllListeners();
|
|
158
156
|
await dnsServer.stop().catch((stopError: Error) => {
|
|
@@ -166,6 +164,14 @@ export class DnsServerRuntime {
|
|
|
166
164
|
}
|
|
167
165
|
}
|
|
168
166
|
|
|
167
|
+
private async attachDnsServer(
|
|
168
|
+
dnsServer: plugins.smartdns.dnsServerMod.DnsServer,
|
|
169
|
+
): Promise<void> {
|
|
170
|
+
if (!this.dcRouterRef.dnsManager) return;
|
|
171
|
+
await this.dcRouterRef.dnsManager.attachDnsServer(dnsServer);
|
|
172
|
+
this.dcRouterRef.mailDnsSync?.requestSync('DNS server attached');
|
|
173
|
+
}
|
|
174
|
+
|
|
169
175
|
/**
|
|
170
176
|
* Create the DoH socket handler SmartProxy routes hand TLS sockets to.
|
|
171
177
|
*/
|
package/ts/dns/manager.dns.ts
CHANGED
|
@@ -690,32 +690,49 @@ export class DnsManager {
|
|
|
690
690
|
localByProviderId.set(providerId, record);
|
|
691
691
|
}
|
|
692
692
|
const remaining = new Set(existing);
|
|
693
|
+
let mirrorChanged = false;
|
|
693
694
|
for (let index = 0; index < providerRecords.length; index++) {
|
|
694
695
|
const pr = providerRecords[index];
|
|
695
696
|
const providerId = providerIds[index];
|
|
696
697
|
const match = localByProviderId.get(providerId);
|
|
697
698
|
if (!match) {
|
|
698
699
|
await this.createSyncedRecord(id, { ...pr, providerRecordId: providerId }, doc.createdBy);
|
|
700
|
+
mirrorChanged = true;
|
|
699
701
|
continue;
|
|
700
702
|
}
|
|
701
703
|
remaining.delete(match);
|
|
702
|
-
|
|
704
|
+
const providerName = pr.name.toLowerCase();
|
|
705
|
+
const providerProxied = pr.proxied;
|
|
706
|
+
const changed = match.name !== providerName
|
|
707
|
+
|| match.type !== pr.type
|
|
708
|
+
|| match.value !== pr.value
|
|
709
|
+
|| match.ttl !== pr.ttl
|
|
710
|
+
|| (match.proxied ?? false) !== (providerProxied ?? false)
|
|
711
|
+
|| match.source !== 'synced'
|
|
712
|
+
|| match.providerRecordId !== providerId;
|
|
713
|
+
if (!changed) continue;
|
|
714
|
+
|
|
715
|
+
match.name = providerName;
|
|
703
716
|
match.type = pr.type;
|
|
704
717
|
match.value = pr.value;
|
|
705
718
|
match.ttl = pr.ttl;
|
|
706
|
-
match.proxied =
|
|
719
|
+
match.proxied = providerProxied;
|
|
707
720
|
match.source = 'synced';
|
|
708
721
|
match.providerRecordId = providerId;
|
|
709
722
|
match.updatedAt = Date.now();
|
|
710
723
|
await match.save();
|
|
724
|
+
mirrorChanged = true;
|
|
711
725
|
}
|
|
712
726
|
for (const staleMirror of remaining) {
|
|
713
727
|
if (staleMirror.source !== 'synced' || !staleMirror.providerRecordId?.trim()) continue;
|
|
714
728
|
await staleMirror.delete();
|
|
729
|
+
mirrorChanged = true;
|
|
730
|
+
}
|
|
731
|
+
if (mirrorChanged) {
|
|
732
|
+
doc.lastSyncedAt = Date.now();
|
|
733
|
+
doc.updatedAt = doc.lastSyncedAt;
|
|
734
|
+
await doc.save();
|
|
715
735
|
}
|
|
716
|
-
doc.lastSyncedAt = Date.now();
|
|
717
|
-
doc.updatedAt = doc.lastSyncedAt;
|
|
718
|
-
await doc.save();
|
|
719
736
|
return {
|
|
720
737
|
success: true,
|
|
721
738
|
recordCount: providerRecords.length,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
MAIL_DNS_MAX_RETRY_INTERVAL_MS,
|
|
17
17
|
MAIL_DNS_RETRY_INTERVAL_MS,
|
|
18
18
|
} from './classes.mail-dns-sync.js';
|
|
19
|
+
import { projectMailDnsIntentStatus } from './mail-dns-status.js';
|
|
19
20
|
|
|
20
21
|
export interface IEmailDomainManagerActionResult {
|
|
21
22
|
success: boolean;
|
|
@@ -325,33 +326,39 @@ export class EmailDomainManager {
|
|
|
325
326
|
type: intent.type,
|
|
326
327
|
name: intent.name,
|
|
327
328
|
value: intent.value,
|
|
328
|
-
status: intent
|
|
329
|
-
? 'valid'
|
|
330
|
-
: intent.status === 'conflict' || intent.status === 'failed'
|
|
331
|
-
? 'invalid'
|
|
332
|
-
: 'missing',
|
|
329
|
+
status: projectMailDnsIntentStatus(intent),
|
|
333
330
|
}));
|
|
334
331
|
}
|
|
335
332
|
|
|
336
333
|
public async provisionDnsRecords(id: string): Promise<IEmailDomainManagerActionResult> {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
)
|
|
340
|
-
|
|
341
|
-
const
|
|
334
|
+
const current = await EmailDomainDoc.findById(id);
|
|
335
|
+
if (!current) throw new Error(`Email domain not found: ${id}`);
|
|
336
|
+
const before = new Set((await DnsRecordDoc.findByDomainId(current.linkedDomainId))
|
|
337
|
+
.filter((record) => record.managedBy === 'mail-dns-reconciler').map((record) => record.id));
|
|
338
|
+
const mailDnsSync = this.dcRouter.mailDnsSync;
|
|
339
|
+
if (!mailDnsSync) throw new Error('MailDnsSync is unavailable');
|
|
340
|
+
const ticket = await mailDnsSync.syncDomain(id, `manual provision: ${id}`);
|
|
341
|
+
const doc = ticket.domain;
|
|
342
342
|
if (!doc) throw new Error(`Email domain not found: ${id}`);
|
|
343
|
-
const provisioned =
|
|
343
|
+
const provisioned = ticket.records
|
|
344
344
|
.filter((record) => record.managedBy === 'mail-dns-reconciler' && !before.has(record.id)).length;
|
|
345
|
-
return { ...this.resultForDoc(doc,
|
|
345
|
+
return { ...this.resultForDoc(doc, true), provisioned };
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
public async validateDns(id: string): Promise<IEmailDomainManagerActionResult> {
|
|
349
|
-
|
|
350
|
-
|
|
349
|
+
const mailDnsSync = this.dcRouter.mailDnsSync;
|
|
350
|
+
if (!mailDnsSync) throw new Error('MailDnsSync is unavailable');
|
|
351
|
+
const ticket = await mailDnsSync.syncDomain(id, `manual validation: ${id}`);
|
|
352
|
+
const doc = ticket.domain;
|
|
351
353
|
if (!doc) throw new Error(`Email domain not found: ${id}`);
|
|
352
|
-
const records =
|
|
354
|
+
const records = (doc.reconciliation?.intents || []).map((intent) => ({
|
|
355
|
+
type: intent.type,
|
|
356
|
+
name: intent.name,
|
|
357
|
+
value: intent.value,
|
|
358
|
+
status: projectMailDnsIntentStatus(intent),
|
|
359
|
+
}));
|
|
353
360
|
return {
|
|
354
|
-
...this.resultForDoc(doc,
|
|
361
|
+
...this.resultForDoc(doc, true),
|
|
355
362
|
domain: this.docToInterface(doc),
|
|
356
363
|
records,
|
|
357
364
|
};
|