syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject svn commit: r1539376 [3/4] - in /syncope/trunk: client/src/main/java/org/apache/syncope/client/ common/src/main/java/org/apache/syncope/common/report/ common/src/main/java/org/apache/syncope/common/services/ common/src/main/java/org/apache/syncope/comm...
Date Wed, 06 Nov 2013 15:57:30 GMT
Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowAdapter.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowAdapter.java Wed Nov  6 15:57:28 2013
@@ -19,7 +19,7 @@
 package org.apache.syncope.core.workflow;
 
 import java.util.List;
-import java.util.Map;
+import org.apache.syncope.common.mod.AbstractAttributableMod;
 import org.apache.syncope.common.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.to.WorkflowFormTO;
 import org.apache.syncope.core.persistence.dao.NotFoundException;
@@ -108,6 +108,6 @@ public interface WorkflowAdapter {
      * @throws NotFoundException not found exception
      * @throws WorkflowException workflow exception
      */
-    WorkflowResult<Map.Entry<Long, String>> submitForm(WorkflowFormTO form, String username)
+    WorkflowResult<? extends AbstractAttributableMod> submitForm(WorkflowFormTO form, String username)
             throws NotFoundException, WorkflowException;
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowUserSuspender.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowUserSuspender.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowUserSuspender.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowUserSuspender.java Wed Nov  6 15:57:28 2013
@@ -21,13 +21,12 @@ package org.apache.syncope.core.workflow
 import java.util.AbstractMap.SimpleEntry;
 import java.util.List;
 import java.util.Map;
-import org.apache.syncope.common.to.UserTO;
+import org.apache.syncope.common.mod.UserMod;
 import org.apache.syncope.core.persistence.beans.PropagationTask;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.policy.UserSuspender;
 import org.apache.syncope.core.propagation.PropagationTaskExecutor;
 import org.apache.syncope.core.propagation.impl.PropagationManager;
-import org.apache.syncope.core.rest.data.UserDataBinder;
 import org.apache.syncope.core.workflow.user.UserWorkflowAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,9 +47,6 @@ public class WorkflowUserSuspender imple
     @Autowired
     private PropagationTaskExecutor taskExecutor;
 
-    @Autowired
-    private UserDataBinder userDataBinder;
-
     @Override
     public void suspend(final SyncopeUser user, final boolean suspend) {
         try {
@@ -64,10 +60,13 @@ public class WorkflowUserSuspender imple
 
             // propagate suspension if and only if it is required by policy
             if (suspend) {
+                UserMod userMod = new UserMod();
+                userMod.setId(updated.getResult());
+
                 final List<PropagationTask> tasks = propagationManager.getUserUpdateTaskIds(
-                        new WorkflowResult<Map.Entry<Long, Boolean>>(
-                        new SimpleEntry<Long, Boolean>(updated.getResult(), Boolean.FALSE),
-                        updated.getPropByRes(), updated.getPerformedTasks()));
+                        new WorkflowResult<Map.Entry<UserMod, Boolean>>(
+                                new SimpleEntry<UserMod, Boolean>(userMod, Boolean.FALSE),
+                                updated.getPropByRes(), updated.getPerformedTasks()));
 
                 taskExecutor.execute(tasks);
             }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/role/NoOpRoleWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/role/NoOpRoleWorkflowAdapter.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/role/NoOpRoleWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/role/NoOpRoleWorkflowAdapter.java Wed Nov  6 15:57:28 2013
@@ -21,7 +21,6 @@ package org.apache.syncope.core.workflow
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.syncope.common.mod.RoleMod;
 import org.apache.syncope.common.to.RoleTO;
@@ -39,10 +38,10 @@ import org.springframework.transaction.a
 /**
  * Simple implementation basically not involving any workflow engine.
  */
-@Transactional(rollbackFor = {Throwable.class})
+@Transactional(rollbackFor = { Throwable.class })
 public class NoOpRoleWorkflowAdapter extends AbstractRoleWorkflowAdapter {
 
-    private static final List<String> TASKS = Arrays.asList(new String[] {"create", "update", "delete"});
+    private static final List<String> TASKS = Arrays.asList(new String[] { "create", "update", "delete" });
 
     @Override
     public WorkflowResult<Long> create(final RoleTO roleTO)
@@ -129,9 +128,10 @@ public class NoOpRoleWorkflowAdapter ext
     }
 
     @Override
-    public WorkflowResult<Map.Entry<Long, String>> submitForm(final WorkflowFormTO form, final String username)
+    public WorkflowResult<RoleMod> submitForm(final WorkflowFormTO form, final String username)
             throws NotFoundException, WorkflowException {
 
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }
+
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/AbstractUserWorkflowAdapter.java Wed Nov  6 15:57:28 2013
@@ -29,10 +29,12 @@ import org.apache.syncope.core.rest.data
 import org.apache.syncope.core.workflow.WorkflowException;
 import org.apache.syncope.core.workflow.WorkflowInstanceLoader;
 import org.apache.syncope.core.workflow.WorkflowResult;
+import org.identityconnectors.common.security.EncryptorFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.codec.Base64;
 import org.springframework.transaction.annotation.Transactional;
 
-@Transactional(rollbackFor = {Throwable.class})
+@Transactional(rollbackFor = { Throwable.class })
 public abstract class AbstractUserWorkflowAdapter implements UserWorkflowAdapter {
 
     @Autowired
@@ -41,6 +43,19 @@ public abstract class AbstractUserWorkfl
     @Autowired
     protected UserDAO userDAO;
 
+    public static String encrypt(final String clear) {
+        byte[] encryptedBytes = EncryptorFactory.getInstance().getDefaultEncryptor().encrypt(clear.getBytes());
+
+        return new String(Base64.encode(encryptedBytes));
+    }
+
+    public static String decrypt(final String crypted) {
+        byte[] decryptedBytes =
+                EncryptorFactory.getInstance().getDefaultEncryptor().decrypt(Base64.decode(crypted.getBytes()));
+
+        return new String(decryptedBytes);
+    }
+
     @Override
     public Class<? extends WorkflowInstanceLoader> getLoaderClass() {
         return null;
@@ -62,11 +77,11 @@ public abstract class AbstractUserWorkfl
         return doActivate(dataBinder.getUserFromId(userId), token);
     }
 
-    protected abstract WorkflowResult<Map.Entry<Long, Boolean>> doUpdate(SyncopeUser user, UserMod userMod)
+    protected abstract WorkflowResult<Map.Entry<UserMod, Boolean>> doUpdate(SyncopeUser user, UserMod userMod)
             throws WorkflowException;
 
     @Override
-    public WorkflowResult<Map.Entry<Long, Boolean>> update(final UserMod userMod)
+    public WorkflowResult<Map.Entry<UserMod, Boolean>> update(final UserMod userMod)
             throws UnauthorizedRoleException, WorkflowException {
 
         return doUpdate(dataBinder.getUserFromId(userMod.getId()), userMod);

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java Wed Nov  6 15:57:28 2013
@@ -40,11 +40,11 @@ import org.springframework.transaction.a
 /**
  * Simple implementation basically not involving any workflow engine.
  */
-@Transactional(rollbackFor = {Throwable.class})
+@Transactional(rollbackFor = { Throwable.class })
 public class NoOpUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
 
     private static final List<String> TASKS =
-            Arrays.asList(new String[] {"create", "activate", "update", "suspend", "reactivate", "delete"});
+            Arrays.asList(new String[] { "create", "activate", "update", "suspend", "reactivate", "delete" });
 
     public static final String ENABLED = "enabled";
 
@@ -107,15 +107,16 @@ public class NoOpUserWorkflowAdapter ext
     }
 
     @Override
-    protected WorkflowResult<Map.Entry<Long, Boolean>> doUpdate(final SyncopeUser user, final UserMod userMod)
+    protected WorkflowResult<Map.Entry<UserMod, Boolean>> doUpdate(final SyncopeUser user, final UserMod userMod)
             throws WorkflowException {
 
         PropagationByResource propByRes = dataBinder.update(user, userMod);
 
         SyncopeUser updated = userDAO.save(user);
 
-        return new WorkflowResult<Map.Entry<Long, Boolean>>(
-                new AbstractMap.SimpleEntry<Long, Boolean>(updated.getId(), !user.isSuspended()), propByRes, "update");
+        userMod.setId(updated.getId());
+        return new WorkflowResult<Map.Entry<UserMod, Boolean>>(
+                new AbstractMap.SimpleEntry<UserMod, Boolean>(userMod, !user.isSuspended()), propByRes, "update");
     }
 
     @Override
@@ -198,7 +199,7 @@ public class NoOpUserWorkflowAdapter ext
     }
 
     @Override
-    public WorkflowResult<Map.Entry<Long, String>> submitForm(final WorkflowFormTO form, final String username)
+    public WorkflowResult<UserMod> submitForm(final WorkflowFormTO form, final String username)
             throws NotFoundException, WorkflowException {
 
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/UserWorkflowAdapter.java Wed Nov  6 15:57:28 2013
@@ -97,7 +97,7 @@ public interface UserWorkflowAdapter ext
      * @throws UnauthorizedRoleException authorization exception
      * @throws WorkflowException workflow exception
      */
-    WorkflowResult<Map.Entry<Long, Boolean>> update(UserMod userMod)
+    WorkflowResult<Map.Entry<UserMod, Boolean>> update(UserMod userMod)
             throws UnauthorizedRoleException, WorkflowException;
 
     /**

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java Wed Nov  6 15:57:28 2013
@@ -67,19 +67,20 @@ import org.apache.syncope.common.to.Work
 import org.apache.syncope.common.types.ResourceOperation;
 import org.apache.syncope.common.types.WorkflowFormPropertyType;
 import org.apache.syncope.common.util.BeanUtils;
+import org.apache.syncope.common.validation.SyncopeClientException;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.persistence.dao.NotFoundException;
+import org.apache.syncope.core.persistence.validation.attrvalue.ParsingValidationException;
 import org.apache.syncope.core.propagation.PropagationByResource;
 import org.apache.syncope.core.rest.controller.UnauthorizedRoleException;
+import org.apache.syncope.core.util.EntitlementUtil;
 import org.apache.syncope.core.workflow.WorkflowException;
 import org.apache.syncope.core.workflow.WorkflowInstanceLoader;
 import org.apache.syncope.core.workflow.WorkflowResult;
 import org.apache.syncope.core.workflow.user.AbstractUserWorkflowAdapter;
-import org.identityconnectors.common.security.EncryptorFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.crypto.codec.Base64;
 import org.springframework.transaction.annotation.Transactional;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
@@ -94,7 +95,7 @@ public class ActivitiUserWorkflowAdapter
      */
     private static final Logger LOG = LoggerFactory.getLogger(ActivitiUserWorkflowAdapter.class);
 
-    private static final String[] PROPERTY_IGNORE_PROPS = {"type"};
+    private static final String[] PROPERTY_IGNORE_PROPS = { "type" };
 
     public static final String WF_PROCESS_ID = "userWorkflow";
 
@@ -102,6 +103,8 @@ public class ActivitiUserWorkflowAdapter
 
     public static final String SYNCOPE_USER = "syncopeUser";
 
+    public static final String WF_EXECUTOR = "wfExecutor";
+
     public static final String USER_TO = "userTO";
 
     public static final String ENABLED = "enabled";
@@ -145,6 +148,18 @@ public class ActivitiUserWorkflowAdapter
         return ActivitiWorkflowLoader.class;
     }
 
+    private void throwException(final ActivitiException e, final String defaultMessage) {
+        if (e.getCause() != null) {
+            if (e.getCause().getCause() instanceof SyncopeClientException) {
+                throw (SyncopeClientException) e.getCause().getCause();
+            } else if (e.getCause().getCause() instanceof ParsingValidationException) {
+                throw (ParsingValidationException) e.getCause().getCause();
+            }
+        }
+
+        throw new WorkflowException(defaultMessage, e);
+    }
+
     private void updateStatus(final SyncopeUser user) {
         List<Task> tasks = taskService.createTaskQuery().processInstanceId(user.getWorkflowId()).list();
         if (tasks.isEmpty() || tasks.size() > 1) {
@@ -185,17 +200,25 @@ public class ActivitiUserWorkflowAdapter
         return result;
     }
 
-    private String encrypt(final String clear) {
-        byte[] encryptedBytes = EncryptorFactory.getInstance().getDefaultEncryptor().encrypt(clear.getBytes());
-
-        return new String(Base64.encode(encryptedBytes));
-    }
+    /**
+     * Saves resources to be propagated and password for later - after form submission - propagation.
+     */
+    private void saveForFormSubmit(final SyncopeUser user, final String password,
+            final PropagationByResource propByRes) {
 
-    private String decrypt(final String crypted) {
-        byte[] decryptedBytes =
-                EncryptorFactory.getInstance().getDefaultEncryptor().decrypt(Base64.decode(crypted.getBytes()));
+        String formTaskId = getFormTask(user);
+        if (formTaskId != null) {
+            // SYNCOPE-238: This is needed to simplify the task query in this.getForms()
+            taskService.setVariableLocal(formTaskId, TASK_IS_FORM, Boolean.TRUE);
+            runtimeService.setVariable(user.getWorkflowId(), PROP_BY_RESOURCE, propByRes);
+            if (propByRes != null) {
+                propByRes.clear();
+            }
 
-        return new String(decryptedBytes);
+            if (StringUtils.isNotBlank(password)) {
+                runtimeService.setVariable(user.getWorkflowId(), ENCRYPTED_PWD, encrypt(password));
+            }
+        }
     }
 
     @Override
@@ -211,20 +234,22 @@ public class ActivitiUserWorkflowAdapter
             throws WorkflowException {
 
         final Map<String, Object> variables = new HashMap<String, Object>();
+        variables.put(WF_EXECUTOR, EntitlementUtil.getAuthenticatedUsername());
         variables.put(USER_TO, userTO);
         variables.put(ENABLED, enabled);
 
-        final ProcessInstance processInstance;
+        ProcessInstance processInstance = null;
         try {
             processInstance = runtimeService.startProcessInstanceByKey(WF_PROCESS_ID, variables);
         } catch (ActivitiException e) {
-            throw new WorkflowException("While starting " + WF_PROCESS_ID + " instance", e);
+            throwException(e, "While starting " + WF_PROCESS_ID + " instance");
         }
 
-        SyncopeUser user = (SyncopeUser) runtimeService.getVariable(processInstance.getProcessInstanceId(),
-                SYNCOPE_USER);
+        SyncopeUser user = (SyncopeUser) runtimeService.getVariable(
+                processInstance.getProcessInstanceId(), SYNCOPE_USER);
 
-        Boolean updatedEnabled = (Boolean) runtimeService.getVariable(processInstance.getProcessInstanceId(), ENABLED);
+        Boolean updatedEnabled = (Boolean) runtimeService.getVariable(
+                processInstance.getProcessInstanceId(), ENABLED);
         if (updatedEnabled != null) {
             user.setSuspended(!updatedEnabled);
         }
@@ -237,28 +262,16 @@ public class ActivitiUserWorkflowAdapter
         updateStatus(user);
         user = userDAO.save(user);
 
-        Boolean propagateEnable = (Boolean) runtimeService.getVariable(processInstance.getProcessInstanceId(),
-                PROPAGATE_ENABLE);
+        Boolean propagateEnable = (Boolean) runtimeService.getVariable(
+                processInstance.getProcessInstanceId(), PROPAGATE_ENABLE);
         if (propagateEnable == null) {
             propagateEnable = enabled;
         }
 
-        // save resources to be propagated and password for later - after form submission - propagation
         PropagationByResource propByRes = new PropagationByResource();
         propByRes.set(ResourceOperation.CREATE, user.getResourceNames());
 
-        String formTaskId = getFormTask(user);
-        if (formTaskId != null) {
-            // SYNCOPE-238: This is needed to simplify the task query in this.getForms()
-            taskService.setVariableLocal(formTaskId, TASK_IS_FORM, Boolean.TRUE);
-            runtimeService.setVariable(processInstance.getProcessInstanceId(), PROP_BY_RESOURCE, propByRes);
-            propByRes = null;
-
-            if (StringUtils.isNotBlank(userTO.getPassword())) {
-                runtimeService.setVariable(
-                        processInstance.getProcessInstanceId(), ENCRYPTED_PWD, encrypt(userTO.getPassword()));
-            }
-        }
+        saveForFormSubmit(user, userTO.getPassword(), propByRes);
 
         return new WorkflowResult<Map.Entry<Long, Boolean>>(
                 new SimpleEntry<Long, Boolean>(user.getId(), propagateEnable), propByRes, getPerformedTasks(user));
@@ -270,9 +283,14 @@ public class ActivitiUserWorkflowAdapter
         Set<String> preTasks = getPerformedTasks(user);
 
         final Map<String, Object> variables = new HashMap<String, Object>();
-        variables.put(SYNCOPE_USER, user);
+        variables.put(WF_EXECUTOR, EntitlementUtil.getAuthenticatedUsername());
         variables.put(TASK, task);
 
+        // using BeanUtils to access all user's properties and trigger lazy loading - we are about to
+        // serialize a SyncopeUser instance for availability within workflow tasks, and this breaks transactions
+        BeanUtils.copyProperties(user, new SyncopeUser());
+        variables.put(SYNCOPE_USER, user);
+
         if (moreVariables != null && !moreVariables.isEmpty()) {
             variables.putAll(moreVariables);
         }
@@ -286,7 +304,7 @@ public class ActivitiUserWorkflowAdapter
             try {
                 taskService.complete(tasks.get(0).getId(), variables);
             } catch (ActivitiException e) {
-                throw new WorkflowException("While completing task '" + tasks.get(0).getName() + "' for " + user, e);
+                throwException(e, "While completing task '" + tasks.get(0).getName() + "' for " + user);
             }
         } else {
             LOG.warn("Expected a single task, found {}", tasks.size());
@@ -302,43 +320,36 @@ public class ActivitiUserWorkflowAdapter
     protected WorkflowResult<Long> doActivate(final SyncopeUser user, final String token)
             throws WorkflowException {
 
-        Set<String> performedTasks = doExecuteTask(user, "activate", Collections.singletonMap(TOKEN, (Object) token));
+        Set<String> tasks = doExecuteTask(user, "activate", Collections.singletonMap(TOKEN, (Object) token));
+
         updateStatus(user);
         SyncopeUser updated = userDAO.save(user);
 
-        return new WorkflowResult<Long>(updated.getId(), null, performedTasks);
+        return new WorkflowResult<Long>(updated.getId(), null, tasks);
     }
 
     @Override
-    protected WorkflowResult<Map.Entry<Long, Boolean>> doUpdate(final SyncopeUser user, final UserMod userMod)
+    protected WorkflowResult<Map.Entry<UserMod, Boolean>> doUpdate(final SyncopeUser user, final UserMod userMod)
             throws WorkflowException {
 
-        Set<String> task = doExecuteTask(user, "update", Collections.singletonMap(USER_MOD, (Object) userMod));
+        Set<String> tasks = doExecuteTask(user, "update", Collections.singletonMap(USER_MOD, (Object) userMod));
 
         updateStatus(user);
         SyncopeUser updated = userDAO.save(user);
 
-        PropagationByResource propByRes = (PropagationByResource) runtimeService.getVariable(user.getWorkflowId(),
-                PROP_BY_RESOURCE);
+        PropagationByResource propByRes = (PropagationByResource) runtimeService.getVariable(
+                user.getWorkflowId(), PROP_BY_RESOURCE);
 
-        // save resources to be propagated and password for later - after form submission - propagation
-        String formTaskId = getFormTask(user);
-        if (formTaskId != null) {
-            // SYNCOPE-238: This is needed to simplify the task query in this.getForms()
-            taskService.setVariableLocal(formTaskId, TASK_IS_FORM, Boolean.TRUE);
-            if (StringUtils.isNotBlank(userMod.getPassword())) {
-                runtimeService.setVariable(user.getWorkflowId(), ENCRYPTED_PWD, encrypt(userMod.getPassword()));
-            }
-        }
+        saveForFormSubmit(updated, userMod.getPassword(), propByRes);
 
         Boolean propagateEnable = (Boolean) runtimeService.getVariable(user.getWorkflowId(), PROPAGATE_ENABLE);
 
-        return new WorkflowResult<Map.Entry<Long, Boolean>>(new SimpleEntry<Long, Boolean>(
-                updated.getId(), propagateEnable), propByRes, task);
+        return new WorkflowResult<Map.Entry<UserMod, Boolean>>(
+                new SimpleEntry<UserMod, Boolean>(userMod, propagateEnable), propByRes, tasks);
     }
 
     @Override
-    @Transactional(rollbackFor = {Throwable.class})
+    @Transactional(rollbackFor = { Throwable.class })
     protected WorkflowResult<Long> doSuspend(final SyncopeUser user)
             throws WorkflowException {
 
@@ -366,12 +377,25 @@ public class ActivitiUserWorkflowAdapter
             throws WorkflowException {
 
         doExecuteTask(user, "delete", null);
-        userDAO.delete(user);
 
-        if (!historyService.createHistoricProcessInstanceQuery().
-                processInstanceId(user.getWorkflowId()).list().isEmpty()) {
+        PropagationByResource propByRes = new PropagationByResource();
+        propByRes.set(ResourceOperation.DELETE, user.getResourceNames());
+
+        saveForFormSubmit(user, null, propByRes);
+
+        if (runtimeService.createProcessInstanceQuery().
+                processInstanceId(user.getWorkflowId()).active().list().isEmpty()) {
+
+            userDAO.delete(user.getId());
+
+            if (!historyService.createHistoricProcessInstanceQuery().
+                    processInstanceId(user.getWorkflowId()).list().isEmpty()) {
 
-            historyService.deleteHistoricProcessInstance(user.getWorkflowId());
+                historyService.deleteHistoricProcessInstance(user.getWorkflowId());
+            }
+        } else {
+            updateStatus(user);
+            userDAO.save(user);
         }
     }
 
@@ -522,7 +546,8 @@ public class ActivitiUserWorkflowAdapter
             }
         }
 
-        final WorkflowFormTO formTO = getHFormTO(task.getProcessInstanceId(), task.getId(), task.getFormKey(), props);
+        final WorkflowFormTO formTO = getHistoricFormTO(
+                task.getProcessInstanceId(), task.getId(), task.getFormKey(), props);
         BeanUtils.copyProperties(task, formTO);
 
         final HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().
@@ -536,8 +561,7 @@ public class ActivitiUserWorkflowAdapter
         return formTO;
     }
 
-    @SuppressWarnings("unchecked")
-    private WorkflowFormTO getHFormTO(
+    private WorkflowFormTO getHistoricFormTO(
             final String processInstanceId,
             final String taskId,
             final String formKey,
@@ -717,7 +741,7 @@ public class ActivitiUserWorkflowAdapter
     }
 
     @Override
-    public WorkflowResult<Map.Entry<Long, String>> submitForm(final WorkflowFormTO form, final String username)
+    public WorkflowResult<UserMod> submitForm(final WorkflowFormTO form, final String username)
             throws WorkflowException {
 
         Map.Entry<Task, TaskFormData> checked = checkTask(form.getTaskId(), username);
@@ -736,7 +760,7 @@ public class ActivitiUserWorkflowAdapter
         try {
             formService.submitTaskFormData(form.getTaskId(), form.getPropertiesForSubmit());
         } catch (ActivitiException e) {
-            throw new WorkflowException("While submitting form for task " + form.getTaskId(), e);
+            throwException(e, "While submitting form for task " + form.getTaskId());
         }
 
         Set<String> postTasks = getPerformedTasks(user);
@@ -750,14 +774,20 @@ public class ActivitiUserWorkflowAdapter
         PropagationByResource propByRes =
                 (PropagationByResource) runtimeService.getVariable(user.getWorkflowId(), PROP_BY_RESOURCE);
 
-        // fetch - if available - the encrpted password
+        // fetch - if available - the encrypted password
         String clearPassword = null;
         String encryptedPwd = (String) runtimeService.getVariable(user.getWorkflowId(), ENCRYPTED_PWD);
         if (StringUtils.isNotBlank(encryptedPwd)) {
             clearPassword = decrypt(encryptedPwd);
         }
 
-        return new WorkflowResult<Map.Entry<Long, String>>(new SimpleEntry<Long, String>(updated.getId(),
-                clearPassword), propByRes, postTasks);
+        UserMod userMod = (UserMod) runtimeService.getVariable(user.getWorkflowId(), USER_MOD);
+        if (userMod == null) {
+            userMod = new UserMod();
+            userMod.setId(updated.getId());
+            userMod.setPassword(clearPassword);
+        }
+
+        return new WorkflowResult<UserMod>(userMod, propByRes, postTasks);
     }
 }

Copied: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiServiceTask.java (from r1538533, syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiDelegate.java)
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiServiceTask.java?p2=syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiServiceTask.java&p1=syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiDelegate.java&r1=1538533&r2=1539376&rev=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiDelegate.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AbstractActivitiServiceTask.java Wed Nov  6 15:57:28 2013
@@ -18,44 +18,31 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.TaskService;
-import org.activiti.engine.delegate.DelegateExecution;
-import org.activiti.engine.delegate.JavaDelegate;
-import org.apache.syncope.core.persistence.dao.ConfDAO;
-import org.apache.syncope.core.rest.data.UserDataBinder;
-import org.apache.syncope.core.util.ApplicationContextProvider;
+import org.activiti.engine.RuntimeService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
- * Abstract base class for Activiti's JavaDelegate implementations in Syncope.
+ * Abstract base class for Activiti's service tasks in Syncope, with Spring support.
  */
-public abstract class AbstractActivitiDelegate implements JavaDelegate {
+@Component
+public abstract class AbstractActivitiServiceTask {
 
     /**
      * Logger.
      */
-    protected static final Logger LOG = LoggerFactory.getLogger(AbstractActivitiDelegate.class);
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractActivitiServiceTask.class);
 
-    protected static final ConfigurableApplicationContext CONTEXT = ApplicationContextProvider.getApplicationContext();
+    @Autowired
+    protected RuntimeService runtimeService;
 
-    protected TaskService taskService;
-
-    protected UserDataBinder dataBinder;
-
-    protected ConfDAO confDAO;
-
-    @Override
-    public final void execute(final DelegateExecution execution) throws Exception {
-
-        taskService = CONTEXT.getBean(TaskService.class);
-
-        dataBinder = CONTEXT.getBean(UserDataBinder.class);
-        confDAO = CONTEXT.getBean(ConfDAO.class);
-
-        doExecute(execution);
+    @Transactional(rollbackFor = { Throwable.class })
+    public void execute(final String executionId) {
+        doExecute(executionId);
     }
 
-    protected abstract void doExecute(DelegateExecution execution) throws Exception;
+    protected abstract void doExecute(final String executionId);
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AutoActivate.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AutoActivate.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AutoActivate.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/AutoActivate.java Wed Nov  6 15:57:28 2013
@@ -18,13 +18,14 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
 import org.apache.syncope.core.workflow.user.activiti.ActivitiUserWorkflowAdapter;
+import org.springframework.stereotype.Component;
 
-public class AutoActivate extends AbstractActivitiDelegate {
+@Component
+public class AutoActivate extends AbstractActivitiServiceTask {
 
     @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
-        execution.setVariable(ActivitiUserWorkflowAdapter.PROPAGATE_ENABLE, Boolean.TRUE);
+    protected void doExecute(final String executionId) {
+        runtimeService.setVariable(executionId, ActivitiUserWorkflowAdapter.PROPAGATE_ENABLE, Boolean.TRUE);
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Create.java Wed Nov  6 15:57:28 2013
@@ -18,24 +18,29 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.rest.data.UserDataBinder;
 import org.apache.syncope.core.workflow.user.activiti.ActivitiUserWorkflowAdapter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
-public class Create extends AbstractActivitiDelegate {
+@Component
+public class Create extends AbstractActivitiServiceTask {
 
-    @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
+    @Autowired
+    private UserDataBinder dataBinder;
 
-        UserTO userTO = (UserTO) execution.getVariable(ActivitiUserWorkflowAdapter.USER_TO);
+    @Override
+    protected void doExecute(final String executionId) {
+        UserTO userTO = (UserTO) runtimeService.getVariable(executionId, ActivitiUserWorkflowAdapter.USER_TO);
 
         // create and set workflow id
         SyncopeUser user = new SyncopeUser();
         dataBinder.create(user, userTO);
-        user.setWorkflowId(execution.getProcessInstanceId());
+        user.setWorkflowId(executionId);
 
         // report SyncopeUser as result
-        execution.setVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER, user);
+        runtimeService.setVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER, user);
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Delete.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Delete.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Delete.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Delete.java Wed Nov  6 15:57:28 2013
@@ -18,23 +18,24 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.workflow.user.activiti.ActivitiUserWorkflowAdapter;
+import org.springframework.stereotype.Component;
 
-public class Delete extends AbstractActivitiDelegate {
+@Component
+public class Delete extends AbstractActivitiServiceTask {
 
     @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
+    protected void doExecute(final String executionId) {
+        SyncopeUser user =
+                (SyncopeUser) runtimeService.getVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER);
 
-        SyncopeUser user = (SyncopeUser) execution.getVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER);
-
-        // TODO: do something with SyncopeUser...
+        // Do something with SyncopeUser...
         if (user != null) {
             user.checkToken("");
         }
 
         // remove SyncopeUser variable
-        execution.removeVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER);
+        runtimeService.removeVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER);
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/GenerateToken.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/GenerateToken.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/GenerateToken.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/GenerateToken.java Wed Nov  6 15:57:28 2013
@@ -18,20 +18,27 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.persistence.dao.ConfDAO;
 import org.apache.syncope.core.workflow.user.activiti.ActivitiUserWorkflowAdapter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
-public class GenerateToken extends AbstractActivitiDelegate {
+@Component
+public class GenerateToken extends AbstractActivitiServiceTask {
+
+    @Autowired
+    private ConfDAO confDAO;
 
     @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
-        SyncopeUser user = (SyncopeUser) execution.getVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER);
+    protected void doExecute(final String executionId) {
+        SyncopeUser user =
+                (SyncopeUser) runtimeService.getVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER);
 
         user.generateToken(
                 Integer.parseInt(confDAO.find("token.length", "256").getValue()),
                 Integer.parseInt(confDAO.find("token.expireTime", "60").getValue()));
 
-        execution.setVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER, user);
+        runtimeService.setVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER, user);
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Reactivate.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Reactivate.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Reactivate.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Reactivate.java Wed Nov  6 15:57:28 2013
@@ -18,11 +18,12 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
 
-public class Reactivate extends AbstractActivitiDelegate {
+@Component
+public class Reactivate extends AbstractActivitiServiceTask {
 
     @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
+    protected void doExecute(final String executionId) {
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Suspend.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Suspend.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Suspend.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Suspend.java Wed Nov  6 15:57:28 2013
@@ -18,11 +18,12 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
 
-public class Suspend extends AbstractActivitiDelegate {
+@Component
+public class Suspend extends AbstractActivitiServiceTask {
 
     @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
+    protected void doExecute(final String executionId) {
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Update.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Update.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Update.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/task/Update.java Wed Nov  6 15:57:28 2013
@@ -18,24 +18,38 @@
  */
 package org.apache.syncope.core.workflow.user.activiti.task;
 
-import org.activiti.engine.delegate.DelegateExecution;
+import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.mod.UserMod;
 import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
 import org.apache.syncope.core.propagation.PropagationByResource;
+import org.apache.syncope.core.rest.data.UserDataBinder;
 import org.apache.syncope.core.workflow.user.activiti.ActivitiUserWorkflowAdapter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
-public class Update extends AbstractActivitiDelegate {
+@Component
+public class Update extends AbstractActivitiServiceTask {
+
+    @Autowired
+    private UserDataBinder dataBinder;
 
     @Override
-    protected void doExecute(final DelegateExecution execution) throws Exception {
-        SyncopeUser user = (SyncopeUser) execution.getVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER);
-        UserMod userMod = (UserMod) execution.getVariable(ActivitiUserWorkflowAdapter.USER_MOD);
+    protected void doExecute(final String executionId) {
+        SyncopeUser user =
+                (SyncopeUser) runtimeService.getVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER);
+        UserMod userMod =
+                (UserMod) runtimeService.getVariable(executionId, ActivitiUserWorkflowAdapter.USER_MOD);
 
+        // update password internally only if required
+        UserMod actualMod = SerializationUtils.clone(userMod);
+        if (actualMod.getPwdPropRequest() != null && !actualMod.getPwdPropRequest().isOnSyncope()) {
+            actualMod.setPassword(null);
+        }
         // update SyncopeUser
-        PropagationByResource propByRes = dataBinder.update(user, userMod);
+        PropagationByResource propByRes = dataBinder.update(user, actualMod);
 
         // report updated user and propagation by resource as result
-        execution.setVariable(ActivitiUserWorkflowAdapter.SYNCOPE_USER, user);
-        execution.setVariable(ActivitiUserWorkflowAdapter.PROP_BY_RESOURCE, propByRes);
+        runtimeService.setVariable(executionId, ActivitiUserWorkflowAdapter.SYNCOPE_USER, user);
+        runtimeService.setVariable(executionId, ActivitiUserWorkflowAdapter.PROP_BY_RESOURCE, propByRes);
     }
 }

Modified: syncope/trunk/core/src/main/resources/content.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/content.xml?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/content.xml (original)
+++ syncope/trunk/core/src/main/resources/content.xml Wed Nov  6 15:57:28 2013
@@ -28,7 +28,7 @@ under the License.
   <SyncopeConf confKey="notificationjob.cronExpression" confValue=""/>
   <SyncopeConf confKey="token.length" confValue="256"/>
   <SyncopeConf confKey="token.expireTime" confValue="60"/>
-  <SyncopeConf confKey="createRequest.allowed" confValue="true"/>
+  <SyncopeConf confKey="selfRegistration.allowed" confValue="true"/>
   <SyncopeConf confKey="notification.maxRetries" confValue="0"/>
     
   <!-- Authentication and authorization -->
@@ -88,11 +88,6 @@ under the License.
   <Entitlement name="NOTIFICATION_READ"/>
   <Entitlement name="NOTIFICATION_UPDATE"/>
   <Entitlement name="NOTIFICATION_DELETE"/>
-  <Entitlement name="USER_REQUEST_LIST"/>
-  <Entitlement name="USER_REQUEST_READ"/>
-  <Entitlement name="USER_REQUEST_DELETE"/>
-  <Entitlement name="USER_REQUEST_EXECUTE"/>
-  <Entitlement name="USER_REQUEST_CLAIM"/>
   <Entitlement name="REPORT_LIST"/>
   <Entitlement name="REPORT_READ"/>
   <Entitlement name="REPORT_CREATE"/>

Modified: syncope/trunk/core/src/main/resources/restContext.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/restContext.xml?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/restContext.xml (original)
+++ syncope/trunk/core/src/main/resources/restContext.xml Wed Nov  6 15:57:28 2013
@@ -97,8 +97,8 @@ under the License.
       <ref bean="roleServiceImpl"/>
       <ref bean="schemaServiceImpl"/>
       <ref bean="taskServiceImpl"/>
-      <ref bean="userRequestServiceImpl"/>
       <ref bean="userServiceImpl"/>
+      <ref bean="userSelfServiceImpl"/>
       <ref bean="workflowServiceImpl"/>
       <ref bean="userWorkflowServiceImpl"/>
     </jaxrs:serviceBeans>

Modified: syncope/trunk/core/src/main/resources/securityContext.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/securityContext.xml?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/securityContext.xml (original)
+++ syncope/trunk/core/src/main/resources/securityContext.xml Wed Nov  6 15:57:28 2013
@@ -42,6 +42,7 @@ under the License.
 
   <security:http security-context-repository-ref="securityContextRepository" realm="Apache Syncope authentication">
     <security:http-basic/>
+    <security:anonymous username="${anonymousUser}"/>
     <security:intercept-url pattern="/**"/>
   </security:http>
 

Modified: syncope/trunk/core/src/main/resources/userWorkflow.bpmn20.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/userWorkflow.bpmn20.xml?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/userWorkflow.bpmn20.xml (original)
+++ syncope/trunk/core/src/main/resources/userWorkflow.bpmn20.xml Wed Nov  6 15:57:28 2013
@@ -35,18 +35,17 @@ under the License.
     <!-- Create an user -->
     <sequenceFlow id="flow1" sourceRef="theStart" targetRef="create"/>
       
-    <serviceTask id="create" name="Create" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.Create"/>
+    <serviceTask id="create" name="Create" activiti:expression="#{create.execute(execution.processInstanceId)}"/>
 
     <sequenceFlow id="flow2" sourceRef="create" targetRef="createGW"/>
         
     <exclusiveGateway id="createGW"/>
+    <sequenceFlow id="createAsAnonymous2Approval" sourceRef="createGW" targetRef="createApproval">
+      <conditionExpression xsi:type="tFormalExpression">${wfExecutor == 'anonymous' || syncopeUser.getRoleIds().contains(9)}</conditionExpression>
+    </sequenceFlow>
     <sequenceFlow id="create2Activate" sourceRef="createGW" targetRef="enableGW">
       <conditionExpression xsi:type="tFormalExpression">${!syncopeUser.getRoleIds().contains(9)}</conditionExpression>
     </sequenceFlow>
-    <sequenceFlow id="create2CreateApproval" sourceRef="createGW" targetRef="createApproval">
-      <conditionExpression xsi:type="tFormalExpression">${syncopeUser.getRoleIds().contains(9)}</conditionExpression>
-    </sequenceFlow>
         
     <userTask id="createApproval" activiti:formKey="createApproval" name="Create approval" activiti:candidateGroups="7">
       <extensionElements>
@@ -73,7 +72,7 @@ under the License.
     </sequenceFlow>
     <!-- activate user if suspension is not required -->
     <sequenceFlow id="createApprovalGW2Activate" sourceRef="enableGW" targetRef="activate">
-      <conditionExpression xsi:type="tFormalExpression">${enabled==null}</conditionExpression>
+      <conditionExpression xsi:type="tFormalExpression">${enabled == null}</conditionExpression>
     </sequenceFlow>
     <sequenceFlow id="createApprovalGW2Active" sourceRef="enableGW" targetRef="active">
       <conditionExpression xsi:type="tFormalExpression">${enabled}</conditionExpression>
@@ -83,12 +82,12 @@ under the License.
     </sequenceFlow>
     
     <serviceTask id="activate" name="Activate" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.AutoActivate"/>
+                 activiti:expression="#{autoActivate.execute(execution.processInstanceId)}"/>
     <sequenceFlow id="flow4" sourceRef="activate" targetRef="active"/>
 
     <!-- Double opt-in required -->
     <serviceTask id="generateToken" name="Generate token" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.GenerateToken"/>
+                 activiti:expression="#{generateToken.execute(execution.processInstanceId)}"/>
         
     <sequenceFlow id="flow5" sourceRef="generateToken" targetRef="created"/>
 
@@ -117,6 +116,15 @@ under the License.
     <sequenceFlow id="flow8" sourceRef="active" targetRef="activeGw"/>
 
     <exclusiveGateway id="activeGw"/>
+    <sequenceFlow id="active2UpdateApproval" sourceRef="activeGw" targetRef="updateApproval">
+      <conditionExpression xsi:type="tFormalExpression">
+        ${wfExecutor == syncopeUser.getUsername() and task == 'update' 
+        and (!userMod.getMembershipsToAdd().isEmpty() or !userMod.getMembershipsToRemove().isEmpty())}
+      </conditionExpression>
+    </sequenceFlow>  
+    <sequenceFlow id="active2DeleteApproval" sourceRef="activeGw" targetRef="deleteApproval">
+      <conditionExpression xsi:type="tFormalExpression">${wfExecutor == syncopeUser.getUsername() and task == 'delete'}</conditionExpression>
+    </sequenceFlow>  
     <sequenceFlow id="active2Update" sourceRef="activeGw" targetRef="update">
       <conditionExpression xsi:type="tFormalExpression">${task == 'update'}</conditionExpression>
     </sequenceFlow>  
@@ -127,15 +135,39 @@ under the License.
       <conditionExpression xsi:type="tFormalExpression">${task == 'delete'}</conditionExpression>
     </sequenceFlow>
 
+    <userTask id="updateApproval" activiti:formKey="updateApproval" name="Update approval" activiti:candidateGroups="7">
+      <extensionElements>
+        <activiti:formProperty id="username" name="Username" type="string" writable="false" expression="${syncopeUser.username}"/>
+        <activiti:formProperty id="approve" variable="approve" name="Approve?" type="boolean" required="true"/>
+        <activiti:formProperty id="rejectReason" variable="rejectReason" name="Reason for rejecting" type="string"/>
+      </extensionElements>
+    </userTask>
+
+    <sequenceFlow id="flow8bis" sourceRef="updateApproval" targetRef="updateApprovalGW"/>
+        
+    <exclusiveGateway id="updateApprovalGW"/>
+    <sequenceFlow id="updateApprovalGW2Update" sourceRef="updateApprovalGW" targetRef="update">
+      <conditionExpression xsi:type="tFormalExpression">${approve}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="updateApprovalGW2Reject" sourceRef="updateApprovalGW" targetRef="rejectUpdate">
+      <conditionExpression xsi:type="tFormalExpression">${!approve}</conditionExpression>
+    </sequenceFlow>
+
+    <scriptTask id="rejectUpdate" name="Reject update" scriptFormat="groovy">
+      <script>
+        execution.setVariable("propByResource", null);
+      </script>
+    </scriptTask>
+        
+    <sequenceFlow id="flow8ter" sourceRef="rejectUpdate" targetRef="active"/>
+
     <!-- Update an active user -->
-    <serviceTask id="update" name="Update" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.Update"/>
+    <serviceTask id="update" name="Update" activiti:expression="#{update.execute(execution.processInstanceId)}"/>
 
     <sequenceFlow id="flow9" sourceRef="update" targetRef="active"/>
 
     <!-- Suspend an active user -->
-    <serviceTask id="suspend" name="Suspend" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.Suspend"/>
+    <serviceTask id="suspend" name="Suspend" activiti:expression="#{suspend.execute(execution.processInstanceId)}"/>
 
     <sequenceFlow id="flow10" sourceRef="suspend" targetRef="suspended"/>
 
@@ -153,7 +185,7 @@ under the License.
 
     <!-- Reactivate a suspended user -->
     <serviceTask id="reactivate" name ="Reactivate" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.Reactivate"/>
+                 activiti:expression="#{reactivate.execute(execution.processInstanceId)}"/>
 
     <sequenceFlow id="flow12" sourceRef="reactivate" targetRef="active"/>
         
@@ -180,9 +212,34 @@ under the License.
       <conditionExpression xsi:type="tFormalExpression">${empty task}</conditionExpression>
     </sequenceFlow>
     
+    <userTask id="deleteApproval" activiti:formKey="deleteApproval" name="Delete approval" activiti:candidateGroups="7">
+      <extensionElements>
+        <activiti:formProperty id="username" name="Username" type="string" writable="false" expression="${syncopeUser.username}"/>
+        <activiti:formProperty id="approve" variable="approve" name="Approve?" type="boolean" required="true"/>
+        <activiti:formProperty id="rejectReason" variable="rejectReason" name="Reason for rejecting" type="string"/>
+      </extensionElements>
+    </userTask>
+
+    <sequenceFlow id="flow14bis" sourceRef="deleteApproval" targetRef="deleteApprovalGW"/>
+        
+    <exclusiveGateway id="deleteApprovalGW"/>
+    <sequenceFlow id="deleteApprovalGW2Delete" sourceRef="deleteApprovalGW" targetRef="delete">
+      <conditionExpression xsi:type="tFormalExpression">${approve}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="deleteApprovalGW2Reject" sourceRef="deleteApprovalGW" targetRef="rejectDelete">
+      <conditionExpression xsi:type="tFormalExpression">${!approve}</conditionExpression>
+    </sequenceFlow>
+    
+    <scriptTask id="rejectDelete" name="Reject delete" scriptFormat="groovy">
+      <script>
+        execution.setVariable("propByResource", null);
+      </script>
+    </scriptTask>
+        
+    <sequenceFlow id="flow14ter" sourceRef="rejectDelete" targetRef="active"/>
+    
     <!-- Delete an user (created, active or suspended) -->
-    <serviceTask id="delete" name="Delete" 
-                 activiti:class="org.apache.syncope.core.workflow.user.activiti.task.Delete"/>
+    <serviceTask id="delete" name="Delete" activiti:expression="#{delete.execute(execution.processInstanceId)}"/>
 
     <sequenceFlow id="flow99" sourceRef="delete" targetRef="theEnd"/>
 

Modified: syncope/trunk/core/src/main/resources/workflowContext.xml
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/resources/workflowContext.xml?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/main/resources/workflowContext.xml (original)
+++ syncope/trunk/core/src/main/resources/workflowContext.xml Wed Nov  6 15:57:28 2013
@@ -19,8 +19,11 @@ under the License.
 -->
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans   
-                           http://www.springframework.org/schema/beans/spring-beans.xsd">
+                           http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context
+                           http://www.springframework.org/schema/context/spring-context.xsd">
 
   <bean id="uwfAdapter" class="${uwfAdapter}"/>
   <bean id="rwfAdapter" class="${rwfAdapter}"/>
@@ -69,6 +72,8 @@ under the License.
   <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
   <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
 
+  <context:component-scan base-package="org.apache.syncope.core.workflow.user.activiti.task"/>
+  
   <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
     <property name="velocityProperties">
       <value>

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/EntitlementTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/EntitlementTest.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/EntitlementTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/EntitlementTest.java Wed Nov  6 15:57:28 2013
@@ -41,7 +41,7 @@ public class EntitlementTest extends Abs
     @Test
     public void findAll() {
         List<Entitlement> list = entitlementDAO.findAll();
-        assertEquals("did not get expected number of entitlements ", 89, list.size());
+        assertEquals("did not get expected number of entitlements ", 84, list.size());
     }
 
     @Test

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/RoleTest.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/RoleTest.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/RoleTest.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/relationships/RoleTest.java Wed Nov  6 15:57:28 2013
@@ -103,7 +103,7 @@ public class RoleTest extends AbstractDA
         assertNotNull(child2);
         assertEquals(role, child2.getParent());
 
-        List<SyncopeRole> ownedRoles = roleDAO.findOwned(user);
+        List<SyncopeRole> ownedRoles = roleDAO.findOwnedByUser(user.getId());
         assertFalse(ownedRoles.isEmpty());
         assertEquals(2, ownedRoles.size());
         assertTrue(ownedRoles.contains(role));

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=1539376&r1=1539375&r2=1539376&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 Nov  6 15:57:28 2013
@@ -46,7 +46,7 @@ import org.apache.syncope.common.service
 import org.apache.syncope.common.services.RoleService;
 import org.apache.syncope.common.services.SchemaService;
 import org.apache.syncope.common.services.TaskService;
-import org.apache.syncope.common.services.UserRequestService;
+import org.apache.syncope.common.services.UserSelfService;
 import org.apache.syncope.common.services.UserService;
 import org.apache.syncope.common.services.UserWorkflowService;
 import org.apache.syncope.common.services.WorkflowService;
@@ -87,6 +87,12 @@ public abstract class AbstractTest {
 
     protected static final SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
 
+    protected static final String RESOURCE_NAME_LDAP = "resource-ldap";
+
+    protected static final String RESOURCE_NAME_TESTDB = "resource-testdb";
+
+    protected static final String RESOURCE_NAME_CSV = "resource-csv";
+
     protected static String ANONYMOUS_UNAME;
 
     protected static String ANONYMOUS_KEY;
@@ -95,6 +101,8 @@ public abstract class AbstractTest {
 
     protected static UserService userService;
 
+    protected static UserSelfService userSelfService;
+
     protected static UserWorkflowService userWorkflowService;
 
     protected static RoleService roleService;
@@ -119,8 +127,6 @@ public abstract class AbstractTest {
 
     protected static SchemaService schemaService;
 
-    protected static UserRequestService userRequestService;
-
     protected static PolicyService policyService;
 
     @Autowired
@@ -157,6 +163,7 @@ public abstract class AbstractTest {
         adminClient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
 
         userService = adminClient.getService(UserService.class);
+        userSelfService = adminClient.getService(UserSelfService.class);
         userWorkflowService = adminClient.getService(UserWorkflowService.class);
         roleService = adminClient.getService(RoleService.class);
         resourceService = adminClient.getService(ResourceService.class);
@@ -170,7 +177,6 @@ public abstract class AbstractTest {
         workflowService = adminClient.getService(WorkflowService.class);
         notificationService = adminClient.getService(NotificationService.class);
         schemaService = adminClient.getService(SchemaService.class);
-        userRequestService = adminClient.getService(UserRequestService.class);
     }
 
     protected static String getUUIDString() {

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/AuthenticationTestITCase.java Wed Nov  6 15:57:28 2013
@@ -57,6 +57,22 @@ import org.junit.runners.MethodSorters;
 @FixMethodOrder(MethodSorters.JVM)
 public class AuthenticationTestITCase extends AbstractTest {
 
+    private int getFailedLogins(UserService testUserService, long userId) {
+        UserTO readUserTO = testUserService.read(userId);
+        assertNotNull(readUserTO);
+        assertNotNull(readUserTO.getFailedLogins());
+        return readUserTO.getFailedLogins();
+    }
+
+    private void assertReadFails(UserService userService, long id) {
+        try {
+            userService.read(id);
+            fail("access should not work");
+        } catch (Exception e) {
+            assertNotNull(e);
+        }
+    }
+
     @Test
     public void testAdminEntitlements() {
         // 1. as anonymous, read all available entitlements
@@ -260,8 +276,8 @@ public class AuthenticationTestITCase ex
         long userId = userTO.getId();
         assertNotNull(userTO);
 
-        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").getService(
-                UserService.class);
+        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
+                getService(UserService.class);
         assertEquals(0, getFailedLogins(userService2, userId));
 
         // authentications failed ...
@@ -274,11 +290,9 @@ public class AuthenticationTestITCase ex
         assertEquals(3, getFailedLogins(userService, userId));
 
         // last authentication before suspension
-        userService3 = clientFactory.create(userTO.getUsername(), "wrongpwd1").getService(UserService.class);
         assertReadFails(userService3, userId);
 
         userTO = userService.read(userTO.getId());
-
         assertNotNull(userTO);
         assertNotNull(userTO.getFailedLogins());
         assertEquals(Integer.valueOf(3), userTO.getFailedLogins());
@@ -342,20 +356,4 @@ public class AuthenticationTestITCase ex
         role1User = response.readEntity(UserTO.class);
         assertNotNull(role1User);
     }
-
-    private int getFailedLogins(UserService testUserService, long userId) {
-        UserTO readUserTO = testUserService.read(userId);
-        assertNotNull(readUserTO);
-        assertNotNull(readUserTO.getFailedLogins());
-        return readUserTO.getFailedLogins();
-    }
-
-    private void assertReadFails(UserService userService, long id) {
-        try {
-            userService.read(id);
-            fail("access should not work");
-        } catch (Exception e) {
-            assertNotNull(e);
-        }
-    }
 }

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=1539376&r1=1539375&r2=1539376&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 Wed Nov  6 15:57:28 2013
@@ -532,7 +532,7 @@ public class ResourceTestITCase extends 
 
     @Test
     public void anonymous() {
-        ResourceService unauthenticated = clientFactory.create(null, null).getService(ResourceService.class);
+        ResourceService unauthenticated = clientFactory.createAnonymous().getService(ResourceService.class);
         try {
             unauthenticated.list();
             fail();

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=1539376&r1=1539375&r2=1539376&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 Nov  6 15:57:28 2013
@@ -503,7 +503,7 @@ public class RoleTestITCase extends Abst
 
     @Test
     public void anonymous() {
-        RoleService unauthenticated = clientFactory.create(null, null).getService(RoleService.class);
+        RoleService unauthenticated = clientFactory.createAnonymous().getService(RoleService.class);
         try {
             unauthenticated.list();
             fail();

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java?rev=1539376&r1=1539375&r2=1539376&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java Wed Nov  6 15:57:28 2013
@@ -284,7 +284,7 @@ public class SchemaTestITCase extends Ab
 
     @Test
     public void anonymous() {
-        SchemaService unauthenticated = clientFactory.create(null, null).getService(SchemaService.class);
+        SchemaService unauthenticated = clientFactory.createAnonymous().getService(SchemaService.class);
         try {
             unauthenticated.list(AttributableType.USER, SchemaType.VIRTUAL);
             fail();

Added: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java?rev=1539376&view=auto
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java (added)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java Wed Nov  6 15:57:28 2013
@@ -0,0 +1,222 @@
+/*
+ * 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.core.rest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.security.AccessControlException;
+import java.util.Map;
+import org.apache.syncope.client.SyncopeClient;
+import org.apache.syncope.common.mod.AttributeMod;
+import org.apache.syncope.common.mod.MembershipMod;
+import org.apache.syncope.common.mod.StatusMod;
+import org.apache.syncope.common.mod.UserMod;
+import org.apache.syncope.common.services.UserSelfService;
+import org.apache.syncope.common.services.UserService;
+import org.apache.syncope.common.to.MembershipTO;
+import org.apache.syncope.common.to.UserTO;
+import org.apache.syncope.common.to.WorkflowFormPropertyTO;
+import org.apache.syncope.common.to.WorkflowFormTO;
+import org.apache.syncope.common.types.AttributableType;
+import org.apache.syncope.common.types.ClientExceptionType;
+import org.apache.syncope.common.validation.SyncopeClientException;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class UserSelfTestITCase extends AbstractTest {
+
+    @Test
+    public void selfRegistrationAllowed() {
+        assertTrue(clientFactory.createAnonymous().isSelfRegistrationAllowed());
+    }
+
+    @Test
+    public void create() {
+        // 1. self-registration as admin: failure
+        try {
+            userSelfService.create(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"));
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        // 2. self-registration as anonymous: works
+        SyncopeClient anonClient = clientFactory.createAnonymous();
+        UserTO self = anonClient.getService(UserSelfService.class).
+                create(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org")).
+                readEntity(UserTO.class);
+        assertNotNull(self);
+        assertEquals("createApproval", self.getStatus());
+    }
+
+    @Test
+    public void createAndApprove() {
+        // self-create user with membership: goes 'createApproval' with resources and membership but no propagation
+        UserTO userTO = UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org");
+        MembershipTO membership = new MembershipTO();
+        membership.setRoleId(3L);
+        userTO.getMemberships().add(membership);
+        userTO.getResources().add(RESOURCE_NAME_TESTDB);
+
+        SyncopeClient anonClient = clientFactory.createAnonymous();
+        userTO = anonClient.getService(UserSelfService.class).
+                create(userTO).
+                readEntity(UserTO.class);
+        assertNotNull(userTO);
+        assertEquals("createApproval", userTO.getStatus());
+        assertFalse(userTO.getMemberships().isEmpty());
+        assertFalse(userTO.getResources().isEmpty());
+
+        try {
+            resourceService.getConnectorObject(RESOURCE_NAME_TESTDB, AttributableType.USER, userTO.getId());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+
+        // now approve and verify that propagation has happened
+        WorkflowFormTO form = userWorkflowService.getFormForUser(userTO.getId());
+        form = userWorkflowService.claimForm(form.getTaskId());
+        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
+        props.get("approve").setValue(Boolean.TRUE.toString());
+        form.setProperties(props.values());
+        userTO = userWorkflowService.submitForm(form);
+        assertNotNull(userTO);
+        assertEquals("active", userTO.getStatus());
+        assertNotNull(resourceService.getConnectorObject(RESOURCE_NAME_TESTDB, AttributableType.USER, userTO.getId()));
+    }
+
+    @Test
+    public void read() {
+        UserService userService2 = clientFactory.create("rossini", ADMIN_PWD).getService(UserService.class);
+
+        try {
+            userService2.read(1L);
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        UserSelfService userSelfService2 = clientFactory.create("rossini", ADMIN_PWD).getService(UserSelfService.class);
+        UserTO userTO = userSelfService2.read();
+        assertEquals("rossini", userTO.getUsername());
+    }
+
+    @Test
+    public void updateWithoutApproval() {
+        // 1. create user as admin
+        UserTO created = createUser(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"));
+        assertNotNull(created);
+        assertFalse(created.getUsername().endsWith("XX"));
+
+        // 2. self-update (username) - works
+        UserMod userMod = new UserMod();
+        userMod.setUsername(created.getUsername() + "XX");
+
+        SyncopeClient authClient = clientFactory.create(created.getUsername(), "password123");
+        UserTO updated = authClient.getService(UserSelfService.class).update(created.getId(), userMod).
+                readEntity(UserTO.class);
+        assertNotNull(updated);
+        assertEquals("active", updated.getStatus());
+        assertTrue(updated.getUsername().endsWith("XX"));
+    }
+
+    @Test
+    public void updateWitApproval() {
+        // 1. create user as admin
+        UserTO created = createUser(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"));
+        assertNotNull(created);
+        assertFalse(created.getUsername().endsWith("XX"));
+
+        // 2. self-update (username + memberships + resource) - works but needs approval
+        MembershipMod membershipMod = new MembershipMod();
+        membershipMod.setRole(7L);
+        AttributeMod testAttributeMod = new AttributeMod();
+        testAttributeMod.setSchema("testAttribute");
+        testAttributeMod.getValuesToBeAdded().add("a value");
+        membershipMod.getAttrsToUpdate().add(testAttributeMod);
+
+        UserMod userMod = new UserMod();
+        userMod.setUsername(created.getUsername() + "XX");
+        userMod.getMembershipsToAdd().add(membershipMod);
+        userMod.getResourcesToAdd().add(RESOURCE_NAME_TESTDB);
+        userMod.setPassword("newPassword123");
+        StatusMod statusMod = new StatusMod();
+        statusMod.setOnSyncope(false);
+        statusMod.getResourceNames().add(RESOURCE_NAME_TESTDB);
+        userMod.setPwdPropRequest(statusMod);
+
+        SyncopeClient authClient = clientFactory.create(created.getUsername(), "password123");
+        UserTO updated = authClient.getService(UserSelfService.class).update(created.getId(), userMod).
+                readEntity(UserTO.class);
+        assertNotNull(updated);
+        assertEquals("updateApproval", updated.getStatus());
+        assertFalse(updated.getUsername().endsWith("XX"));
+        assertTrue(updated.getMemberships().isEmpty());
+
+        // no propagation happened
+        assertTrue(updated.getResources().isEmpty());
+        try {
+            resourceService.getConnectorObject(RESOURCE_NAME_TESTDB, AttributableType.USER, updated.getId());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+
+        // 3. approve self-update as admin
+        WorkflowFormTO form = userWorkflowService.getFormForUser(updated.getId());
+        form = userWorkflowService.claimForm(form.getTaskId());
+        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
+        props.get("approve").setValue(Boolean.TRUE.toString());
+        form.setProperties(props.values());
+        updated = userWorkflowService.submitForm(form);
+        assertNotNull(updated);
+        assertEquals("active", updated.getStatus());
+        assertTrue(updated.getUsername().endsWith("XX"));
+        assertEquals(1, updated.getMemberships().size());
+
+        // check that propagation also happened
+        assertTrue(updated.getResources().contains(RESOURCE_NAME_TESTDB));
+        assertNotNull(resourceService.getConnectorObject(RESOURCE_NAME_TESTDB, AttributableType.USER, updated.getId()));
+    }
+
+    @Test
+    public void delete() {
+        UserTO created = createUser(UserTestITCase.getUniqueSampleTO("anonymous@syncope.apache.org"));
+        assertNotNull(created);
+
+        SyncopeClient authClient = clientFactory.create(created.getUsername(), "password123");
+        UserTO deleted = authClient.getService(UserSelfService.class).delete().readEntity(UserTO.class);
+        assertNotNull(deleted);
+        assertEquals("deleteApproval", deleted.getStatus());
+    }
+
+    @Test
+    public void issueSYNCOPE373() {
+        UserTO userTO = userSelfService.read();
+        assertEquals(ADMIN_UNAME, userTO.getUsername());
+    }
+
+}

Propchange: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserSelfTestITCase.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message