/* * Copyright (c) 2010-2017 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.policy.sod; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; 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.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.policy.AbstractWfTestPolicy; import com.evolveum.midpoint.wf.impl.policy.ExpectedTask; import com.evolveum.midpoint.wf.impl.policy.ExpectedWorkItem; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; 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 java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.List; import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNull; /** * Testing approvals of role SoD: assigning roles that are in conflict. * * Subclasses provide specializations regarding ways how rules and/or approvers are attached to roles. * * @author mederly */ @ContextConfiguration(locations = {"classpath:ctx-workflow-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class AbstractTestSoD extends AbstractWfTestPolicy { protected static final Trace LOGGER = TraceManager.getTrace(AbstractTestSoD.class); protected static final File TEST_SOD_RESOURCE_DIR = new File("src/test/resources/policy/sod"); protected static final File METAROLE_CRIMINAL_EXCLUSION_FILE = new File(TEST_SOD_RESOURCE_DIR, "metarole-criminal-exclusion.xml"); protected static final File ROLE_JUDGE_FILE = new File(TEST_SOD_RESOURCE_DIR, "role-judge.xml"); protected static final File ROLE_PIRATE_FILE = new File(TEST_SOD_RESOURCE_DIR, "role-pirate.xml"); protected static final File ROLE_THIEF_FILE = new File(TEST_SOD_RESOURCE_DIR, "role-thief.xml"); protected static final File ROLE_RESPECTABLE_FILE = new File(TEST_SOD_RESOURCE_DIR, "role-respectable.xml"); protected static final File USER_SOD_APPROVER_FILE = new File(TEST_SOD_RESOURCE_DIR, "user-sod-approver.xml"); protected String metaroleCriminalExclusion; protected String roleJudgeOid; protected String rolePirateOid; protected String roleThiefOid; protected String roleRespectableOid; protected String userSodApproverOid; @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); metaroleCriminalExclusion = repoAddObjectFromFile(METAROLE_CRIMINAL_EXCLUSION_FILE, initResult).getOid(); roleJudgeOid = repoAddObjectFromFile(ROLE_JUDGE_FILE, initResult).getOid(); rolePirateOid = repoAddObjectFromFile(ROLE_PIRATE_FILE, initResult).getOid(); roleThiefOid = repoAddObjectFromFile(ROLE_THIEF_FILE, initResult).getOid(); roleRespectableOid = repoAddObjectFromFile(ROLE_RESPECTABLE_FILE, initResult).getOid(); userSodApproverOid = addAndRecomputeUser(USER_SOD_APPROVER_FILE, initTask, initResult); //DebugUtil.setDetailedDebugDump(true); } /** * Assign Judge to jack. This should work without approvals. */ @Test public void test010AssignRoleJudge() throws Exception { final String TEST_NAME = "test010AssignRoleJudge"; TestUtil.displayTestTile(this, TEST_NAME); login(userAdministrator); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN assignRole(userJackOid, roleJudgeOid, task, result); // THEN display("jack as a Judge", getUser(userJackOid)); assertAssignedRole(userJackOid, roleJudgeOid, task, result); } /** * Assign Pirate to jack. This should trigger an approval. */ @Test public void test020AssignRolePirate() throws Exception { final String TEST_NAME = "test020AssignRolePirate"; TestUtil.displayTestTile(this, TEST_NAME); login(userAdministrator); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject<UserType> jack = getUser(userJackOid); String originalDescription = jack.asObjectable().getDescription(); @SuppressWarnings("unchecked") ObjectDelta<UserType> addPirateDelta = (ObjectDelta<UserType>) DeltaBuilder .deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add(createAssignmentTo(rolePirateOid, ObjectTypes.ROLE, prismContext)) .asObjectDelta(userJackOid); @SuppressWarnings("unchecked") ObjectDelta<UserType> changeDescriptionDelta = (ObjectDelta<UserType>) DeltaBuilder .deltaFor(UserType.class, prismContext) .item(UserType.F_DESCRIPTION).replace("Pirate Judge") .asObjectDelta(userJackOid); ObjectDelta<UserType> primaryDelta = ObjectDelta.summarize(addPirateDelta, changeDescriptionDelta); // WHEN+THEN executeTest2(TEST_NAME, new TestDetails2<UserType>() { @Override protected PrismObject<UserType> getFocus(OperationResult result) throws Exception { return jack.clone(); } @Override protected ObjectDelta<UserType> getFocusDelta() throws SchemaException { return primaryDelta.clone(); } @Override protected int getNumberOfDeltasToApprove() { return 1; } @Override protected List<Boolean> getApprovals() { return Collections.singletonList(true); } @Override protected List<ObjectDelta<UserType>> getExpectedDeltasToApprove() { return Arrays.asList(addPirateDelta.clone()); } @Override protected ObjectDelta<UserType> getExpectedDelta0() { //return ObjectDelta.createEmptyModifyDelta(UserType.class, jack.getOid(), prismContext); //return ObjectDelta.createModifyDelta(jack.getOid(), Collections.emptyList(), UserType.class, prismContext); return changeDescriptionDelta.clone(); } @Override protected String getObjectOid() { return jack.getOid(); } @Override protected List<ExpectedTask> getExpectedTasks() { return Collections.singletonList( new ExpectedTask(rolePirateOid, "Assigning Pirate to jack")); } @Override protected List<ExpectedWorkItem> getExpectedWorkItems() { List<ExpectedTask> etasks = getExpectedTasks(); return Collections.singletonList( new ExpectedWorkItem(userSodApproverOid, rolePirateOid, etasks.get(0))); } @Override protected void assertDeltaExecuted(int number, boolean yes, Task rootTask, OperationResult result) throws Exception { switch (number) { case 0: if (yes) { assertUserProperty(userJackOid, UserType.F_DESCRIPTION, "Pirate Judge"); } else { if (originalDescription != null) { assertUserProperty(userJackOid, UserType.F_DESCRIPTION, originalDescription); } else { assertUserNoProperty(userJackOid, UserType.F_DESCRIPTION); } } break; case 1: if (yes) { assertAssignedRole(userJackOid, rolePirateOid, rootTask, result); } else { assertNotAssignedRole(userJackOid, rolePirateOid, rootTask, result); } break; } } @Override protected Boolean decideOnApproval(String executionId, org.activiti.engine.task.Task task) throws Exception { login(getUser(userSodApproverOid)); return true; } }, 1, false); // THEN display("jack as a Pirate + Judge", getUser(userJackOid)); assertAssignedRole(userJackOid, roleJudgeOid, task, result); assertAssignedRole(userJackOid, rolePirateOid, task, result); } /** * Assign Respectable to jack. This should trigger an approval as well (because it implies a Thief). */ @Test public void test030AssignRoleRespectable() throws Exception { final String TEST_NAME = "test030AssignRoleRespectable"; TestUtil.displayTestTile(this, TEST_NAME); login(userAdministrator); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // GIVEN unassignRole(userJackOid, rolePirateOid, task, result); assertNotAssignedRole(userJackOid, rolePirateOid, task, result); // WHEN+THEN PrismObject<UserType> jack = getUser(userJackOid); @SuppressWarnings("unchecked") ObjectDelta<UserType> addRespectableDelta = (ObjectDelta<UserType>) DeltaBuilder .deltaFor(UserType.class, prismContext) .item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRespectableOid, ObjectTypes.ROLE, prismContext)) .asObjectDelta(userJackOid); // WHEN+THEN executeTest2(TEST_NAME, new TestDetails2<UserType>() { @Override protected PrismObject<UserType> getFocus(OperationResult result) throws Exception { return jack.clone(); } @Override protected ObjectDelta<UserType> getFocusDelta() throws SchemaException { return addRespectableDelta.clone(); } @Override protected int getNumberOfDeltasToApprove() { return 1; } @Override protected List<Boolean> getApprovals() { return Collections.singletonList(true); } @Override protected List<ObjectDelta<UserType>> getExpectedDeltasToApprove() { return Arrays.asList(addRespectableDelta.clone()); } @Override protected ObjectDelta<UserType> getExpectedDelta0() { //return ObjectDelta.createEmptyModifyDelta(UserType.class, jack.getOid(), prismContext); return ObjectDelta.createModifyDelta(jack.getOid(), Collections.emptyList(), UserType.class, prismContext); } @Override protected String getObjectOid() { return jack.getOid(); } @Override protected List<ExpectedTask> getExpectedTasks() { return Collections.singletonList( new ExpectedTask(roleRespectableOid, "Assigning Respectable to jack")); } @Override protected List<ExpectedWorkItem> getExpectedWorkItems() { List<ExpectedTask> etasks = getExpectedTasks(); return Collections.singletonList( new ExpectedWorkItem(userSodApproverOid, roleRespectableOid, etasks.get(0))); } @Override protected void assertDeltaExecuted(int number, boolean yes, Task rootTask, OperationResult result) throws Exception { switch (number) { case 1: if (yes) { assertAssignedRole(userJackOid, roleRespectableOid, rootTask, result); } else { assertNotAssignedRole(userJackOid, roleRespectableOid, rootTask, result); } break; } } @Override protected Boolean decideOnApproval(String executionId, org.activiti.engine.task.Task task) throws Exception { login(getUser(userSodApproverOid)); return true; } }, 1, false); // THEN display("jack as a Judge + Respectable", getUser(userJackOid)); assertAssignedRole(userJackOid, roleJudgeOid, task, result); assertAssignedRole(userJackOid, roleRespectableOid, task, result); } @Test public void zzzMarkAsNotInitialized() { display("Setting class as not initialized"); unsetSystemInitialized(); } }