You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2012/07/16 16:09:53 UTC

svn commit: r1362044 - in /incubator/syncope/trunk/core/src: main/java/org/apache/syncope/core/propagation/ main/java/org/apache/syncope/core/rest/data/ test/java/org/apache/syncope/core/persistence/dao/ test/java/org/apache/syncope/core/rest/ test/res...

Author: fmartelli
Date: Mon Jul 16 14:09:52 2012
New Revision: 1362044

URL: http://svn.apache.org/viewvc?rev=1362044&view=rev
Log:
SYNCOPE-111 #comment in case of membership add/remove just resources indirectly linked to it was used to be considered

Modified:
    incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java
    incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
    incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/SchemaTest.java
    incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
    incubator/syncope/trunk/core/src/test/resources/content.xml

Modified: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java?rev=1362044&r1=1362043&r2=1362044&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/PropagationManager.java Mon Jul 16 14:09:52 2012
@@ -358,14 +358,12 @@ public class PropagationManager {
             default:
         }
 
-        final Entry<AbstractSchema, List<AbstractAttrValue>> entry = SchemaMappingUtil.getIntValues(mapping,
-                attributables, password, schemaDAO);
+        final Entry<AbstractSchema, List<AbstractAttrValue>> entry =
+                SchemaMappingUtil.getIntValues(mapping, attributables, password, schemaDAO);
 
         final List<AbstractAttrValue> values = entry.getValue();
         final AbstractSchema schema = entry.getKey();
-        final SchemaType schemaType = schema == null
-                ? SchemaType.String
-                : schema.getType();
+        final SchemaType schemaType = schema == null ? SchemaType.String : schema.getType();
 
         final String extAttrName = SchemaMappingUtil.getExtAttrName(mapping);
 
@@ -725,15 +723,32 @@ public class PropagationManager {
                             final SyncopeUser user = getSyncopeUser(task.getSyncopeUser().getId());
 
                             if (user == null || !user.getResourceNames().contains(task.getResource().getName())) {
+                                // perform de-provisioning
+                                LOG.debug("Perform deprovisioning on {}", task.getResource().getName());
+
                                 connector.delete(
                                         task.getPropagationMode(),
                                         ObjectClass.ACCOUNT,
                                         before.getUid(),
                                         null,
                                         propagationAttempted);
-                            }
+                            } else {
+                                // Update remote profile.
+                                // This is absolutely needed because otherwise the resource won't be updated: 
+                                // resources to be deleted won't be considered by UserDataBinder.update() for the update
+                                // but, often, this have to be done.
+                                LOG.debug("Update remote object on {}", task.getResource().getName());
 
+                                connector.update(
+                                        task.getPropagationMode(),
+                                        ObjectClass.ACCOUNT,
+                                        before.getUid(),
+                                        task.getAttributes(),
+                                        null,
+                                        propagationAttempted);
+                            }
                         }
+
                         break;
 
                     default:

Modified: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java?rev=1362044&r1=1362043&r2=1362044&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java Mon Jul 16 14:09:52 2012
@@ -237,7 +237,7 @@ public class UserDataBinder extends Abst
 
             user.setChangePwdDate(new Date());
 
-            propByRes.addAll(PropagationOperation.UPDATE, user.getResourceNames());
+            propByRes.addAll(PropagationOperation.UPDATE, currentResources);
         }
 
         // username
@@ -246,7 +246,7 @@ public class UserDataBinder extends Abst
             String oldUsername = user.getUsername();
 
             user.setUsername(userMod.getUsername());
