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));
}