@@ -30,6 +30,57 @@ async function refresh(browser: CompassBrowser, connectionName: string) {
30
30
) ;
31
31
}
32
32
33
+ function fieldOldNewByMode ( mode : string ) {
34
+ switch ( mode ) {
35
+ case 'indexed' :
36
+ case 'unindexed' :
37
+ return [ 'phoneNumber' , '"30303030"' , '"10101010"' ] ;
38
+
39
+ case 'range' :
40
+ return [
41
+ 'date' ,
42
+ 'new Date("1999-01-01T00:00:00.000Z")' ,
43
+ 'new Date("2023-02-10T11:08:34.456Z")' ,
44
+ ] ;
45
+
46
+ case 'prefixPreview' :
47
+ return [ 'encryptedText' , '"prefixFoo"' , '"prefixBar"' ] ;
48
+
49
+ case 'suffixPreview' :
50
+ return [ 'encryptedText' , '"fooSuffix"' , '"barSuffix"' ] ;
51
+
52
+ case 'substringPreview' :
53
+ return [ 'encryptedText' , '"fooSubstringFoo"' , '"barSubstringBar"' ] ;
54
+
55
+ default :
56
+ throw new Error ( `Unknown mode ${ mode } ` ) ;
57
+ }
58
+ }
59
+
60
+ function filterByMode (
61
+ mode : string ,
62
+ { _id, field, newValue } : { _id : string ; field : string ; newValue : string }
63
+ ) : string {
64
+ switch ( mode ) {
65
+ case 'unindexed' :
66
+ // Querying on encrypted fields when they are unindexed is not
67
+ // supported, so we use document _id instead
68
+ return `{ _id: ${ _id } }` ;
69
+
70
+ case 'prefixPreview' :
71
+ return `{ $expr: { $encStrStartsWith: { input: '$${ field } ', prefix: 'prefix' } } }` ;
72
+
73
+ case 'suffixPreview' :
74
+ return `{ $expr: { $encStrEndsWith: { input: '$${ field } ', suffix: 'Suffix' } } }` ;
75
+
76
+ case 'substringPreview' :
77
+ return `{ $expr: { $encStrContains: { input: '$${ field } ', substring: 'Substring' } } }` ;
78
+
79
+ default :
80
+ return `{ ${ field } : ${ newValue } }` ;
81
+ }
82
+ }
83
+
33
84
/**
34
85
* @securityTest In-Use Encryption Testing
35
86
*
@@ -56,6 +107,7 @@ describe('CSFLE / QE', function () {
56
107
describe ( 'server version gte 4.2.20 and not a linux platform' , function ( ) {
57
108
const databaseName = 'fle-test' ;
58
109
const collectionName = 'my-another-collection' ;
110
+
59
111
let compass : Compass ;
60
112
let browser : CompassBrowser ;
61
113
@@ -283,6 +335,10 @@ describe('CSFLE / QE', function () {
283
335
const collectionName = 'my-another-collection' ;
284
336
const collectionNameUnindexed = 'my-another-collection2' ;
285
337
const collectionNameRange = 'my-range-collection' ;
338
+ const collectionNamePrefixPreview = 'my-prefix-collection' ;
339
+ const collectionNameSuffixPreview = 'my-suffix-collection' ;
340
+ const collectionNameSubstringPreview = 'my-substring-collection' ;
341
+
286
342
let compass : Compass ;
287
343
let browser : CompassBrowser ;
288
344
let plainMongo : MongoClient ;
@@ -332,15 +388,73 @@ describe('CSFLE / QE', function () {
332
388
keyId: UUID("28bbc608-524e-4717-9246-33633361788e"),
333
389
bsonType: 'date',
334
390
queries: [{
335
- queryType: " range" ,
391
+ queryType: ' range' ,
336
392
contention: 4,
337
393
sparsity: 1,
338
394
min: new Date('1970'),
339
395
max: new Date('2100')
340
396
}]
341
397
}
342
398
]
343
- }
399
+ },
400
+ '${ databaseName } .${ collectionNamePrefixPreview } ': {
401
+ fields: [
402
+ {
403
+ path: 'encryptedText',
404
+ keyId: UUID("28bbc608-524e-4717-9246-33633361788e"),
405
+ bsonType: 'string',
406
+ queries: [
407
+ {
408
+ queryType: 'prefixPreview',
409
+ contention: 0,
410
+ strMinQueryLength: 3,
411
+ strMaxQueryLength: 30,
412
+ caseSensitive: true,
413
+ diacriticSensitive: true,
414
+ }
415
+ ]
416
+ }
417
+ ]
418
+ },
419
+ '${ databaseName } .${ collectionNameSuffixPreview } ': {
420
+ fields: [
421
+ {
422
+ path: 'encryptedText',
423
+ keyId: UUID("28bbc608-524e-4717-9246-33633361788e"),
424
+ bsonType: 'string',
425
+ queries: [
426
+ {
427
+ queryType: 'suffixPreview',
428
+ contention: 0,
429
+ strMinQueryLength: 3,
430
+ strMaxQueryLength: 30,
431
+ caseSensitive: true,
432
+ diacriticSensitive: true,
433
+ }
434
+ ]
435
+ }
436
+ ]
437
+ },
438
+ '${ databaseName } .${ collectionNameSubstringPreview } ': {
439
+ fields: [
440
+ {
441
+ path: 'encryptedText',
442
+ keyId: UUID("28bbc608-524e-4717-9246-33633361788e"),
443
+ bsonType: 'string',
444
+ queries: [
445
+ {
446
+ queryType: 'substringPreview',
447
+ contention: 0,
448
+ strMinQueryLength: 3,
449
+ strMaxQueryLength: 10,
450
+ strMaxLength: 20,
451
+ caseSensitive: true,
452
+ diacriticSensitive: true
453
+ }
454
+ ]
455
+ }
456
+ ]
457
+ },
344
458
}` ,
345
459
connectionName,
346
460
} ) ;
@@ -513,21 +627,28 @@ describe('CSFLE / QE', function () {
513
627
[ 'indexed' , collectionName ] ,
514
628
[ 'unindexed' , collectionNameUnindexed ] ,
515
629
[ 'range' , collectionNameRange ] ,
630
+ [ 'prefixPreview' , collectionNamePrefixPreview ] ,
631
+ [ 'suffixPreview' , collectionNameSuffixPreview ] ,
632
+ [ 'substringPreview' , collectionNameSubstringPreview ] ,
516
633
] as const ) {
517
634
it ( `can edit and query the ${ mode } encrypted field in the CRUD view` , async function ( ) {
518
635
if ( mode === 'range' && serverSatisfies ( '< 7.99.99' , true ) ) {
519
636
// We are using latest crypt libraries which only support range algorithm.
520
637
console . log ( 'Skipping range test for server version < 7.99.99' ) ;
521
638
return this . skip ( ) ;
522
639
}
523
- const [ field , oldValue , newValue ] =
524
- mode !== 'range'
525
- ? [ 'phoneNumber' , '"30303030"' , '"10101010"' ]
526
- : [
527
- 'date' ,
528
- 'new Date("1999-01-01T00:00:00.000Z")' ,
529
- 'new Date("2023-02-10T11:08:34.456Z")' ,
530
- ] ;
640
+
641
+ if (
642
+ [ 'prefixPreview' , 'suffixPreview' , 'substringPreview' ] . includes (
643
+ mode as string
644
+ ) &&
645
+ ! serverSatisfies ( '>= 8.2.0-rc4' , true )
646
+ ) {
647
+ // QE Prefix/Suffix/Substring Support only available on 8.2+
648
+ return this . skip ( ) ;
649
+ }
650
+
651
+ const [ field , oldValue , newValue ] = fieldOldNewByMode ( mode ) ;
531
652
const oldValueJS = eval ( oldValue ) ;
532
653
const newValueJS = eval ( newValue ) ;
533
654
const toString = ( v : any ) =>
@@ -587,14 +708,12 @@ describe('CSFLE / QE', function () {
587
708
}
588
709
await footer . waitForDisplayed ( { reverse : true } ) ;
589
710
590
- await browser . runFindOperation (
591
- 'Documents' ,
592
- // Querying on encrypted fields when they are unindexed is not
593
- // supported, so we use document _id instead
594
- mode === 'unindexed'
595
- ? `{ _id: ${ result . _id } }`
596
- : `{ ${ field } : ${ newValue } }`
597
- ) ;
711
+ const filter = filterByMode ( mode , {
712
+ _id : result . _id ,
713
+ field,
714
+ newValue,
715
+ } ) ;
716
+ await browser . runFindOperation ( 'Documents' , filter ) ;
598
717
599
718
const modifiedResult = await browser . getFirstListDocument ( ) ;
600
719
expect ( modifiedResult [ field ] ) . to . be . equal ( toString ( newValueJS ) ) ;
0 commit comments