-            propByRes.addAll(PropagationOperation.UPDATE, user.getResourceNames());
+            propByRes.addAll(PropagationOperation.UPDATE, currentResources);
 
             for (ExternalResource resource : user.getResources()) {
                 for (SchemaMapping mapping : resource.getMappings()) {
@@ -266,6 +266,9 @@ public class UserDataBinder extends Abst
             membershipToBeAddedRoleIds.add(membToBeAdded.getRole());
         }
 
+        final Set<String> toBeDeprovisioned = new HashSet<String>();
+        final Set<String> toBeProvisioned = new HashSet<String>();
+
         // memberships to be removed
         Membership membership = null;
         for (Long membershipId : userMod.getMembershipsToBeRemoved()) {
@@ -275,12 +278,9 @@ public class UserDataBinder extends Abst
             if (membership == null) {
                 LOG.debug("Invalid membership id specified to be removed: {}", membershipId);
             } else {
-                for (ExternalResource resource : membership.getSyncopeRole().getResources()) {
-
-                    if (!membershipToBeAddedRoleIds.contains(membership.getSyncopeRole().getId())) {
 
-                        propByRes.add(PropagationOperation.DELETE, resource.getName());
-                    }
+                if (!membershipToBeAddedRoleIds.contains(membership.getSyncopeRole().getId())) {
+                    toBeDeprovisioned.addAll(membership.getSyncopeRole().getResourceNames());
                 }
 
                 // In order to make the removeMembership() below to work,
@@ -342,7 +342,7 @@ public class UserDataBinder extends Abst
 
                     user.addMembership(membership);
 
-                    propByRes.addAll(PropagationOperation.UPDATE, role.getResourceNames());
+                    toBeProvisioned.addAll(role.getResourceNames());
                 }
 
                 propByRes.merge(fill(membership, membershipMod,
@@ -350,8 +350,7 @@ public class UserDataBinder extends Abst
             }
         }
 
-        // now, let's see if there are new resource subscriptions without
-        // providing password
+        // now, let's see if there are new resource subscriptions without providing password
         Set<String> updatedResources = user.getResourceNames();
         updatedResources.removeAll(currentResources);
         if (!updatedResources.isEmpty() && StringUtils.isBlank(userMod.getPassword())) {
@@ -363,6 +362,18 @@ public class UserDataBinder extends Abst
             throw scce;
         }
 
+        propByRes.addAll(PropagationOperation.DELETE, toBeDeprovisioned);
+        propByRes.addAll(PropagationOperation.UPDATE, toBeProvisioned);
+
+        /**
+         * In case of new memberships all the current resources have to be updated in order to propagate new role and
+         * membership attribute values.
+         */
+        if (!toBeDeprovisioned.isEmpty() || !toBeProvisioned.isEmpty()) {
+            currentResources.removeAll(toBeDeprovisioned);
+            propByRes.addAll(PropagationOperation.UPDATE, currentResources);
+        }
+
         return propByRes;
     }
 

Modified: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/SchemaTest.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/SchemaTest.java?rev=1362044&r1=1362043&r2=1362044&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/SchemaTest.java (original)
+++ incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/SchemaTest.java Mon Jul 16 14:09:52 2012
@@ -46,7 +46,7 @@ public class SchemaTest extends Abstract
         assertEquals(12, userList.size());
 
         List<RSchema> roleList = schemaDAO.findAll(RSchema.class);
-        assertEquals(4, roleList.size());
+        assertEquals(5, roleList.size());
     }
 
     @Test

Modified: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java?rev=1362044&r1=1362043&r2=1362044&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java (original)
+++ incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java Mon Jul 16 14:09:52 2012
@@ -63,6 +63,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.types.CipherAlgorithm;
 import org.apache.syncope.types.PropagationTaskExecStatus;
 import org.apache.syncope.types.SyncopeClientExceptionType;
+import org.springframework.util.StringUtils;
 
 public class UserTestITCase extends AbstractTest {
 
@@ -1849,4 +1850,91 @@ public class UserTestITCase extends Abst
         assertNotNull(t);
         // -----------------------------------
     }
+
+    @Test
+    public void issueSYNCOPE111() {
+        UserTO userTO = getSampleTO("syncope111@syncope.apache.org");
+        userTO.getResources().clear();
+        userTO.getMemberships().clear();
+        userTO.getDerivedAttributes().clear();
+        userTO.getVirtualAttributes().clear();
+
+        AttributeTO csvuserid = new AttributeTO();
+        csvuserid.setSchema("csvuserid");
+        userTO.addDerivedAttribute(csvuserid);
+
+        MembershipTO memb12 = new MembershipTO();
+        memb12.setRoleId(12L);
+
+        AttributeTO description = new AttributeTO();
+        description.setSchema("description");
+        description.addValue("description");
+
+        memb12.addAttribute(description);
+
+        userTO.addMembership(memb12);
+
+        MembershipTO memb13 = new MembershipTO();
+        memb13.setRoleId(13L);
+
+        userTO.addMembership(memb13);
+
+        userTO.addResource("resource-ldap");
+
+        UserTO actual = restTemplate.postForObject(BASE_URL + "user/create", userTO, UserTO.class);
+
+        assertNotNull(actual);
+        assertEquals(2, actual.getMemberships().size());
+
+        ConnObjectTO connObjectTO = restTemplate.getForObject(
+                BASE_URL + "/resource/{resourceName}/read/{objectId}.json",
+                ConnObjectTO.class,
+                "resource-ldap",
+                userTO.getUsername());
+
+        assertNotNull(connObjectTO);
+
+        description = connObjectTO.getAttributeMap().get("description");
+        assertNotNull(description);
+        assertEquals(1, description.getValues().size());
+        assertEquals("description", description.getValues().get(0));
+
+        AttributeTO title = connObjectTO.getAttributeMap().get("title");
+        assertNotNull(title);
+        assertEquals(2, title.getValues().size());
+        assertTrue(title.getValues().contains("r12") && title.getValues().contains("r13"));
+
+        // -----------------------------------
+        // Remove the first membership and check for membership attr propagation and role attr propagation
+        // -----------------------------------
+        UserMod userMod = new UserMod();
+        userMod.setId(actual.getId());
+
+        MembershipTO membershipTO = actual.getMemberships().get(0).getRoleId() == 12L
+                ? actual.getMemberships().get(0) : actual.getMemberships().get(1);
+
+        userMod.addMembershipToBeRemoved(membershipTO.getId());
+
+        actual = restTemplate.postForObject(BASE_URL + "user/update", userMod, UserTO.class);
+        assertNotNull(actual);
+        assertEquals(1, actual.getMemberships().size());
+
+        connObjectTO = restTemplate.getForObject(
+                BASE_URL + "/resource/{resourceName}/read/{objectId}.json",
+                ConnObjectTO.class,
+                "resource-ldap",
+                userTO.getUsername());
+
+        assertNotNull(connObjectTO);
+
+        description = connObjectTO.getAttributeMap().get("description");
+        assertTrue(description == null
+                || description.getValues().isEmpty() || StringUtils.hasText(description.getValues().get(0)));
+
+        title = connObjectTO.getAttributeMap().get("title");
+        assertNotNull(title);
+        assertEquals(1, title.getValues().size());
+        assertTrue(title.getValues().contains("r13"));
+        // -----------------------------------
+    }
 }

