You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2013/09/16 15:35:15 UTC

svn commit: r1523644 - in /syncope/trunk: common/src/main/java/org/apache/syncope/common/services/ core/src/main/java/org/apache/syncope/core/rest/controller/ core/src/main/java/org/apache/syncope/core/services/ core/src/main/java/org/apache/syncope/co...

Author: fmartelli
Date: Mon Sep 16 13:35:15 2013
New Revision: 1523644

URL: http://svn.apache.org/r1523644
Log:
SYNCOPE-15 fixed

Modified:
    syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserWorkflowService.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserWorkflowController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserWorkflowServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/role/NoOpRoleWorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/NoOpUserWorkflowAdapter.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/user/activiti/ActivitiUserWorkflowAdapter.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserWorkflowService.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserWorkflowService.java?rev=1523644&r1=1523643&r2=1523644&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserWorkflowService.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserWorkflowService.java Mon Sep 16 13:35:15 2013
@@ -30,23 +30,28 @@ import org.apache.syncope.common.to.Work
 
 @Path("userworkflow")
 public interface UserWorkflowService {
-	@POST
-	@Path("forms")
-	UserTO submitForm(WorkflowFormTO form);
-
-	@GET
-	@Path("forms")
-	List<WorkflowFormTO> getForms();
-
-	@GET
-	@Path("forms/{userId}")
-	WorkflowFormTO getFormForUser(@PathParam("userId") Long userId);
-	
-	@POST
-	@Path("tasks/{taskId}/claim")
-	WorkflowFormTO claimForm(@PathParam("taskId") String taskId);
-
-	@POST
-	@Path("tasks/{taskId}/execute")
-	UserTO executeWorkflow(@PathParam("taskId") String taskId, UserTO userTO);
+
+    @POST
+    @Path("forms")
+    UserTO submitForm(WorkflowFormTO form);
+
+    @GET
+    @Path("forms")
+    List<WorkflowFormTO> getForms();
+
+    @GET
+    @Path("forms/{userId}/{name}")
+    List<WorkflowFormTO> getFormsByName(@PathParam("userId") final Long userId, @PathParam("name") final String name);
+
+    @GET
+    @Path("forms/{userId}")
+    WorkflowFormTO getFormForUser(@PathParam("userId") Long userId);
+
+    @POST
+    @Path("tasks/{taskId}/claim")
+    WorkflowFormTO claimForm(@PathParam("taskId") String taskId);
+
+    @POST
+    @Path("tasks/{taskId}/execute")
+    UserTO executeWorkflow(@PathParam("taskId") String taskId, UserTO userTO);
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserWorkflowController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserWorkflowController.java?rev=1523644&r1=1523643&r2=1523644&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserWorkflowController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserWorkflowController.java Mon Sep 16 13:35:15 2013
@@ -124,6 +124,19 @@ public class UserWorkflowController exte
         return forms;
     }
 
