This is an automated email from the ASF dual-hosted git repository. ilgrosso pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/syncope.git
commit 95a6de78c36ba7242c5ee69dd3eb2fd1248773db Author: Francesco Chicchiriccò <[email protected]> AuthorDate: Wed Jun 24 14:31:17 2026 +0200 Restricting orderby clauses for Audit Events search (#1437) --- .../common/dao/AbstractAuditEventDAO.java | 37 ++++++++++++++++++++++ .../core/persistence/jpa/dao/JPAAuditEventDAO.java | 10 ++++-- .../persistence/neo4j/dao/Neo4jAuditEventDAO.java | 13 ++++---- .../core/persistence/neo4j/dao/Neo4jTaskDAO.java | 4 +-- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAuditEventDAO.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAuditEventDAO.java new file mode 100644 index 0000000000..a84dd746fc --- /dev/null +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAuditEventDAO.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.common.dao; + +import java.util.List; +import java.util.stream.Stream; +import org.apache.syncope.core.persistence.api.entity.AuditEvent; +import org.springframework.data.domain.Sort; +import org.springframework.util.ReflectionUtils; + +public abstract class AbstractAuditEventDAO { + + protected List<Sort.Order> filterOrderBy( + final Stream<Sort.Order> orderByClauses, + final Class<? extends AuditEvent> clazz) { + + return orderByClauses. + filter(clause -> ReflectionUtils.findField(clazz, clause.getProperty().trim()) != null). + toList(); + } +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditEventDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditEventDAO.java index 8226c7e033..307dcc22eb 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditEventDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditEventDAO.java @@ -29,11 +29,13 @@ import org.apache.syncope.common.lib.to.AuditEventTO; import org.apache.syncope.common.lib.types.OpEvent; import org.apache.syncope.core.persistence.api.dao.AuditEventDAO; import org.apache.syncope.core.persistence.api.entity.AuditEvent; +import org.apache.syncope.core.persistence.common.dao.AbstractAuditEventDAO; import org.apache.syncope.core.persistence.jpa.entity.JPAAuditEvent; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.transaction.annotation.Transactional; -public class JPAAuditEventDAO implements AuditEventDAO { +public class JPAAuditEventDAO extends AbstractAuditEventDAO implements AuditEventDAO { protected static class AuditEventCriteriaBuilder { @@ -168,8 +170,10 @@ public class JPAAuditEventDAO implements AuditEventDAO { before(before, parameters). after(after, parameters). build(); - if (!pageable.getSort().isEmpty()) { - queryString += " ORDER BY " + pageable.getSort().stream(). + + List<Sort.Order> orderBy = filterOrderBy(pageable.getSort().stream(), JPAAuditEvent.class); + if (!orderBy.isEmpty()) { + queryString += " ORDER BY " + orderBy.stream(). map(clause -> ("when".equals(clause.getProperty()) ? "event_date" : clause.getProperty()) + ' ' + clause.getDirection().name()). collect(Collectors.joining(",")); diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAuditEventDAO.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAuditEventDAO.java index 8c8d9f2b4f..6cc3d0903c 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAuditEventDAO.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jAuditEventDAO.java @@ -28,18 +28,16 @@ import org.apache.syncope.common.lib.to.AuditEventTO; import org.apache.syncope.common.lib.types.OpEvent; import org.apache.syncope.core.persistence.api.dao.AuditEventDAO; import org.apache.syncope.core.persistence.api.entity.AuditEvent; +import org.apache.syncope.core.persistence.common.dao.AbstractAuditEventDAO; import org.apache.syncope.core.persistence.neo4j.entity.Neo4jAuditEvent; import org.apache.syncope.core.persistence.neo4j.spring.NodeValidator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.neo4j.core.Neo4jClient; import org.springframework.data.neo4j.core.Neo4jTemplate; import org.springframework.transaction.annotation.Transactional; -public class Neo4jAuditEventDAO implements AuditEventDAO { - - protected static final Logger LOG = LoggerFactory.getLogger(AuditEventDAO.class); +public class Neo4jAuditEventDAO extends AbstractAuditEventDAO implements AuditEventDAO { protected static class AuditEventCriteriaBuilder { @@ -169,8 +167,9 @@ public class Neo4jAuditEventDAO implements AuditEventDAO { build() + " RETURN n.id"); - if (!pageable.getSort().isEmpty()) { - query.append(" ORDER BY ").append(pageable.getSort().stream(). + List<Sort.Order> orderBy = filterOrderBy(pageable.getSort().stream(), Neo4jAuditEvent.class); + if (!orderBy.isEmpty()) { + query.append(" ORDER BY ").append(orderBy.stream(). map(clause -> "n." + clause.getProperty() + ' ' + clause.getDirection().name()). collect(Collectors.joining(","))); } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java index 408c8e8e0d..924d553d28 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/Neo4jTaskDAO.java @@ -291,7 +291,7 @@ public class Neo4jTaskDAO extends AbstractDAO implements TaskDAO { query.append("(p)-[:").append(execRelationship(type)).append("]-() "); } - query.append("RETURN p.id ").append(toOrderByStatement(pageable.getSort().get())); + query.append("RETURN p.id ").append(toOrderByStatement(pageable.getSort().stream())); if (pageable.isPaged()) { query.append(" SKIP ").append(pageable.getPageSize() * pageable.getPageNumber()). @@ -463,7 +463,7 @@ public class Neo4jTaskDAO extends AbstractDAO implements TaskDAO { query.append(" WITH n "); - query.append(toOrderByStatement(pageable.getSort().get())); + query.append(toOrderByStatement(pageable.getSort().stream())); if (pageable.isPaged()) { query.append(" SKIP ").append(pageable.getPageSize() * pageable.getPageNumber()).
