You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/01/29 17:17:26 UTC

[3/7] syncope git commit: [SYNCOPE-632] Reworking provided patch

[SYNCOPE-632] Reworking provided patch


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

Branch: refs/heads/1_2_X
Commit: 3237d26dfcba2b8d00d6b7d71b47853207ed5270
Parents: 60a6243
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jan 29 17:15:41 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jan 29 17:15:41 2015 +0100

----------------------------------------------------------------------
 .../org/apache/syncope/common/to/MappingTO.java | 17 ++--
 .../rest/controller/ResourceController.java     |  4 +-
 .../data/AbstractAttributableDataBinder.java    | 25 ++++++
 .../syncope/core/rest/data/RoleDataBinder.java  | 26 ++++--
 .../syncope/core/rest/data/UserDataBinder.java  | 38 ++++----
 .../apache/syncope/core/rest/AbstractTest.java  | 28 ++++--
 .../syncope/core/rest/ConnectorTestITCase.java  | 13 ++-
 .../syncope/core/rest/RoleTestITCase.java       | 92 ++++++++++++++++++++
 .../syncope/core/rest/UserSelfTestITCase.java   |  2 +-
 pom.xml                                         |  4 +-
 10 files changed, 195 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/common/src/main/java/org/apache/syncope/common/to/MappingTO.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/syncope/common/to/MappingTO.java b/common/src/main/java/org/apache/syncope/common/to/MappingTO.java
index 3e702a9..3acd063 100644
--- a/common/src/main/java/org/apache/syncope/common/to/MappingTO.java
+++ b/common/src/main/java/org/apache/syncope/common/to/MappingTO.java
@@ -48,18 +48,17 @@ public class MappingTO extends AbstractBaseBean {
         this.accountLink = accountLink;
     }
 
