Skip to content

Commit 51a573f

Browse files
authored
feat(NODE-4986)!: remove callbacks from ClientEncryption encrypt, decrypt, and createDataKey (#3797)
1 parent 1044be1 commit 51a573f

14 files changed

+129
-239
lines changed

Diff for: .evergreen/run-azure-kms-tests.sh

-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ source ".evergreen/init-node-and-npm-env.sh"
99

1010
set -o xtrace
1111

12-
npm install mongodb-client-encryption@alpha
13-
1412
export MONGODB_URI="mongodb://localhost:27017"
1513

1614
export EXPECTED_AZUREKMS_OUTCOME=${EXPECTED_AZUREKMS_OUTCOME:-omitted}

Diff for: .evergreen/run-custom-csfle-tests.sh

-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ bash ./etc/build-static.sh
5757

5858
npm run rebuild # just in case this is necessary?
5959

60-
ls
61-
ls lib
6260
BINDINGS_DIR=$(pwd)
6361
popd # libmongocrypt/bindings/node
6462
popd # ../csfle-deps-tmp

Diff for: .evergreen/run-gcp-kms-tests.sh

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ source ".evergreen/init-node-and-npm-env.sh"
99

1010
set -o xtrace
1111

12-
npm install mongodb-client-encryption@alpha
1312
npm install gcp-metadata
1413

1514
export MONGODB_URI="mongodb://localhost:27017"

Diff for: .evergreen/run-serverless-tests.sh

-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ if [ -z ${MONGODB_URI+omitted} ]; then echo "MONGODB_URI is unset" && exit 1; fi
1010
if [ -z ${SERVERLESS_ATLAS_USER+omitted} ]; then echo "SERVERLESS_ATLAS_USER is unset" && exit 1; fi
1111
if [ -z ${SERVERLESS_ATLAS_PASSWORD+omitted} ]; then echo "SERVERLESS_ATLAS_PASSWORD is unset" && exit 1; fi
1212

13-
npm install mongodb-client-encryption@alpha
14-
1513
npx mocha \
1614
--config test/mocha_mongodb.json \
1715
test/integration/crud/crud.spec.test.js \

Diff for: .evergreen/run-tests.sh

-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ else
5252
source "$DRIVERS_TOOLS"/.evergreen/csfle/set-temp-creds.sh
5353
fi
5454

55-
npm install mongodb-client-encryption@alpha
5655
npm install @mongodb-js/zstd
5756
npm install snappy
5857

Diff for: package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"js-yaml": "^4.1.0",
9999
"mocha": "^10.2.0",
100100
"mocha-sinon": "^2.1.2",
101-
"mongodb-client-encryption": "^6.0.0-alpha.1",
101+
"mongodb-client-encryption": "6.0.0-alpha.1",
102102
"mongodb-legacy": "^5.0.0",
103103
"nyc": "^15.1.0",
104104
"prettier": "^2.8.8",

Diff for: src/bson.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export {
1919
MinKey,
2020
ObjectId,
2121
serialize,
22-
Timestamp
22+
Timestamp,
23+
UUID
2324
} from 'bson';
2425

2526
/**

Diff for: src/client-side-encryption/client_encryption.ts

+29-97
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {
55
MongoCryptOptions
66
} from 'mongodb-client-encryption';
77

8-
import { type Binary, type Document, type Long, serialize } from '../bson';
8+
import { type Binary, type Document, type Long, serialize, type UUID } from '../bson';
99
import { type AnyBulkWriteOperation, type BulkWriteResult } from '../bulk/common';
1010
import { type ProxyOptions } from '../cmap/connection';
1111
import { type Collection } from '../collection';
@@ -16,8 +16,7 @@ import { type MongoClient } from '../mongo_client';
1616
import { type Filter } from '../mongo_types';
1717
import { type CreateCollectionOptions } from '../operations/create_collection';
1818
import { type DeleteResult } from '../operations/delete';
19-
import { type Callback, MongoDBCollectionNamespace } from '../utils';
20-
import { maybeCallback, promiseOrCallback } from './common';
19+
import { MongoDBCollectionNamespace } from '../utils';
2120
import * as cryptoCallbacks from './crypto_callbacks';
2221
import {
2322
MongoCryptCreateDataKeyError,
@@ -36,7 +35,7 @@ import { type CSFLEKMSTlsOptions, StateMachine } from './state_machine';
3635
* The schema for a DataKey in the key vault collection.
3736
*/
3837
export interface DataKey {
39-
_id: Binary;
38+
_id: UUID;
4039
version?: number;
4140
keyAltNames?: string[];
4241
keyMaterial: Binary;
@@ -133,18 +132,6 @@ export class ClientEncryption {
133132
*
134133
* @example
135134
* ```ts
136-
* // Using callbacks to create a local key
137-
* clientEncryption.createDataKey('local', (err, dataKey) => {
138-
* if (err) {
139-
* // This means creating the key failed.
140-
* } else {
141-
* // key creation succeeded
142-
* }
143-
* });
144-
* ```
145-
*
146-
* @example
147-
* ```ts
148135
* // Using async/await to create a local key
149136
* const dataKeyId = await clientEncryption.createDataKey('local');
150137
* ```
@@ -172,21 +159,10 @@ export class ClientEncryption {
172159
* });
173160
* ```
174161
*/
175-
createDataKey(
162+
async createDataKey(
176163
provider: ClientEncryptionDataKeyProvider,
177-
options?: ClientEncryptionCreateDataKeyProviderOptions,
178-
callback?: Callback<DataKey>
179-
) {
180-
if (typeof options === 'function') {
181-
callback = options;
182-
options = {};
183-
}
184-
if (options == null) {
185-
options = {};
186-
}
187-
188-
const dataKey = Object.assign({ provider }, options.masterKey);
189-
164+
options: ClientEncryptionCreateDataKeyProviderOptions = {}
165+
): Promise<UUID> {
190166
if (options.keyAltNames && !Array.isArray(options.keyAltNames)) {
191167
throw new MongoCryptInvalidArgumentError(
192168
`Option "keyAltNames" must be an array of strings, but was of type ${typeof options.keyAltNames}.`
@@ -211,42 +187,33 @@ export class ClientEncryption {
211187
keyMaterial = serialize({ keyMaterial: options.keyMaterial });
212188
}
213189

214-
const dataKeyBson = serialize(dataKey);
190+
const dataKeyBson = serialize({
191+
provider,
192+
...options.masterKey
193+
});
194+
215195
const context = this._mongoCrypt.makeDataKeyContext(dataKeyBson, {
216196
keyAltNames,
217197
keyMaterial
218198
});
199+
219200
const stateMachine = new StateMachine({
220201
proxyOptions: this._proxyOptions,
221202
tlsOptions: this._tlsOptions
222203
});
223204

224-
// @ts-expect-error We did not convert promiseOrCallback to TS
225-
return promiseOrCallback(callback, cb => {
226-
stateMachine.execute<DataKey>(this, context, (err, dataKey) => {
227-
if (err || !dataKey) {
228-
cb(err, null);
229-
return;
230-
}
205+
const dataKey = await stateMachine.executeAsync<DataKey>(this, context);
231206

232-
const { db: dbName, collection: collectionName } = MongoDBCollectionNamespace.fromString(
233-
this._keyVaultNamespace
234-
);
207+
const { db: dbName, collection: collectionName } = MongoDBCollectionNamespace.fromString(
208+
this._keyVaultNamespace
209+
);
235210

236-
this._keyVaultClient
237-
.db(dbName)
238-
.collection<DataKey>(collectionName)
239-
.insertOne(dataKey, { writeConcern: { w: 'majority' } })
240-
.then(
241-
result => {
242-
return cb(null, result.insertedId);
243-
},
244-
err => {
245-
cb(err, null);
246-
}
247-
);
248-
});
249-
});
211+
const { insertedId } = await this._keyVaultClient
212+
.db(dbName)
213+
.collection<DataKey>(collectionName)
214+
.insertOne(dataKey, { writeConcern: { w: 'majority' } });
215+
216+
return insertedId;
250217
}
251218

252219
/**
@@ -601,21 +568,7 @@ export class ClientEncryption {
601568
*
602569
* @param value - The value that you wish to serialize. Must be of a type that can be serialized into BSON
603570
* @param options -
604-
* @param callback - Optional callback to invoke when value is encrypted
605-
* @returns If no callback is provided, returns a Promise that either resolves with the encrypted value, or rejects with an error. If a callback is provided, returns nothing.
606-
*
607-
* @example
608-
* ```ts
609-
* // Encryption with callback API
610-
* function encryptMyData(value, callback) {
611-
* clientEncryption.createDataKey('local', (err, keyId) => {
612-
* if (err) {
613-
* return callback(err);
614-
* }
615-
* clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }, callback);
616-
* });
617-
* }
618-
* ```
571+
* @returns a Promise that either resolves with the encrypted value, or rejects with an error.
619572
*
620573
* @example
621574
* ```ts
@@ -635,12 +588,8 @@ export class ClientEncryption {
635588
* }
636589
* ```
637590
*/
638-
encrypt(
639-
value: unknown,
640-
options: ClientEncryptionEncryptOptions,
641-
callback: Callback<Binary>
642-
): Promise<Binary> | void {
643-
return maybeCallback(() => this._encrypt(value, false, options), callback);
591+
async encrypt(value: unknown, options: ClientEncryptionEncryptOptions): Promise<Binary> {
592+
return this._encrypt(value, false, options);
644593
}
645594

646595
/**
@@ -672,16 +621,7 @@ export class ClientEncryption {
672621
* Explicitly decrypt a provided encrypted value
673622
*
674623
* @param value - An encrypted value
675-
* @param callback - Optional callback to invoke when value is decrypted
676-
* @returns If no callback is provided, returns a Promise that either resolves with the decrypted value, or rejects with an error. If a callback is provided, returns nothing.
677-
*
678-
* ```ts
679-
* @example
680-
* // Decrypting value with callback API
681-
* function decryptMyValue(value, callback) {
682-
* clientEncryption.decrypt(value, callback);
683-
* }
684-
* ```
624+
* @returns a Promise that either resolves with the decrypted value, or rejects with an error
685625
*
686626
* @example
687627
* ```ts
@@ -691,7 +631,7 @@ export class ClientEncryption {
691631
* }
692632
* ```
693633
*/
694-
decrypt<T = any>(value: Binary, callback?: Callback<T>): Promise<T> | void {
634+
async decrypt<T = any>(value: Binary): Promise<T> {
695635
const valueBuffer = serialize({ v: value });
696636
const context = this._mongoCrypt.makeExplicitDecryptionContext(valueBuffer);
697637

@@ -700,17 +640,9 @@ export class ClientEncryption {
700640
tlsOptions: this._tlsOptions
701641
});
702642

703-
// @ts-expect-error We did not convert promiseOrCallback to TS
704-
return promiseOrCallback(callback, cb => {
705-
stateMachine.execute<{ v: T }>(this, context, (err, result) => {
706-
if (err || !result) {
707-
cb(err, null);
708-
return;
709-
}
643+
const { v } = await stateMachine.executeAsync<{ v: T }>(this, context);
710644

711-
cb(null, result.v);
712-
});
713-
});
645+
return v;
714646
}
715647

716648
/**

Diff for: src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ export {
3333
MaxKey,
3434
MinKey,
3535
ObjectId,
36-
Timestamp
36+
Timestamp,
37+
UUID
3738
} from './bson';
3839
export { AnyBulkWriteOperation, BulkWriteOptions, MongoBulkWriteError } from './bulk/common';
3940
export { ClientEncryption } from './client-side-encryption/client_encryption';

Diff for: test/integration/client-side-encryption/client_side_encryption.prose.12.deadlock.test.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as BSON from 'bson';
22
import { expect } from 'chai';
33
import { readFileSync } from 'fs';
44
import * as path from 'path';
5-
import * as util from 'util';
65

76
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
87
import { ClientEncryption } from '../../../src/client-side-encryption/client_encryption';
@@ -138,11 +137,8 @@ describe('Connection Pool Deadlock Prevention', function () {
138137
keyVaultClient: this.keyVaultClient,
139138
extraOptions: getEncryptExtraOptions()
140139
});
141-
this.clientEncryption.encryptPromisified = util.promisify(
142-
this.clientEncryption.encrypt.bind(this.clientEncryption)
143-
);
144140

145-
this.ciphertext = await this.clientEncryption.encryptPromisified('string0', {
141+
this.ciphertext = await this.clientEncryption.encrypt('string0', {
146142
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic',
147143
keyAltName: 'local'
148144
});

0 commit comments

Comments
 (0)