Author: andreapatricelli Date: Mon May 26 14:07:59 2014 New Revision: 1597590
URL: http://svn.apache.org/r1597590 Log: [SYNCOPE-493] added mapping purpose NONE, changed console layout of mapping purpose Added: syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.java syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.html syncope/trunk/console/src/main/webapp/img/actions/both-icon.png (with props) syncope/trunk/console/src/main/webapp/img/actions/none-icon.png (with props) syncope/trunk/console/src/main/webapp/img/actions/propagation-icon.png (with props) syncope/trunk/console/src/main/webapp/img/actions/synchronization-icon.png (with props) Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/MappingItemTO.java syncope/trunk/common/src/main/java/org/apache/syncope/common/types/MappingPurpose.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourceMappingPanel.java syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/ResourceMappingPanel.html syncope/trunk/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/RoleTestITCase.java syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java syncope/trunk/core/src/test/resources/content.xml Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/MappingItemTO.java URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/MappingItemTO.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/MappingItemTO.java (original) +++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/MappingItemTO.java Mon May 26 14:07:59 2014 @@ -65,7 +65,7 @@ public class MappingItemTO extends Abstr private String mandatoryCondition = "false"; /** - * Mapping purposes: SYNCHRONIZATION, PROPAGATION, BOTH. + * Mapping purposes: SYNCHRONIZATION, PROPAGATION, BOTH, NONE. */ private MappingPurpose purpose; Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/types/MappingPurpose.java URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/types/MappingPurpose.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/common/src/main/java/org/apache/syncope/common/types/MappingPurpose.java (original) +++ syncope/trunk/common/src/main/java/org/apache/syncope/common/types/MappingPurpose.java Mon May 26 14:07:59 2014 @@ -22,6 +22,7 @@ public enum MappingPurpose { BOTH, SYNCHRONIZATION, - PROPAGATION + PROPAGATION, + NONE } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResourceModalPage.java Mon May 26 14:07:59 2014 @@ -81,7 +81,7 @@ public class ResourceModalPage extends B //-------------------------------- //-------------------------------- - // Resource mapping panel + // Resource connector configuration panel //-------------------------------- form.add(new ResourceConnConfPanel("connconf", resourceTO, createFlag)); //-------------------------------- Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourceMappingPanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourceMappingPanel.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourceMappingPanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourceMappingPanel.java Mon May 26 14:07:59 2014 @@ -44,6 +44,7 @@ import org.apache.syncope.console.wicket import org.apache.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.console.wicket.markup.html.form.FieldPanel; +import org.apache.syncope.console.wicket.markup.html.form.MappingPurposePanel; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.attributes.AjaxCallListener; @@ -212,11 +213,18 @@ public class ResourceMappingPanel extend } else if (left.getPurpose() != MappingPurpose.BOTH && right.getPurpose() == MappingPurpose.BOTH) { compared = 1; } else if (left.getPurpose() == MappingPurpose.PROPAGATION - && right.getPurpose() == MappingPurpose.SYNCHRONIZATION) { + && (right.getPurpose() == MappingPurpose.SYNCHRONIZATION || right.getPurpose() + == MappingPurpose.NONE)) { compared = -1; } else if (left.getPurpose() == MappingPurpose.SYNCHRONIZATION && right.getPurpose() == MappingPurpose.PROPAGATION) { compared = 1; + } else if (left.getPurpose() == MappingPurpose.SYNCHRONIZATION + && right.getPurpose() == MappingPurpose.NONE) { + compared = -1; + } else if (left.getPurpose() == MappingPurpose.NONE + && right.getPurpose() != MappingPurpose.NONE) { + compared = 1; } else if (left.isAccountid()) { compared = -1; } else if (right.isAccountid()) { @@ -411,22 +419,13 @@ public class ResourceMappingPanel extend password.setVisible(false); } - final AjaxDropDownChoicePanel<MappingPurpose> purpose = - new AjaxDropDownChoicePanel<MappingPurpose>("purpose", - new ResourceModel("purpose", "purpose").getObject(), - new PropertyModel<MappingPurpose>(mapItem, "purpose"), - false); - purpose.setChoices(Arrays.asList(MappingPurpose.values())); - purpose.setStyleSheet(FIELD_STYLE); - purpose.setRequired(true); - purpose.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + final WebMarkupContainer purpose = new WebMarkupContainer("purpose"); + purpose.setOutputMarkupId(Boolean.TRUE); - private static final long serialVersionUID = -1107858522700306810L; + final MappingPurposePanel panel = new MappingPurposePanel("purposeActions", + new PropertyModel<MappingPurpose>(mapItem, "purpose"), purpose); - @Override - protected void onUpdate(final AjaxRequestTarget target) { - } - }); + purpose.add(panel); item.add(purpose); Added: syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.java?rev=1597590&view=auto ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.java (added) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.java Mon May 26 14:07:59 2014 @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.console.wicket.markup.html.form; + +import org.apache.syncope.common.types.MappingPurpose; +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; + +public class MappingPurposePanel extends Panel { + + private static final long serialVersionUID = 322966537010107771L; + + private final AjaxLink<Void> propagation; + + private final AjaxLink<Void> synchronization; + + private final AjaxLink<Void> both; + + private final AjaxLink<Void> none; + + public MappingPurposePanel(final String componentId, final IModel<MappingPurpose> model, final WebMarkupContainer container) { + super(componentId, model); + + propagation = new AjaxLink<Void>("propagationPurposeLink") { + + private static final long serialVersionUID = -6957616042924610305L; + + @Override + public void onClick(final AjaxRequestTarget target) { + model.setObject(MappingPurpose.PROPAGATION); + setOpacity(MappingPurpose.PROPAGATION); + target.add(container); + } + }; + + synchronization = new AjaxLink<Void>("synchronizationPurposeLink") { + + private static final long serialVersionUID = -6957616042924610305L; + + @Override + public void onClick(final AjaxRequestTarget target) { + model.setObject(MappingPurpose.SYNCHRONIZATION); + setOpacity(MappingPurpose.SYNCHRONIZATION); + target.add(container); + } + }; + + both = new AjaxLink<Void>("bothPurposeLink") { + + private static final long serialVersionUID = -6957616042924610305L; + + @Override + public void onClick(final AjaxRequestTarget target) { + model.setObject(MappingPurpose.BOTH); + setOpacity(MappingPurpose.BOTH); + target.add(container); + } + }; + + none = new AjaxLink<Void>("nonePurposeLink") { + + private static final long serialVersionUID = -6957616042924610305L; + + @Override + public void onClick(final AjaxRequestTarget target) { + model.setObject(MappingPurpose.NONE); + setOpacity(MappingPurpose.NONE); + target.add(container); + } + }; + + add(propagation); + add(synchronization); + add(both); + add(none); + + setOpacity(model.getObject()); + } + + private void setOpacity(final MappingPurpose mappingPurpose) { + switch (mappingPurpose) { + case PROPAGATION: + propagation.add(new AttributeModifier("style", new Model<String>("opacity: 1;"))); + synchronization.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + both.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + none.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + break; + case SYNCHRONIZATION: + synchronization.add(new AttributeModifier("style", new Model<String>("opacity: 1;"))); + propagation.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + both.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + none.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + break; + case BOTH: + both.add(new AttributeModifier("style", new Model<String>("opacity: 1;"))); + propagation.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + synchronization.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + none.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + break; + case NONE: + none.add(new AttributeModifier("style", new Model<String>("opacity: 1;"))); + synchronization.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + propagation.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + both.add(new AttributeModifier("style", new Model<String>("opacity: 0.3;"))); + break; + default: + // do nothing + } + } +} Modified: syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/ResourceMappingPanel.html URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/ResourceMappingPanel.html?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/ResourceMappingPanel.html (original) +++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/ResourceMappingPanel.html Mon May 26 14:07:59 2014 @@ -83,7 +83,9 @@ under the License. <span wicket:id="password">[password]</span> </td> <td align="center" valign="middle"> - <span wicket:id="purpose">[purpose]</span> + <span wicket:id="purpose"> + <span wicket:id="purposeActions">[purpose]</span> + </span> </td> </tr> </tbody> Added: syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.html URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.html?rev=1597590&view=auto ============================================================================== --- syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.html (added) +++ syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/markup/html/form/MappingPurposePanel.html Mon May 26 14:07:59 2014 @@ -0,0 +1,31 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org"> + <wicket:panel> + + <a href="#" wicket:id="propagationPurposeLink"><img id="action" src="img/actions/propagation-icon.png" alt="Propagation icon" title="Propagation"/></a> + + <a href="#" wicket:id="synchronizationPurposeLink"><img id="action" src="img/actions/synchronization-icon.png" alt="Synchronization icon" title="Synchronization"/></a> + + <a href="#" wicket:id="bothPurposeLink"><img id="action" src="img/actions/both-icon.png" alt="Both icon" title="Both"/></a> + + <a href="#" wicket:id="nonePurposeLink"><img id="action" src="img/actions/none-icon.png" alt="None icon" title="None"/></a> + + </wicket:panel> +</html> Added: syncope/trunk/console/src/main/webapp/img/actions/both-icon.png URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/webapp/img/actions/both-icon.png?rev=1597590&view=auto ============================================================================== Binary file - no diff available. Propchange: syncope/trunk/console/src/main/webapp/img/actions/both-icon.png ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: syncope/trunk/console/src/main/webapp/img/actions/none-icon.png URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/webapp/img/actions/none-icon.png?rev=1597590&view=auto ============================================================================== Binary file - no diff available. Propchange: syncope/trunk/console/src/main/webapp/img/actions/none-icon.png ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: syncope/trunk/console/src/main/webapp/img/actions/propagation-icon.png URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/webapp/img/actions/propagation-icon.png?rev=1597590&view=auto ============================================================================== Binary file - no diff available. Propchange: syncope/trunk/console/src/main/webapp/img/actions/propagation-icon.png ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: syncope/trunk/console/src/main/webapp/img/actions/synchronization-icon.png URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/webapp/img/actions/synchronization-icon.png?rev=1597590&view=auto ============================================================================== Binary file - no diff available. Propchange: syncope/trunk/console/src/main/webapp/img/actions/synchronization-icon.png ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java (original) +++ syncope/trunk/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java Mon May 26 14:07:59 2014 @@ -235,7 +235,7 @@ public final class AttributableUtil { switch (purpose) { case SYNCHRONIZATION: for (T item : items) { - if (MappingPurpose.PROPAGATION != item.getPurpose()) { + if (MappingPurpose.PROPAGATION != item.getPurpose() && MappingPurpose.NONE != item.getPurpose()) { result.add(item); } } @@ -243,13 +243,21 @@ public final class AttributableUtil { case PROPAGATION: for (T item : items) { - if (MappingPurpose.SYNCHRONIZATION != item.getPurpose()) { + if (MappingPurpose.SYNCHRONIZATION != item.getPurpose() && MappingPurpose.NONE != item.getPurpose()) { result.add(item); } } break; case BOTH: + for (T item : items) { + if (MappingPurpose.NONE != item.getPurpose()) { + result.add(item); + } + } + break; + + case NONE: default: result.addAll(items); } Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java (original) +++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AbstractTest.java Mon May 26 14:07:59 2014 @@ -133,6 +133,8 @@ public abstract class AbstractTest { protected static final String RESOURCE_NAME_DELETE = "ws-target-resource-delete"; protected static final String RESOURCE_NAME_UPDATE = "ws-target-resource-update"; + + protected static final String RESOURCE_NAME_CREATE_NONE = "ws-target-resource-create-none"; protected static String ANONYMOUS_UNAME; Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java (original) +++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java Mon May 26 14:07:59 2014 @@ -543,4 +543,44 @@ public class ResourceTestITCase extends getService(ResourceService.class); assertFalse(anonymous.list().isEmpty()); } + + @Test + public void issueSYNCOPE493() { + // create resource with attribute mapping set to NONE and check its propagation + String resourceName = RESOURCE_NAME_CREATE_NONE; + ResourceTO resourceTO = new ResourceTO(); + resourceTO.setName(resourceName); + resourceTO.setConnectorId(102L); + + MappingTO umapping = new MappingTO(); + + MappingItemTO item = new MappingItemTO(); + item.setIntMappingType(IntMappingType.UserId); + item.setAccountid(true); + item.setPurpose(MappingPurpose.PROPAGATION); + umapping.setAccountIdItem(item); + + MappingItemTO item2 = new MappingItemTO(); + item2.setIntMappingType(IntMappingType.UserSchema); + item2.setAccountid(false); + item2.setIntAttrName("gender"); + item2.setExtAttrName("gender"); + item2.setPurpose(MappingPurpose.NONE); + umapping.addItem(item2); + + resourceTO.setUmapping(umapping); + + Response response = resourceService.create(resourceTO); + ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class); + + assertNotNull(actual); + assertNotNull(actual.getUmapping()); + assertNotNull(actual.getUmapping().getItems()); + assertEquals(MappingPurpose.PROPAGATION, actual.getUmapping().getAccountIdItem().getPurpose()); + for (MappingItemTO itemTO : actual.getUmapping().getItems()) { + if ("gender".equals(itemTO.getIntAttrName())) { + assertEquals(MappingPurpose.NONE, itemTO.getPurpose()); + } + } + } } 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=1597590&r1=1597589&r2=1597590&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 Mon May 26 14:07:59 2014 @@ -28,6 +28,7 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.io.InputStream; import java.security.AccessControlException; +import java.util.Collection; import java.util.List; import javax.ws.rs.core.Response; import org.apache.commons.io.IOUtils; @@ -48,7 +49,12 @@ import org.apache.syncope.common.types.R import org.apache.syncope.common.types.SchemaType; import org.apache.syncope.common.util.CollectionWrapper; import org.apache.syncope.common.SyncopeClientException; +import org.apache.syncope.common.mod.AttributeMod; import org.apache.syncope.common.reqres.BulkActionResult; +import org.apache.syncope.common.to.MappingItemTO; +import org.apache.syncope.common.to.MappingTO; +import org.apache.syncope.common.to.ResourceTO; +import org.apache.syncope.common.types.MappingPurpose; import org.apache.syncope.common.types.ResourceAssociationActionType; import org.apache.syncope.common.types.ResourceDeassociationActionType; import org.identityconnectors.framework.common.objects.Name; @@ -719,4 +725,83 @@ public class RoleTestITCase extends Abst assertNull(getLdapRemoteObject(parentRemoteObject.getAttrMap().get(Name.NAME).getValues().get(0))); assertNull(getLdapRemoteObject(childRemoteObject.getAttrMap().get(Name.NAME).getValues().get(0))); } + + @Test + public void issueSYNCOPE493() { + // 1. create role and check that title is propagated on resource with mapping for title set to BOTH + RoleTO roleTO = buildBasicRoleTO("issueSYNCOPE493-Role"); + roleTO.getResources().add(RESOURCE_NAME_LDAP); + roleTO.getRAttrTemplates().add("title"); + roleTO.getAttrs().add(attributeTO("title", "TITLE")); + + roleTO = createRole(roleTO); + assertTrue(roleTO.getResources().contains(RESOURCE_NAME_LDAP)); + + ConnObjectTO actual = resourceService.getConnectorObject(RESOURCE_NAME_LDAP, AttributableType.ROLE, + roleTO.getId()); + assertNotNull(actual); + + // check if mapping attribute with purpose BOTH has really been propagated + assertNotNull(actual.getAttrMap().get("description")); + assertEquals("TITLE", actual.getAttrMap().get("description").getValues().get(0)); + + // 2. update resource LDAP + ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP); + assertNotNull(ldap); + + MappingTO ldapNewRMapping = ldap.getRmapping(); + // change purpose from BOTH to NONE + for (MappingItemTO itemTO : ldapNewRMapping.getItems()) { + if ("title".equals(itemTO.getIntAttrName())) { + itemTO.setPurpose(MappingPurpose.NONE); + } + } + + ldap.setRmapping(ldapNewRMapping); + ldap.setUmapping(ldap.getUmapping()); + + resourceService.update(RESOURCE_NAME_LDAP, ldap); + ResourceTO newLdap = resourceService.read(ldap.getName()); + assertNotNull(newLdap); + + // check for existence + Collection<MappingItemTO> mapItems = newLdap.getRmapping().getItems(); + assertNotNull(mapItems); + assertEquals(4, mapItems.size()); + + // 3. update role and check that title han not been propagated, external attribute description must not be present + // in role mapping + RoleMod roleMod = new RoleMod(); + roleMod.setId(roleTO.getId()); + + AttributeMod attr = attributeMod("title", "TITLENEW"); + attr.getValuesToBeRemoved().add("TITLE"); + roleMod.getAttrsToUpdate().add(attr); + roleTO = updateRole(roleMod); + assertNotNull(roleTO); + assertEquals(1, roleTO.getPropagationStatusTOs().size()); + assertTrue(roleTO.getPropagationStatusTOs().get(0).getStatus().isSuccessful()); + // check update on Syncope + assertEquals("TITLENEW", roleTO.getAttrMap().get("title").getValues().get(0)); + + final ConnObjectTO newRole = resourceService.getConnectorObject(RESOURCE_NAME_LDAP, AttributableType.ROLE, + roleTO.getId()); + + // due to NONE mapping for attribute title external attribute description must not be present + assertNull(newRole.getAttrMap().get("description")); + + // 4. restore resource LDAP mapping + ldapNewRMapping = newLdap.getRmapping(); + // restore purpose from NONE to BOTH + for (MappingItemTO itemTO : ldapNewRMapping.getItems()) { + if ("title".equals(itemTO.getIntAttrName())) { + itemTO.setPurpose(MappingPurpose.BOTH); + } + } + + newLdap.setRmapping(ldapNewRMapping); + newLdap.setUmapping(newLdap.getUmapping()); + + resourceService.update(RESOURCE_NAME_LDAP, newLdap); + } } Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java (original) +++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java Mon May 26 14:07:59 2014 @@ -72,6 +72,7 @@ import org.identityconnectors.framework. import java.io.IOException; import java.io.InputStream; +import java.util.Collection; import javax.naming.NamingException; import javax.ws.rs.core.EntityTag; import javax.xml.ws.WebServiceException; @@ -81,6 +82,8 @@ import org.apache.syncope.client.Syncope import org.apache.syncope.common.mod.ResourceAssociationMod; import org.apache.syncope.common.services.UserService; import org.apache.syncope.common.reqres.PagedResult; +import org.apache.syncope.common.to.MappingTO; +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; @@ -1833,7 +1836,7 @@ public class UserTestITCase extends Abst userMod.getResourcesToAdd().add(RESOURCE_NAME_WS1); userMod.getResourcesToAdd().add(RESOURCE_NAME_TESTDB); userTO = updateUser(userMod); - + List<PropagationStatus> propagationStatuses = userTO.getPropagationStatusTOs(); PropagationStatus ws1PropagationStatus = null; if (propagationStatuses != null) { @@ -2216,4 +2219,76 @@ public class UserTestITCase extends Abst "password123", connObject.getAttrMap().get(Name.NAME).getValues().get(0))); } + + @Test + public void issueSYNCOPE493() { + // 1. create user and check that firstname is not propagated on resource with mapping for firstname set to NONE + UserTO userTO = getUniqueSampleTO("[email protected]"); + userTO.getResources().add(RESOURCE_NAME_WS1); + userTO = createUser(userTO); + assertNotNull(userTO); + assertEquals(1, userTO.getPropagationStatusTOs().size()); + assertTrue(userTO.getPropagationStatusTOs().get(0).getStatus().isSuccessful()); + + final ConnObjectTO actual = resourceService.getConnectorObject(RESOURCE_NAME_WS1, AttributableType.USER, userTO. + getId()); + assertNotNull(actual); + // check if mapping attribute with purpose NONE really hasn't been propagated + assertNull(actual.getAttrMap().get("NAME")); + + // 2. update resource ws-target-resource-1 + ResourceTO ws1 = resourceService.read(RESOURCE_NAME_WS1); + assertNotNull(ws1); + + MappingTO ws1NewUMapping = ws1.getUmapping(); + // change purpose from NONE to BOTH + for (MappingItemTO itemTO : ws1NewUMapping.getItems()) { + if ("firstname".equals(itemTO.getIntAttrName())) { + itemTO.setPurpose(MappingPurpose.BOTH); + } + } + + ws1.setUmapping(ws1NewUMapping); + ws1.setRmapping(ws1.getRmapping()); + + resourceService.update(RESOURCE_NAME_WS1, ws1); + ResourceTO newWs1 = resourceService.read(ws1.getName()); + assertNotNull(newWs1); + + // check for existence + Collection<MappingItemTO> mapItems = newWs1.getUmapping().getItems(); + assertNotNull(mapItems); + assertEquals(7, mapItems.size()); + + // 3. update user and check firstname propagation + UserMod userMod = new UserMod(); + userMod.setId(userTO.getId()); + userMod.setPwdPropRequest(new StatusMod()); + userMod.getAttrsToUpdate().add(attributeMod("firstname", "firstnameNew")); + + userTO = updateUser(userMod); + assertNotNull(userTO); + assertEquals(1, userTO.getPropagationStatusTOs().size()); + assertTrue(userTO.getPropagationStatusTOs().get(0).getStatus().isSuccessful()); + + final ConnObjectTO newUser = resourceService.getConnectorObject(RESOURCE_NAME_WS1, AttributableType.USER, + userTO.getId()); + + assertNotNull(newUser.getAttrMap().get("NAME")); + assertEquals("firstnameNew", newUser.getAttrMap().get("NAME").getValues().get(0)); + + // 4. restore resource ws-target-resource-1 mapping + ws1NewUMapping = newWs1.getUmapping(); + // restore purpose from BOTH to NONE + for (MappingItemTO itemTO : ws1NewUMapping.getItems()) { + if ("firstname".equals(itemTO.getIntAttrName())) { + itemTO.setPurpose(MappingPurpose.NONE); + } + } + + newWs1.setUmapping(ws1NewUMapping); + newWs1.setRmapping(newWs1.getRmapping()); + + resourceService.update(RESOURCE_NAME_WS1, newWs1); + } } Modified: syncope/trunk/core/src/test/resources/content.xml URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/resources/content.xml?rev=1597590&r1=1597589&r2=1597590&view=diff ============================================================================== --- syncope/trunk/core/src/test/resources/content.xml (original) +++ syncope/trunk/core/src/test/resources/content.xml Mon May 26 14:07:59 2014 @@ -600,7 +600,10 @@ under the License. <UMappingItem id="336" mapping_id="15" extAttrName="type" intAttrName="type" intMappingType="UserSchema" mandatoryCondition="true" accountid="0" password="0" purpose="PROPAGATION"/> - + <UMappingItem id="337" mapping_id="15" + extAttrName="name" intAttrName="firstname" intMappingType="UserSchema" mandatoryCondition="false" + accountid="0" password="0" purpose="NONE"/> + <UMapping id="12" resource_name="ws-target-resource-list-mappings-1"/> <UMappingItem id="103" mapping_id="12" extAttrName="__NAME__" intAttrName="email" intMappingType="UserSchema" mandatoryCondition="true"
