/*
* 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.policy.assignments.metarole;
import com.evolveum.midpoint.prism.PrismObject;
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.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.util.TestUtil;
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.ApprovalInstruction;
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.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
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.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo;
import static com.evolveum.midpoint.test.IntegrationTestTools.display;
/**
* A special test dealing with assigning roles that have different metarole-induced approval policies.
*
* Role21 - uses default approval (org:approver)
* Role22 - uses metarole 1 'default' induced approval (org:special-approver)
* Role23 - uses both metarole 'default' and 'security' induced approval (org:special-approver and org:security-approver)
*
* @author mederly
*/
@ContextConfiguration(locations = {"classpath:ctx-workflow-test-main.xml"})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class TestAssignmentsWithDifferentMetaroles extends AbstractWfTestPolicy {
protected static final Trace LOGGER = TraceManager.getTrace(TestAssignmentsWithDifferentMetaroles.class);
protected static final File TEST_ASSIGNMENTS_RESOURCE_DIR = new File("src/test/resources/policy/assignments");
protected static final File ROLE_ROLE21_FILE = new File(TEST_ASSIGNMENTS_RESOURCE_DIR, "role-role21-standard.xml");
protected static final File ROLE_ROLE22_FILE = new File(TEST_ASSIGNMENTS_RESOURCE_DIR, "role-role22-special.xml");
protected static final File ROLE_ROLE23_FILE = new File(TEST_ASSIGNMENTS_RESOURCE_DIR, "role-role23-special-and-security.xml");
protected static final File USER_LEAD21_FILE = new File(TEST_ASSIGNMENTS_RESOURCE_DIR, "user-lead21.xml");
protected static final File USER_LEAD22_FILE = new File(TEST_ASSIGNMENTS_RESOURCE_DIR, "user-lead22.xml");
protected static final File USER_LEAD23_FILE = new File(TEST_ASSIGNMENTS_RESOURCE_DIR, "user-lead23.xml");
protected String roleRole21Oid;
protected String roleRole22Oid;
protected String roleRole23Oid;
protected String userLead21Oid;
protected String userLead22Oid;
protected String userLead23Oid;
@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
super.initSystem(initTask, initResult);
roleRole21Oid = repoAddObjectFromFile(ROLE_ROLE21_FILE, initResult).getOid();
roleRole22Oid = repoAddObjectFromFile(ROLE_ROLE22_FILE, initResult).getOid();
roleRole23Oid = repoAddObjectFromFile(ROLE_ROLE23_FILE, initResult).getOid();
userLead21Oid = addAndRecomputeUser(USER_LEAD21_FILE, initTask, initResult);
userLead22Oid = addAndRecomputeUser(USER_LEAD22_FILE, initTask, initResult);
userLead23Oid = addAndRecomputeUser(USER_LEAD23_FILE, initTask, initResult);
}
@Test
public void test102AddRoles123AssignmentYYYYDeputy() throws Exception {
final String TEST_NAME = "test102AddRoles123AssignmentYYYYDeputy";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, false, true, true, true, true, true);
}
@Test
public void test105AddRoles123AssignmentYYYYImmediate() throws Exception {
final String TEST_NAME = "test105AddRoles123AssignmentYYYYImmediate";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, true, true, true, true, true, false);
}
@Test
public void test110AddRoles123AssignmentNNNN() throws Exception {
final String TEST_NAME = "test110AddRoles123AssignmentNNNN";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, true, false, false, false, false, false);
}
@Test
public void test115AddRoles123AssignmentNNNNImmediate() throws Exception {
final String TEST_NAME = "test115AddRoles123AssignmentNNNNImmediate";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, true, false, false, false, false, false);
}
@Test
public void test120AddRoles123AssignmentYNNN() throws Exception {
final String TEST_NAME = "test120AddRoles123AssignmentYNNN";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, true, true, false, false, false, false);
}
@Test
public void test125AddRoles123AssignmentYNNNImmediate() throws Exception {
final String TEST_NAME = "test125AddRoles123AssignmentYNNNImmediate";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, true, true, false, false, false, false);
}
@Test
public void test130AddRoles123AssignmentYYYN() throws Exception {
final String TEST_NAME = "test130AddRoles123AssignmentYYYN";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, false, true, true, true, false, false);
}
@Test
public void test132AddRoles123AssignmentYYYNDeputy() throws Exception {
final String TEST_NAME = "test132AddRoles123AssignmentYYYNDeputy";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, false, true, true, true, false, true);
}
@Test
public void test135AddRoles123AssignmentYYYNImmediate() throws Exception {
final String TEST_NAME = "test135AddRoles123AssignmentYYYNImmediate";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, true, true, true, true, false, false);
}
/**
* Attempt to assign roles 21-23 along with changing description.
*/
@Test
public void test200AddRoles123AssignmentYYYY() throws Exception {
final String TEST_NAME = "test200AddRoles012AssignmentYYYY";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid);
executeAssignRoles123ToJack(TEST_NAME, false, true, true, true, true, false);
}
@Test
public void test210DeleteRoles123AssignmentN() throws Exception {
final String TEST_NAME = "test210DeleteRoles123AssignmentN";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
executeUnassignRoles123ToJack(TEST_NAME, false, false, false, true);
}
@Test
public void test212DeleteRoles123AssignmentNById() throws Exception {
final String TEST_NAME = "test212DeleteRoles123AssignmentNById";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
executeUnassignRoles123ToJack(TEST_NAME, false, false, true, false);
}
@Test
public void test218DeleteRoles123AssignmentY() throws Exception {
final String TEST_NAME = "test218DeleteRoles123AssignmentY";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
executeUnassignRoles123ToJack(TEST_NAME, false, true, false, false);
}
@Test
public void test220AddRoles123AssignmentYYYY() throws Exception {
final String TEST_NAME = "test220AddRoles012AssignmentYYYY";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
unassignAllRoles(userJackOid, true);
executeAssignRoles123ToJack(TEST_NAME, false, true, true, true, true, false);
}
@Test
public void test230DeleteRoles123AssignmentYById() throws Exception {
final String TEST_NAME = "test230DeleteRoles123AssignmentYById";
TestUtil.displayTestTile(this, TEST_NAME);
login(userAdministrator);
executeUnassignRoles123ToJack(TEST_NAME, false, true, true, true);
}
private void executeAssignRoles123ToJack(String TEST_NAME, boolean immediate,
boolean approve1, boolean approve2, boolean approve3a, boolean approve3b, boolean securityDeputy) throws Exception {
Task task = createTask("executeAssignRoles123ToJack");
PrismObject<UserType> jack = getUser(userJackOid);
@SuppressWarnings("unchecked")
ObjectDelta<UserType> addRole1Delta = (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRole21Oid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
ObjectDelta<UserType> addRole2Delta = (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRole22Oid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
ObjectDelta<UserType> addRole3Delta = (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRole23Oid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
ObjectDelta<UserType> changeDescriptionDelta = (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace(TEST_NAME)
.asObjectDelta(userJackOid);
ObjectDelta<UserType> primaryDelta = ObjectDelta.summarize(addRole1Delta, addRole2Delta, addRole3Delta, changeDescriptionDelta);
ObjectDelta<UserType> delta0 = changeDescriptionDelta.clone();
String originalDescription = getUser(userJackOid).asObjectable().getDescription();
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 3;
}
@Override
protected List<Boolean> getApprovals() {
return Arrays.asList(approve1, approve2, approve3a && approve3b);
}
@Override
protected List<ObjectDelta<UserType>> getExpectedDeltasToApprove() {
return Arrays.asList(addRole1Delta.clone(), addRole2Delta.clone(), addRole3Delta.clone());
}
@Override
protected ObjectDelta<UserType> getExpectedDelta0() {
return delta0.clone();
}
@Override
protected String getObjectOid() {
return jack.getOid();
}
@Override
protected List<ExpectedTask> getExpectedTasks() {
return Arrays.asList(
new ExpectedTask(roleRole21Oid, "Assigning Role21 to jack"),
new ExpectedTask(roleRole22Oid, "Assigning Role22 to jack"),
new ExpectedTask(roleRole23Oid, "Assigning Role23 to jack"));
}
// after first step
@Override
protected List<ExpectedWorkItem> getExpectedWorkItems() {
List<ExpectedTask> tasks = getExpectedTasks();
return Arrays.asList(
new ExpectedWorkItem(userLead21Oid, roleRole21Oid, tasks.get(0)),
new ExpectedWorkItem(userLead22Oid, roleRole22Oid, tasks.get(1)),
new ExpectedWorkItem(userLead23Oid, roleRole23Oid, tasks.get(2))
);
}
@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, TEST_NAME);
} else {
if (originalDescription != null) {
assertUserProperty(userJackOid, UserType.F_DESCRIPTION, originalDescription);
} else {
assertUserNoProperty(userJackOid, UserType.F_DESCRIPTION);
}
}
break;
case 1:
case 2:
case 3:
String[] oids = { roleRole21Oid, roleRole22Oid, roleRole23Oid };
if (yes) {
assertAssignedRole(userJackOid, oids[number-1], rootTask, result);
} else {
assertNotAssignedRole(userJackOid, oids[number-1], rootTask, result);
}
break;
}
}
@Override
protected Boolean decideOnApproval(String executionId, org.activiti.engine.task.Task task) throws Exception {
return null; // ignore this way of approving
}
@Override
public List<ApprovalInstruction> getApprovalSequence() {
List<ExpectedTask> tasks = getExpectedTasks();
List<ApprovalInstruction> instructions = new ArrayList<>();
instructions.add(new ApprovalInstruction(
new ExpectedWorkItem(userLead21Oid, roleRole21Oid, tasks.get(0)), approve1, userLead21Oid));
instructions.add(new ApprovalInstruction(
new ExpectedWorkItem(userLead22Oid, roleRole22Oid, tasks.get(1)), approve2, userLead22Oid));
instructions.add(new ApprovalInstruction(
new ExpectedWorkItem(userLead23Oid, roleRole23Oid, tasks.get(2)), approve3a, userLead23Oid));
if (approve3a) {
ExpectedWorkItem expectedWorkItem = new ExpectedWorkItem(userSecurityApproverOid, roleRole23Oid, tasks.get(2));
ApprovalInstruction.CheckedRunnable before = () -> {
login(getUserFromRepo(userSecurityApproverOid));
checkVisibleWorkItem(expectedWorkItem, 1, task, task.getResult());
login(getUserFromRepo(userSecurityApproverDeputyOid));
checkVisibleWorkItem(expectedWorkItem, 1, task, task.getResult());
login(getUserFromRepo(userSecurityApproverDeputyLimitedOid));
checkVisibleWorkItem(null, 0, task, task.getResult());
};
instructions.add(new ApprovalInstruction(expectedWorkItem, approve3b,
securityDeputy ? userSecurityApproverDeputyOid : userSecurityApproverOid, before, null));
}
return instructions;
}
}, 3, immediate);
}
private void executeUnassignRoles123ToJack(String TEST_NAME, boolean immediate, boolean approve, boolean byId, boolean has1and2) throws Exception {
PrismObject<UserType> jack = getUser(userJackOid);
AssignmentType a1 = has1and2 ? findAssignmentByTargetRequired(jack, roleRole21Oid) : null;
AssignmentType a2 = has1and2 ? findAssignmentByTargetRequired(jack, roleRole22Oid) : null;
AssignmentType a3 = findAssignmentByTargetRequired(jack, roleRole23Oid);
AssignmentType del1 = toDelete(a1, byId);
AssignmentType del2 = toDelete(a2, byId);
AssignmentType del3 = toDelete(a3, byId);
@SuppressWarnings("unchecked")
ObjectDelta<UserType> deleteRole1Delta = has1and2 ? (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(del1)
.asObjectDelta(userJackOid) : null;
@SuppressWarnings("unchecked")
ObjectDelta<UserType> deleteRole2Delta = has1and2 ? (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(del2)
.asObjectDelta(userJackOid) : null;
@SuppressWarnings("unchecked")
ObjectDelta<UserType> deleteRole3Delta = (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(del3)
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
ObjectDelta<UserType> changeDescriptionDelta = (ObjectDelta<UserType>) DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace(TEST_NAME)
.asObjectDelta(userJackOid);
ObjectDelta<UserType> primaryDelta = ObjectDelta.summarize(changeDescriptionDelta, deleteRole1Delta, deleteRole2Delta, deleteRole3Delta);
ObjectDelta<UserType> delta0 = ObjectDelta.summarize(changeDescriptionDelta, deleteRole1Delta, deleteRole2Delta);
String originalDescription = getUser(userJackOid).asObjectable().getDescription();
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 Arrays.asList(approve);
}
@Override
protected List<ObjectDelta<UserType>> getExpectedDeltasToApprove() {
return Arrays.asList(deleteRole3Delta.clone());
}
@Override
protected ObjectDelta<UserType> getExpectedDelta0() {
return delta0.clone();
}
@Override
protected String getObjectOid() {
return jack.getOid();
}
@Override
protected List<ExpectedTask> getExpectedTasks() {
return Arrays.asList(
new ExpectedTask(roleRole23Oid, "Unassigning Role23 from jack"));
}
// after first step
@Override
protected List<ExpectedWorkItem> getExpectedWorkItems() {
List<ExpectedTask> tasks = getExpectedTasks();
return Arrays.asList(
new ExpectedWorkItem(userSecurityApproverOid, roleRole23Oid, tasks.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, TEST_NAME);
} else {
if (originalDescription != null) {
assertUserProperty(userJackOid, UserType.F_DESCRIPTION, originalDescription);
} else {
assertUserNoProperty(userJackOid, UserType.F_DESCRIPTION);
}
}
if (yes || !has1and2) {
assertNotAssignedRole(userJackOid, roleRole21Oid, rootTask, result);
assertNotAssignedRole(userJackOid, roleRole22Oid, rootTask, result);
} else {
assertAssignedRole(userJackOid, roleRole21Oid, rootTask, result);
assertAssignedRole(userJackOid, roleRole22Oid, rootTask, result);
}
break;
case 1:
if (yes) {
assertNotAssignedRole(userJackOid, roleRole23Oid, rootTask, result);
} else {
assertAssignedRole(userJackOid, roleRole23Oid, rootTask, result);
}
break;
default:
throw new IllegalArgumentException("Unexpected delta number: " + number);
}
}
@Override
protected Boolean decideOnApproval(String executionId, org.activiti.engine.task.Task task) throws Exception {
return null; // ignore this way of approving
}
@Override
public List<ApprovalInstruction> getApprovalSequence() {
List<ExpectedTask> tasks = getExpectedTasks();
List<ApprovalInstruction> instructions = new ArrayList<>();
instructions.add(new ApprovalInstruction(
new ExpectedWorkItem(userSecurityApproverOid, roleRole23Oid, tasks.get(0)), approve,
userSecurityApproverOid));
return instructions;
}
}, 1, immediate);
}
private AssignmentType toDelete(AssignmentType assignment, boolean byId) {
if (assignment == null) {
return null;
}
if (!byId) {
return assignment.clone();
} else {
AssignmentType rv = new AssignmentType(prismContext);
rv.setId(assignment.getId());
return rv;
}
}
@Test
public void zzzMarkAsNotInitialized() {
display("Setting class as not initialized");
unsetSystemInitialized();
}
}