Skip to content

Commit 0c03cf7

Browse files
committed
fix: preserve key order in encryption scenarios
1 parent 6a52f66 commit 0c03cf7

File tree

3 files changed

+84
-15
lines changed

3 files changed

+84
-15
lines changed

src/cmap/connection.ts

+16
Original file line numberDiff line numberDiff line change
@@ -594,11 +594,27 @@ export class CryptoConnection extends Connection {
594594
return;
595595
}
596596

597+
const sort: Map<string, number> | null = cmd.find || cmd.findAndModify ? cmd.sort : null;
598+
const indexKeys: Map<string, number>[] | null = cmd.createIndexes
599+
? cmd.indexes.map((index: { key: Map<string, number> }) => index.key)
600+
: null;
601+
597602
autoEncrypter.encrypt(ns.toString(), cmd, options, (err, encrypted) => {
598603
if (err || encrypted == null) {
599604
callback(err, null);
600605
return;
601606
}
607+
608+
// Repair JS Map loss
609+
if ((cmd.find || cmd.findAndModify) && sort != null) {
610+
encrypted.sort = sort;
611+
}
612+
if (cmd.createIndexes && indexKeys != null) {
613+
for (const [offset, index] of indexKeys.entries()) {
614+
encrypted.indexes[offset].key = index;
615+
}
616+
}
617+
602618
super.command(ns, encrypted, options, (err, response) => {
603619
if (err || response == null) {
604620
callback(err, response);

test/integration/client-side-encryption/client_side_encryption.prose.test.js

-15
Original file line numberDiff line numberDiff line change
@@ -729,21 +729,6 @@ describe('Client Side Encryption Prose Tests', metadata, function () {
729729
});
730730
});
731731

732-
it('should maintain an ordered sort', async function () {
733-
const coll = this.encryptedColl;
734-
const events = [];
735-
this.clientEncrypted.on('commandStarted', ev => events.push(ev));
736-
const sort = new Map([
737-
['1', 1],
738-
['0', 1]
739-
]);
740-
await coll.findOne({}, { sort });
741-
expect(events).to.have.lengthOf(2);
742-
expect(events[0]).to.have.property('commandName', 'listCollections');
743-
expect(events[1]).to.have.property('commandName', 'find');
744-
expect(events[1].command.sort).to.deep.equal(sort);
745-
});
746-
747732
function pruneEvents(events) {
748733
return events.map(event => {
749734
// We are pruning out the bunch of repeating As, mostly

test/integration/client-side-encryption/driver.test.js

+68
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,72 @@ describe('Client Side Encryption Functional', function () {
222222
});
223223
});
224224
});
225+
226+
describe('key order aware command properties', () => {
227+
let client;
228+
let collection;
229+
230+
beforeEach(async function () {
231+
const encryptionOptions = {
232+
monitorCommands: true,
233+
autoEncryption: {
234+
keyVaultNamespace,
235+
kmsProviders: { local: { key: 'A'.repeat(128) } }
236+
}
237+
};
238+
client = this.configuration.newClient({}, encryptionOptions);
239+
collection = client.db(dataDbName).collection('keyOrder');
240+
});
241+
242+
afterEach(async () => {
243+
if (client) await client.close();
244+
});
245+
246+
describe('find', () => {
247+
it('should maintain ordered sort', async function () {
248+
const events = [];
249+
client.on('commandStarted', ev => events.push(ev));
250+
const sort = new Map([
251+
['1', 1],
252+
['0', 1]
253+
]);
254+
await collection.findOne({}, { sort });
255+
const findEvent = events.find(event => !!event.command.find);
256+
expect(findEvent).to.have.property('commandName', 'find');
257+
expect(findEvent.command.sort).to.deep.equal(sort);
258+
});
259+
});
260+
261+
describe('findAndModify', () => {
262+
it('should maintain ordered sort', async function () {
263+
const events = [];
264+
client.on('commandStarted', ev => events.push(ev));
265+
const sort = new Map([
266+
['1', 1],
267+
['0', 1]
268+
]);
269+
await collection.findOneAndUpdate({}, { $setOnInsert: { a: 1 } }, { sort });
270+
const findAndModifyEvent = events.find(event => !!event.command.findAndModify);
271+
expect(findAndModifyEvent).to.have.property('commandName', 'findAndModify');
272+
expect(findAndModifyEvent.command.sort).to.deep.equal(sort);
273+
});
274+
});
275+
276+
describe('createIndexes', () => {
277+
it('should maintain ordered index keys', async function () {
278+
const events = [];
279+
client.on('commandStarted', ev => events.push(ev));
280+
const indexDescription = new Map([
281+
['1', 1],
282+
['0', 1]
283+
]);
284+
await collection.createIndex(indexDescription, { name: 'myIndex' });
285+
const createIndexEvent = events.find(event => !!event.command.createIndexes);
286+
expect(createIndexEvent).to.have.property('commandName', 'createIndexes');
287+
expect(createIndexEvent.command.indexes).to.have.lengthOf(1);
288+
const index = createIndexEvent.command.indexes[0];
289+
expect(index.key).to.deep.equal(indexDescription);
290+
});
291+
});
292+
});
225293
});

0 commit comments

Comments
 (0)