|
|
|
@ -45,6 +45,7 @@ import org.springframework.data.mongodb.core.mapping.RangeEncrypted; |
|
|
|
import org.springframework.data.mongodb.util.BsonUtils; |
|
|
|
import org.springframework.data.mongodb.util.BsonUtils; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.util.ObjectUtils; |
|
|
|
import org.springframework.util.ObjectUtils; |
|
|
|
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Default implementation of {@link EncryptingConverter}. Properties used with this converter must be annotated with |
|
|
|
* Default implementation of {@link EncryptingConverter}. Properties used with this converter must be annotated with |
|
|
|
@ -168,7 +169,7 @@ public class MongoEncryptionConverter implements EncryptingConverter<Object, Obj |
|
|
|
|
|
|
|
|
|
|
|
if (annotation == null) { |
|
|
|
if (annotation == null) { |
|
|
|
throw new IllegalStateException(String.format("Property %s.%s is not annotated with @Encrypted", |
|
|
|
throw new IllegalStateException(String.format("Property %s.%s is not annotated with @Encrypted", |
|
|
|
getProperty(context).getOwner().getName(), getProperty(context).getName())); |
|
|
|
persistentProperty.getOwner().getName(), persistentProperty.getName())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String algorithm = annotation.algorithm(); |
|
|
|
String algorithm = annotation.algorithm(); |
|
|
|
@ -178,42 +179,45 @@ public class MongoEncryptionConverter implements EncryptingConverter<Object, Obj |
|
|
|
EncryptionOptions encryptionOptions = new EncryptionOptions(algorithm, key, |
|
|
|
EncryptionOptions encryptionOptions = new EncryptionOptions(algorithm, key, |
|
|
|
getEQOptions(persistentProperty, fieldNameAndQueryOperator)); |
|
|
|
getEQOptions(persistentProperty, fieldNameAndQueryOperator)); |
|
|
|
|
|
|
|
|
|
|
|
if (fieldNameAndQueryOperator != null |
|
|
|
if (fieldNameAndQueryOperator != null && encryptionOptions.queryableEncryptionOptions() != null) { |
|
|
|
&& !encryptionOptions.queryableEncryptionOptions().equals(QueryableEncryptionOptions.none())) { |
|
|
|
|
|
|
|
return encryptExpression(fieldNameAndQueryOperator, value, encryptionOptions); |
|
|
|
return encryptExpression(fieldNameAndQueryOperator, value, encryptionOptions); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return encryptValue(value, context, persistentProperty, encryptionOptions); |
|
|
|
return encryptValue(value, context, persistentProperty, encryptionOptions); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static QueryableEncryptionOptions getEQOptions(MongoPersistentProperty persistentProperty, |
|
|
|
private static @Nullable QueryableEncryptionOptions getEQOptions(MongoPersistentProperty persistentProperty, |
|
|
|
String fieldNameAndQueryOperator) { |
|
|
|
String fieldNameAndQueryOperator) { |
|
|
|
|
|
|
|
|
|
|
|
QueryableEncryptionOptions queryableEncryptionOptions = QueryableEncryptionOptions.none(); |
|
|
|
Encrypted encryptedAnnotation = persistentProperty.findAnnotation(Encrypted.class); |
|
|
|
RangeEncrypted rangeEncryptedAnnotation = persistentProperty.findAnnotation(RangeEncrypted.class); |
|
|
|
if (encryptedAnnotation != null && !StringUtils.hasText(encryptedAnnotation.queryType())) { |
|
|
|
if (rangeEncryptedAnnotation == null) { |
|
|
|
return null; |
|
|
|
return queryableEncryptionOptions; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String rangeOptions = rangeEncryptedAnnotation.rangeOptions(); |
|
|
|
QueryableEncryptionOptions queryableEncryptionOptions = QueryableEncryptionOptions.none(); |
|
|
|
if (!rangeOptions.isEmpty()) { |
|
|
|
|
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions.attributes(Document.parse(rangeOptions)); |
|
|
|
String queryAttributes = encryptedAnnotation.queryAttributes(); |
|
|
|
|
|
|
|
if (!queryAttributes.isEmpty()) { |
|
|
|
|
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions.attributes(Document.parse(queryAttributes)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (rangeEncryptedAnnotation.contentionFactor() >= 0) { |
|
|
|
RangeEncrypted rangeEncryptedAnnotation = persistentProperty.findAnnotation(RangeEncrypted.class); |
|
|
|
|
|
|
|
if (rangeEncryptedAnnotation != null && rangeEncryptedAnnotation.contentionFactor() >= 0) { |
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions |
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions |
|
|
|
.contentionFactor(rangeEncryptedAnnotation.contentionFactor()); |
|
|
|
.contentionFactor(rangeEncryptedAnnotation.contentionFactor()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean isPartOfARangeQuery = fieldNameAndQueryOperator != null; |
|
|
|
boolean isPartOfARangeQuery = fieldNameAndQueryOperator != null; |
|
|
|
if (isPartOfARangeQuery) { |
|
|
|
if (isPartOfARangeQuery || !encryptedAnnotation.queryType().isEmpty()) { |
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions.queryType("range"); |
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions.queryType(encryptedAnnotation.queryType()); // should the type move to an extra annotation?
|
|
|
|
|
|
|
|
queryableEncryptionOptions = queryableEncryptionOptions.contentionFactor(1l); |
|
|
|
} |
|
|
|
} |
|
|
|
return queryableEncryptionOptions; |
|
|
|
return queryableEncryptionOptions; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private BsonBinary encryptValue(Object value, EncryptionContext context, MongoPersistentProperty persistentProperty, |
|
|
|
private BsonBinary encryptValue(Object value, EncryptionContext context, MongoPersistentProperty persistentProperty, |
|
|
|
EncryptionOptions encryptionOptions) { |
|
|
|
EncryptionOptions encryptionOptions) { |
|
|
|
|
|
|
|
|
|
|
|
if (!persistentProperty.isEntity()) { |
|
|
|
if (!persistentProperty.isEntity()) { |
|
|
|
|
|
|
|
|
|
|
|
if (persistentProperty.isCollectionLike()) { |
|
|
|
if (persistentProperty.isCollectionLike()) { |
|
|
|
@ -227,6 +231,7 @@ public class MongoEncryptionConverter implements EncryptingConverter<Object, Obj |
|
|
|
} |
|
|
|
} |
|
|
|
return encryption.encrypt(BsonUtils.simpleToBsonValue(value), encryptionOptions); |
|
|
|
return encryption.encrypt(BsonUtils.simpleToBsonValue(value), encryptionOptions); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (persistentProperty.isCollectionLike()) { |
|
|
|
if (persistentProperty.isCollectionLike()) { |
|
|
|
return encryption.encrypt(collectionLikeToBsonValue(value, persistentProperty, context), encryptionOptions); |
|
|
|
return encryption.encrypt(collectionLikeToBsonValue(value, persistentProperty, context), encryptionOptions); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -251,6 +256,7 @@ public class MongoEncryptionConverter implements EncryptingConverter<Object, Obj |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private BsonValue encryptExpression(String fieldNameAndQueryOperator, Object value, |
|
|
|
private BsonValue encryptExpression(String fieldNameAndQueryOperator, Object value, |
|
|
|
EncryptionOptions encryptionOptions) { |
|
|
|
EncryptionOptions encryptionOptions) { |
|
|
|
|
|
|
|
|
|
|
|
BsonValue doc = BsonUtils.simpleToBsonValue(value); |
|
|
|
BsonValue doc = BsonUtils.simpleToBsonValue(value); |
|
|
|
|
|
|
|
|
|
|
|
String fieldName = fieldNameAndQueryOperator; |
|
|
|
String fieldName = fieldNameAndQueryOperator; |
|
|
|
|