Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 94103af

Browse files
authored
Support text indexes with encryption (#1797)
JAVA-5851 JAVA-5903 JAVA-5924
1 parent 24236e3 commit 94103af

File tree

20 files changed

+972
-137
lines changed

20 files changed

+972
-137
lines changed

‎driver-core/src/main/com/mongodb/client/model/vault/EncryptOptions.java‎

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.mongodb.client.model.vault;
1818

19+
import com.mongodb.annotations.Alpha;
20+
import com.mongodb.annotations.Reason;
1921
import com.mongodb.lang.Nullable;
2022
import org.bson.BsonBinary;
2123

@@ -31,6 +33,7 @@ public class EncryptOptions {
3133
private Long contentionFactor;
3234
private String queryType;
3335
private RangeOptions rangeOptions;
36+
private TextOptions textOptions;
3437

3538
/**
3639
* Construct an instance with the given algorithm.
@@ -51,8 +54,13 @@ public EncryptOptions(final String algorithm) {
5154
* <li>Indexed</li>
5255
* <li>Unindexed</li>
5356
* <li>Range</li>
57+
* <li>TextPreview</li>
5458
* </ul>
5559
*
60+
* <p>The "TextPreview" algorithm is in preview and should be used for experimental workloads only.
61+
* These features are unstable and their security is not guaranteed until released as Generally Available (GA).
62+
* The GA version of these features may not be backwards compatible with the preview version.</p>
63+
*
5664
* @return the encryption algorithm
5765
*/
5866
public String getAlgorithm() {
@@ -141,8 +149,8 @@ public Long getContentionFactor() {
141149
/**
142150
* The QueryType.
143151
*
144-
* <p>Currently, we support only "equality"or "range" queryType.</p>
145-
* <p>It is an error to set queryType when the algorithm is not "Indexed"or "Range".</p>
152+
* <p>Currently, we support only "equality", "range", "prefixPreview", "suffixPreview" or "substringPreview" queryType.</p>
153+
* <p>It is an error to set queryType when the algorithm is not "Indexed", "Range" or "TextPreview".</p>
146154
* @param queryType the query type
147155
* @return this
148156
* @since 4.7
@@ -194,6 +202,36 @@ public RangeOptions getRangeOptions() {
194202
return rangeOptions;
195203
}
196204

205+
/**
206+
* The TextOptions
207+
*
208+
* <p>It is an error to set TextOptions when the algorithm is not "TextPreview".
209+
* @param textOptions the text options
210+
* @return this
211+
* @since 5.6
212+
* @mongodb.server.release 8.2
213+
* @mongodb.driver.manual /core/queryable-encryption/ queryable encryption
214+
*/
215+
@Alpha(Reason.SERVER)
216+
public EncryptOptions textOptions(@Nullable final TextOptions textOptions) {
217+
this.textOptions = textOptions;
218+
return this;
219+
}
220+
221+
/**
222+
* Gets the TextOptions
223+
* @see #textOptions(TextOptions)
224+
* @return the text options or null if not set
225+
* @since 5.6
226+
* @mongodb.server.release 8.2
227+
* @mongodb.driver.manual /core/queryable-encryption/ queryable encryption
228+
*/
229+
@Alpha(Reason.SERVER)
230+
@Nullable
231+
public TextOptions getTextOptions() {
232+
return textOptions;
233+
}
234+
197235
@Override
198236
public String toString() {
199237
return "EncryptOptions{"
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.client.model.vault;
18+
19+
import com.mongodb.annotations.Alpha;
20+
import com.mongodb.annotations.Reason;
21+
import com.mongodb.lang.Nullable;
22+
import org.bson.BsonDocument;
23+
24+
/**
25+
* Text options for a Queryable Encryption field that supports text queries.
26+
*
27+
* <p>Note: TextOptions is in Alpha and subject to backwards breaking changes.
28+
*
29+
* @since 5.6
30+
* @mongodb.server.release 8.2
31+
* @mongodb.driver.manual /core/queryable-encryption/ queryable encryption
32+
*/
33+
@Alpha(Reason.SERVER)
34+
public class TextOptions {
35+
private Boolean caseSensitive;
36+
private Boolean diacriticSensitive;
37+
@Nullable
38+
private BsonDocument prefixOptions;
39+
@Nullable
40+
private BsonDocument suffixOptions;
41+
@Nullable
42+
private BsonDocument substringOptions;
43+
44+
/**
45+
* Construct a new instance
46+
*/
47+
public TextOptions() {
48+
}
49+
50+
/**
51+
* @return true if text indexes for this field are case sensitive.
52+
*/
53+
public boolean getCaseSensitive() {
54+
return caseSensitive;
55+
}
56+
57+
/**
58+
* Set case sensitivity
59+
*
60+
* @param caseSensitive true if text indexes are case sensitive
61+
* @return this
62+
*/
63+
public TextOptions caseSensitive(final boolean caseSensitive) {
64+
this.caseSensitive = caseSensitive;
65+
return this;
66+
}
67+
68+
/**
69+
* @return true if text indexes are diacritic sensitive
70+
*/
71+
public boolean getDiacriticSensitive() {
72+
return diacriticSensitive;
73+
}
74+
75+
/**
76+
* Set diacritic sensitivity
77+
*
78+
* @param diacriticSensitive true if text indexes are diacritic sensitive
79+
* @return this
80+
*/
81+
public TextOptions diacriticSensitive(final boolean diacriticSensitive) {
82+
this.diacriticSensitive = diacriticSensitive;
83+
return this;
84+
}
85+
86+
/**
87+
* Set the prefix options.
88+
*
89+
* <p>Expected to be a {@link BsonDocument} in the format of:</p>
90+
*
91+
* <pre>
92+
* {@code
93+
* {
94+
* // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
95+
* strMinQueryLength: BsonInt32,
96+
* // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
97+
* strMaxQueryLength: BsonInt32
98+
* }
99+
* }
100+
* </pre>
101+
*
102+
* @param prefixOptions the prefix options or null
103+
* @return this
104+
*/
105+
public TextOptions prefixOptions(@Nullable final BsonDocument prefixOptions) {
106+
this.prefixOptions = prefixOptions;
107+
return this;
108+
}
109+
110+
/**
111+
* @see #prefixOptions(BsonDocument)
112+
* @return the prefix options document or null
113+
*/
114+
@Nullable
115+
public BsonDocument getPrefixOptions() {
116+
return prefixOptions;
117+
}
118+
119+
/**
120+
* Set the suffix options.
121+
*
122+
* <p>Expected to be a {@link BsonDocument} in the format of:</p>
123+
*
124+
* <pre>
125+
* {@code
126+
* {
127+
* // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
128+
* strMinQueryLength: BsonInt32,
129+
* // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
130+
* strMaxQueryLength: BsonInt32
131+
* }
132+
* }
133+
* </pre>
134+
*
135+
* @param suffixOptions the suffix options or null
136+
* @return this
137+
*/
138+
public TextOptions suffixOptions(@Nullable final BsonDocument suffixOptions) {
139+
this.suffixOptions = suffixOptions;
140+
return this;
141+
}
142+
143+
/**
144+
* @see #suffixOptions(BsonDocument)
145+
* @return the suffix options document or null
146+
*/
147+
@Nullable
148+
public BsonDocument getSuffixOptions() {
149+
return suffixOptions;
150+
}
151+
152+
/**
153+
* Set the substring options.
154+
*
155+
* <p>Expected to be a {@link BsonDocument} in the format of:</p>
156+
*
157+
* <pre>
158+
* {@code
159+
* {
160+
* // strMaxLength is the maximum allowed length to insert. Inserting longer strings will error.
161+
* strMaxLength: BsonInt32,
162+
* // strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
163+
* strMinQueryLength: BsonInt32,
164+
* // strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
165+
* strMaxQueryLength: BsonInt32
166+
* }
167+
* }
168+
* </pre>
169+
*
170+
* @param substringOptions the substring options or null
171+
* @return this
172+
*/
173+
public TextOptions substringOptions(@Nullable final BsonDocument substringOptions) {
174+
this.substringOptions = substringOptions;
175+
return this;
176+
}
177+
178+
/**
179+
* @see #substringOptions(BsonDocument)
180+
* @return the substring options document or null
181+
*/
182+
@Nullable
183+
public BsonDocument getSubstringOptions() {
184+
return substringOptions;
185+
}
186+
187+
}

‎driver-core/src/main/com/mongodb/internal/client/vault/EncryptOptionsHelper.java‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
import com.mongodb.client.model.vault.EncryptOptions;
1919
import com.mongodb.client.model.vault.RangeOptions;
20+
import com.mongodb.client.model.vault.TextOptions;
2021
import com.mongodb.internal.crypt.capi.MongoExplicitEncryptOptions;
22+
import org.bson.BsonBoolean;
2123
import org.bson.BsonDocument;
2224
import org.bson.BsonInt32;
2325
import org.bson.BsonInt64;
@@ -70,6 +72,30 @@ public static MongoExplicitEncryptOptions asMongoExplicitEncryptOptions(final En
7072
}
7173
encryptOptionsBuilder.rangeOptions(rangeOptionsBsonDocument);
7274
}
75+
76+
TextOptions textOptions = options.getTextOptions();
77+
if (textOptions != null) {
78+
BsonDocument textOptionsDocument = new BsonDocument();
79+
textOptionsDocument.put("caseSensitive", BsonBoolean.valueOf(textOptions.getCaseSensitive()));
80+
textOptionsDocument.put("diacriticSensitive", BsonBoolean.valueOf(textOptions.getDiacriticSensitive()));
81+
82+
BsonDocument substringOptions = textOptions.getSubstringOptions();
83+
if (substringOptions != null) {
84+
textOptionsDocument.put("substring", substringOptions);
85+
}
86+
87+
BsonDocument prefixOptions = textOptions.getPrefixOptions();
88+
if (prefixOptions != null) {
89+
textOptionsDocument.put("prefix", prefixOptions);
90+
}
91+
92+
BsonDocument suffixOptions = textOptions.getSuffixOptions();
93+
if (suffixOptions != null) {
94+
textOptionsDocument.put("suffix", suffixOptions);
95+
}
96+
encryptOptionsBuilder.textOptions(textOptionsDocument);
97+
}
98+
7399
return encryptOptionsBuilder.build();
74100
}
75101
private EncryptOptionsHelper() {

‎driver-core/src/test/functional/com/mongodb/ClusterFixture.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import com.mongodb.internal.connection.StreamFactoryFactory;
6565
import com.mongodb.internal.connection.TlsChannelStreamFactoryFactory;
6666
import com.mongodb.internal.connection.netty.NettyStreamFactoryFactory;
67+
import com.mongodb.internal.crypt.capi.CAPI;
6768
import com.mongodb.internal.operation.BatchCursor;
6869
import com.mongodb.internal.operation.CommandReadOperation;
6970
import com.mongodb.internal.operation.DropDatabaseOperation;
@@ -148,6 +149,7 @@ public final class ClusterFixture {
148149
private static final Map<ReadPreference, ReadWriteBinding> BINDING_MAP = new HashMap<>();
149150
private static final Map<ReadPreference, AsyncReadWriteBinding> ASYNC_BINDING_MAP = new HashMap<>();
150151

152+
private static ServerVersion mongoCryptVersion;
151153
private static ServerVersion serverVersion;
152154
private static BsonDocument serverParameters;
153155

@@ -181,6 +183,13 @@ public static ClusterDescription getClusterDescription(final Cluster cluster) {
181183
}
182184
}
183185

186+
public static ServerVersion getMongoCryptVersion() {
187+
if (mongoCryptVersion == null) {
188+
mongoCryptVersion = new ServerVersion(getVersionList(CAPI.mongocrypt_version(null).toString()));
189+
}
190+
return mongoCryptVersion;
191+
}
192+
184193
public static ServerVersion getServerVersion() {
185194
if (serverVersion == null) {
186195
serverVersion = getVersion(new CommandReadOperation<>("admin",

‎driver-core/src/test/functional/com/mongodb/client/test/CollectionHelper.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474

7575
import static com.mongodb.ClusterFixture.executeAsync;
7676
import static com.mongodb.ClusterFixture.getBinding;
77+
import static java.lang.String.format;
7778
import static java.util.Arrays.asList;
7879
import static java.util.Collections.singletonList;
7980

@@ -154,6 +155,16 @@ public void drop(final WriteConcern writeConcern) {
154155
drop(namespace, writeConcern);
155156
}
156157

158+
public void dropAndCreate(final BsonDocument createOptions) {
159+
// Drop the collection and any encryption collections: enxcol_.<collectionName>.esc and enxcol_.<collectionName>.ecoc
160+
drop(namespace, WriteConcern.MAJORITY);
161+
drop(new MongoNamespace(namespace.getDatabaseName(), format("enxcol_.%s.esc", namespace.getCollectionName())),
162+
WriteConcern.MAJORITY);
163+
drop(new MongoNamespace(namespace.getDatabaseName(), format("enxcol_.%s.ecoc", namespace.getCollectionName())),
164+
WriteConcern.MAJORITY);
165+
create(WriteConcern.MAJORITY, createOptions);
166+
}
167+
157168
public void create() {
158169
create(namespace.getCollectionName(), new CreateCollectionOptions(), WriteConcern.ACKNOWLEDGED);
159170
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /