From 88020f731af91109fd8196574d9069616c93fdbe Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Wed, 21 May 2014 19:50:08 +0200 Subject: [PATCH 1/2] Test for focusMappings+role outbound interaction (MID-1897) --- ...bstractConfiguredModelIntegrationTest.java | 1 + .../midpoint/model/intest/TestOrgStruct.java | 1 - .../model/intest/TestOrgStructMeta.java | 149 +++++++++++++++++- .../resources/orgstruct/role-organized.xml | 41 +++++ 4 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 model/model-intest/src/test/resources/orgstruct/role-organized.xml diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java index c099251b157..bc6aafc4729 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java @@ -194,6 +194,7 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra protected static final File USER_HERMAN_FILE = new File(COMMON_DIR_NAME, "user-herman.xml"); protected static final String USER_HERMAN_OID = "c0c010c0-d34d-b33f-f00d-111111111122"; protected static final String USER_HERMAN_USERNAME = "herman"; + protected static final String USER_HERMAN_FULL_NAME = "Herman Toothrot"; // Has null name, doesn not have given name, no employeeType protected static final String USER_THREE_HEADED_MONKEY_FILENAME = COMMON_DIR_NAME + "/user-three-headed-monkey.xml"; diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStruct.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStruct.java index b15dec37cf3..e3c9b217bed 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStruct.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStruct.java @@ -384,7 +384,6 @@ protected void assertUserOrg(PrismObject user, String... orgOids) thro assertAssignedOrg(user, orgOid); assertHasOrg(user, orgOid); } - assertAssignments(user, orgOids.length); assertHasOrgs(user, orgOids.length); } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStructMeta.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStructMeta.java index f243b285e14..021e90c2908 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStructMeta.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestOrgStructMeta.java @@ -44,6 +44,7 @@ import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; 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.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; @@ -72,7 +73,10 @@ public class TestOrgStructMeta extends TestOrgStruct { protected static final File ROLE_META_FUNCTIONAL_ORG_FILE = new File(TEST_DIR, "role-meta-functional-org.xml"); protected static final String ROLE_META_FUNCTIONAL_ORG_OID = "74aac2c8-ca0f-11e3-bb29-001e8c717e5b"; - + + protected static final File ROLE_ORGANIZED_FILE = new File(TEST_DIR, "role-organized.xml"); + protected static final String ROLE_ORGANIZED_OID = "12345111-1111-2222-1111-121212111001"; + @Override protected boolean doAddOrgstruct() { return false; @@ -86,6 +90,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti setDefaultObjectTemplate(OrgType.COMPLEX_TYPE, OBJECT_TEMPLATE_ORG_OID); repoAddObjectFromFile(ROLE_META_FUNCTIONAL_ORG_FILE, RoleType.class, initResult); + repoAddObjectFromFile(ROLE_ORGANIZED_FILE, RoleType.class, initResult); } @Override @@ -150,5 +155,147 @@ protected void assertUserNoOrg(PrismObject user) throws Exception { // test05x - test3xx inherited from superclass + @Test + public void test400JackAssignScummBar() throws Exception { + final String TEST_NAME = "test400JackAssignScummBar"; + TestUtil.displayTestTile(this, TEST_NAME); + + Task task = taskManager.createTaskInstance(TestOrgStruct.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + addObject(USER_JACK_FILE); + + // Precondition + assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME); + + // WHEN + assignOrg(USER_JACK_OID, ORG_SCUMM_BAR_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + PrismObject user = getUser(USER_JACK_OID); + display("User after", user); + assertUserOrg(user, ORG_SCUMM_BAR_OID); + + assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_FULL_NAME, true); + + // Postcondition + assertMonkeyIslandOrgSanity(); + } + + @Test + public void test402JackAssignOrganized() throws Exception { + final String TEST_NAME = "test402JackAssignOrganized"; + TestUtil.displayTestTile(this, TEST_NAME); + + Task task = taskManager.createTaskInstance(TestOrgStruct.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + assignRole(USER_JACK_OID, ROLE_ORGANIZED_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + PrismObject user = getUser(USER_JACK_OID); + display("User after", user); + assertUserOrg(user, ORG_SCUMM_BAR_OID); + assertAssignedRole(user, ROLE_ORGANIZED_OID); + + assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_FULL_NAME, true); + assertDummyAccountAttribute(null, ACCOUNT_JACK_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, "Proud member of F0006"); + + // Postcondition + assertMonkeyIslandOrgSanity(); + } + + @Test + public void test404JackUnAssignOrganized() throws Exception { + final String TEST_NAME = "test404JackUnAssignOrganized"; + TestUtil.displayTestTile(this, TEST_NAME); + + Task task = taskManager.createTaskInstance(TestOrgStruct.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + unassignRole(USER_JACK_OID, ROLE_ORGANIZED_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + PrismObject user = getUser(USER_JACK_OID); + display("User after", user); + assertUserOrg(user, ORG_SCUMM_BAR_OID); + + assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_FULL_NAME, true); + assertDummyAccountAttribute(null, ACCOUNT_JACK_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME); + + // Postcondition + assertMonkeyIslandOrgSanity(); + } + + @Test + public void test409JackUnassignScummBar() throws Exception { + final String TEST_NAME = "test400JackAssignScummBar"; + TestUtil.displayTestTile(this, TEST_NAME); + + Task task = taskManager.createTaskInstance(TestOrgStruct.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + unassignOrg(USER_JACK_OID, ORG_SCUMM_BAR_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + PrismObject userJack = getUser(USER_JACK_OID); + display("User jack after", userJack); + assertUserNoOrg(userJack); + + assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME); + + // Postcondition + assertMonkeyIslandOrgSanity(); + } + + /** + * Now do the same things as 40x but do it all at once. + */ + @Test + public void test410JackAssignScummBarOrganized() throws Exception { + final String TEST_NAME = "test410JackAssignScummBarOrganized"; + TestUtil.displayTestTile(this, TEST_NAME); + + Task task = taskManager.createTaskInstance(TestOrgStruct.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // Precondition + assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME); + + Collection> modifications = new ArrayList>(); + modifications.add((createAssignmentModification(ROLE_ORGANIZED_OID, RoleType.COMPLEX_TYPE, null, null, null, true))); + modifications.add((createAssignmentModification(ORG_SCUMM_BAR_OID, OrgType.COMPLEX_TYPE, null, null, null, true))); + ObjectDelta userDelta = ObjectDelta.createModifyDelta(USER_JACK_OID, modifications, UserType.class, prismContext); + + // WHEN + modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + PrismObject user = getUser(USER_JACK_OID); + display("User after", user); + assertUserOrg(user, ORG_SCUMM_BAR_OID); + assertAssignedRole(user, ROLE_ORGANIZED_OID); + + assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_FULL_NAME, true); + assertDummyAccountAttribute(null, ACCOUNT_JACK_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, "Proud member of F0006"); + + // Postcondition + assertMonkeyIslandOrgSanity(); + } } diff --git a/model/model-intest/src/test/resources/orgstruct/role-organized.xml b/model/model-intest/src/test/resources/orgstruct/role-organized.xml new file mode 100644 index 00000000000..cc8c81518c1 --- /dev/null +++ b/model/model-intest/src/test/resources/orgstruct/role-organized.xml @@ -0,0 +1,41 @@ + + + Organized + + + + account + + ri:title + + + + $focus/organization + + + + + + + + + From 023d5d29233a420b57aa25f230eff2f6401c9984 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Wed, 21 May 2014 23:00:20 +0200 Subject: [PATCH 2/2] Refactoring assignment processor to support focusMappings + outbound in roles (MID-1897) --- .../model/impl/lens/AssignmentEvaluator.java | 23 +-- .../model/impl/lens/EvaluatedAssignment.java | 34 ++++ .../lens/projector/AssignmentProcessor.java | 177 ++++++++++++------ .../impl/security/UserProfileServiceImpl.java | 2 +- .../impl/lens/TestAssignmentEvaluator.java | 2 +- ...bstractConfiguredModelIntegrationTest.java | 5 - ...stractInitializedModelIntegrationTest.java | 9 - .../intest/TestModelServiceContract.java | 23 +-- .../test/resources/common/user-barbossa.xml | 58 +----- 9 files changed, 181 insertions(+), 152 deletions(-) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java index 83462b030f4..15760071fcd 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java @@ -73,7 +73,7 @@ public class AssignmentEvaluator { private static final Trace LOGGER = TraceManager.getTrace(AssignmentEvaluator.class); private RepositoryService repository; - private ObjectDeltaObject userOdo; + private ObjectDeltaObject focusOdo; private LensContext lensContext; private String channel; private ObjectResolver objectResolver; @@ -92,12 +92,12 @@ public void setRepository(RepositoryService repository) { this.repository = repository; } - public ObjectDeltaObject getUserOdo() { - return userOdo; + public ObjectDeltaObject getFocusOdo() { + return focusOdo; } - public void setUserOdo(ObjectDeltaObject userOdo) { - this.userOdo = userOdo; + public void setFocusOdo(ObjectDeltaObject userOdo) { + this.focusOdo = userOdo; } public LensContext getLensContext() { @@ -189,6 +189,7 @@ public EvaluatedAssignment evaluate(AssignmentType assignmentType, ObjectType so throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException { assertSource(source, assignmentType); EvaluatedAssignment evalAssignment = new EvaluatedAssignment(); + evalAssignment.setAssignmentType(assignmentType); AssignmentPath assignmentPath = new AssignmentPath(); AssignmentPathSegment assignmentPathSegment = new AssignmentPathSegment(assignmentType, null); assignmentPathSegment.setSource(source); @@ -242,7 +243,7 @@ private void evaluateAssignment(EvaluatedAssignment evalAssignment, AssignmentPa if (assignmentType.getConstruction() != null) { if (evaluateConstructions && assignmentPathSegment.isEvaluateConstructions()) { - evaluateConstruction(evalAssignment, assignmentPathSegment, source, sourceDescription, + prepareConstructionEvaluation(evalAssignment, assignmentPathSegment, source, sourceDescription, assignmentPath, assignmentPathSegment.getOrderOneObject(), task, result); } @@ -272,7 +273,7 @@ private void evaluateAssignment(EvaluatedAssignment evalAssignment, AssignmentPa assignmentPath.remove(assignmentPathSegment); } - private void evaluateConstruction(EvaluatedAssignment evaluatedAssignment, AssignmentPathSegment assignmentPathSegment, ObjectType source, String sourceDescription, + private void prepareConstructionEvaluation(EvaluatedAssignment evaluatedAssignment, AssignmentPathSegment assignmentPathSegment, ObjectType source, String sourceDescription, AssignmentPath assignmentPath, ObjectType orderOneObject, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { assertSource(source, evaluatedAssignment); @@ -280,12 +281,12 @@ private void evaluateConstruction(EvaluatedAssignment evaluatedAssignment, Assig AssignmentType assignmentType = assignmentPathSegment.getAssignmentType(); ConstructionType constructionType = assignmentType.getConstruction(); - LOGGER.trace("Evaluate construction '{}' in {}", constructionType.getDescription(), source); + LOGGER.trace("Preparing construction '{}' in {}", constructionType.getDescription(), source); Construction construction = new Construction(constructionType, source); // We have to clone here as the path is constantly changing during evaluation construction.setAssignmentPath(assignmentPath.clone()); - construction.setUserOdo(userOdo); + construction.setUserOdo(focusOdo); construction.setLensContext(lensContext); construction.setObjectResolver(objectResolver); construction.setPrismContext(prismContext); @@ -294,7 +295,7 @@ private void evaluateConstruction(EvaluatedAssignment evaluatedAssignment, Assig construction.setChannel(channel); construction.setOrderOneObject(orderOneObject); - construction.evaluate(task, result); + // Do not evaluate the construction here. We will do it in the second pass. Just prepare everything to be evaluated. evaluatedAssignment.addConstruction(construction); } @@ -312,7 +313,7 @@ private void evaluateFocusMappings(EvaluatedAssignment evaluatedAssignment, Assi AssignmentPathVariables assignmentPathVariables = LensUtil.computeAssignmentPathVariables(assignmentPath); for (MappingType mappingType: mappingsType.getMapping()) { - Mapping mapping = LensUtil.createFocusMapping(mappingFactory, lensContext, mappingType, source, userOdo, + Mapping mapping = LensUtil.createFocusMapping(mappingFactory, lensContext, mappingType, source, focusOdo, assignmentPathVariables, systemConfiguration, now, sourceDescription, result); if (mapping == null) { continue; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignment.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignment.java index dee9c6096f4..226add43977 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignment.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignment.java @@ -18,16 +18,22 @@ import java.util.ArrayList; import java.util.Collection; +import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject; import com.evolveum.midpoint.model.common.mapping.Mapping; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.security.api.Authorization; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; 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.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; @@ -39,13 +45,17 @@ * @author Radovan Semancik */ public class EvaluatedAssignment implements DebugDumpable { + + private static final Trace LOGGER = TraceManager.getTrace(EvaluatedAssignment.class); + private AssignmentType assignmentType; private Collection> constructions; private Collection orgRefVals; private Collection authorizations; private Collection>> focusMappings; private PrismObject target; private boolean isValid; + private boolean forceRecon; public EvaluatedAssignment() { constructions = new ArrayList<>(); @@ -54,6 +64,14 @@ public EvaluatedAssignment() { focusMappings = new ArrayList<>(); } + public AssignmentType getAssignmentType() { + return assignmentType; + } + + public void setAssignmentType(AssignmentType assignmentType) { + this.assignmentType = assignmentType; + } + public Collection> getConstructions() { return constructions; } @@ -102,6 +120,14 @@ public void setValid(boolean isValid) { this.isValid = isValid; } + public boolean isForceRecon() { + return forceRecon; + } + + public void setForceRecon(boolean forceRecon) { + this.forceRecon = forceRecon; + } + public Collection getResources(OperationResult result) throws ObjectNotFoundException, SchemaException { Collection resources = new ArrayList(); for (Construction acctConstr: constructions) { @@ -109,6 +135,14 @@ public Collection getResources(OperationResult result) throws Obje } return resources; } + + public void evaluateConstructions(ObjectDeltaObject focusOdo, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { + for (Construction construction :constructions) { + construction.setUserOdo(focusOdo); + LOGGER.trace("Evaluating construction '{}' in {}", construction); + construction.evaluate(task, result); + } + } @Override public String debugDump() { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java index 0dc1a9b456c..205ebeda828 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java @@ -66,6 +66,7 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.exception.TunnelException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; @@ -195,7 +196,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo // assignments (roles). AssignmentEvaluator assignmentEvaluator = new AssignmentEvaluator(); assignmentEvaluator.setRepository(repositoryService); - assignmentEvaluator.setUserOdo(focusContext.getObjectDeltaObject()); + assignmentEvaluator.setFocusOdo(focusContext.getObjectDeltaObject()); assignmentEvaluator.setLensContext(context); assignmentEvaluator.setChannel(context.getChannel()); assignmentEvaluator.setObjectResolver(objectResolver); @@ -277,8 +278,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, minusConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToMinusSet(evaluatedAssignment); + collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } else { if (assignmentDelta.isReplace()) { @@ -300,24 +300,21 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, zeroConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToZeroSet(evaluatedAssignment); + collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } else if (willHaveValue) { // add EvaluatedAssignment evaluatedAssignment = evaluateAssignment(assignmentType, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result); if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, plusConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToPlusSet(evaluatedAssignment); + collectToPlus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } else if (hadValue) { // delete EvaluatedAssignment evaluatedAssignment = evaluateAssignment(assignmentCValOld.asContainerable(), context, source, assignmentEvaluator, assignmentPlacementDesc, task, result); if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, minusConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToMinusSet(evaluatedAssignment); + collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } else { throw new SystemException("Whoops. Unexpected things happen. Assignment is not old nor new (replace delta)"); } @@ -343,8 +340,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, zeroConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToZeroSet(evaluatedAssignment); + collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } else { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Processing changed assignment, add: {}", SchemaDebugUtil.prettyPrint(assignmentCVal)); @@ -353,8 +349,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, plusConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToPlusSet(evaluatedAssignment); + collectToPlus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } } else if (isDelete && !isAdd) { @@ -366,8 +361,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, minusConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToMinusSet(evaluatedAssignment); + collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } else { // Small change inside an assignment @@ -386,8 +380,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, zeroConstructionMap, evaluatedAssignment, true, result); - evaluatedAssignmentTriple.addToZeroSet(evaluatedAssignment); + collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, true); } else if (isValid) { // Assignment became valid. We need to place it in plus set to initiate provisioning if (LOGGER.isTraceEnabled()) { @@ -397,8 +390,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, plusConstructionMap, evaluatedAssignment, true, result); - evaluatedAssignmentTriple.addToPlusSet(evaluatedAssignment); + collectToPlus(evaluatedAssignmentTriple, evaluatedAssignment, true); } else { // Assignment became invalid. We need to place is in minus set to initiate deprovisioning if (LOGGER.isTraceEnabled()) { @@ -408,8 +400,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, minusConstructionMap, evaluatedAssignment, true, result); - evaluatedAssignmentTriple.addToMinusSet(evaluatedAssignment); + collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, true); } } @@ -423,8 +414,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo if (evaluatedAssignment == null) { continue; } - collectToConstructionMap(context, zeroConstructionMap, evaluatedAssignment, forceRecon, result); - evaluatedAssignmentTriple.addToZeroSet(evaluatedAssignment); + collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); } } } @@ -452,9 +442,18 @@ private void processAssignmentsProjectionsWithFocus(LensCo focusOdo, focusContext.getObjectDefinition(), "focus mappings in assignments of "+focusContext.getHumanReadableName()); LOGGER.trace("Computed focus deltas: {}", focusDeltas); focusContext.applyProjectionWaveSecondaryDeltas(focusDeltas); + focusContext.recompute(); // PROCESSING PROJECTIONS + + // Evaluate the constructions in assignements now. These were not evaluated in the first pass of AssignmentEvaluator + // because there may be interaction from focusMappings of some roles to outbound mappings of other roles. + // Now we have complete focus with all the focusMappings so we can evaluate the constructions + evaluateConstructions(context, evaluatedAssignmentTriple, task, result); + collectToConstructionMap(context, evaluatedAssignmentTriple.getZeroSet(), zeroConstructionMap, result); + collectToConstructionMap(context, evaluatedAssignmentTriple.getPlusSet(), plusConstructionMap, result); + collectToConstructionMap(context, evaluatedAssignmentTriple.getMinusSet(), minusConstructionMap, result); if (LOGGER.isTraceEnabled()) { // Dump the maps @@ -635,6 +634,108 @@ private void processAssignmentsProjectionsWithFocus(LensCo } + private void collectToZero(DeltaSetTriple> evaluatedAssignmentTriple, + EvaluatedAssignment evaluatedAssignment, boolean forceRecon) { + evaluatedAssignment.setForceRecon(forceRecon); + evaluatedAssignmentTriple.addToZeroSet(evaluatedAssignment); + } + + private void collectToPlus(DeltaSetTriple> evaluatedAssignmentTriple, + EvaluatedAssignment evaluatedAssignment, boolean forceRecon) { + evaluatedAssignment.setForceRecon(forceRecon); + evaluatedAssignmentTriple.addToPlusSet(evaluatedAssignment); + } + + private void collectToMinus(DeltaSetTriple> evaluatedAssignmentTriple, + EvaluatedAssignment evaluatedAssignment, boolean forceRecon) { + evaluatedAssignment.setForceRecon(forceRecon); + evaluatedAssignmentTriple.addToMinusSet(evaluatedAssignment); + } + + private void evaluateConstructions(LensContext context, + DeltaSetTriple> evaluatedAssignmentTriple, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { + evaluateConstructions(context, evaluatedAssignmentTriple.getZeroSet(), task, result); + evaluateConstructions(context, evaluatedAssignmentTriple.getPlusSet(), task, result); + evaluateConstructions(context, evaluatedAssignmentTriple.getMinusSet(), task, result); + } + + private void evaluateConstructions(LensContext context, + Collection> evaluatedAssignments, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException { + if (evaluatedAssignments == null) { + return; + } + ObjectDeltaObject focusOdo = null; + LensFocusContext focusContext = context.getFocusContext(); + if (focusContext != null) { + focusOdo = focusContext.getObjectDeltaObject(); + } + Iterator> iterator = evaluatedAssignments.iterator(); + while (iterator.hasNext()) { + EvaluatedAssignment evaluatedAssignment = iterator.next(); + try { + evaluatedAssignment.evaluateConstructions(focusOdo, task, result); + } catch (ObjectNotFoundException ex){ + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Processing of assignment resulted in error {}: {}", ex, SchemaDebugUtil.prettyPrint(evaluatedAssignment.getAssignmentType())); + } + iterator.remove(); + if (!ModelExecuteOptions.isForce(context.getOptions())){ + ModelUtils.recordFatalError(result, ex); + } + } catch (SchemaException ex){ + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Processing of assignment resulted in error {}: {}", ex, SchemaDebugUtil.prettyPrint(evaluatedAssignment.getAssignmentType())); + } + ModelUtils.recordFatalError(result, ex); + String resourceOid = determineResource(evaluatedAssignment.getAssignmentType()); + if (resourceOid == null) { + // This is a role assignment or something like that. Just throw the original exception for now. + throw ex; + } + ResourceShadowDiscriminator rad = new ResourceShadowDiscriminator(resourceOid, + determineKind(evaluatedAssignment.getAssignmentType()), determineIntent(evaluatedAssignment.getAssignmentType())); + LensProjectionContext accCtx = context.findProjectionContext(rad); + if (accCtx != null) { + accCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN); + } + iterator.remove(); + } + } + } + + private void collectToConstructionMap(LensContext context, + Collection> evaluatedAssignments, + Map constructionMap, + OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { + for (EvaluatedAssignment evaluatedAssignment: evaluatedAssignments) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Collecting evaluated assignment:\n{}", evaluatedAssignment.debugDump()); + } + for (Construction construction : evaluatedAssignment.getConstructions()) { + String resourceOid = construction.getResource(result).getOid(); + String intent = construction.getIntent(); + ShadowKindType kind = construction.getKind(); + ResourceType resource = LensUtil.getResource(context, resourceOid, provisioningService, result); + intent = LensUtil.refineProjectionIntent(kind, intent, resource, prismContext); + ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(resourceOid, kind, intent); + ConstructionPack constructionPack = null; + if (constructionMap.containsKey(rat)) { + constructionPack = constructionMap.get(rat); + } else { + constructionPack = new ConstructionPack(); + constructionMap.put(rat, constructionPack); + } + constructionPack.add(new PrismPropertyValue(construction)); + if (evaluatedAssignment.isValid()) { + constructionPack.setHasValidAssignment(true); + } + if (evaluatedAssignment.isForceRecon()) { + constructionPack.setForceRecon(true); + } + } + } + } + private Collection> mergeAssignments( Collection> currentAssignments, Collection> changedAssignments) { @@ -958,36 +1059,6 @@ public void processAssignmentsAccountValues(LensProjectionContext accountContext } - private void collectToConstructionMap(LensContext context, - Map accountMap, EvaluatedAssignment evaluatedAssignment, - boolean forceRecon, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Collecting evaluated assignment:\n{}", evaluatedAssignment.debugDump()); - } - for (Construction construction : evaluatedAssignment.getConstructions()) { - String resourceOid = construction.getResource(result).getOid(); - String intent = construction.getIntent(); - ShadowKindType kind = construction.getKind(); - ResourceType resource = LensUtil.getResource(context, resourceOid, provisioningService, result); - intent = LensUtil.refineProjectionIntent(kind, intent, resource, prismContext); - ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(resourceOid, kind, intent); - ConstructionPack constructionPack = null; - if (accountMap.containsKey(rat)) { - constructionPack = accountMap.get(rat); - } else { - constructionPack = new ConstructionPack(); - accountMap.put(rat, constructionPack); - } - constructionPack.add(new PrismPropertyValue(construction)); - if (evaluatedAssignment.isValid()) { - constructionPack.setHasValidAssignment(true); - } - if (forceRecon) { - constructionPack.setForceRecon(true); - } - } - } - private String dumpAccountMap(Map accountMap) { StringBuilder sb = new StringBuilder(); Set> entrySet = accountMap.entrySet(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java index ecfb0d93517..d03eca53e46 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java @@ -159,7 +159,7 @@ private void addAuthorizations(MidPointPrincipal principal) { AssignmentEvaluator assignmentEvaluator = new AssignmentEvaluator(); assignmentEvaluator.setRepository(repositoryService); - assignmentEvaluator.setUserOdo(new ObjectDeltaObject(userType.asPrismObject(), null, userType.asPrismObject())); + assignmentEvaluator.setFocusOdo(new ObjectDeltaObject(userType.asPrismObject(), null, userType.asPrismObject())); assignmentEvaluator.setChannel(null); assignmentEvaluator.setObjectResolver(objectResolver); assignmentEvaluator.setPrismContext(prismContext); diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java index 6dd030ba8c0..562175153b3 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java @@ -104,7 +104,7 @@ private AssignmentEvaluator createAssignmentEvaluator() throws ObjectNotFoundExc assignmentEvaluator.setRepository(repositoryService); PrismObject userJack = userTypeJack.asPrismObject(); - assignmentEvaluator.setUserOdo(new ObjectDeltaObject(userJack, null, null)); + assignmentEvaluator.setFocusOdo(new ObjectDeltaObject(userJack, null, null)); assignmentEvaluator.setObjectResolver(objectResolver); assignmentEvaluator.setPrismContext(prismContext); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java index bc6aafc4729..d1e7cad1125 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java @@ -92,11 +92,6 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra protected static final String CONNECTOR_DUMMY_FILENAME = COMMON_DIR_NAME + "/connector-dummy.xml"; - protected static final String RESOURCE_OPENDJ_FILENAME = COMMON_DIR_NAME + "/resource-opendj.xml"; - protected static final String RESOURCE_OPENDJ_NAME = "Localhost OpenDJ"; - protected static final String RESOURCE_OPENDJ_OID = "10000000-0000-0000-0000-000000000003"; - protected static final String RESOURCE_OPENDJ_NAMESPACE = MidPointConstants.NS_RI; - protected static final File RESOURCE_DUMMY_FILE = new File(COMMON_DIR, "resource-dummy.xml"); protected static final File RESOURCE_DUMMY_DEPRECATED_FILE = new File(COMMON_DIR, "resource-dummy-deprecated.xml"); protected static final String RESOURCE_DUMMY_OID = "10000000-0000-0000-0000-000000000004"; diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java index 46891a8f863..2950519c6af 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java @@ -92,9 +92,6 @@ public class AbstractInitializedModelIntegrationTest extends AbstractConfiguredM protected UserType userTypeGuybrush; protected UserType userTypeElaine; - protected ResourceType resourceOpenDjType; - protected PrismObject resourceOpenDj; - protected DummyResource dummyResource; protected DummyResourceContoller dummyResourceCtl; protected ResourceType resourceDummyType; @@ -147,12 +144,6 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti clockwork.setDebugListener(lensDebugListener); // Resources - resourceOpenDj = importAndGetObjectFromFile(ResourceType.class, RESOURCE_OPENDJ_FILENAME, RESOURCE_OPENDJ_OID, initTask, initResult); - resourceOpenDjType = resourceOpenDj.asObjectable(); - openDJController.setResource(resourceOpenDj); - if (!openDJController.isRunning()) { - initResult.muteLastSubresultError(); - } dummyResourceCtl = DummyResourceContoller.create(null); dummyResourceCtl.extendSchemaPirate(); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java index 98b0a31b870..9f2677f1f23 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java @@ -164,12 +164,7 @@ public void test041SearchResources() throws Exception { preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); // WHEN - - // opendj is not started, so we do not want to list it (it returns partial_error) - ObjectQuery query = ObjectQuery.createObjectQuery( - new NotFilter( - EqualFilter.createEqual(ResourceType.F_NAME, ResourceType.class, prismContext, PolyStringOrigMatchingRule.NAME, new PolyString(RESOURCE_OPENDJ_NAME)))); - List> resources = modelService.searchObjects(ResourceType.class, query, null, task, result); + List> resources = modelService.searchObjects(ResourceType.class, null, null, task, result); // THEN assertNotNull("null search return", resources); @@ -194,13 +189,7 @@ public void test042SearchResourcesIterative() throws Exception { // GIVEN Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); - preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); - - // opendj is not started, so we do not want to list it (it returns partial_error) - ObjectQuery query = ObjectQuery.createObjectQuery( - new NotFilter( - EqualFilter.createEqual(ResourceType.F_NAME, ResourceType.class, prismContext, PolyStringOrigMatchingRule.NAME, new PolyString(RESOURCE_OPENDJ_NAME)))); - + preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); final List> resources = new ArrayList>(); @@ -218,7 +207,7 @@ public boolean handle(PrismObject resource, OperationResult parent }; // WHEN - modelService.searchObjectsIterative(ResourceType.class, query, handler, null, task, result); + modelService.searchObjectsIterative(ResourceType.class, null, handler, null, task, result); // THEN result.computeStatus(); @@ -296,11 +285,7 @@ public void test051GetUserBarbossa() throws Exception { TestUtil.assertSuccess("getObject result", result); userBarbossa.checkConsistence(true, true); - - PrismContainer assignmentContainer = userBarbossa.findContainer(UserType.F_ASSIGNMENT); - assertEquals("Unexpected number of assignment values", 2, assignmentContainer.size()); - PrismAsserts.assertValueId(1001L,assignmentContainer); - + assertSteadyResources(); } diff --git a/model/model-intest/src/test/resources/common/user-barbossa.xml b/model/model-intest/src/test/resources/common/user-barbossa.xml index f7bf51db930..0546e9378d9 100644 --- a/model/model-intest/src/test/resources/common/user-barbossa.xml +++ b/model/model-intest/src/test/resources/common/user-barbossa.xml @@ -1,6 +1,6 @@ - - ri:o - - - Pirate Brethren, Inc. - - - - - ri:l - - - $c:user/c:locality - - - - - - - - - - - - Shipwreck account construction - - - - ri:l - - - Shipwreck cove - - - - - + + + enabled + Hector Barbossa Hector Barbossa Caribbean - - enabled - -