@serve.zone/dcrouter 11.23.5 → 12.0.0
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 +1 -1
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/classes.cert-provision-scheduler.d.ts +6 -8
- package/dist_ts/classes.cert-provision-scheduler.js +37 -17
- package/dist_ts/classes.dcrouter.d.ts +15 -29
- package/dist_ts/classes.dcrouter.js +96 -91
- package/dist_ts/classes.storage-cert-manager.d.ts +3 -6
- package/dist_ts/classes.storage-cert-manager.js +35 -25
- package/dist_ts/config/classes.api-token-manager.d.ts +1 -3
- package/dist_ts/config/classes.api-token-manager.js +45 -15
- package/dist_ts/config/classes.route-config-manager.d.ts +1 -3
- package/dist_ts/config/classes.route-config-manager.js +62 -24
- package/dist_ts/{cache → db}/classes.cache.cleaner.d.ts +3 -3
- package/dist_ts/db/classes.cache.cleaner.js +130 -0
- package/dist_ts/{cache → db}/classes.cached.document.js +1 -1
- package/dist_ts/db/classes.dcrouter-db.d.ts +70 -0
- package/dist_ts/db/classes.dcrouter-db.js +146 -0
- package/dist_ts/db/documents/classes.accounting-session.doc.d.ts +32 -0
- package/dist_ts/db/documents/classes.accounting-session.doc.js +214 -0
- package/dist_ts/db/documents/classes.acme-cert.doc.d.ts +13 -0
- package/dist_ts/db/documents/classes.acme-cert.doc.js +109 -0
- package/dist_ts/db/documents/classes.api-token.doc.d.ts +18 -0
- package/dist_ts/db/documents/classes.api-token.doc.js +127 -0
- package/dist_ts/{cache → db}/documents/classes.cached.email.js +3 -3
- package/dist_ts/{cache → db}/documents/classes.cached.ip.reputation.js +3 -3
- package/dist_ts/db/documents/classes.cert-backoff.doc.d.ts +11 -0
- package/dist_ts/db/documents/classes.cert-backoff.doc.js +97 -0
- package/dist_ts/db/documents/classes.proxy-cert.doc.d.ts +12 -0
- package/dist_ts/db/documents/classes.proxy-cert.doc.js +103 -0
- package/dist_ts/db/documents/classes.remote-ingress-edge.doc.d.ts +17 -0
- package/dist_ts/db/documents/classes.remote-ingress-edge.doc.js +130 -0
- package/dist_ts/db/documents/classes.route-override.doc.d.ts +10 -0
- package/dist_ts/db/documents/classes.route-override.doc.js +91 -0
- package/dist_ts/db/documents/classes.stored-route.doc.d.ts +12 -0
- package/dist_ts/db/documents/classes.stored-route.doc.js +103 -0
- package/dist_ts/db/documents/classes.vlan-mappings.doc.d.ts +15 -0
- package/dist_ts/db/documents/classes.vlan-mappings.doc.js +77 -0
- package/dist_ts/db/documents/classes.vpn-client.doc.d.ts +18 -0
- package/dist_ts/db/documents/classes.vpn-client.doc.js +136 -0
- package/dist_ts/db/documents/classes.vpn-server-keys.doc.d.ts +10 -0
- package/dist_ts/db/documents/classes.vpn-server-keys.doc.js +94 -0
- package/dist_ts/db/documents/index.d.ts +13 -0
- package/dist_ts/db/documents/index.js +20 -0
- package/dist_ts/{cache → db}/index.d.ts +1 -1
- package/dist_ts/db/index.js +9 -0
- package/dist_ts/opsserver/handlers/certificate.handler.js +66 -66
- package/dist_ts/opsserver/handlers/config.handler.js +14 -15
- package/dist_ts/paths.d.ts +0 -1
- package/dist_ts/paths.js +1 -2
- package/dist_ts/radius/classes.accounting.manager.d.ts +4 -12
- package/dist_ts/radius/classes.accounting.manager.js +80 -93
- package/dist_ts/radius/classes.radius.server.d.ts +1 -3
- package/dist_ts/radius/classes.radius.server.js +4 -6
- package/dist_ts/radius/classes.vlan.manager.d.ts +3 -7
- package/dist_ts/radius/classes.vlan.manager.js +21 -28
- package/dist_ts/radius/index.d.ts +1 -1
- package/dist_ts/radius/index.js +1 -1
- package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +3 -5
- package/dist_ts/remoteingress/classes.remoteingress-manager.js +41 -21
- package/dist_ts/security/classes.ipreputationchecker.d.ts +6 -21
- package/dist_ts/security/classes.ipreputationchecker.js +59 -138
- package/dist_ts/vpn/classes.vpn-manager.d.ts +4 -22
- package/dist_ts/vpn/classes.vpn-manager.js +40 -45
- package/dist_ts_oci_container/index.js +4 -4
- package/dist_ts_web/00_commitinfo_data.js +2 -2
- package/package.json +1 -1
- package/readme.storage.md +55 -91
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.cert-provision-scheduler.ts +35 -17
- package/ts/classes.dcrouter.ts +113 -125
- package/ts/classes.storage-cert-manager.ts +34 -22
- package/ts/config/classes.api-token-manager.ts +42 -11
- package/ts/config/classes.route-config-manager.ts +56 -21
- package/ts/{cache → db}/classes.cache.cleaner.ts +6 -6
- package/ts/db/classes.dcrouter-db.ts +179 -0
- package/ts/db/documents/classes.accounting-session.doc.ts +106 -0
- package/ts/db/documents/classes.acme-cert.doc.ts +41 -0
- package/ts/db/documents/classes.api-token.doc.ts +56 -0
- package/ts/{cache → db}/documents/classes.cached.email.ts +2 -2
- package/ts/{cache → db}/documents/classes.cached.ip.reputation.ts +2 -2
- package/ts/db/documents/classes.cert-backoff.doc.ts +35 -0
- package/ts/db/documents/classes.proxy-cert.doc.ts +38 -0
- package/ts/db/documents/classes.remote-ingress-edge.doc.ts +54 -0
- package/ts/db/documents/classes.route-override.doc.ts +32 -0
- package/ts/db/documents/classes.stored-route.doc.ts +38 -0
- package/ts/db/documents/classes.vlan-mappings.doc.ts +32 -0
- package/ts/db/documents/classes.vpn-client.doc.ts +57 -0
- package/ts/db/documents/classes.vpn-server-keys.doc.ts +31 -0
- package/ts/db/documents/index.ts +24 -0
- package/ts/{cache → db}/index.ts +6 -2
- package/ts/opsserver/handlers/certificate.handler.ts +67 -65
- package/ts/opsserver/handlers/config.handler.ts +13 -14
- package/ts/paths.ts +0 -1
- package/ts/radius/classes.accounting.manager.ts +81 -103
- package/ts/radius/classes.radius.server.ts +3 -6
- package/ts/radius/classes.vlan.manager.ts +20 -32
- package/ts/radius/index.ts +1 -1
- package/ts/remoteingress/classes.remoteingress-manager.ts +40 -22
- package/ts/security/classes.ipreputationchecker.ts +103 -196
- package/ts/vpn/classes.vpn-manager.ts +44 -75
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/dist_ts/cache/classes.cache.cleaner.js +0 -130
- package/dist_ts/cache/classes.cachedb.d.ts +0 -60
- package/dist_ts/cache/classes.cachedb.js +0 -126
- package/dist_ts/cache/documents/index.d.ts +0 -2
- package/dist_ts/cache/documents/index.js +0 -3
- package/dist_ts/cache/index.js +0 -7
- package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
- package/dist_ts/storage/classes.storagemanager.js +0 -348
- package/dist_ts/storage/index.d.ts +0 -1
- package/dist_ts/storage/index.js +0 -3
- package/ts/cache/classes.cachedb.ts +0 -155
- package/ts/cache/documents/index.ts +0 -2
- package/ts/storage/classes.storagemanager.ts +0 -404
- package/ts/storage/index.ts +0 -2
- /package/dist_ts/{cache → db}/classes.cached.document.d.ts +0 -0
- /package/dist_ts/{cache → db}/documents/classes.cached.email.d.ts +0 -0
- /package/dist_ts/{cache → db}/documents/classes.cached.ip.reputation.d.ts +0 -0
- /package/ts/{cache → db}/classes.cached.document.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { logger } from '../logger.js';
|
|
3
|
-
import
|
|
3
|
+
import { StoredRouteDoc, RouteOverrideDoc } from '../db/index.js';
|
|
4
4
|
import type {
|
|
5
5
|
IStoredRoute,
|
|
6
6
|
IRouteOverride,
|
|
@@ -10,16 +10,12 @@ import type {
|
|
|
10
10
|
import type { IDcRouterRouteConfig } from '../../ts_interfaces/data/remoteingress.js';
|
|
11
11
|
import { type IHttp3Config, augmentRouteWithHttp3 } from '../http3/index.js';
|
|
12
12
|
|
|
13
|
-
const ROUTES_PREFIX = '/config-api/routes/';
|
|
14
|
-
const OVERRIDES_PREFIX = '/config-api/overrides/';
|
|
15
|
-
|
|
16
13
|
export class RouteConfigManager {
|
|
17
14
|
private storedRoutes = new Map<string, IStoredRoute>();
|
|
18
15
|
private overrides = new Map<string, IRouteOverride>();
|
|
19
16
|
private warnings: IRouteWarning[] = [];
|
|
20
17
|
|
|
21
18
|
constructor(
|
|
22
|
-
private storageManager: StorageManager,
|
|
23
19
|
private getHardcodedRoutes: () => plugins.smartproxy.IRouteConfig[],
|
|
24
20
|
private getSmartProxy: () => plugins.smartproxy.SmartProxy | undefined,
|
|
25
21
|
private getHttp3Config?: () => IHttp3Config | undefined,
|
|
@@ -127,7 +123,8 @@ export class RouteConfigManager {
|
|
|
127
123
|
public async deleteRoute(id: string): Promise<boolean> {
|
|
128
124
|
if (!this.storedRoutes.has(id)) return false;
|
|
129
125
|
this.storedRoutes.delete(id);
|
|
130
|
-
await
|
|
126
|
+
const doc = await StoredRouteDoc.findById(id);
|
|
127
|
+
if (doc) await doc.delete();
|
|
131
128
|
await this.applyRoutes();
|
|
132
129
|
return true;
|
|
133
130
|
}
|
|
@@ -148,7 +145,20 @@ export class RouteConfigManager {
|
|
|
148
145
|
updatedBy,
|
|
149
146
|
};
|
|
150
147
|
this.overrides.set(routeName, override);
|
|
151
|
-
await
|
|
148
|
+
const existingDoc = await RouteOverrideDoc.findByRouteName(routeName);
|
|
149
|
+
if (existingDoc) {
|
|
150
|
+
existingDoc.enabled = override.enabled;
|
|
151
|
+
existingDoc.updatedAt = override.updatedAt;
|
|
152
|
+
existingDoc.updatedBy = override.updatedBy;
|
|
153
|
+
await existingDoc.save();
|
|
154
|
+
} else {
|
|
155
|
+
const doc = new RouteOverrideDoc();
|
|
156
|
+
doc.routeName = override.routeName;
|
|
157
|
+
doc.enabled = override.enabled;
|
|
158
|
+
doc.updatedAt = override.updatedAt;
|
|
159
|
+
doc.updatedBy = override.updatedBy;
|
|
160
|
+
await doc.save();
|
|
161
|
+
}
|
|
152
162
|
this.computeWarnings();
|
|
153
163
|
await this.applyRoutes();
|
|
154
164
|
}
|
|
@@ -156,7 +166,8 @@ export class RouteConfigManager {
|
|
|
156
166
|
public async removeOverride(routeName: string): Promise<boolean> {
|
|
157
167
|
if (!this.overrides.has(routeName)) return false;
|
|
158
168
|
this.overrides.delete(routeName);
|
|
159
|
-
await
|
|
169
|
+
const doc = await RouteOverrideDoc.findByRouteName(routeName);
|
|
170
|
+
if (doc) await doc.delete();
|
|
160
171
|
this.computeWarnings();
|
|
161
172
|
await this.applyRoutes();
|
|
162
173
|
return true;
|
|
@@ -167,12 +178,17 @@ export class RouteConfigManager {
|
|
|
167
178
|
// =========================================================================
|
|
168
179
|
|
|
169
180
|
private async loadStoredRoutes(): Promise<void> {
|
|
170
|
-
const
|
|
171
|
-
for (const
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
const docs = await StoredRouteDoc.findAll();
|
|
182
|
+
for (const doc of docs) {
|
|
183
|
+
if (doc.id) {
|
|
184
|
+
this.storedRoutes.set(doc.id, {
|
|
185
|
+
id: doc.id,
|
|
186
|
+
route: doc.route,
|
|
187
|
+
enabled: doc.enabled,
|
|
188
|
+
createdAt: doc.createdAt,
|
|
189
|
+
updatedAt: doc.updatedAt,
|
|
190
|
+
createdBy: doc.createdBy,
|
|
191
|
+
});
|
|
176
192
|
}
|
|
177
193
|
}
|
|
178
194
|
if (this.storedRoutes.size > 0) {
|
|
@@ -181,12 +197,15 @@ export class RouteConfigManager {
|
|
|
181
197
|
}
|
|
182
198
|
|
|
183
199
|
private async loadOverrides(): Promise<void> {
|
|
184
|
-
const
|
|
185
|
-
for (const
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
200
|
+
const docs = await RouteOverrideDoc.findAll();
|
|
201
|
+
for (const doc of docs) {
|
|
202
|
+
if (doc.routeName) {
|
|
203
|
+
this.overrides.set(doc.routeName, {
|
|
204
|
+
routeName: doc.routeName,
|
|
205
|
+
enabled: doc.enabled,
|
|
206
|
+
updatedAt: doc.updatedAt,
|
|
207
|
+
updatedBy: doc.updatedBy,
|
|
208
|
+
});
|
|
190
209
|
}
|
|
191
210
|
}
|
|
192
211
|
if (this.overrides.size > 0) {
|
|
@@ -195,7 +214,23 @@ export class RouteConfigManager {
|
|
|
195
214
|
}
|
|
196
215
|
|
|
197
216
|
private async persistRoute(stored: IStoredRoute): Promise<void> {
|
|
198
|
-
await
|
|
217
|
+
const existingDoc = await StoredRouteDoc.findById(stored.id);
|
|
218
|
+
if (existingDoc) {
|
|
219
|
+
existingDoc.route = stored.route;
|
|
220
|
+
existingDoc.enabled = stored.enabled;
|
|
221
|
+
existingDoc.updatedAt = stored.updatedAt;
|
|
222
|
+
existingDoc.createdBy = stored.createdBy;
|
|
223
|
+
await existingDoc.save();
|
|
224
|
+
} else {
|
|
225
|
+
const doc = new StoredRouteDoc();
|
|
226
|
+
doc.id = stored.id;
|
|
227
|
+
doc.route = stored.route;
|
|
228
|
+
doc.enabled = stored.enabled;
|
|
229
|
+
doc.createdAt = stored.createdAt;
|
|
230
|
+
doc.updatedAt = stored.updatedAt;
|
|
231
|
+
doc.createdBy = stored.createdBy;
|
|
232
|
+
await doc.save();
|
|
233
|
+
}
|
|
199
234
|
}
|
|
200
235
|
|
|
201
236
|
// =========================================================================
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { logger } from '../logger.js';
|
|
3
|
-
import {
|
|
3
|
+
import { DcRouterDb } from './classes.dcrouter-db.js';
|
|
4
4
|
|
|
5
5
|
// Import document classes for cleanup
|
|
6
6
|
import { CachedEmail } from './documents/classes.cached.email.js';
|
|
@@ -26,10 +26,10 @@ export class CacheCleaner {
|
|
|
26
26
|
private cleanupInterval: ReturnType<typeof setInterval> | null = null;
|
|
27
27
|
private isRunning: boolean = false;
|
|
28
28
|
private options: Required<ICacheCleanerOptions>;
|
|
29
|
-
private
|
|
29
|
+
private dcRouterDb: DcRouterDb;
|
|
30
30
|
|
|
31
|
-
constructor(
|
|
32
|
-
this.
|
|
31
|
+
constructor(dcRouterDb: DcRouterDb, options: ICacheCleanerOptions = {}) {
|
|
32
|
+
this.dcRouterDb = dcRouterDb;
|
|
33
33
|
this.options = {
|
|
34
34
|
intervalMs: options.intervalMs || 60 * 60 * 1000, // 1 hour default
|
|
35
35
|
verbose: options.verbose || false,
|
|
@@ -86,8 +86,8 @@ export class CacheCleaner {
|
|
|
86
86
|
* Run a single cleanup cycle
|
|
87
87
|
*/
|
|
88
88
|
public async runCleanup(): Promise<void> {
|
|
89
|
-
if (!this.
|
|
90
|
-
logger.log('warn', '
|
|
89
|
+
if (!this.dcRouterDb.isReady()) {
|
|
90
|
+
logger.log('warn', 'DcRouterDb not ready, skipping cleanup');
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { logger } from '../logger.js';
|
|
3
|
+
import { defaultTsmDbPath } from '../paths.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the unified DCRouter database
|
|
7
|
+
*/
|
|
8
|
+
export interface IDcRouterDbConfig {
|
|
9
|
+
/** External MongoDB connection URL. If absent, uses embedded LocalSmartDb. */
|
|
10
|
+
mongoDbUrl?: string;
|
|
11
|
+
/** Storage path for embedded LocalSmartDb data (default: ~/.serve.zone/dcrouter/tsmdb) */
|
|
12
|
+
storagePath?: string;
|
|
13
|
+
/** Database name (default: dcrouter) */
|
|
14
|
+
dbName?: string;
|
|
15
|
+
/** Enable debug logging */
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* DcRouterDb - Unified database layer for DCRouter
|
|
21
|
+
*
|
|
22
|
+
* Replaces both StorageManager (flat-file key-value) and CacheDb (embedded MongoDB).
|
|
23
|
+
* All data is stored as smartdata document classes in a single database.
|
|
24
|
+
*
|
|
25
|
+
* Two modes:
|
|
26
|
+
* - **Embedded** (default): Spawns a LocalSmartDb (Rust-based MongoDB-compatible engine)
|
|
27
|
+
* - **External**: Connects to a provided MongoDB URL
|
|
28
|
+
*/
|
|
29
|
+
export class DcRouterDb {
|
|
30
|
+
private static instance: DcRouterDb | null = null;
|
|
31
|
+
|
|
32
|
+
private localSmartDb: plugins.smartdb.LocalSmartDb | null = null;
|
|
33
|
+
private smartdataDb!: plugins.smartdata.SmartdataDb;
|
|
34
|
+
private options: Required<IDcRouterDbConfig>;
|
|
35
|
+
private isStarted: boolean = false;
|
|
36
|
+
|
|
37
|
+
constructor(options: IDcRouterDbConfig = {}) {
|
|
38
|
+
this.options = {
|
|
39
|
+
mongoDbUrl: options.mongoDbUrl || '',
|
|
40
|
+
storagePath: options.storagePath || defaultTsmDbPath,
|
|
41
|
+
dbName: options.dbName || 'dcrouter',
|
|
42
|
+
debug: options.debug || false,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get or create the singleton instance
|
|
48
|
+
*/
|
|
49
|
+
public static getInstance(options?: IDcRouterDbConfig): DcRouterDb {
|
|
50
|
+
if (!DcRouterDb.instance) {
|
|
51
|
+
DcRouterDb.instance = new DcRouterDb(options);
|
|
52
|
+
}
|
|
53
|
+
return DcRouterDb.instance;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Reset the singleton instance (useful for testing)
|
|
58
|
+
*/
|
|
59
|
+
public static resetInstance(): void {
|
|
60
|
+
DcRouterDb.instance = null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Start the database
|
|
65
|
+
* - If mongoDbUrl is provided, connects directly to external MongoDB
|
|
66
|
+
* - Otherwise, starts an embedded LocalSmartDb instance
|
|
67
|
+
*/
|
|
68
|
+
public async start(): Promise<void> {
|
|
69
|
+
if (this.isStarted) {
|
|
70
|
+
logger.log('warn', 'DcRouterDb already started');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
let connectionUri: string;
|
|
76
|
+
|
|
77
|
+
if (this.options.mongoDbUrl) {
|
|
78
|
+
// External MongoDB mode
|
|
79
|
+
connectionUri = this.options.mongoDbUrl;
|
|
80
|
+
logger.log('info', `DcRouterDb connecting to external MongoDB`);
|
|
81
|
+
} else {
|
|
82
|
+
// Embedded LocalSmartDb mode
|
|
83
|
+
await plugins.fsUtils.ensureDir(this.options.storagePath);
|
|
84
|
+
|
|
85
|
+
this.localSmartDb = new plugins.smartdb.LocalSmartDb({
|
|
86
|
+
folderPath: this.options.storagePath,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const connectionInfo = await this.localSmartDb.start();
|
|
90
|
+
connectionUri = connectionInfo.connectionUri;
|
|
91
|
+
|
|
92
|
+
if (this.options.debug) {
|
|
93
|
+
logger.log('debug', `LocalSmartDb started with URI: ${connectionUri}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
logger.log('info', `DcRouterDb started embedded instance at ${this.options.storagePath}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Initialize smartdata ORM
|
|
100
|
+
this.smartdataDb = new plugins.smartdata.SmartdataDb({
|
|
101
|
+
mongoDbUrl: connectionUri,
|
|
102
|
+
mongoDbName: this.options.dbName,
|
|
103
|
+
});
|
|
104
|
+
await this.smartdataDb.init();
|
|
105
|
+
|
|
106
|
+
this.isStarted = true;
|
|
107
|
+
logger.log('info', `DcRouterDb ready (db: ${this.options.dbName})`);
|
|
108
|
+
} catch (error: unknown) {
|
|
109
|
+
logger.log('error', `Failed to start DcRouterDb: ${(error as Error).message}`);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Stop the database
|
|
116
|
+
*/
|
|
117
|
+
public async stop(): Promise<void> {
|
|
118
|
+
if (!this.isStarted) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
// Close smartdata connection
|
|
124
|
+
if (this.smartdataDb) {
|
|
125
|
+
await this.smartdataDb.close();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Stop embedded LocalSmartDb if running
|
|
129
|
+
if (this.localSmartDb) {
|
|
130
|
+
await this.localSmartDb.stop();
|
|
131
|
+
this.localSmartDb = null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.isStarted = false;
|
|
135
|
+
logger.log('info', 'DcRouterDb stopped');
|
|
136
|
+
} catch (error: unknown) {
|
|
137
|
+
logger.log('error', `Error stopping DcRouterDb: ${(error as Error).message}`);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get the smartdata database instance for @Collection decorators
|
|
144
|
+
*/
|
|
145
|
+
public getDb(): plugins.smartdata.SmartdataDb {
|
|
146
|
+
if (!this.isStarted) {
|
|
147
|
+
throw new Error('DcRouterDb not started. Call start() first.');
|
|
148
|
+
}
|
|
149
|
+
return this.smartdataDb;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check if the database is ready
|
|
154
|
+
*/
|
|
155
|
+
public isReady(): boolean {
|
|
156
|
+
return this.isStarted;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Whether running in embedded mode (LocalSmartDb) vs external MongoDB
|
|
161
|
+
*/
|
|
162
|
+
public isEmbedded(): boolean {
|
|
163
|
+
return !this.options.mongoDbUrl;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get the storage path (only relevant for embedded mode)
|
|
168
|
+
*/
|
|
169
|
+
public getStoragePath(): string {
|
|
170
|
+
return this.options.storagePath;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get the database name
|
|
175
|
+
*/
|
|
176
|
+
public getDbName(): string {
|
|
177
|
+
return this.options.dbName;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
|
|
4
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
5
|
+
|
|
6
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
7
|
+
export class AccountingSessionDoc extends plugins.smartdata.SmartDataDbDoc<AccountingSessionDoc, AccountingSessionDoc> {
|
|
8
|
+
@plugins.smartdata.unI()
|
|
9
|
+
@plugins.smartdata.svDb()
|
|
10
|
+
public sessionId!: string;
|
|
11
|
+
|
|
12
|
+
@plugins.smartdata.svDb()
|
|
13
|
+
public username!: string;
|
|
14
|
+
|
|
15
|
+
@plugins.smartdata.svDb()
|
|
16
|
+
public macAddress!: string;
|
|
17
|
+
|
|
18
|
+
@plugins.smartdata.svDb()
|
|
19
|
+
public nasIpAddress!: string;
|
|
20
|
+
|
|
21
|
+
@plugins.smartdata.svDb()
|
|
22
|
+
public nasPort!: number;
|
|
23
|
+
|
|
24
|
+
@plugins.smartdata.svDb()
|
|
25
|
+
public nasPortType!: string;
|
|
26
|
+
|
|
27
|
+
@plugins.smartdata.svDb()
|
|
28
|
+
public nasIdentifier!: string;
|
|
29
|
+
|
|
30
|
+
@plugins.smartdata.svDb()
|
|
31
|
+
public vlanId!: number;
|
|
32
|
+
|
|
33
|
+
@plugins.smartdata.svDb()
|
|
34
|
+
public framedIpAddress!: string;
|
|
35
|
+
|
|
36
|
+
@plugins.smartdata.svDb()
|
|
37
|
+
public calledStationId!: string;
|
|
38
|
+
|
|
39
|
+
@plugins.smartdata.svDb()
|
|
40
|
+
public callingStationId!: string;
|
|
41
|
+
|
|
42
|
+
@plugins.smartdata.svDb()
|
|
43
|
+
public startTime!: number;
|
|
44
|
+
|
|
45
|
+
@plugins.smartdata.svDb()
|
|
46
|
+
public endTime!: number;
|
|
47
|
+
|
|
48
|
+
@plugins.smartdata.svDb()
|
|
49
|
+
public lastUpdateTime!: number;
|
|
50
|
+
|
|
51
|
+
@plugins.smartdata.index()
|
|
52
|
+
@plugins.smartdata.svDb()
|
|
53
|
+
public status!: 'active' | 'stopped' | 'terminated';
|
|
54
|
+
|
|
55
|
+
@plugins.smartdata.svDb()
|
|
56
|
+
public terminateCause!: string;
|
|
57
|
+
|
|
58
|
+
@plugins.smartdata.svDb()
|
|
59
|
+
public inputOctets!: number;
|
|
60
|
+
|
|
61
|
+
@plugins.smartdata.svDb()
|
|
62
|
+
public outputOctets!: number;
|
|
63
|
+
|
|
64
|
+
@plugins.smartdata.svDb()
|
|
65
|
+
public inputPackets!: number;
|
|
66
|
+
|
|
67
|
+
@plugins.smartdata.svDb()
|
|
68
|
+
public outputPackets!: number;
|
|
69
|
+
|
|
70
|
+
@plugins.smartdata.svDb()
|
|
71
|
+
public sessionTime!: number;
|
|
72
|
+
|
|
73
|
+
@plugins.smartdata.svDb()
|
|
74
|
+
public serviceType!: string;
|
|
75
|
+
|
|
76
|
+
constructor() {
|
|
77
|
+
super();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public static async findBySessionId(sessionId: string): Promise<AccountingSessionDoc | null> {
|
|
81
|
+
return await AccountingSessionDoc.getInstance({ sessionId });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public static async findActive(): Promise<AccountingSessionDoc[]> {
|
|
85
|
+
return await AccountingSessionDoc.getInstances({ status: 'active' });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public static async findByUsername(username: string): Promise<AccountingSessionDoc[]> {
|
|
89
|
+
return await AccountingSessionDoc.getInstances({ username });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public static async findByNas(nasIpAddress: string): Promise<AccountingSessionDoc[]> {
|
|
93
|
+
return await AccountingSessionDoc.getInstances({ nasIpAddress });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public static async findByVlan(vlanId: number): Promise<AccountingSessionDoc[]> {
|
|
97
|
+
return await AccountingSessionDoc.getInstances({ vlanId });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public static async findStoppedBefore(cutoffTime: number): Promise<AccountingSessionDoc[]> {
|
|
101
|
+
return await AccountingSessionDoc.getInstances({
|
|
102
|
+
status: { $in: ['stopped', 'terminated'] } as any,
|
|
103
|
+
endTime: { $lt: cutoffTime, $gt: 0 } as any,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
|
|
4
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
5
|
+
|
|
6
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
7
|
+
export class AcmeCertDoc extends plugins.smartdata.SmartDataDbDoc<AcmeCertDoc, AcmeCertDoc> {
|
|
8
|
+
@plugins.smartdata.unI()
|
|
9
|
+
@plugins.smartdata.svDb()
|
|
10
|
+
public domainName!: string;
|
|
11
|
+
|
|
12
|
+
@plugins.smartdata.svDb()
|
|
13
|
+
public id!: string;
|
|
14
|
+
|
|
15
|
+
@plugins.smartdata.svDb()
|
|
16
|
+
public created!: number;
|
|
17
|
+
|
|
18
|
+
@plugins.smartdata.svDb()
|
|
19
|
+
public privateKey!: string;
|
|
20
|
+
|
|
21
|
+
@plugins.smartdata.svDb()
|
|
22
|
+
public publicKey!: string;
|
|
23
|
+
|
|
24
|
+
@plugins.smartdata.svDb()
|
|
25
|
+
public csr!: string;
|
|
26
|
+
|
|
27
|
+
@plugins.smartdata.svDb()
|
|
28
|
+
public validUntil!: number;
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
super();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static async findByDomain(domainName: string): Promise<AcmeCertDoc | null> {
|
|
35
|
+
return await AcmeCertDoc.getInstance({ domainName });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public static async findAll(): Promise<AcmeCertDoc[]> {
|
|
39
|
+
return await AcmeCertDoc.getInstances({});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
import type { TApiTokenScope } from '../../../ts_interfaces/data/route-management.js';
|
|
4
|
+
|
|
5
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
6
|
+
|
|
7
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
8
|
+
export class ApiTokenDoc extends plugins.smartdata.SmartDataDbDoc<ApiTokenDoc, ApiTokenDoc> {
|
|
9
|
+
@plugins.smartdata.unI()
|
|
10
|
+
@plugins.smartdata.svDb()
|
|
11
|
+
public id!: string;
|
|
12
|
+
|
|
13
|
+
@plugins.smartdata.svDb()
|
|
14
|
+
public name: string = '';
|
|
15
|
+
|
|
16
|
+
@plugins.smartdata.svDb()
|
|
17
|
+
public tokenHash!: string;
|
|
18
|
+
|
|
19
|
+
@plugins.smartdata.svDb()
|
|
20
|
+
public scopes!: TApiTokenScope[];
|
|
21
|
+
|
|
22
|
+
@plugins.smartdata.svDb()
|
|
23
|
+
public createdAt!: number;
|
|
24
|
+
|
|
25
|
+
@plugins.smartdata.svDb()
|
|
26
|
+
public expiresAt!: number | null;
|
|
27
|
+
|
|
28
|
+
@plugins.smartdata.svDb()
|
|
29
|
+
public lastUsedAt!: number | null;
|
|
30
|
+
|
|
31
|
+
@plugins.smartdata.svDb()
|
|
32
|
+
public createdBy!: string;
|
|
33
|
+
|
|
34
|
+
@plugins.smartdata.svDb()
|
|
35
|
+
public enabled!: boolean;
|
|
36
|
+
|
|
37
|
+
constructor() {
|
|
38
|
+
super();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public static async findById(id: string): Promise<ApiTokenDoc | null> {
|
|
42
|
+
return await ApiTokenDoc.getInstance({ id });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public static async findByTokenHash(tokenHash: string): Promise<ApiTokenDoc | null> {
|
|
46
|
+
return await ApiTokenDoc.getInstance({ tokenHash });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public static async findAll(): Promise<ApiTokenDoc[]> {
|
|
50
|
+
return await ApiTokenDoc.getInstances({});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public static async findEnabled(): Promise<ApiTokenDoc[]> {
|
|
54
|
+
return await ApiTokenDoc.getInstances({ enabled: true });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import { CachedDocument, TTL } from '../classes.cached.document.js';
|
|
3
|
-
import {
|
|
3
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Email status in the cache
|
|
@@ -10,7 +10,7 @@ export type TCachedEmailStatus = 'pending' | 'processing' | 'delivered' | 'faile
|
|
|
10
10
|
/**
|
|
11
11
|
* Helper to get the smartdata database instance
|
|
12
12
|
*/
|
|
13
|
-
const getDb = () =>
|
|
13
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* CachedEmail - Stores email queue items in the cache
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import { CachedDocument, TTL } from '../classes.cached.document.js';
|
|
3
|
-
import {
|
|
3
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Helper to get the smartdata database instance
|
|
7
7
|
*/
|
|
8
|
-
const getDb = () =>
|
|
8
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* IP reputation result data
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
|
|
4
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
5
|
+
|
|
6
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
7
|
+
export class CertBackoffDoc extends plugins.smartdata.SmartDataDbDoc<CertBackoffDoc, CertBackoffDoc> {
|
|
8
|
+
@plugins.smartdata.unI()
|
|
9
|
+
@plugins.smartdata.svDb()
|
|
10
|
+
public domain!: string;
|
|
11
|
+
|
|
12
|
+
@plugins.smartdata.svDb()
|
|
13
|
+
public failures!: number;
|
|
14
|
+
|
|
15
|
+
@plugins.smartdata.svDb()
|
|
16
|
+
public lastFailure!: string;
|
|
17
|
+
|
|
18
|
+
@plugins.smartdata.svDb()
|
|
19
|
+
public retryAfter!: string;
|
|
20
|
+
|
|
21
|
+
@plugins.smartdata.svDb()
|
|
22
|
+
public lastError!: string;
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public static async findByDomain(domain: string): Promise<CertBackoffDoc | null> {
|
|
29
|
+
return await CertBackoffDoc.getInstance({ domain });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public static async findAll(): Promise<CertBackoffDoc[]> {
|
|
33
|
+
return await CertBackoffDoc.getInstances({});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
|
|
4
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
5
|
+
|
|
6
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
7
|
+
export class ProxyCertDoc extends plugins.smartdata.SmartDataDbDoc<ProxyCertDoc, ProxyCertDoc> {
|
|
8
|
+
@plugins.smartdata.unI()
|
|
9
|
+
@plugins.smartdata.svDb()
|
|
10
|
+
public domain!: string;
|
|
11
|
+
|
|
12
|
+
@plugins.smartdata.svDb()
|
|
13
|
+
public publicKey!: string;
|
|
14
|
+
|
|
15
|
+
@plugins.smartdata.svDb()
|
|
16
|
+
public privateKey!: string;
|
|
17
|
+
|
|
18
|
+
@plugins.smartdata.svDb()
|
|
19
|
+
public ca!: string;
|
|
20
|
+
|
|
21
|
+
@plugins.smartdata.svDb()
|
|
22
|
+
public validUntil!: number;
|
|
23
|
+
|
|
24
|
+
@plugins.smartdata.svDb()
|
|
25
|
+
public validFrom!: number;
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
super();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public static async findByDomain(domain: string): Promise<ProxyCertDoc | null> {
|
|
32
|
+
return await ProxyCertDoc.getInstance({ domain });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public static async findAll(): Promise<ProxyCertDoc[]> {
|
|
36
|
+
return await ProxyCertDoc.getInstances({});
|
|
37
|
+
}
|
|
38
|
+
}
|