[SYNCOPE-1099] Adding checks to ensure that all resources (including the ones 
coming from dynamic groups) are considered for propagation


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/ca0fcf1b
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/ca0fcf1b
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/ca0fcf1b

Branch: refs/heads/master
Commit: ca0fcf1b728c9c6937b55fd0a8bead1d91d3edb4
Parents: 3088b03
Author: Francesco Chicchiriccò <ilgro...@apache.org>
Authored: Fri May 26 14:37:45 2017 +0200
Committer: Francesco Chicchiriccò <ilgro...@apache.org>
Committed: Fri May 26 14:38:15 2017 +0200

----------------------------------------------------------------------
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    |  2 +-
 .../core/persistence/jpa/dao/JPAUserDAO.java    |  2 +-
 .../provisioning/api/PropagationByResource.java |  6 ++++
 .../DefaultAnyObjectProvisioningManager.java    | 17 +++++++--
 .../provisioning/java/VirAttrHandlerImpl.java   |  5 ++-
 .../java/data/AbstractAnyDataBinder.java        | 17 ++++++++-
 .../java/data/AnyObjectDataBinderImpl.java      | 36 ++++++++++++++++----
 .../java/data/UserDataBinderImpl.java           | 35 +++++++++++++++----
 .../activiti/ActivitiUserWorkflowAdapter.java   |  4 +--
 .../java/DefaultAnyObjectWorkflowAdapter.java   |  2 +-
 .../java/DefaultUserWorkflowAdapter.java        |  4 +--
 .../org/apache/syncope/fit/core/UserITCase.java |  5 ++-
 .../syncope/fit/core/UserIssuesITCase.java      | 28 +++++++++++++++
 13 files changed, 131 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index f882ad7..1521749 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -311,7 +311,7 @@ public class JPAAnyObjectDAO extends 
AbstractAnyDAO<AnyObject> implements AnyObj
         return result;
     }
 
