Author: fmartelli Date: Wed Dec 4 11:46:48 2013 New Revision: 1547772 URL: http://svn.apache.org/r1547772 Log: SYNCOPE-455 merge from 1.1.X
Modified: syncope/trunk/ (props changed) syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java Propchange: syncope/trunk/ ------------------------------------------------------------------------------ Merged /syncope/branches/1_1_X:r1547477-1547766 Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java?rev=1547772&r1=1547771&r2=1547772&view=diff ============================================================================== --- syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java (original) +++ syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/PropagationManager.java Wed Dec 4 11:46:48 2013 @@ -442,7 +442,7 @@ public class PropagationManager { } /** - * Perform delete on each resource associated to the user. It is possible to ask for a mandatory provisioning for + * Perform delete on each resource associated to the role. It is possible to ask for a mandatory provisioning for * some resources specifying a set of resource names. Exceptions won't be ignored and the process will be stopped if * the creation fails onto a mandatory resource. * Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java?rev=1547772&r1=1547771&r2=1547772&view=diff ============================================================================== --- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java (original) +++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/RoleController.java Wed Dec 4 11:46:48 2013 @@ -174,7 +174,7 @@ public class RoleController extends Abst } @PreAuthorize("hasRole('ROLE_READ')") - @Transactional(readOnly = true, rollbackFor = { Throwable.class }) + @Transactional(readOnly = true, rollbackFor = {Throwable.class}) public List<RoleTO> search(final NodeCond searchCondition) throws InvalidSearchConditionException { @@ -182,7 +182,7 @@ public class RoleController extends Abst } @PreAuthorize("hasRole('ROLE_READ')") - @Transactional(readOnly = true, rollbackFor = { Throwable.class }) + @Transactional(readOnly = true, rollbackFor = {Throwable.class}) public List<RoleTO> search(final NodeCond searchCondition, final int page, final int size) throws InvalidSearchConditionException { @@ -204,7 +204,7 @@ public class RoleController extends Abst } @PreAuthorize("hasRole('ROLE_READ')") - @Transactional(readOnly = true, rollbackFor = { Throwable.class }) + @Transactional(readOnly = true, rollbackFor = {Throwable.class}) public int searchCount(final NodeCond searchCondition) throws InvalidSearchConditionException { @@ -307,15 +307,31 @@ public class RoleController extends Abst throw sce; } - // Generate propagation tasks for deleting users from role resources, if they are on those resources only - // because of the reason being deleted (see SYNCOPE-357) - List<PropagationTask> tasks = new ArrayList<PropagationTask>(); - for (WorkflowResult<Long> wfResult : binder.getUsersOnResourcesOnlyBecauseOfRole(roleId)) { - tasks.addAll(propagationManager.getUserDeleteTaskIds(wfResult)); + final List<SyncopeRole> toBeDeprovisioned = new ArrayList<SyncopeRole>(); + + final SyncopeRole syncopeRole = roleDAO.find(roleId); + + if (syncopeRole != null) { + toBeDeprovisioned.add(syncopeRole); + + final List<SyncopeRole> descendants = roleDAO.findDescendants(toBeDeprovisioned.get(0)); + if (descendants != null) { + toBeDeprovisioned.addAll(descendants); + } } - // Generate propagation tasks for deleting this role from resources - tasks.addAll(propagationManager.getRoleDeleteTaskIds(roleId)); + final List<PropagationTask> tasks = new ArrayList<PropagationTask>(); + + for (SyncopeRole role : toBeDeprovisioned) { + // Generate propagation tasks for deleting users from role resources, if they are on those resources only + // because of the reason being deleted (see SYNCOPE-357) + for (WorkflowResult<Long> wfResult : binder.getUsersOnResourcesOnlyBecauseOfRole(role.getId())) { + tasks.addAll(propagationManager.getUserDeleteTaskIds(wfResult)); + } + + // Generate propagation tasks for deleting this role from resources + tasks.addAll(propagationManager.getRoleDeleteTaskIds(role.getId())); + } RoleTO roleTO = new RoleTO(); roleTO.setId(roleId); Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java?rev=1547772&r1=1547771&r2=1547772&view=diff ============================================================================== --- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java (original) +++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java Wed Dec 4 11:46:48 2013 @@ -28,27 +28,33 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.io.InputStream; import java.security.AccessControlException; +import java.util.Hashtable; import java.util.List; +import java.util.Map; +import javax.naming.Context; +import javax.naming.directory.InitialDirContext; import javax.ws.rs.core.Response; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.cxf.helpers.IOUtils; import org.apache.syncope.client.SyncopeClient; - import org.apache.syncope.common.mod.RoleMod; import org.apache.syncope.common.services.RoleService; import org.apache.syncope.common.to.ConnObjectTO; import org.apache.syncope.common.to.ResourceNameTO; +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.SchemaType; import org.apache.syncope.common.types.ClientExceptionType; +import org.apache.syncope.common.types.ConnConfProperty; import org.apache.syncope.common.types.Preference; import org.apache.syncope.common.types.RESTHeaders; import org.apache.syncope.common.types.ResourceAssociationActionType; +import org.apache.syncope.common.types.SchemaType; import org.apache.syncope.common.util.CollectionWrapper; import org.apache.syncope.common.validation.SyncopeClientException; +import org.identityconnectors.framework.common.objects.Name; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; @@ -547,4 +553,77 @@ public class RoleTestITCase extends Abst assertEquals(Preference.RETURN_NO_CONTENT.toString(), response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED)); assertEquals(StringUtils.EMPTY, IOUtils.toString((InputStream) response.getEntity())); } + + @Test + public void issueSYNCOPE455() { + final String parentName = "issueSYNCOPE455-PRole"; + final String childName = "issueSYNCOPE455-CRole"; + + // 1. create parent role + RoleTO parent = buildBasicRoleTO(parentName); + parent.getResources().add(RESOURCE_NAME_LDAP); + + parent = createRole(parent); + assertTrue(parent.getResources().contains(RESOURCE_NAME_LDAP)); + + final ConnObjectTO parentRemoteObject = + resourceService.getConnectorObject(RESOURCE_NAME_LDAP, AttributableType.ROLE, parent.getId()); + assertNotNull(parentRemoteObject); + assertNotNull(getLdapRemoteObject(parentRemoteObject.getAttrMap().get(Name.NAME).getValues().get(0))); + + // 2. create child role + RoleTO child = buildBasicRoleTO(childName); + child.getResources().add(RESOURCE_NAME_LDAP); + child.setParent(parent.getId()); + + child = createRole(child); + assertTrue(child.getResources().contains(RESOURCE_NAME_LDAP)); + + final ConnObjectTO childRemoteObject = + resourceService.getConnectorObject(RESOURCE_NAME_LDAP, AttributableType.ROLE, child.getId()); + assertNotNull(childRemoteObject); + assertNotNull(getLdapRemoteObject(childRemoteObject.getAttrMap().get(Name.NAME).getValues().get(0))); + + // 3. remove parent role + roleService.delete(parent.getId()); + + // 4. asserts for issue 455 + try { + roleService.read(parent.getId()); + fail(); + } catch (SyncopeClientException scce) { + // ignore + } + + try { + roleService.read(child.getId()); + fail(); + } catch (SyncopeClientException scce) { + // ignore + } + + assertNull(getLdapRemoteObject(parentRemoteObject.getAttrMap().get(Name.NAME).getValues().get(0))); + assertNull(getLdapRemoteObject(childRemoteObject.getAttrMap().get(Name.NAME).getValues().get(0))); + } + + private Object getLdapRemoteObject(final String name) { + ResourceTO ldapRes = resourceService.read(RESOURCE_NAME_LDAP); + final Map<String, ConnConfProperty> ldapConnConf = + connectorService.read(ldapRes.getConnectorId()).getConfigurationMap(); + + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, "ldap://" + ldapConnConf.get("host").getValues().get(0) + + ":" + ldapConnConf.get("port").getValues().get(0) + "/"); + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + env.put(Context.SECURITY_PRINCIPAL, ldapConnConf.get("principal").getValues().get(0)); + env.put(Context.SECURITY_CREDENTIALS, ldapConnConf.get("credentials").getValues().get(0)); + + try { + final InitialDirContext ctx = new InitialDirContext(env); + return ctx.lookup(name); + } catch (Exception e) { + return null; + } + } }