From aca1ad7c4edbd5cb2edd787882eabfd47d1f433b Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 1 Mar 2017 21:28:06 +0100 Subject: [PATCH 1/3] Simplified TestStrings story test by using global policy rules. --- .../primary/policy/ApprovalSchemaBuilder.java | 4 + .../repo/sql/SqlRepositoryServiceImpl.java | 2 +- .../midpoint/testing/story/TestStrings.java | 134 +++++----- .../strings/roles-specific/a-test-1.xml | 21 +- .../strings/roles-specific/a-test-2a.xml | 32 +-- .../strings/roles-specific/a-test-2b.xml | 32 +-- .../strings/roles-specific/a-test-3a.xml | 11 +- .../strings/roles-specific/a-test-3b.xml | 11 +- .../strings/roles-specific/a-test-3x.xml | 10 - .../strings/roles-specific/a-test-3y.xml | 10 - .../strings/roles-specific/a-test-4.xml | 7 +- .../strings/roles/global-policy-rules.xml | 232 ++++++++++++++++++ ...ole-approval-escalation-then-rejection.xml | 70 ------ .../roles/metarole-approval-line-managers.xml | 51 ---- .../roles/metarole-approval-rejection.xml | 50 ---- .../metarole-approval-role-approvers-all.xml | 47 ---- ...metarole-approval-role-approvers-first.xml | 6 +- .../roles/metarole-approval-security.xml | 5 +- .../strings/roles/metarole-approval-sod.xml | 69 ------ testing/story/testng-integration.xml | 1 + 20 files changed, 321 insertions(+), 484 deletions(-) create mode 100644 testing/story/src/test/resources/strings/roles/global-policy-rules.xml delete mode 100644 testing/story/src/test/resources/strings/roles/metarole-approval-escalation-then-rejection.xml delete mode 100644 testing/story/src/test/resources/strings/roles/metarole-approval-line-managers.xml delete mode 100644 testing/story/src/test/resources/strings/roles/metarole-approval-rejection.xml delete mode 100644 testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-all.xml delete mode 100644 testing/story/src/test/resources/strings/roles/metarole-approval-sod.xml diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java index 9714de10507..da3046da083 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java @@ -269,6 +269,10 @@ private void sortFragments(List fragments) { if (o1 == null || o2 == null) { return MiscUtil.compareNullLast(o1, o2); } + int c = Integer.compare(o1, o2); + if (c != 0) { + return c; + } // non-mergeable first boolean m1 = BooleanUtils.isTrue(s1.isMergeable()); boolean m2 = BooleanUtils.isTrue(s2.isMergeable()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index e5573af1fa8..ac4a3c5f133 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -932,7 +932,7 @@ public boolean selectorMatches(ObjectSelectorType objectS // Type if (specTypeQName != null && !QNameUtil.match(specTypeQName, objectDefinition.getTypeName())) { - logger.trace("{} type mismatch, expected {}, was {}", specTypeQName, objectDefinition.getTypeName()); + logger.trace("{} type mismatch, expected {}, was {}", logMessagePrefix, specTypeQName, objectDefinition.getTypeName()); return false; } diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java index 536d40d6ace..ecb21045c9c 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java @@ -59,6 +59,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.util.*; +import java.util.stream.Collectors; import static com.evolveum.midpoint.prism.util.PrismAsserts.assertReferenceValues; import static com.evolveum.midpoint.test.IntegrationTestTools.display; @@ -96,22 +97,12 @@ public class TestStrings extends AbstractStoryTest { private static final File FORM_USER_DETAILS_FILE = new File(ROLES_DIR, "form-user-details.xml"); private static String formUserDetailsOid; - private static final File METAROLE_APPROVAL_LINE_MANAGERS_FILE = new File(ROLES_DIR, "metarole-approval-line-managers.xml"); - private static String metaroleApprovalLineManagersOid; - private static final File METAROLE_APPROVAL_ROLE_APPROVERS_ALL_FILE = new File(ROLES_DIR, "metarole-approval-role-approvers-all.xml"); - private static String metaroleApprovalRoleApproversAllOid; private static final File METAROLE_APPROVAL_ROLE_APPROVERS_FIRST_FILE = new File(ROLES_DIR, "metarole-approval-role-approvers-first.xml"); private static String metaroleApprovalRoleApproversFirstOid; private static final File METAROLE_APPROVAL_ROLE_APPROVERS_FORM_FILE = new File(ROLES_DIR, "metarole-approval-role-approvers-form.xml"); private static String metaroleApprovalRoleApproversFormOid; private static final File METAROLE_APPROVAL_SECURITY_FILE = new File(ROLES_DIR, "metarole-approval-security.xml"); private static String metaroleApprovalSecurityOid; - private static final File METAROLE_APPROVAL_SOD_FILE = new File(ROLES_DIR, "metarole-approval-sod.xml"); - private static String metaroleApprovalSodOid; - private static final File METAROLE_ESCALATION_THEN_REJECTION_FILE = new File(ROLES_DIR, "metarole-approval-escalation-then-rejection.xml"); - private static String metaroleEscalationThenRejectionOid; - private static final File METAROLE_REJECTION_FILE = new File(ROLES_DIR, "metarole-approval-rejection.xml"); - private static String metaroleRejectionOid; private static final File ROLE_A_TEST_1 = new File(ROLES_SPECIFIC_DIR, "a-test-1.xml"); private static String roleATest1Oid; @@ -147,6 +138,8 @@ public class TestStrings extends AbstractStoryTest { private static final File USER_LECHUCK_FILE = new File(USERS_DIR, "lechuck.xml"); private static String userLechuckOid; + private static final File CONFIG_WITH_GLOBAL_RULES_FILE = new File(ROLES_DIR, "global-policy-rules.xml"); + public static final String NS_STRINGS_EXT = "http://midpoint.evolveum.com/xml/ns/strings"; private static final String DUMMY_WORK_ITEM_LIFECYCLE = "dummy:workItemLifecycle"; @@ -158,6 +151,16 @@ public class TestStrings extends AbstractStoryTest { public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); + // copy rules from the file into live system config object + PrismObject rules = prismContext.parserFor(CONFIG_WITH_GLOBAL_RULES_FILE).parse(); + repositoryService.modifyObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), + DeltaBuilder.deltaFor(SystemConfigurationType.class, prismContext) + .item(SystemConfigurationType.F_GLOBAL_POLICY_RULE).add( + rules.asObjectable().getGlobalPolicyRule().stream() + .map(r -> r.clone().asPrismContainerValue()) + .collect(Collectors.toList())) + .asItemDeltas(), initResult); + // we prefer running trigger scanner by hand resetTriggerTask(initResult); // and we don't need validity scanner @@ -174,14 +177,9 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti orgSodApproversOid = repoAddObjectFromFile(ORG_SOD_APPROVERS_FILE, initResult).getOid(); formUserDetailsOid = repoAddObjectFromFile(FORM_USER_DETAILS_FILE, initResult).getOid(); - metaroleApprovalLineManagersOid = repoAddObjectFromFile(METAROLE_APPROVAL_LINE_MANAGERS_FILE, initResult).getOid(); - metaroleApprovalRoleApproversAllOid = repoAddObjectFromFile(METAROLE_APPROVAL_ROLE_APPROVERS_ALL_FILE, initResult).getOid(); metaroleApprovalRoleApproversFirstOid = repoAddObjectFromFile(METAROLE_APPROVAL_ROLE_APPROVERS_FIRST_FILE, initResult).getOid(); metaroleApprovalRoleApproversFormOid = repoAddObjectFromFile(METAROLE_APPROVAL_ROLE_APPROVERS_FORM_FILE, initResult).getOid(); metaroleApprovalSecurityOid = repoAddObjectFromFile(METAROLE_APPROVAL_SECURITY_FILE, initResult).getOid(); - metaroleApprovalSodOid = repoAddObjectFromFile(METAROLE_APPROVAL_SOD_FILE, initResult).getOid(); - metaroleEscalationThenRejectionOid = repoAddObjectFromFile(METAROLE_ESCALATION_THEN_REJECTION_FILE, initResult).getOid(); - metaroleRejectionOid = repoAddObjectFromFile(METAROLE_REJECTION_FILE, initResult).getOid(); roleATest1Oid = addAndRecompute(ROLE_A_TEST_1, initTask, initResult); roleATest2aOid = addAndRecompute(ROLE_A_TEST_2A, initTask, initResult); @@ -981,7 +979,7 @@ public void test220FormRoleAssignmentStart() throws Exception { assertNotAssignedRole(getUser(userBobOid), roleATest4Oid); List workItems = getWorkItems(task, result); - displayWorkItems("Work item after 1st approval", workItems); + displayWorkItems("Work item after start", workItems); PrismObject wfTask = getTask(workItems.get(0).getTaskRef().getOid()); display("wfTask", wfTask); @@ -989,10 +987,10 @@ public void test220FormRoleAssignmentStart() throws Exception { ItemApprovalProcessStateType info = WfContextUtil.getItemApprovalProcessInfo(wfTask.asObjectable().getWorkflowContext()); ApprovalSchemaType schema = info.getApprovalSchema(); - assertEquals("Wrong # of approval levels", 1, schema.getLevel().size()); - assertApprovalLevel(schema, 1, "Role approvers (all)", "P5D", 2); - assertStage(wfTask, 1, 1, "Role approvers (all)", null); -// assertAssignee(workItem, userLechuckOid, userLechuckOid); + assertEquals("Wrong # of approval levels", 2, schema.getLevel().size()); + assertApprovalLevel(schema, 1, "Line managers", "P5D", 2); + assertApprovalLevel(schema, 2, "Role approvers (first)", "P5D", 2); + assertStage(wfTask, 1, 2, "Line managers", null); List lifecycleMessages = dummyTransport.getMessages(DUMMY_WORK_ITEM_LIFECYCLE); List allocationMessages = dummyTransport.getMessages(DUMMY_WORK_ITEM_ALLOCATION); @@ -1001,21 +999,51 @@ public void test220FormRoleAssignmentStart() throws Exception { display("work items allocation notifications", allocationMessages); display("processes notifications", processMessages); -// assertEquals("Wrong # of work items lifecycle messages", 1, lifecycleMessages.size()); -// assertMessage(lifecycleMessages.get(0), "lechuck@evolveum.com", "A new work item has been created", -// "Stage: Line managers (1/3)", "Allocated to: Captain LeChuck (lechuck)", "(in 5 days)"); -// -// assertEquals("Wrong # of work items allocation messages", 1, allocationMessages.size()); -// assertMessage(allocationMessages.get(0), "lechuck@evolveum.com", "Work item has been allocated to you", -// "Stage: Line managers (1/3)", "Allocated to: Captain LeChuck (lechuck)", "(in 5 days)"); -// -// assertEquals("Wrong # of process messages", 1, processMessages.size()); -// assertMessage(processMessages.get(0), "administrator@evolveum.com", "Workflow process instance has been started", -// "Process instance name: Assigning a-test-1 to bob", "Stage: Line managers (1/3)"); + display("audit", dummyAuditService); + } + + @Test + public void test221FormApproveByLechuck() throws Exception { + final String TEST_NAME = "test221FormApproveByLechuck"; + TestUtil.displayTestTile(this, TEST_NAME); + Task task = createTask(TestStrings.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + dummyAuditService.clear(); + dummyTransport.clearMessages(); + + // GIVEN + login(userAdministrator); + WorkItemType workItem = getWorkItem(task, result); + + // WHEN + PrismObject lechuck = getUserFromRepo(userLechuckOid); + login(lechuck); + workflowService.completeWorkItem(workItem.getWorkItemId(), true, "OK. LeChuck", null, result); + + // THEN + login(userAdministrator); + List workItems = getWorkItems(task, result); + displayWorkItems("Work item after 1st approval", workItems); + PrismObject wfTask = getTask(workItems.get(0).getTaskRef().getOid()); + assertStage(wfTask, 2, 2, "Role approvers (first)", null); + + ApprovalLevelType level = WfContextUtil.getCurrentApprovalLevel(wfTask.asObjectable().getWorkflowContext()); + assertEquals("Wrong evaluation strategy", LevelEvaluationStrategyType.FIRST_DECIDES, level.getEvaluationStrategy()); + + // notifications + List lifecycleMessages = dummyTransport.getMessages(DUMMY_WORK_ITEM_LIFECYCLE); + List allocationMessages = dummyTransport.getMessages(DUMMY_WORK_ITEM_ALLOCATION); + List processMessages = dummyTransport.getMessages(DUMMY_PROCESS); + display("work items lifecycle notifications", lifecycleMessages); + display("work items allocation notifications", allocationMessages); + display("processes notifications", processMessages); + dummyTransport.clearMessages(); display("audit", dummyAuditService); } + @Test public void test222FormApproveByCheese() throws Exception { final String TEST_NAME = "test222FormApproveByCheese"; @@ -1044,13 +1072,13 @@ public void test222FormApproveByCheese() throws Exception { login(userAdministrator); workItems = getWorkItems(task, result); - displayWorkItems("Work item after 1st approval", workItems); - assertEquals("Wrong # of work items after 1st approval", 2, workItems.size()); + displayWorkItems("Work item after 2nd approval", workItems); + assertEquals("Wrong # of work items after 2nd approval", 0, workItems.size()); PrismObject wfTask = getTask(workItem.getTaskRef().getOid()); - display("wfTask after 1st approval", wfTask); + display("wfTask after 2nd approval", wfTask); - assertStage(wfTask, 1, 1, "Role approvers (all)", null); + assertStage(wfTask, 2, 2, "Role approvers (first)", null); // assertTriggers(wfTask, 4); // notifications @@ -1061,39 +1089,10 @@ public void test222FormApproveByCheese() throws Exception { display("work items allocation notifications", allocationMessages); display("processes notifications", processMessages); -// assertEquals("Wrong # of work items lifecycle messages", 3, lifecycleMessages.size()); -// assertEquals("Wrong # of work items allocation messages", 3, allocationMessages.size()); -// assertNull("process messages", processMessages); - -// Map sorted = sortByRecipientsSingle(lifecycleMessages); -// assertMessage(sorted.get("lechuck@evolveum.com"), "lechuck@evolveum.com", "Work item has been completed", -// "Work item: Approve assigning a-test-1 to bob", "Stage: Line managers (1/3)", -// "Allocated to: Captain LeChuck (lechuck)", "Result: APPROVED", "^Deadline:"); -// assertMessage(sorted.get("elaine@evolveum.com"), "elaine@evolveum.com", "A new work item has been created", -// "Work item: Approve assigning a-test-1 to bob", "Stage: Security (2/3)", -// "Allocated to: Elaine Marley (elaine)", "(in 7 days)", "^Result:"); -// assertMessage(sorted.get("barkeeper@evolveum.com"), "barkeeper@evolveum.com", "A new work item has been created", -// "Work item: Approve assigning a-test-1 to bob", "Stage: Security (2/3)", -// "Allocated to: Horridly Scarred Barkeep (barkeeper)", "(in 7 days)", "^Result:"); -// -// Map sorted2 = sortByRecipientsSingle(allocationMessages); -// assertMessage(sorted2.get("lechuck@evolveum.com"), "lechuck@evolveum.com", "Work item has been completed", -// "Work item: Approve assigning a-test-1 to bob", "Stage: Line managers (1/3)", -// "Allocated to: Captain LeChuck (lechuck)", "Result: APPROVED", "^Deadline:"); -// assertMessage(sorted2.get("elaine@evolveum.com"), "elaine@evolveum.com", "Work item has been allocated to you", -// "Work item: Approve assigning a-test-1 to bob", "Stage: Security (2/3)", "Allocated to: Elaine Marley (elaine)", -// "(in 7 days)", "^Result:"); -// assertMessage(sorted2.get("barkeeper@evolveum.com"), "barkeeper@evolveum.com", "Work item has been allocated to you", -// "Work item: Approve assigning a-test-1 to bob", "Stage: Security (2/3)", -// "Allocated to: Horridly Scarred Barkeep (barkeeper)", "(in 7 days)", "^Result:"); - - // events -// List events = assertEvents(wfTask, 1); -// assertCompletionEvent(events.get(0), userLechuckOid, userLechuckOid, 1, "Line managers", WorkItemOutcomeType.APPROVE, "OK. LeChuck"); - + // audit display("audit", dummyAuditService); List records = dummyAuditService.getRecords(); - assertEquals("Wrong # of audit records", 1, records.size()); + assertEquals("Wrong # of audit records", 4, records.size()); AuditEventRecord record = records.get(0); Collection> deltas = record.getDeltas(); assertEquals("Wrong # of deltas in audit record", 1, deltas.size()); @@ -1104,6 +1103,9 @@ public void test222FormApproveByCheese() throws Exception { fail("Wrong item path in delta: expected: "+new ItemPath(UserType.F_DESCRIPTION)+", found: "+itemDelta.getPath()); } assertEquals("Wrong value in delta", "Hello", itemDelta.getValuesToReplace().iterator().next().getRealValue()); + + // record #1, #2: cancellation of work items of other approvers + // record #3: finishing process execution } diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-1.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-1.xml index 7840687aa23..c9c91c6257b 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-1.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-1.xml @@ -21,16 +21,6 @@ a-test-1 Approved by managers, security and role approvers (all) - - - - name - metarole-approval-line-managers - - - - - @@ -40,17 +30,8 @@ - - - - - name - metarole-approval-role-approvers-all - - - - + test \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-2a.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-2a.xml index 5b128847d97..c712c982b64 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-2a.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-2a.xml @@ -20,36 +20,6 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-2a Approved by managers and role approvers (all) - exclusive with test-2b - - - - - name - metarole-approval-line-managers - - - - - - - - - name - metarole-approval-role-approvers-all - - - - - - - - - name - metarole-approval-sod - - - - @@ -64,5 +34,5 @@ - + test \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-2b.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-2b.xml index 05f322234ee..ab364b218e7 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-2b.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-2b.xml @@ -20,36 +20,6 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-2b Approved by managers and role approvers (first) - exclusive with test-2a - - - - - name - metarole-approval-line-managers - - - - - - - - - name - metarole-approval-role-approvers-all - - - - - - - - - name - metarole-approval-sod - - - - @@ -64,5 +34,5 @@ - + test \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-3a.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-3a.xml index 1b2060bd157..b6f6b378586 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-3a.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-3a.xml @@ -20,17 +20,8 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-3a Testing SoD with induced role (test-3x) - - - - - name - metarole-approval-sod - - - - + test \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-3b.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-3b.xml index 75467895632..a367ddb4952 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-3b.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-3b.xml @@ -20,17 +20,8 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-3b Testing SoD with induced role (test-3y) - - - - - name - metarole-approval-sod - - - - + test \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-3x.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-3x.xml index 15bf304fdde..cc4229f71d3 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-3x.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-3x.xml @@ -20,16 +20,6 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-3x Embedded role, conflicting with 3y - - - - - name - metarole-approval-sod - - - - diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-3y.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-3y.xml index b5f3dc54d65..e0168ef0670 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-3y.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-3y.xml @@ -20,16 +20,6 @@ xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-3y Embedded role, conflicting with 3x - - - - - name - metarole-approval-sod - - - - diff --git a/testing/story/src/test/resources/strings/roles-specific/a-test-4.xml b/testing/story/src/test/resources/strings/roles-specific/a-test-4.xml index 5d6e0dd1500..1438492f4b3 100644 --- a/testing/story/src/test/resources/strings/roles-specific/a-test-4.xml +++ b/testing/story/src/test/resources/strings/roles-specific/a-test-4.xml @@ -19,13 +19,13 @@ xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> a-test-4 - Approved by role managers but with a form + Approved by role managers (first, form) name - metarole-approval-role-approvers-all + metarole-approval-role-approvers-form @@ -35,7 +35,7 @@ name - metarole-approval-role-approvers-form + metarole-approval-role-approvers-first @@ -43,4 +43,5 @@ + test \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles/global-policy-rules.xml b/testing/story/src/test/resources/strings/roles/global-policy-rules.xml new file mode 100644 index 00000000000..974e5ad98b7 --- /dev/null +++ b/testing/story/src/test/resources/strings/roles/global-policy-rules.xml @@ -0,0 +1,232 @@ + + + + + + + + sod-approval + Approval action for (existing) exclusion violations + + + http://midpoint.evolveum.com/xml/ns/public/model/policy/situation#exclusionViolation + + + + + + 30 + + + + SoD + + + + name + SoD Approvers + + + run + + firstDecides + + + + + + UserType + + + RoleType + + + + + role-approvers-all-approval + Approval of role assignment by all the role approvers + + + + + + + 40 + true + 1 + + + + Role approvers (all) + approver + allMustApprove + reject + + + + + + UserType + + + RoleType + + + roleType + test + + + + + + + line-manager-approval + Approval of role assignment by the line manager(s) + + + + + + + 10 + true + + + + Line managers + + + + allMustApprove + reject + + + + + + UserType + + + RoleType + + + roleType + test + + + + + + + + + escalate-then-reject-for-levels-20-30 + Automatic escalation followed by rejection for levels 10 and 40 (LM, role approvers) + + + + + + + 10 + 40 + + + + P5D + + + + + + + P9D + addAssignees + P1D + Line manager escalation + + + + + + + + reject + P2D + P2DT12H + + + 1 + 1 + + + + + + + UserType + + + RoleType + + + + + auto-reject-for-levels-20-30 + Automatic rejection for levels 20 and 30 (security, SoD) + + + + + + + 20 + 30 + + + + P7D + + + + + reject + P2D + + + + + + + + + UserType + + + RoleType + + + + diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-escalation-then-rejection.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-escalation-then-rejection.xml deleted file mode 100644 index 0315a5aaf79..00000000000 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-escalation-then-rejection.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - metarole-approval-escalation-then-rejection - Needs to be used along with some other approvals - Metarole: escalation feature for approvals - - - - - - - - - 10 - 40 - - - - P5D - - - - - - - P9D - addAssignees - P1D - Line manager escalation - - - - - - - - reject - P2D - P2DT12H - - - 1 - 1 - - - - - - - - \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-line-managers.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-line-managers.xml deleted file mode 100644 index 81809ff1615..00000000000 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-line-managers.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - metarole-approval-line-managers - Requests to assign role holding this metarole will be approved by the line manager(s) - Metarole: approval by the line manager(s) - - - - - - - - - 10 - true - - - - Line managers - - - - allMustApprove - reject - - - - - - - - - - \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-rejection.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-rejection.xml deleted file mode 100644 index ada80655374..00000000000 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-rejection.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - metarole-approval-rejection - Needs to be used along with some other approvals - Metarole: auto-rejection feature for approvals - - - - - - - - - 20 - 30 - - - - P7D - - - - - reject - P2D - - - - - - - - - - \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-all.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-all.xml deleted file mode 100644 index 7e08232bd99..00000000000 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-all.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - metarole-approval-role-approvers-all - Requests to assign role holding this metarole will be approved by the role approver(s) using "all must approve" method - Metarole: approval by the role approver(s) - all must approve - - - - - - - - - 40 - true - - - - Role approvers (all) - approver - allMustApprove - reject - - - - - - - - - - \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-first.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-first.xml index 486d5d0a91d..cc548ed3ab4 100644 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-first.xml +++ b/testing/story/src/test/resources/strings/roles/metarole-approval-role-approvers-first.xml @@ -26,8 +26,12 @@ + 40 - true + true + 2 diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-security.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-security.xml index ad8a1732374..a6a5c450d16 100644 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-security.xml +++ b/testing/story/src/test/resources/strings/roles/metarole-approval-security.xml @@ -43,15 +43,12 @@ run firstDecides - onWorkItemCreation reject + onWorkItemCreation - - - \ No newline at end of file diff --git a/testing/story/src/test/resources/strings/roles/metarole-approval-sod.xml b/testing/story/src/test/resources/strings/roles/metarole-approval-sod.xml deleted file mode 100644 index 3c9341f2bb8..00000000000 --- a/testing/story/src/test/resources/strings/roles/metarole-approval-sod.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - metarole-approval-sod - All assignments of this metarole-bearer that are in exclusion conflicts will have to be approved - Metarole: approval by the SoD people - - - - - http://midpoint.evolveum.com/xml/ns/public/model/policy/situation#exclusionViolation - - - - - - 30 - - - - SoD - - - - name - SoD Approvers - - - run - - firstDecides - reject - - - - - - - - - - - \ No newline at end of file diff --git a/testing/story/testng-integration.xml b/testing/story/testng-integration.xml index b17b8e7adec..5bde53c2bdd 100644 --- a/testing/story/testng-integration.xml +++ b/testing/story/testng-integration.xml @@ -38,6 +38,7 @@ + From 406405e44e4cc736f86c7f9254e296b1c48d39b2 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 1 Mar 2017 22:50:05 +0100 Subject: [PATCH 2/3] Storing operation business context in workflow process (in "process created" event). --- .../page/admin/workflow/dto/WorkItemDto.java | 13 +++++--- .../web/page/self/PageAssignmentsList.java | 11 ++++--- .../midpoint/schema/util/WfContextUtil.java | 15 ++++++--- .../ns/public/common/common-workflows-3.xsd | 33 ++++++++++++++----- .../PcpChildWfTaskCreationInstruction.java | 17 +++++++--- .../impl/tasks/WfTaskCreationInstruction.java | 2 +- .../policy/other/TestSimpleCompletion.java | 29 ++++++++++++---- .../midpoint/testing/story/TestStrings.java | 8 ++--- 8 files changed, 92 insertions(+), 36 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/dto/WorkItemDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/dto/WorkItemDto.java index 4fa32d8d723..76ce7c69215 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/dto/WorkItemDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/dto/WorkItemDto.java @@ -94,6 +94,8 @@ public class WorkItemDto extends Selectable { public static final String F_PROCESS_INSTANCE_ID = "processInstanceId"; public static final String F_CHANGES = "changes"; + public static final String F_REQUESTER_COMMENT = "requesterComment"; + // workItem may or may not contain resolved taskRef; // and this task may or may not contain filled-in workflowContext -> and then requesterRef object // @@ -232,11 +234,7 @@ public String getTargetName() { public WfContextType getWorkflowContext() { TaskType task = getTaskType(); - if (task == null || task.getWorkflowContext() == null) { - return null; - } else { - return task.getWorkflowContext(); - } + return task != null ? task.getWorkflowContext() : null; } public String getRequesterName() { @@ -401,4 +399,9 @@ public ObjectType getFocus(PageBase pageBase) { } return focus; } + + public String getRequesterComment() { + OperationBusinessContextType businessContext = WfContextUtil.getBusinessContext(getWorkflowContext()); + return businessContext != null ? businessContext.getComment() : null; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java index 2d2e021db59..d76fd6421dc 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java @@ -184,10 +184,13 @@ private void onRequestPerformed(AjaxRequestTarget target) { PrismContainerDefinition def = user.getDefinition().findContainerDefinition(UserType.F_ASSIGNMENT); handleAssignmentDeltas(delta, addAssignmentsToUser(), def); - OperationBusinessContextType businessContextType = new OperationBusinessContextType(); - businessContextType.setComment(descriptionModel.getObject() != null ? - descriptionModel.getObject() : ""); - + OperationBusinessContextType businessContextType; + if (descriptionModel.getObject() != null) { + businessContextType = new OperationBusinessContextType(); + businessContextType.setComment(descriptionModel.getObject()); + } else { + businessContextType = null; + } getModelService().executeChanges(deltas, ModelExecuteOptions.createRequestBusinessContext(businessContextType), createSimpleTask(OPERATION_REQUEST_ASSIGNMENTS), result); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/WfContextUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/WfContextUtil.java index 1d4d9b935d6..b72df860ac4 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/WfContextUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/WfContextUtil.java @@ -20,10 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -267,4 +264,14 @@ public static void checkLevelsOrderingStrict(ApprovalSchemaType schema) { } } } + + public static OperationBusinessContextType getBusinessContext(WfContextType wfc) { + if (wfc == null) { + return null; + } + return wfc.getEvent().stream() + .filter(e -> e instanceof WfProcessCreationEventType) + .map(e -> ((WfProcessCreationEventType) e).getBusinessContext()) + .findFirst().orElse(null); + } } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd index 64509b8b762..a0981da4350 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd @@ -1399,14 +1399,6 @@ - - - - - - - - @@ -1624,6 +1616,31 @@ + + + + Event describing the creation of a workflow process instance. + + + 3.6 + + + + + + + + + Business context of the operation, if provided. + TODO move to WfProcessEventType? + + + + + + + + diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java index 7bf11d95439..9e2d4ed319a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java @@ -21,7 +21,9 @@ import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.ObjectTreeDeltas; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; @@ -33,12 +35,11 @@ import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.tasks.ProcessSpecificContent; import com.evolveum.midpoint.wf.impl.tasks.WfTaskCreationInstruction; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ApprovalSchemaType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SchemaAttachedPolicyRulesType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.jetbrains.annotations.NotNull; +import java.util.Date; + /** * @author mederly */ @@ -77,6 +78,14 @@ public void prepareCommonAttributes(PrimaryChangeAspect aspect, ModelContext setTaskModelContext(((PrimaryChangeProcessor) getChangeProcessor()).contextCopyWithNoDelta((LensContext) modelContext)); setExecuteModelOperationHandler(true); } + + WfProcessCreationEventType event = new WfProcessCreationEventType(); + event.setTimestamp(XmlTypeConverter.createXMLGregorianCalendar(new Date())); + if (requester != null) { + event.setInitiatorRef(ObjectTypeUtil.createObjectRef(requester)); + } + event.setBusinessContext(((LensContext) modelContext).getRequestBusinessContext()); + wfContext.getEvent().add(event); } public void setDeltasToProcess(ObjectDelta delta) { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java index 87919ede5c5..625557ec2d9 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java @@ -59,7 +59,7 @@ public class WfTaskCreationInstruction userDelta = createAssignmentUserDelta(userJackOid, roleRole1aOid, RoleType.COMPLEX_TYPE, null, null, null, true); + Collection> deltas = MiscSchemaUtil.createCollection(userDelta); + modelService.executeChanges(deltas, ModelExecuteOptions.createRequestBusinessContext(businessContext), task, result); + assertNotAssignedRole(userJackOid, roleRole1aOid, task, result); WorkItemType workItem = getWorkItem(task, result); @@ -72,12 +84,17 @@ public void test100SimpleApprove() throws Exception { TaskType wfTask = getTask(workItem.getTaskRef().getOid()).asObjectable(); display("workflow context", wfTask.getWorkflowContext()); List events = wfTask.getWorkflowContext().getEvent(); - assertEquals("Wrong # of events", 1, events.size()); - WorkItemEventType event = (WorkItemEventType) events.get(0); - display("Event", event); + assertEquals("Wrong # of events", 2, events.size()); + + WfProcessCreationEventType event1 = (WfProcessCreationEventType) events.get(0); + display("Event 1", event1); + assertEquals("Wrong requester comment", "req.comment", WfContextUtil.getBusinessContext(wfTask.getWorkflowContext()).getComment()); + + WorkItemEventType event2 = (WorkItemEventType) events.get(1); + display("Event 2", event2); - assertNotNull("Original assignee is null", event.getOriginalAssigneeRef()); - assertEquals("Wrong original assignee OID", userLead1Oid, event.getOriginalAssigneeRef().getOid()); + assertNotNull("Original assignee is null", event2.getOriginalAssigneeRef()); + assertEquals("Wrong original assignee OID", userLead1Oid, event2.getOriginalAssigneeRef().getOid()); } } diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java index ecb21045c9c..d1ef3686c3b 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestStrings.java @@ -351,8 +351,8 @@ public void test102SimpleAssignmentApproveByLechuck() throws Exception { "Allocated to: Horridly Scarred Barkeep (barkeeper)", "(in 7 days)", "^Result:"); // events - List events = assertEvents(wfTask, 1); - assertCompletionEvent(events.get(0), userLechuckOid, userLechuckOid, 1, "Line managers", WorkItemOutcomeType.APPROVE, "OK. LeChuck"); + List events = assertEvents(wfTask, 2); + assertCompletionEvent(events.get(1), userLechuckOid, userLechuckOid, 1, "Line managers", WorkItemOutcomeType.APPROVE, "OK. LeChuck"); display("audit", dummyAuditService); } @@ -687,8 +687,8 @@ public void test204SixDaysLater() throws Exception { assertEquals("Wrong escalation level #", (Integer) 1, workItem.getEscalationLevelNumber()); assertEquals("Wrong escalation level name", "Line manager escalation", workItem.getEscalationLevelName()); - List events = assertEvents(wfTask, 1); - assertEscalationEvent(events.get(0), userAdministrator.getOid(), userGuybrushOid, 1, "Line managers", + List events = assertEvents(wfTask, 2); + assertEscalationEvent(events.get(1), userAdministrator.getOid(), userGuybrushOid, 1, "Line managers", Collections.singletonList(userGuybrushOid), Collections.singletonList(userCheeseOid), WorkItemDelegationMethodType.ADD_ASSIGNEES, 1, "Line manager escalation"); From 0e2d36add7ad86689199b0c230ff4e87037add8a Mon Sep 17 00:00:00 2001 From: honchar Date: Thu, 2 Mar 2017 11:49:23 +0100 Subject: [PATCH 3/3] Requester comment fiels is added to work item page --- .../midpoint/web/page/admin/workflow/WorkItemPanel.html | 4 ++++ .../midpoint/web/page/admin/workflow/WorkItemPanel.java | 8 ++++++++ .../src/main/resources/localization/Midpoint.properties | 1 + 3 files changed, 13 insertions(+) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.html index d0bc4337546..9cc9c703e60 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.html @@ -64,6 +64,10 @@

+ + + + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.java index 9345ebb5769..f9c7eeae7ce 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/WorkItemPanel.java @@ -92,6 +92,9 @@ public class WorkItemPanel extends BasePanel { private static final String ID_APPROVER_COMMENT = "approverComment"; private static final String ID_SHOW_REQUEST = "showRequest"; private static final String ID_SHOW_REQUEST_HELP = "showRequestHelp"; + private static final String ID_REQUESTER_COMMENT_CONTAINER = "requesterCommentContainer"; + private static final String ID_REQUESTER_COMMENT_MESSAGE = "requesterCommentMessage"; + public WorkItemPanel(String id, IModel model, Form mainForm, PageBase pageBase) { super(id, model); @@ -176,6 +179,11 @@ public boolean isVisible() { escalationLevelInfoContainer.add(new Label(ID_ESCALATION_LEVEL_INFO, new PropertyModel(getModel(), WorkItemDto.F_ESCALATION_LEVEL_INFO))); escalationLevelInfoContainer.add(new VisibleBehaviour(() -> getModelObject().getEscalationLevelInfo() != null)); + WebMarkupContainer requesterCommentContainer = new WebMarkupContainer(ID_REQUESTER_COMMENT_CONTAINER); + requesterCommentContainer.setOutputMarkupId(true); + primaryInfoColumn.add(requesterCommentContainer); + requesterCommentContainer.add(new Label(ID_REQUESTER_COMMENT_MESSAGE, new PropertyModel(getModel(), WorkItemDto.F_REQUESTER_COMMENT))); + //primaryInfoColumn.add(new ScenePanel(ID_DELTAS_TO_BE_APPROVED, new PropertyModel(getModel(), WorkItemDto.F_DELTAS))); primaryInfoColumn.add(new TaskChangesPanel(ID_DELTAS_TO_BE_APPROVED, new PropertyModel<>(getModel(), WorkItemDto.F_CHANGES))); primaryInfoColumn.add(new AttributeModifier("class", new AbstractReadOnlyModel() { diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index bc6fcb53ed7..4c46195b1c6 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -2186,6 +2186,7 @@ workItemPanel.currentlyAllocatedTo=Currently allocated to\: workItemPanel.candidateActors=Candidate actors\: workItemPanel.stage=Approval stage\: workItemPanel.escalationLevel=Escalation level\: +workItemPanel.requesterComment=Requester comment\: workItemPanel.delta=Delta to be approved workItemPanel.mainInfo=Basic information workItemPanel.options=Options