mongodb 5.2.0 → 5.4.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/lib/admin.js +18 -0
- package/lib/admin.js.map +1 -1
- package/lib/bulk/common.js +28 -7
- package/lib/bulk/common.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +29 -2
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js +5 -3
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/cache.js +28 -0
- package/lib/cmap/auth/mongodb_oidc/cache.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js +83 -0
- package/lib/cmap/auth/mongodb_oidc/callback_lock_cache.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +138 -112
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js +4 -2
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js +12 -56
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js +17 -13
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/command_monitoring_events.js +6 -0
- package/lib/cmap/command_monitoring_events.js.map +1 -1
- package/lib/cmap/connect.js +1 -0
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +12 -12
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +7 -3
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/connection_pool_events.js +28 -3
- package/lib/cmap/connection_pool_events.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +173 -0
- package/lib/cmap/handshake/client_metadata.js.map +1 -0
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/cmap/wire_protocol/shared.js +2 -2
- package/lib/cmap/wire_protocol/shared.js.map +1 -1
- package/lib/collection.js +3 -0
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +48 -53
- package/lib/connection_string.js.map +1 -1
- package/lib/constants.js +11 -0
- package/lib/constants.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +1 -0
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/db.js +18 -0
- package/lib/db.js.map +1 -1
- package/lib/mongo_client.js +16 -0
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_logger.js +258 -27
- package/lib/mongo_logger.js.map +1 -1
- package/lib/operations/add_user.js.map +1 -1
- package/lib/operations/find.js +0 -7
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/stats.js.map +1 -1
- package/lib/operations/update.js.map +1 -1
- package/lib/sdam/srv_polling.js +1 -15
- package/lib/sdam/srv_polling.js.map +1 -1
- package/lib/sdam/topology.js.map +1 -1
- package/lib/utils.js +48 -35
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +247 -47
- package/package.json +3 -3
- package/src/admin.ts +18 -0
- package/src/bulk/common.ts +28 -7
- package/src/change_stream.ts +1 -1
- package/src/cmap/auth/mongo_credentials.ts +35 -2
- package/src/cmap/auth/mongodb_oidc/aws_service_workflow.ts +6 -3
- package/src/cmap/auth/mongodb_oidc/cache.ts +27 -0
- package/src/cmap/auth/mongodb_oidc/callback_lock_cache.ts +107 -0
- package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +208 -171
- package/src/cmap/auth/mongodb_oidc/service_workflow.ts +5 -3
- package/src/cmap/auth/mongodb_oidc/token_entry_cache.ts +17 -96
- package/src/cmap/auth/mongodb_oidc.ts +61 -37
- package/src/cmap/command_monitoring_events.ts +13 -1
- package/src/cmap/connect.ts +3 -1
- package/src/cmap/connection.ts +16 -13
- package/src/cmap/connection_pool.ts +14 -4
- package/src/cmap/connection_pool_events.ts +68 -6
- package/src/cmap/handshake/client_metadata.ts +272 -0
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/cmap/wire_protocol/shared.ts +2 -3
- package/src/collection.ts +6 -3
- package/src/connection_string.ts +55 -55
- package/src/constants.ts +11 -0
- package/src/cursor/abstract_cursor.ts +1 -0
- package/src/db.ts +18 -0
- package/src/index.ts +24 -6
- package/src/mongo_client.ts +50 -6
- package/src/mongo_logger.ts +363 -44
- package/src/operations/add_user.ts +8 -2
- package/src/operations/find.ts +0 -10
- package/src/operations/run_command.ts +40 -3
- package/src/operations/stats.ts +11 -2
- package/src/operations/update.ts +8 -4
- package/src/sdam/srv_polling.ts +1 -16
- package/src/sdam/topology.ts +1 -3
- package/src/utils.ts +54 -73
- package/lib/cmap/auth/mongodb_oidc/workflow.js +0 -3
- package/lib/cmap/auth/mongodb_oidc/workflow.js.map +0 -1
- package/src/cmap/auth/mongodb_oidc/workflow.ts +0 -21
package/src/bulk/common.ts
CHANGED
|
@@ -212,37 +212,58 @@ export class BulkWriteResult {
|
|
|
212
212
|
return this.result.ok;
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
/**
|
|
215
|
+
/**
|
|
216
|
+
* The number of inserted documents
|
|
217
|
+
* @deprecated Use insertedCount instead.
|
|
218
|
+
*/
|
|
216
219
|
get nInserted(): number {
|
|
217
220
|
return this.result.nInserted;
|
|
218
221
|
}
|
|
219
222
|
|
|
220
|
-
/**
|
|
223
|
+
/**
|
|
224
|
+
* Number of upserted documents
|
|
225
|
+
* @deprecated User upsertedCount instead.
|
|
226
|
+
*/
|
|
221
227
|
get nUpserted(): number {
|
|
222
228
|
return this.result.nUpserted;
|
|
223
229
|
}
|
|
224
230
|
|
|
225
|
-
/**
|
|
231
|
+
/**
|
|
232
|
+
* Number of matched documents
|
|
233
|
+
* @deprecated Use matchedCount instead.
|
|
234
|
+
*/
|
|
226
235
|
get nMatched(): number {
|
|
227
236
|
return this.result.nMatched;
|
|
228
237
|
}
|
|
229
238
|
|
|
230
|
-
/**
|
|
239
|
+
/**
|
|
240
|
+
* Number of documents updated physically on disk
|
|
241
|
+
* @deprecated Use modifiedCount instead.
|
|
242
|
+
*/
|
|
231
243
|
get nModified(): number {
|
|
232
244
|
return this.result.nModified;
|
|
233
245
|
}
|
|
234
246
|
|
|
235
|
-
/**
|
|
247
|
+
/**
|
|
248
|
+
* Number of removed documents
|
|
249
|
+
* @deprecated Use deletedCount instead.
|
|
250
|
+
*/
|
|
236
251
|
get nRemoved(): number {
|
|
237
252
|
return this.result.nRemoved;
|
|
238
253
|
}
|
|
239
254
|
|
|
240
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* Returns an array of all inserted ids
|
|
257
|
+
* @deprecated Use insertedIds instead.
|
|
258
|
+
*/
|
|
241
259
|
getInsertedIds(): Document[] {
|
|
242
260
|
return this.result.insertedIds;
|
|
243
261
|
}
|
|
244
262
|
|
|
245
|
-
/**
|
|
263
|
+
/**
|
|
264
|
+
* Returns an array of all upserted ids
|
|
265
|
+
* @deprecated Use upsertedIds instead.
|
|
266
|
+
*/
|
|
246
267
|
getUpsertedIds(): Document[] {
|
|
247
268
|
return this.result.upserted;
|
|
248
269
|
}
|
package/src/change_stream.ts
CHANGED
|
@@ -700,7 +700,7 @@ export class ChangeStream<
|
|
|
700
700
|
/**
|
|
701
701
|
* Try to get the next available document from the Change Stream's cursor or `null` if an empty batch is returned
|
|
702
702
|
*/
|
|
703
|
-
async tryNext(): Promise<
|
|
703
|
+
async tryNext(): Promise<TChange | null> {
|
|
704
704
|
this._setIsIterator();
|
|
705
705
|
// Change streams must resume indefinitely while each resume event succeeds.
|
|
706
706
|
// This loop continues until either a change event is received or until a resume attempt
|
|
@@ -30,6 +30,18 @@ function getDefaultAuthMechanism(hello?: Document): AuthMechanism {
|
|
|
30
30
|
return AuthMechanism.MONGODB_CR;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const ALLOWED_HOSTS_ERROR = 'Auth mechanism property ALLOWED_HOSTS must be an array of strings.';
|
|
34
|
+
|
|
35
|
+
/** @internal */
|
|
36
|
+
export const DEFAULT_ALLOWED_HOSTS = [
|
|
37
|
+
'*.mongodb.net',
|
|
38
|
+
'*.mongodb-dev.net',
|
|
39
|
+
'*.mongodbgov.net',
|
|
40
|
+
'localhost',
|
|
41
|
+
'127.0.0.1',
|
|
42
|
+
'::1'
|
|
43
|
+
];
|
|
44
|
+
|
|
33
45
|
/** @public */
|
|
34
46
|
export interface AuthMechanismProperties extends Document {
|
|
35
47
|
SERVICE_HOST?: string;
|
|
@@ -43,11 +55,13 @@ export interface AuthMechanismProperties extends Document {
|
|
|
43
55
|
REFRESH_TOKEN_CALLBACK?: OIDCRefreshFunction;
|
|
44
56
|
/** @experimental */
|
|
45
57
|
PROVIDER_NAME?: 'aws';
|
|
58
|
+
/** @experimental */
|
|
59
|
+
ALLOWED_HOSTS?: string[];
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
/** @public */
|
|
49
63
|
export interface MongoCredentialsOptions {
|
|
50
|
-
username
|
|
64
|
+
username?: string;
|
|
51
65
|
password: string;
|
|
52
66
|
source: string;
|
|
53
67
|
db?: string;
|
|
@@ -72,7 +86,7 @@ export class MongoCredentials {
|
|
|
72
86
|
readonly mechanismProperties: AuthMechanismProperties;
|
|
73
87
|
|
|
74
88
|
constructor(options: MongoCredentialsOptions) {
|
|
75
|
-
this.username = options.username;
|
|
89
|
+
this.username = options.username ?? '';
|
|
76
90
|
this.password = options.password;
|
|
77
91
|
this.source = options.source;
|
|
78
92
|
if (!this.source && options.db) {
|
|
@@ -101,6 +115,13 @@ export class MongoCredentials {
|
|
|
101
115
|
}
|
|
102
116
|
}
|
|
103
117
|
|
|
118
|
+
if (this.mechanism === AuthMechanism.MONGODB_OIDC && !this.mechanismProperties.ALLOWED_HOSTS) {
|
|
119
|
+
this.mechanismProperties = {
|
|
120
|
+
...this.mechanismProperties,
|
|
121
|
+
ALLOWED_HOSTS: DEFAULT_ALLOWED_HOSTS
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
104
125
|
Object.freeze(this.mechanismProperties);
|
|
105
126
|
Object.freeze(this);
|
|
106
127
|
}
|
|
@@ -181,6 +202,18 @@ export class MongoCredentials {
|
|
|
181
202
|
`Either a PROVIDER_NAME or a REQUEST_TOKEN_CALLBACK must be specified for mechanism '${this.mechanism}'.`
|
|
182
203
|
);
|
|
183
204
|
}
|
|
205
|
+
|
|
206
|
+
if (this.mechanismProperties.ALLOWED_HOSTS) {
|
|
207
|
+
const hosts = this.mechanismProperties.ALLOWED_HOSTS;
|
|
208
|
+
if (!Array.isArray(hosts)) {
|
|
209
|
+
throw new MongoInvalidArgumentError(ALLOWED_HOSTS_ERROR);
|
|
210
|
+
}
|
|
211
|
+
for (const host of hosts) {
|
|
212
|
+
if (typeof host !== 'string') {
|
|
213
|
+
throw new MongoInvalidArgumentError(ALLOWED_HOSTS_ERROR);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
184
217
|
}
|
|
185
218
|
|
|
186
219
|
if (AUTH_MECHS_AUTH_SRC_EXTERNAL.has(this.mechanism)) {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs from 'fs';
|
|
2
2
|
|
|
3
3
|
import { MongoAWSError } from '../../../error';
|
|
4
4
|
import { ServiceWorkflow } from './service_workflow';
|
|
5
5
|
|
|
6
|
+
/** Error for when the token is missing in the environment. */
|
|
7
|
+
const TOKEN_MISSING_ERROR = 'AWS_WEB_IDENTITY_TOKEN_FILE must be set in the environment.';
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
* Device workflow implementation for AWS.
|
|
8
11
|
*
|
|
@@ -19,8 +22,8 @@ export class AwsServiceWorkflow extends ServiceWorkflow {
|
|
|
19
22
|
async getToken(): Promise<string> {
|
|
20
23
|
const tokenFile = process.env.AWS_WEB_IDENTITY_TOKEN_FILE;
|
|
21
24
|
if (!tokenFile) {
|
|
22
|
-
throw new MongoAWSError(
|
|
25
|
+
throw new MongoAWSError(TOKEN_MISSING_ERROR);
|
|
23
26
|
}
|
|
24
|
-
return readFile(tokenFile, 'utf8');
|
|
27
|
+
return fs.promises.readFile(tokenFile, 'utf8');
|
|
25
28
|
}
|
|
26
29
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for OIDC caches.
|
|
3
|
+
*/
|
|
4
|
+
export abstract class Cache<T> {
|
|
5
|
+
entries: Map<string, T>;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create a new cache.
|
|
9
|
+
*/
|
|
10
|
+
constructor() {
|
|
11
|
+
this.entries = new Map<string, T>();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Clear the cache.
|
|
16
|
+
*/
|
|
17
|
+
clear() {
|
|
18
|
+
this.entries.clear();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a cache key from the address and username.
|
|
23
|
+
*/
|
|
24
|
+
cacheKey(address: string, username: string, callbackHash: string): string {
|
|
25
|
+
return JSON.stringify([address, username, callbackHash]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { MongoInvalidArgumentError } from '../../../error';
|
|
2
|
+
import type { Connection } from '../../connection';
|
|
3
|
+
import type { MongoCredentials } from '../mongo_credentials';
|
|
4
|
+
import type {
|
|
5
|
+
IdPServerInfo,
|
|
6
|
+
IdPServerResponse,
|
|
7
|
+
OIDCCallbackContext,
|
|
8
|
+
OIDCRefreshFunction,
|
|
9
|
+
OIDCRequestFunction
|
|
10
|
+
} from '../mongodb_oidc';
|
|
11
|
+
import { Cache } from './cache';
|
|
12
|
+
|
|
13
|
+
/** Error message for when request callback is missing. */
|
|
14
|
+
const REQUEST_CALLBACK_REQUIRED_ERROR =
|
|
15
|
+
'Auth mechanism property REQUEST_TOKEN_CALLBACK is required.';
|
|
16
|
+
/* Counter for function "hashes".*/
|
|
17
|
+
let FN_HASH_COUNTER = 0;
|
|
18
|
+
/* No function present function */
|
|
19
|
+
const NO_FUNCTION: OIDCRequestFunction = async () => ({ accessToken: 'test' });
|
|
20
|
+
/* The map of function hashes */
|
|
21
|
+
const FN_HASHES = new WeakMap<OIDCRequestFunction | OIDCRefreshFunction, number>();
|
|
22
|
+
/* Put the no function hash in the map. */
|
|
23
|
+
FN_HASHES.set(NO_FUNCTION, FN_HASH_COUNTER);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* An entry of callbacks in the cache.
|
|
27
|
+
*/
|
|
28
|
+
interface CallbacksEntry {
|
|
29
|
+
requestCallback: OIDCRequestFunction;
|
|
30
|
+
refreshCallback?: OIDCRefreshFunction;
|
|
31
|
+
callbackHash: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A cache of request and refresh callbacks per server/user.
|
|
36
|
+
*/
|
|
37
|
+
export class CallbackLockCache extends Cache<CallbacksEntry> {
|
|
38
|
+
/**
|
|
39
|
+
* Get the callbacks for the connection and credentials. If an entry does not
|
|
40
|
+
* exist a new one will get set.
|
|
41
|
+
*/
|
|
42
|
+
getCallbacks(connection: Connection, credentials: MongoCredentials): CallbacksEntry {
|
|
43
|
+
const requestCallback = credentials.mechanismProperties.REQUEST_TOKEN_CALLBACK;
|
|
44
|
+
const refreshCallback = credentials.mechanismProperties.REFRESH_TOKEN_CALLBACK;
|
|
45
|
+
if (!requestCallback) {
|
|
46
|
+
throw new MongoInvalidArgumentError(REQUEST_CALLBACK_REQUIRED_ERROR);
|
|
47
|
+
}
|
|
48
|
+
const callbackHash = hashFunctions(requestCallback, refreshCallback);
|
|
49
|
+
const key = this.cacheKey(connection.address, credentials.username, callbackHash);
|
|
50
|
+
const entry = this.entries.get(key);
|
|
51
|
+
if (entry) {
|
|
52
|
+
return entry;
|
|
53
|
+
}
|
|
54
|
+
return this.setCallbacks(key, callbackHash, requestCallback, refreshCallback);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Set locked callbacks on for connection and credentials.
|
|
59
|
+
*/
|
|
60
|
+
private setCallbacks(
|
|
61
|
+
key: string,
|
|
62
|
+
callbackHash: string,
|
|
63
|
+
requestCallback: OIDCRequestFunction,
|
|
64
|
+
refreshCallback?: OIDCRefreshFunction
|
|
65
|
+
): CallbacksEntry {
|
|
66
|
+
const entry = {
|
|
67
|
+
requestCallback: withLock(requestCallback),
|
|
68
|
+
refreshCallback: refreshCallback ? withLock(refreshCallback) : undefined,
|
|
69
|
+
callbackHash: callbackHash
|
|
70
|
+
};
|
|
71
|
+
this.entries.set(key, entry);
|
|
72
|
+
return entry;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Ensure the callback is only executed one at a time.
|
|
78
|
+
*/
|
|
79
|
+
function withLock(callback: OIDCRequestFunction | OIDCRefreshFunction) {
|
|
80
|
+
let lock: Promise<any> = Promise.resolve();
|
|
81
|
+
return async (info: IdPServerInfo, context: OIDCCallbackContext): Promise<IdPServerResponse> => {
|
|
82
|
+
await lock;
|
|
83
|
+
lock = lock.then(() => callback(info, context));
|
|
84
|
+
return lock;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get the hash string for the request and refresh functions.
|
|
90
|
+
*/
|
|
91
|
+
function hashFunctions(requestFn: OIDCRequestFunction, refreshFn?: OIDCRefreshFunction): string {
|
|
92
|
+
let requestHash = FN_HASHES.get(requestFn);
|
|
93
|
+
let refreshHash = FN_HASHES.get(refreshFn ?? NO_FUNCTION);
|
|
94
|
+
if (requestHash == null) {
|
|
95
|
+
// Create a new one for the function and put it in the map.
|
|
96
|
+
FN_HASH_COUNTER++;
|
|
97
|
+
requestHash = FN_HASH_COUNTER;
|
|
98
|
+
FN_HASHES.set(requestFn, FN_HASH_COUNTER);
|
|
99
|
+
}
|
|
100
|
+
if (refreshHash == null && refreshFn) {
|
|
101
|
+
// Create a new one for the function and put it in the map.
|
|
102
|
+
FN_HASH_COUNTER++;
|
|
103
|
+
refreshHash = FN_HASH_COUNTER;
|
|
104
|
+
FN_HASHES.set(refreshFn, FN_HASH_COUNTER);
|
|
105
|
+
}
|
|
106
|
+
return `${requestHash}-${refreshHash}`;
|
|
107
|
+
}
|