/* * Copyright (c) 2010-2016 Evolveum * * Licensed 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 com.evolveum.midpoint.wf.impl.legacy; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.prism.xnode.PrimitiveXNode; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.WfContextUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.DummyResourceContoller; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.WfTestUtil; import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; import com.evolveum.midpoint.wf.impl.processes.common.LightweightObjectRef; import com.evolveum.midpoint.wf.impl.WorkflowResult; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import java.io.File; import java.util.*; import static com.evolveum.midpoint.prism.PrismConstants.T_PARENT; import static com.evolveum.midpoint.schema.GetOperationOptions.createRetrieve; import static com.evolveum.midpoint.schema.GetOperationOptions.resolveItemsNamed; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_WORKFLOW_CONTEXT; import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType.*; import static com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemType.*; import static org.testng.AssertJUnit.*; /** * @author mederly */ @ContextConfiguration(locations = {"classpath:ctx-workflow-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class TestUserChangeApprovalLegacy extends AbstractWfTestLegacy { protected static final Trace LOGGER = TraceManager.getTrace(TestUserChangeApprovalLegacy.class); private static final File REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE1 = new File(TEST_RESOURCE_DIR, "user-jack-modify-add-assignment-role1.xml"); private static final File REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE2_CHANGE_GN = new File(TEST_RESOURCE_DIR, "user-jack-modify-add-assignment-role2-change-gn.xml"); private static final File REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE3_CHANGE_GN2 = new File(TEST_RESOURCE_DIR, "user-jack-modify-add-assignment-role3-change-gn2.xml"); private static final File REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLES2_3_4 = new File(TEST_RESOURCE_DIR, "user-jack-modify-add-assignment-roles2-3-4.xml"); private static final File REQ_USER_JACK_MODIFY_ACTIVATION_DISABLE = new File(TEST_RESOURCE_DIR, "user-jack-modify-activation-disable.xml"); private static final File REQ_USER_JACK_MODIFY_ACTIVATION_ENABLE = new File(TEST_RESOURCE_DIR, "user-jack-modify-activation-enable.xml"); private static final File REQ_USER_JACK_MODIFY_CHANGE_PASSWORD = new File(TEST_RESOURCE_DIR, "user-jack-modify-change-password.xml"); private static final File REQ_USER_JACK_MODIFY_CHANGE_PASSWORD_2 = new File(TEST_RESOURCE_DIR, "user-jack-modify-change-password-2.xml"); private static final File REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE10 = new File(TEST_RESOURCE_DIR, "user-jack-modify-add-assignment-role10.xml"); private static final File REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_DUMMY = new File(TEST_RESOURCE_DIR, "user-jack-modify-add-assignment-dummy.xml"); public TestUserChangeApprovalLegacy() throws JAXBException { super(); } /** * The simplest case: user modification with one security-sensitive role. */ @Test public void test010UserModifyAddRole() throws Exception { TestUtil.displayTestTile(this, "test010UserModifyAddRole"); login(userAdministrator); executeTest("test010UserModifyAddRole", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE1); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> subtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); assertNotAssignedRole(USER_JACK_OID, ROLE_R1_OID, rootTask, result); assertWfContextAfterClockworkRun(rootTask, subtasks, result, "Assigning Role1 to jack"); } @Override void assertsRootTaskFinishes(Task rootTask, List<Task> subtasks, OperationResult result) throws Exception { assertAssignedRole(USER_JACK_OID, ROLE_R1_OID, rootTask, result); checkDummyTransportMessages("simpleUserNotifier", 1); checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(R1BOSS_OID), result); assertWfContextAfterRootTaskFinishes(rootTask, subtasks, result, "Assigning Role1 to jack"); } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } }); } protected void assertWfContextAfterClockworkRun(Task rootTask, List<Task> subtasks, OperationResult result, String... processNames) throws Exception { final Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(new ItemPath(F_WORKFLOW_CONTEXT, F_WORK_ITEM), createRetrieve()); Task opTask = taskManager.createTaskInstance(); TaskType rootTaskType = modelService.getObject(TaskType.class, rootTask.getOid(), options, opTask, result).asObjectable(); display("rootTask", rootTaskType); assertTrue("unexpected process instance id in root task", rootTaskType.getWorkflowContext() == null || rootTaskType.getWorkflowContext().getProcessInstanceId() == null); assertEquals("Wrong # of wf subtasks w.r.t processNames (" + Arrays.asList(processNames) + ")", processNames.length, subtasks.size()); int i = 0; for (Task subtask : subtasks) { TaskType subtaskType = modelService.getObject(TaskType.class, subtask.getOid(), options, opTask, result).asObjectable(); display("Subtask #"+(i+1)+": ", subtaskType); checkTask(subtaskType, subtask.toString(), processNames[i++]); WfTestUtil.assertRef("requester ref", subtaskType.getWorkflowContext().getRequesterRef(), USER_ADMINISTRATOR_OID, false, false); } final Collection<SelectorOptions<GetOperationOptions>> options1 = resolveItemsNamed( new ItemPath(T_PARENT, F_OBJECT_REF), new ItemPath(T_PARENT, F_TARGET_REF), F_ASSIGNEE_REF, F_ORIGINAL_ASSIGNEE_REF, new ItemPath(T_PARENT, F_REQUESTER_REF)); List<WorkItemType> workItems = modelService.searchContainers(WorkItemType.class, null, options1, opTask, result); assertEquals("Wrong # of work items", processNames.length, workItems.size()); i = 0; for (WorkItemType workItem : workItems) { display("Work item #"+(i+1)+": ", workItem); display("Task ref", WfContextUtil.getTask(workItem)); WfTestUtil.assertRef("object reference", WfContextUtil.getObjectRef(workItem), USER_JACK_OID, true, true); WfTestUtil.assertRef("target reference", WfContextUtil.getTargetRef(workItem), ROLE_R1_OID, true, true); WfTestUtil.assertRef("assignee reference", workItem.getOriginalAssigneeRef(), R1BOSS_OID, false, true); // name is not known, as it is not stored in activiti (only OID is) //WfTestUtil.assertRef("task reference", workItem.getTaskRef(), null, false, true); final TaskType subtaskType = WfContextUtil.getTask(workItem); checkTask(subtaskType, "task in workItem", processNames[i++]); WfTestUtil.assertRef("requester ref", subtaskType.getWorkflowContext().getRequesterRef(), USER_ADMINISTRATOR_OID, false, true); } } private void checkTask(TaskType subtaskType, String subtaskName, String processName) { assertEquals("Unexpected fetch result in wf subtask: " + subtaskName, null, subtaskType.getFetchResult()); WfContextType wfc = subtaskType.getWorkflowContext(); assertNotNull("Missing workflow context in wf subtask: " + subtaskName, wfc); assertNotNull("No process ID in wf subtask: " + subtaskName, wfc.getProcessInstanceId()); assertEquals("Wrong process ID name in subtask: " + subtaskName, processName, wfc.getProcessInstanceName()); assertNotNull("Missing process start time in subtask: " + subtaskName, wfc.getStartTimestamp()); assertNull("Unexpected process end time in subtask: " + subtaskName, wfc.getEndTimestamp()); assertEquals("Wrong outcome", null, wfc.getOutcome()); //assertEquals("Wrong state", null, wfc.getState()); } protected void assertWfContextAfterRootTaskFinishes(Task rootTask, List<Task> subtasks, OperationResult result, String... processNames) throws Exception { final Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(new ItemPath(F_WORKFLOW_CONTEXT, F_WORK_ITEM), createRetrieve()); Task opTask = taskManager.createTaskInstance(); TaskType rootTaskType = modelService.getObject(TaskType.class, rootTask.getOid(), options, opTask, result).asObjectable(); assertTrue("unexpected process instance id in root task", rootTaskType.getWorkflowContext() == null || rootTaskType.getWorkflowContext().getProcessInstanceId() == null); assertEquals("Wrong # of wf subtasks w.r.t processNames (" + Arrays.asList(processNames) + ")", processNames.length, subtasks.size()); int i = 0; for (Task subtask : subtasks) { TaskType subtaskType = modelService.getObject(TaskType.class, subtask.getOid(), options, opTask, result).asObjectable(); display("Subtask #"+(i+1)+": ", subtaskType); assertNull("Unexpected fetch result in wf subtask: " + subtask, subtaskType.getFetchResult()); WfContextType wfc = subtaskType.getWorkflowContext(); assertNotNull("Missing workflow context in wf subtask: " + subtask, wfc); assertNotNull("No process ID in wf subtask: " + subtask, wfc.getProcessInstanceId()); assertEquals("Wrong process ID name in subtask: " + subtask, processNames[i++], wfc.getProcessInstanceName()); assertNotNull("Missing process start time in subtask: " + subtask, wfc.getStartTimestamp()); assertNotNull("Missing process end time in subtask: " + subtask, wfc.getEndTimestamp()); assertEquals("Wrong outcome", SchemaConstants.MODEL_APPROVAL_OUTCOME_APPROVE, wfc.getOutcome()); } } /** * User modification with one security-sensitive role and other (unrelated) change - e.g. change of the given name. * Aggregated execution. */ @Test(enabled = true) public void test011UserModifyAddRoleChangeGivenName() throws Exception { TestUtil.displayTestTile(this, "test011UserModifyAddRoleChangeGivenName"); login(userAdministrator); executeTest("test011UserModifyAddRoleChangeGivenName", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE2_CHANGE_GN); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There is wrong number of modifications left in primary focus delta", 1, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); ItemDelta givenNameDelta = (ItemDelta) taskModelContext.getFocusContext().getPrimaryDelta().getModifications().iterator().next(); assertNotNull("givenName delta is incorrect (not a replace delta)", givenNameDelta.isReplace()); assertEquals("givenName delta is incorrect (wrong value)", "JACK", ((PrismPropertyValue<PolyString>) givenNameDelta.getValuesToReplace().iterator().next()).getValue().getOrig()); PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertNotAssignedRole(jack, ROLE_R2_OID); assertEquals("Wrong given name before change", "Jack", jack.asObjectable().getGivenName().getOrig()); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertNotAssignedRole(jack, ROLE_R2_OID); assertEquals("Wrong given name after change", "JACK", jack.asObjectable().getGivenName().getOrig()); checkDummyTransportMessages("simpleUserNotifier", 1); checkWorkItemAuditRecords(createResultMap(ROLE_R2_OID, WorkflowResult.REJECTED)); checkUserApprovers(USER_JACK_OID, new ArrayList<String>(), result); } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } }); } @Test(enabled = true) public void test012UserModifyAddRoleChangeGivenNameImmediate() throws Exception { TestUtil.displayTestTile(this, "test012UserModifyAddRoleChangeGivenNameImmediate"); login(userAdministrator); executeTest("test012UserModifyAddRoleChangeGivenNameImmediate", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 2; } @Override boolean immediate() { return true; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE3_CHANGE_GN2); context.setOptions(ModelExecuteOptions.createExecuteImmediatelyAfterApproval()); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { assertFalse("There is model context in the root task (it should not be there)", wfTaskUtil.hasModelContext(rootTask)); } @Override void assertsAfterImmediateExecutionFinished(Task task, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertNotAssignedRole(jack, ROLE_R3_OID); assertEquals("Wrong given name after immediate execution", "J-A-C-K", jack.asObjectable().getGivenName().getOrig()); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertAssignedRole(jack, ROLE_R3_OID); checkDummyTransportMessages("simpleUserNotifier", 2); checkWorkItemAuditRecords(createResultMap(ROLE_R3_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(R3BOSS_OID), result); // given name is changed before role is added, so the approver should be recorded } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } }); } @Test(enabled = true) public void test020UserModifyAddThreeRoles() throws Exception { TestUtil.displayTestTile(this, "test020UserModifyAddThreeRoles"); login(userAdministrator); executeTest("test020UserModifyAddThreeRoles", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 2; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLES2_3_4); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ACTIVATION_DISABLE); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There is wrong number of modifications left in primary focus delta", 2, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); Iterator<? extends ItemDelta> it = taskModelContext.getFocusContext().getPrimaryDelta().getModifications().iterator(); ItemDelta addRoleDelta = null, activationChange = null; while (it.hasNext()) { ItemDelta mod = it.next(); if (mod.isAdd()) { addRoleDelta = mod; } else if (mod.isReplace()) { activationChange = mod; } } assertNotNull("role add delta was not found", addRoleDelta); assertEquals("role add delta contains wrong number of values", 1, addRoleDelta.getValuesToAdd().size()); assertNotNull("activation change delta was not found", activationChange); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = getUserFromRepo(USER_JACK_OID, result); assertNotAssignedRole(jack, ROLE_R1_OID); assertNotAssignedRole(jack, ROLE_R2_OID); assertAssignedRole(jack, ROLE_R3_OID); assertAssignedRole(jack, ROLE_R4_OID); assertEquals("activation has not been changed", ActivationStatusType.DISABLED, jack.asObjectable().getActivation().getAdministrativeStatus()); checkDummyTransportMessages("simpleUserNotifier", 1); checkWorkItemAuditRecords(createResultMap(ROLE_R2_OID, WorkflowResult.REJECTED, ROLE_R3_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(R3BOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } }); } @Test(enabled = true) public void test021UserModifyAddThreeRolesImmediate() throws Exception { TestUtil.displayTestTile(this, "test021UserModifyAddThreeRolesImmediate"); login(userAdministrator); executeTest("test021UserModifyAddThreeRolesImmediate", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 3; } @Override boolean immediate() { return true; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLES2_3_4); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ACTIVATION_ENABLE); context.setOptions(ModelExecuteOptions.createExecuteImmediatelyAfterApproval()); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { assertFalse("There is model context in the root task (it should not be there)", wfTaskUtil.hasModelContext(rootTask)); } @Override void assertsAfterImmediateExecutionFinished(Task task, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertNotAssignedRole(jack, ROLE_R1_OID); assertNotAssignedRole(jack, ROLE_R2_OID); assertNotAssignedRole(jack, ROLE_R3_OID); assertAssignedRole(jack, ROLE_R4_OID); assertEquals("activation has not been changed", ActivationStatusType.ENABLED, jack.asObjectable().getActivation().getAdministrativeStatus()); checkUserApprovers(USER_JACK_OID, new ArrayList<String>(), result); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = getUserFromRepo(USER_JACK_OID, result); assertNotAssignedRole(jack, ROLE_R1_OID); assertNotAssignedRole(jack, ROLE_R2_OID); assertAssignedRole(jack, ROLE_R3_OID); assertAssignedRole(jack, ROLE_R4_OID); assertEquals("activation has not been changed", ActivationStatusType.ENABLED, jack.asObjectable().getActivation().getAdministrativeStatus()); checkDummyTransportMessages("simpleUserNotifier", 2); checkWorkItemAuditRecords(createResultMap(ROLE_R2_OID, WorkflowResult.REJECTED, ROLE_R3_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(R3BOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } }); } @Test(enabled = true) public void test030UserAdd() throws Exception { TestUtil.displayTestTile(this, "test030UserAdd"); login(userAdministrator); executeTest("test030UserAdd", null, new TestDetails() { @Override int subtaskCount() { return 2; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return false; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); PrismObject<UserType> bill = prismContext.parseObject(USER_BILL_FILE); fillContextWithAddUserDelta(context, bill); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); PrismObject<UserType> objectToAdd = taskModelContext.getFocusContext().getPrimaryDelta().getObjectToAdd(); assertNotNull("There is no object to add left in primary focus delta", objectToAdd); assertFalse("There is assignment of R1 in reduced primary focus delta", assignmentExists(objectToAdd.asObjectable().getAssignment(), ROLE_R1_OID)); assertFalse("There is assignment of R2 in reduced primary focus delta", assignmentExists(objectToAdd.asObjectable().getAssignment(), ROLE_R2_OID)); assertFalse("There is assignment of R3 in reduced primary focus delta", assignmentExists(objectToAdd.asObjectable().getAssignment(), ROLE_R3_OID)); assertTrue("There is no assignment of R4 in reduced primary focus delta", assignmentExists(objectToAdd.asObjectable().getAssignment(), ROLE_R4_OID)); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> bill = findUserInRepo("bill", result); assertAssignedRole(bill, ROLE_R1_OID); assertNotAssignedRole(bill, ROLE_R2_OID); assertNotAssignedRole(bill, ROLE_R3_OID); assertAssignedRole(bill, ROLE_R4_OID); //assertEquals("Wrong number of assignments for bill", 4, bill.asObjectable().getAssignment().size()); checkDummyTransportMessages("simpleUserNotifier", 1); checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED, ROLE_R2_OID, WorkflowResult.REJECTED)); checkUserApproversForCreate(bill.getOid(), Arrays.asList(R1BOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } @Override String getObjectOid(Task task, OperationResult result) throws SchemaException { //return findUserInRepo("bill", result).getOid(); return DONT_CHECK; // don't check in this case } }); } @Test(enabled = true) public void test031UserAddImmediate() throws Exception { TestUtil.displayTestTile(this, "test031UserAddImmediate"); login(userAdministrator); deleteUserFromModel("bill"); executeTest("test031UserAddImmediate", null, new TestDetails() { @Override int subtaskCount() { return 3; } @Override boolean immediate() { return true; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); PrismObject<UserType> bill = prismContext.parseObject(USER_BILL_FILE); fillContextWithAddUserDelta(context, bill); context.setOptions(ModelExecuteOptions.createExecuteImmediatelyAfterApproval()); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { assertFalse("There is model context in the root task (it should not be there)", wfTaskUtil.hasModelContext(rootTask)); } @Override void assertsAfterImmediateExecutionFinished(Task task, OperationResult result) throws Exception { PrismObject<UserType> bill = findUserInRepo("bill", result); assertNotAssignedRole(bill, ROLE_R1_OID); assertNotAssignedRole(bill, ROLE_R2_OID); assertNotAssignedRole(bill, ROLE_R3_OID); assertAssignedRole(bill, ROLE_R4_OID); //assertEquals("Wrong number of assignments for bill", 3, bill.asObjectable().getAssignment().size()); checkUserApproversForCreate(USER_JACK_OID, new ArrayList<>(), result); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> bill = findUserInRepo("bill", result); assertAssignedRole(bill, ROLE_R1_OID); assertNotAssignedRole(bill, ROLE_R2_OID); assertNotAssignedRole(bill, ROLE_R3_OID); assertAssignedRole(bill, ROLE_R4_OID); //assertEquals("Wrong number of assignments for bill", 4, bill.asObjectable().getAssignment().size()); checkDummyTransportMessages("simpleUserNotifier", 2); checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED, ROLE_R2_OID, WorkflowResult.REJECTED)); checkUserApprovers(bill.getOid(), Arrays.asList(R1BOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { return decideOnRoleApproval(executionId); } @Override String getObjectOid(Task task, OperationResult result) throws SchemaException { return findUserInRepo("bill", result).getOid(); } }); } @Test(enabled = true) public void test040UserModifyPasswordChangeBlocked() throws Exception { TestUtil.displayTestTile(this, "test040UserModifyPasswordChangeBlocked"); login(userAdministrator); PrismObject<UserType> jack = getUser(USER_JACK_OID); final ProtectedStringType originalPasswordValue = jack.asObjectable().getCredentials().getPassword().getValue(); LOGGER.trace("password before test = " + originalPasswordValue); executeTest("test040UserModifyPasswordChangeBlocked", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); encryptAndAddFocusModificationToContext(context, REQ_USER_JACK_MODIFY_CHANGE_PASSWORD); //context.setOptions(ModelExecuteOptions.createNoCrypt()); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = getUser(USER_JACK_OID); ProtectedStringType afterTestPasswordValue = jack.asObjectable().getCredentials().getPassword().getValue(); LOGGER.trace("password after test = " + afterTestPasswordValue); //assertNotNull("password was not set", afterTestPasswordValue.getEncryptedData()); assertTrue("password was changed", originalPasswordValue.getEncryptedDataType().equals(afterTestPasswordValue.getEncryptedDataType())); checkDummyTransportMessages("simpleUserNotifier", 0); // we don't check for modifyApproverRef because in this test the value was not changed (no change was executed) } @Override boolean decideOnApproval(String executionId) throws Exception { login(getUser(USER_ADMINISTRATOR_OID)); return false; } }); } @Test(enabled = true) public void test041UserModifyPasswordChange() throws Exception { TestUtil.displayTestTile(this, "test041UserModifyPasswordChange"); login(userAdministrator); PrismObject<UserType> jack = getUser(USER_JACK_OID); final ProtectedStringType originalPasswordValue = jack.asObjectable().getCredentials().getPassword().getValue(); LOGGER.trace("password before test = " + originalPasswordValue); executeTest("test041UserModifyPasswordChange", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); encryptAndAddFocusModificationToContext(context, REQ_USER_JACK_MODIFY_CHANGE_PASSWORD); //context.setOptions(ModelExecuteOptions.createNoCrypt()); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = getUser(USER_JACK_OID); ProtectedStringType afterTestPasswordValue = jack.asObjectable().getCredentials().getPassword().getValue(); LOGGER.trace("password after test = " + afterTestPasswordValue); //assertNotNull("password was not set", afterTestPasswordValue.getEncryptedData()); assertFalse("password was not changed", originalPasswordValue.getEncryptedDataType().equals(afterTestPasswordValue.getEncryptedDataType())); checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { login(getUser(USER_ADMINISTRATOR_OID)); return true; } }); } @Test(enabled = true) public void test050UserModifyAddRoleAndPasswordChange() throws Exception { TestUtil.displayTestTile(this, "test050UserModifyAddRoleAndPasswordChange"); login(userAdministrator); PrismObject<UserType> jack = getUser(USER_JACK_OID); final ProtectedStringType originalPasswordValue = jack.asObjectable().getCredentials().getPassword().getValue(); LOGGER.trace("password before test = " + originalPasswordValue); executeTest("test050UserModifyAddRoleAndPasswordChange", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 2; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); encryptAndAddFocusModificationToContext(context, REQ_USER_JACK_MODIFY_CHANGE_PASSWORD_2); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE1); //context.setOptions(ModelExecuteOptions.createNoCrypt()); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = getUser(USER_JACK_OID); ProtectedStringType afterTestPasswordValue = jack.asObjectable().getCredentials().getPassword().getValue(); LOGGER.trace("password after test = " + afterTestPasswordValue); // todo why is password value not set? //assertNotNull("password was not set", afterTestPasswordValue.getEncryptedData()); //assertFalse("password was not changed", originalPasswordValue.getEncryptedData().equals(afterTestPasswordValue.getEncryptedData())); assertAssignedRole(jack, ROLE_R1_OID); checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { LightweightObjectRef targetRef = (LightweightObjectRef) activitiEngine.getRuntimeService().getVariable(executionId, CommonProcessVariableNames.VARIABLE_TARGET_REF); if (targetRef != null && RoleType.COMPLEX_TYPE.equals(targetRef.toObjectReferenceType().getType())) { return decideOnRoleApproval(executionId); } else { login(getUser(USER_ADMINISTRATOR_OID)); return true; } } }); } @Test(enabled = true) public void test060UserModifyAddRoleAutoApproval() throws Exception { TestUtil.displayTestTile(this, "test060UserModifyAddRoleAutoApproval"); login(userAdministrator); executeTest("test060UserModifyAddRoleAutoApproval", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean approvedAutomatically() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_ROLE10); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { // todo perhaps the role should be assigned even at this point? } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertAssignedRole(jack, ROLE_R10_OID); checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { throw new AssertionError("Decision should not be acquired in this scenario."); } }); } @Test public void test062UserModifyAddRoleAutoApprovalFirstDecides() throws Exception { TestUtil.displayTestTile(this, "test062UserModifyAddRoleAutoApprovalFirstDecides"); login(userAdministrator); executeTest("test062UserModifyAddRoleAutoApprovalFirstDecides", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean approvedAutomatically() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusDeltaToContext(context, (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add( ObjectTypeUtil.createAssignmentTo(ROLE_R11_OID, ObjectTypes.ROLE, prismContext).asPrismContainerValue()) .asObjectDelta(USER_JACK_OID)); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { // todo perhaps the role should be assigned even at this point? } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertAssignedRole(jack, ROLE_R11_OID); checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { throw new AssertionError("Decision should not be acquired in this scenario."); } }); } @Test public void test064UserModifyAddRoleNoApproversAllMustAgree() throws Exception { TestUtil.displayTestTile(this, "test064UserModifyAddRoleNoApproversAllMustAgree"); login(userAdministrator); executeTest("test064UserModifyAddRoleNoApproversAllMustAgree", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean approvedAutomatically() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusDeltaToContext(context, (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add( ObjectTypeUtil.createAssignmentTo(ROLE_R12_OID, ObjectTypes.ROLE, prismContext).asPrismContainerValue()) .asObjectDelta(USER_JACK_OID)); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { // todo perhaps the role should be assigned even at this point? } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertAssignedRole(jack, ROLE_R12_OID); checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { throw new AssertionError("Decision should not be acquired in this scenario."); } }); } @Test public void test065UserModifyAddRoleNoApproversFirstDecides() throws Exception { TestUtil.displayTestTile(this, "test065UserModifyAddRoleNoApproversFirstDecides"); login(userAdministrator); executeTest("test065UserModifyAddRoleNoApproversFirstDecides", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean approvedAutomatically() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusDeltaToContext(context, (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add( ObjectTypeUtil.createAssignmentTo(ROLE_R13_OID, ObjectTypes.ROLE, prismContext).asPrismContainerValue()) .asObjectDelta(USER_JACK_OID)); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { // todo perhaps the role should be assigned even at this point? } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { PrismObject<UserType> jack = repositoryService.getObject(UserType.class, USER_JACK_OID, null, result); assertAssignedRole(jack, ROLE_R13_OID); checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { throw new AssertionError("Decision should not be acquired in this scenario."); } }); } @Test(enabled = true) public void test070UserModifyAssignment() throws Exception { TestUtil.displayTestTile(this, "test070UserModifyAssignment"); login(userAdministrator); removeAllAssignments(USER_JACK_OID, new OperationResult("dummy")); assignRoleRaw(USER_JACK_OID, ROLE_R1_OID); final XMLGregorianCalendar validFrom = XmlTypeConverter.createXMLGregorianCalendar(2015, 2, 25, 10, 0, 0); final XMLGregorianCalendar validTo = XmlTypeConverter.createXMLGregorianCalendar(2015, 3, 25, 10, 0, 0); executeTest("test070UserModifyAssignment", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean removeAssignmentsBeforeTest() { return false; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); UserType jack = context.getFocusContext().getObjectOld().asObjectable(); modifyAssignmentValidity(context, jack, validFrom, validTo); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); UserType jack = getUser(USER_JACK_OID).asObjectable(); checkNoAssignmentValidity(jack); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { UserType jack = getUser(USER_JACK_OID).asObjectable(); checkAssignmentValidity(jack, validFrom, validTo); // TODO //checkDummyTransportMessages("simpleUserNotifier", 1); } @Override boolean decideOnApproval(String executionId) throws Exception { login(getUser(R1BOSS_OID)); return true; } }); } private void checkAssignmentValidity(UserType jack, XMLGregorianCalendar validFrom, XMLGregorianCalendar validTo) { assertEquals("jack's assignments", 1, jack.getAssignment().size()); AssignmentType assignmentType = jack.getAssignment().get(0); assertEquals("wrong validFrom", validFrom, assignmentType.getActivation().getValidFrom()); assertEquals("wrong validTo", validTo, assignmentType.getActivation().getValidTo()); } protected void checkNoAssignmentValidity(UserType jack) { assertEquals("jack's assignments", 1, jack.getAssignment().size()); AssignmentType assignmentType = jack.getAssignment().get(0); if (assignmentType.getActivation() != null) { assertNull("validFrom already set", assignmentType.getActivation().getValidFrom()); assertNull("validTo already set", assignmentType.getActivation().getValidTo()); } } protected void modifyAssignmentValidity(LensContext<UserType> context, UserType jack, XMLGregorianCalendar validFrom, XMLGregorianCalendar validTo) throws SchemaException { assertEquals("jack's assignments", 1, jack.getAssignment().size()); PrismContainerDefinition<ActivationType> activationDef = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(UserType.class) .findContainerDefinition(new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION)); assertNotNull("no activationDef", activationDef); Long assignmentId = jack.getAssignment().get(0).getId(); PrismPropertyDefinition<XMLGregorianCalendar> validFromDef = activationDef.findPropertyDefinition(ActivationType.F_VALID_FROM); PropertyDelta<XMLGregorianCalendar> validFromDelta = new PropertyDelta<>( new ItemPath(new NameItemPathSegment(UserType.F_ASSIGNMENT), new IdItemPathSegment(assignmentId), new NameItemPathSegment(AssignmentType.F_ACTIVATION), new NameItemPathSegment(ActivationType.F_VALID_FROM)), validFromDef, prismContext); validFromDelta.setValueToReplace(new PrismPropertyValue<>(validFrom)); PrismPropertyDefinition<XMLGregorianCalendar> validToDef = activationDef.findPropertyDefinition(ActivationType.F_VALID_TO); PropertyDelta<XMLGregorianCalendar> validToDelta = new PropertyDelta<>( new ItemPath(new NameItemPathSegment(UserType.F_ASSIGNMENT), new IdItemPathSegment(assignmentId), new NameItemPathSegment(AssignmentType.F_ACTIVATION), new NameItemPathSegment(ActivationType.F_VALID_TO)), validToDef, prismContext); validToDelta.setValueToReplace(new PrismPropertyValue<>(validTo)); ObjectDelta<UserType> userDelta = new ObjectDelta<>(UserType.class, ChangeType.MODIFY, prismContext); userDelta.setOid(USER_JACK_OID); userDelta.addModification(validFromDelta); userDelta.addModification(validToDelta); addFocusDeltaToContext(context, userDelta); } private void assignRoleRaw(String userOid, String roleOid) throws SchemaException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException, PolicyViolationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { ObjectDelta<UserType> userDelta = createAssignmentUserDelta(userOid, roleOid, RoleType.COMPLEX_TYPE, null, null, null, true); Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(userDelta); repositoryService.modifyObject(UserType.class, userOid, userDelta.getModifications(), new OperationResult("dummy")); } /** * User modification: adding single security-sensitive resource assignment. */ @Test(enabled = true) public void test080UserModifyAddResource() throws Exception { TestUtil.displayTestTile(this, "test080UserModifyAddResource"); login(userAdministrator); executeTest("test080UserModifyAddResource", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); addFocusModificationToContext(context, REQ_USER_JACK_MODIFY_ADD_ASSIGNMENT_DUMMY); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); assertNotAssignedResource(USER_JACK_OID, RESOURCE_DUMMY_OID, rootTask, result); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { assertAssignedResource(USER_JACK_OID, RESOURCE_DUMMY_OID, task, result); checkDummyTransportMessages("simpleUserNotifier", 1); //checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(DUMMYBOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { login(getUser(DUMMYBOSS_OID)); return true; } }); } /** * User modification: modifying validity of single security-sensitive resource assignment. */ @Test(enabled = true) public void test090UserModifyModifyResourceAssignmentValidity() throws Exception { TestUtil.displayTestTile(this, "test090UserModifyModifyResourceAssignmentValidity"); login(userAdministrator); final XMLGregorianCalendar validFrom = XmlTypeConverter.createXMLGregorianCalendar(2015, 2, 25, 10, 0, 0); final XMLGregorianCalendar validTo = XmlTypeConverter.createXMLGregorianCalendar(2015, 3, 25, 10, 0, 0); executeTest("test090UserModifyModifyResourceAssignmentValidity", USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean removeAssignmentsBeforeTest() { return false; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); UserType jack = context.getFocusContext().getObjectOld().asObjectable(); modifyAssignmentValidity(context, jack, validFrom, validTo); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); UserType jack = getUser(USER_JACK_OID).asObjectable(); checkNoAssignmentValidity(jack); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { assertAssignedResource(USER_JACK_OID, RESOURCE_DUMMY_OID, task, result); UserType jack = getUser(USER_JACK_OID).asObjectable(); checkAssignmentValidity(jack, validFrom, validTo); checkDummyTransportMessages("simpleUserNotifier", 1); //checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(DUMMYBOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { login(getUser(DUMMYBOSS_OID)); return true; } }); } /** * User modification: modifying attribute of single security-sensitive resource assignment. * * User primary delta: * ObjectDelta<UserType>(UserType:377205db-33d1-47e5-bf96-bbe2a7d1222e,MODIFY): * assignment/[1]/construction/attribute * ADD: ResourceAttributeDefinitionType(ref=ItemPathType{itemPath=lastname}...) * DELETE: ResourceAttributeDefinitionType(ref=ItemPathType{itemPath=lastname}...) * */ @Test(enabled = true) public void test095UserModifyModifyResourceAssignmentConstruction() throws Exception { final String TEST_NAME = "test095UserModifyModifyResourceAssignmentConstruction"; TestUtil.displayTestTile(this, TEST_NAME); login(userAdministrator); executeTest(TEST_NAME, USER_JACK_OID, new TestDetails() { @Override int subtaskCount() { return 1; } @Override boolean immediate() { return false; } @Override boolean checkObjectOnSubtasks() { return true; } @Override boolean removeAssignmentsBeforeTest() { return false; } @Override public LensContext createModelContext(OperationResult result) throws Exception { LensContext<UserType> context = createUserLensContext(); fillContextWithUser(context, USER_JACK_OID, result); UserType jack = context.getFocusContext().getObjectOld().asObjectable(); modifyAssignmentConstruction(context, jack, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_DRINK_NAME, "water", true); return context; } @Override public void assertsAfterClockworkRun(Task rootTask, List<Task> wfSubtasks, OperationResult result) throws Exception { ModelContext taskModelContext = wfTaskUtil.getModelContext(rootTask, result); assertEquals("There are modifications left in primary focus delta", 0, taskModelContext.getFocusContext().getPrimaryDelta().getModifications().size()); UserType jack = getUser(USER_JACK_OID).asObjectable(); checkNoAssignmentConstruction(jack, "drink"); } @Override void assertsRootTaskFinishes(Task task, List<Task> subtasks, OperationResult result) throws Exception { assertAssignedResource(USER_JACK_OID, RESOURCE_DUMMY_OID, task, result); UserType jack = getUser(USER_JACK_OID).asObjectable(); checkAssignmentConstruction(jack, "drink", "water"); checkDummyTransportMessages("simpleUserNotifier", 1); //checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED)); checkUserApprovers(USER_JACK_OID, Arrays.asList(DUMMYBOSS_OID), result); } @Override boolean decideOnApproval(String executionId) throws Exception { login(getUser(DUMMYBOSS_OID)); return true; } }); } protected void modifyAssignmentConstruction(LensContext<UserType> context, UserType jack, String attributeName, String value, boolean add) throws SchemaException { assertEquals("jack's assignments", 1, jack.getAssignment().size()); PrismPropertyDefinition<ResourceAttributeDefinitionType> attributeDef = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(UserType.class) .findPropertyDefinition(new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_CONSTRUCTION, ConstructionType.F_ATTRIBUTE)); assertNotNull("no attributeDef", attributeDef); Long assignmentId = jack.getAssignment().get(0).getId(); PropertyDelta<ResourceAttributeDefinitionType> attributeDelta = new PropertyDelta<ResourceAttributeDefinitionType>( new ItemPath(new NameItemPathSegment(UserType.F_ASSIGNMENT), new IdItemPathSegment(assignmentId), new NameItemPathSegment(AssignmentType.F_CONSTRUCTION), new NameItemPathSegment(ConstructionType.F_ATTRIBUTE)), attributeDef, prismContext); ResourceAttributeDefinitionType attributeDefinitionType = new ResourceAttributeDefinitionType(); attributeDefinitionType.setRef(new ItemPathType(new ItemPath(new QName(RESOURCE_DUMMY_NAMESPACE, attributeName)))); MappingType outbound = new MappingType(); outbound.setStrength(MappingStrengthType.STRONG); // to see changes on the resource ExpressionType expression = new ExpressionType(); expression.getExpressionEvaluator().add(new ObjectFactory().createValue(value)); outbound.setExpression(expression); attributeDefinitionType.setOutbound(outbound); if (add) { attributeDelta.addValueToAdd(new PrismPropertyValue<>(attributeDefinitionType)); } else { attributeDelta.addValueToDelete(new PrismPropertyValue<>(attributeDefinitionType)); } ObjectDelta<UserType> userDelta = new ObjectDelta<>(UserType.class, ChangeType.MODIFY, prismContext); userDelta.setOid(USER_JACK_OID); userDelta.addModification(attributeDelta); addFocusDeltaToContext(context, userDelta); } private void checkAssignmentConstruction(UserType jack, String attributeName, String value) throws SchemaException { assertEquals("jack's assignments", 1, jack.getAssignment().size()); AssignmentType assignmentType = jack.getAssignment().get(0); ConstructionType constructionType = assignmentType.getConstruction(); assertNotNull("construction is null", constructionType); boolean found = false; for (ResourceAttributeDefinitionType attributeDefinitionType : constructionType.getAttribute()) { if (attributeDefinitionType.getRef().equivalent(new ItemPathType(new ItemPath(new QName(attributeName))))) { ExpressionType expressionType = attributeDefinitionType.getOutbound().getExpression(); assertNotNull("no expression", expressionType); assertEquals("wrong # of expression evaluators", 1, expressionType.getExpressionEvaluator().size()); JAXBElement<?> element = expressionType.getExpressionEvaluator().get(0); PrimitiveXNode valueXNode = (PrimitiveXNode) (((RawType) element.getValue()).serializeToXNode()); assertEquals("wrong outbound value", value, valueXNode.getStringValue()); found = true; } } assertTrue("attribute " + attributeName + " mapping not found", found); } private void checkNoAssignmentConstruction(UserType jack, String attributeName) { assertEquals("jack's assignments", 1, jack.getAssignment().size()); AssignmentType assignmentType = jack.getAssignment().get(0); ConstructionType constructionType = assignmentType.getConstruction(); assertNotNull("construction is null", constructionType); for (ResourceAttributeDefinitionType attributeDefinitionType : constructionType.getAttribute()) { if (attributeDefinitionType.getRef().equivalent(new ItemPathType(new ItemPath(new QName(attributeName))))) { fail("Construction attribute " + attributeName + " present, although it shouldn't"); } } } @Test public void zzzMarkAsNotInitialized() { display("Setting class as not initialized"); unsetSystemInitialized(); } }