@serve.zone/dcrouter 18.9.3 → 18.9.5

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.
Files changed (42) hide show
  1. package/deno.json +1 -1
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/classes.dcrouter.js +5 -4
  4. package/dist_ts/db/documents/classes.authentication-event.doc.d.ts +0 -1
  5. package/dist_ts/db/documents/classes.authentication-event.doc.js +176 -259
  6. package/dist_ts/db/documents/classes.email-traffic-bucket.doc.js +110 -188
  7. package/dist_ts/dns/manager.dns-authority.d.ts +5 -0
  8. package/dist_ts/dns/manager.dns-authority.js +97 -53
  9. package/dist_ts/dns/manager.dns.js +23 -5
  10. package/dist_ts/email/classes.email-domain.manager.js +14 -3
  11. package/dist_ts/email/classes.email-settings.manager.js +26 -6
  12. package/dist_ts/email/classes.mail-dns-sync.js +43 -11
  13. package/dist_ts/monitoring/classes.metricscache.d.ts +28 -19
  14. package/dist_ts/monitoring/classes.metricscache.js +133 -62
  15. package/dist_ts/monitoring/classes.metricsmanager.js +7 -5
  16. package/dist_ts/plugins.d.ts +2 -1
  17. package/dist_ts/plugins.js +3 -2
  18. package/dist_ts/remoteingress/classes.remoteingress-manager.js +46 -9
  19. package/dist_ts/security/classes.authentication-event-manager.d.ts +5 -1
  20. package/dist_ts/security/classes.authentication-event-manager.js +32 -22
  21. package/dist_ts/vpn/classes.vpn-manager.js +34 -2
  22. package/dist_ts_migrations/index.d.ts +4 -1
  23. package/dist_ts_migrations/index.js +18 -3
  24. package/dist_ts_web/00_commitinfo_data.js +1 -1
  25. package/package.json +7 -6
  26. package/readme.hints.md +84 -0
  27. package/ts/00_commitinfo_data.ts +1 -1
  28. package/ts/classes.dcrouter.ts +4 -3
  29. package/ts/db/documents/classes.authentication-event.doc.ts +64 -87
  30. package/ts/db/documents/classes.email-traffic-bucket.doc.ts +10 -9
  31. package/ts/dns/manager.dns-authority.ts +92 -54
  32. package/ts/dns/manager.dns.ts +20 -4
  33. package/ts/email/classes.email-domain.manager.ts +12 -2
  34. package/ts/email/classes.email-settings.manager.ts +23 -5
  35. package/ts/email/classes.mail-dns-sync.ts +45 -10
  36. package/ts/monitoring/classes.metricscache.ts +133 -79
  37. package/ts/monitoring/classes.metricsmanager.ts +6 -4
  38. package/ts/plugins.ts +2 -0
  39. package/ts/remoteingress/classes.remoteingress-manager.ts +42 -8
  40. package/ts/security/classes.authentication-event-manager.ts +31 -20
  41. package/ts/vpn/classes.vpn-manager.ts +32 -1
  42. package/ts_web/00_commitinfo_data.ts +1 -1
@@ -1,273 +1,190 @@
1
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
- var _, done = false;
7
- for (var i = decorators.length - 1; i >= 0; i--) {
8
- var context = {};
9
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
- if (kind === "accessor") {
14
- if (result === void 0) continue;
15
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
- if (_ = accept(result.get)) descriptor.get = _;
17
- if (_ = accept(result.set)) descriptor.set = _;
18
- if (_ = accept(result.init)) initializers.unshift(_);
19
- }
20
- else if (_ = accept(result)) {
21
- if (kind === "field") initializers.unshift(_);
22
- else descriptor[key] = _;
23
- }
24
- }
25
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
- done = true;
27
- };
28
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
- var useValue = arguments.length > 2;
30
- for (var i = 0; i < initializers.length; i++) {
31
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
- }
33
- return useValue ? value : void 0;
34
- };
35
1
  import * as plugins from '../../plugins.js';
36
2
  import { DcRouterDb } from '../classes.dcrouter-db.js';
37
3
  const DB_OPERATION_TIMEOUT_MS = 5_000;
38
4
  const getDb = () => DcRouterDb.getInstance().getDb();