-    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
+    @Transactional(readOnly = true)
     @Override
     public Collection<String> findAllResourceKeys(final String key) {
         return CollectionUtils.collect(findAllResources(authFind(key)), 
EntityUtils.<ExternalResource>keyTransformer());

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 28af7e2..47d6f30 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -562,7 +562,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> 
implements UserDAO {
         return result;
     }
 
-    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
+    @Transactional(readOnly = true)
     @Override
     public Collection<String> findAllResourceKeys(final String key) {
         return CollectionUtils.collect(findAllResources(authFind(key)), 
EntityUtils.keyTransformer());

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/PropagationByResource.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/PropagationByResource.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/PropagationByResource.java
index e7b8bfc..b02c34a 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/PropagationByResource.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/PropagationByResource.java
@@ -236,6 +236,12 @@ public class PropagationByResource implements Serializable 
{
         return result;
     }
 
+    public boolean contains(final String resourceKey) {
+        return toBeCreated.contains(resourceKey)
+                || toBeUpdated.contains(resourceKey)
+                || toBeDeleted.contains(resourceKey);
+    }
+
     /**
      * Get resources for a given resource operation type.
      *

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
index ad966de..9b23633 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
@@ -39,6 +39,7 @@ import 
org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import 
org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
 import 
org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
+import 
org.apache.syncope.core.provisioning.api.propagation.PropagationException;
 import org.apache.syncope.core.workflow.api.AnyObjectWorkflowAdapter;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Propagation;
@@ -123,14 +124,26 @@ public class DefaultAnyObjectProvisioningManager 
implements AnyObjectProvisionin
     public List<PropagationStatus> delete(
             final String key, final Set<String> excludedResources, final 
boolean nullPriorityAsync) {
 
+        PropagationByResource propByRes = new PropagationByResource();
+        propByRes.set(ResourceOperation.DELETE, 
anyObjectDAO.findAllResourceKeys(key));
+
+        // Note here that we can only notify about "delete", not any other
+        // task defined in workflow process definition: this because this
+        // information could only be available after awfAdapter.delete(), which
+        // will also effectively remove user from db, thus making virtually
+        // impossible by NotificationManager to fetch required user information
         List<PropagationTask> tasks = propagationManager.getDeleteTasks(
                 AnyTypeKind.ANY_OBJECT,
                 key,
-                null,
+                propByRes,
                 excludedResources);
         PropagationReporter propagationReporter = taskExecutor.execute(tasks, 
nullPriorityAsync);
 
-        awfAdapter.delete(key);
+        try {
+            awfAdapter.delete(key);
+        } catch (PropagationException e) {
+            throw e;
+        }
 
         return propagationReporter.getStatuses();
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
index 85e6522..b4090d8 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.provisioning.java;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -69,7 +68,7 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
     private AnyUtilsFactory anyUtilsFactory;
 
     private Map<VirSchema, List<String>> getValues(final Any<?> any, final 
Set<VirSchema> schemas) {
-        Collection<? extends ExternalResource> ownedResources = 
anyUtilsFactory.getInstance(any).getAllResources(any);
+        Set<ExternalResource> ownedResources = 
anyUtilsFactory.getInstance(any).getAllResources(any);
 
         Map<VirSchema, List<String>> result = new HashMap<>();
 
@@ -179,7 +178,7 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
         return getValues(
                 any,
                 anyUtilsFactory.getInstance(any).getAllowedSchemas(any, 
VirSchema.class).
-                getForMembership(membership.getRightEnd()));
+                        getForMembership(membership.getRightEnd()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
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 160c702..b25712b 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
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -93,6 +94,20 @@ abstract class AbstractAnyDataBinder {
 
     protected static final Logger LOG = 
LoggerFactory.getLogger(AbstractAnyDataBinder.class);
 
+    protected static class PropByResContains implements Predicate<String> {
+
+        private final PropagationByResource propByRes;
+
+        PropByResContains(final PropagationByResource propByRes) {
+            this.propByRes = propByRes;
+        }
+
+        @Override
+        public boolean evaluate(final String resourceKey) {
+            return !propByRes.contains(resourceKey);
+        }
+    }
+
     @Autowired
     protected SchemaDataBinder schemaDataBinder;
 
@@ -287,7 +302,7 @@ abstract class AbstractAnyDataBinder {
             final PlainSchema schema,
             final PlainAttr<?> attr,
             final AnyUtils anyUtils,
-            final Set<ExternalResource> resources,
+            final Collection<ExternalResource> resources,
             final PropagationByResource propByRes,
             final SyncopeClientException invalidValues) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
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 dc944b5..5428f5f 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
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
@@ -231,10 +232,10 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                 } else {
                     LOG.error("{} cannot be assigned to {}", group, anyObject);
 
-                    SyncopeClientException unassignabled =
+                    SyncopeClientException unassignable =
                             
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
-                    unassignabled.getElements().add("Cannot be assigned: " + 
group);
-                    scce.addException(unassignabled);
+                    unassignable.getElements().add("Cannot be assigned: " + 
group);
+                    scce.addException(unassignable);
                 }
             }
         }
@@ -326,10 +327,10 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
                             } else {
                                 LOG.error("{} cannot be assigned to {}", 
otherEnd, anyObject);
 
-                                SyncopeClientException unassignabled =
+                                SyncopeClientException unassignable =
                                         
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
-                                unassignabled.getElements().add("Cannot be 
assigned: " + otherEnd);
-                                scce.addException(unassignabled);
+                                unassignable.getElements().add("Cannot be 
assigned: " + otherEnd);
+                                scce.addException(unassignable);
                             }
                         }
                     }
@@ -337,7 +338,7 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
             }
         }
 
-        Set<ExternalResource> resources = anyUtils.getAllResources(anyObject);
+        Collection<ExternalResource> resources = 
anyObjectDAO.findAllResources(anyObject);
         SyncopeClientException invalidValues = 
SyncopeClientException.build(ClientExceptionType.InvalidValues);
 
         // memberships
@@ -437,6 +438,27 @@ public class AnyObjectDataBinderImpl extends 
AbstractAnyDataBinder implements An
             }
         }
 
+        // finally double-check that there are no resources owned (after all 
changes above) that remain
+        // not considered for provisioning
+        anyObject = anyObjectDAO.save(anyObject);
+        PropByResContains propByResContains = new PropByResContains(propByRes);
+        Collection<String> prospectResources = 
anyObjectDAO.findAllResourceKeys(anyObject.getKey());
+        for (String resourceKey : IterableUtils.filteredIterable(
+                CollectionUtils.intersection(currentResources, 
prospectResources), propByResContains)) {
+
+            propByRes.add(ResourceOperation.DELETE, resourceKey);
+        }
+        for (String resourceKey : IterableUtils.filteredIterable(
+                CollectionUtils.intersection(prospectResources, 
currentResources), propByResContains)) {
+
+            propByRes.add(ResourceOperation.CREATE, resourceKey);
+        }
+        for (String resourceKey : IterableUtils.filteredIterable(
+                CollectionUtils.intersection(prospectResources, 
currentResources), propByResContains)) {
+
+            propByRes.add(ResourceOperation.UPDATE, resourceKey);
+        }
+
         // Throw composite exception if there is at least one element set in 
the composing exceptions
         if (scce.hasExceptions()) {
             throw scce;

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
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 0140de3..3cd52c3 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
@@ -272,10 +272,10 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
                 } else {
                     LOG.error("{} cannot be assigned to {}", group, user);
 
-                    SyncopeClientException unassignabled =
+                    SyncopeClientException unassignable =
                             
SyncopeClientException.build(ClientExceptionType.InvalidMembership);
-                    unassignabled.getElements().add("Cannot be assigned: " + 
group);
-                    scce.addException(unassignabled);
+                    unassignable.getElements().add("Cannot be assigned: " + 
group);
+                    scce.addException(unassignable);
                 }
             }
         }
@@ -432,17 +432,17 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
                         } else {
                             LOG.error("{} cannot be assigned to {}", otherEnd, 
user);
 
-                            SyncopeClientException unassignabled =
+                            SyncopeClientException unassignable =
                                     
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
-                            unassignabled.getElements().add("Cannot be 
assigned: " + otherEnd);
-                            scce.addException(unassignabled);
+                            unassignable.getElements().add("Cannot be 
assigned: " + otherEnd);
+                            scce.addException(unassignable);
                         }
                     }
                 }
             }
         }
 
-        Set<ExternalResource> resources = anyUtils.getAllResources(user);
+        Collection<ExternalResource> resources = 
userDAO.findAllResources(user);
         SyncopeClientException invalidValues = 
SyncopeClientException.build(ClientExceptionType.InvalidValues);
 
         // memberships
@@ -554,6 +554,27 @@ public class UserDataBinderImpl extends 
AbstractAnyDataBinder implements UserDat
             }
         }
 
+        // finally double-check that there are no resources owned (after all 
changes above) that remain
+        // not considered for provisioning
+        user = userDAO.save(user);
+        PropByResContains propByResContains = new PropByResContains(propByRes);
+        Collection<String> prospectResources = 
userDAO.findAllResourceKeys(user.getKey());
+        for (String resourceKey : IterableUtils.filteredIterable(
+                CollectionUtils.intersection(currentResources, 
prospectResources), propByResContains)) {
+
+            propByRes.add(ResourceOperation.DELETE, resourceKey);
+        }
+        for (String resourceKey : IterableUtils.filteredIterable(
+                CollectionUtils.intersection(prospectResources, 
currentResources), propByResContains)) {
+
+            propByRes.add(ResourceOperation.CREATE, resourceKey);
+        }
+        for (String resourceKey : IterableUtils.filteredIterable(
+                CollectionUtils.intersection(prospectResources, 
currentResources), propByResContains)) {
+
+            propByRes.add(ResourceOperation.UPDATE, resourceKey);
+        }
+
         // Throw composite exception if there is at least one element set in 
the composing exceptions
         if (scce.hasExceptions()) {
             throw scce;

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git 
a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
 
b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
index 66dd5e2..21727fd 100644
--- 
a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
+++ 
b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
@@ -258,9 +258,7 @@ public class ActivitiUserWorkflowAdapter extends 
AbstractUserWorkflowAdapter {
         }
 
         PropagationByResource propByRes = new PropagationByResource();
-        propByRes.set(
-                ResourceOperation.CREATE,
-                CollectionUtils.collect(userDAO.findAllResources(user), 
EntityUtils.keyTransformer()));
+        propByRes.set(ResourceOperation.CREATE, 
userDAO.findAllResourceKeys(user.getKey()));
 
         saveForFormSubmit(user, userTO.getPassword(), propByRes);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
----------------------------------------------------------------------
diff --git 
a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
 
b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
index 8852aa0..ada196f 100644
--- 
a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
+++ 
b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
@@ -44,7 +44,7 @@ public class DefaultAnyObjectWorkflowAdapter extends 
AbstractAnyObjectWorkflowAd
         anyObject = anyObjectDAO.save(anyObject);
 
         PropagationByResource propByRes = new PropagationByResource();
-        propByRes.set(ResourceOperation.CREATE, anyObject.getResourceKeys());
+        propByRes.set(ResourceOperation.CREATE, 
anyObjectDAO.findAllResourceKeys(anyObject.getKey()));
 
         return new WorkflowResult<>(anyObject.getKey(), propByRes, "create");
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git 
a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
 
b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
index b94930b..e3b87ba 100644
--- 
a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
+++ 
b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
@@ -79,9 +79,7 @@ public class DefaultUserWorkflowAdapter extends 
AbstractUserWorkflowAdapter {
         user = userDAO.save(user);
 
         PropagationByResource propByRes = new PropagationByResource();
-        propByRes.set(
-                ResourceOperation.CREATE,
-                CollectionUtils.collect(userDAO.findAllResources(user), 
EntityUtils.keyTransformer()));
+        propByRes.set(ResourceOperation.CREATE, 
userDAO.findAllResourceKeys(user.getKey()));
 
         return new WorkflowResult<Pair<String, Boolean>>(
                 new ImmutablePair<>(user.getKey(), propagateEnable), 
propByRes, "create");

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
index 21e9fe6..69dd12e 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
@@ -599,8 +599,7 @@ public class UserITCase extends AbstractITCase {
         assertFalse(beforeTasks <= 0);
 
         UserTO userTO = getUniqueSampleTO("pwdo...@t.com");
-        userTO.getMemberships().add(new MembershipTO.Builder().
-                group("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
+        userTO.getMemberships().add(new 
MembershipTO.Builder().group("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
 
         userTO = createUser(userTO).getEntity();
 
@@ -615,7 +614,7 @@ public class UserITCase extends AbstractITCase {
 
         int afterTasks = taskService.list(
                 new 
TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1).build()).getTotalCount();
-        assertFalse(beforeTasks <= 0);
+        assertFalse(afterTasks <= 0);
 
         assertTrue(beforeTasks < afterTasks);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ca0fcf1b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
index a831dd0..df32cad 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
@@ -1344,4 +1344,32 @@ public class UserIssuesITCase extends AbstractITCase {
         // 5. verify that user is not in LDAP anynmore
         assertNull(getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, 
RESOURCE_LDAP_ADMIN_PWD, userDn.getValues().get(0)));
     }
+
+    @Test
+    public void issueSYNCOPE1099() {
+        // 1. create group with dynamic condition and resource
+        GroupTO group = GroupITCase.getSampleTO("syncope1099G");
+        group.getResources().clear();
+        group.getResources().add(RESOURCE_NAME_TESTDB);
+        group.setUDynMembershipCond("firstname==issueSYNCOPE1099");
+
+        group = createGroup(group).getEntity();
+        assertNotNull(group);
+
+        // 2. create user matching the condition above
+        UserTO user = UserITCase.getUniqueSampleTO("syncope10...@apache.org");
+        user.getPlainAttrMap().get("firstname").getValues().set(0, 
"issueSYNCOPE1099");
+
+        ProvisioningResult<UserTO> created = createUser(user);
+        assertNotNull(created);
+
+        // 3. verify that dynamic membership is set and that resource is 
consequently assigned
+        user = created.getEntity();
+        assertTrue(user.getDynGroups().contains(group.getKey()));
+        assertTrue(user.getResources().contains(RESOURCE_NAME_TESTDB));
+
+        // 4. verify that propagation happened towards the resource of the 
dynamic group
+        assertFalse(created.getPropagationStatuses().isEmpty());
+        assertEquals(RESOURCE_NAME_TESTDB, 
created.getPropagationStatuses().get(0).getResource());
+    }
 }

Reply via email to