From b1896ed72d5542d8249cde0ee6417c168441078b Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Fri, 13 Apr 2018 14:44:16 +0200 Subject: [PATCH] Fixing tricky dependencies bug (MID-4554) --- .../lens/projector/ActivationProcessor.java | 36 +- .../impl/lens/projector/MappingEvaluator.java | 6 +- .../projector/MappingEvaluatorParams.java | 6 +- .../impl/lens/projector/MappingTimeEval.java | 26 + .../ProjectionCredentialsProcessor.java | 5 +- .../focus/AssignmentTripleEvaluator.java | 13 +- .../projector/focus/InboundProcessor.java | 3 +- .../model/intest/TestMultiResource.java | 257 ++++++++-- .../midpoint/model/intest/rbac/TestRbac.java | 2 +- .../src/test/resources/logback-test.xml | 6 +- ...sable.xml => resource-dummy-dark-peru.xml} | 7 +- .../multi/resource-dummy-dark-yellow.xml | 482 ++++++++++++++++++ ...-disable.xml => role-dark-yellow-peru.xml} | 8 +- .../test/AbstractModelIntegrationTest.java | 37 +- 14 files changed, 802 insertions(+), 92 deletions(-) create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingTimeEval.java rename model/model-intest/src/test/resources/multi/{resource-dummy-peru-disable.xml => resource-dummy-dark-peru.xml} (95%) create mode 100644 model/model-intest/src/test/resources/multi/resource-dummy-dark-yellow.xml rename model/model-intest/src/test/resources/multi/{role-yellow-peru-disable.xml => role-dark-yellow-peru.xml} (82%) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java index dc383c1d266..6fc31a31b02 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java @@ -179,9 +179,11 @@ public void processActivationUserCurrent(LensContext co return; } - boolean shadowShouldExist = evaluateExistenceMapping(context, projCtx, now, true, task, result); + LOGGER.trace("Evaluating intended existence of projection {} (legal={})", projCtxDesc, projCtx.isLegal()); + + boolean shadowShouldExist = evaluateExistenceMapping(context, projCtx, now, MappingTimeEval.CURRENT, task, result); - LOGGER.trace("Evaluated intended existence of projection {} to {}", projCtxDesc, shadowShouldExist); + LOGGER.trace("Evaluated intended existence of projection {} to {} (legal={})", projCtxDesc, shadowShouldExist, projCtx.isLegal()); // Let's reconcile the existence intent (shadowShouldExist) and the synchronization intent in the context @@ -296,7 +298,7 @@ public void processActivationUserCurrent(LensContext co evaluateActivationMapping(context, projCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - capActivation, now, true, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result); + capActivation, now, MappingTimeEval.CURRENT, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result); } else { LOGGER.trace("Skipping activation administrative status processing because {} does not have activation administrative status capability", projCtx.getResource()); } @@ -309,7 +311,7 @@ public void processActivationUserCurrent(LensContext co } else { evaluateActivationMapping(context, projCtx, activationType.getValidFrom(), SchemaConstants.PATH_ACTIVATION_VALID_FROM, SchemaConstants.PATH_ACTIVATION_VALID_FROM, - null, now, true, ActivationType.F_VALID_FROM.getLocalPart(), task, result); + null, now, MappingTimeEval.CURRENT, ActivationType.F_VALID_FROM.getLocalPart(), task, result); } ResourceBidirectionalMappingType validToMappingType = activationType.getValidTo(); @@ -320,14 +322,14 @@ public void processActivationUserCurrent(LensContext co } else { evaluateActivationMapping(context, projCtx, activationType.getValidTo(), SchemaConstants.PATH_ACTIVATION_VALID_TO, SchemaConstants.PATH_ACTIVATION_VALID_TO, - null, now, true, ActivationType.F_VALID_TO.getLocalPart(), task, result); + null, now, MappingTimeEval.CURRENT, ActivationType.F_VALID_TO.getLocalPart(), task, result); } if (capLockoutStatus != null) { evaluateActivationMapping(context, projCtx, activationType.getLockoutStatus(), SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, - capActivation, now, true, ActivationType.F_LOCKOUT_STATUS.getLocalPart(), task, result); + capActivation, now, MappingTimeEval.CURRENT, ActivationType.F_LOCKOUT_STATUS.getLocalPart(), task, result); } else { LOGGER.trace("Skipping activation lockout status processing because {} does not have activation lockout status capability", projCtx.getResource()); } @@ -417,7 +419,7 @@ public void processActivationUserFuture(LensContext con accCtx.recompute(); - evaluateExistenceMapping(context, accCtx, now, false, task, result); + evaluateExistenceMapping(context, accCtx, now, MappingTimeEval.FUTURE, task, result); PrismObject focusNew = context.getFocusContext().getObjectNew(); if (focusNew == null) { @@ -448,26 +450,26 @@ public void processActivationUserFuture(LensContext con evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - capActivation, now, false, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result); + capActivation, now, MappingTimeEval.FUTURE, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result); } if (capValidFrom != null) { evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_VALID_FROM, SchemaConstants.PATH_ACTIVATION_VALID_FROM, - null, now, false, ActivationType.F_VALID_FROM.getLocalPart(), task, result); + null, now, MappingTimeEval.FUTURE, ActivationType.F_VALID_FROM.getLocalPart(), task, result); } if (capValidTo != null) { evaluateActivationMapping(context, accCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_VALID_TO, SchemaConstants.PATH_ACTIVATION_VALID_TO, - null, now, false, ActivationType.F_VALID_FROM.getLocalPart(), task, result); + null, now, MappingTimeEval.FUTURE, ActivationType.F_VALID_FROM.getLocalPart(), task, result); } } private boolean evaluateExistenceMapping(final LensContext context, - final LensProjectionContext projCtx, final XMLGregorianCalendar now, final boolean current, + final LensProjectionContext projCtx, final XMLGregorianCalendar now, final MappingTimeEval current, Task task, final OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { final String projCtxDesc = projCtx.toHumanReadableString(); @@ -477,8 +479,6 @@ private boolean evaluateExistenceMapping(final LensContext throw new IllegalStateException("Null 'legal' for "+projCtxDesc); } - LOGGER.trace("Evaluating intended existence of projection {}; legal={}", projCtxDesc, legal); - ResourceObjectTypeDefinitionType resourceAccountDefType = projCtx.getResourceObjectTypeDefinitionType(); if (resourceAccountDefType == null) { return legal; @@ -583,7 +583,7 @@ private boolean evaluateExistenceMapping(final LensContext private void evaluateActivationMapping(final LensContext context, final LensProjectionContext projCtx, ResourceBidirectionalMappingType bidirectionalMappingType, final ItemPath focusPropertyPath, final ItemPath projectionPropertyPath, - final ActivationCapabilityType capActivation, XMLGregorianCalendar now, final boolean current, + final ActivationCapabilityType capActivation, XMLGregorianCalendar now, final MappingTimeEval current, String desc, final Task task, final OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { MappingInitializer,PrismPropertyDefinition> initializer = @@ -647,7 +647,7 @@ private void evaluateOutboundMapping(final LensContext< final LensProjectionContext projCtx, ResourceBidirectionalMappingType bidirectionalMappingType, final ItemPath focusPropertyPath, final ItemPath projectionPropertyPath, final MappingInitializer,PrismPropertyDefinition> initializer, - XMLGregorianCalendar now, final boolean evaluateCurrent, String desc, final Task task, final OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { + XMLGregorianCalendar now, final MappingTimeEval evaluateCurrent, String desc, final Task task, final OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { if (bidirectionalMappingType == null) { LOGGER.trace("No '{}' definition in projection {}, skipping", desc, projCtx.toHumanReadableString()); @@ -696,7 +696,7 @@ private void evaluateOutboundMapping(final LensContext< Map>> outputTripleMap = mappingEvaluator.evaluateMappingSetProjection(params, task, result); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Mapping processing output after {}:\n{}", desc, DebugUtil.debugDump(outputTripleMap, 1)); + LOGGER.trace("Mapping processing output after {} ({}):\n{}", desc, evaluateCurrent, DebugUtil.debugDump(outputTripleMap, 1)); } if (projCtx.isDoReconciliation()) { @@ -704,7 +704,7 @@ private void evaluateOutboundMapping(final LensContext< } } - + /** * TODO: can we align this with ReconciliationProcessor? */ @@ -926,7 +926,7 @@ private void processLifecycleFocus(LensContext context, LOGGER.trace("Computing projection lifecycle (mapping): {}", lifecycleStateMappingType); evaluateActivationMapping(context, projCtx, lifecycleStateMappingType, SchemaConstants.PATH_LIFECYCLE_STATE, SchemaConstants.PATH_LIFECYCLE_STATE, - null, now, true, ObjectType.F_LIFECYCLE_STATE.getLocalPart(), task, result); + null, now, MappingTimeEval.CURRENT, ObjectType.F_LIFECYCLE_STATE.getLocalPart(), task, result); } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java index 4cb4fb79023..46eaa1b3ce4 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java @@ -156,7 +156,7 @@ public void evaluateOutboundMapping(final LensContext outboundMappings, final ItemPath focusPropertyPath, final ItemPath projectionPropertyPath, final MappingInitializer,PrismPropertyDefinition> initializer, MappingOutputProcessor> processor, - XMLGregorianCalendar now, final boolean evaluateCurrent, boolean evaluateWeak, + XMLGregorianCalendar now, final MappingTimeEval evaluateCurrent, boolean evaluateWeak, String desc, final Task task, final OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { String projCtxDesc = projCtx.toHumanReadableString(); @@ -245,11 +245,11 @@ public context; private boolean hasFullTargetObject; @@ -137,11 +137,11 @@ public void setSourceContext(ObjectDeltaObject sourceContext) { this.sourceContext = sourceContext; } - public Boolean getEvaluateCurrent() { + public MappingTimeEval getEvaluateCurrent() { return evaluateCurrent; } - public void setEvaluateCurrent(Boolean evaluateCurrent) { + public void setEvaluateCurrent(MappingTimeEval evaluateCurrent) { this.evaluateCurrent = evaluateCurrent; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingTimeEval.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingTimeEval.java new file mode 100644 index 00000000000..d049c9a1537 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingTimeEval.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2018 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.model.impl.lens.projector; + +/** + * @author semancik + * + */ +public enum MappingTimeEval { + + CURRENT, FUTURE; + +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java index a0b0768a3ba..2b302c2c46d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluator; import com.evolveum.midpoint.model.impl.lens.projector.MappingInitializer; import com.evolveum.midpoint.model.impl.lens.projector.MappingOutputProcessor; +import com.evolveum.midpoint.model.impl.lens.projector.MappingTimeEval; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.OriginType; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -255,7 +256,7 @@ public ValuePolicyType resolve() { mappingEvaluator.evaluateOutboundMapping(context, projCtx, outboundMappingTypes, SchemaConstants.PATH_PASSWORD_VALUE, SchemaConstants.PATH_PASSWORD_VALUE, initializer, processor, - now, true, evaluateWeak, "password mapping", task, result); + now, MappingTimeEval.CURRENT, evaluateWeak, "password mapping", task, result); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java index 90c19e34f35..63f8e0a2366 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java @@ -396,16 +396,25 @@ private void processAssignment(DeltaSetTriple> evalua } else { // No change in assignment if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Processing unchanged assignment {}", SchemaDebugUtil.prettyPrint(assignmentCVal)); + LOGGER.trace("Processing unchanged assignment ({}) {}", + presentInCurrent ? "present" : "not present", + SchemaDebugUtil.prettyPrint(assignmentCVal)); } EvaluatedAssignmentImpl evaluatedAssignment = evaluateAssignment(createAssignmentIdiNoChange(assignmentCVal), PlusMinusZero.ZERO, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result); if (evaluatedAssignment == null) { return; } + // NOTE: unchanged may mean both: + // * was there before, is there now + // * was not there before, is not there now evaluatedAssignment.setPresentInCurrentObject(presentInCurrent); evaluatedAssignment.setPresentInOldObject(presentInOld); evaluatedAssignment.setWasValid(evaluatedAssignment.isValid()); - collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); + if (presentInCurrent) { + collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); + } else { + collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon); + } } } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java index d00d9ba6426..909c823c8e0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java @@ -58,6 +58,7 @@ import com.evolveum.midpoint.model.impl.lens.projector.MappingEvaluatorParams; import com.evolveum.midpoint.model.impl.lens.projector.MappingInitializer; import com.evolveum.midpoint.model.impl.lens.projector.MappingOutputProcessor; +import com.evolveum.midpoint.model.impl.lens.projector.MappingTimeEval; import com.evolveum.midpoint.model.impl.lens.projector.credentials.CredentialsProcessor; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; @@ -1438,7 +1439,7 @@ private void processSpecialPropertyInbound(Collection userBefore = getUser(USER_JACK_OID); display("User before", userBefore); assertAssignments(userBefore, 0); + assertLinks(userBefore, 1); // WHEN displayWhen(TEST_NAME); - assignAccount(USER_JACK_OID, RESOURCE_DUMMY_YELLOW_OID, null, task, result); + deleteUserAccount(USER_JACK_OID, RESOURCE_DUMMY_YELLOW_OID, task, result); // THEN displayThen(TEST_NAME); assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); + assertAssignments(userAfter, 0); + assertLinks(userAfter, 0); + + assertNoDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME); + assertNoDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME); + assertNoDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME); + } + + @Test + public void test501JackAssignDummyDarkYellow() throws Exception { + final String TEST_NAME = "test501JackAssignDummyDarkYellow"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); + + PrismObject userBefore = getUser(USER_JACK_OID); + display("User before", userBefore); + assertAssignments(userBefore, 0); + assertLinks(userBefore, 0); + + // WHEN + displayWhen(TEST_NAME); + assignAccount(USER_JACK_OID, RESOURCE_DUMMY_DARK_YELLOW_OID, null, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); assertAssignments(userAfter, 1); assertLinks(userAfter, 1); - assertDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); } - + @Test - public void test502JackAssignDummyPeruDisable() throws Exception { - final String TEST_NAME = "test502JackAssignDummyPeruDisable"; + public void test502JackAssignDummyDarkPeru() throws Exception { + final String TEST_NAME = "test502JackAssignDummyDarkPeru"; displayTestTitle(TEST_NAME); // GIVEN @@ -2327,26 +2374,27 @@ public void test502JackAssignDummyPeruDisable() throws Exception { // WHEN displayWhen(TEST_NAME); - assignAccount(USER_JACK_OID, RESOURCE_DUMMY_PERU_DISABLE_OID, null, task, result); + assignAccount(USER_JACK_OID, RESOURCE_DUMMY_DARK_PERU_OID, null, task, result); // THEN displayThen(TEST_NAME); assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); assertAssignments(userAfter, 2); assertLinks(userAfter, 2); - assertDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); - assertDummyAccount(RESOURCE_DUMMY_PERU_DISABLE_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); } /** * MID-4554 */ @Test - public void test504JackUnassignDummyPeruDisable() throws Exception { - final String TEST_NAME = "test504JackUnassignDummyPeruDisable"; + public void test504JackUnassignDummyDarkPeru() throws Exception { + final String TEST_NAME = "test504JackUnassignDummyDarkPeru"; displayTestTitle(TEST_NAME); // GIVEN @@ -2358,23 +2406,24 @@ public void test504JackUnassignDummyPeruDisable() throws Exception { // WHEN displayWhen(TEST_NAME); - unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_PERU_DISABLE_OID, null, task, result); + unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_DARK_PERU_OID, null, task, result); // THEN displayThen(TEST_NAME); assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); assertAssignments(userAfter, 1); assertLinks(userAfter, 2); - assertDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); - assertDummyAccount(RESOURCE_DUMMY_PERU_DISABLE_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); } @Test - public void test509JackUnassignDummyYellow() throws Exception { - final String TEST_NAME = "test509JackUnassignDummyYellow"; + public void test507JackUnassignDummyDarkYellow() throws Exception { + final String TEST_NAME = "test507JackUnassignDummyDarkYellow"; displayTestTitle(TEST_NAME); // GIVEN @@ -2386,23 +2435,82 @@ public void test509JackUnassignDummyYellow() throws Exception { // WHEN displayWhen(TEST_NAME); - unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_YELLOW_OID, null, task, result); + unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_DARK_YELLOW_OID, null, task, result); // THEN displayThen(TEST_NAME); assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); + assertAssignments(userAfter, 0); + assertLinks(userAfter, 2); + + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + } + + @Test + public void test508JackDeleteDummyDarkYellowAccount() throws Exception { + final String TEST_NAME = "test508JackDeleteDummyDarkYellowAccount"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject userBefore = getUser(USER_JACK_OID); + display("User before", userBefore); + + // WHEN + displayWhen(TEST_NAME); + deleteUserAccount(USER_JACK_OID, RESOURCE_DUMMY_DARK_YELLOW_OID, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); assertAssignments(userAfter, 0); assertLinks(userAfter, 1); - assertNoDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME); - assertDummyAccount(RESOURCE_DUMMY_PERU_DISABLE_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + assertNoDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); } @Test - public void test510JackAssignRoleYellowPeruDisable() throws Exception { - final String TEST_NAME = "test510JackAssignRoleYellowPeruDisable"; + public void test509JackDeleteDummyDarkPeruAccount() throws Exception { + final String TEST_NAME = "test509JackDeleteDummyDarkPeruAccount"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject userBefore = getUser(USER_JACK_OID); + display("User before", userBefore); + + // WHEN + displayWhen(TEST_NAME); + deleteUserAccount(USER_JACK_OID, RESOURCE_DUMMY_DARK_PERU_OID, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); + assertAssignments(userAfter, 0); + assertLinks(userAfter, 0); + + assertNoDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME); + assertNoDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME); + } + + @Test + public void test510JackAssignRoleDarkYellowPeru() throws Exception { + final String TEST_NAME = "test510JackAssignRoleDarkYellowPeru"; displayTestTitle(TEST_NAME); // GIVEN @@ -2419,26 +2527,27 @@ public void test510JackAssignRoleYellowPeruDisable() throws Exception { // WHEN displayWhen(TEST_NAME); - assignRole(USER_JACK_OID, ROLE_YELLOW_PERU_DISABLE_OID, task, result); + assignRole(USER_JACK_OID, ROLE_DARK_YELLOW_PERU_OID, task, result); // THEN displayThen(TEST_NAME); assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); assertAssignments(userAfter, 1); assertLinks(userAfter, 2); - assertDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); - assertDummyAccount(RESOURCE_DUMMY_PERU_DISABLE_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); } /** * MID-4554 */ @Test - public void test519JackUnassignRoleYellowPeruDisable() throws Exception { - final String TEST_NAME = "test519JackUnassignRoleYellowPeruDisable"; + public void test519JackUnassignDarkRoleYellowPeru() throws Exception { + final String TEST_NAME = "test519JackUnassignDarkRoleYellowPeru"; displayTestTitle(TEST_NAME); // GIVEN @@ -2450,18 +2559,86 @@ public void test519JackUnassignRoleYellowPeruDisable() throws Exception { // WHEN displayWhen(TEST_NAME); - unassignRole(USER_JACK_OID, ROLE_YELLOW_PERU_DISABLE_OID, task, result); + unassignRole(USER_JACK_OID, ROLE_DARK_YELLOW_PERU_OID, task, result); // THEN displayThen(TEST_NAME); assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); assertAssignments(userAfter, 0); - assertLinks(userAfter, 1); + assertLinks(userAfter, 2); - assertNoDummyAccount(RESOURCE_DUMMY_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME); - assertDummyAccount(RESOURCE_DUMMY_PERU_DISABLE_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + } + + @Test + public void test520JackAssignRoleDarkYellowPeru() throws Exception { + final String TEST_NAME = "test520JackAssignRoleDarkYellowPeru"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); + + // Old password too short for yellow resource + modifyUserChangePassword(USER_JACK_OID, "123abc456QWE", task, result); + + PrismObject userBefore = getUser(USER_JACK_OID); + display("User before", userBefore); + assertAssignments(userBefore, 0); + + // WHEN + displayWhen(TEST_NAME); + assignRole(USER_JACK_OID, ROLE_DARK_YELLOW_PERU_OID, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); + assertAssignments(userAfter, 1); + assertLinks(userAfter, 2); + + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + } + + /** + * MID-4554 + */ + @Test + public void test529JackUnassignRoleDarkYellowPeru() throws Exception { + final String TEST_NAME = "test529JackUnassignRoleDarkYellowPeru"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject userBefore = getUser(USER_JACK_OID); + display("User before", userBefore); + AssignmentType currentAssignment = findAssignmentByTargetRequired(userBefore, ROLE_DARK_YELLOW_PERU_OID); + + // WHEN + displayWhen(TEST_NAME); + unassign(UserType.class, USER_JACK_OID, currentAssignment.getId(), task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after", userAfter); + assertAssignments(userAfter, 0); + assertLinks(userAfter, 2); + + assertDummyAccount(RESOURCE_DUMMY_DARK_YELLOW_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); + assertDummyAccount(RESOURCE_DUMMY_DARK_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, false); } } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestRbac.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestRbac.java index c6224f683ff..ed176ccc2cc 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestRbac.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestRbac.java @@ -1525,7 +1525,7 @@ public void test539JackUnAssignRoleCleric() throws Exception { // WHEN displayWhen(TEST_NAME); - modelService.executeChanges(MiscSchemaUtil.createCollection(assignmentDelta), getDefaultOptions(), task, result); + executeChanges(assignmentDelta, getDefaultOptions(), task, result); // THEN displayThen(TEST_NAME); diff --git a/model/model-intest/src/test/resources/logback-test.xml b/model/model-intest/src/test/resources/logback-test.xml index 51016166b76..81fc1303dea 100644 --- a/model/model-intest/src/test/resources/logback-test.xml +++ b/model/model-intest/src/test/resources/logback-test.xml @@ -49,20 +49,20 @@ - - + + @@ -89,7 +89,7 @@ - + diff --git a/model/model-intest/src/test/resources/multi/resource-dummy-peru-disable.xml b/model/model-intest/src/test/resources/multi/resource-dummy-dark-peru.xml similarity index 95% rename from model/model-intest/src/test/resources/multi/resource-dummy-peru-disable.xml rename to model/model-intest/src/test/resources/multi/resource-dummy-dark-peru.xml index f5b9c07c50f..02b77cb71e3 100644 --- a/model/model-intest/src/test/resources/multi/resource-dummy-peru-disable.xml +++ b/model/model-intest/src/test/resources/multi/resource-dummy-dark-peru.xml @@ -29,7 +29,7 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - Dummy Resource Peru Disable + Dummy Resource Dark Peru @@ -48,7 +48,7 @@ xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3"> - peru-disable + dark-peru @@ -99,7 +99,7 @@ - + relaxed @@ -113,7 +113,6 @@ - strong + + + + + weak + + $c:user/c:name + + + + + icfs:uid + UID + + + ri:fullname + Full Name + + + $user/fullName + + + + weak + + $user/fullName + + + + + ri:location + Location + + strong + + + $c:user/c:locality + + + + + + + + http://midpoint.evolveum.com/xml/ns/public/provisioning/channels-3#import + + + + + description + + + + + ri:ship + Ship + + + + + + organizationalUnit + + + + + + + + ri:loot + Loot + explicit + + http://pirates.net/avast + + + + + + + ri:weapon + Weapon + + weak + + + declare namespace piracy = "http://midpoint.evolveum.com/xml/ns/samples/piracy"; + $user/extension/piracy:weapon + + + + + + ri:drink + Drink + false + + strong + + drink + + + + + ri:quote + Quote + false + + yellow-outbound-quote + strong + + shadowStatus + $shadow/activation/administrativeStatus + + + + + + + + + + + ri:gossip + Gossip + + + + + + + + + + ri:water + + true + + + + + fishy + + + + + + very FISHY + + + $user/fullName + + + + + + 5 + + + + daviejones + + + calypso + + + + + + weak + + $focusExists + + + + + + + + + + + + + + + + passwd-asis + + + + + + passwd-generate + weak + + + + + + weak + + + + + + + + + + + + + + usr + + + + acc + + + + res + + + 3 + size + + +to spiral :size + if :size > 30 [stop] + fd :size rt 15 + spiral :size *1.02 +end + + add + after + + + + + + + + + + + + + + + + true + + + + + true + + + c:name + + declare namespace icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"; + $account/attributes/icfs:name + + + + + + + diff --git a/model/model-intest/src/test/resources/multi/role-yellow-peru-disable.xml b/model/model-intest/src/test/resources/multi/role-dark-yellow-peru.xml similarity index 82% rename from model/model-intest/src/test/resources/multi/role-yellow-peru-disable.xml rename to model/model-intest/src/test/resources/multi/role-dark-yellow-peru.xml index 7095aadcdae..4d76765a876 100644 --- a/model/model-intest/src/test/resources/multi/role-yellow-peru-disable.xml +++ b/model/model-intest/src/test/resources/multi/role-dark-yellow-peru.xml @@ -18,17 +18,17 @@ xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"> - Yellow Peru Disable - Yellow account + Peru disable account + Dark Yellow Peru + Dark yellow account + dark peru account - + account - + account diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java index 884ddcefb33..ead7c93b000 100644 --- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java +++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java @@ -991,8 +991,7 @@ protected void modifyUserAssignment(String userOid, String roleOid, QName refTyp SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { ObjectDelta userDelta = createAssignmentUserDelta(userOid, roleOid, refType, relation, extension, activationType, add); - Collection> deltas = MiscSchemaUtil.createCollection(userDelta); - modelService.executeChanges(deltas, options, task, result); + executeChanges(userDelta, options, task, result); } protected void modifyFocusAssignment(Class focusClass, String focusOid, String roleOid, QName refType, QName relation, Task task, @@ -1009,8 +1008,7 @@ protected void modifyFocusAssignment(Class focusClass, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { ObjectDelta delta = createAssignmentFocusDelta(focusClass, focusOid, roleOid, refType, relation, extension, activationType, add); - Collection> deltas = MiscSchemaUtil.createCollection(delta); - modelService.executeChanges(deltas, options, task, result); + executeChanges(delta, options, task, result); } protected void modifyUserAssignment(String userOid, String roleOid, QName refType, QName relation, Task task, @@ -1036,7 +1034,7 @@ protected void modifyFocusAssignment(Class focusClass, throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { ObjectDelta focusDelta = createAssignmentFocusDelta(focusClass, focusOid, roleOid, refType, relation, modificationBlock, add); Collection> deltas = MiscSchemaUtil.createCollection(focusDelta); - modelService.executeChanges(deltas, options, task, result); + executeChanges(focusDelta, options, task, result); } protected void deleteFocusAssignmentEmptyDelta(PrismObject existingFocus, String targetOid, Task task, OperationResult result) @@ -1053,10 +1051,19 @@ protected void deleteFocusAssignmentEmptyDelta(PrismObject ModelExecuteOptions options, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { ObjectDelta focusDelta = createAssignmentFocusEmptyDeleteDelta(existingFocus, targetOid, relation); - Collection> deltas = MiscSchemaUtil.createCollection(focusDelta); - modelService.executeChanges(deltas, options, task, result); + executeChanges(focusDelta, options, task, result); + } + + protected void unassign(Class focusClass, String focusOid, long assignmentId, Task task, OperationResult result) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { + unassign(focusClass, focusOid, assignmentId, null, task, result); } + protected void unassign(Class focusClass, String focusOid, long assignmentId, ModelExecuteOptions options, Task task, OperationResult result) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { + unassign(focusClass, focusOid, createAssignmentIdOnly(assignmentId), options, task, result); + } + protected void unassign(Class focusClass, String focusOid, AssignmentType currentAssignment, ModelExecuteOptions options, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException { Collection> modifications = new ArrayList<>(); @@ -1064,8 +1071,7 @@ protected void unassign(Class focusClass, String focusO assignmentDelta.addValuesToDelete(currentAssignment.asPrismContainerValue().clone()); modifications.add(assignmentDelta); ObjectDelta focusDelta = ObjectDelta.createModifyDelta(focusOid, modifications, focusClass, prismContext); - Collection> deltas = MiscSchemaUtil.createCollection(focusDelta); - modelService.executeChanges(deltas, options, task, result); + executeChanges(focusDelta, options, task, result); } /** @@ -2597,7 +2603,11 @@ protected ObjectDelta createModifyUserDeleteDummyAccount(String userOi } protected ObjectDelta createModifyUserDeleteAccount(String userOid, PrismObject resource) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - String accountOid = getLinkRefOid(userOid, resource.getOid()); + return createModifyUserDeleteAccount(userOid, resource.getOid()); + } + + protected ObjectDelta createModifyUserDeleteAccount(String userOid, String resourceOid) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + String accountOid = getLinkRefOid(userOid, resourceOid); PrismObject account = getShadowModel(accountOid); ObjectDelta userDelta = ObjectDelta.createEmptyModifyDelta(UserType.class, userOid, prismContext); @@ -2620,6 +2630,11 @@ protected ObjectDelta createModifyUserUnlinkAccount(String userOid, Pr return userDelta; } + + protected void deleteUserAccount(String userOid, String resourceOid, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException { + ObjectDelta userDelta = createModifyUserDeleteAccount(userOid, resourceOid); + executeChanges(userDelta, null, task, result); + } // TASKS @@ -4166,7 +4181,7 @@ protected void modifyRoleDeleteInducement(String roleOid, long inducementId, boo RoleType.F_INDUCEMENT, prismContext, inducement); ModelExecuteOptions options = nullToEmpty(defaultOptions); options.setReconcileAffected(reconcileAffected); - modelService.executeChanges(MiscSchemaUtil.createCollection(roleDelta), options, task, result); + executeChanges(roleDelta, options, task, result); result.computeStatus(); if (reconcileAffected) { TestUtil.assertInProgressOrSuccess(result);