Browse Source

Fix update of encrypted field

issue/4185-light
Christoph Strobl 9 months ago
parent
commit
3fbed7b93c
No known key found for this signature in database
GPG Key ID: E6054036D0C37A4B
  1. 4
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java
  2. 13
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
  3. 67
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/encryption/RangeEncryptionTests.java

4
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

@ -683,7 +683,7 @@ public class QueryMapper { @@ -683,7 +683,7 @@ public class QueryMapper {
}
@Nullable
private Object convertValueWithConversionContext(Field documentField, Object sourceValue, Object value,
protected Object convertValueWithConversionContext(Field documentField, Object sourceValue, Object value,
PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter,
MongoConversionContext conversionContext) {
@ -1624,7 +1624,7 @@ public class QueryMapper { @@ -1624,7 +1624,7 @@ public class QueryMapper {
return converter;
}
private enum NoPropertyPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
enum NoPropertyPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
INSTANCE;

13
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java

@ -24,6 +24,8 @@ import java.util.Map.Entry; @@ -24,6 +24,8 @@ import java.util.Map.Entry;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.PropertyValueConverter;
import org.springframework.data.convert.ValueConversionContext;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mapping.Association;
@ -160,6 +162,17 @@ public class UpdateMapper extends QueryMapper { @@ -160,6 +162,17 @@ public class UpdateMapper extends QueryMapper {
return super.getMappedObjectForField(field, rawValue);
}
protected Object convertValueWithConversionContext(Field documentField, Object sourceValue, Object value,
PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter,
MongoConversionContext conversionContext) {
MongoConversionContext ctx = new MongoConversionContext(NoPropertyPropertyValueProvider.INSTANCE,
conversionContext.getProperty(), converter, conversionContext.getSpELContext(), null);
return super.convertValueWithConversionContext(documentField, sourceValue, value, valueConverter, ctx);
}
private Entry<String, Object> getMappedUpdateModifier(Field field, Object rawValue) {
Object value;

67
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/encryption/RangeEncryptionTests.java

@ -54,6 +54,7 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -54,6 +54,7 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.Queryable;
import org.springframework.data.mongodb.core.mapping.RangeEncrypted;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion;
import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable;
@ -78,6 +79,7 @@ import com.mongodb.client.model.IndexOptions; @@ -78,6 +79,7 @@ import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.Indexes;
import com.mongodb.client.model.vault.EncryptOptions;
import com.mongodb.client.model.vault.RangeOptions;
import com.mongodb.client.result.UpdateResult;
import com.mongodb.client.vault.ClientEncryption;
import com.mongodb.client.vault.ClientEncryptions;
@ -101,7 +103,7 @@ class RangeEncryptionTests { @@ -101,7 +103,7 @@ class RangeEncryptionTests {
}
@Test // GH-4185
void canGreaterThanEqualMatchRangeEncryptedField() {
void manuallyEncryptedValuesCanBeSavedAndRetrievedCorrectly() {
EncryptOptions encryptOptions = new EncryptOptions("Range").contentionFactor(1L)
.keyId(keyHolder.getEncryptionKey("encryptedInt"))
@ -111,21 +113,18 @@ class RangeEncryptionTests { @@ -111,21 +113,18 @@ class RangeEncryptionTests {
.rangeOptions(new RangeOptions().min(new BsonInt32(0)).max(new BsonInt32(200)))
.keyId(keyHolder.getEncryptionKey("encryptedInt")).queryType("range");
/*
@Encrypted(algorithm = "Indexed")
@Queryable(queryType = "equality", contentionFactor = 0)
*/
EncryptOptions equalityEncOptions = new EncryptOptions("Indexed")
.contentionFactor(0L)
.keyId(keyHolder.getEncryptionKey("age"));;
EncryptOptions equalityEncOptions = new EncryptOptions("Indexed").contentionFactor(0L)
.keyId(keyHolder.getEncryptionKey("age"));
;
EncryptOptions equalityEncOptionsString = new EncryptOptions("Indexed")
.contentionFactor(0L)
.keyId(keyHolder.getEncryptionKey("name"));;
EncryptOptions equalityEncOptionsString = new EncryptOptions("Indexed").contentionFactor(0L)
.keyId(keyHolder.getEncryptionKey("name"));
;
Document source = new Document("_id", "id-1");
source.put("name", clientEncryption.getClientEncryption().encrypt(new BsonString("It's a Me, Mario!"), equalityEncOptionsString));
source.put("name",
clientEncryption.getClientEncryption().encrypt(new BsonString("It's a Me, Mario!"), equalityEncOptionsString));
source.put("age", clientEncryption.getClientEncryption().encrypt(new BsonInt32(101), equalityEncOptions));
source.put("encryptedInt", clientEncryption.getClientEncryption().encrypt(new BsonInt32(101), encryptOptions));
source.put("_class", Person.class.getName());
@ -155,7 +154,7 @@ class RangeEncryptionTests { @@ -155,7 +154,7 @@ class RangeEncryptionTests {
}
@Test
void eqQueryWorksOnEncryptedField() {
void canQueryEqualityEncryptedField() {
Person source = createPerson();
template.insert(source);
@ -165,19 +164,31 @@ class RangeEncryptionTests { @@ -165,19 +164,31 @@ class RangeEncryptionTests {
}
@Test
void canRangeMatchRangeEncryptedField() {
void canExcludeSafeContentFromResult() {
Person source = createPerson();
template.insert(source);
Query q = Query.query(where("encryptedLong").lte(1001L).gte(1001L));
q.fields().exclude("__safeContent__");
Person loaded = template.query(Person.class).matching(q).firstValue();
assertThat(loaded).isEqualTo(source);
}
@Test
void canUpdateRangeEncryptedField() {
void canRangeMatchRangeEncryptedField() {
Person source = createPerson();
template.insert(source);
Query q = Query.query(where("encryptedLong").lte(1001L).gte(1001L));
Person loaded = template.query(Person.class).matching(q).firstValue();
assertThat(loaded).isEqualTo(source);
}
@Test
void canReplaceEntityWithRangeEncryptedField() {
Person source = createPerson();
template.insert(source);
@ -190,6 +201,20 @@ class RangeEncryptionTests { @@ -190,6 +201,20 @@ class RangeEncryptionTests {
assertThat(loaded).isEqualTo(source);
}
@Test
void canUpdateRangeEncryptedField() {
Person source = createPerson();
template.insert(source);
UpdateResult updateResult = template.update(Person.class).matching(where("id").is(source.id))
.apply(Update.update("encryptedLong", 5000L)).first();
assertThat(updateResult.getModifiedCount()).isOne();
Person loaded = template.query(Person.class).matching(where("id").is(source.id)).firstValue();
assertThat(loaded.encryptedLong).isEqualTo(5000L);
}
@Test
void errorsWhenUsingNonRangeOperatorEqOnRangeEncryptedField() {
@ -382,13 +407,14 @@ class RangeEncryptionTests { @@ -382,13 +407,14 @@ class RangeEncryptionTests {
String id;
@ValueConverter(MongoEncryptionConverter.class)
@Encrypted(algorithm = "Indexed")
@Queryable(queryType = "equality", contentionFactor = 0)
@Encrypted(algorithm = "Indexed") //
@Queryable(queryType = "equality", contentionFactor = 0) //
String name;
@ValueConverter(MongoEncryptionConverter.class)
@Encrypted(algorithm = "Indexed")
@Queryable(queryType = "equality", contentionFactor = 0)
//@Encrypted(algorithm = "Indexed", queries = {@Queryable(queryType = "equality", contentionFactor = 0)})
@Encrypted(algorithm = "Indexed") //
@Queryable(queryType = "equality", contentionFactor = 0) //
Integer age;
@ValueConverter(MongoEncryptionConverter.class)
@ -401,9 +427,6 @@ class RangeEncryptionTests { @@ -401,9 +427,6 @@ class RangeEncryptionTests {
rangeOptions = "{\"min\": {\"$numberLong\": \"1000\"}, \"max\": {\"$numberLong\": \"9999\"}, \"trimFactor\": 1, \"sparsity\": 1}") //
Long encryptedLong;
public String getId() {
return this.id;
}

Loading…
Cancel
Save