DATAMONGO-2545 - Fix full Query Document binding resulting from SpEL.

We reenabled annotated queries using a SpEL expression resulting in the actual query document.

Original pull request: #864.
This commit is contained in:
Christoph Strobl
2020-05-13 11:30:16 +02:00
committed by Mark Paluch
parent 7d48dd0ce4
commit fde59411da
3 changed files with 60 additions and 3 deletions

View File

@@ -38,6 +38,7 @@ import org.bson.Document;
import org.bson.Transformer;
import org.bson.codecs.*;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.json.JsonParseException;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
@@ -190,9 +191,26 @@ public class ParameterBindingDocumentCodec implements CollectibleCodec<Document>
Document document = new Document();
reader.readStartDocument();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
String fieldName = reader.readName();
document.put(fieldName, readValue(reader, decoderContext));
try {
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
String fieldName = reader.readName();
Object value = readValue(reader, decoderContext);
document.put(fieldName, value);
}
} catch (JsonParseException e) {
try {
Object value = readValue(reader, decoderContext);
if (value instanceof Map) {
if (!((Map) value).isEmpty()) {
return new Document((Map) value);
}
}
} catch (Exception ex) {
throw e;
}
}
reader.readEndDocument();

View File

@@ -25,6 +25,7 @@ import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.function.Supplier;
import java.util.regex.Matcher;
@@ -495,6 +496,9 @@ public class ParameterBindingJsonReader extends AbstractBsonReader {
if (ClassUtils.isAssignable(Iterable.class, type)) {
return BsonType.ARRAY;
}
if (ClassUtils.isAssignable(Map.class, type)) {
return BsonType.DOCUMENT;
}
return BsonType.UNDEFINED;
}

View File

@@ -17,6 +17,9 @@ package org.springframework.data.mongodb.util.json;
import static org.assertj.core.api.Assertions.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
@@ -310,6 +313,26 @@ public class ParameterBindingJsonReaderUnitTests {
assertThat(target).isEqualTo(new Document("isBatman", "nooo"));
}
@Test // DATAMONGO-2545
void evaluatesSpelExpressionDefiningEntireQuery() {
Object[] args = new Object[] {};
StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT
.getEvaluationContext(args);
evaluationContext.setRootObject(new DummySecurityObject(new DummyWithId("wonderwoman")));
String json = "?#{ T(" + this.getClass().getName()
+ ").isBatman() ? {'_class': { '$eq' : 'region' }} : { '$and' : { {'_class': { '$eq' : 'region' } }, {'user.superviser': principal.id } } } }";
ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json,
new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext));
Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build());
assertThat(target)
.isEqualTo(new Document("$and", Arrays.asList(new Document("_class", new Document("$eq", "region")),
new Document("user.superviser", "wonderwoman"))));
}
private static Document parse(String json, Object... args) {
ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args);
@@ -321,4 +344,16 @@ public class ParameterBindingJsonReaderUnitTests {
return false;
}
@Data
@AllArgsConstructor
public static class DummySecurityObject {
DummyWithId principal;
}
@Data
@AllArgsConstructor
public static class DummyWithId {
String id;
}
}