This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/4_0_X by this push:
     new 0148f0b92d Prevent sorting by _id in Elasticsearch or OpenSearch
0148f0b92d is described below

commit 0148f0b92dced9c4a1fa2f4d2553bc0c035eb6f8
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Mon Jul 21 15:38:34 2025 +0200

    Prevent sorting by _id in Elasticsearch or OpenSearch
---
 .../dao/ElasticsearchAnySearchDAO.java             | 29 ++++++++++++----------
 .../dao/ElasticsearchAuditEventDAO.java            |  7 ++++--
 .../dao/ElasticsearchRealmSearchDAO.java           | 15 +++++++----
 .../opensearch/dao/OpenSearchAnySearchDAO.java     | 29 ++++++++++++----------
 .../opensearch/dao/OpenSearchAuditEventDAO.java    |  7 ++++--
 .../opensearch/dao/OpenSearchRealmSearchDAO.java   | 12 ++++++---
 6 files changed, 60 insertions(+), 39 deletions(-)

diff --git 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
index 2998833c1e..335a53dd45 100644
--- 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
+++ 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAnySearchDAO.java
@@ -88,6 +88,8 @@ import org.springframework.util.CollectionUtils;
  */
 public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
 
+    protected static final Set<String> ID_PROPS = Set.of("key", "id", "_id");
+
     protected final ElasticsearchClient client;
 
     protected final int indexMaxResultWindow;
@@ -220,12 +222,12 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
                 
index(ElasticsearchUtils.getAnyIndex(AuthContextUtils.getDomain(), kind)).
                 query(getQuery(base, recursive, adminRealms, cond, kind)).
                 build();
-        LOG.debug("Count JSON request: {}", request);
+        LOG.debug("Count request: {}", request);
 
         try {
             return client.count(request).count();
         } catch (Exception e) {
-            LOG.error("While counting in Elasticsearch", e);
+            LOG.error("While counting in Elasticsearch with request {}", 
request, e);
             return 0;
         }
     }