39
- let AuthenticationEventDoc = (() => {
40
- let _classDecorators = [plugins.smartdata.Collection(() => getDb())];
41
- let _classDescriptor;
42
- let _classExtraInitializers = [];
43
- let _classThis;
44
- let _classSuper = plugins.smartdata.SmartDataDbDoc;
45
- let _id_decorators;
46
- let _id_initializers = [];
47
- let _id_extraInitializers = [];
48
- let _timestamp_decorators;
49
- let _timestamp_initializers = [];
50
- let _timestamp_extraInitializers = [];
51
- let _username_decorators;
52
- let _username_initializers = [];
53
- let _username_extraInitializers = [];
54
- let _userId_decorators;
55
- let _userId_initializers = [];
56
- let _userId_extraInitializers = [];
57
- let _success_decorators;
58
- let _success_initializers = [];
59
- let _success_extraInitializers = [];
60
- let _requestedAuthSource_decorators;
61
- let _requestedAuthSource_initializers = [];
62
- let _requestedAuthSource_extraInitializers = [];
63
- let _resolvedAuthSource_decorators;
64
- let _resolvedAuthSource_initializers = [];
65
- let _resolvedAuthSource_extraInitializers = [];
66
- let _failureReason_decorators;
67
- let _failureReason_initializers = [];
68
- let _failureReason_extraInitializers = [];
69
- var AuthenticationEventDoc = class extends _classSuper {
70
- static { _classThis = this; }
71
- static {
72
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
73
- _id_decorators = [plugins.smartdata.unI(), plugins.smartdata.svDb()];
74
- _timestamp_decorators = [plugins.smartdata.svDb()];
75
- _username_decorators = [plugins.smartdata.svDb()];
76
- _userId_decorators = [plugins.smartdata.svDb()];
77
- _success_decorators = [plugins.smartdata.svDb()];
78
- _requestedAuthSource_decorators = [plugins.smartdata.svDb()];
79
- _resolvedAuthSource_decorators = [plugins.smartdata.svDb()];
80
- _failureReason_decorators = [plugins.smartdata.svDb()];
81
- __esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
82
- __esDecorate(null, null, _timestamp_decorators, { kind: "field", name: "timestamp", static: false, private: false, access: { has: obj => "timestamp" in obj, get: obj => obj.timestamp, set: (obj, value) => { obj.timestamp = value; } }, metadata: _metadata }, _timestamp_initializers, _timestamp_extraInitializers);
83
- __esDecorate(null, null, _username_decorators, { kind: "field", name: "username", static: false, private: false, access: { has: obj => "username" in obj, get: obj => obj.username, set: (obj, value) => { obj.username = value; } }, metadata: _metadata }, _username_initializers, _username_extraInitializers);
84
- __esDecorate(null, null, _userId_decorators, { kind: "field", name: "userId", static: false, private: false, access: { has: obj => "userId" in obj, get: obj => obj.userId, set: (obj, value) => { obj.userId = value; } }, metadata: _metadata }, _userId_initializers, _userId_extraInitializers);
85
- __esDecorate(null, null, _success_decorators, { kind: "field", name: "success", static: false, private: false, access: { has: obj => "success" in obj, get: obj => obj.success, set: (obj, value) => { obj.success = value; } }, metadata: _metadata }, _success_initializers, _success_extraInitializers);
86
- __esDecorate(null, null, _requestedAuthSource_decorators, { kind: "field", name: "requestedAuthSource", static: false, private: false, access: { has: obj => "requestedAuthSource" in obj, get: obj => obj.requestedAuthSource, set: (obj, value) => { obj.requestedAuthSource = value; } }, metadata: _metadata }, _requestedAuthSource_initializers, _requestedAuthSource_extraInitializers);
87
- __esDecorate(null, null, _resolvedAuthSource_decorators, { kind: "field", name: "resolvedAuthSource", static: false, private: false, access: { has: obj => "resolvedAuthSource" in obj, get: obj => obj.resolvedAuthSource, set: (obj, value) => { obj.resolvedAuthSource = value; } }, metadata: _metadata }, _resolvedAuthSource_initializers, _resolvedAuthSource_extraInitializers);
88
- __esDecorate(null, null, _failureReason_decorators, { kind: "field", name: "failureReason", static: false, private: false, access: { has: obj => "failureReason" in obj, get: obj => obj.failureReason, set: (obj, value) => { obj.failureReason = value; } }, metadata: _metadata }, _failureReason_initializers, _failureReason_extraInitializers);
89
- __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
90
- AuthenticationEventDoc = _classThis = _classDescriptor.value;
91
- if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
92
- __runInitializers(_classThis, _classExtraInitializers);
5
+ export class AuthenticationEventDoc extends plugins.smartdata.SmartDataDbDoc {
6
+ id;
7
+ timestamp;
8
+ username;
9
+ userId;
10
+ success;
11
+ requestedAuthSource;
12
+ resolvedAuthSource;
13
+ failureReason;
14
+ constructor() {
15
+ super();
16
+ }
17
+ toApiObject() {
18
+ return {
19
+ id: this.id,
20
+ timestamp: this.timestamp,
21
+ username: this.username,
22
+ success: this.success,
23
+ requestedAuthSource: this.requestedAuthSource,
24
+ ...(this.userId ? { userId: this.userId } : {}),
25
+ ...(this.resolvedAuthSource ? { resolvedAuthSource: this.resolvedAuthSource } : {}),
26
+ ...(this.failureReason ? { failureReason: this.failureReason } : {}),
27
+ };
28
+ }
29
+ static toPersistedFields(eventArg) {
30
+ return {
31
+ id: eventArg.id,
32
+ timestamp: eventArg.timestamp,
33
+ username: eventArg.username,
34
+ success: eventArg.success,
35
+ requestedAuthSource: eventArg.requestedAuthSource,
36
+ ...(eventArg.userId !== undefined ? { userId: eventArg.userId } : {}),
37
+ ...(eventArg.resolvedAuthSource !== undefined
38
+ ? { resolvedAuthSource: eventArg.resolvedAuthSource }
39
+ : {}),
40
+ ...(eventArg.failureReason !== undefined ? { failureReason: eventArg.failureReason } : {}),
41
+ };
42
+ }
43
+ static validateEvent(eventArg) {
44
+ if (typeof eventArg.id !== 'string'
45
+ || !eventArg.id.trim()
46
+ || !Number.isSafeInteger(eventArg.timestamp)
47
+ || eventArg.timestamp < 0
48
+ || typeof eventArg.username !== 'string'
49
+ || !eventArg.username.trim()
50
+ || typeof eventArg.success !== 'boolean'
51
+ || !['auto', 'local', 'idp.global'].includes(eventArg.requestedAuthSource)) {
52
+ throw new Error('Invalid authentication event');
93
53
  }
94
- id = __runInitializers(this, _id_initializers, void 0);
95
- timestamp = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _timestamp_initializers, void 0));
96
- username = (__runInitializers(this, _timestamp_extraInitializers), __runInitializers(this, _username_initializers, void 0));
97
- userId = (__runInitializers(this, _username_extraInitializers), __runInitializers(this, _userId_initializers, void 0));
98
- success = (__runInitializers(this, _userId_extraInitializers), __runInitializers(this, _success_initializers, void 0));
99
- requestedAuthSource = (__runInitializers(this, _success_extraInitializers), __runInitializers(this, _requestedAuthSource_initializers, void 0));
100
- resolvedAuthSource = (__runInitializers(this, _requestedAuthSource_extraInitializers), __runInitializers(this, _resolvedAuthSource_initializers, void 0));
101
- failureReason = (__runInitializers(this, _resolvedAuthSource_extraInitializers), __runInitializers(this, _failureReason_initializers, void 0));
102
- constructor() {
103
- super();
104
- __runInitializers(this, _failureReason_extraInitializers);
54
+ if (eventArg.userId !== undefined
55
+ && (typeof eventArg.userId !== 'string' || !eventArg.userId.trim())) {
56
+ throw new Error('Invalid authentication event user ID');
105
57
  }
106
- toApiObject() {
107
- return {
108
- id: this.id,
109
- timestamp: this.timestamp,
110
- username: this.username,
111
- success: this.success,
112
- requestedAuthSource: this.requestedAuthSource,
113
- ...(this.userId ? { userId: this.userId } : {}),
114
- ...(this.resolvedAuthSource ? { resolvedAuthSource: this.resolvedAuthSource } : {}),
115
- ...(this.failureReason ? { failureReason: this.failureReason } : {}),
116
- };
58
+ if (eventArg.resolvedAuthSource !== undefined
59
+ && eventArg.resolvedAuthSource !== 'local'
60
+ && eventArg.resolvedAuthSource !== 'idp.global') {
61
+ throw new Error('Invalid resolved authentication source');
117
62
  }
118
- static async getNativeCollection() {
119
- const smartdataCollection = AuthenticationEventDoc.collection;
120
- await smartdataCollection.init();
121
- const probe = new AuthenticationEventDoc();
122
- await smartdataCollection.markUniqueIndexes(probe.uniqueIndexes || []);
123
- await smartdataCollection.createRegularIndexes(probe.regularIndexes || []);
124
- return smartdataCollection.mongoDbCollection;
63
+ if (eventArg.failureReason !== undefined
64
+ && ![
65
+ 'invalidCredentials',
66
+ 'serviceUnavailable',
67
+ 'identityIssuanceFailed',
68
+ 'internalError',
69
+ ].includes(eventArg.failureReason)) {
70
+ throw new Error('Invalid authentication failure reason');
125
71
  }
126
- static toPersistedFields(eventArg) {
127
- return {
128
- id: eventArg.id,
129
- timestamp: eventArg.timestamp,
130
- username: eventArg.username,
131
- success: eventArg.success,
132
- requestedAuthSource: eventArg.requestedAuthSource,
133
- ...(eventArg.userId !== undefined ? { userId: eventArg.userId } : {}),
134
- ...(eventArg.resolvedAuthSource !== undefined
135
- ? { resolvedAuthSource: eventArg.resolvedAuthSource }
136
- : {}),
137
- ...(eventArg.failureReason !== undefined ? { failureReason: eventArg.failureReason } : {}),
138
- };
72
+ if (eventArg.success && eventArg.failureReason) {
73
+ throw new Error('Successful authentication events cannot carry a failure reason');
139
74
  }
140
- static validateEvent(eventArg) {
141
- if (typeof eventArg.id !== 'string'
142
- || !eventArg.id.trim()
143
- || !Number.isSafeInteger(eventArg.timestamp)
144
- || eventArg.timestamp < 0
145
- || typeof eventArg.username !== 'string'
146
- || !eventArg.username.trim()
147
- || typeof eventArg.success !== 'boolean'
148
- || !['auto', 'local', 'idp.global'].includes(eventArg.requestedAuthSource)) {
149
- throw new Error('Invalid authentication event');
150
- }
151
- if (eventArg.userId !== undefined
152
- && (typeof eventArg.userId !== 'string' || !eventArg.userId.trim())) {
153
- throw new Error('Invalid authentication event user ID');
154
- }
155
- if (eventArg.resolvedAuthSource !== undefined
156
- && eventArg.resolvedAuthSource !== 'local'
157
- && eventArg.resolvedAuthSource !== 'idp.global') {
158
- throw new Error('Invalid resolved authentication source');
159
- }
160
- if (eventArg.failureReason !== undefined
161
- && ![
162
- 'invalidCredentials',
163
- 'serviceUnavailable',
164
- 'identityIssuanceFailed',
165
- 'internalError',
166
- ].includes(eventArg.failureReason)) {
167
- throw new Error('Invalid authentication failure reason');
168
- }
169
- if (eventArg.success && eventArg.failureReason) {
170
- throw new Error('Successful authentication events cannot carry a failure reason');
171
- }
172
- if (!eventArg.success && !eventArg.failureReason) {
173
- throw new Error('Failed authentication events require a failure reason');
174
- }
75
+ if (!eventArg.success && !eventArg.failureReason) {
76
+ throw new Error('Failed authentication events require a failure reason');
175
77
  }
176
- static async upsertMany(eventsArg) {
177
- if (eventsArg.length === 0)
178
- return;
179
- if (eventsArg.length > 500) {
180
- throw new Error('AuthenticationEventDoc.upsertMany accepts at most 500 events');
181
- }
182
- for (const event of eventsArg) {
183
- AuthenticationEventDoc.validateEvent(event);
184
- }
185
- const collection = await AuthenticationEventDoc.getNativeCollection();
186
- await collection.bulkWrite(eventsArg.map((event) => {
187
- const timestamp = new Date(event.timestamp).toISOString();
188
- const persistedEvent = AuthenticationEventDoc.toPersistedFields(event);
189
- return {
190
- updateOne: {
191
- filter: { id: event.id },
192
- update: {
193
- $setOnInsert: {
194
- ...persistedEvent,
195
- _createdAt: timestamp,
196
- _updatedAt: timestamp,
197
- },
198
- },
199
- upsert: true,
200
- },
201
- };
202
- }), { ordered: false, timeoutMS: DB_OPERATION_TIMEOUT_MS });
78
+ }
79
+ static async upsertMany(eventsArg) {
80
+ if (eventsArg.length === 0)
81
+ return;
82
+ if (eventsArg.length > 500) {
83
+ throw new Error('AuthenticationEventDoc.upsertMany accepts at most 500 events');
203
84
  }
204
- static async getWindowSummary(cutoffArg, limitArg = 100) {
205
- if (!Number.isSafeInteger(cutoffArg) || cutoffArg < 0) {
206
- throw new Error('AuthenticationEventDoc.getWindowSummary requires a valid cutoff');
207
- }
208
- if (!Number.isSafeInteger(limitArg) || limitArg <= 0 || limitArg > 500) {
209
- throw new Error('AuthenticationEventDoc.getWindowSummary requires a limit from 1 to 500');
210
- }
211
- const collection = await AuthenticationEventDoc.getNativeCollection();
212
- const selector = { timestamp: { $gte: cutoffArg } };
213
- const cursor = collection
214
- .find(selector, { timeoutMS: DB_OPERATION_TIMEOUT_MS })
215
- .sort({ timestamp: -1, id: -1 })
216
- .limit(limitArg);
217
- try {
218
- const [successes, failures, rows] = await Promise.all([
219
- collection.countDocuments({ ...selector, success: true }, { timeoutMS: DB_OPERATION_TIMEOUT_MS }),
220
- collection.countDocuments({ ...selector, success: false }, { timeoutMS: DB_OPERATION_TIMEOUT_MS }),
221
- cursor.toArray(),
222
- ]);
223
- return {
224
- successes,
225
- failures,
226
- events: rows.map((row) => AuthenticationEventDoc
227
- .createInstanceFromMongoDbNativeDoc(row)
228
- .toApiObject()),
229
- };
230
- }
231
- finally {
232
- await cursor.close({ timeoutMS: DB_OPERATION_TIMEOUT_MS });
233
- }
85
+ for (const event of eventsArg) {
86
+ AuthenticationEventDoc.validateEvent(event);
234
87
  }
235
- static async findExistingIds(idsArg) {
236
- const ids = [...new Set(idsArg)];
237
- if (ids.length === 0)
238
- return new Set();
239
- if (ids.length > 500) {
240
- throw new Error('AuthenticationEventDoc.findExistingIds accepts at most 500 ids');
241
- }
242
- const collection = await AuthenticationEventDoc.getNativeCollection();
243
- const rows = await collection
244
- .find({ id: { $in: ids } }, { projection: { id: 1 }, timeoutMS: DB_OPERATION_TIMEOUT_MS })
245
- .toArray();
246
- return new Set(rows.map((row) => String(row.id)));
88
+ const documents = new Map();
89
+ for (const event of eventsArg) {
90
+ if (documents.has(event.id))
91
+ continue;
92
+ const timestamp = new Date(event.timestamp).toISOString();
93
+ documents.set(event.id, Object.assign(new AuthenticationEventDoc(), {
94
+ ...AuthenticationEventDoc.toPersistedFields(event),
95
+ _createdAt: timestamp,
96
+ _updatedAt: timestamp,
97
+ }));
247
98
  }
248
- static async pruneBefore(cutoffArg) {
249
- if (!Number.isSafeInteger(cutoffArg) || cutoffArg < 0) {
250
- throw new Error('AuthenticationEventDoc.pruneBefore requires a valid cutoff');
251
- }
252
- const collection = await AuthenticationEventDoc.getNativeCollection();
253
- let deletedCount = 0;
254
- while (true) {
255
- const rows = await collection
256
- .find({ timestamp: { $lt: cutoffArg } }, { projection: { _id: 1 }, timeoutMS: DB_OPERATION_TIMEOUT_MS })
257
- .sort({ timestamp: 1, _id: 1 })
258
- .limit(500)
259
- .toArray();
260
- if (rows.length === 0)
261
- break;
262
- const result = await collection.deleteMany({ _id: { $in: rows.map((row) => row._id) } }, { timeoutMS: DB_OPERATION_TIMEOUT_MS });
263
- deletedCount += result.deletedCount;
264
- if (rows.length < 500)
265
- break;
266
- }
267
- return deletedCount;
99
+ await AuthenticationEventDoc.insertManyIfAbsent([...documents.values()], {
100
+ identityField: 'id', timeoutMS: DB_OPERATION_TIMEOUT_MS,
101
+ });
102
+ }
103
+ static async getWindowSummary(cutoffArg, limitArg = 100) {
104
+ if (!Number.isSafeInteger(cutoffArg) || cutoffArg < 0) {
105
+ throw new Error('AuthenticationEventDoc.getWindowSummary requires a valid cutoff');
268
106
  }
269
- };
270
- return AuthenticationEventDoc = _classThis;
271
- })();
272
- export { AuthenticationEventDoc };
273
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRoZW50aWNhdGlvbi1ldmVudC5kb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9kYi9kb2N1bWVudHMvY2xhc3Nlcy5hdXRoZW50aWNhdGlvbi1ldmVudC5kb2MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBUXZELE1BQU0sdUJBQXVCLEdBQUcsS0FBSyxDQUFDO0FBRXRDLE1BQU0sS0FBSyxHQUFHLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUd4QyxzQkFBc0I7NEJBRGxDLE9BQU8sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDOzs7O3NCQUNBLE9BQU8sQ0FBQyxTQUFTLENBQUMsY0FBYzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztzQ0FBeEMsU0FBUSxXQUczQzs7Ozs4QkFDRSxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUN2QixPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRTtxQ0FHeEIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUU7b0NBR3hCLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFO2tDQUd4QixPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRTttQ0FHeEIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUU7K0NBR3hCLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFOzhDQUd4QixPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRTt5Q0FHeEIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUU7WUFwQnpCLHdKQUFP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
107
+ if (!Number.isSafeInteger(limitArg) || limitArg <= 0 || limitArg > 500) {
108
+ throw new Error('AuthenticationEventDoc.getWindowSummary requires a limit from 1 to 500');
109
+ }
110
+ await AuthenticationEventDoc.ensureInitialized();
111
+ const selector = { timestamp: { $gte: cutoffArg } };
112
+ const [totalsResult, rowsResult] = await Promise.allSettled([
113
+ AuthenticationEventDoc.getGroupedTotals({
114
+ filter: selector, groupBy: ['success'], limit: 3,
115
+ maxTimeMS: DB_OPERATION_TIMEOUT_MS, timeoutMS: DB_OPERATION_TIMEOUT_MS,
116
+ }),
117
+ AuthenticationEventDoc.getOffsetPage(selector, {
118
+ skip: 0, limit: limitArg, sort: { timestamp: -1, id: -1 },
119
+ maxTimeMS: DB_OPERATION_TIMEOUT_MS, timeoutMS: DB_OPERATION_TIMEOUT_MS,
120
+ }),
121
+ ]);
122
+ // Both public queries own a cursor; drain both before releasing this computation.
123
+ if (totalsResult.status === 'rejected')
124
+ throw totalsResult.reason;
125
+ if (rowsResult.status === 'rejected')
126
+ throw rowsResult.reason;
127
+ const totals = totalsResult.value;
128
+ const rows = rowsResult.value;
129
+ let successes = 0;
130
+ let failures = 0;
131
+ for (const total of totals) {
132
+ if (total.group.success === true)
133
+ successes = total.count;
134
+ else if (total.group.success === false)
135
+ failures = total.count;
136
+ else
137
+ throw new Error('Authentication events contain an invalid success value');
138
+ }
139
+ return { successes, failures, events: rows.map((row) => row.toApiObject()) };
140
+ }
141
+ static async findExistingIds(idsArg) {
142
+ const ids = [...new Set(idsArg)];
143
+ if (ids.length === 0)
144
+ return new Set();
145
+ if (ids.length > 500) {
146
+ throw new Error('AuthenticationEventDoc.findExistingIds accepts at most 500 ids');
147
+ }
148
+ await AuthenticationEventDoc.ensureInitialized();
149
+ const rows = await AuthenticationEventDoc.getOffsetPage({ id: { $in: ids } }, {
150
+ skip: 0, limit: ids.length, sort: { id: 1 }, projection: { id: 1, _id: 0 },
151
+ maxTimeMS: DB_OPERATION_TIMEOUT_MS, timeoutMS: DB_OPERATION_TIMEOUT_MS,
152
+ });
153
+ return new Set(rows.map((row) => row.id));
154
+ }
155
+ static async pruneBefore(cutoffArg) {
156
+ if (!Number.isSafeInteger(cutoffArg) || cutoffArg < 0) {
157
+ throw new Error('AuthenticationEventDoc.pruneBefore requires a valid cutoff');
158
+ }
159
+ await AuthenticationEventDoc.ensureInitialized();
160
+ let deletedCount = 0;
161
+ while (true) {
162
+ const rows = await AuthenticationEventDoc.getOffsetPage({ timestamp: { $lt: cutoffArg } }, {
163
+ skip: 0, limit: 500, sort: { timestamp: 1, id: 1 }, projection: { id: 1, _id: 0 },
164
+ maxTimeMS: DB_OPERATION_TIMEOUT_MS, timeoutMS: DB_OPERATION_TIMEOUT_MS,
165
+ });
166
+ if (rows.length === 0)
167
+ break;
168
+ const result = await AuthenticationEventDoc.atomicDeleteMany({ timestamp: { $lt: cutoffArg }, $or: rows.map((row) => ({ id: row.id })) }, { timeoutMS: DB_OPERATION_TIMEOUT_MS });
169
+ deletedCount += result.deletedCount;
170
+ if (rows.length < 500)
171
+ break;
172
+ }
173
+ return deletedCount;
174
+ }
175
+ }
176
+ // Match the names installed by create-monitoring-event-indexes on existing hubs.
177
+ plugins.smartdata.defineCollectionModel(AuthenticationEventDoc, getDb, {
178
+ collectionName: 'AuthenticationEventDoc',
179
+ persistedFields: [
180
+ 'id', 'timestamp', 'username', 'userId', 'success',
181
+ 'requestedAuthSource', 'resolvedAuthSource', 'failureReason',
182
+ ],
183
+ identityFields: ['id'],
184
+ indexes: [
185
+ { name: 'authentication_event_id_unique', key: { id: 1 }, options: { unique: true } },
186
+ { name: 'authentication_event_timestamp', key: { timestamp: -1 } },
187
+ { name: 'authentication_event_success_timestamp', key: { success: 1, timestamp: -1 } },
188
+ ],
189
+ });
190
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRoZW50aWNhdGlvbi1ldmVudC5kb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9kYi9kb2N1bWVudHMvY2xhc3Nlcy5hdXRoZW50aWNhdGlvbi1ldmVudC5kb2MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFRdkQsTUFBTSx1QkFBdUIsR0FBRyxLQUFLLENBQUM7QUFFdEMsTUFBTSxLQUFLLEdBQUcsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBRXJELE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLGNBRzdEO0lBQ1EsRUFBRSxDQUFVO0lBRVosU0FBUyxDQUFVO0lBRW5CLFFBQVEsQ0FBVTtJQUVsQixNQUFNLENBQVU7SUFFaEIsT0FBTyxDQUFXO0lBRWxCLG1CQUFtQixDQUF5QjtJQUU1QyxrQkFBa0IsQ0FBaUM7SUFFbkQsYUFBYSxDQUFnQztJQUVwRDtRQUNFLEtBQUssRUFBRSxDQUFDO0lBQ1YsQ0FBQztJQUVNLFdBQVc7UUFDaEIsT0FBTztZQUNMLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtZQUNYLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLG1CQUFtQixFQUFFLElBQUksQ0FBQyxtQkFBbUI7WUFDN0MsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQy9DLEdBQUcsQ0FBQyxJQUFJLENBQUMsa0JB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