未验证 提交 b3790166 编写于 作者: B Bassam Al-Sarori 提交者: GitHub

Limit process access and actions (#3851)

* Limit process access and actions
Signed-off-by: NBassam Al-Sarori <2126270+balsarori@users.noreply.github.com>

* rename method test name
Signed-off-by: NBassam Al-Sarori <2126270+balsarori@users.noreply.github.com>
上级 5034a5dd
......@@ -54,6 +54,7 @@ import org.activiti.core.common.spring.security.policies.ProcessSecurityPolicies
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.impl.event.EventSubscriptionPayloadMappingProvider;
import org.activiti.runtime.api.conf.impl.ProcessRuntimeConfigurationImpl;
......@@ -174,6 +175,7 @@ public class ProcessRuntimeAutoConfiguration {
public ProcessRuntime processRuntime(RepositoryService repositoryService,
APIProcessDefinitionConverter processDefinitionConverter,
RuntimeService runtimeService,
TaskService taskService,
ProcessSecurityPoliciesManager securityPoliciesManager,
APIProcessInstanceConverter processInstanceConverter,
APIVariableInstanceConverter variableInstanceConverter,
......@@ -185,6 +187,7 @@ public class ProcessRuntimeAutoConfiguration {
return new ProcessRuntimeImpl(repositoryService,
processDefinitionConverter,
runtimeService,
taskService,
securityPoliciesManager,
processInstanceConverter,
variableInstanceConverter,
......
......@@ -58,8 +58,10 @@ import org.activiti.core.common.spring.security.policies.SecurityPolicyAccess;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstanceBuilder;
import org.activiti.engine.task.TaskQuery;
import org.activiti.runtime.api.model.impl.APIDeploymentConverter;
import org.activiti.runtime.api.model.impl.APIProcessDefinitionConverter;
import org.activiti.runtime.api.model.impl.APIProcessInstanceConverter;
......@@ -78,6 +80,8 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
private final RuntimeService runtimeService;
private final TaskService taskService;
private final APIProcessInstanceConverter processInstanceConverter;
private final APIVariableInstanceConverter variableInstanceConverter;
......@@ -97,6 +101,7 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
public ProcessRuntimeImpl(RepositoryService repositoryService,
APIProcessDefinitionConverter processDefinitionConverter,
RuntimeService runtimeService,
TaskService taskService,
ProcessSecurityPoliciesManager securityPoliciesManager,
APIProcessInstanceConverter processInstanceConverter,
APIVariableInstanceConverter variableInstanceConverter,
......@@ -108,6 +113,7 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
this.repositoryService = repositoryService;
this.processDefinitionConverter = processDefinitionConverter;
this.runtimeService = runtimeService;
this.taskService = taskService;
this.securityPoliciesManager = securityPoliciesManager;
this.processInstanceConverter = processInstanceConverter;
this.variableInstanceConverter = variableInstanceConverter;
......@@ -196,15 +202,9 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public ProcessInstance processInstance(String processInstanceId) {
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (internalProcessInstance == null) {
throw new NotFoundException("Unable to find process instance for the given id:'" + processInstanceId + "'");
}
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(processInstanceId);
if (!securityPoliciesManager.canRead(internalProcessInstance.getProcessDefinitionKey())) {
if (!canReadProcessInstance(internalProcessInstance)) {
throw new ActivitiObjectNotFoundException("You cannot read the process instance with Id:'" + processInstanceId + "' due to security policies violation");
}
return processInstanceConverter.from(internalProcessInstance);
......@@ -264,31 +264,27 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public ProcessInstance start(StartProcessPayload startProcessPayload) {
return processInstanceConverter.from(this.createProcessInstanceBuilder(startProcessPayload).start());
}
@Override
public ProcessInstance startCreatedProcess(String processInstanceId, StartProcessPayload startProcessPayload) {
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(processInstanceId);
if (internalProcessInstance == null) {
throw new NotFoundException("Unable to find process instance for the given id:'" + processInstanceId + "'");
}
if (!securityPoliciesManager.canRead(internalProcessInstance.getProcessDefinitionKey())) {
throw new ActivitiObjectNotFoundException("You cannot read the process instance with Id:'" + processInstanceId + "' due to security policies violation");
if (!canWriteProcessInstance(internalProcessInstance)) {
throw new ActivitiObjectNotFoundException("You cannot start the process instance with Id:'" + processInstanceId + "' due to security policies violation");
}
processVariablesValidator.checkStartProcessPayloadVariables(startProcessPayload, internalProcessInstance.getProcessDefinitionId());
return processInstanceConverter.from(runtimeService.startCreatedProcessInstance(internalProcessInstance, startProcessPayload.getVariables()));
}
@Override
public ProcessInstance create(CreateProcessInstancePayload startProcessPayload) {
return processInstanceConverter.from(createProcessInstanceBuilder(startProcessPayload).create());
public ProcessInstance create(CreateProcessInstancePayload createProcessInstancePayload) {
return processInstanceConverter.from(createProcessInstanceBuilder(createProcessInstancePayload).create());
}
private ProcessInstanceBuilder createProcessInstanceBuilder(StartProcessPayload startProcessPayload) {
......@@ -320,9 +316,9 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public ProcessInstance suspend(SuspendProcessPayload suspendProcessPayload) {
ProcessInstance processInstance = processInstance(suspendProcessPayload.getProcessInstanceId());
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(suspendProcessPayload.getProcessInstanceId());
checkUserCanWrite(processInstance.getProcessDefinitionKey());
checkUserCanWritePermissionOnProcessInstance(internalProcessInstance);
runtimeService.suspendProcessInstanceById(suspendProcessPayload.getProcessInstanceId());
return processInstanceConverter.from(runtimeService.createProcessInstanceQuery().processInstanceId(suspendProcessPayload.getProcessInstanceId()).singleResult());
......@@ -330,9 +326,9 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public ProcessInstance resume(ResumeProcessPayload resumeProcessPayload) {
ProcessInstance processInstance = processInstance(resumeProcessPayload.getProcessInstanceId());
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(resumeProcessPayload.getProcessInstanceId());
checkUserCanWrite(processInstance.getProcessDefinitionKey());
checkUserCanWritePermissionOnProcessInstance(internalProcessInstance);
runtimeService.activateProcessInstanceById(resumeProcessPayload.getProcessInstanceId());
return processInstanceConverter.from(runtimeService.createProcessInstanceQuery()
......@@ -341,12 +337,14 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public ProcessInstance delete(DeleteProcessPayload deleteProcessPayload) {
ProcessInstanceImpl processInstance = (ProcessInstanceImpl) processInstance(deleteProcessPayload.getProcessInstanceId());
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(deleteProcessPayload.getProcessInstanceId());
checkUserCanWrite(processInstance.getProcessDefinitionKey());
checkUserCanWritePermissionOnProcessInstance(internalProcessInstance);
runtimeService.deleteProcessInstance(deleteProcessPayload.getProcessInstanceId(),
deleteProcessPayload.getReason());
ProcessInstanceImpl processInstance = (ProcessInstanceImpl) processInstanceConverter.from(internalProcessInstance);
processInstance.setStatus(ProcessInstance.ProcessInstanceStatus.CANCELLED);
return processInstance;
}
......@@ -364,9 +362,9 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public void removeVariables(RemoveProcessVariablesPayload removeProcessVariablesPayload) {
ProcessInstanceImpl processInstance = (ProcessInstanceImpl) processInstance(removeProcessVariablesPayload.getProcessInstanceId());
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(removeProcessVariablesPayload.getProcessInstanceId());
checkUserCanWrite(processInstance.getProcessDefinitionKey());
checkUserCanWritePermissionOnProcessInstance(internalProcessInstance);
runtimeService.removeVariables(removeProcessVariablesPayload.getProcessInstanceId(),
removeProcessVariablesPayload.getVariableNames());
......@@ -375,12 +373,12 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public void setVariables(SetProcessVariablesPayload setProcessVariablesPayload) {
ProcessInstanceImpl processInstance = (ProcessInstanceImpl) processInstance(setProcessVariablesPayload.getProcessInstanceId());
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(setProcessVariablesPayload.getProcessInstanceId());
checkUserCanWrite(processInstance.getProcessDefinitionKey());
checkUserCanWritePermissionOnProcessInstance(internalProcessInstance);
processVariablesValidator.checkPayloadVariables(setProcessVariablesPayload,
processInstance.getProcessDefinitionId());
internalProcessInstance.getProcessDefinitionId());
runtimeService.setVariables(setProcessVariablesPayload.getProcessInstanceId(),
setProcessVariablesPayload.getVariables());
......@@ -416,9 +414,9 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
@Override
public ProcessInstance update(UpdateProcessPayload updateProcessPayload) {
ProcessInstance processInstance = processInstance(updateProcessPayload.getProcessInstanceId());
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = internalProcessInstance(updateProcessPayload.getProcessInstanceId());
checkUserCanWrite(processInstance.getProcessDefinitionKey());
checkUserCanWritePermissionOnProcessInstance(internalProcessInstance);
if (updateProcessPayload.getBusinessKey() != null) {
runtimeService.updateBusinessKey(updateProcessPayload.getProcessInstanceId(), updateProcessPayload.getBusinessKey());
......@@ -458,13 +456,20 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
return processInstance;
}
private void checkUserCanWrite(String processDefinitionKey) {
private void checkUserCanWritePermissionOnProcessDefinition(String processDefinitionKey) {
if (!securityPoliciesManager.canWrite(processDefinitionKey)) {
throw new ActivitiForbiddenException("Operation not permitted for " + processDefinitionKey + " due security policy violation");
}
}
private void checkUserCanWritePermissionOnProcessInstance(org.activiti.engine.runtime.ProcessInstance processInstance) {
if (!canWriteProcessInstance(processInstance)) {
throw new ActivitiForbiddenException("Operation not permitted for on process instance " + processInstance.getProcessInstanceId() + " due security policy violation");
}
}
protected ProcessDefinition getProcessDefinitionAndCheckUserHasRights(String processDefinitionId, String processDefinitionKey) {
String checkId = processDefinitionKey != null ? processDefinitionKey : processDefinitionId;
......@@ -475,7 +480,7 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
throw new IllegalStateException("At least Process Definition Id or Key needs to be provided to start a process");
}
checkUserCanWrite(processDefinition.getKey());
checkUserCanWritePermissionOnProcessDefinition(processDefinition.getKey());
return processDefinition;
}
......@@ -491,4 +496,39 @@ public class ProcessRuntimeImpl implements ProcessRuntime {
);
}
public org.activiti.engine.runtime.ProcessInstance internalProcessInstance(String processInstanceId) {
org.activiti.engine.runtime.ProcessInstance internalProcessInstance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (internalProcessInstance == null) {
throw new NotFoundException("Unable to find process instance for the given id:'" + processInstanceId + "'");
}
return internalProcessInstance;
}
private boolean canReadProcessInstance(org.activiti.engine.runtime.ProcessInstance processInstance) {
return securityPoliciesManager.canRead(processInstance.getProcessDefinitionKey()) &&
(securityManager.getAuthenticatedUserId().equals(processInstance.getStartUserId()) ||
isATaskAssigneeOrACandidate(processInstance.getProcessInstanceId()));
}
private boolean canWriteProcessInstance(org.activiti.engine.runtime.ProcessInstance processInstance) {
return securityPoliciesManager.canWrite(processInstance.getProcessDefinitionKey()) &&
securityManager.getAuthenticatedUserId().equals(processInstance.getStartUserId());
}
private boolean isATaskAssigneeOrACandidate(String processInstanceId) {
String authenticatedUserId = securityManager.getAuthenticatedUserId();
TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstanceId);
taskQuery.or()
.taskCandidateOrAssigned(securityManager.getAuthenticatedUserId(),
securityManager.getAuthenticatedUserGroups())
.taskOwner(authenticatedUserId)
.endOr();
return taskQuery.count() > 0;
}
}
......@@ -23,6 +23,7 @@ import org.activiti.core.common.spring.security.policies.ProcessSecurityPolicies
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
......@@ -44,6 +45,11 @@ public class ProcessRuntimeTestApp {
return mock(RuntimeService.class);
}
@Bean
public TaskService taskService() {
return mock(TaskService.class);
}
@Bean
public ManagementService managementService() {
return mock(ManagementService.class);
......
......@@ -47,6 +47,7 @@ import org.activiti.api.runtime.shared.security.SecurityManager;
import org.activiti.core.common.spring.security.policies.ProcessSecurityPoliciesManager;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl;
......@@ -78,6 +79,9 @@ public class ProcessRuntimeImplTest {
@Mock
private RuntimeService runtimeService;
@Mock
private TaskService taskService;
@Mock
private APIProcessInstanceConverter processInstanceConverter;
......@@ -105,6 +109,7 @@ public class ProcessRuntimeImplTest {
processRuntime = spy(new ProcessRuntimeImpl(repositoryService,
processDefinitionConverter,
runtimeService,
taskService,
securityPoliciesManager,
processInstanceConverter,
null,
......@@ -119,13 +124,15 @@ public class ProcessRuntimeImplTest {
@Test
public void updateShouldBeAbleToUpdateNameBusinessKey() {
//given
ProcessInstanceImpl process = new ProcessInstanceImpl();
process.setId("processId");
process.setProcessDefinitionKey("processDefinitionKey");
ExecutionEntityImpl internalProcessInstance = new ExecutionEntityImpl();
internalProcessInstance.setId("processId");
internalProcessInstance.setProcessDefinitionKey("processDefinitionKey");
internalProcessInstance.setStartUserId("testuser");
doReturn(process).when(processRuntime).processInstance("processId");
doReturn(internalProcessInstance).when(processRuntime).internalProcessInstance("processId");
doReturn(true).when(securityPoliciesManager).canWrite("processDefinitionKey");
doReturn("testuser").when(securityManager).getAuthenticatedUserId();
ProcessInstanceQuery processQuery = mock(ProcessInstanceQuery.class);
doReturn(processQuery).when(processQuery).processInstanceId("processId");
......@@ -135,6 +142,7 @@ public class ProcessRuntimeImplTest {
doReturn(internalProcess).when(processQuery).singleResult();
UpdateProcessPayload updateProcessPayload = ProcessPayloadBuilder.update()
.withProcessInstanceId("processId")
.withBusinessKey("businessKey")
......@@ -276,7 +284,8 @@ public class ProcessRuntimeImplTest {
ProcessInstanceQuery processQuery = mock(ProcessInstanceQuery.class);
doReturn(processQuery).when(processQuery).processInstanceId(processInstanceId);
doReturn(processQuery).when(runtimeService).createProcessInstanceQuery();
org.activiti.engine.runtime.ProcessInstance internalProcess = new ExecutionEntityImpl();
ExecutionEntityImpl internalProcess = new ExecutionEntityImpl();
internalProcess.setStartUserId("testuser");
internalProcess.setAppVersion(1);
doReturn(internalProcess).when(processQuery).singleResult();
when(runtimeService.startCreatedProcessInstance(internalProcess, new HashMap<>())).thenReturn(internalProcess);
......@@ -284,7 +293,8 @@ public class ProcessRuntimeImplTest {
apiProcessInstance.setBusinessKey("business-result");
apiProcessInstance.setId("999-999");
given(processInstanceConverter.from(internalProcess)).willReturn(apiProcessInstance);
given(securityPoliciesManager.canRead(any())).willReturn(true);
given(securityPoliciesManager.canWrite(any())).willReturn(true);
doReturn("testuser").when(securityManager).getAuthenticatedUserId();
//when
StartProcessPayload payload = new StartProcessPayload();
......
......@@ -28,10 +28,7 @@ import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.activiti.api.runtime.shared.identity.UserGroupManager;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.*;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.spring.process.model.ProcessExtensionModel;
import org.junit.jupiter.api.BeforeEach;
......@@ -62,6 +59,9 @@ public class ProcessVariablesInitiatorIT {
@MockBean
private RuntimeService runtimeService;
@MockBean
private TaskService taskService;
@MockBean
private ManagementService managementService;
......
......@@ -27,6 +27,7 @@ import org.activiti.core.common.spring.security.policies.ProcessSecurityPolicies
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.runtime.api.impl.ProcessAdminRuntimeImpl;
import org.activiti.runtime.api.impl.ProcessRuntimeImpl;
import org.activiti.runtime.api.impl.ProcessVariablesPayloadValidator;
......@@ -68,6 +69,9 @@ public class HistoryConfigurationTest {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private ProcessSecurityPoliciesManager securityPoliciesManager;
......@@ -108,6 +112,7 @@ public class HistoryConfigurationTest {
spy(new ProcessRuntimeImpl(repositoryService,
processDefinitionConverter,
runtimeService,
taskService,
securityPoliciesManager,
processInstanceConverter,
variableInstanceConverter,
......
......@@ -16,6 +16,7 @@
package org.activiti.spring.boot.process;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.groups.Tuple.tuple;
import static org.mockito.Mockito.spy;
......@@ -43,10 +44,12 @@ import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.core.common.spring.security.policies.ActivitiForbiddenException;
import org.activiti.core.common.spring.security.policies.ProcessSecurityPoliciesManager;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.runtime.api.impl.ProcessAdminRuntimeImpl;
import org.activiti.runtime.api.impl.ProcessRuntimeImpl;
import org.activiti.runtime.api.impl.ProcessVariablesPayloadValidator;
......@@ -75,6 +78,7 @@ public class ProcessRuntimeIT {
private static final String SUB_PROCESS = "subProcess";
private static final String SUPER_PROCESS = "superProcess";
private static final String TWO_TASKS_PROCESS = "twoTaskProcess";
private static final Pageable PAGEABLE = Pageable.of(0,
50);
public static final String CATEGORIZE_HUMAN_PROCESS_CATEGORY = "test-category";
......@@ -97,6 +101,9 @@ public class ProcessRuntimeIT {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private ProcessSecurityPoliciesManager securityPoliciesManager;
......@@ -146,6 +153,7 @@ public class ProcessRuntimeIT {
processRuntimeMock = spy(new ProcessRuntimeImpl(repositoryService,
processDefinitionConverter,
runtimeService,
taskService,
securityPoliciesManager,
processInstanceConverter,
variableInstanceConverter,
......@@ -877,7 +885,7 @@ public class ProcessRuntimeIT {
}
@Test
public void should_not_returnProcessesToNonInitiatorUser() {
public void should_not_returnProcessesToNonInitiatorAndNotTaskInvolvedUser() {
//given
processRuntime.start(ProcessPayloadBuilder.start()
.withProcessDefinitionKey(CATEGORIZE_HUMAN_PROCESS)
......@@ -894,4 +902,60 @@ public class ProcessRuntimeIT {
assertThat(processInstancePage).isNotNull();
assertThat(processInstancePage.getContent()).isEmpty();
}
@Test
public void should_returnProcessToTaskAssignee() {
//given
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start()
.withProcessDefinitionKey(SINGLE_TASK_PROCESS)
.build());
securityUtil.logInAs("garth");
//when
processInstance = processRuntime.processInstance(processInstance.getId());
assertThat(processInstance.getInitiator()).isEqualTo("user");
}
@Test
public void should_returnProcessToTaskCandidate() {
//given
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start()
.withProcessDefinitionKey(TWO_TASKS_PROCESS)
.build());
securityUtil.logInAs("garth");
//when
processInstance = processRuntime.processInstance(processInstance.getId());
assertThat(processInstance.getInitiator()).isEqualTo("user");
}
@Test
public void should_ForbidCancelingProcessInstanceUsingTaskInvolvedUser() {
//given
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start()
.withProcessDefinitionKey(SINGLE_TASK_PROCESS)
.build());
securityUtil.logInAs("garth");
assertThatThrownBy(() -> { processRuntime.delete(ProcessPayloadBuilder.delete(processInstance)); })
.isInstanceOf(ActivitiForbiddenException.class);
}
@Test
public void should_CancelProcessInstanceUsingInitiatorUser() {
//given
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start()
.withProcessDefinitionKey(SINGLE_TASK_PROCESS)
.build());
ProcessInstance deletedProcessInstance = processRuntime.delete(ProcessPayloadBuilder.delete(processInstance));
assertThat(deletedProcessInstance).isNotNull();
assertThat(deletedProcessInstance.getStatus()).isEqualTo(ProcessInstance.ProcessInstanceStatus.CANCELLED);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册