You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/06/11 13:42:42 UTC

[1/3] syncope git commit: [SYNCOPE-1322] Implementation provided

Repository: syncope
Updated Branches:
  refs/heads/2_0_X df5c7fe4d -> ded0106d7
  refs/heads/master 26e2b9dd3 -> 8db75d21c


[SYNCOPE-1322] Implementation provided


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/b10beb88
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/b10beb88
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/b10beb88

Branch: refs/heads/2_0_X
Commit: b10beb88374efbabd3d781b4c8206e55130a2235
Parents: df5c7fe
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Jun 11 14:50:54 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Jun 11 14:50:54 2018 +0200

----------------------------------------------------------------------
 .../syncope/common/lib/to/WorkflowTaskTO.java   | 40 ++++++++++++++++
 .../rest/api/service/UserWorkflowService.java   | 11 +++++
 .../syncope/core/logic/UserWorkflowLogic.java   | 13 ++++-
 .../cxf/service/UserWorkflowServiceImpl.java    |  6 +++
 .../activiti/ActivitiUserWorkflowAdapter.java   | 50 +++++++++++++++++++-
 .../core/workflow/api/WorkflowAdapter.java      |  9 ++++
 .../flowable/FlowableUserWorkflowAdapter.java   | 49 ++++++++++++++++++-
 .../java/DefaultAnyObjectWorkflowAdapter.java   |  6 +++
 .../java/DefaultGroupWorkflowAdapter.java       |  6 +++
 .../java/DefaultUserWorkflowAdapter.java        |  6 +++
 .../syncope/fit/core/UserWorkflowITCase.java    | 35 ++++++++++++++
 11 files changed, 227 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java
