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


The following commit(s) were added to refs/heads/master by this push:
     new 57499d370c [SYNCOPE-1719] No more limitations when setting memberships 
and relationships (#399)
57499d370c is described below

commit 57499d370cbcda40eedc58fa597d251f0d5efc81
Author: Francesco Chicchiriccò <ilgro...@users.noreply.github.com>
AuthorDate: Tue Jan 3 16:27:49 2023 +0100

    [SYNCOPE-1719] No more limitations when setting memberships and 
relationships (#399)
---
 .../syncope/client/console/wizards/any/Groups.java |  2 +-
 .../client/enduser/panels/any/PlainAttrs.java      |  6 +--
 .../src/test/resources/enduser-debug.properties    |  2 +-
 .../AnyObjectFiqlSearchConditionBuilder.java       | 12 ------
 .../common/lib/search/AnyObjectProperty.java       |  2 -
 .../search/GroupFiqlSearchConditionBuilder.java    | 12 ------
 .../syncope/common/lib/search/GroupProperty.java   |  2 -
 .../syncope/common/lib/search/SpecialAttr.java     |  6 +--
 .../syncope/common/lib/to/RelationshipTO.java      |  3 +-
 .../apache/syncope/core/logic/SyncopeLogic.java    | 16 +++----
 .../core/rest/cxf/service/AbstractAnyService.java  |  8 +---
 .../persistence/api/search/SearchCondVisitor.java  |  7 ---
 .../api/search/SearchCondConverterTest.java        | 13 ------
 core/persistence-jpa-json/pom.xml                  | 29 -------------
 .../persistence/jpa/dao/PGJPAJSONAnySearchDAO.java | 26 -----------
 .../persistence/jpa/dao/AbstractAnySearchDAO.java  | 10 -----
 .../core/persistence/jpa/dao/JPAAnyMatchDAO.java   | 17 --------
 .../core/persistence/jpa/dao/JPAAnySearchDAO.java  | 29 -------------
 .../core/persistence/jpa/dao/JPAGroupDAO.java      | 23 +++-------
 .../core/persistence/jpa/inner/AnySearchTest.java  | 22 ----------
 .../java/data/AbstractAnyDataBinder.java           |  4 +-
 .../java/data/AnyObjectDataBinderImpl.java         | 43 +++----------------
 .../provisioning/java/data/UserDataBinderImpl.java | 19 +-------
 .../jpa/dao/ElasticsearchAnySearchDAO.java         | 30 -------------
 .../reference/flowable/CreateARelationship.java    |  5 +--
 .../apache/syncope/fit/core/AnyObjectITCase.java   | 50 ++++++++++++----------
 .../org/apache/syncope/fit/core/GroupITCase.java   | 48 ++++++++++++---------
 .../syncope/fit/core/PropagationTaskITCase.java    |  4 +-
 .../org/apache/syncope/fit/core/SearchITCase.java  | 21 ---------
 .../asciidoc/reference-guide/concepts/realms.adoc  |  7 +--
 .../reference-guide/usage/clientlibrary.adoc       |  6 +--
 31 files changed, 91 insertions(+), 393 deletions(-)

diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
index e9642c5754..13426911bc 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
@@ -247,7 +247,7 @@ public class Groups extends AbstractGroups {
                 if (!conditions.isEmpty()) {
                     assignedGroups.putAll(groupRestClient.search(
                             realmObj,
-                            
builder.isAssignable().and().or(conditions).query(),
+                            builder.or(conditions).query(),
                             1,
                             Constants.MAX_GROUP_LIST_SIZE,
                             sort,
diff --git 
a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
 
b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
index 3b597b92e7..887e9b6c40 100644
--- 
a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
+++ 
b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/panels/any/PlainAttrs.java
@@ -371,10 +371,8 @@ public class PlainAttrs extends 
AbstractAttrs<PlainSchemaTO> {
 
                     AbstractFieldPanel<?> panel = 
getFieldPanel(schemas.get(attrTO.getSchema()));
                     if (schemas.get(attrTO.getSchema()).isMultivalue()) {
-                        panel = new MultiFieldPanel.Builder<>(
-                                new PropertyModel<>(
-                                        
attributableTO.getObject().getPlainAttr(attrTO.getSchema()), "values"))
-                                .build("panel", attrTO.getSchema(), 
FieldPanel.class.cast(panel));
+                        panel = new MultiFieldPanel.Builder<>(new 
PropertyModel<>(attrTO, "values")).
+                                build("panel", attrTO.getSchema(), 
FieldPanel.class.cast(panel));
                         // SYNCOPE-1215 the entire multifield panel must be 
readonly, not only its field
                         ((MultiFieldPanel) panel).setReadOnly(schema == null ? 
false : schema.isReadonly());
                     } else {
diff --git a/client/idrepo/enduser/src/test/resources/enduser-debug.properties 
b/client/idrepo/enduser/src/test/resources/enduser-debug.properties
index f03153d767..dc5eaed661 100644
--- a/client/idrepo/enduser/src/test/resources/enduser-debug.properties
+++ b/client/idrepo/enduser/src/test/resources/enduser-debug.properties
@@ -19,6 +19,6 @@ keymaster.username=${anonymousUser}
 keymaster.password=${anonymousKey}
 
 server.port=9091
-service.discovery.address=http://localhost:9090/syncope-console/
+service.discovery.address=http://localhost:9090/syncope-enduser/
 
 logging.config=file://${project.build.testOutputDirectory}/log4j2.xml
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
index c2d8895366..cfdc87eb7e 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectFiqlSearchConditionBuilder.java
@@ -91,12 +91,6 @@ public class AnyObjectFiqlSearchConditionBuilder extends 
AbstractFiqlSearchCondi
                 notInRelationshipTypes(type, moreTypes);
     }
 
-    public AnyObjectCompleteCondition isAssignable() {
-        return newBuilderInstance().
-                is(SpecialAttr.ASSIGNABLE.toString()).
-                isAssignable();
-    }
-
     protected class Builder extends AbstractFiqlSearchConditionBuilder.Builder<
             AnyObjectProperty, AnyObjectPartialCondition, 
AnyObjectCompleteCondition>
             implements AnyObjectProperty, AnyObjectPartialCondition, 
AnyObjectCompleteCondition {
@@ -157,11 +151,5 @@ public class AnyObjectFiqlSearchConditionBuilder extends 
AbstractFiqlSearchCondi
             this.result = SpecialAttr.RELATIONSHIP_TYPES.toString();
             return condition(FiqlParser.NEQ, type, (Object[]) moreTypes);
         }
-
-        @Override
-        public AnyObjectCompleteCondition isAssignable() {
-            this.result = SpecialAttr.ASSIGNABLE.toString();
-            return condition(FiqlParser.EQ, SpecialAttr.NULL);
-        }
     }
 }
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
index 24cd9436e1..755d1d935a 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AnyObjectProperty.java
@@ -31,6 +31,4 @@ public interface AnyObjectProperty extends 
SyncopeProperty<AnyObjectCompleteCond
     AnyObjectCompleteCondition inRelationshipTypes(String type, String... 
moreTypes);
 
     AnyObjectCompleteCondition notInRelationshipTypes(String type, String... 
moreTypes);
-
-    AnyObjectCompleteCondition isAssignable();
 }
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
index bf7ddb292b..512e699b79 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupFiqlSearchConditionBuilder.java
@@ -40,12 +40,6 @@ public class GroupFiqlSearchConditionBuilder
         return newBuilderInstance().is(property);
     }
 
-    public GroupCompleteCondition isAssignable() {
-        return newBuilderInstance().
-                is(SpecialAttr.ASSIGNABLE.toString()).
-                isAssignable();
-    }
-
     public GroupCompleteCondition withMembers(final String member, final 
String... moreMembers) {
         return newBuilderInstance().
                 is(SpecialAttr.MEMBER.toString()).
@@ -77,12 +71,6 @@ public class GroupFiqlSearchConditionBuilder
             return b;
         }
 
-        @Override
-        public GroupCompleteCondition isAssignable() {
-            this.result = SpecialAttr.ASSIGNABLE.toString();
-            return condition(FiqlParser.EQ, SpecialAttr.NULL);
-        }
-
         @Override
         public GroupCompleteCondition withMembers(final String member, final 
String... moreMembers) {
             this.result = SpecialAttr.MEMBER.toString();
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
index 8108012f03..a71bb93ba5 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/GroupProperty.java
@@ -20,8 +20,6 @@ package org.apache.syncope.common.lib.search;
 
 public interface GroupProperty extends SyncopeProperty<GroupCompleteCondition> 
{
 
-    GroupCompleteCondition isAssignable();
-
     GroupCompleteCondition withMembers(String member, String... moreMembers);
 
     GroupCompleteCondition withoutMembers(String member, String... 
moreMembers);
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
index 3bd37291bc..4d960c1815 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
@@ -66,11 +66,7 @@ public enum SpecialAttr {
     /**
      * Applies to groups.
      */
-    MEMBER("$member"),
-    /**
-     * Applies to groups and any objects.
-     */
-    ASSIGNABLE("$assignable");
+    MEMBER("$member");
 
     private final String literal;
 
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
index fd491cea37..8100da88d0 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
@@ -30,9 +30,8 @@ public class RelationshipTO implements BaseBean {
 
         private final RelationshipTO instance = new RelationshipTO();
 
-        public Builder type(final String type) {
+        public Builder(final String type) {
             instance.setType(type);
-            return this;
         }
 
         public Builder otherEnd(final String otherEndType, final String 
otherEndKey) {
diff --git 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index 7aaea2ecca..3ad2049c8d 100644
--- 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -39,7 +39,6 @@ import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
@@ -123,21 +122,16 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> 
{
         Realm base = Optional.ofNullable(realmDAO.findByFullPath(realm)).
                 orElseThrow(() -> new NotFoundException("Realm " + realm));
 
-        AssignableCond assignableCond = new AssignableCond();
-        assignableCond.setRealmFullPath(realm);
-
-        SearchCond searchCond;
+        AnyCond termCond;
         if (StringUtils.isNotBlank(term)) {
-            AnyCond termCond = new AnyCond(AttrCond.Type.ILIKE);
+            termCond = new AnyCond(AttrCond.Type.ILIKE);
             termCond.setSchema("name");
             termCond.setExpression(term.replace("*", "%"));
-
-            searchCond = SearchCond.getAnd(
-                    SearchCond.getLeaf(assignableCond),
-                    SearchCond.getLeaf(termCond));
         } else {
-            searchCond = SearchCond.getLeaf(assignableCond);
+            termCond = new AnyCond(AttrCond.Type.ISNOTNULL);
+            termCond.setSchema("key");
         }
+        SearchCond searchCond = SearchCond.getLeaf(termCond);
 
         int count = searchDAO.count(base, true, 
SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.GROUP);
 
diff --git 
a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
 
b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
index 833edd6891..67a3aa93a3 100644
--- 
a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
+++ 
b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
@@ -36,7 +36,6 @@ import org.apache.syncope.common.lib.request.AnyUR;
 import org.apache.syncope.common.lib.request.AttrPatch;
 import org.apache.syncope.common.lib.request.ResourceAR;
 import org.apache.syncope.common.lib.request.ResourceDR;
-import org.apache.syncope.common.lib.search.SpecialAttr;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
@@ -128,11 +127,6 @@ public abstract class AbstractAnyService<TO extends AnyTO, 
CR extends AnyCR, UR
     public PagedResult<TO> search(final AnyQuery anyQuery) {
         String realm = StringUtils.prependIfMissing(anyQuery.getRealm(), 
SyncopeConstants.ROOT_REALM);
 
-        // if an assignable query is provided in the FIQL string, start anyway 
from root realm
-        boolean isAssignableCond = StringUtils.isBlank(anyQuery.getFiql())
-                ? false
-                : -1 != 
anyQuery.getFiql().indexOf(SpecialAttr.ASSIGNABLE.toString());
-
         SearchCond searchCond = StringUtils.isBlank(anyQuery.getFiql())
                 ? null
                 : getSearchCond(anyQuery.getFiql(), realm);
@@ -143,7 +137,7 @@ public abstract class AbstractAnyService<TO extends AnyTO, 
CR extends AnyCR, UR
                     anyQuery.getPage(),
                     anyQuery.getSize(),
                     getOrderByClauses(anyQuery.getOrderBy()),
-                    isAssignableCond ? SyncopeConstants.ROOT_REALM : realm,
+                    realm,
                     anyQuery.getRecursive(),
                     anyQuery.getDetails());
 
diff --git 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
index acc8658298..92de4a349e 100644
--- 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
+++ 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
@@ -35,7 +35,6 @@ import org.apache.syncope.common.lib.search.SyncopeFiqlParser;
 import org.apache.syncope.common.lib.search.SyncopeFiqlSearchCondition;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
@@ -200,12 +199,6 @@ public class SearchCondVisitor extends 
AbstractSearchConditionVisitor<SearchBean
                             leaf = SearchCond.getLeaf(dynRealmCond);
                             break;
 
-                        case ASSIGNABLE:
-                            AssignableCond assignableCond = new 
AssignableCond();
-                            assignableCond.setRealmFullPath(REALM.get());
-                            leaf = SearchCond.getLeaf(assignableCond);
-                            break;
-
                         case MEMBER:
                             MemberCond memberCond = new MemberCond();
                             memberCond.setMember(value);
diff --git 
a/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
 
b/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
index f62d0d3781..eff4efd305 100644
--- 
a/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
+++ 
b/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
@@ -27,7 +27,6 @@ import org.apache.syncope.common.lib.search.SpecialAttr;
 import org.apache.syncope.common.lib.search.UserFiqlSearchConditionBuilder;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
@@ -251,18 +250,6 @@ public class SearchCondConverterTest {
         assertEquals(leaf, SearchCondConverter.convert(VISITOR, fiql));
     }
 
-    @Test
-    public void assignable() {
-        String fiql = new 
GroupFiqlSearchConditionBuilder().isAssignable().query();
-        assertEquals(SpecialAttr.ASSIGNABLE + "==" + SpecialAttr.NULL, fiql);
-
-        AssignableCond assignableCond = new AssignableCond();
-        assignableCond.setRealmFullPath("/even/two");
-        SearchCond leaf = SearchCond.getLeaf(assignableCond);
-
-        assertEquals(leaf, SearchCondConverter.convert(VISITOR, fiql, 
"/even/two"));
-    }
-
     @Test
     public void type() {
         String fiql = new 
AnyObjectFiqlSearchConditionBuilder("PRINTER").query();
diff --git a/core/persistence-jpa-json/pom.xml 
b/core/persistence-jpa-json/pom.xml
index 73f86de5fa..c301d216df 100644
--- a/core/persistence-jpa-json/pom.xml
+++ b/core/persistence-jpa-json/pom.xml
@@ -158,35 +158,6 @@ under the License.
   </build>
 
   <profiles>
-    <profile>
-      <id>sqlgen</id>
-      
-      <properties>
-        <skipTests>true</skipTests>
-      </properties>
-      
-      <build>
-        <defaultGoal>clean verify</defaultGoal>
-        
-        <plugins>
-          <plugin>
-            <groupId>org.apache.openjpa</groupId>
-            <artifactId>openjpa-maven-plugin</artifactId>
-            <inherited>true</inherited>
-            <executions>
-              <execution>
-                <id>sqlgen</id>
-                <phase>process-classes</phase>
-                <goals>
-                  <goal>sql</goal>
-                </goals>
-              </execution>
-            </executions>
-          </plugin>          
-        </plugins>
-      </build>
-    </profile>
-    
     <profile>
       <id>openjpa</id>
       
diff --git 
a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
 
b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
index e2c4c71f0f..4fceb3609b 100644
--- 
a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
+++ 
b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
@@ -42,7 +42,6 @@ import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
@@ -459,31 +458,6 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO 
{
         return query.toString();
     }
 
-    @Override
-    protected String getQuery(
-            final AssignableCond cond,
-            final List<Object> parameters,
-            final SearchSupport svs) {
-
-        Realm realm = check(cond);
-
-        StringBuilder query = new StringBuilder().append('(');
-        if (cond.isFromGroup()) {
-            realmDAO.findDescendants(realm).forEach(current -> 
query.append("realm_id=?").
-                    append(setParameter(parameters, 
current.getKey())).append(" OR "));
-            query.setLength(query.length() - 4);
-        } else {
-            for (Realm current = realm; current.getParent() != null; current = 
current.getParent()) {
-                query.append("realm_id=?").append(setParameter(parameters, 
current.getKey())).append(" OR ");
-            }
-            query.append("realm_id=?").append(setParameter(parameters, 
realmDAO.getRoot().getKey()));
-        }
-
-        query.append(')');
-
-        return query.toString();
-    }
-
     @Override
     protected String getQuery(
             final MemberCond cond,
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
index 0443b45761..41479e11ea 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java
@@ -45,7 +45,6 @@ import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AbstractSearchCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
 import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
@@ -315,15 +314,6 @@ public abstract class AbstractAnySearchDAO extends 
AbstractDAO<Any<?>> implement
         return rightAnyObjectKey;
     }
 
-    protected Realm check(final AssignableCond cond) {
-        Realm realm = realmDAO.findByFullPath(cond.getRealmFullPath());
-        if (realm == null) {
-            throw new IllegalArgumentException("Could not find realm for " + 
cond.getRealmFullPath());
-        }
-
-        return realm;
-    }
-
     protected String check(final MemberCond cond) {
         String memberKey;
         if (SyncopeConstants.UUID_PATTERN.matcher(cond.getMember()).matches()) 
{
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
index d086fc8ad0..4e06850bb8 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyMatchDAO.java
@@ -44,7 +44,6 @@ import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
 import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
@@ -61,7 +60,6 @@ import 
org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
-import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
@@ -143,12 +141,6 @@ public class JPAAnyMatchDAO extends AbstractDAO<Any<?>> 
implements AnyMatchDAO {
                             orElse(null);
                 }
 
-                if (match == null) {
-                    match = cond.getLeaf(AssignableCond.class).
-                            map(leaf -> matches(any, leaf, not)).
-                            orElse(null);
-                }
-
                 if (match == null) {
                     match = cond.getLeaf(RoleCond.class).
                             filter(leaf -> any instanceof User).
@@ -243,15 +235,6 @@ public class JPAAnyMatchDAO extends AbstractDAO<Any<?>> 
implements AnyMatchDAO {
         return not ? !found : found;
     }
 
-    protected boolean matches(final Any<?> any, final AssignableCond cond, 
final boolean not) {
-        Realm realm = realmDAO.findByFullPath(cond.getRealmFullPath());
-        boolean found = Optional.ofNullable(realm)
-                .filter(realm1 -> (cond.isFromGroup() ? 
realmDAO.findDescendants(realm1) : realmDAO.
-                findAncestors(realm1)).
-                stream().anyMatch(item -> 
item.equals(any.getRealm()))).isPresent();
-        return not ? !found : found;
-    }
-
     protected boolean matches(final User user, final RoleCond cond, final 
boolean not) {
         boolean found = userDAO.findAllRoles(user).stream().anyMatch(role -> 
role.getKey().equals(cond.getRole()));
         return not ? !found : found;
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 023b370876..e3f6b50286 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -44,7 +44,6 @@ import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
@@ -578,9 +577,6 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
                         filter(leaf -> AnyTypeKind.GROUP == svs.anyTypeKind).
                         ifPresent(leaf -> query.append(getQuery(leaf, not, 
parameters, svs)));
 
-                cond.getLeaf(AssignableCond.class).
-                        ifPresent(leaf -> query.append(getQuery(leaf, 
parameters, svs)));
-
                 cond.getLeaf(RoleCond.class).
                         filter(leaf -> AnyTypeKind.USER == svs.anyTypeKind).
                         ifPresent(leaf -> query.append(getQuery(leaf, not, 
parameters, svs)));
@@ -897,31 +893,6 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
         return query.toString();
     }
 
-    protected String getQuery(
-            final AssignableCond cond,
-            final List<Object> parameters,
-            final SearchSupport svs) {
-
-        Realm realm = check(cond);
-
-        StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM 
").
-                append(svs.field().name).append(" WHERE (");
-        if (cond.isFromGroup()) {
-            realmDAO.findDescendants(realm).forEach(current -> {
-                query.append("realm_id=?").append(setParameter(parameters, 
current.getKey())).append(" OR ");
-            });
-            query.setLength(query.length() - 4);
-        } else {
-            for (Realm current = realm; current.getParent() != null; current = 
current.getParent()) {
-                query.append("realm_id=?").append(setParameter(parameters, 
current.getKey())).append(" OR ");
-            }
-            query.append("realm_id=?").append(setParameter(parameters, 
realmDAO.getRoot().getKey()));
-        }
-        query.append(')');
-
-        return query.toString();
-    }
-
     protected String getQuery(
             final MemberCond cond,
             final boolean not,
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index ac5c3d15c5..adb6a76745 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -42,7 +42,6 @@ import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
@@ -279,14 +278,8 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> 
implements GroupDAO {
         return findAllKeys(JPAGroup.TABLE, page, itemsPerPage);
     }
 
-    protected SearchCond buildDynMembershipCond(final String baseCondFIQL, 
final Realm groupRealm) {
-        AssignableCond cond = new AssignableCond();
-        cond.setRealmFullPath(groupRealm.getFullPath());
-        cond.setFromGroup(true);
-
-        return SearchCond.getAnd(
-                SearchCond.getLeaf(cond),
-                SearchCondConverter.convert(searchCondVisitor, baseCondFIQL));
+    protected SearchCond buildDynMembershipCond(final String baseCondFIQL) {
+        return SearchCondConverter.convert(searchCondVisitor, baseCondFIQL);
     }
 
     @Override
@@ -296,7 +289,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> 
implements GroupDAO {
         // refresh dynamic memberships
         clearUDynMembers(merged);
         if (merged.getUDynMembership() != null) {
-            SearchCond cond = 
buildDynMembershipCond(merged.getUDynMembership().getFIQLCond(), 
merged.getRealm());
+            SearchCond cond = 
buildDynMembershipCond(merged.getUDynMembership().getFIQLCond());
             int count = anySearchDAO.count(
                     merged.getRealm(), true, 
Set.of(merged.getRealm().getFullPath()), cond, AnyTypeKind.USER);
             for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; 
page++) {
@@ -323,7 +316,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> 
implements GroupDAO {
         }
         clearADynMembers(merged);
         merged.getADynMemberships().forEach(memb -> {
-            SearchCond cond = buildDynMembershipCond(memb.getFIQLCond(), 
merged.getRealm());
+            SearchCond cond = buildDynMembershipCond(memb.getFIQLCond());
             int count = anySearchDAO.count(
                     merged.getRealm(), true, 
Set.of(merged.getRealm().getFullPath()), cond, AnyTypeKind.ANY_OBJECT);
             for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; 
page++) {
@@ -495,9 +488,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> 
implements GroupDAO {
         Set<String> before = new HashSet<>();
         Set<String> after = new HashSet<>();
         findWithADynMemberships(anyObject.getType()).forEach(memb -> {
-            boolean matches = anyMatchDAO.matches(
-                    anyObject,
-                    buildDynMembershipCond(memb.getFIQLCond(), 
memb.getGroup().getRealm()));
+            boolean matches = anyMatchDAO.matches(anyObject, 
buildDynMembershipCond(memb.getFIQLCond()));
             if (matches) {
                 after.add(memb.getGroup().getKey());
             }
@@ -596,9 +587,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> 
implements GroupDAO {
         Set<String> before = new HashSet<>();
         Set<String> after = new HashSet<>();
         findWithUDynMemberships().forEach(memb -> {
-            boolean matches = anyMatchDAO.matches(
-                    user,
-                    buildDynMembershipCond(memb.getFIQLCond(), 
memb.getGroup().getRealm()));
+            boolean matches = anyMatchDAO.matches(user, 
buildDynMembershipCond(memb.getFIQLCond()));
             if (matches) {
                 after.add(memb.getGroup().getKey());
             }
diff --git 
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
 
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 0b2bf3399a..1fff8d5176 100644
--- 
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ 
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -45,7 +45,6 @@ import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
 import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
@@ -619,27 +618,6 @@ public class AnySearchTest extends AbstractTest {
                 groups.size());
     }
 
-    @Test
-    public void assignable() {
-        AssignableCond assignableCond = new AssignableCond();
-        assignableCond.setRealmFullPath("/even/two");
-        SearchCond searchCondition = SearchCond.getLeaf(assignableCond);
-        assertTrue(searchCondition.isValid());
-
-        List<Group> groups = searchDAO.search(searchCondition, 
AnyTypeKind.GROUP);
-        assertTrue(groups.stream().anyMatch(group -> 
"additional".equals(group.getName())));
-        assertFalse(groups.stream().anyMatch(group -> 
"fake".equals(group.getName())));
-
-        assignableCond = new AssignableCond();
-        assignableCond.setRealmFullPath("/odd");
-        searchCondition = SearchCond.getLeaf(assignableCond);
-        assertTrue(searchCondition.isValid());
-
-        List<AnyObject> anyObjects = searchDAO.search(searchCondition, 
AnyTypeKind.ANY_OBJECT);
-        assertFalse(anyObjects.stream().
-                anyMatch(anyObject -> 
"9e1d130c-d6a3-48b1-98b3-182477ed0688".equals(anyObject.getKey())));
-    }
-
     @Test
     public void member() {
         MemberCond memberCond = new MemberCond();
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index c8a89310f8..b237bf43a9 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -658,8 +658,8 @@ abstract class AbstractAnyDataBinder {
     }
 
     protected static RelationshipTO getRelationshipTO(final String 
relationshipType, final AnyObject otherEnd) {
-        return new RelationshipTO.Builder().
-                type(relationshipType).otherEnd(otherEnd.getType().getKey(), 
otherEnd.getKey(), otherEnd.getName()).
+        return new RelationshipTO.Builder(relationshipType).
+                otherEnd(otherEnd.getType().getKey(), otherEnd.getKey(), 
otherEnd.getName()).
                 build();
     }
 
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index 643f2e7c19..306a8d0809 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -236,10 +236,11 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
 
                     SyncopeClientException assigned =
                             
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
-                    assigned.getElements().add(otherEnd.getType().getKey() + " 
" + otherEnd.getName()
-                            + " in relationship " + relationshipTO.getType());
+                    assigned.getElements().add("AnyObject was already in 
relationship "
+                            + relationshipTO.getType() + " with "
+                            + otherEnd.getType().getKey() + " " + 
otherEnd.getName());
                     scce.addException(assigned);
-                } else if 
(anyObject.getRealm().getFullPath().startsWith(otherEnd.getRealm().getFullPath()))
 {
+                } else {
                     relationships.add(Pair.of(otherEnd.getKey(), 
relationshipTO.getType()));
 
                     RelationshipType relationshipType = 
relationshipTypeDAO.find(relationshipTO.getType());
@@ -253,14 +254,6 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
 
                         anyObject.add(relationship);
                     }
-                } else {
-                    LOG.error("{} cannot be related to {}", otherEnd, 
anyObject);
-
-                    SyncopeClientException unrelatable =
-                            
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
-                    unrelatable.getElements().add(otherEnd.getType().getKey() 
+ " " + otherEnd.getName()
-                            + " cannot be related");
-                    scce.addException(unrelatable);
                 }
             }
         });
@@ -281,7 +274,7 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                         
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
                 assigned.getElements().add("Group " + group.getName() + " was 
already assigned");
                 scce.addException(assigned);
-            } else if 
(anyObject.getRealm().getFullPath().startsWith(group.getRealm().getFullPath())) 
{
+            } else {
                 groups.add(group.getKey());
 
                 AMembership membership = 
entityFactory.newEntity(AMembership.class);
@@ -292,13 +285,6 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
 
                 // membership attributes
                 fill(anyObject, membership, membershipTO, 
anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), scce);
-            } else {
-                LOG.error("{} cannot be assigned to {}", group, anyObject);
-
-                SyncopeClientException unassignable =
-                        
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
-                unassignable.getElements().add("Group " + group.getName() + " 
cannot be assigned");
-                scce.addException(unassignable);
             }
         });
 
@@ -378,7 +364,7 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                                     + patch.getRelationshipTO().getType() + " 
with "
                                     + otherEnd.getType().getKey() + " " + 
otherEnd.getName());
                             scce.addException(assigned);
-                        } else if 
(anyObject.getRealm().getFullPath().startsWith(otherEnd.getRealm().getFullPath()))
 {
+                        } else {
                             relationships.add(Pair.of(otherEnd.getKey(), 
patch.getRelationshipTO().getType()));
 
                             ARelationship newRelationship = 
entityFactory.newEntity(ARelationship.class);
@@ -387,14 +373,6 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                             newRelationship.setLeftEnd(anyObject);
 
                             anyObject.add(newRelationship);
-                        } else {
-                            LOG.error("{} cannot be related to {}", otherEnd, 
anyObject);
-
-                            SyncopeClientException unrelatable =
-                                    
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
-                            
unrelatable.getElements().add(otherEnd.getType().getKey() + " " + 
otherEnd.getName()
-                                    + " cannot be related");
-                            scce.addException(unrelatable);
                         }
                     }
                 }
@@ -433,7 +411,7 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                             
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
                     assigned.getElements().add("Multiple patches for group " + 
group.getName() + " were found");
                     scce.addException(assigned);
-                } else if 
(anyObject.getRealm().getFullPath().startsWith(group.getRealm().getFullPath())) 
{
+                } else {
                     groups.add(group.getKey());
 
                     AMembership newMembership = 
entityFactory.newEntity(AMembership.class);
@@ -475,13 +453,6 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                     }
 
                     propByRes.addAll(ResourceOperation.UPDATE, 
groupDAO.findAllResourceKeys(group.getKey()));
-                } else {
-                    LOG.error("{} cannot be assigned to {}", group, anyObject);
-
-                    SyncopeClientException unassignable =
-                            
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
-                    unassignable.getElements().add("Group " + group.getName() 
+ " cannot be assigned");
-                    scce.addException(unassignable);
                 }
             }
         });
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index b61320990a..4062101b73 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -404,7 +404,7 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
                         
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
                 assigned.getElements().add("Group " + group.getName() + " was 
already assigned");
                 scce.addException(assigned);
-            } else if 
(user.getRealm().getFullPath().startsWith(group.getRealm().getFullPath())) {
+            } else {
                 groups.add(group.getKey());
 
                 UMembership membership = 
entityFactory.newEntity(UMembership.class);
@@ -415,13 +415,6 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
 
                 // membership attributes
                 fill(user, membership, membershipTO, 
anyUtilsFactory.getInstance(AnyTypeKind.USER), scce);
-            } else {
-                LOG.error("{} cannot be assigned to {}", group, user);
-
-                SyncopeClientException unassignable =
-                        
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
-                unassignable.getElements().add("Group " + group.getName() + " 
cannot be assigned");
-                scce.addException(unassignable);
             }
         });
 
@@ -629,7 +622,7 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
                             
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
                     assigned.getElements().add("Multiple patches for group " + 
group.getName() + " were found");
                     scce.addException(assigned);
-                } else if 
(user.getRealm().getFullPath().startsWith(group.getRealm().getFullPath())) {
+                } else {
                     groups.add(group.getKey());
 
                     UMembership newMembership = 
entityFactory.newEntity(UMembership.class);
@@ -681,13 +674,6 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
                                 filter(this::isPasswordMapped).
                                 forEach(resource -> 
userUR.getPassword().getResources().add(resource.getKey()));
                     }
-                } else {
-                    LOG.error("{} cannot be assigned to {}", group, user);
-
-                    SyncopeClientException unassignable =
-                            
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
-                    unassignable.getElements().add("Group " + group.getName() 
+ " cannot be assigned");
-                    scce.addException(unassignable);
                 }
             }
         });
@@ -714,7 +700,6 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
                     plainAttrValueDAO.deleteAll(attr, 
anyUtilsFactory.getLinkedAccountInstance());
                     plainAttrDAO.delete(attr);
                 });
-
             });
             if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
                 linkedAccount(
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 b7cb0c09c4..a04f980710 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
@@ -57,7 +57,6 @@ import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
-import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
 import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
 import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
@@ -358,12 +357,6 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
                             orElse(null);
                 }
 
