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 2013/12/04 16:34:14 UTC

svn commit: r1547823 - in /syncope/trunk: ./ console/ console/src/main/java/org/apache/syncope/console/pages/ console/src/main/java/org/apache/syncope/console/pages/panels/ core/src/main/java/org/apache/syncope/core/propagation/impl/ core/src/main/java...

Author: ilgrosso
Date: Wed Dec  4 15:34:14 2013
New Revision: 1547823

URL: http://svn.apache.org/r1547823
Log:
[SYNCOPE-454] Merge from 1_1_X

Modified:
    syncope/trunk/   (props changed)
    syncope/trunk/console/pom.xml
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java
    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/main/java/org/apache/syncope/core/sync/impl/LDAPMembershipSyncActions.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/SyncopeSyncResultHandler.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.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/RoleTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirAttrTestITCase.java

Propchange: syncope/trunk/
------------------------------------------------------------------------------
  Merged /syncope/branches/1_1_X:r1547767-1547809

Modified: syncope/trunk/console/pom.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/console/pom.xml?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/console/pom.xml (original)
+++ syncope/trunk/console/pom.xml Wed Dec  4 15:34:14 2013
@@ -261,6 +261,7 @@ under the License.
                   <fileset dir="${project.build.directory}/test-classes">
                     <exclude name="**/*.class"/>
                     <exclude name="restClientContext.xml"/>
+                    <exclude name="rest.properties"/>
                   </fileset>
                 </copy>
               </target>

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java Wed Dec  4 15:34:14 2013
@@ -74,6 +74,7 @@ public class EditUserModalPage extends U
         }
     }
 
+    @SuppressWarnings("rawtypes")
     @Override
     protected void submitAction(final AjaxRequestTarget target, final Form form) {
         final UserTO updatedUserTO = (UserTO) form.getModelObject();
@@ -94,6 +95,7 @@ public class EditUserModalPage extends U
         }
     }
 
