You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2023/02/04 10:38:38 UTC

[syncope] branch 3_0_X updated: [SYNCOPE-1727] Indexing realm values by key, not by full path (#407)

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

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


The following commit(s) were added to refs/heads/3_0_X by this push:
     new 624487e9cb [SYNCOPE-1727] Indexing realm values by key, not by full path (#407)
624487e9cb is described below

commit 624487e9cb3cdcc8f6bcf8a4436641bef3708ab5
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Sat Feb 4 11:38:33 2023 +0100

    [SYNCOPE-1727] Indexing realm values by key, not by full path (#407)
---
 .../elasticsearch/client/ElasticsearchUtils.java   |  2 +-
 .../jpa/dao/ElasticsearchAnySearchDAO.java         | 33 ++++++--------
 .../jpa/dao/ElasticsearchAnySearchDAOTest.java     |  4 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |  6 +++
 .../org/apache/syncope/fit/core/RealmITCase.java   |  5 --
 .../org/apache/syncope/fit/core/SearchITCase.java  | 53 +++++++++++++++++++++-
 6 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
index 7421d0fc26..19c5769485 100644
--- a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
+++ b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
@@ -100,7 +100,7 @@ public class ElasticsearchUtils {
 
         Map<String, Object> builder = new HashMap<>();
         builder.put("id", any.getKey());
-        builder.put("realm", any.getRealm().getFullPath());
+        builder.put("realm", any.getRealm().getKey());
         builder.put("anyType", any.getType().getKey());
         builder.put("creationDate", any.getCreationDate());
         builder.put("creationContext", any.getCreationContext());
diff --git a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
index 67681a51c6..726b8b8047 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
+++ b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
@@ -152,17 +152,16 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
                 if (goRealm.isPresent()) {
                     groupOwners.add(goRealm.get().getRight());
                 } else if (realmPath.startsWith("/")) {
-                    Realm realm = realmDAO.findByFullPath(realmPath);
-                    if (realm == null) {
+                    Realm realm = Optional.ofNullable(realmDAO.findByFullPath(realmPath)).orElseThrow(() -> {
                         SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
                         noRealm.getElements().add("Invalid realm specified: " + realmPath);
-                        throw noRealm;
-                    } else {
-                        realmDAO.findDescendants(realm).forEach(descendant -> queries.add(
-                                new Query.Builder().term(QueryBuilders.term().
-                                        field("realm").value(FieldValue.of(descendant.getFullPath())).build()).
-                                        build()));
-                    }
+                        return noRealm;
+                    });
+
+                    realmDAO.findDescendants(realm).forEach(descendant -> queries.add(
+                            new Query.Builder().term(QueryBuilders.term().
+                                    field("realm").value(FieldValue.of(descendant.getKey())).build()).
+                                    build()));
                 } else {
                     DynRealm dynRealm = dynRealmDAO.find(realmPath);
                     if (dynRealm == null) {
@@ -178,7 +177,7 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
         } else {
             if (adminRealms.stream().anyMatch(r -> base.getFullPath().startsWith(r))) {
                 queries.add(new Query.Builder().term(QueryBuilders.term().
-                        field("realm").value(FieldValue.of(base.getFullPath())).build()).
+                        field("realm").value(FieldValue.of(base.getKey())).build()).
                         build());
             }
         }
@@ -206,7 +205,7 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
                 query = new Query.Builder().bool(
                         QueryBuilders.bool().
                                 must(new Query.Builder().term(QueryBuilders.term().
-                                        field("realm").value(FieldValue.of(base.getFullPath())).build()).
+                                        field("realm").value(FieldValue.of(base.getKey())).build()).
                                         build()).
                                 must(query).build()).
                         build();
@@ -635,14 +634,10 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
     }
 
     protected Query getQuery(final AnyCond cond, final AnyTypeKind kind) {
-        if (JAXRSService.PARAM_REALM.equals(cond.getSchema())
-                && SyncopeConstants.UUID_PATTERN.matcher(cond.getExpression()).matches()) {
-
-            Realm realm = realmDAO.find(cond.getExpression());
-            if (realm == null) {
-                throw new IllegalArgumentException("Invalid Realm key: " + cond.getExpression());
-            }
-            cond.setExpression(realm.getFullPath());
+        if (JAXRSService.PARAM_REALM.equals(cond.getSchema()) && cond.getExpression().startsWith("/")) {
+            Realm realm = Optional.ofNullable(realmDAO.findByFullPath(cond.getExpression())).
+                    orElseThrow(() -> new IllegalArgumentException("Invalid Realm full path: " + cond.getExpression()));
+            cond.setExpression(realm.getKey());
         }
 
         Triple<PlainSchema, PlainAttrValue, AnyCond> checked = check(cond, kind);
diff --git a/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java b/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
index 02f4b7893f..1adbd0001b 100644
--- a/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
+++ b/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
@@ -113,7 +113,7 @@ public class ElasticsearchAnySearchDAOTest {
     public void getAdminRealmsFilter4realm() throws IOException {
         // 1. mock
         Realm root = mock(Realm.class);
-        when(root.getFullPath()).thenReturn(SyncopeConstants.ROOT_REALM);
+        when(root.getKey()).thenReturn("rootKey");
 
         when(realmDAO.findByFullPath(SyncopeConstants.ROOT_REALM)).thenReturn(root);
         when(realmDAO.findDescendants(root)).thenReturn(List.of(root));
@@ -126,7 +126,7 @@ public class ElasticsearchAnySearchDAOTest {
         assertThat(
                 new Query.Builder().disMax(QueryBuilders.disMax().queries(
                         new Query.Builder().term(QueryBuilders.term().field("realm").value(
-                                FieldValue.of(SyncopeConstants.ROOT_REALM)).build()).build()).build()).
+                                FieldValue.of("rootKey")).build()).build()).build()).
                         build()).
                 usingRecursiveComparison().isEqualTo(filter.getLeft().get());
         assertEquals(Set.of(), filter.getMiddle());
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 59dda15f92..a15398d403 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -34,6 +34,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.UUID;
@@ -88,6 +89,7 @@ import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.RoleTO;
@@ -983,6 +985,10 @@ public abstract class AbstractITCase {
         return results;
     }
 
+    protected static Optional<RealmTO> getRealm(final String fullPath) {
+        return REALM_SERVICE.list(fullPath).stream().filter(realm -> fullPath.equals(realm.getFullPath())).findFirst();
+    }
+
     @Autowired
     protected ConfParamOps confParamOps;
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index 2be1f8767c..a40a22ec1f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -26,7 +26,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.util.List;
-import java.util.Optional;
 import java.util.UUID;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.Response;
@@ -60,10 +59,6 @@ import org.junit.jupiter.api.Test;
 
 public class RealmITCase extends AbstractITCase {
 
-    private static Optional<RealmTO> getRealm(final String fullPath) {
-        return REALM_SERVICE.list(fullPath).stream().filter(realm -> fullPath.equals(realm.getFullPath())).findFirst();
-    }
-
     @Test
     public void search() {
         PagedResult<RealmTO> match = REALM_SERVICE.search(new RealmQuery.Builder().keyword("*o*").build());
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
index b894524c61..9128d9d1cc 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
@@ -50,6 +50,7 @@ import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PagedConnObjectResult;
 import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -57,6 +58,7 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.beans.AnyQuery;
 import org.apache.syncope.common.rest.api.beans.ConnObjectTOQuery;
 import org.apache.syncope.common.rest.api.service.GroupService;
+import org.apache.syncope.common.rest.api.service.RealmService;
 import org.apache.syncope.common.rest.api.service.RoleService;
 import org.apache.syncope.fit.AbstractITCase;
 import org.identityconnectors.framework.common.objects.Name;
@@ -326,8 +328,6 @@ public class SearchITCase extends AbstractITCase {
 
     @Test
     public void searchByDate() {
-        CLIENT_FACTORY.create("bellini", "password").self();
-
         if (IS_ELASTICSEARCH_ENABLED) {
             try {
                 Thread.sleep(2000);
@@ -808,4 +808,53 @@ public class SearchITCase extends AbstractITCase {
         assertNotNull(matching2);
         assertFalse(matching2.getResult().isEmpty());
     }
+
+    @Test
+    public void issueSYNCOPE1727() {
+        RealmTO realm = new RealmTO();
+        realm.setName("syncope1727");
+
+        // 1. create Realm
+        Response response = REALM_SERVICE.create("/even/two", realm);
+        RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
+        assertNotNull(actuals);
+        assertTrue(actuals.length > 0);
+        realm = actuals[0];
+        assertNotNull(realm.getKey());
+        assertEquals("syncope1727", realm.getName());
+        assertEquals("/even/two/syncope1727", realm.getFullPath());
+        assertEquals(realm.getParent(), getRealm("/even/two").get().getKey());
+
+        // 2. create user
+        UserCR userCR = UserITCase.getUniqueSample("syncope1727@syncope.apache.org");
+        userCR.setRealm(realm.getFullPath());
+        UserTO user = createUser(userCR).getEntity();
+
+        // 3. search for user
+        if (IS_ELASTICSEARCH_ENABLED) {
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException ex) {
+                // ignore
+            }
+        }
+
+        PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().is("realm").
+                        equalTo(realm.getKey()).query()).build());
+        assertEquals(1, users.getResult().size());
+        assertEquals(user.getKey(), users.getResult().get(0).getKey());
+
+        // 4. update parent Realm
+        realm.setParent(getRealm("/odd").get().getKey());
+        REALM_SERVICE.update(realm);
+        realm = getRealm("/odd/syncope1727").get();
+
+        // 5. search again for user
+        users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().is("realm").
+                        equalTo(realm.getKey()).query()).build());
+        assertEquals(1, users.getResult().size());
+        assertEquals(user.getKey(), users.getResult().get(0).getKey());
+    }
 }