Repository: syncope Updated Branches: refs/heads/master d433501b9 -> e34a8e4f3
[SYNCOPE-119] Adding isAssignable support to dynamic group memberships Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/e34a8e4f Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/e34a8e4f Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/e34a8e4f Branch: refs/heads/master Commit: e34a8e4f3330c1ce4bc9565f894bfe336b28cb7b Parents: d433501 Author: Francesco Chicchiriccò <[email protected]> Authored: Tue Dec 1 12:19:39 2015 +0100 Committer: Francesco Chicchiriccò <[email protected]> Committed: Tue Dec 1 12:19:39 2015 +0100 ---------------------------------------------------------------------- .../api/dao/search/AssignableCond.java | 15 ++++ .../persistence/jpa/dao/JPAAnySearchDAO.java | 73 ++++++++++---------- .../core/persistence/jpa/dao/JPAGroupDAO.java | 37 +++++++--- .../core/persistence/jpa/dao/SearchSupport.java | 4 ++ 4 files changed, 83 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/e34a8e4f/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java ---------------------------------------------------------------------- diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java index 0ece01b..54587f3 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AssignableCond.java @@ -24,6 +24,13 @@ public class AssignableCond extends AbstractSearchCond { private String realmFullPath; + /** + * Whether this condition should be evaluated from the assignable group (default) - or instead the + * assignee - point of view. + * The converter from FIQL will ignore this setting, which is meant for internal usage. + */ + private boolean fromGroup = true; + public String getRealmFullPath() { return realmFullPath; } @@ -32,6 +39,14 @@ public class AssignableCond extends AbstractSearchCond { this.realmFullPath = realmFullPath; } + public boolean isFromGroup() { + return fromGroup; + } + + public void setFromGroup(final boolean fromGroup) { + this.fromGroup = fromGroup; + } + @Override public final boolean isValid() { return realmFullPath != null; http://git-wip-us.apache.org/repos/asf/syncope/blob/e34a8e4f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java ---------------------------------------------------------------------- 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 c0f57b0..942b950 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 @@ -137,7 +137,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea // 1. get the query string from the search condition SearchSupport svs = new SearchSupport(typeKind); - StringBuilder queryString = getQuery(searchCondition, parameters, typeKind, svs); + StringBuilder queryString = getQuery(searchCondition, parameters, svs); // 2. take into account administrative realms queryString.insert(0, "SELECT u.any_id FROM ("); @@ -206,7 +206,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea // 1. get the query string from the search condition SearchSupport svs = new SearchSupport(typeKind); - StringBuilder queryString = getQuery(searchCondition, parameters, typeKind, svs); + StringBuilder queryString = getQuery(searchCondition, parameters, svs); boolean matches; if (queryString.length() == 0) { @@ -365,7 +365,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea // 1. get the query string from the search condition SearchSupport svs = new SearchSupport(typeKind); - StringBuilder queryString = getQuery(nodeCond, parameters, typeKind, svs); + StringBuilder queryString = getQuery(nodeCond, parameters, svs); // 2. take into account administrative groups and ordering OrderBySupport orderBySupport = parseOrderBy(typeKind, svs, orderBy); @@ -417,64 +417,59 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea return result; } - private StringBuilder getQuery(final SearchCond nodeCond, final List<Object> parameters, - final AnyTypeKind anyTypeKind, final SearchSupport svs) { - + private StringBuilder getQuery(final SearchCond nodeCond, final List<Object> parameters, final SearchSupport svs) { StringBuilder query = new StringBuilder(); switch (nodeCond.getType()) { case LEAF: case NOT_LEAF: - if (nodeCond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == anyTypeKind) { + if (nodeCond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind()) { query.append(getQuery(nodeCond.getAnyTypeCond(), nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } else if (nodeCond.getRelationshipTypeCond() != null - && (AnyTypeKind.USER == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) { + && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) { query.append(getQuery(nodeCond.getRelationshipTypeCond(), nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } else if (nodeCond.getRelationshipCond() != null - && (AnyTypeKind.USER == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) { + && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) { query.append(getQuery(nodeCond.getRelationshipCond(), nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } else if (nodeCond.getMembershipCond() != null - && (AnyTypeKind.USER == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) { + && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) { query.append(getQuery(nodeCond.getMembershipCond(), nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); - } else if (nodeCond.getAssignableCond() != null - && (AnyTypeKind.GROUP == anyTypeKind || AnyTypeKind.ANY_OBJECT == anyTypeKind)) { - - query.append(getQuery(nodeCond.getAssignableCond(), parameters, anyTypeKind, svs)); - } else if (nodeCond.getRoleCond() != null && AnyTypeKind.USER == anyTypeKind) { + } else if (nodeCond.getAssignableCond() != null) { + query.append(getQuery(nodeCond.getAssignableCond(), parameters, svs)); + } else if (nodeCond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind()) { query.append(getQuery(nodeCond.getRoleCond(), nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } else if (nodeCond.getResourceCond() != null) { query.append(getQuery(nodeCond.getResourceCond(), - nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, anyTypeKind, svs)); + nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } else if (nodeCond.getAttributeCond() != null) { query.append(getQuery(nodeCond.getAttributeCond(), - nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, anyTypeKind, svs)); + nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } else if (nodeCond.getAnyCond() != null) { query.append(getQuery(nodeCond.getAnyCond(), - nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, anyTypeKind, - svs)); + nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs)); } break; case AND: - query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, anyTypeKind, svs)). + query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, svs)). append(" AND any_id IN ( "). - append(getQuery(nodeCond.getRightNodeCond(), parameters, anyTypeKind, svs)). + append(getQuery(nodeCond.getRightNodeCond(), parameters, svs)). append(")"); break; case OR: - query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, anyTypeKind, svs)). + query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, svs)). append(" OR any_id IN ( "). - append(getQuery(nodeCond.getRightNodeCond(), parameters, anyTypeKind, svs)). + append(getQuery(nodeCond.getRightNodeCond(), parameters, svs)). append(")"); break; @@ -607,7 +602,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea } private String getQuery(final ResourceCond cond, final boolean not, final List<Object> parameters, - final AnyTypeKind typeKind, final SearchSupport svs) { + final SearchSupport svs) { StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM "). append(svs.field().name).append(" WHERE "); @@ -623,7 +618,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea append(" WHERE resource_name=?"). append(setParameter(parameters, cond.getResourceName())); - if (typeKind == AnyTypeKind.USER) { + if (svs.anyTypeKind() == AnyTypeKind.USER) { query.append(" UNION SELECT DISTINCT any_id FROM "). append(svs.groupResource().name). append(" WHERE resource_name=?"). @@ -635,9 +630,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea return query.toString(); } - private String getQuery(final AssignableCond cond, final List<Object> parameters, final AnyTypeKind typeKind, - final SearchSupport svs) { - + private String getQuery(final AssignableCond cond, final List<Object> parameters, final SearchSupport svs) { Realm realm = realmDAO.find(cond.getRealmFullPath()); if (realm == null) { return EMPTY_QUERY; @@ -645,10 +638,18 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM "). append(svs.field().name).append(" WHERE ("); - for (Realm current = realm; current.getParent() != null; current = current.getParent()) { - query.append("realm_id=?").append(setParameter(parameters, current.getKey())).append(" OR "); + if (cond.isFromGroup()) { + 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())); + } else { + for (Realm current : realmDAO.findDescendants(realm)) { + query.append("realm_id=?").append(setParameter(parameters, current.getKey())).append(" OR "); + } + query.setLength(query.length() - 4); } - query.append("realm_id=?").append(setParameter(parameters, realmDAO.getRoot().getKey())).append(')'); + query.append(')'); return query.toString(); } @@ -746,9 +747,9 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea } private String getQuery(final AttributeCond cond, final boolean not, final List<Object> parameters, - final AnyTypeKind typeKind, final SearchSupport svs) { + final SearchSupport svs) { - AnyUtils attrUtils = anyUtilsFactory.getInstance(typeKind); + AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind()); PlainSchema schema = schemaDAO.find(cond.getSchema()); if (schema == null) { @@ -797,9 +798,9 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea @SuppressWarnings("rawtypes") private String getQuery(final AnyCond cond, final boolean not, final List<Object> parameters, - final AnyTypeKind typeKind, final SearchSupport svs) { + final SearchSupport svs) { - AnyUtils attrUtils = anyUtilsFactory.getInstance(typeKind); + AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind()); // Keeps track of difference between entity's getKey() and JPA @Id fields if ("key".equals(cond.getSchema())) { @@ -840,7 +841,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>, Long> implements AnySea if (anyField.getType().getAnnotation(Entity.class) != null) { Method relMethod = null; try { - relMethod = ClassUtils.getPublicMethod(anyField.getType(), "getKey", new Class[0]); + relMethod = ClassUtils.getPublicMethod(anyField.getType(), "getKey", new Class<?>[0]); } catch (Exception e) { LOG.error("Could not find {}#getKey", anyField.getType(), e); } http://git-wip-us.apache.org/repos/asf/syncope/blob/e34a8e4f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java ---------------------------------------------------------------------- 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 d050d4c..671582c 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,9 +42,12 @@ import org.apache.syncope.core.misc.search.SearchCondConverter; import org.apache.syncope.core.misc.security.AuthContextUtils; import org.apache.syncope.core.misc.security.DelegatedAdministrationException; import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO; +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.Any; import org.apache.syncope.core.persistence.api.entity.AnyTypeClass; import org.apache.syncope.core.persistence.api.entity.AnyUtils; +import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership; import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject; import org.apache.syncope.core.persistence.api.entity.group.TypeExtension; @@ -159,12 +162,21 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO { return query.getResultList(); } + private SearchCond buildDynMembershipCond(final String baseCondFIQL, final Realm groupRealm) { + AssignableCond cond = new AssignableCond(); + cond.setRealmFullPath(groupRealm.getFullPath()); + cond.setFromGroup(false); + + return SearchCond.getAndCond(SearchCond.getLeafCond(cond), SearchCondConverter.convert(baseCondFIQL)); + } + @Override public Group save(final Group group) { // refresh dynaminc memberships if (group.getADynMembership() != null) { List<AnyObject> matching = searchDAO.search( - SearchCondConverter.convert(group.getADynMembership().getFIQLCond()), AnyTypeKind.ANY_OBJECT); + buildDynMembershipCond(group.getADynMembership().getFIQLCond(), group.getRealm()), + AnyTypeKind.ANY_OBJECT); group.getADynMembership().getMembers().clear(); for (AnyObject anyObject : matching) { @@ -173,7 +185,8 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO { } if (group.getUDynMembership() != null) { List<User> matching = searchDAO.search( - SearchCondConverter.convert(group.getUDynMembership().getFIQLCond()), AnyTypeKind.USER); + buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()), + AnyTypeKind.USER); group.getUDynMembership().getMembers().clear(); for (User user : matching) { @@ -258,11 +271,13 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO { @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public void refreshDynMemberships(final AnyObject anyObject) { - for (Group role : findAll()) { - if (role.getADynMembership() != null && !searchDAO.matches(anyObject, - SearchCondConverter.convert(role.getADynMembership().getFIQLCond()), AnyTypeKind.ANY_OBJECT)) { + for (Group group : findAll()) { + if (group.getADynMembership() != null && !searchDAO.matches( + anyObject, + buildDynMembershipCond(group.getADynMembership().getFIQLCond(), group.getRealm()), + AnyTypeKind.ANY_OBJECT)) { - role.getADynMembership().remove(anyObject); + group.getADynMembership().remove(anyObject); } } } @@ -270,11 +285,13 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO { @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public void refreshDynMemberships(final User user) { - for (Group role : findAll()) { - if (role.getUDynMembership() != null && !searchDAO.matches(user, - SearchCondConverter.convert(role.getUDynMembership().getFIQLCond()), AnyTypeKind.USER)) { + for (Group group : findAll()) { + if (group.getUDynMembership() != null && !searchDAO.matches( + user, + buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()), + AnyTypeKind.USER)) { - role.getUDynMembership().remove(user); + group.getUDynMembership().remove(user); } } } http://git-wip-us.apache.org/repos/asf/syncope/blob/e34a8e4f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java index 4c8297a..06854df 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java @@ -53,6 +53,10 @@ class SearchSupport { this.anyTypeKind = anyTypeKind; } + public AnyTypeKind anyTypeKind() { + return anyTypeKind; + } + public String fieldName(final AttrSchemaType attrSchemaType) { String result;