Modified: incubator/syncope/trunk/core/src/test/resources/content.xml
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/resources/content.xml?rev=1362044&r1=1362043&r2=1362044&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/resources/content.xml (original)
+++ incubator/syncope/trunk/core/src/test/resources/content.xml Mon Jul 16 14:09:52 2012
@@ -123,6 +123,9 @@ under the License.
 
   <RSchema name="rderived_dx" type="String"
            mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+           
+  <RSchema name="title" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
 
   <MSchema name="subscriptionDate" type="Date"
            mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
@@ -133,6 +136,9 @@ under the License.
 
   <MSchema name="mderived_dx" type="String"
            mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+           
+  <MSchema name="description" type="String"
+           mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
 
   <UAttr id="100" owner_id="1" schema_name="fullname"/>
   <UAttrUniqueValue id="10" attribute_id="100" schema_name="fullname" stringValue="chicchiricco"/>
@@ -188,6 +194,12 @@ under the License.
     
     <!-- rderiveddata is used to verify der schema deletion -->
   <RDerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx"/>
+  
+  <RAttr id="1004" owner_id="12" schema_name="title"/>
+  <RAttrValue attribute_id="1004" id="94" stringValue="r12"/>
+  
+  <RAttr id="1005" owner_id="13" schema_name="title"/>
+  <RAttrValue attribute_id="1005" id="95" stringValue="r13"/>
 
   <MAttr id="100" owner_id="4" schema_name="subscriptionDate"/>
 
@@ -525,6 +537,12 @@ under the License.
   <SchemaMapping id="315" accountid="0" password="0"
                  extAttrName="mail" intAttrName="email" intMappingType="UserSchema"
                  mandatoryCondition="false" resource_name="resource-ldap"/>
+  <SchemaMapping id="316" accountid="0" password="0"
+                 extAttrName="title" intAttrName="title" intMappingType="RoleSchema"
+                 mandatoryCondition="false" resource_name="resource-ldap"/>
+  <SchemaMapping id="317" accountid="0" password="0"
+                 extAttrName="description" intAttrName="description" intMappingType="MembershipSchema"
+                 mandatoryCondition="false" resource_name="resource-ldap"/>
                    
   <Task DTYPE="PropagationTask" id="1" propagationMode="TWO_PHASES" propagationOperation="UPDATE"
         resource_name="ws-target-resource-2" syncopeUser_id="1" latestExecStatus="SUCCESS"