-    @SuppressWarnings("unchecked")
-    public <T extends MappingItemTO> T getAccountIdItem() {
-        T accountIdItem = null;
+    public MappingItemTO getAccountIdItem() {
+        MappingItemTO accountIdItem = null;
         for (MappingItemTO item : getItems()) {
             if (item.isAccountid()) {
-                accountIdItem = (T) item;
+                accountIdItem = item;
             }
         }
         return accountIdItem;
     }
 
-    protected <T extends MappingItemTO> boolean addAccountIdItem(final T accountIdItem) {
+    protected boolean addAccountIdItem(final MappingItemTO accountIdItem) {
         if (IntMappingType.UserVirtualSchema == accountIdItem.getIntMappingType()
                 || IntMappingType.RoleVirtualSchema == accountIdItem.getIntMappingType()
                 || IntMappingType.MembershipVirtualSchema == accountIdItem.getIntMappingType()
@@ -78,11 +77,9 @@ public class MappingTO extends AbstractBaseBean {
     }
 
     public boolean setAccountIdItem(final MappingItemTO accountIdItem) {
-        if (accountIdItem == null) {
-            return this.removeItem(getAccountIdItem());
-        } else {
-            return addAccountIdItem(accountIdItem);
-        }
+        return accountIdItem == null
+                ? this.removeItem(getAccountIdItem())
+                : addAccountIdItem(accountIdItem);
     }
 
     public MappingItemTO getPasswordItem() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java b/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java
index d3dc9d7..a3307d7 100644
--- a/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java
+++ b/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java
@@ -190,8 +190,8 @@ public class ResourceController extends AbstractTransactionalController<Resource
 
         AbstractMappingItem accountIdItem = attrUtil.getAccountIdItem(resource);
         if (accountIdItem == null) {
-            throw new NotFoundException("AccountId mapping for " + type + " " + id + " on resource '" + resourceName
-                    + "'");
+            throw new NotFoundException(
+                    "AccountId mapping for " + type + " " + id + " on resource '" + resourceName + "'");
         }
         final String accountIdValue = MappingUtil.getAccountIdValue(
                 subject, resource, attrUtil.getAccountIdItem(resource));

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java b/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
index 399b118..e6fcb48 100644
--- a/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
+++ b/core/src/main/java/org/apache/syncope/core/rest/data/AbstractAttributableDataBinder.java
@@ -21,9 +21,11 @@ package org.apache.syncope.core.rest.data;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.SyncopeClientCompositeException;
@@ -76,6 +78,7 @@ import org.apache.syncope.core.persistence.dao.AttrValueDAO;
 import org.apache.syncope.core.persistence.dao.DerAttrDAO;
 import org.apache.syncope.core.persistence.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.dao.MembershipDAO;
+import org.apache.syncope.core.persistence.dao.NotFoundException;
 import org.apache.syncope.core.persistence.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.dao.ResourceDAO;
 import org.apache.syncope.core.persistence.dao.RoleDAO;
@@ -916,4 +919,26 @@ public abstract class AbstractAttributableDataBinder {
             }
         }
     }
+
+    protected Map<String, String> getAccountIds(final AbstractSubject subject, final AttributableType type) {
+        Map<String, String> accountIds = new HashMap<String, String>();
+
+        for (ExternalResource resource : subject.getResources()) {
+            if ((type == AttributableType.USER && resource.getUmapping() != null)
+                    || (type == AttributableType.ROLE && resource.getRmapping() != null)) {
+
+                AbstractMappingItem accountIdItem =
+                        AttributableUtil.getInstance(type).getAccountIdItem(resource);
+                if (accountIdItem == null) {
+                    throw new NotFoundException(
+                            "AccountId mapping for " + type + " " + subject.getId()
+                            + " on resource '" + resource.getName() + "'");
+                }
+
+                accountIds.put(resource.getName(), MappingUtil.getAccountIdValue(subject, resource, accountIdItem));
+            }
+        }
+
+        return accountIds;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java b/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java
index e3fe433..58029aa 100644
--- a/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java
+++ b/core/src/main/java/org/apache/syncope/core/rest/data/RoleDataBinder.java
@@ -21,14 +21,15 @@ package org.apache.syncope.core.rest.data;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import org.apache.syncope.common.SyncopeClientCompositeException;
+import org.apache.syncope.common.SyncopeClientException;
 import org.apache.syncope.common.mod.RoleMod;
 import org.apache.syncope.common.to.RoleTO;
 import org.apache.syncope.common.types.AttributableType;
-import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.common.types.ClientExceptionType;
-import org.apache.syncope.common.SyncopeClientCompositeException;
-import org.apache.syncope.common.SyncopeClientException;
+import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.core.connid.ConnObjectUtil;
 import org.apache.syncope.core.persistence.beans.AbstractAttrTemplate;
 import org.apache.syncope.core.persistence.beans.AbstractSchema;
@@ -245,7 +246,8 @@ public class RoleDataBinder extends AbstractAttributableDataBinder {
 
         SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
 
-        Set<String> currentResources = role.getResourceNames();
+        // fetch account ids before update
+        Map<String, String> oldAccountIds = getAccountIds(role, AttributableType.ROLE);
 
         // name
         SyncopeClientException invalidRoles = SyncopeClientException.build(ClientExceptionType.InvalidRoles);
@@ -254,10 +256,7 @@ public class RoleDataBinder extends AbstractAttributableDataBinder {
                     role.getParent() == null ? null : role.getParent().getId());
             if (otherRole == null || role.equals(otherRole)) {
                 if (!roleMod.getName().equals(role.getName())) {
-                    propByRes.addAll(ResourceOperation.UPDATE, currentResources);
-                    for (String resource : currentResources) {
-                        propByRes.addOldAccountId(resource, role.getName());
-                    }
+                    propByRes.addAll(ResourceOperation.UPDATE, role.getResourceNames());
 
                     role.setName(roleMod.getName());
                 }
@@ -354,6 +353,17 @@ public class RoleDataBinder extends AbstractAttributableDataBinder {
         // attributes, derived attributes, virtual attributes and resources
         propByRes.merge(fill(role, roleMod, AttributableUtil.getInstance(AttributableType.ROLE), scce));
 
+        // check if some account id was changed by the update above
+        Map<String, String> newAccountIds = getAccountIds(role, AttributableType.ROLE);
+        for (Map.Entry<String, String> entry : oldAccountIds.entrySet()) {
+            if (newAccountIds.containsKey(entry.getKey())
+                    && !entry.getValue().equals(newAccountIds.get(entry.getKey()))) {
+
+                propByRes.addOldAccountId(entry.getKey(), entry.getValue());
+                propByRes.add(ResourceOperation.UPDATE, entry.getKey());
+            }
+        }
+
         return propByRes;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java b/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
index a37aacb..a904611 100644
--- a/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
+++ b/core/src/main/java/org/apache/syncope/core/rest/data/UserDataBinder.java
@@ -22,25 +22,24 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.Resource;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.SyncopeClientCompositeException;
+import org.apache.syncope.common.SyncopeClientException;
+import org.apache.syncope.common.mod.AttributeMod;
 import org.apache.syncope.common.mod.MembershipMod;
 import org.apache.syncope.common.mod.UserMod;
 import org.apache.syncope.common.to.MembershipTO;
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.common.types.AttributableType;
-import org.apache.syncope.common.types.IntMappingType;
-import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.common.types.ClientExceptionType;
+import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.common.util.BeanUtils;
-import org.apache.syncope.common.SyncopeClientCompositeException;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.common.mod.AttributeMod;
 import org.apache.syncope.core.connid.ConnObjectUtil;
 import org.apache.syncope.core.persistence.beans.AbstractAttr;
 import org.apache.syncope.core.persistence.beans.AbstractDerAttr;
-import org.apache.syncope.core.persistence.beans.AbstractMappingItem;
 import org.apache.syncope.core.persistence.beans.AbstractVirAttr;
 import org.apache.syncope.core.persistence.beans.ExternalResource;
 import org.apache.syncope.core.persistence.beans.SecurityQuestion;
@@ -55,8 +54,8 @@ import org.apache.syncope.core.persistence.dao.SecurityQuestionDAO;
 import org.apache.syncope.core.propagation.PropagationByResource;
 import org.apache.syncope.core.rest.controller.UnauthorizedRoleException;
 import org.apache.syncope.core.util.AttributableUtil;
-import org.apache.syncope.core.util.EntitlementUtil;
 import org.apache.syncope.core.util.Encryptor;
+import org.apache.syncope.core.util.EntitlementUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
@@ -267,6 +266,9 @@ public class UserDataBinder extends AbstractAttributableDataBinder {
 
         Set<String> currentResources = user.getResourceNames();
 
+        // fetch account ids before update
+        Map<String, String> oldAccountIds = getAccountIds(user, AttributableType.USER);
+
         // password
         if (StringUtils.isNotBlank(userMod.getPassword())) {
             setPassword(user, userMod.getPassword(), scce);
@@ -276,18 +278,9 @@ public class UserDataBinder extends AbstractAttributableDataBinder {
 
         // username
         if (userMod.getUsername() != null && !userMod.getUsername().equals(user.getUsername())) {
-            String oldUsername = user.getUsername();
-
-            user.setUsername(userMod.getUsername());
             propByRes.addAll(ResourceOperation.UPDATE, currentResources);
 
-            for (ExternalResource resource : user.getResources()) {
-                for (AbstractMappingItem mapItem : resource.getUmapping().getItems()) {
-                    if (mapItem.isAccountid() && mapItem.getIntMappingType() == IntMappingType.Username) {
-                        propByRes.addOldAccountId(resource.getName(), oldUsername);
-                    }
-                }
-            }
+            user.setUsername(userMod.getUsername());
         }
 
         // security question / answer:
@@ -405,6 +398,17 @@ public class UserDataBinder extends AbstractAttributableDataBinder {
             propByRes.addAll(ResourceOperation.UPDATE, currentResources);
         }
 
+        // check if some account id was changed by the update above
+        Map<String, String> newAccountIds = getAccountIds(user, AttributableType.USER);
+        for (Map.Entry<String, String> entry : oldAccountIds.entrySet()) {
+            if (newAccountIds.containsKey(entry.getKey())
+                    && !entry.getValue().equals(newAccountIds.get(entry.getKey()))) {
+
+                propByRes.addOldAccountId(entry.getKey(), entry.getValue());
+                propByRes.add(ResourceOperation.UPDATE, entry.getKey());
+            }
+        }
+
         return propByRes;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java b/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java
index 785734d..767ca6f 100644
--- a/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java
+++ b/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.UUID;
 import javax.naming.Context;
+import javax.naming.NamingException;
 import javax.naming.directory.InitialDirContext;
 import javax.sql.DataSource;
 import javax.ws.rs.core.Response;
@@ -335,12 +336,9 @@ public abstract class AbstractTest {
         return getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
     }
 
-    protected Object getLdapRemoteObject(final String objectDn) {
-        return getLdapRemoteObject(null, null, objectDn);
-    }
-
     @SuppressWarnings({ "unchecked", "rawtypes", "UseOfObsoleteCollectionType" })
-    protected Object getLdapRemoteObject(final String bindDn, final String bindPwd, final String objectDn) {
+    protected InitialDirContext getLdapResourceDirContext(final String bindDn, final String bindPwd)
+            throws NamingException {
         ResourceTO ldapRes = resourceService.read(RESOURCE_NAME_LDAP);
         final Map<String, ConnConfProperty> ldapConnConf =
                 connectorService.read(ldapRes.getConnectorId()).getConfigurationMap();
@@ -355,11 +353,29 @@ public abstract class AbstractTest {
         env.put(Context.SECURITY_CREDENTIALS,
                 bindPwd == null ? ldapConnConf.get("credentials").getValues().get(0) : bindPwd);
 
+        return new InitialDirContext(env);
+    }
+
+    protected Object getLdapRemoteObject(final String bindDn, final String bindPwd, final String objectDn) {
+        InitialDirContext ctx = null;
         try {
-            final InitialDirContext ctx = new InitialDirContext(env);
+            ctx = getLdapResourceDirContext(bindDn, bindPwd);
             return ctx.lookup(objectDn);
         } catch (Exception e) {
             return null;
+        } finally {
+            if (ctx != null) {
+                try {
+                    ctx.close();
+                } catch (NamingException e) {
+                    // ignore
+                }
+            }
         }
     }
+
+    protected Object getLdapRemoteObject(final String objectDn) {
+        return getLdapRemoteObject(null, null, objectDn);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/test/java/org/apache/syncope/core/rest/ConnectorTestITCase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/syncope/core/rest/ConnectorTestITCase.java b/core/src/test/java/org/apache/syncope/core/rest/ConnectorTestITCase.java
index fc4e830..393a104 100644
--- a/core/src/test/java/org/apache/syncope/core/rest/ConnectorTestITCase.java
+++ b/core/src/test/java/org/apache/syncope/core/rest/ConnectorTestITCase.java
@@ -313,7 +313,7 @@ public class ConnectorTestITCase extends AbstractTest {
 
         connInstanceTO = getObject(response.getLocation(), ConnectorService.class, ConnInstanceTO.class);
         assertNotNull(connInstanceTO);
-        assertTrue(connInstanceTO.getCapabilities().isEmpty());
+        assertFalse(connInstanceTO.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
 
         long connId = connInstanceTO.getId();
 
@@ -337,26 +337,23 @@ public class ConnectorTestITCase extends AbstractTest {
         // Check for spring bean.
         // ----------------------------------
         ConnInstanceTO connInstanceBean = connectorService.readByResource(resourceTO.getName());
-
         assertNotNull(connInstanceBean);
-        assertTrue(connInstanceBean.getCapabilities().isEmpty());
+        assertFalse(connInstanceBean.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
         // ----------------------------------
 
         // ----------------------------------
         // Check for spring bean update after connector instance update.
         // ----------------------------------
-        connInstanceTO.getCapabilities().add(ConnectorCapability.SEARCH);
+        connInstanceTO.getCapabilities().add(ConnectorCapability.AUTHENTICATE);
 
         connectorService.update(connInstanceTO.getId(), connInstanceTO);
         ConnInstanceTO actual = connectorService.read(connInstanceTO.getId());
-
         assertNotNull(actual);
-        assertFalse(connInstanceTO.getCapabilities().isEmpty());
+        assertTrue(connInstanceTO.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
 
         // check for spring bean update
         connInstanceBean = connectorService.readByResource(resourceTO.getName());
-
-        assertFalse(connInstanceBean.getCapabilities().isEmpty());
+        assertTrue(connInstanceBean.getCapabilities().contains(ConnectorCapability.AUTHENTICATE));
         // ----------------------------------
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java b/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java
index a6a6009..6e384d4 100644
--- a/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java
+++ b/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java
@@ -29,6 +29,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.security.AccessControlException;
 import java.util.List;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
 import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -40,11 +45,15 @@ import org.apache.syncope.common.reqres.BulkActionResult;
 import org.apache.syncope.common.reqres.PagedResult;
 import org.apache.syncope.common.services.RoleService;
 import org.apache.syncope.common.to.ConnObjectTO;
+import org.apache.syncope.common.to.MappingItemTO;
+import org.apache.syncope.common.to.ResourceTO;
 import org.apache.syncope.common.to.RoleTO;
 import org.apache.syncope.common.to.SchemaTO;
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.common.types.AttributableType;
 import org.apache.syncope.common.types.ClientExceptionType;
+import org.apache.syncope.common.types.IntMappingType;
+import org.apache.syncope.common.types.MappingPurpose;
 import org.apache.syncope.common.types.Preference;
 import org.apache.syncope.common.types.RESTHeaders;
 import org.apache.syncope.common.types.ResourceAssociationActionType;
@@ -794,4 +803,87 @@ public class RoleTestITCase extends AbstractTest {
         assertNotNull(child.getAttrMap().get("icon").getValues());
         assertEquals("parentIcon", child.getAttrMap().get("icon").getValues().get(0));
     }
+
+    @Test
+    public void issueSYNCOPE632() {
+        RoleTO roleTO = null;
+        try {
+            // 1. create new LDAP resource having account id mapped to a derived attribute
+            ResourceTO newLDAP = resourceService.read(RESOURCE_NAME_LDAP);
+            newLDAP.setName("new-ldap");
+            newLDAP.setPropagationPrimary(true);
+            MappingItemTO accountId = newLDAP.getRmapping().getAccountIdItem();
+            accountId.setIntMappingType(IntMappingType.RoleDerivedSchema);
+            accountId.setIntAttrName("displayProperty");
+            newLDAP.getRmapping().setAccountIdItem(accountId);
+            newLDAP.getRmapping().setAccountLink("'cn=' + displayProperty + ',ou=groups,o=isp'");
+
+            MappingItemTO description = new MappingItemTO();
+            description.setIntMappingType(IntMappingType.RoleId);
+            description.setExtAttrName("description");
+            description.setPurpose(MappingPurpose.BOTH);
+            newLDAP.getRmapping().addItem(description);
+
+            newLDAP = createResource(newLDAP);
+            assertNotNull(newLDAP);
+
+            // 2. create a role and give the resource created above
+            roleTO = buildRoleTO("lastRole");
+            roleTO.getRAttrTemplates().add("icon");
+            roleTO.getAttrs().add(attributeTO("icon", "anIcon"));
+            roleTO.getRAttrTemplates().add("show");
+            roleTO.getAttrs().add(attributeTO("show", "true"));
+            roleTO.getRDerAttrTemplates().add("displayProperty");
+            roleTO.getDerAttrs().add(attributeTO("displayProperty", null));
+            roleTO.getResources().clear();
+            roleTO.getResources().add("new-ldap");
+
+            roleTO = createRole(roleTO);
+            assertNotNull(roleTO);
+
+            // 3. update the role
+            RoleMod roleMod = new RoleMod();
+            roleMod.setId(roleTO.getId());
+            roleMod.getAttrsToRemove().add("icon");
+            roleMod.getAttrsToUpdate().add(attributeMod("icon", "anotherIcon"));
+
+            roleTO = updateRole(roleMod);
+            assertNotNull(roleTO);
+
+            // 4. check that a single group exists in LDAP for the role created and updated above
+            int entries = 0;
+            DirContext ctx = null;
+            try {
+                ctx = getLdapResourceDirContext(null, null);
+
+                SearchControls ctls = new SearchControls();
+                ctls.setReturningAttributes(new String[] { "*", "+" });
+                ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+
+                NamingEnumeration<SearchResult> result =
+                        ctx.search("ou=groups,o=isp", "(description=" + roleTO.getId() + ")", ctls);
+                while (result.hasMore()) {
+                    SearchResult entry = result.next();
+                    entries++;
+                }
+            } catch (Exception e) {
+                // ignore
+            } finally {
+                if (ctx != null) {
+                    try {
+                        ctx.close();
+                    } catch (NamingException e) {
+                        // ignore
+                    }
+                }
+            }
+
+            assertEquals(1, entries);
+        } finally {
+            if (roleTO != null) {
+                roleService.delete(roleTO.getId());
+            }
+            resourceService.delete("new-ldap");
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java b/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
index 595341f..3fa50e2 100644
--- a/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
+++ b/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
@@ -158,7 +158,7 @@ public class UserSelfTestITCase extends AbstractTest {
     }
 
     @Test
-    public void updateWitApproval() {
+    public void updateWithApproval() {
         Assume.assumeTrue(ActivitiDetector.isActivitiEnabledForUsers());
 
         // 1. create user as admin

http://git-wip-us.apache.org/repos/asf/syncope/blob/3237d26d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ba16c75..a40e6c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -335,7 +335,7 @@ under the License.
 
     <activiti.version>5.16.4</activiti.version>
 
-    <aspectj.version>1.8.4</aspectj.version>
+    <aspectj.version>1.8.5</aspectj.version>
 
     <cxf.version>3.0.3</cxf.version>	
     <spring.version>4.0.9.RELEASE</spring.version>
@@ -1128,7 +1128,7 @@ under the License.
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-dependency-plugin</artifactId>
-          <version>2.9</version>
+          <version>2.10</version>
           <configuration>
             <outputDirectory>${bundles.directory}</outputDirectory>
             <artifactItems>