+    @PreAuthorize("hasRole('WORKFLOW_FORM_READ') and hasRole('USER_READ')")
+    @Transactional(rollbackFor = {Throwable.class})
+    public List<WorkflowFormTO> getForms(final Long userId, final String formName) {
+        SyncopeUser user = binder.getUserFromId(userId);
+        final List<WorkflowFormTO> result = uwfAdapter.getForms(user.getWorkflowId(), formName);
+
+        auditManager.audit(AuditElements.Category.user, AuditElements.UserSubCategory.getFormForUser,
+                AuditElements.Result.success,
+                "Successfully read workflow form for user: " + user.getUsername());
+
+        return result;
+    }
+
     @PreAuthorize("hasRole('WORKFLOW_FORM_SUBMIT')")
     @Transactional(rollbackFor = {Throwable.class})
     public UserTO submitForm(final WorkflowFormTO form) {

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserWorkflowServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserWorkflowServiceImpl.java?rev=1523644&r1=1523643&r2=1523644&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserWorkflowServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserWorkflowServiceImpl.java Mon Sep 16 13:35:15 2013
@@ -37,7 +37,6 @@ public class UserWorkflowServiceImpl imp
     public WorkflowFormTO claimForm(final String taskId) {
         return controller.claimForm(taskId);
     }
-    
 
     @Override
     public UserTO executeWorkflow(final String taskId, final UserTO userTO) {
@@ -53,11 +52,14 @@ public class UserWorkflowServiceImpl imp
     public List<WorkflowFormTO> getForms() {
         return controller.getForms();
     }
-    
 
     @Override
     public UserTO submitForm(final WorkflowFormTO form) {
         return controller.submitForm(form);
     }
-    
+
+    @Override
+    public List<WorkflowFormTO> getFormsByName(final Long userId, final String taskName) {
+        return controller.getForms(userId, taskName);
+    }
 }

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=1523644&r1=1523643&r2=1523644&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 Mon Sep 16 13:35:15 2013
@@ -68,6 +68,17 @@ public interface WorkflowAdapter {
     List<WorkflowFormTO> getForms();
 
     /**
+     * Gets all forms with the given name for the given workflowId(include historical forms).
+     *
+     * @param workflowId workflow id.
+     * @param name form name.
+     * @return forms (if present), otherwise an empty list.
+     * @throws NotFoundException definition not found exception
+     * @throws WorkflowException workflow exception
+     */
+    List<WorkflowFormTO> getForms(String workflowId, String name);
+
+    /**
      * Get form for given workflowId (if present).
      *
      * @param workflowId workflow id

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=1523644&r1=1523643&r2=1523644&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 Mon Sep 16 13:35:15 2013
@@ -42,7 +42,7 @@ import org.springframework.transaction.a
 @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)
@@ -110,6 +110,11 @@ public class NoOpRoleWorkflowAdapter ext
     }
 
     @Override
+    public List<WorkflowFormTO> getForms(final String workflowId, final String name) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public WorkflowFormTO getForm(final String workflowId)
             throws NotFoundException, WorkflowException {
 

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=1523644&r1=1523643&r2=1523644&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 Mon Sep 16 13:35:15 2013
@@ -44,7 +44,7 @@ import org.springframework.transaction.a
 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";
 
@@ -179,6 +179,11 @@ public class NoOpUserWorkflowAdapter ext
     }
 
     @Override
+    public List<WorkflowFormTO> getForms(final String workflowId, final String name) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public WorkflowFormTO getForm(final String workflowId)
             throws NotFoundException, 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=1523644&r1=1523643&r2=1523644&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 Mon Sep 16 13:35:15 2013
@@ -50,6 +50,10 @@ import org.activiti.engine.form.FormProp
 import org.activiti.engine.form.FormType;
 import org.activiti.engine.form.TaskFormData;
 import org.activiti.engine.history.HistoricActivityInstance;
+import org.activiti.engine.history.HistoricDetail;
+import org.activiti.engine.history.HistoricTaskInstance;
+import org.activiti.engine.impl.persistence.entity.HistoricFormPropertyEntity;
+import org.activiti.engine.query.Query;
 import org.activiti.engine.repository.ProcessDefinition;
 import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.task.Task;
@@ -171,11 +175,10 @@ public class ActivitiUserWorkflowAdapter
     }
 
     private Set<String> getPerformedTasks(final SyncopeUser user) {
-        Set<String> result = new HashSet<String>();
+        final Set<String> result = new HashSet<String>();
 
-        List<HistoricActivityInstance> tasks = historyService.createHistoricActivityInstanceQuery().executionId(
-                user.getWorkflowId()).list();
-        for (HistoricActivityInstance task : tasks) {
+        for (HistoricActivityInstance task : historyService.createHistoricActivityInstanceQuery().executionId(user.
+                getWorkflowId()).list()) {
             result.add(task.getActivityId());
         }
 
@@ -491,22 +494,90 @@ public class ActivitiUserWorkflowAdapter
         return result;
     }
 
+    private WorkflowFormTO getFormTO(final Task task) {
+        return getFormTO(task, formService.getTaskFormData(task.getId()));
+    }
+
+    private WorkflowFormTO getFormTO(final Task task, final TaskFormData fd) {
+        final WorkflowFormTO formTO =
+                getFormTO(task.getProcessInstanceId(), task.getId(), fd.getFormKey(), fd.getFormProperties());
+
+        BeanUtils.copyProperties(task, formTO);
+        return formTO;
+    }
+
+    private WorkflowFormTO getFormTO(final HistoricTaskInstance task) {
+        final List<HistoricFormPropertyEntity> props = new ArrayList<HistoricFormPropertyEntity>();
+
+        for (HistoricDetail historicDetail : historyService.createHistoricDetailQuery().taskId(task.getId()).list()) {
+
+            if (historicDetail instanceof HistoricFormPropertyEntity) {
+                props.add((HistoricFormPropertyEntity) historicDetail);
+            }
+        }
+
+        final WorkflowFormTO formTO = getHFormTO(task.getProcessInstanceId(), task.getId(), task.getFormKey(), props);
+        BeanUtils.copyProperties(task, formTO);
+
+        final HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().
+                executionId(task.getExecutionId()).activityType("userTask").activityName(task.getName()).singleResult();
+
+        if (historicActivityInstance != null) {
+            formTO.setCreateTime(historicActivityInstance.getStartTime());
+            formTO.setDueDate(historicActivityInstance.getEndTime());
+        }
+
+        return formTO;
+    }
+
     @SuppressWarnings("unchecked")
-    private WorkflowFormTO getFormTO(final Task task, final TaskFormData formData) {
+    private WorkflowFormTO getHFormTO(
+            final String processInstanceId,
+            final String taskId,
+            final String formKey,
+            final List<HistoricFormPropertyEntity> props) {
+
         WorkflowFormTO formTO = new WorkflowFormTO();
 
-        SyncopeUser user = userDAO.findByWorkflowId(task.getProcessInstanceId());
+        SyncopeUser user = userDAO.findByWorkflowId(processInstanceId);
         if (user == null) {
-            throw new NotFoundException("User with workflow id " + task.getProcessInstanceId());
+            throw new NotFoundException("User with workflow id " + processInstanceId);
         }
         formTO.setUserId(user.getId());
 
-        formTO.setTaskId(task.getId());
-        formTO.setKey(formData.getFormKey());
+        formTO.setTaskId(taskId);
+        formTO.setKey(formKey);
 
-        BeanUtils.copyProperties(task, formTO);
+        for (HistoricFormPropertyEntity prop : props) {
+            WorkflowFormPropertyTO propertyTO = new WorkflowFormPropertyTO();
+            propertyTO.setId(prop.getPropertyId());
+            propertyTO.setName(prop.getPropertyId());
+            propertyTO.setValue(prop.getPropertyValue());
+            formTO.addProperty(propertyTO);
+        }
+
+        return formTO;
+    }
+
+    @SuppressWarnings("unchecked")
+    private WorkflowFormTO getFormTO(
+            final String processInstanceId,
+            final String taskId,
+            final String formKey,
+            final List<FormProperty> properties) {
+
+        WorkflowFormTO formTO = new WorkflowFormTO();
 
-        for (FormProperty fProp : formData.getFormProperties()) {
+        SyncopeUser user = userDAO.findByWorkflowId(processInstanceId);
+        if (user == null) {
+            throw new NotFoundException("User with workflow id " + processInstanceId);
+        }
+        formTO.setUserId(user.getId());
+
+        formTO.setTaskId(taskId);
+        formTO.setKey(formKey);
+
+        for (FormProperty fProp : properties) {
             WorkflowFormPropertyTO propertyTO = new WorkflowFormPropertyTO();
             BeanUtils.copyProperties(fProp, propertyTO, PROPERTY_IGNORE_PROPS);
             propertyTO.setType(fromActivitiFormType(fProp.getType()));
@@ -526,16 +597,36 @@ public class ActivitiUserWorkflowAdapter
 
     @Override
     public List<WorkflowFormTO> getForms() {
-        List<WorkflowFormTO> forms = new ArrayList<WorkflowFormTO>();
+        return getForms(taskService.createTaskQuery().taskVariableValueEquals(TASK_IS_FORM, Boolean.TRUE));
+    }
+
+    @Override
+    public List<WorkflowFormTO> getForms(final String workflowId, final String name) {
+        final List<WorkflowFormTO> forms = getForms(
+                taskService.createTaskQuery().processInstanceId(workflowId).taskName(name).
+                taskVariableValueEquals(TASK_IS_FORM, Boolean.TRUE));
+
+        forms.addAll(getForms(historyService.createHistoricTaskInstanceQuery().taskName(name)
+                .taskVariableValueEquals(TASK_IS_FORM, Boolean.TRUE)));
 
-        for (Task task : taskService.createTaskQuery().taskVariableValueEquals(TASK_IS_FORM, Boolean.TRUE).list()) {
+        return forms;
+    }
+
+    private <T extends Query<?, ?>, U extends Object> List<WorkflowFormTO> getForms(final Query<T, U> query) {
+        final List<WorkflowFormTO> forms = new ArrayList<WorkflowFormTO>();
+
+        for (U obj : query.list()) {
             try {
-                TaskFormData formData = formService.getTaskFormData(task.getId());
-                if (formData != null && !formData.getFormProperties().isEmpty()) {
-                    forms.add(getFormTO(task, formData));
+                if (obj instanceof HistoricTaskInstance) {
+                    forms.add(getFormTO((HistoricTaskInstance) obj));
+                } else if (obj instanceof Task) {
+                    forms.add(getFormTO((Task) obj));
+                } else {
+                    throw new ActivitiException(
+                            "Failure retrieving form", new IllegalArgumentException("Invalid task type"));
                 }
             } catch (ActivitiException e) {
-                LOG.debug("No form found for task {}", task.getId(), e);
+                LOG.debug("No form found for task {}", obj, e);
             }
         }
 
@@ -563,7 +654,7 @@ public class ActivitiUserWorkflowAdapter
 
         WorkflowFormTO result = null;
         if (formData != null && !formData.getFormProperties().isEmpty()) {
-            result = getFormTO(task, formData);
+            result = getFormTO(task);
         }
 
         return result;

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=1523644&r1=1523643&r2=1523644&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java Mon Sep 16 13:35:15 2013
@@ -2323,6 +2323,96 @@ public class UserTestITCase extends Abst
         assertEquals(PropagationTaskExecStatus.UNSUBMITTED, userTO.getPropagationStatusTOs().get(1).getStatus());
     }
 
+    @Test
+    public void issueSYNCOPE15() {
+        Assume.assumeTrue(ActivitiDetector.isActivitiEnabledForUsers());
+
+        UserTO userTO = getUniqueSampleTO("issueSYNCOPE15@syncope.apache.org");
+        userTO.getResources().clear();
+        userTO.getVirtualAttributes().clear();
+        userTO.getDerivedAttributes().clear();
+        userTO.getMemberships().clear();
+
+        // User with role 9 are defined in workflow as subject to approval
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(9L);
+        userTO.getMemberships().add(membershipTO);
+
+        // 1. create user with role 9 (and verify that no propagation occurred)
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+        assertNotEquals(0L, userTO.getId());
+        assertNotNull(userTO.getCreationDate());
+        assertNotNull(userTO.getCreator());
+        assertNotNull(userTO.getLastChangeDate());
+        assertNotNull(userTO.getLastModifier());
+        assertEquals(userTO.getCreationDate(), userTO.getLastChangeDate());
+
+        // 2. request if there is any pending form for user just created
+        List<WorkflowFormTO> forms = userWorkflowService.getForms();
+        assertEquals(1, forms.size());
+
+        WorkflowFormTO form = userWorkflowService.getFormForUser(userTO.getId());
+        assertNotNull(form);
+
+        // 3. first claim ny bellini ....
+        UserWorkflowService userService3 = createServiceInstance(UserWorkflowService.class, "bellini", ADMIN_PWD);
+
+        form = userService3.claimForm(form.getTaskId());
+        assertNotNull(form);
+        assertNotNull(form.getTaskId());
+        assertNotNull(form.getOwner());
+
+        // 4. second claim task by admin
+        form = userWorkflowService.claimForm(form.getTaskId());
+        assertNotNull(form);
+
+        // 5. approve user
+        final Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
+        props.get("approve").setValue(Boolean.TRUE.toString());
+        form.setProperties(props.values());
+
+        // 6. submit approve
+        userTO = userWorkflowService.submitForm(form);
+        assertNotNull(userTO);
+        assertEquals(0, userWorkflowService.getForms().size());
+        assertNull(userWorkflowService.getFormForUser(userTO.getId()));
+
+        // 7. search approval into the history as well
+        forms = userWorkflowService.getFormsByName(userTO.getId(), "Create approval");
+        assertFalse(forms.isEmpty());
+
+        int count = 0;
+        for (WorkflowFormTO hform : forms) {
+            if (form.getTaskId().equals(hform.getTaskId())) {
+                count++;
+
+                assertEquals("createApproval", hform.getKey());
+                assertNotNull(hform.getCreateTime());
+                assertNotNull(hform.getDueDate());
+                assertTrue(Boolean.parseBoolean(hform.getPropertyMap().get("approve").getValue()));
+                assertNull(hform.getPropertyMap().get("rejectReason").getValue());
+            }
+        }
+        assertEquals(1, count);
+
+        userService.delete(userTO.getId());
+
+        try {
+            userService.read(userTO.getId());
+            fail();
+        } catch (Exception ignore) {
+            // ignore
+        }
+
+        try {
+            userWorkflowService.getFormsByName(userTO.getId(), "Create approval");
+            fail();
+        } catch (Exception ignore) {
+            // ignore
+        }
+    }
+
     private boolean getBooleanAttribute(ConnObjectTO connObjectTO, String attrName) {
         return Boolean.parseBoolean(getStringAttribute(connObjectTO, attrName));
     }