-                if (query == null) {
-                    query = cond.getLeaf(AssignableCond.class).
-                            map(this::getQuery).
-                            orElse(null);
-                }
-
                 if (query == null) {
                     query = cond.getLeaf(RoleCond.class).
                             filter(leaf -> AnyTypeKind.USER == kind).
@@ -473,29 +466,6 @@ public class ElasticsearchAnySearchDAO extends 
AbstractAnySearchDAO {
         return new 
Query.Builder().disMax(QueryBuilders.disMax().queries(membershipQueries).build()).build();
     }
 
-    protected Query getQuery(final AssignableCond cond) {
-        Realm realm = check(cond);
-
-        List<Query> queries = new ArrayList<>();
-        if (cond.isFromGroup()) {
-            realmDAO.findDescendants(realm).forEach(
-                    current -> queries.add(new 
Query.Builder().term(QueryBuilders.term().
-                            
field("realm").value(FieldValue.of(current.getFullPath())).build()).
-                            build()));
-        } else {
-            for (Realm current = realm; current.getParent() != null; current = 
current.getParent()) {
-                queries.add(new Query.Builder().term(QueryBuilders.term().
-                        
field("realm").value(FieldValue.of(current.getFullPath())).build()).
-                        build());
-            }
-            queries.add(new Query.Builder().term(QueryBuilders.term().
-                    
field("realm").value(FieldValue.of(realmDAO.getRoot().getFullPath())).build()).
-                    build());
-        }
-
-        return new 
Query.Builder().disMax(QueryBuilders.disMax().queries(queries).build()).build();
-    }
-
     protected Query getQuery(final RoleCond cond) {
         return new Query.Builder().term(QueryBuilders.term().
                 field("roles").value(FieldValue.of(cond.getRole())).build()).
diff --git 
a/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java
 
b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java
index e781bf43e1..cfd3e40948 100644
--- 
a/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java
+++ 
b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java
@@ -53,9 +53,8 @@ public class CreateARelationship extends FlowableServiceTask {
 
             UserUR userUR = new UserUR();
             userUR.setKey(user.getKey());
-            userUR.getRelationships().add(new RelationshipUR.Builder(new 
RelationshipTO.Builder().
-                    otherEnd("PRINTER", printer).type("neighborhood").build()).
-                    build());
+            userUR.getRelationships().add(new RelationshipUR.Builder(new 
RelationshipTO.Builder("neighborhood").
+                    otherEnd("PRINTER", printer).build()).build());
 
             Pair<PropagationByResource<String>, 
PropagationByResource<Pair<String, String>>> propInfo =
                     dataBinder.update(user, userUR);
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
index c7ddf8fca2..f1ca61ce8c 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
@@ -33,10 +33,10 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.request.AnyObjectCR;
 import org.apache.syncope.common.lib.request.AnyObjectUR;
+import org.apache.syncope.common.lib.request.RelationshipUR;
 import org.apache.syncope.common.lib.request.StringPatchItem;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.ConnObject;
-import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -75,27 +75,6 @@ public class AnyObjectITCase extends AbstractITCase {
                 connObjectTO.getAttr("LOCATION").get().getValues());
     }
 
-    @Test
-    public void createInvalidMembership() {
-        // 1. create anyObject in realm /odd and attempt to assign group 15, 
from realm /even => exception
-        AnyObjectCR anyObjectCR = getSample("createInvalidMembership");
-        anyObjectCR.setRealm("/odd");
-        anyObjectCR.getMemberships().add(new 
MembershipTO.Builder("034740a9-fa10-453b-af37-dc7897e98fb1").build());
-
-        try {
-            createAnyObject(anyObjectCR);
-            fail("This should not happen");
-        } catch (SyncopeClientException e) {
-            assertEquals(ClientExceptionType.InvalidMembership, e.getType());
-        }
-
-        // 2. change anyObject's realm to /even/two, now it works
-        anyObjectCR.setRealm("/even/two");
-
-        AnyObjectTO anyObjectTO = createAnyObject(anyObjectCR).getEntity();
-        
assertNotNull(anyObjectTO.getMembership("034740a9-fa10-453b-af37-dc7897e98fb1"));
-    }
-
     @Test
     public void delete() {
         try {
@@ -199,10 +178,35 @@ public class AnyObjectITCase extends AbstractITCase {
         }
     }
 
+    @Test
+    public void unlimitedRelationships() {
+        AnyObjectCR anyObjectCR = getSample("unlimited1");
+        anyObjectCR.setRealm("/even/two");
+        anyObjectCR.getResources().clear();
+        AnyObjectTO left = createAnyObject(anyObjectCR).getEntity();
+
+        anyObjectCR = getSample("unlimited2");
+        anyObjectCR.setRealm(SyncopeConstants.ROOT_REALM);
+        anyObjectCR.getResources().clear();
+        anyObjectCR.getRelationships().add(new 
RelationshipTO.Builder("neighborhood").
+                otherEnd(left.getType(), left.getKey()).build());
+        AnyObjectTO right = createAnyObject(anyObjectCR).getEntity();
+
+        assertEquals(1, right.getRelationships().size());
+        assertEquals(left.getKey(), 
right.getRelationships().get(0).getOtherEndKey());
+
+        AnyObjectUR anyObjectUR = new AnyObjectUR.Builder(left.getKey()).
+                relationship(new RelationshipUR.Builder(new 
RelationshipTO.Builder("neighborhood").
+                        otherEnd(right.getType(), 
right.getKey()).build()).build()).build();
+        left = updateAnyObject(anyObjectUR).getEntity();
+        assertEquals(2, left.getRelationships().size());
+        assertTrue(left.getRelationships().stream().anyMatch(r -> 
right.getKey().equals(r.getOtherEndKey())));
+    }
+
     @Test
     public void issueSYNCOPE756() {
         AnyObjectCR anyObjectCR = getSample("issueSYNCOPE756");
-        anyObjectCR.getRelationships().add(new 
RelationshipTO.Builder().otherEnd(
+        anyObjectCR.getRelationships().add(new 
RelationshipTO.Builder("neighborhood").otherEnd(
                 AnyTypeKind.USER.name(), 
"1417acbe-cbf6-4277-9372-e75e04f97000").build());
 
         try {
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
index a859b95b1b..d2e6760f05 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
@@ -32,6 +32,7 @@ import java.io.IOException;
 import java.security.AccessControlException;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -691,17 +692,12 @@ public class GroupITCase extends AbstractITCase {
         groupCR.setUDynMembershipCond("cool==true");
         GroupTO group = createGroup(groupCR).getEntity();
         assertNotNull(group);
-        final String groupKey = group.getKey();
 
-        List<MembershipTO> memberships = USER_SERVICE.read(
-                "c9b2dec2-00a7-4855-97c0-d854842b4b24").getDynMemberships();
-        assertTrue(memberships.stream().anyMatch(m -> 
m.getGroupKey().equals(groupKey)));
+        List<MembershipTO> memberships = 
USER_SERVICE.read("c9b2dec2-00a7-4855-97c0-d854842b4b24").getDynMemberships();
+        assertTrue(memberships.stream().anyMatch(m -> 
m.getGroupKey().equals(group.getKey())));
         assertEquals(1, 
GROUP_SERVICE.read(group.getKey()).getDynamicUserMembershipCount());
 
-        GroupUR groupUR = new GroupUR();
-        groupUR.setKey(group.getKey());
-        groupUR.setUDynMembershipCond("cool==false");
-        GROUP_SERVICE.update(groupUR);
+        GROUP_SERVICE.update(new 
GroupUR.Builder(group.getKey()).udynMembershipCond("cool==false").build());
 
         
assertTrue(USER_SERVICE.read("c9b2dec2-00a7-4855-97c0-d854842b4b24").getDynMemberships().isEmpty());
         assertEquals(0, 
GROUP_SERVICE.read(group.getKey()).getDynamicUserMembershipCount());
@@ -1000,26 +996,40 @@ public class GroupITCase extends AbstractITCase {
         }
     }
 
+    @Test
+    public void unlimitedMembership() {
+        GroupCR groupCR = new GroupCR();
+        groupCR.setName("unlimited" + getUUIDString());
+        groupCR.setRealm("/even/two");
+        GroupTO groupTO = createGroup(groupCR).getEntity();
+
+        UserCR userCR = 
UserITCase.getUniqueSample("unlimi...@syncope.apache.org");
+        userCR.setRealm(SyncopeConstants.ROOT_REALM);
+        userCR.getMemberships().add(new 
MembershipTO.Builder(groupTO.getKey()).build());
+        UserTO userTO = createUser(userCR).getEntity();
+
+        assertFalse(userTO.getMemberships().isEmpty());
+        assertEquals(groupTO.getKey(), 
userTO.getMemberships().get(0).getGroupKey());
+    }
+
     @Test
     public void issue178() {
         GroupCR groupCR = new GroupCR();
-        String groupName = "torename" + getUUIDString();
-        groupCR.setName(groupName);
-        groupCR.setRealm("/");
+        groupCR.setName("torename" + getUUIDString());
+        groupCR.setRealm(SyncopeConstants.ROOT_REALM);
 
         GroupTO actual = createGroup(groupCR).getEntity();
 
         assertNotNull(actual);
-        assertEquals(groupName, actual.getName());
+        assertEquals(groupCR.getName(), actual.getName());
 
         GroupUR groupUR = new GroupUR();
         groupUR.setKey(actual.getKey());
-        String renamedGroup = "renamed" + getUUIDString();
-        groupUR.setName(new 
StringReplacePatchItem.Builder().value(renamedGroup).build());
+        groupUR.setName(new StringReplacePatchItem.Builder().value("renamed" + 
getUUIDString()).build());
 
         actual = updateGroup(groupUR).getEntity();
         assertNotNull(actual);
-        assertEquals(renamedGroup, actual.getName());
+        assertEquals(groupUR.getName().getValue(), actual.getName());
     }
 
     @Test
@@ -1116,9 +1126,7 @@ public class GroupITCase extends AbstractITCase {
             assertEquals(1, entries);
         } finally {
             SCHEMA_SERVICE.update(SchemaType.DERIVED, orig);
-            if (groupTO != null) {
-                GROUP_SERVICE.delete(groupTO.getKey());
-            }
+            Optional.ofNullable(groupTO).ifPresent(g -> 
GROUP_SERVICE.delete(g.getKey()));
             RESOURCE_SERVICE.delete("new-ldap");
         }
     }
@@ -1214,9 +1222,7 @@ public class GroupITCase extends AbstractITCase {
             assertNotNull(connObjectTO);
             assertEquals("fixedSYNCOPE1467", 
connObjectTO.getAttr("cn").get().getValues().get(0));
         } finally {
-            if (groupTO.getKey() != null) {
-                GROUP_SERVICE.delete(groupTO.getKey());
-            }
+            Optional.ofNullable(groupTO).ifPresent(g -> 
GROUP_SERVICE.delete(g.getKey()));
         }
     }
 
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index 4210840e1d..c6a02e4013 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -897,8 +897,8 @@ public class PropagationTaskITCase extends 
AbstractTaskITCase {
 
             // 1. create user with relationship and the new resource assigned
             UserCR userCR = 
UserITCase.getUniqueSample("syncope1...@syncope.apache.org");
-            userCR.getRelationships().add(new RelationshipTO.Builder().
-                    type("neighborhood").otherEnd(PRINTER, 
"fc6dbc3a-6c07-4965-8781-921e7401a4a5").build());
+            userCR.getRelationships().add(new 
RelationshipTO.Builder("neighborhood").
+                    otherEnd(PRINTER, 
"fc6dbc3a-6c07-4965-8781-921e7401a4a5").build());
             userCR.getResources().clear();
             userCR.getResources().add(ldap.getKey());
 
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 e0a6f31cc8..b894524c61 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
@@ -459,27 +459,6 @@ public class SearchITCase extends AbstractITCase {
         }
     }
 
-    @Test
-    public void assignable() {
-        PagedResult<GroupTO> groups = GROUP_SERVICE.search(new 
AnyQuery.Builder().realm("/even/two").page(1).size(1000).
-                
fiql(SyncopeClient.getGroupSearchConditionBuilder().isAssignable().
-                        and("name").equalTo("*").query()).
-                build());
-        assertNotNull(groups);
-        assertTrue(groups.getResult().stream().
-                anyMatch(group -> 
"034740a9-fa10-453b-af37-dc7897e98fb1".equals(group.getKey())));
-        assertFalse(groups.getResult().stream().
-                anyMatch(group -> 
"e7ff94e8-19c9-4f0a-b8b7-28327edbf6ed".equals(group.getKey())));
-
-        PagedResult<AnyObjectTO> anyObjects = ANY_OBJECT_SERVICE.search(new 
AnyQuery.Builder().realm("/odd").
-                
fiql(SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).isAssignable().
-                        and("name").equalTo("*").query()).
-                build());
-        assertNotNull(anyObjects);
-        assertFalse(anyObjects.getResult().stream().
-                anyMatch(anyObject -> 
"9e1d130c-d6a3-48b1-98b3-182477ed0688".equals(anyObject.getKey())));
-    }
-
     @Test
     public void member() {
         PagedResult<GroupTO> groups = GROUP_SERVICE.search(new 
AnyQuery.Builder().realm("/").
diff --git a/src/main/asciidoc/reference-guide/concepts/realms.adoc 
b/src/main/asciidoc/reference-guide/concepts/realms.adoc
index 3da0cddaae..15f8eb449c 100644
--- a/src/main/asciidoc/reference-guide/concepts/realms.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/realms.adoc
@@ -34,12 +34,7 @@ If Users, Groups and Any Objects are members of a realm then 
they are also membe
 realm contains everything, and other realms can be seen as containers that 
split up the total number of entities into
 smaller pools.
 
-This has consequences on <<memberships-relationships,memberships and 
relationships>>:
-
-* A User or an Any Object can be members of Groups in the same realm or in one 
of the parent realms.
-* A User or an Any object can be in a relation with Any Objects in the same 
realm or in one of parent realms.
-
-Moreover, this partition allows fine-grained control over policy enforcement 
and, alongside with
+This partition allows fine-grained control over policy enforcement and, 
alongside with
 <<entitlements,entitlements>> and <<roles,roles>>, helps to implement
 <<delegated-administration,delegated administration>>.
 
diff --git a/src/main/asciidoc/reference-guide/usage/clientlibrary.adoc 
b/src/main/asciidoc/reference-guide/usage/clientlibrary.adoc
index 9137dfe524..0a8629f5e1 100644
--- a/src/main/asciidoc/reference-guide/usage/clientlibrary.adoc
+++ b/src/main/asciidoc/reference-guide/usage/clientlibrary.adoc
@@ -158,8 +158,8 @@ GroupService groupService = 
client.getService(GroupService.class);
 
 PagedResult<GroupTO> matchingGroups = groupService.search(
     new AnyQuery.Builder().realm("/even/two").page(3).size(150).
-    fiql(SyncopeClient.getGroupSearchConditionBuilder().isAssignable().
-        and("name").equalTo("palo*").query()).
+    fiql(SyncopeClient.getGroupSearchConditionBuilder().
+        is("name").equalTo("palo*").query()).
     build()); // <6>
 ----
 <1> get the total number of users available in the given deployment (and 
<<domains,domain>>)
@@ -168,7 +168,7 @@ PagedResult<GroupTO> matchingGroups = groupService.search(
 given deployment
 <4> get users in the root realm with <<roles,role>> `Other` assigned
 <5> get all any objects in the root realm with <<anytype,type>> `PRINTER`
-<6> get all groups that can be assigned to users or any objects in the 
`/even/two` realm - third page of the result,
+<6> get all groups having name starting with prefix 'palo' - third page of the 
result,
 where each page contains 150 items
 ====
 

Reply via email to