new file mode 100644
index 0000000..d2834c8
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java
@@ -0,0 +1,40 @@
+/*
+ * 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.common.lib.to;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "workflowTask")
+@XmlType
+public class WorkflowTaskTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -3095016727396210808L;
+
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
index 3be75ae..7be582c 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
@@ -32,6 +32,7 @@ import javax.ws.rs.core.MediaType;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 
 /**
  * REST operations related to user workflow.
@@ -87,6 +88,16 @@ public interface UserWorkflowService extends JAXRSService {
     UserTO submitForm(@NotNull WorkflowFormTO form);
 
     /**
+     * Returns a list of available tasks for the given user key.
+     *
+     * @param userKey user key
+     * @return list of available tasks for the given user key
+     */
+    @GET
+    @Path("tasks/{userKey}")
+    List<WorkflowTaskTO> getAvailableTasks(@NotNull @PathParam("userKey") String userKey);
+
+    /**
      * Executes workflow task for matching id.
      *
      * @param taskId workflow task id

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
index 5a41b9c..8725c82 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
@@ -26,6 +26,7 @@ import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -80,8 +81,8 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
         return binder.getUserTO(updated.getResult());
     }
 
-    @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_READ + "') and hasRole('"
-            + StandardEntitlement.USER_READ + "')")
+    @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_READ + "') "
+            + "and hasRole('" + StandardEntitlement.USER_READ + "')")
     @Transactional(readOnly = true)
     public WorkflowFormTO getFormForUser(final String key) {
         User user = userDAO.authFind(key);
@@ -94,6 +95,13 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
         return uwfAdapter.getForms();
     }
 
+    @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_TASK_LIST + "') "
+            + "and hasRole('" + StandardEntitlement.USER_READ + "')")
+    public List<WorkflowTaskTO> getAvailableTasks(final String key) {
+        User user = userDAO.authFind(key);
+        return uwfAdapter.getAvailableTasks(user.getWorkflowId());
+    }
+
     @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_SUBMIT + "')")
     public UserTO submitForm(final WorkflowFormTO form) {
         WorkflowResult<? extends AnyPatch> updated = uwfAdapter.submitForm(form);
@@ -121,4 +129,5 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
 
         throw new UnresolvedReferenceException();
     }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
index c24d66f..8022f36 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.rest.cxf.service;
 import java.util.List;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.common.rest.api.service.UserWorkflowService;
 import org.apache.syncope.core.logic.UserWorkflowLogic;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -53,6 +54,11 @@ public class UserWorkflowServiceImpl implements UserWorkflowService {
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String userKey) {
+        return logic.getAvailableTasks(userKey);
+    }
+
+    @Override
     public UserTO submitForm(final WorkflowFormTO form) {
         return logic.submitForm(form);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
index f7aed6c..b25ffd9 100644
--- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
@@ -34,6 +34,10 @@ import java.util.Set;
 import javax.annotation.Resource;
 import org.activiti.bpmn.converter.BpmnXMLConverter;
 import org.activiti.bpmn.model.BpmnModel;
+import org.activiti.bpmn.model.FlowElement;
+import org.activiti.bpmn.model.Gateway;
+import org.activiti.bpmn.model.Process;
+import org.activiti.bpmn.model.SequenceFlow;
 import org.activiti.editor.constants.ModelDataJsonConstants;
 import org.activiti.editor.language.json.converter.BpmnJsonConverter;
 import org.activiti.engine.ActivitiException;
@@ -62,6 +66,7 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.common.lib.types.WorkflowFormPropertyType;
@@ -363,7 +368,6 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         String authUser = AuthContextUtils.getUsername();
         engine.getRuntimeService().setVariable(user.getWorkflowId(), FORM_SUBMITTER, authUser);
 
-        LOG.debug("Executing request-certify");
         Set<String> performedTasks = doExecuteTask(user, "request-certify", null);
 
         PropagationByResource propByRes = engine.getRuntimeService().getVariable(
@@ -803,6 +807,50 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         return new WorkflowResult<>(userPatch, propByRes, postTasks);
     }
 
+    protected void navigateAvailableTasks(final FlowElement flow, final List<String> availableTasks) {
+        if (flow instanceof Gateway) {
+            for (SequenceFlow subflow : ((Gateway) flow).getOutgoingFlows()) {
+                navigateAvailableTasks(subflow, availableTasks);
+            }
+        } else if (flow instanceof SequenceFlow) {
+            availableTasks.add(((SequenceFlow) flow).getTargetRef());
+        } else {
+            LOG.debug("Unexpected flow found: {}", flow);
+        }
+    }
+
+    @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        List<String> availableTasks = new ArrayList<>();
+        try {
+            Task currentTask = engine.getTaskService().createTaskQuery().processInstanceId(workflowId).singleResult();
+
+            Process process = engine.getRepositoryService().
+                    getBpmnModel(getProcessDefinitionByKey(WF_PROCESS_ID).getId()).getProcesses().get(0);
+            for (FlowElement flowElement : process.getFlowElements()) {
+                if (flowElement instanceof SequenceFlow) {
+                    SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
+                    if (sequenceFlow.getSourceRef().equals(currentTask.getTaskDefinitionKey())) {
+                        FlowElement target = process.getFlowElementRecursive(sequenceFlow.getTargetRef());
+                        navigateAvailableTasks(target, availableTasks);
+                    }
+                }
+            }
+        } catch (ActivitiException e) {
+            throw new WorkflowException("While reading available tasks for workflow instance " + workflowId, e);
+        }
+
+        return CollectionUtils.collect(availableTasks, new Transformer<String, WorkflowTaskTO>() {
+
+            @Override
+            public WorkflowTaskTO transform(final String input) {
+                WorkflowTaskTO workflowTaskTO = new WorkflowTaskTO();
+                workflowTaskTO.setName(input);
+                return workflowTaskTO;
+            }
+        }, new ArrayList<WorkflowTaskTO>());
+    }
+
     protected Model getModel(final ProcessDefinition procDef) {
         try {
             Model model = engine.getRepositoryService().createModelQuery().

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
index 881c4dc..2f2f273 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.workflow.api;
 import java.util.List;
 import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 
 public interface WorkflowAdapter {
@@ -65,4 +66,12 @@ public interface WorkflowAdapter {
      * @return object updated by this form submit
      */
     WorkflowResult<? extends AnyPatch> submitForm(WorkflowFormTO form);
+
+    /**
+     * Get tasks available for execution, for given workflow id.
+     * 
+     * @param workflowId workflow id
+     * @return available tasks
+     */
+    List<WorkflowTaskTO> getAvailableTasks(String workflowId);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
index 686c86e..23a4da1 100644
--- a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
+++ b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
@@ -34,6 +34,9 @@ import java.util.Set;
 import javax.annotation.Resource;
 import org.activiti.bpmn.converter.BpmnXMLConverter;
 import org.activiti.bpmn.model.BpmnModel;
