diff --git a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/utils/CriteriaUtils.java b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/utils/CriteriaUtils.java index 310fc23ba532456dc173a842a61140b948571d6d..204e05c6143de04b1ca363fd7bceb3a8f4c98829 100644 --- a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/utils/CriteriaUtils.java +++ b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/utils/CriteriaUtils.java @@ -127,21 +127,32 @@ public final class CriteriaUtils { */ public static void checkContainsAuthorizedKeys(final QueryDto queryDto, final Collection<String> allowedKeys) { queryDto.getCriterionList().forEach(criterion -> { + if (allowedKeys.contains(criterion.getKey())) { + return; + } + // if we have a ElemMatch operator we have to check that current field is allowed and his child field also // field.childField + String keyWithPoint = criterion.getKey() + "."; if (criterion.getOperator().equals(CriterionOperator.ELEMMATCH) && - allowedKeys.stream().anyMatch(key -> key.startsWith(criterion.getKey() + "."))) { - // we recurse on children to check the allowed key + allowedKeys.stream().anyMatch(key -> key.startsWith(keyWithPoint))) { + // we recurse on children's to check the allowed key try { QueryDto elemMatchQuery = QueryDto.fromJson(JsonUtils.toJson(criterion.getValue())); - checkContainsAuthorizedKeys(elemMatchQuery, allowedKeys); + List<String> elemAllowedKeys = + allowedKeys.stream() + .filter(key -> key.startsWith(keyWithPoint)) + .map(key -> key.replaceFirst(keyWithPoint, "")) + .collect(Collectors.toList()); + checkContainsAuthorizedKeys(elemMatchQuery, elemAllowedKeys); } catch (JsonProcessingException e) { throw new InvalidFormatException(e.getMessage(), e); } - } else if (!allowedKeys.contains(criterion.getKey())) { - throw new ForbiddenException("Criterion with key : " + criterion.getKey() + " is not allowed"); + return; } + + throw new ForbiddenException("Criterion with key : " + criterion.getKey() + " is not allowed"); }); queryDto.getSubQueries().forEach(queryDtoItem -> checkContainsAuthorizedKeys(queryDtoItem, allowedKeys)); } diff --git a/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java b/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java index 2186eceffad2fed5f2d06a680a837e7f6414730f..9326268ced60077684fe2ff756c5c40980314ee6 100644 --- a/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java +++ b/commons/commons-mongo/src/main/java/fr/gouv/vitamui/commons/mongo/utils/MongoUtils.java @@ -290,7 +290,7 @@ public final class MongoUtils { criteria = buildAndOperator(startCriteria, endCriteria); break; case ELEMMATCH : - criteria = Criteria.where(key).elemMatch(queryDtoToCriterion((QueryDto)val)); + criteria = Criteria.where(key).elemMatch(queryDtoToCriteria((QueryDto)val)); break; default : throw new IllegalArgumentException("Operator " + operator + " is not supported"); @@ -298,7 +298,12 @@ public final class MongoUtils { return criteria; } - public static Criteria queryDtoToCriterion(QueryDto queryDto) { + /** + * convert QueryDto to mongodb criteria + * @param queryDto the QueryDto to convert + * @return mongodb criteria + */ + public static Criteria queryDtoToCriteria(QueryDto queryDto) { Collection<CriteriaDefinition> criteria = new ArrayList<>(); queryDto.getCriterionList().forEach(criterion -> { criteria.add(MongoUtils.getCriteria(criterion.getKey(), criterion.getValue(), criterion.getOperator())); @@ -306,7 +311,7 @@ public final class MongoUtils { // if the criteria contains subQueries, a recursive call is made for each subQuery queryDto.getSubQueries().forEach(queryDtoItem -> { - criteria.add(queryDtoToCriterion(queryDtoItem)); + criteria.add(queryDtoToCriteria(queryDtoItem)); }); final Criteria commonCustomCriteria = new Criteria();