@@ -237,17 +239,18 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
         orderBy.forEach(clause -> {
             String sortName = null;
 
-            // Manage difference between external key attribute and internal 
_id
-            String fieldName = "key".equals(clause.getProperty()) ? "_id" : 
clause.getProperty();
-
-            Field anyField = anyUtils.getField(fieldName).orElse(null);
-            if (anyField == null) {
-                PlainSchema schema = 
plainSchemaDAO.findById(fieldName).orElse(null);
-                if (schema != null) {
+            String fieldName = clause.getProperty();
+            // Cannot sort by internal _id
+            if (!ID_PROPS.contains(fieldName)) {
+                Field anyField = anyUtils.getField(fieldName).orElse(null);
+                if (anyField == null) {
+                    PlainSchema schema = 
plainSchemaDAO.findById(fieldName).orElse(null);
+                    if (schema != null) {
+                        sortName = fieldName;
+                    }
+                } else {
                     sortName = fieldName;
                 }
-            } else {
-                sortName = fieldName;
             }
 
             if (sortName == null) {
@@ -283,13 +286,13 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
                 sort(sortBuilders(kind, pageable.getSort().get())).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
-        LOG.debug("Search JSON request: {}", request);
+        LOG.debug("Search request: {}", request);
 
         List<Hit<Void>> esResult = null;
         try {
             esResult = client.search(request, Void.class).hits().hits();
         } catch (Exception e) {
-            LOG.error("While searching in Elasticsearch", e);
+            LOG.error("While searching in Elasticsearch with request {}", 
request, e);
         }
 
         return CollectionUtils.isEmpty(esResult)
diff --git 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
index 567fd9971a..481ef19833 100644
--- 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
+++ 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
@@ -142,10 +142,12 @@ public class ElasticsearchAuditEventDAO implements 
AuditEventDAO {
                 
index(ElasticsearchUtils.getAuditIndex(AuthContextUtils.getDomain())).
                 query(getQuery(entityKey, type, category, subcategory, op, 
outcome, before, after)).
                 build();
+        LOG.debug("Count request: {}", request);
+
         try {
             return client.count(request).count();
         } catch (IOException e) {
-            LOG.error("Search error", e);
+            LOG.error("While counting in Elasticsearch with request {}", 
request, e);
             return 0L;
         }
     }
@@ -179,12 +181,13 @@ public class ElasticsearchAuditEventDAO implements 
AuditEventDAO {
                 size(pageable.isUnpaged() ? indexMaxResultWindow : 
pageable.getPageSize()).
                 sort(sortBuilders(pageable.getSort().get())).
                 build();
+        LOG.debug("Search request: {}", request);
 
         List<Hit<ObjectNode>> esResult = null;
         try {
             esResult = client.search(request, ObjectNode.class).hits().hits();
         } catch (Exception e) {
-            LOG.error("While searching in Elasticsearch", e);
+            LOG.error("While searching in Elasticsearch with request {}", 
request, e);
         }
 
         return CollectionUtils.isEmpty(esResult)
diff --git 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchRealmSearchDAO.java
 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchRealmSearchDAO.java
index b71124383a..5dae257e56 100644
--- 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchRealmSearchDAO.java
+++ 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchRealmSearchDAO.java
@@ -96,6 +96,7 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                 size(1).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         try {
             String result = client.search(request, 
Void.class).hits().hits().stream().findFirst().
@@ -103,7 +104,7 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                     orElse(null);
             return realmDAO.findById(result).map(Realm.class::cast);
         } catch (Exception e) {
-            LOG.error("While searching ES for one match", e);
+            LOG.error("While searching Elasticsearch for Realm path {} with 
request {}", fullPath, request, e);
         }
 
         return Optional.empty();
@@ -117,13 +118,14 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                 sort(REALM_SORT_OPTIONS).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         try {
             return client.search(request, Void.class).hits().hits().stream().
                     map(Hit::id).
                     toList();
         } catch (Exception e) {
-            LOG.error("While searching in Elasticsearch", e);
+            LOG.error("While searching in Elasticsearch with request {}", 
request, e);
             return List.of();
         }
     }
@@ -194,11 +196,12 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                 
index(ElasticsearchUtils.getRealmIndex(AuthContextUtils.getDomain())).
                 query(buildDescendantsQuery(bases, keyword)).
                 build();
+        LOG.debug("Count request: {}", request);
 
         try {
             return client.count(request).count();
         } catch (Exception e) {
-            LOG.error("While counting in Elasticsearch", e);
+            LOG.error("While counting in Elasticsearch with request {}", 
request, e);
             return 0;
         }
     }
@@ -219,6 +222,7 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                 sort(REALM_SORT_OPTIONS).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         List<String> result = List.of();
         try {
@@ -226,7 +230,7 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                     map(Hit::id).
                     toList();
         } catch (Exception e) {
-            LOG.error("While searching in Elasticsearch", e);
+            LOG.error("While searching in Elasticsearch with request {}", 
request, e);
         }
 
         return result.stream().map(realmDAO::findById).
@@ -255,6 +259,7 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                 sort(REALM_SORT_OPTIONS).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         List<String> result = List.of();
         try {
@@ -262,7 +267,7 @@ public class ElasticsearchRealmSearchDAO implements 
RealmSearchDAO {
                     map(Hit::id).
                     toList();
         } catch (Exception e) {
-            LOG.error("While searching in Elasticsearch", e);
+            LOG.error("While searching in Elasticsearch with request {}", 
request, e);
         }
         return result;
     }
diff --git 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
index 15216979d2..f58cf9c3f7 100644
--- 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
+++ 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAnySearchDAO.java
@@ -87,6 +87,8 @@ import org.springframework.util.CollectionUtils;
  */
 public class OpenSearchAnySearchDAO extends AbstractAnySearchDAO {
 
+    protected static final Set<String> ID_PROPS = Set.of("key", "id", "_id");
+
     protected final OpenSearchClient client;
 
     protected final int indexMaxResultWindow;
@@ -219,12 +221,12 @@ public class OpenSearchAnySearchDAO extends 
AbstractAnySearchDAO {
                 
index(OpenSearchUtils.getAnyIndex(AuthContextUtils.getDomain(), kind)).
                 query(getQuery(base, recursive, adminRealms, cond, kind)).
                 build();
-        LOG.debug("Count JSON request: {}", request);
+        LOG.debug("Count request: {}", request);
 
         try {
             return client.count(request).count();
         } catch (Exception e) {
-            LOG.error("While counting in OpenSearch", e);
+            LOG.error("While counting in OpenSearch with request {}", request, 
e);
             return 0;
         }
     }
@@ -236,17 +238,18 @@ public class OpenSearchAnySearchDAO extends 
AbstractAnySearchDAO {
         orderBy.forEach(clause -> {
             String sortName = null;
 
-            // Manage difference between external key attribute and internal 
_id
-            String fieldName = "key".equals(clause.getProperty()) ? "_id" : 
clause.getProperty();
-
-            Field anyField = anyUtils.getField(fieldName).orElse(null);
-            if (anyField == null) {
-                PlainSchema schema = 
plainSchemaDAO.findById(fieldName).orElse(null);
-                if (schema != null) {
+            String fieldName = clause.getProperty();
+            // Cannot sort by internal _id
+            if (!ID_PROPS.contains(fieldName)) {
+                Field anyField = anyUtils.getField(fieldName).orElse(null);
+                if (anyField == null) {
+                    PlainSchema schema = 
plainSchemaDAO.findById(fieldName).orElse(null);
+                    if (schema != null) {
+                        sortName = fieldName;
+                    }
+                } else {
                     sortName = fieldName;
                 }
-            } else {
-                sortName = fieldName;
             }
 
             if (sortName == null) {
@@ -281,13 +284,13 @@ public class OpenSearchAnySearchDAO extends 
AbstractAnySearchDAO {
                 sort(sortBuilders(kind, pageable.getSort().get())).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
-        LOG.debug("Search JSON request: {}", request);
+        LOG.debug("Search request: {}", request);
 
         List<Hit<Void>> esResult = null;
         try {
             esResult = client.search(request, Void.class).hits().hits();
         } catch (Exception e) {
-            LOG.error("While searching in OpenSearch", e);
+            LOG.error("While searching in OpenSearch with request {}", 
request, e);
         }
 
         return CollectionUtils.isEmpty(esResult)
diff --git 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
index 0b2dfd8e1a..71f487bfb5 100644
--- 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
+++ 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
@@ -141,10 +141,12 @@ public class OpenSearchAuditEventDAO implements 
AuditEventDAO {
                 
index(OpenSearchUtils.getAuditIndex(AuthContextUtils.getDomain())).
                 query(getQuery(entityKey, type, category, subcategory, op, 
outcome, before, after)).
                 build();
+        LOG.debug("Count request: {}", request);
+
         try {
             return client.count(request).count();
         } catch (IOException e) {
-            LOG.error("Search error", e);
+            LOG.error("While counting in OpenSearch with request {}", request, 
e);
             return 0L;
         }
     }
@@ -178,12 +180,13 @@ public class OpenSearchAuditEventDAO implements 
AuditEventDAO {
                 size(pageable.isUnpaged() ? indexMaxResultWindow : 
pageable.getPageSize()).
                 sort(sortBuilders(pageable.getSort().get())).
                 build();
+        LOG.debug("Search request: {}", request);
 
         List<Hit<ObjectNode>> esResult = null;
         try {
             esResult = client.search(request, ObjectNode.class).hits().hits();
         } catch (Exception e) {
-            LOG.error("While searching in OpenSearch", e);
+            LOG.error("While searching in OpenSearch with request {}", 
request, e);
         }
 
         return CollectionUtils.isEmpty(esResult)
diff --git 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchRealmSearchDAO.java
 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchRealmSearchDAO.java
index 942e8a9fcd..77cf5f3022 100644
--- 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchRealmSearchDAO.java
+++ 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchRealmSearchDAO.java
@@ -97,6 +97,7 @@ public class OpenSearchRealmSearchDAO implements 
RealmSearchDAO {
                 size(1).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         try {
             String result = client.search(request, 
Void.class).hits().hits().stream().findFirst().
@@ -104,7 +105,7 @@ public class OpenSearchRealmSearchDAO implements 
RealmSearchDAO {
                     orElse(null);
             return realmDAO.findById(result).map(Realm.class::cast);
         } catch (Exception e) {
-            LOG.error("While searching ES for one match", e);
+            LOG.error("While searching OpenSearch for Realm path {} with 
request {}", fullPath, request, e);
         }
 
         return Optional.empty();
@@ -118,13 +119,14 @@ public class OpenSearchRealmSearchDAO implements 
RealmSearchDAO {
                 sort(REALM_SORT_OPTIONS).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         try {
             return client.search(request, Void.class).hits().hits().stream().
                     map(Hit::id).
                     toList();
         } catch (Exception e) {
-            LOG.error("While searching in OpenSearch", e);
+            LOG.error("While searching in OpenSearch with request {}", 
request, e);
             return List.of();
         }
     }
@@ -194,11 +196,12 @@ public class OpenSearchRealmSearchDAO implements 
RealmSearchDAO {
                 
index(OpenSearchUtils.getRealmIndex(AuthContextUtils.getDomain())).
                 query(buildDescendantsQuery(bases, keyword)).
                 build();
+        LOG.debug("Count request: {}", request);
 
         try {
             return client.count(request).count();
         } catch (Exception e) {
-            LOG.error("While counting in OpenSearch", e);
+            LOG.error("While counting in OpenSearch with request {}", request, 
e);
             return 0;
         }
     }
@@ -219,6 +222,7 @@ public class OpenSearchRealmSearchDAO implements 
RealmSearchDAO {
                 sort(REALM_SORT_OPTIONS).
                 fields(List.of()).source(new 
SourceConfig.Builder().fetch(false).build()).
                 build();
+        LOG.debug("Search request: {}", request);
 
         List<String> result = List.of();
         try {
@@ -226,7 +230,7 @@ public class OpenSearchRealmSearchDAO implements 
RealmSearchDAO {
                     map(Hit::id).
                     toList();
         } catch (Exception e) {
-            LOG.error("While searching in OpenSearch", e);
+            LOG.error("While searching in OpenSearch with request {}", 
request, e);
         }
 
         return result.stream().map(realmDAO::findById).

Reply via email to