+import org.activiti.bpmn.model.FlowElement;
+import org.activiti.bpmn.model.Gateway;
+import org.activiti.bpmn.model.SequenceFlow;
 import org.activiti.editor.constants.ModelDataJsonConstants;
 import org.activiti.editor.language.json.converter.BpmnJsonConverter;
 import org.activiti.engine.ActivitiException;
@@ -62,6 +65,7 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.common.lib.types.WorkflowFormPropertyType;
@@ -363,7 +367,6 @@ public class FlowableUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         String authUser = AuthContextUtils.getUsername();
         engine.getRuntimeService().setVariable(user.getWorkflowId(), FORM_SUBMITTER, authUser);
 
-        LOG.debug("Executing request-certify");
         Set<String> performedTasks = doExecuteTask(user, "request-certify", null);
 
         PropagationByResource propByRes = engine.getRuntimeService().getVariable(
@@ -803,6 +806,50 @@ public class FlowableUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         return new WorkflowResult<>(userPatch, propByRes, postTasks);
     }
 
+    protected void navigateAvailableTasks(final FlowElement flow, final List<String> availableTasks) {
+        if (flow instanceof Gateway) {
+            for (SequenceFlow subflow : ((Gateway) flow).getOutgoingFlows()) {
+                navigateAvailableTasks(subflow, availableTasks);
+            }
+        } else if (flow instanceof SequenceFlow) {
+            availableTasks.add(((SequenceFlow) flow).getTargetRef());
+        } else {
+            LOG.debug("Unexpected flow found: {}", flow);
+        }
+    }
+
+    @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        List<String> availableTasks = new ArrayList<>();
+        try {
+            Task currentTask = engine.getTaskService().createTaskQuery().processInstanceId(workflowId).singleResult();
+
+            org.activiti.bpmn.model.Process process = engine.getRepositoryService().
+                    getBpmnModel(getProcessDefinitionByKey(WF_PROCESS_ID).getId()).getProcesses().get(0);
+            for (FlowElement flowElement : process.getFlowElements()) {
+                if (flowElement instanceof SequenceFlow) {
+                    SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
+                    if (sequenceFlow.getSourceRef().equals(currentTask.getTaskDefinitionKey())) {
+                        FlowElement target = process.getFlowElementRecursive(sequenceFlow.getTargetRef());
+                        navigateAvailableTasks(target, availableTasks);
+                    }
+                }
+            }
+        } catch (ActivitiException e) {
+            throw new WorkflowException("While reading available tasks for workflow instance " + workflowId, e);
+        }
+
+        return CollectionUtils.collect(availableTasks, new Transformer<String, WorkflowTaskTO>() {
+
+            @Override
+            public WorkflowTaskTO transform(final String input) {
+                WorkflowTaskTO workflowTaskTO = new WorkflowTaskTO();
+                workflowTaskTO.setName(input);
+                return workflowTaskTO;
+            }
+        }, new ArrayList<WorkflowTaskTO>());
+    }
+
     protected Model getModel(final ProcessDefinition procDef) {
         try {
             Model model = engine.getRepositoryService().createModelQuery().

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
index e1a6ad5..2a35600 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
@@ -28,6 +28,7 @@ import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -103,6 +104,11 @@ public class DefaultAnyObjectWorkflowAdapter extends AbstractAnyObjectWorkflowAd
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public List<WorkflowDefinitionTO> getDefinitions() {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
index ef05edd..e3adfab 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
@@ -28,6 +28,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -103,6 +104,11 @@ public class DefaultGroupWorkflowAdapter extends AbstractGroupWorkflowAdapter {
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public List<WorkflowDefinitionTO> getDefinitions() {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
index bf2ddab..8503622 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
@@ -30,6 +30,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
@@ -194,6 +195,11 @@ public class DefaultUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public WorkflowResult<String> requestCertify(final User user) {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b10beb88/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
index f6cb707..dadaf29 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
@@ -32,6 +32,8 @@ import java.util.List;
 import java.util.UUID;
 import javax.sql.DataSource;
 import javax.ws.rs.core.Response;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.patch.MembershipPatch;
@@ -43,6 +45,7 @@ import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.rest.api.service.UserSelfService;
@@ -283,6 +286,38 @@ public class UserWorkflowITCase extends AbstractITCase {
     }
 
     @Test
+    public void availableTasks() {
+        Assume.assumeTrue(ActivitiDetector.isActivitiEnabledForUsers(syncopeService));
+
+        UserTO user = createUser(UserITCase.getUniqueSampleTO("availableTasks@apache.org")).getEntity();
+        assertEquals("active", user.getStatus());
+
+        List<WorkflowTaskTO> tasks = userWorkflowService.getAvailableTasks(user.getKey());
+        assertNotNull(tasks);
+        assertTrue(IterableUtils.matchesAny(tasks, new Predicate<WorkflowTaskTO>() {
+
+            @Override
+            public boolean evaluate(final WorkflowTaskTO task) {
+                return "update".equals(task.getName());
+            }
+        }));
+        assertTrue(IterableUtils.matchesAny(tasks, new Predicate<WorkflowTaskTO>() {
+
+            @Override
+            public boolean evaluate(final WorkflowTaskTO task) {
+                return "suspend".equals(task.getName());
+            }
+        }));
+        assertTrue(IterableUtils.matchesAny(tasks, new Predicate<WorkflowTaskTO>() {
+
+            @Override
+            public boolean evaluate(final WorkflowTaskTO task) {
+                return "delete".equals(task.getName());
+            }
+        }));
+    }
+
+    @Test
     public void issueSYNCOPE15() {
         Assume.assumeTrue(ActivitiDetector.isActivitiEnabledForUsers(syncopeService));
 


[2/3] syncope git commit: Upgrading OpenJPA

Posted by il...@apache.org.
Upgrading OpenJPA


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/ded0106d
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/ded0106d
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/ded0106d

Branch: refs/heads/2_0_X
Commit: ded0106d7535fe648a344dd7ec170afae8f09836
Parents: b10beb8
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Jun 11 14:51:23 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Jun 11 14:51:23 2018 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/ded0106d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c697e83..9720898 100644
--- a/pom.xml
+++ b/pom.xml
@@ -375,7 +375,7 @@ under the License.
     <spring.version>4.3.17.RELEASE</spring.version>
     <spring-security.version>4.2.6.RELEASE</spring-security.version>
 
-    <openjpa.version>2.4.2</openjpa.version>
+    <openjpa.version>2.4.3</openjpa.version>
     <hikaricp.version>2.4.13</hikaricp.version>
     <bval.version>1.1.2</bval.version>
 


[3/3] syncope git commit: [SYNCOPE-1322] Implementation provided

Posted by il...@apache.org.
[SYNCOPE-1322] Implementation provided


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/8db75d21
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/8db75d21
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/8db75d21

Branch: refs/heads/master
Commit: 8db75d21c2bdaa0800a366cc2c5a5412e459e9f4
Parents: 26e2b9d
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Jun 11 14:50:54 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Jun 11 15:39:50 2018 +0200

----------------------------------------------------------------------
 .../syncope/common/lib/to/WorkflowTaskTO.java   | 40 ++++++++++++++++++
 .../rest/api/service/UserWorkflowService.java   | 11 +++++
 .../syncope/core/logic/UserWorkflowLogic.java   | 13 +++++-
 .../cxf/service/UserWorkflowServiceImpl.java    |  6 +++
 .../core/workflow/api/WorkflowAdapter.java      |  9 ++++
 .../flowable/FlowableUserWorkflowAdapter.java   | 43 +++++++++++++++++++-
 .../java/DefaultAnyObjectWorkflowAdapter.java   |  6 +++
 .../java/DefaultGroupWorkflowAdapter.java       |  6 +++
 .../java/DefaultUserWorkflowAdapter.java        |  6 +++
 .../syncope/fit/core/UserWorkflowITCase.java    | 15 +++++++
 10 files changed, 152 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java
new file mode 100644
index 0000000..d2834c8
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowTaskTO.java
@@ -0,0 +1,40 @@
+/*
+ * 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.common.lib.to;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "workflowTask")
+@XmlType
+public class WorkflowTaskTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -3095016727396210808L;
+
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
index a9fb842..5dbe7d5 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowService.java
@@ -33,6 +33,7 @@ import javax.ws.rs.core.MediaType;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 
 /**
  * REST operations related to user workflow.
@@ -89,6 +90,16 @@ public interface UserWorkflowService extends JAXRSService {
     UserTO submitForm(@NotNull WorkflowFormTO form);
 
     /**
+     * Returns a list of available tasks for the given user key.
+     *
+     * @param userKey user key
+     * @return list of available tasks for the given user key
+     */
+    @GET
+    @Path("tasks/{userKey}")
+    List<WorkflowTaskTO> getAvailableTasks(@NotNull @PathParam("userKey") String userKey);
+
+    /**
      * Executes workflow task for matching id.
      *
      * @param taskId workflow task id

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
index 8fc4745..8171ca9 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
@@ -26,6 +26,7 @@ import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -79,8 +80,8 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
         return binder.getUserTO(updated.getResult());
     }
 
-    @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_READ + "') and hasRole('"
-            + StandardEntitlement.USER_READ + "')")
+    @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_READ + "') "
+            + "and hasRole('" + StandardEntitlement.USER_READ + "')")
     @Transactional(readOnly = true)
     public WorkflowFormTO getFormForUser(final String key) {
         User user = userDAO.authFind(key);
@@ -93,6 +94,13 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
         return uwfAdapter.getForms();
     }
 
+    @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_TASK_LIST + "') "
+            + "and hasRole('" + StandardEntitlement.USER_READ + "')")
+    public List<WorkflowTaskTO> getAvailableTasks(final String key) {
+        User user = userDAO.authFind(key);
+        return uwfAdapter.getAvailableTasks(user.getWorkflowId());
+    }
+
     @PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_SUBMIT + "')")
     public UserTO submitForm(final WorkflowFormTO form) {
         WorkflowResult<? extends AnyPatch> updated = uwfAdapter.submitForm(form);
@@ -120,4 +128,5 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
 
         throw new UnresolvedReferenceException();
     }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
index c24d66f..8022f36 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserWorkflowServiceImpl.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.rest.cxf.service;
 import java.util.List;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.common.rest.api.service.UserWorkflowService;
 import org.apache.syncope.core.logic.UserWorkflowLogic;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -53,6 +54,11 @@ public class UserWorkflowServiceImpl implements UserWorkflowService {
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String userKey) {
+        return logic.getAvailableTasks(userKey);
+    }
+
+    @Override
     public UserTO submitForm(final WorkflowFormTO form) {
         return logic.submitForm(form);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
index 72a2727..3b44487 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.workflow.api;
 import java.util.List;
 import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 
 public interface WorkflowAdapter {
@@ -60,4 +61,12 @@ public interface WorkflowAdapter {
      * @return object updated by this form submit
      */
     WorkflowResult<? extends AnyPatch> submitForm(WorkflowFormTO form);
+
+    /**
+     * Get tasks available for execution, for given workflow id.
+     *
+     * @param workflowId workflow id
+     * @return available tasks
+     */
+    List<WorkflowTaskTO> getAvailableTasks(String workflowId);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
index 8071eb9..e765300 100644
--- a/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
+++ b/core/workflow-flowable/src/main/java/org/apache/syncope/core/workflow/flowable/FlowableUserWorkflowAdapter.java
@@ -43,6 +43,7 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.common.lib.types.WorkflowFormPropertyType;
@@ -59,6 +60,10 @@ import org.apache.syncope.core.workflow.api.WorkflowException;
 import org.apache.syncope.core.workflow.java.AbstractUserWorkflowAdapter;
 import org.flowable.bpmn.converter.BpmnXMLConverter;
 import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.bpmn.model.Gateway;
+import org.flowable.bpmn.model.Process;
+import org.flowable.bpmn.model.SequenceFlow;
 import org.flowable.editor.constants.ModelDataJsonConstants;
 import org.flowable.editor.language.json.converter.BpmnJsonConverter;
 import org.flowable.common.engine.api.FlowableException;
@@ -355,7 +360,6 @@ public class FlowableUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         String authUser = AuthContextUtils.getUsername();
         engine.getRuntimeService().setVariable(user.getWorkflowId(), FORM_SUBMITTER, authUser);
 
-        LOG.debug("Executing request-certify");
         Set<String> performedTasks = doExecuteTask(user, "request-certify", null);
 
         PropagationByResource propByRes = engine.getRuntimeService().getVariable(
@@ -795,6 +799,43 @@ public class FlowableUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         return new WorkflowResult<>(userPatch, propByRes, postTasks);
     }
 
+    protected void navigateAvailableTasks(final FlowElement flow, final List<String> availableTasks) {
+        if (flow instanceof Gateway) {
+            ((Gateway) flow).getOutgoingFlows().forEach(subflow -> navigateAvailableTasks(subflow, availableTasks));
+        } else if (flow instanceof SequenceFlow) {
+            availableTasks.add(((SequenceFlow) flow).getTargetRef());
+        } else {
+            LOG.debug("Unexpected flow found: {}", flow);
+        }
+    }
+
+    @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        List<String> availableTasks = new ArrayList<>();
+        try {
+            Task currentTask = engine.getTaskService().createTaskQuery().processInstanceId(workflowId).singleResult();
+
+            Process process = engine.getRepositoryService().
+                    getBpmnModel(getProcessDefinitionByKey(WF_PROCESS_ID).getId()).getProcesses().get(0);
+            process.getFlowElements().stream().
+                    filter(SequenceFlow.class::isInstance).
+                    map(SequenceFlow.class::cast).
+                    filter(sequenceFlow -> sequenceFlow.getSourceRef().equals(currentTask.getTaskDefinitionKey())).
+                    forEach(sequenceFlow -> {
+                        FlowElement target = process.getFlowElement(sequenceFlow.getTargetRef(), true);
+                        navigateAvailableTasks(target, availableTasks);
+                    });
+        } catch (FlowableException e) {
+            throw new WorkflowException("While reading available tasks for workflow instance " + workflowId, e);
+        }
+
+        return availableTasks.stream().map(input -> {
+            WorkflowTaskTO workflowTaskTO = new WorkflowTaskTO();
+            workflowTaskTO.setName(input);
+            return workflowTaskTO;
+        }).collect(Collectors.toList());
+    }
+
     protected Model getModel(final ProcessDefinition procDef) {
         try {
             Model model = engine.getRepositoryService().createModelQuery().

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
index 8899b06..5cb7303 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
@@ -28,6 +28,7 @@ import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -98,6 +99,11 @@ public class DefaultAnyObjectWorkflowAdapter extends AbstractAnyObjectWorkflowAd
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public List<WorkflowDefinitionTO> getDefinitions() {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
index b61bbf3..f0cbbd0 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
@@ -28,6 +28,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -98,6 +99,11 @@ public class DefaultGroupWorkflowAdapter extends AbstractGroupWorkflowAdapter {
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public List<WorkflowDefinitionTO> getDefinitions() {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
index 6365c33..54276e1 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
@@ -30,6 +30,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowDefinitionTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
@@ -189,6 +190,11 @@ public class DefaultUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     }
 
     @Override
+    public List<WorkflowTaskTO> getAvailableTasks(final String workflowId) {
+        return Collections.emptyList();
+    }
+
+    @Override
     public WorkflowResult<String> requestCertify(final User user) {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8db75d21/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
index c4a21c4..e3fa1c0 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
@@ -44,6 +44,7 @@ import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.rest.api.service.UserSelfService;
@@ -280,6 +281,20 @@ public class UserWorkflowITCase extends AbstractITCase {
     }
 
     @Test
+    public void availableTasks() {
+        assumeTrue(FlowableDetector.isFlowableEnabledForUsers(syncopeService));
+
+        UserTO user = createUser(UserITCase.getUniqueSampleTO("availableTasks@apache.org")).getEntity();
+        assertEquals("active", user.getStatus());
+
+        List<WorkflowTaskTO> tasks = userWorkflowService.getAvailableTasks(user.getKey());
+        assertNotNull(tasks);
+        assertTrue(tasks.stream().anyMatch(task -> "update".equals(task.getName())));
+        assertTrue(tasks.stream().anyMatch(task -> "suspend".equals(task.getName())));
+        assertTrue(tasks.stream().anyMatch(task -> "delete".equals(task.getName())));
+    }
+
+    @Test
     public void issueSYNCOPE15() {
         assumeTrue(FlowableDetector.isFlowableEnabledForUsers(syncopeService));