+    @SuppressWarnings("rawtypes")
     @Override
     protected void closeAction(final AjaxRequestTarget target, final Form form) {
         setResponsePage(new ResultStatusModalPage.Builder(window, userTO).mode(mode).build());

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java Wed Dec  4 15:34:14 2013
@@ -105,7 +105,7 @@ public class Reports extends BasePage {
         setupAudit();
     }
 
-    @SuppressWarnings({"rawtypes", "unchecked"})
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     private void setupReport() {
         reportContainer = new WebMarkupContainer("reportContainer");
         setWindowClosedCallback(window, reportContainer);
@@ -272,6 +272,7 @@ public class Reports extends BasePage {
         add(createLink);
     }
 
+    @SuppressWarnings("rawtypes")
     private void setupAudit() {
         auditContainer = new WebMarkupContainer("auditContainer");
         auditContainer.setOutputMarkupId(true);
@@ -300,77 +301,79 @@ public class Reports extends BasePage {
         form.add(new LoggerCategoryPanel(
                 "events", loggerRestClient.listEvents(), model, getPageReference(), "Reports") {
 
-            private static final long serialVersionUID = 6113164334533550277L;
+                    private static final long serialVersionUID = 6113164334533550277L;
 
-            @Override
-            protected String[] getListRoles() {
-                return new String[] {
-                    xmlRolesReader.getAllAllowedRoles("Audit", "list")
-                };
-            }
+                    @Override
+                    protected String[] getListRoles() {
+                        return new String[] {
+                            xmlRolesReader.getAllAllowedRoles("Audit", "list")
+                        };
+                    }
 
-            @Override
-            protected String[] getChangeRoles() {
-                return new String[] {
-                    xmlRolesReader.getAllAllowedRoles("Audit", "enable"),
-                    xmlRolesReader.getAllAllowedRoles("Audit", "disable")
-                };
-            }
+                    @Override
+                    protected String[] getChangeRoles() {
+                        return new String[] {
+                            xmlRolesReader.getAllAllowedRoles("Audit", "enable"),
+                            xmlRolesReader.getAllAllowedRoles("Audit", "disable")
+                        };
+                    }
 
-            @Override
-            public void onEventAction(final IEvent<?> event) {
-                if (event.getPayload() instanceof SelectedEventsPanel.EventSelectionChanged) {
+                    @Override
+                    public void onEventAction(final IEvent<?> event) {
+                        if (event.getPayload() instanceof SelectedEventsPanel.EventSelectionChanged) {
 
-                    final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged =
+                            final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged =
                             (SelectedEventsPanel.EventSelectionChanged) event.getPayload();
 
-                    for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
-                        if (events.contains(toBeRemoved)) {
-                            final Map.Entry<EventCategoryTO, Result> eventCategory =
+                            for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
+                                if (events.contains(toBeRemoved)) {
+                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
                                     LoggerEventUtils.parseEventCategory(toBeRemoved);
 
-                            final AuditLoggerName auditLoggerName = new AuditLoggerName(
-                                    eventCategory.getKey().getType(),
-                                    eventCategory.getKey().getCategory(),
-                                    eventCategory.getKey().getSubcategory(),
-                                    CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
-                                    ? null : eventCategory.getKey().getEvents().iterator().next(),
-                                    eventCategory.getValue());
-
-                            loggerRestClient.disableAudit(auditLoggerName);
-                            events.remove(toBeRemoved);
-                        }
-                    }
+                                    final AuditLoggerName auditLoggerName = new AuditLoggerName(
+                                            eventCategory.getKey().getType(),
+                                            eventCategory.getKey().getCategory(),
+                                            eventCategory.getKey().getSubcategory(),
+                                            CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
+                                            ? null : eventCategory.getKey().getEvents().iterator().next(),
+                                            eventCategory.getValue());
+
+                                    loggerRestClient.disableAudit(auditLoggerName);
+                                    events.remove(toBeRemoved);
+                                }
+                            }
 
-                    for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
-                        if (!events.contains(toBeAdded)) {
-                            final Map.Entry<EventCategoryTO, Result> eventCategory =
+                            for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
+                                if (!events.contains(toBeAdded)) {
+                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
                                     LoggerEventUtils.parseEventCategory(toBeAdded);
 
-                            final AuditLoggerName auditLoggerName = new AuditLoggerName(
-                                    eventCategory.getKey().getType(),
-                                    eventCategory.getKey().getCategory(),
-                                    eventCategory.getKey().getSubcategory(),
-                                    CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
-                                    ? null : eventCategory.getKey().getEvents().iterator().next(),
-                                    eventCategory.getValue());
-
-                            loggerRestClient.enableAudit(auditLoggerName);
-                            events.add(toBeAdded);
+                                    final AuditLoggerName auditLoggerName = new AuditLoggerName(
+                                            eventCategory.getKey().getType(),
+                                            eventCategory.getKey().getCategory(),
+                                            eventCategory.getKey().getSubcategory(),
+                                            CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
+                                            ? null : eventCategory.getKey().getEvents().iterator().next(),
+                                            eventCategory.getValue());
+
+                                    loggerRestClient.enableAudit(auditLoggerName);
+                                    events.add(toBeAdded);
+                                }
+                            }
                         }
                     }
-                }
-            }
-        });
+                });
     }
 
     private class ReportProvider extends SortableDataProvider<ReportTO, String> {
 
         private static final long serialVersionUID = -2311716167583335852L;
 
-        private SortableDataProviderComparator<ReportTO> comparator;
+        private final SortableDataProviderComparator<ReportTO> comparator;
 
         public ReportProvider() {
+            super();
+
             //Default sorting
             setSort("id", SortOrder.ASCENDING);
             comparator = new SortableDataProviderComparator<ReportTO>(this);

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java Wed Dec  4 15:34:14 2013
@@ -228,12 +228,11 @@ public class StatusPanel extends Panel i
     }
 
     public StatusMod getStatusMod() {
-        StatusMod result = null;
+        StatusMod result = new StatusMod();
 
         Collection<StatusBean> statusBeans = checkGroup.getModel().getObject();
         if (statusBeans != null && !statusBeans.isEmpty()) {
             result = StatusUtils.buildStatusMod(statusBeans);
-
         }
 
         return result;

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=1547823&r1=1547822&r2=1547823&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 15:34:14 2013
@@ -59,6 +59,7 @@ import org.apache.syncope.core.workflow.
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.OperationalAttributes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -67,7 +68,7 @@ import org.springframework.transaction.a
 /**
  * Manage the data propagation to external resources.
  */
-@Transactional(rollbackFor = {Throwable.class})
+@Transactional(rollbackFor = { Throwable.class })
 public class PropagationManager {
 
     /**
@@ -198,7 +199,7 @@ public class PropagationManager {
             propByRes.get(ResourceOperation.CREATE).removeAll(noPropResourceNames);
         }
 
-        return createTasks(attributable, password, null, null, enable, false, propByRes);
+        return createTasks(attributable, password, true, null, null, enable, false, propByRes);
     }
 
     /**
@@ -217,6 +218,7 @@ public class PropagationManager {
         return getUpdateTaskIds(
                 user, // SyncopeUser to be updated on external resources
                 null, // no password
+                false,
                 enable, // status to be propagated
                 Collections.<String>emptySet(), // no virtual attributes to be managed
                 Collections.<AttributeMod>emptySet(), // no virtual attributes to be managed
@@ -228,18 +230,20 @@ public class PropagationManager {
      * Performs update on each resource associated to the user.
      *
      * @param wfResult user to be propagated (and info associated), as per result from workflow
+     * @param changePwd whether password should be included for propagation attributes or not
      * @param noPropResourceNames external resources not to be considered for propagation
      * @return list of propagation tasks
      * @throws NotFoundException if user is not found
      * @throws UnauthorizedRoleException if caller doesn't own enough entitlements to administer the given user
      */
     public List<PropagationTask> getUserUpdateTaskIds(final WorkflowResult<Map.Entry<UserMod, Boolean>> wfResult,
-            final Collection<String> noPropResourceNames)
+            final boolean changePwd, final Collection<String> noPropResourceNames)
             throws NotFoundException, UnauthorizedRoleException {
 
         SyncopeUser user = userDataBinder.getUserFromId(wfResult.getResult().getKey().getId());
         return getUpdateTaskIds(user,
                 wfResult.getResult().getKey().getPassword(),
+                changePwd,
                 wfResult.getResult().getValue(),
                 wfResult.getResult().getKey().getVirAttrsToRemove(),
                 wfResult.getResult().getKey().getVirAttrsToUpdate(),
@@ -254,7 +258,7 @@ public class PropagationManager {
         List<PropagationTask> tasks = new ArrayList<PropagationTask>();
         if (userMod.getPwdPropRequest() == null) {
             // a. no specific password propagation request: generate propagation tasks for any resource associated
-            tasks = getUserUpdateTaskIds(wfResult, null);
+            tasks = getUserUpdateTaskIds(wfResult, true, null);
         } else {
             // b. generate the propagation task list in two phases: first the ones containing password,
             // the the rest (with no password)
@@ -270,7 +274,7 @@ public class PropagationManager {
                 Set<String> toBeExcluded = new HashSet<String>(currentResourceNames);
                 toBeExcluded.addAll(userMod.getResourcesToAdd());
                 toBeExcluded.removeAll(pwdResourceNames);
-                tasks.addAll(getUserUpdateTaskIds(wfResult, toBeExcluded));
+                tasks.addAll(getUserUpdateTaskIds(wfResult, true, toBeExcluded));
             }
 
             final PropagationByResource nonPwdPropByRes = new PropagationByResource();
@@ -278,7 +282,7 @@ public class PropagationManager {
             nonPwdPropByRes.removeAll(pwdResourceNames);
             nonPwdPropByRes.purge();
             if (!nonPwdPropByRes.isEmpty()) {
-                tasks.addAll(getUserUpdateTaskIds(wfResult, pwdResourceNames));
+                tasks.addAll(getUserUpdateTaskIds(wfResult, false, pwdResourceNames));
             }
         }
 
@@ -319,12 +323,12 @@ public class PropagationManager {
             throws NotFoundException, UnauthorizedRoleException {
 
         SyncopeRole role = roleDataBinder.getRoleFromId(wfResult.getResult());
-        return getUpdateTaskIds(role, null, null,
+        return getUpdateTaskIds(role, null, false, null,
                 vAttrsToBeRemoved, vAttrsToBeUpdated, wfResult.getPropByRes(), noPropResourceNames);
     }
 
     protected List<PropagationTask> getUpdateTaskIds(final AbstractAttributable attributable,
-            final String password, final Boolean enable,
+            final String password, final boolean changePwd, final Boolean enable,
             final Set<String> vAttrsToBeRemoved, final Set<AttributeMod> vAttrsToBeUpdated,
             final PropagationByResource propByRes, final Collection<String> noPropResourceNames)
             throws NotFoundException {
@@ -356,7 +360,7 @@ public class PropagationManager {
             }
         }
 
-        return createTasks(attributable, password,
+        return createTasks(attributable, password, changePwd,
                 vAttrsToBeRemoved, vAttrsToBeUpdatedMap, enable, false, localPropByRes);
     }
 
@@ -422,7 +426,7 @@ public class PropagationManager {
      */
     public List<PropagationTask> getUserDeleteTaskIds(final WorkflowResult<Long> wfResult) {
         SyncopeUser user = userDataBinder.getUserFromId(wfResult.getResult());
-        return createTasks(user, null, null, null, false, true, wfResult.getPropByRes());
+        return createTasks(user, null, false, null, null, false, true, wfResult.getPropByRes());
     }
 
     /**
@@ -484,7 +488,7 @@ public class PropagationManager {
         if (noPropResourceNames != null && !noPropResourceNames.isEmpty()) {
             propByRes.get(ResourceOperation.DELETE).removeAll(noPropResourceNames);
         }
-        return createTasks(attributable, null, null, null, false, true, propByRes);
+        return createTasks(attributable, null, false, null, null, false, true, propByRes);
     }
 
     /**
@@ -494,6 +498,7 @@ public class PropagationManager {
      * @param attrUtil user / role
      * @param subject given user / role
      * @param password clear-text password
+     * @param changePwd whether password should be included for propagation attributes or not
      * @param vAttrsToBeRemoved virtual attributes to be removed
      * @param vAttrsToBeUpdated virtual attributes to be added
      * @param enable whether user must be enabled or not
@@ -501,7 +506,7 @@ public class PropagationManager {
      * @return account link + prepared attributes
      */
     protected <T extends AbstractAttributable> Map.Entry<String, Set<Attribute>> prepareAttributes(
-            final AttributableUtil attrUtil, final T subject, final String password,
+            final AttributableUtil attrUtil, final T subject, final String password, final boolean changePwd,
             final Set<String> vAttrsToBeRemoved, final Map<String, AttributeMod> vAttrsToBeUpdated,
             final Boolean enable, final ExternalResource resource) {
 
@@ -527,11 +532,11 @@ public class PropagationManager {
                 Map.Entry<String, Attribute> preparedAttribute = MappingUtil.prepareAttribute(
                         resource, mapping, subject, password, passwordGenerator, vAttrsToBeRemoved, vAttrsToBeUpdated);
 
-                if (preparedAttribute.getKey() != null) {
+                if (preparedAttribute != null && preparedAttribute.getKey() != null) {
                     accountId = preparedAttribute.getKey();
                 }
 
-                if (preparedAttribute.getValue() != null) {
+                if (preparedAttribute != null && preparedAttribute.getValue() != null) {
                     Attribute alreadyAdded = AttributeUtil.find(preparedAttribute.getValue().getName(), attributes);
 
                     if (alreadyAdded == null) {
@@ -555,6 +560,12 @@ public class PropagationManager {
         if (enable != null) {
             attributes.add(AttributeBuilder.buildEnabled(enable));
         }
+        if (!changePwd) {
+            Attribute pwdAttr = AttributeUtil.find(OperationalAttributes.PASSWORD_NAME, attributes);
+            if (pwdAttr != null) {
+                attributes.remove(pwdAttr);
+            }
+        }
 
         return new SimpleEntry<String, Set<Attribute>>(accountId, attributes);
     }
@@ -565,6 +576,7 @@ public class PropagationManager {
      * @param <T> user / role
      * @param subject user / role to be provisioned
      * @param password cleartext password to be provisioned
+     * @param changePwd whether password should be included for propagation attributes or not
      * @param vAttrsToBeRemoved virtual attributes to be removed
      * @param vAttrsToBeUpdated virtual attributes to be added
      * @param enable whether user must be enabled or not
@@ -572,7 +584,8 @@ public class PropagationManager {
      * @param propByRes operation to be performed per resource
      * @return list of propagation tasks created
      */
-    protected <T extends AbstractAttributable> List<PropagationTask> createTasks(final T subject, final String password,
+    protected <T extends AbstractAttributable> List<PropagationTask> createTasks(final T subject,
+            final String password, final boolean changePwd,
             final Set<String> vAttrsToBeRemoved, final Map<String, AttributeMod> vAttrsToBeUpdated,
             final Boolean enable, final boolean deleteOnResource,
             final PropagationByResource propByRes) {
@@ -624,8 +637,8 @@ public class PropagationManager {
                     task.setPropagationMode(resource.getPropagationMode());
                     task.setOldAccountId(propByRes.getOldAccountId(resource.getName()));
 
-                    Map.Entry<String, Set<Attribute>> preparedAttrs = prepareAttributes(attrUtil, subject, password,
-                            vAttrsToBeRemoved, vAttrsToBeUpdated, enable, resource);
+                    Map.Entry<String, Set<Attribute>> preparedAttrs = prepareAttributes(attrUtil, subject,
+                            password, changePwd, vAttrsToBeRemoved, vAttrsToBeUpdated, enable, resource);
                     task.setAccountId(preparedAttrs.getKey());
 
                     // Check if any of mandatory attributes (in the mapping) is missing or not received any value: 

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=1547823&r1=1547822&r2=1547823&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 15:34:14 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 {
 
@@ -310,7 +310,7 @@ public class RoleController extends Abst
         final List<SyncopeRole> toBeDeprovisioned = new ArrayList<SyncopeRole>();
 
         final SyncopeRole syncopeRole = roleDAO.find(roleId);
-        
+
         if (syncopeRole != null) {
             toBeDeprovisioned.add(syncopeRole);
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/LDAPMembershipSyncActions.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/LDAPMembershipSyncActions.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/LDAPMembershipSyncActions.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/LDAPMembershipSyncActions.java Wed Dec  4 15:34:14 2013
@@ -211,7 +211,7 @@ public class LDAPMembershipSyncActions e
             updated = uwfAdapter.update(userMod);
 
             List<PropagationTask> tasks = propagationManager.getUserUpdateTaskIds(
-                    updated, Collections.singleton(resourceName));
+                    updated, false, Collections.singleton(resourceName));
 
             taskExecutor.execute(tasks);
             result = Result.SUCCESS;

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/SyncopeSyncResultHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/SyncopeSyncResultHandler.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/SyncopeSyncResultHandler.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/sync/impl/SyncopeSyncResultHandler.java Wed Dec  4 15:34:14 2013
@@ -475,7 +475,7 @@ public class SyncopeSyncResultHandler im
 
         final List<ConnectorObject> found = connector.search(objectClass,
                 new EqualsFilter(new Name(name)), connector.getOperationOptions(
-                attrUtil.getMappingItems(syncTask.getResource(), MappingPurpose.SYNCHRONIZATION)));
+                        attrUtil.getMappingItems(syncTask.getResource(), MappingPurpose.SYNCHRONIZATION)));
 
         if (found.isEmpty()) {
             LOG.debug("No {} found on {} with __NAME__ {}", objectClass, syncTask.getResource(), name);
@@ -678,7 +678,8 @@ public class SyncopeSyncResultHandler im
         }
 
         List<PropagationTask> tasks = propagationManager.getUserUpdateTaskIds(
-                updated, Collections.singleton(syncTask.getResource().getName()));
+                updated, updated.getResult().getKey().getPassword() != null,
+                Collections.singleton(syncTask.getResource().getName()));
 
         taskExecutor.execute(tasks);
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/util/MappingUtil.java Wed Dec  4 15:34:14 2013
@@ -247,8 +247,12 @@ public final class MappingUtil {
                     }
                 }
 
-                result = new AbstractMap.SimpleEntry<String, Attribute>(null,
-                        AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
+                if (passwordAttrValue == null) {
+                    result = null;
+                } else {
+                    result = new AbstractMap.SimpleEntry<String, Attribute>(null,
+                            AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
+                }
             } else {
                 if ((schema != null && schema.isMultivalue()) || AttributableUtil.getInstance(subject).getType()
                         != mapItem.getIntMappingType().getAttributableType()) {

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=1547823&r1=1547822&r2=1547823&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 Wed Dec  4 15:34:14 2013
@@ -22,9 +22,12 @@ import static org.junit.Assert.assertNot
 
 import java.io.InputStream;
 import java.net.URI;
+import java.util.Hashtable;
+import java.util.Map;
 import java.util.Properties;
 import java.util.UUID;
-
+import javax.naming.Context;
+import javax.naming.directory.InitialDirContext;
 import javax.sql.DataSource;
 import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
@@ -58,6 +61,7 @@ import org.apache.syncope.common.to.Reso
 import org.apache.syncope.common.to.RoleTO;
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.common.types.AttributableType;
+import org.apache.syncope.common.types.ConnConfProperty;
 import org.apache.syncope.common.types.RESTHeaders;
 import org.apache.syncope.common.types.SchemaType;
 import org.apache.syncope.core.util.PasswordEncoder;
@@ -70,7 +74,7 @@ import org.springframework.test.context.
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 @RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = {"classpath:testJDBCContext.xml"})
+@ContextConfiguration(locations = { "classpath:testJDBCContext.xml" })
 public abstract class AbstractTest {
 
     /**
@@ -257,14 +261,14 @@ public abstract class AbstractTest {
     protected UserTO deleteUser(final Long id) {
         return userService.delete(id).readEntity(UserTO.class);
     }
-    
+
     public <T> T getObject(final URI location, final Class<?> serviceClass, final Class<T> resultClass) {
         WebClient webClient = WebClient.fromClient(WebClient.client(adminClient.getService(serviceClass)));
         webClient.accept(clientFactory.getContentType().getMediaType()).to(location.toASCIIString(), false);
 
         return webClient.get(resultClass);
     }
-    
+
     @SuppressWarnings("unchecked")
     protected <T extends AbstractSchemaTO> T createSchema(final AttributableType kind,
             final SchemaType type, final T schemaTO) {
@@ -321,4 +325,32 @@ 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) {
+        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,
+                bindDn == null ? ldapConnConf.get("principal").getValues().get(0) : bindDn);
+        env.put(Context.SECURITY_CREDENTIALS,
+                bindPwd == null ? ldapConnConf.get("credentials").getValues().get(0) : bindPwd);
+
+        try {
+            final InitialDirContext ctx = new InitialDirContext(env);
+            return ctx.lookup(objectDn);
+        } catch (Exception e) {
+            return null;
+        }
+    }
 }

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=1547823&r1=1547822&r2=1547823&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 15:34:14 2013
@@ -28,11 +28,7 @@ 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;
@@ -41,13 +37,11 @@ import org.apache.syncope.common.mod.Rol
 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.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;
@@ -592,38 +586,17 @@ public class RoleTestITCase extends Abst
             roleService.read(parent.getId());
             fail();
         } catch (SyncopeClientException scce) {
-            // ignore
+            assertNotNull(scce);
         }
 
         try {
             roleService.read(child.getId());
             fail();
         } catch (SyncopeClientException scce) {
-            // ignore
+            assertNotNull(scce);
         }
 
         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;
-        }
-    }
 }

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=1547823&r1=1547822&r2=1547823&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 Wed Dec  4 15:34:14 2013
@@ -73,6 +73,7 @@ import org.identityconnectors.framework.
 
 import java.io.IOException;
 import java.io.InputStream;
+import javax.naming.NamingException;
 import javax.ws.rs.core.EntityTag;
 import javax.xml.ws.WebServiceException;
 import org.apache.commons.lang3.StringUtils;
@@ -81,6 +82,7 @@ import org.apache.syncope.client.Syncope
 import org.apache.syncope.common.services.UserService;
 import org.apache.syncope.common.types.Preference;
 import org.apache.syncope.common.types.RESTHeaders;
+import org.identityconnectors.framework.common.objects.Name;
 import org.junit.Assume;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -1060,7 +1062,6 @@ public class UserTestITCase extends Abst
 
         // 2. try to update by adding a resource, but no password: must fail
         UserMod userMod = AttributableOperations.diff(toBeUpdated, original);
-
         assertNotNull(userMod);
 
         toBeUpdated = updateUser(userMod);
@@ -1447,7 +1448,7 @@ public class UserTestITCase extends Abst
         assertEquals(PropagationTaskExecStatus.SUBMITTED, userTO.getPropagationStatusTOs().get(0).getStatus());
 
         ConnObjectTO connObjectTO =
-                resourceService.getConnectorObject("resource-db-virattr", AttributableType.USER, userTO.getId());
+                resourceService.getConnectorObject(RESOURCE_NAME_DBVIRATTR, AttributableType.USER, userTO.getId());
         assertNotNull(connObjectTO);
         assertEquals("virtualvalue", connObjectTO.getAttrMap().get("USERNAME").getValues().get(0));
         // ----------------------------------
@@ -1636,7 +1637,7 @@ public class UserTestITCase extends Abst
         UserTO actual = createUser(userTO);
         assertNotNull(actual);
 
-        final ConnObjectTO connObjectTO =
+        ConnObjectTO connObjectTO =
                 resourceService.getConnectorObject(RESOURCE_NAME_CSV, AttributableType.USER, actual.getId());
         assertNull(connObjectTO.getAttrMap().get("email"));
     }
@@ -2043,4 +2044,38 @@ public class UserTestITCase extends Abst
         userTO = userService.read(userTO.getId());
         assertTrue(userTO.getUsername().endsWith("XX"));
     }
+
+    @Test
+    public void issueSYNCOPE454() throws NamingException {
+        // 1. create user with LDAP resource (with 'Generate password if missing' enabled)
+        UserTO userTO = getUniqueSampleTO("syncope454@syncope.apache.org");
+        userTO.getResources().add(RESOURCE_NAME_LDAP);
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+
+        // 2. read resource configuration for LDAP binding
+        ConnObjectTO connObject =
+                resourceService.getConnectorObject(RESOURCE_NAME_LDAP, AttributableType.USER, userTO.getId());
+
+        // 3. try (and succeed) to perform simple LDAP binding with provided password ('password123')
+        assertNotNull(getLdapRemoteObject(
+                connObject.getAttrMap().get(Name.NAME).getValues().get(0),
+                "password123",
+                connObject.getAttrMap().get(Name.NAME).getValues().get(0)));
+
+        // 4. update user without any password change request
+        UserMod userMod = new UserMod();
+        userMod.setId(userTO.getId());
+        userMod.setPwdPropRequest(new StatusMod());
+        userMod.getAttrsToUpdate().add(attributeMod("surname", "surname2"));
+
+        userService.update(userTO.getId(), userMod);
+
+        // 5. try (and succeed again) to perform simple LDAP binding: password has not changed
+        assertNotNull(getLdapRemoteObject(
+                connObject.getAttrMap().get(Name.NAME).getValues().get(0),
+                "password123",
+                connObject.getAttrMap().get(Name.NAME).getValues().get(0)));
+    }
+
 }

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirAttrTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirAttrTestITCase.java?rev=1547823&r1=1547822&r2=1547823&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirAttrTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirAttrTestITCase.java Wed Dec  4 15:34:14 2013
@@ -136,8 +136,7 @@ public class VirAttrTestITCase extends A
         userTO = userService.status(userTO.getId(), statusMod).readEntity(UserTO.class);
         assertEquals("suspended", userTO.getStatus());
 
-        connObjectTO =
-                resourceService.getConnectorObject(RESOURCE_NAME_WS2, AttributableType.USER, userTO.getId());
+        connObjectTO = resourceService.getConnectorObject(RESOURCE_NAME_WS2, AttributableType.USER, userTO.getId());
         assertNotNull(connObjectTO);
         assertFalse(connObjectTO.getAttrMap().get("NAME").getValues().isEmpty());
         assertEquals("virtualvalue2", connObjectTO.getAttrMap().get("NAME").getValues().get(0));
@@ -147,8 +146,7 @@ public class VirAttrTestITCase extends A
         userTO = userService.status(userTO.getId(), statusMod).readEntity(UserTO.class);
         assertEquals("active", userTO.getStatus());
 
-        connObjectTO =
-                resourceService.getConnectorObject(RESOURCE_NAME_WS2, AttributableType.USER, userTO.getId());
+        connObjectTO = resourceService.getConnectorObject(RESOURCE_NAME_WS2, AttributableType.USER, userTO.getId());
         assertNotNull(connObjectTO);
         assertFalse(connObjectTO.getAttrMap().get("NAME").getValues().isEmpty());
         assertEquals("virtualvalue2", connObjectTO.getAttrMap().get("NAME").getValues().get(0));