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 2019/12/17 15:43:01 UTC
[syncope] branch master updated: [SYNCOPE-1530] Provide the
possibility to start a User Request with custom variables. (#150)
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new 475d6ca [SYNCOPE-1530] Provide the possibility to start a User Request with custom variables. (#150)
475d6ca is described below
commit 475d6ca6de6f2c521ad07d983b0861c949c73756
Author: Federico Palmitesta <fe...@gmail.com>
AuthorDate: Tue Dec 17 16:24:30 2019 +0100
[SYNCOPE-1530] Provide the possibility to start a User Request with custom variables. (#150)
---
.../client/enduser/rest/UserRequestRestClient.java | 2 +-
.../core/flowable/api/UserRequestHandler.java | 4 +-
.../flowable/impl/FlowableUserRequestHandler.java | 7 ++-
.../syncope/core/logic/UserRequestLogic.java | 19 +++++--
.../rest/api/service/UserRequestService.java | 5 +-
.../rest/cxf/service/UserRequestServiceImpl.java | 7 ++-
.../main/resources/verifyAddedVariables.bpmn20.xml | 64 ++++++++++++++++++++++
.../apache/syncope/fit/core/UserRequestITCase.java | 57 +++++++++++++++++--
8 files changed, 146 insertions(+), 19 deletions(-)
diff --git a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java
index 86335e5..3d449af 100644
--- a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java
+++ b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/rest/UserRequestRestClient.java
@@ -82,7 +82,7 @@ public class UserRequestRestClient extends BaseRestClient {
}
public static void start(final String bpmnProcess, final String user) {
- getService(UserRequestService.class).start(bpmnProcess, user);
+ getService(UserRequestService.class).start(bpmnProcess, user, null);
}
public static UserRequestForm claimForm(final String taskKey) {
diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
index 4b47edd..105278e 100644
--- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
+++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
@@ -23,6 +23,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.request.UserUR;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.UserWorkflowResult;
@@ -49,9 +50,10 @@ public interface UserRequestHandler {
*
* @param bpmnProcess BPMN process
* @param user user
+ * @param inputVariables variables
* @return data about the started request service, including execution id
*/
- UserRequest start(String bpmnProcess, User user);
+ UserRequest start(String bpmnProcess, User user, WorkflowTaskExecInput inputVariables);
/**
* Parses the given execution id to find matching user request and owner.
diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
index 5a12062..233b3f2 100644
--- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
+++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
@@ -35,6 +35,7 @@ import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.to.UserRequestFormProperty;
import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.UserRequestFormPropertyType;
@@ -195,12 +196,14 @@ public class FlowableUserRequestHandler implements UserRequestHandler {
}
@Override
- public UserRequest start(final String bpmnProcess, final User user) {
+ public UserRequest start(final String bpmnProcess, final User user, final WorkflowTaskExecInput inputVariables) {
Map<String, Object> variables = new HashMap<>();
variables.put(FlowableRuntimeUtils.WF_EXECUTOR, AuthContextUtils.getUsername());
variables.put(FlowableRuntimeUtils.USER, lazyLoad(user));
variables.put(FlowableRuntimeUtils.USER_TO, dataBinder.getUserTO(user, true));
-
+ if (inputVariables != null) {
+ variables.putAll(inputVariables.getVariables());
+ }
ProcessInstance procInst = null;
try {
procInst = engine.getRuntimeService().startProcessInstanceByKey(bpmnProcess, variables);
diff --git a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
index a0b4a3a..65ed365 100644
--- a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
+++ b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
@@ -28,6 +28,7 @@ import org.apache.syncope.common.lib.to.EntityTO;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
import org.apache.syncope.common.lib.types.BpmnProcessFormat;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.FlowableEntitlement;
@@ -95,21 +96,27 @@ public class UserRequestLogic extends AbstractTransactionalLogic<EntityTO> {
return userRequestHandler.getUserRequests(userKey, page, size, orderByClauses);
}
- protected UserRequest doStart(final String bpmnProcess, final User user) {
+ protected UserRequest doStart(
+ final String bpmnProcess,
+ final User user,
+ final WorkflowTaskExecInput inputVariables) {
// check if BPMN process exists
bpmnProcessManager.exportProcess(bpmnProcess, BpmnProcessFormat.XML, new NullOutputStream());
- return userRequestHandler.start(bpmnProcess, user);
+ return userRequestHandler.start(bpmnProcess, user, inputVariables);
}
@PreAuthorize("isAuthenticated()")
- public UserRequest start(final String bpmnProcess) {
- return doStart(bpmnProcess, userDAO.findByUsername(AuthContextUtils.getUsername()));
+ public UserRequest start(final String bpmnProcess, final WorkflowTaskExecInput inputVariables) {
+ return doStart(bpmnProcess, userDAO.findByUsername(AuthContextUtils.getUsername()), inputVariables);
}
@PreAuthorize("hasRole('" + FlowableEntitlement.USER_REQUEST_START + "')")
- public UserRequest start(final String bpmnProcess, final String userKey) {
- return doStart(bpmnProcess, userDAO.authFind(userKey));
+ public UserRequest start(
+ final String bpmnProcess,
+ final String userKey,
+ final WorkflowTaskExecInput inputVariables) {
+ return doStart(bpmnProcess, userDAO.authFind(userKey), inputVariables);
}
protected static void securityChecks(final String username, final String entitlement, final String errorMessage) {
diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
index b38cd61..d9bcd53 100644
--- a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
+++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
@@ -38,6 +38,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery;
import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
@@ -67,6 +68,7 @@ public interface UserRequestService extends JAXRSService {
*
* @param bpmnProcess BPMN process
* @param user if value looks like a UUID then it is interpreted as key otherwise as a username
+ * @param inputVariables initial request variables
* @return data about the started request service, including execution id
*/
@POST
@@ -74,7 +76,8 @@ public interface UserRequestService extends JAXRSService {
@Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
UserRequest start(
@NotNull @PathParam("bpmnProcess") String bpmnProcess,
- @QueryParam(JAXRSService.PARAM_USER) String user);
+ @QueryParam(JAXRSService.PARAM_USER) String user,
+ WorkflowTaskExecInput inputVariables);
/**
* Cancel a running user request.
diff --git a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
index d339ac8..4f939c4 100644
--- a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
+++ b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
@@ -24,6 +24,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.to.UserRequestForm;
+import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery;
import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
import org.apache.syncope.core.logic.UserRequestLogic;
@@ -53,10 +54,10 @@ public class UserRequestServiceImpl extends AbstractServiceImpl implements UserR
}
@Override
- public UserRequest start(final String bpmnProcess, final String user) {
+ public UserRequest start(final String bpmnProcess, final String user, final WorkflowTaskExecInput inputVariables) {
return user == null
- ? logic.start(bpmnProcess)
- : logic.start(bpmnProcess, getActualKey(userDAO, user));
+ ? logic.start(bpmnProcess, inputVariables)
+ : logic.start(bpmnProcess, getActualKey(userDAO, user), inputVariables);
}
@Override
diff --git a/fit/core-reference/src/main/resources/verifyAddedVariables.bpmn20.xml b/fit/core-reference/src/main/resources/verifyAddedVariables.bpmn20.xml
new file mode 100644
index 0000000..0528e22
--- /dev/null
+++ b/fit/core-reference/src/main/resources/verifyAddedVariables.bpmn20.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:flowable="http://flowable.org/bpmn"
+ xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
+ xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
+ xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
+ typeLanguage="http://www.w3.org/2001/XMLSchema"
+ expressionLanguage="http://www.w3.org/1999/XPath"
+ targetNamespace="http://www.flowable.org/processdef">
+
+ <process id="verifyAddedVariables" name="Verify Added Variables" isExecutable="true">
+ <startEvent id="startevent1" name="Start" flowable:formFieldValidation="true"/>
+ <userTask id="testForm" name="Test Form" flowable:formKey="approval" flowable:formFieldValidation="true">
+ <extensionElements>
+ <flowable:formProperty id="approve" name="Approve?" type="boolean" variable="approve" required="true"/>
+ <flowable:formProperty id="providedVariable" name="Provided Variable" type="string" expression="${providedVariable}" writable="false"/>
+ <flowable:formProperty id="username" name="Username" type="string" expression="${userTO.username}" writable="false"/>
+ </extensionElements>
+ </userTask>
+ <sequenceFlow id="sid-27C1484D-96E9-4B39-A129-F4AB14ABDF13" sourceRef="testForm" targetRef="endevent1"/>
+ <sequenceFlow id="sid-A9FEC01B-768E-4C07-B025-6D019D72015F" sourceRef="startevent1" targetRef="testForm"/>
+ <endEvent id="endevent1" name="End"/>
+ </process>
+ <bpmndi:BPMNDiagram id="BPMNDiagram_userWorkflow">
+ <bpmndi:BPMNPlane bpmnElement="userWorkflow" id="BPMNPlane_userWorkflow">
+ <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
+ <omgdc:Bounds height="30.0" width="30.0" x="150.0" y="115.0"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape bpmnElement="testForm" id="BPMNShape_testForm">
+ <omgdc:Bounds height="80.0" width="100.0" x="345.0" y="90.0"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
+ <omgdc:Bounds height="28.0" width="28.0" x="615.0" y="116.0"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge bpmnElement="sid-27C1484D-96E9-4B39-A129-F4AB14ABDF13" id="BPMNEdge_sid-27C1484D-96E9-4B39-A129-F4AB14ABDF13">
+ <omgdi:waypoint x="444.94999999992734" y="130.0"/>
+ <omgdi:waypoint x="615.0" y="130.0"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge bpmnElement="sid-A9FEC01B-768E-4C07-B025-6D019D72015F" id="BPMNEdge_sid-A9FEC01B-768E-4C07-B025-6D019D72015F">
+ <omgdi:waypoint x="179.94999965443563" y="130.0"/>
+ <omgdi:waypoint x="345.0" y="130.0"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</definitions>
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java
index dd5b907..e1a89ad 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java
@@ -35,6 +35,7 @@ import org.apache.syncope.common.lib.to.RelationshipTO;
import org.apache.syncope.common.lib.to.UserRequestForm;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.to.WorkflowTaskExecInput;
import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery;
import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
import org.apache.syncope.common.rest.api.service.UserRequestService;
@@ -54,6 +55,8 @@ public class UserRequestITCase extends AbstractITCase {
IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/directorGroupRequest.bpmn20.xml")));
bpmnProcessService.set("assignPrinterRequest",
IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/assignPrinterRequest.bpmn20.xml")));
+ bpmnProcessService.set("verifyAddedVariables",
+ IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/verifyAddedVariables.bpmn20.xml")));
}
@Test
@@ -65,7 +68,7 @@ public class UserRequestITCase extends AbstractITCase {
assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
// start request
- UserRequest req = userRequestService.start("directorGroupRequest", user.getKey());
+ UserRequest req = userRequestService.start("directorGroupRequest", user.getKey(), null);
assertNotNull(req);
assertEquals("directorGroupRequest", req.getBpmnProcess());
assertNotNull(req.getExecutionId());
@@ -91,7 +94,7 @@ public class UserRequestITCase extends AbstractITCase {
assertFalse(userService.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
// start request again
- req = userRequestService.start("directorGroupRequest", user.getKey());
+ req = userRequestService.start("directorGroupRequest", user.getKey(), null);
assertNotNull(req);
// 1st approval -> accept
@@ -114,7 +117,7 @@ public class UserRequestITCase extends AbstractITCase {
assertFalse(userService.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
// start request again
- req = userRequestService.start("directorGroupRequest", user.getKey());
+ req = userRequestService.start("directorGroupRequest", user.getKey(), null);
assertNotNull(req);
// 1st approval -> accept
@@ -149,7 +152,7 @@ public class UserRequestITCase extends AbstractITCase {
assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
// start request
- UserRequest req = userRequestService.start("directorGroupRequest", user.getKey());
+ UserRequest req = userRequestService.start("directorGroupRequest", user.getKey(), null);
assertNotNull(req);
// check that form was generated
@@ -186,7 +189,7 @@ public class UserRequestITCase extends AbstractITCase {
SyncopeClient client = clientFactory.create(user.getUsername(), "password123");
// start request as user
- UserRequest req = client.getService(UserRequestService.class).start("assignPrinterRequest", null);
+ UserRequest req = client.getService(UserRequestService.class).start("assignPrinterRequest", null, null);
assertNotNull(req);
// check (as admin) that a new form is available
@@ -244,4 +247,48 @@ public class UserRequestITCase extends AbstractITCase {
assertTrue(relationships.stream().
anyMatch(relationship -> "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(relationship.getOtherEndKey())));
}
+
+ @Test
+ public void addVariablesToUserRequestAtStart() {
+ assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
+
+ PagedResult<UserRequestForm> forms =
+ userRequestService.getForms(new UserRequestFormQuery.Builder().build());
+ int preForms = forms.getTotalCount();
+
+ UserTO user = createUser(UserITCase.getUniqueSample("addVariables@tirasa.net")).getEntity();
+ assertNotNull(user);
+
+ SyncopeClient client = clientFactory.create(user.getUsername(), "password123");
+
+ WorkflowTaskExecInput testInput = new WorkflowTaskExecInput();
+ testInput.getVariables().put("providedVariable", "test");
+
+ // start request as user
+ UserRequest req = client.getService(UserRequestService.class).start("verifyAddedVariables", null, testInput);
+ assertNotNull(req);
+
+ // check that a new form is available
+ forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build());
+ assertEquals(preForms + 1, forms.getTotalCount());
+
+ // get the form and verify the property value
+ PagedResult<UserRequestForm> userForms = userRequestService.
+ getForms(new UserRequestFormQuery.Builder().user(user.getKey()).build());
+ assertEquals(1, userForms.getTotalCount());
+
+ UserRequestForm form = userForms.getResult().get(0);
+ form = userRequestService.claimForm(form.getTaskId());
+ assertEquals(form.getProperty("providedVariable").get().getValue(), "test");
+
+ // cancel request
+ userRequestService.cancel(req.getExecutionId(), "nothing in particular");
+
+ // no more forms available
+ forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build());
+ assertEquals(preForms, forms.getTotalCount());
+
+ assertTrue(client.getService(UserRequestService.class).
+ list(new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty());
+ }
}