This is an automated email from the ASF dual-hosted git repository.
pefernan pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git
The following commit(s) were added to refs/heads/main by this push:
new 7fe7d7b5d0 [incubator-kie-issues#2303] Authorization incorrectly
enforced on all work items before when getting workItem by Id (#4285)
7fe7d7b5d0 is described below
commit 7fe7d7b5d07ace843f06222ab239636a438e18fd
Author: Pere Fernández <[email protected]>
AuthorDate: Thu May 14 09:16:36 2026 +0200
[incubator-kie-issues#2303] Authorization incorrectly enforced on all work
items before when getting workItem by Id (#4285)
* [incubator-kie-issues#2303] Authorization incorrectly enforced on all
work items before when getting workItem by Id
* - headers
* - Align variable names
---
.../java/org/kie/kogito/auth/SecurityPolicy.java | 10 +-
.../process/impl/AbstractProcessInstance.java | 26 +--
.../jbpm/bpmn2/task/BPMN2-MultipleUserTasks.bpmn | 236 +++++++++++++++++++++
.../jbpm/bpmn2/ProcessWorkItemSecurityTest.java | 175 +++++++++++++++
4 files changed, 430 insertions(+), 17 deletions(-)
diff --git
a/api/kogito-api/src/main/java/org/kie/kogito/auth/SecurityPolicy.java
b/api/kogito-api/src/main/java/org/kie/kogito/auth/SecurityPolicy.java
index a32ef609c1..393c5c75be 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/auth/SecurityPolicy.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/auth/SecurityPolicy.java
@@ -36,6 +36,8 @@ import org.slf4j.LoggerFactory;
*/
public class SecurityPolicy implements Policy {
+ static final String NOT_AUTHORIZED_MESSAGE_TEMPLATE = "Identity '%s' with
roles '%s' is not allowed to access workItem '%s'";
+
private static final Logger LOGGER =
LoggerFactory.getLogger(SecurityPolicy.class);
private IdentityProvider identity;
@@ -88,14 +90,14 @@ public class SecurityPolicy implements Policy {
List<String> roles = actualRoles != null ?
List.of(actualRoles.split(",")) : new ArrayList<>();
List<String> userRoles = new ArrayList<>(identity.getRoles());
userRoles.retainAll(roles);
- LOGGER.debug("enforcing identity {} and roles {} with potential
owners {} and potential groups {} and exclude groups {}",
- identity.getName(), identity.getRoles(), owners, roles,
excluded);
+ LOGGER.debug("enforcing identity {} and roles {} with potential
owners {} and potential groups {} and exclude groups {} on workItem {}",
+ identity.getName(), identity.getRoles(), owners, roles,
excluded, workItem.getStringId());
if (!owners.contains(identity.getName()) && userRoles.isEmpty()) {
LOGGER.debug("not authorized with owner {} against identity
{}", actualOwner, identity.getName());
- throw new NotAuthorizedException("this work item " +
workItem.getStringId() + " is not allows by this owner " + actualOwners + " or
" + actualRoles);
+ throw new
NotAuthorizedException(NOT_AUTHORIZED_MESSAGE_TEMPLATE.formatted(identity.getName(),
identity.getRoles(), workItem.getStringId()));
} else if (userRoles.isEmpty() && actualOwner != null &&
!identity.getName().equals(actualOwner)) {
LOGGER.debug("identity {} with roles {} not authorized in {}",
identity.getName(), identity.getRoles(), roles);
- throw new NotAuthorizedException("this work item " +
workItem.getStringId() + " is not allows by this owner " + actualOwner);
+ throw new
NotAuthorizedException(NOT_AUTHORIZED_MESSAGE_TEMPLATE.formatted(identity.getName(),
identity.getRoles(), workItem.getStringId()));
}
}
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
index 4bbb483677..d00495594c 100644
---
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
@@ -648,19 +648,19 @@ public abstract class AbstractProcessInstance<T extends
Model> implements Proces
@Override
public WorkItem workItem(String workItemId, Policy... policies) {
- return executeInWorkflowProcessInstanceRead(pi ->
pi.getNodeInstances(true).stream()
- .filter(WorkItemNodeInstance.class::isInstance)
- .map(WorkItemNodeInstance.class::cast)
- .filter(w -> enforceException(w.getWorkItem(), policies))
- .filter(ni -> ni.getWorkItemId().equals(workItemId))
- .map(this::toBaseWorkItem)
- .findAny()
- .orElseThrow(() -> new WorkItemNotFoundException("Work item
with id " + workItemId + " was not found in process instance " + id(),
workItemId)));
- }
-
- private boolean enforceException(KogitoWorkItem kogitoWorkItem, Policy...
policies) {
- Stream.of(policies).forEach(p -> p.enforce(kogitoWorkItem));
- return true;
+ return executeInWorkflowProcessInstanceRead(pi -> {
+ WorkItemNodeInstance nodeInstance =
pi.getNodeInstances(true).stream()
+ .filter(WorkItemNodeInstance.class::isInstance)
+ .map(WorkItemNodeInstance.class::cast)
+ .filter(ni -> ni.getWorkItemId().equals(workItemId))
+ .findAny()
+ .orElseThrow(() -> new WorkItemNotFoundException("Work
item with id '" + workItemId + "' was not found in process instance '" + id() +
"'", workItemId));
+
+ // Enforcing policies after WorkItem is found
+ Stream.of(policies).forEach(p ->
p.enforce(nodeInstance.getWorkItem()));
+
+ return toBaseWorkItem(nodeInstance);
+ });
}
@Override
diff --git
a/jbpm/jbpm-tests/src/test/bpmn/org/jbpm/bpmn2/task/BPMN2-MultipleUserTasks.bpmn
b/jbpm/jbpm-tests/src/test/bpmn/org/jbpm/bpmn2/task/BPMN2-MultipleUserTasks.bpmn
new file mode 100644
index 0000000000..0be78bc93f
--- /dev/null
+++
b/jbpm/jbpm-tests/src/test/bpmn/org/jbpm/bpmn2/task/BPMN2-MultipleUserTasks.bpmn
@@ -0,0 +1,236 @@
+<?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:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:drools="http://www.jboss.org/drools"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
namespace="https://kie.org/bpmn/_31F51AB8-0EF3-4643-ADA0-662F7F0864EA"
id="_9715D8BE-7A54-4F1A-AD64-CB2A3DF1AA8F"
name="BPMN_C7F3129F-0A63-4EB0-92E0-DD6741044B38">
+ <itemDefinition id="_30BE51F2-FCAF-486D-80FD-B43A1F339137"
structureRef="String" />
+ <process id="MultipleUserTasks" name="MultipleUserTasks"
drools:packageName="org.jbpm.bpmn2.task" processType="Public"
drools:version="1.0">
+ <startEvent id="_D78A69CD-C07E-4023-966E-9AACAFC14D53">
+ <outgoing>_4A20CADC-9357-4805-9D99-FA1F6D8156B1</outgoing>
+ </startEvent>
+ <endEvent id="_113AE158-AFD0-45FF-970B-DA78ECB0AE70">
+ <incoming>_19647CAD-DD0C-47A6-92D0-54EED1A21519</incoming>
+ </endEvent>
+ <inclusiveGateway id="_ABE745EA-9D0C-42C9-BB0A-06B5BA2F48DB"
gatewayDirection="Converging">
+ <incoming>_16F9F814-79B0-4055-8B41-79B122CADA1D</incoming>
+ <incoming>_902EDD57-1690-4F35-ACC2-F3C423AB2545</incoming>
+ <incoming>_0764F0BC-BC41-4A7B-86E1-7D904FBB6A75</incoming>
+ <incoming>_B617ADC8-FEC8-4CD5-B95E-DAC519260559</incoming>
+ <incoming>_4E214B5B-9B5B-4B43-A2E2-B0E7CD06116D</incoming>
+ <incoming>_7437ACD2-D820-4990-89FB-E7137BE9B93B</incoming>
+ <outgoing>_19647CAD-DD0C-47A6-92D0-54EED1A21519</outgoing>
+ </inclusiveGateway>
+ <parallelGateway id="_006B1615-FC0C-4EA9-9CC8-D0EA75151BB4"
gatewayDirection="Diverging">
+ <incoming>_4A20CADC-9357-4805-9D99-FA1F6D8156B1</incoming>
+ <outgoing>_A464DFB1-488B-45A4-A302-F5FEF0EF808D</outgoing>
+ <outgoing>_13EAB3F0-FBE7-46BA-9295-1DCE04826225</outgoing>
+ <outgoing>_8CC9EEBF-9CAF-4C05-9E05-3D03DC7722A6</outgoing>
+ </parallelGateway>
+ <userTask id="_7C0F7B65-3C20-4AB0-A6AE-AC5E69611ADB" name="Task 1">
+ <extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue>Task 1</drools:metaValue>
+ </drools:metaData>
+ </extensionElements>
+ <incoming>_A464DFB1-488B-45A4-A302-F5FEF0EF808D</incoming>
+ <outgoing>_16F9F814-79B0-4055-8B41-79B122CADA1D</outgoing>
+ <ioSpecification id="_B0A36B9D-E1C2-4878-973A-201672F22103">
+ <dataInput id="_DFE56A51-281D-42BC-8F20-EA19535DC473" name="TaskName"
drools:dtype="String" itemSubjectRef="_30BE51F2-FCAF-486D-80FD-B43A1F339137" />
+ <inputSet id="_289F7A08-DA78-411F-9F36-04DDCC70A091">
+ <dataInputRefs>_DFE56A51-281D-42BC-8F20-EA19535DC473</dataInputRefs>
+ </inputSet>
+ <outputSet id="_BFEADAE9-BDD3-453D-861E-27918DA7AC74" />
+ </ioSpecification>
+ <dataInputAssociation id="_EEE7845A-BDA2-48EF-A598-42AEAC80C05D">
+ <targetRef>_DFE56A51-281D-42BC-8F20-EA19535DC473</targetRef>
+ <assignment id="_96377010-C0E0-4983-9EB2-3A5CD81C8B66">
+ <from id="_5EE7634D-5D0B-4763-9239-9062D9897718"
xsi:type="tFormalExpression">Task1</from>
+ <to
id="_C0305D8C-A4F2-4B18-B04D-C976018989E0">_DFE56A51-281D-42BC-8F20-EA19535DC473</to>
+ </assignment>
+ </dataInputAssociation>
+ <potentialOwner id="_D5C00719-052C-43FF-98D1-310A9155DACA">
+ <resourceAssignmentExpression
id="_4C45F660-F256-447A-AAA0-6D809CC348D7">
+ <formalExpression
id="_3B409B95-4B2D-405A-BFEF-A1AF372DB8EB">john</formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ </userTask>
+ <userTask id="_9B38317B-02AC-458F-83C1-EB1FA0C34C8A" name="Task 2">
+ <incoming>_13EAB3F0-FBE7-46BA-9295-1DCE04826225</incoming>
+ <outgoing>_902EDD57-1690-4F35-ACC2-F3C423AB2545</outgoing>
+ <ioSpecification id="_B7BDA06F-B3AE-4B4D-9081-A95C2413A814">
+ <dataInput id="_02EEDAB6-115C-4AF1-8503-9288F27C0961" name="TaskName"
drools:dtype="String" itemSubjectRef="_30BE51F2-FCAF-486D-80FD-B43A1F339137" />
+ <inputSet id="_FAE3E4DF-586D-4720-9056-CCF8D99E3A24">
+ <dataInputRefs>_02EEDAB6-115C-4AF1-8503-9288F27C0961</dataInputRefs>
+ </inputSet>
+ <outputSet id="_E128773B-8618-4EB1-8CE9-A37CDA93B22B" />
+ </ioSpecification>
+ <dataInputAssociation id="_4C7366F2-D8C8-4A60-92FD-84752484E58D">
+ <targetRef>_02EEDAB6-115C-4AF1-8503-9288F27C0961</targetRef>
+ <assignment id="_A485F767-4501-4AC0-B92C-56987B10976E">
+ <from id="_13E0AB6B-9D63-4C79-A065-73F6A73DA332"
xsi:type="tFormalExpression">Task2</from>
+ <to
id="_60484DCA-D205-41F3-BCA0-CFBA4E621815">_02EEDAB6-115C-4AF1-8503-9288F27C0961</to>
+ </assignment>
+ </dataInputAssociation>
+ <potentialOwner id="_B1D30B3D-1D04-4853-B288-59EEBA7E97CE">
+ <resourceAssignmentExpression
id="_86663BC1-437B-438A-93EB-29900B9D7032">
+ <formalExpression
id="_EFC9063E-EB70-4818-AC61-10F2E941DCF8">mary</formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ <potentialOwner id="_35F1DE40-52ED-46BD-98E2-43084931E179">
+ <resourceAssignmentExpression
id="_9CD4F91E-64C0-4E2E-89A9-E66996242FDB">
+ <formalExpression
id="_74793440-955E-4F37-BF56-1BE6E0901670">john</formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ </userTask>
+ <userTask id="_82C790A5-0227-425A-A758-216F0E3E8D1A" name="Task 3">
+ <extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue>Task 3</drools:metaValue>
+ </drools:metaData>
+ </extensionElements>
+ <incoming>_8CC9EEBF-9CAF-4C05-9E05-3D03DC7722A6</incoming>
+ <outgoing>_0764F0BC-BC41-4A7B-86E1-7D904FBB6A75</outgoing>
+ <outgoing>_B617ADC8-FEC8-4CD5-B95E-DAC519260559</outgoing>
+ <outgoing>_4998E91D-54DE-4B96-BE0C-E58D0BDCF25D</outgoing>
+ <outgoing>_4E214B5B-9B5B-4B43-A2E2-B0E7CD06116D</outgoing>
+ <outgoing>_7437ACD2-D820-4990-89FB-E7137BE9B93B</outgoing>
+ <ioSpecification id="_24C1B0A8-50BC-4042-8C8E-8F76A8B975FC">
+ <dataInput id="_884DAAC5-EE9B-4F71-9C16-4FECA32912B5" name="TaskName"
drools:dtype="String" itemSubjectRef="_30BE51F2-FCAF-486D-80FD-B43A1F339137" />
+ <inputSet id="_3AB38DB2-94B0-4162-82B0-77560C9F1EBF">
+ <dataInputRefs>_884DAAC5-EE9B-4F71-9C16-4FECA32912B5</dataInputRefs>
+ </inputSet>
+ <outputSet id="_D88D2111-2997-43B9-A638-81285FBA7740" />
+ </ioSpecification>
+ <dataInputAssociation id="_0A44C071-C919-4D27-BE82-081FB3B1F41F">
+ <targetRef>_884DAAC5-EE9B-4F71-9C16-4FECA32912B5</targetRef>
+ <assignment id="_57FE16CB-6E69-4832-A61A-25A6D7AA179E">
+ <from id="_EEF8D98D-6439-4BDA-926B-DFA2E07F1F70"
xsi:type="tFormalExpression">Task3</from>
+ <to
id="_B6BF38AE-455F-4D75-8140-2E1C66134EC9">_884DAAC5-EE9B-4F71-9C16-4FECA32912B5</to>
+ </assignment>
+ </dataInputAssociation>
+ <potentialOwner id="_6E067A5A-94D4-4E1A-8F7A-F133F1306726">
+ <resourceAssignmentExpression
id="_32D47B16-206D-45AD-B448-28EDD9746A87">
+ <formalExpression
id="_CE76BC75-2234-44A8-99B3-FB1770C0F75A">alice</formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ <potentialOwner id="_8A4442F3-572E-42D5-AFAE-4F8D535E6D9E">
+ <resourceAssignmentExpression
id="_4B346A34-8B3C-4897-B5EF-05F63CAB43C1">
+ <formalExpression
id="_FFADFF0F-1F10-4704-AC77-9126E4F5E904">john</formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ <potentialOwner id="_8924B268-2AE6-4200-8EC0-22EFE3DDDBE1">
+ <resourceAssignmentExpression
id="_55C5D00A-858D-495F-8BB2-98D967917713">
+ <formalExpression
id="_DE28C3DC-BA7E-461B-9198-6DA5B26CF608">mary</formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ </userTask>
+ <sequenceFlow id="_4A20CADC-9357-4805-9D99-FA1F6D8156B1"
sourceRef="_D78A69CD-C07E-4023-966E-9AACAFC14D53"
targetRef="_006B1615-FC0C-4EA9-9CC8-D0EA75151BB4" />
+ <sequenceFlow id="_A464DFB1-488B-45A4-A302-F5FEF0EF808D"
sourceRef="_006B1615-FC0C-4EA9-9CC8-D0EA75151BB4"
targetRef="_7C0F7B65-3C20-4AB0-A6AE-AC5E69611ADB" />
+ <sequenceFlow id="_16F9F814-79B0-4055-8B41-79B122CADA1D"
sourceRef="_7C0F7B65-3C20-4AB0-A6AE-AC5E69611ADB"
targetRef="_ABE745EA-9D0C-42C9-BB0A-06B5BA2F48DB" />
+ <sequenceFlow id="_19647CAD-DD0C-47A6-92D0-54EED1A21519"
sourceRef="_ABE745EA-9D0C-42C9-BB0A-06B5BA2F48DB"
targetRef="_113AE158-AFD0-45FF-970B-DA78ECB0AE70" />
+ <sequenceFlow id="_13EAB3F0-FBE7-46BA-9295-1DCE04826225"
sourceRef="_006B1615-FC0C-4EA9-9CC8-D0EA75151BB4"
targetRef="_9B38317B-02AC-458F-83C1-EB1FA0C34C8A" />
+ <sequenceFlow id="_902EDD57-1690-4F35-ACC2-F3C423AB2545"
sourceRef="_9B38317B-02AC-458F-83C1-EB1FA0C34C8A"
targetRef="_ABE745EA-9D0C-42C9-BB0A-06B5BA2F48DB" />
+ <sequenceFlow id="_8CC9EEBF-9CAF-4C05-9E05-3D03DC7722A6"
sourceRef="_006B1615-FC0C-4EA9-9CC8-D0EA75151BB4"
targetRef="_82C790A5-0227-425A-A758-216F0E3E8D1A" />
+ <sequenceFlow id="_4E214B5B-9B5B-4B43-A2E2-B0E7CD06116D"
sourceRef="_82C790A5-0227-425A-A758-216F0E3E8D1A"
targetRef="_ABE745EA-9D0C-42C9-BB0A-06B5BA2F48DB" />
+ </process>
+ <bpmndi:BPMNDiagram id="_6627BC94-1286-431F-B9C6-DC55E7113C4C">
+ <bpmndi:BPMNPlane id="_E93CABDE-1006-48AD-8EB2-08CA9B2FB652">
+ <bpmndi:BPMNShape id="_99610030-2F4B-4589-B4DA-CCF7A34F2236"
bpmnElement="_D78A69CD-C07E-4023-966E-9AACAFC14D53">
+ <dc:Bounds x="0" y="160" width="60" height="60" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
bpmnElement="_006B1615-FC0C-4EA9-9CC8-D0EA75151BB4">
+ <dc:Bounds x="80" y="160" width="60" height="60" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_AF5A90B4-5326-4DCB-A403-F56AC209194F"
bpmnElement="_7C0F7B65-3C20-4AB0-A6AE-AC5E69611ADB">
+ <dc:Bounds x="180" y="20" width="180" height="100" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3"
bpmnElement="_ABE745EA-9D0C-42C9-BB0A-06B5BA2F48DB">
+ <dc:Bounds x="400" y="160" width="60" height="60" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_B91ECC67-DAFB-428B-BF0E-A03401335A54"
bpmnElement="_113AE158-AFD0-45FF-970B-DA78ECB0AE70">
+ <dc:Bounds x="520" y="160" width="60" height="60" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_578E8933-0016-4E20-AA5D-07CF2E9ADD64"
bpmnElement="_9B38317B-02AC-458F-83C1-EB1FA0C34C8A">
+ <dc:Bounds x="180" y="140" width="180" height="100" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_6C077FF8-AE79-48EE-A71F-2699B18BCFAB"
bpmnElement="_82C790A5-0227-425A-A758-216F0E3E8D1A">
+ <dc:Bounds x="180" y="260" width="180" height="100" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="_85199750-3AB1-4DC8-BAD5-3FE27CE39DE9-AUTO-TARGET"
bpmnElement="_A28EB9D1-7B79-4548-912F-AC7632A93E8C"
sourceElement="_99610030-2F4B-4589-B4DA-CCF7A34F2236"
targetElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD">
+ <di:waypoint x="30" y="190" />
+ <di:waypoint x="150" y="270" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="_F71F2D47-9ED0-4B42-8273-1C3EED955721-AUTO-SOURCE-AUTO-TARGET"
bpmnElement="_4A20CADC-9357-4805-9D99-FA1F6D8156B1"
sourceElement="_99610030-2F4B-4589-B4DA-CCF7A34F2236"
targetElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD">
+ <di:waypoint x="30" y="190" />
+ <di:waypoint x="110" y="190" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_EA314039-79D9-4A0C-B831-DA1EF670FC15-AUTO-TARGET"
bpmnElement="_B1C70BB6-2CA7-4386-8904-4C984E747ED4"
sourceElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
targetElement="_AF5A90B4-5326-4DCB-A403-F56AC209194F">
+ <di:waypoint x="110" y="190" />
+ <di:waypoint x="250" y="290" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="_81EF86CF-CF2B-4F79-8E54-313ABF17EB92-AUTO-SOURCE-AUTO-TARGET"
bpmnElement="_A464DFB1-488B-45A4-A302-F5FEF0EF808D"
sourceElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
targetElement="_AF5A90B4-5326-4DCB-A403-F56AC209194F">
+ <di:waypoint x="110" y="190" />
+ <di:waypoint x="270" y="70" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_9A84F742-842C-4F63-A480-AA115BD79922-AUTO-TARGET"
bpmnElement="_E3B98CD4-4A6D-4083-BF4F-0ADCF8D0CE03"
sourceElement="_AF5A90B4-5326-4DCB-A403-F56AC209194F"
targetElement="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3">
+ <di:waypoint x="250" y="70" />
+ <di:waypoint x="430" y="130" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="_A33592BC-430E-4122-8309-5EC89FD0D63C-AUTO-SOURCE-AUTO-TARGET"
bpmnElement="_16F9F814-79B0-4055-8B41-79B122CADA1D"
sourceElement="_AF5A90B4-5326-4DCB-A403-F56AC209194F"
targetElement="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3">
+ <di:waypoint x="270" y="70" />
+ <di:waypoint x="430" y="190" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_0A29E958-860D-4EBD-96FE-C5E897A4FF1C-AUTO-TARGET"
bpmnElement="_ECEC0ECE-2FD0-4271-8FC1-0A744ABE72EF"
sourceElement="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3"
targetElement="_B91ECC67-DAFB-428B-BF0E-A03401335A54">
+ <di:waypoint x="430" y="190" />
+ <di:waypoint x="650" y="250" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="_6E253313-C7C2-45EB-A1DD-B918956A71FD-AUTO-SOURCE-AUTO-TARGET"
bpmnElement="_19647CAD-DD0C-47A6-92D0-54EED1A21519"
sourceElement="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3"
targetElement="_B91ECC67-DAFB-428B-BF0E-A03401335A54">
+ <di:waypoint x="430" y="190" />
+ <di:waypoint x="550" y="190" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_E5DA1DF4-0FEF-44B3-90A4-F59AEC41688F-AUTO-TARGET"
bpmnElement="_80F77149-8C3F-47BC-8B2F-0706B65BC9E9"
sourceElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
targetElement="_578E8933-0016-4E20-AA5D-07CF2E9ADD64">
+ <di:waypoint x="110" y="190" />
+ <di:waypoint x="250" y="290" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="_02F679E8-75F4-475A-9325-0ACC7E11A503-AUTO-SOURCE-AUTO-TARGET"
bpmnElement="_13EAB3F0-FBE7-46BA-9295-1DCE04826225"
sourceElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
targetElement="_578E8933-0016-4E20-AA5D-07CF2E9ADD64">
+ <di:waypoint x="110" y="190" />
+ <di:waypoint x="270" y="190" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_68E47EC0-B754-4455-9017-E8D463A6D93B"
bpmnElement="_902EDD57-1690-4F35-ACC2-F3C423AB2545"
sourceElement="_578E8933-0016-4E20-AA5D-07CF2E9ADD64"
targetElement="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3">
+ <di:waypoint x="270" y="190" />
+ <di:waypoint x="400" y="190" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_4B86B1D0-2170-47FA-B749-8623C2F57888-AUTO-TARGET"
bpmnElement="_1EA19338-C30E-42DD-AA7B-5984B5CE0178"
sourceElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
targetElement="_6C077FF8-AE79-48EE-A71F-2699B18BCFAB">
+ <di:waypoint x="110" y="190" />
+ <di:waypoint x="250" y="290" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="_9A11212C-A6F5-4F87-86EA-2A39587B2033-AUTO-SOURCE-AUTO-TARGET"
bpmnElement="_8CC9EEBF-9CAF-4C05-9E05-3D03DC7722A6"
sourceElement="_221D16A0-73EB-43C5-BD7D-DCA18754B3AD"
targetElement="_6C077FF8-AE79-48EE-A71F-2699B18BCFAB">
+ <di:waypoint x="110" y="190" />
+ <di:waypoint x="270" y="310" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_3144246B-1095-47EC-95C0-FF5263483192-AUTO-TARGET"
bpmnElement="_2544A0D1-CD5F-4F68-8EBE-5E724D481042"
sourceElement="_6C077FF8-AE79-48EE-A71F-2699B18BCFAB"
targetElement="_A5F14C45-BAD4-4DAE-BB97-95D615E21D8D">
+ <di:waypoint x="270" y="310" />
+ <di:waypoint x="490" y="370" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_D4A571D2-47D8-49E6-8F14-416C732836E8"
bpmnElement="_4E214B5B-9B5B-4B43-A2E2-B0E7CD06116D"
sourceElement="_6C077FF8-AE79-48EE-A71F-2699B18BCFAB"
targetElement="_9522BAB9-FA35-486D-B59C-8E0E545BF7B3">
+ <di:waypoint x="360" y="310" />
+ <di:waypoint x="400" y="190" />
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</definitions>
diff --git
a/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/ProcessWorkItemSecurityTest.java
b/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/ProcessWorkItemSecurityTest.java
new file mode 100644
index 0000000000..fb429ada9a
--- /dev/null
+++
b/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/ProcessWorkItemSecurityTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.jbpm.bpmn2;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.jbpm.bpmn2.objects.TestWorkItemHandler;
+import org.jbpm.bpmn2.task.MultipleUserTasksModel;
+import org.jbpm.bpmn2.task.MultipleUserTasksProcess;
+import org.jbpm.test.utils.ProcessTestHelper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.kie.kogito.Application;
+import org.kie.kogito.auth.SecurityPolicy;
+import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
+import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
+import org.kie.kogito.internal.process.workitem.WorkItemNotFoundException;
+import org.kie.kogito.process.Process;
+import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.WorkItem;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class ProcessWorkItemSecurityTest extends JbpmBpmn2TestCase {
+
+ private static final String TASK_1 = "Task1";
+ private static final String TASK_2 = "Task2";
+ private static final String TASK_3 = "Task3";
+
+ private Application application;
+ private TestWorkItemHandler workItemHandler;
+
+ @BeforeEach
+ public void setUp() {
+ application = ProcessTestHelper.newApplication();
+ workItemHandler = new TestWorkItemHandler();
+ ProcessTestHelper.registerHandler(application, "Human Task",
workItemHandler);
+ }
+
+ @Test
+ public void testGetWorkItemWithAllWorkItemsAccess() {
+ Process<MultipleUserTasksModel> process =
MultipleUserTasksProcess.newProcess(application);
+
+ ProcessInstance<MultipleUserTasksModel> instance =
process.createInstance(process.createModel());
+
+ instance.start();
+
+ assertThat(instance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
+
+ List<KogitoWorkItem> allWorkItems = workItemHandler.getWorkItems();
+
+ assertThat(allWorkItems).hasSize(3);
+
+ String task1WorkItemId = getTaskWorkItem(allWorkItems, TASK_1);
+ String task2WorkItemId = getTaskWorkItem(allWorkItems, TASK_2);
+ String task3WorkItemId = getTaskWorkItem(allWorkItems, TASK_3);
+
+ List<WorkItem> assignedWorItems =
instance.workItems(SecurityPolicy.of("john", Collections.emptyList()));
+
+ assertThat(assignedWorItems).hasSize(3);
+
+ WorkItem task1WorkItem = instance.workItem(task1WorkItemId,
SecurityPolicy.of("john", Collections.emptyList()));
+
+ assertThat(task1WorkItem).isNotNull()
+ .hasFieldOrPropertyWithValue("id", task1WorkItemId);
+
+ WorkItem task2WorkItem = instance.workItem(task2WorkItemId,
SecurityPolicy.of("john", Collections.emptyList()));
+
+ assertThat(task2WorkItem).isNotNull()
+ .hasFieldOrPropertyWithValue("id", task2WorkItemId);
+
+ WorkItem task3WorkItem = instance.workItem(task3WorkItemId,
SecurityPolicy.of("john", Collections.emptyList()));
+
+ assertThat(task3WorkItem).isNotNull()
+ .hasFieldOrPropertyWithValue("id", task3WorkItemId);
+
+ instance.abort();
+
+ assertThat(instance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
+
+ assertThat(workItemHandler.getWorkItems()).hasSize(0);
+ }
+
+ @Test
+ public void testGetWorkItemWithRestrictedWorkItemsAccess() {
+ Process<MultipleUserTasksModel> process =
MultipleUserTasksProcess.newProcess(application);
+
+ ProcessInstance<MultipleUserTasksModel> instance =
process.createInstance(process.createModel());
+
+ instance.start();
+
+ assertThat(instance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
+
+ List<KogitoWorkItem> allWorkItems = workItemHandler.getWorkItems();
+
+ assertThat(allWorkItems).hasSize(3);
+
+ String task1WorkItemId = getTaskWorkItem(allWorkItems, TASK_1);
+ String task2WorkItemId = getTaskWorkItem(allWorkItems, TASK_2);
+ String task3WorkItemId = getTaskWorkItem(allWorkItems, TASK_3);
+
+ List<WorkItem> assignedWorItems =
instance.workItems(SecurityPolicy.of("alice", Collections.emptyList()));
+
+ assertThat(assignedWorItems).hasSize(1)
+ .anyMatch(workItem ->
workItem.getId().equals(task3WorkItemId));
+
+ assertThatThrownBy(() -> {
+ instance.workItem(task1WorkItemId, SecurityPolicy.of("alice",
Collections.emptyList()));
+ }).isInstanceOf(NotAuthorizedException.class)
+ .hasMessage("Identity 'alice' with roles '[]' is not allowed
to access workItem '" + task1WorkItemId + "'");
+
+ assertThatThrownBy(() -> {
+ instance.workItem(task2WorkItemId, SecurityPolicy.of("alice",
Collections.emptyList()));
+ }).isInstanceOf(NotAuthorizedException.class)
+ .hasMessage("Identity 'alice' with roles '[]' is not allowed
to access workItem '" + task2WorkItemId + "'");
+
+ WorkItem task3WorkItem = instance.workItem(task3WorkItemId,
SecurityPolicy.of("alice", Collections.emptyList()));
+
+ assertThat(task3WorkItem).isNotNull()
+ .hasFieldOrPropertyWithValue("id", task3WorkItemId);
+
+ instance.abort();
+
+ assertThat(instance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
+
+ assertThat(workItemHandler.getWorkItems()).hasSize(0);
+ }
+
+ @Test
+ public void testGetUnexistingWorkItem() {
+ Process<MultipleUserTasksModel> process =
MultipleUserTasksProcess.newProcess(application);
+
+ ProcessInstance<MultipleUserTasksModel> instance =
process.createInstance(process.createModel());
+
+ instance.start();
+
+ assertThat(instance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
+
+ assertThatThrownBy(() -> {
+ instance.workItem("wrongWorkItemIdThatWillFail",
SecurityPolicy.of("alice", Collections.emptyList()));
+ }).isInstanceOf(WorkItemNotFoundException.class)
+ .hasMessage("Work item with id 'wrongWorkItemIdThatWillFail'
was not found in process instance '" + instance.id() + "'");
+
+ instance.abort();
+
+ assertThat(instance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
+ }
+
+ String getTaskWorkItem(Collection<KogitoWorkItem> allWorkItems, String
taskName) {
+ return allWorkItems.stream()
+ .filter(kogitoWorkItem ->
taskName.equals(kogitoWorkItem.getParameter("TaskName")))
+ .map(KogitoWorkItem::getStringId)
+ .findFirst()
+ .orElseThrow();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]