handler, ValuePolicy
case PERSONA:
handlePersonas(handler, contextDescription, task, result);
break;
+ case PROJECTION:
+ handleProjections(handler, prohibitedValueItemType, contextDescription, task, result);
+ break;
default:
throw new IllegalArgumentException("Unexpected origin type "+originType);
}
@@ -93,6 +110,52 @@ private void handlePersonas(ResultHandler
handler, Str
handler.handle((PrismObject
) persona.asPrismObject(), result);
}
}
+
+ private
void handleProjections(ResultHandler
handler, ProhibitedValueItemType prohibitedValueItemType, String contextDescription, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException {
+ PrismObject object = getObject();
+ // Not very efficient. We will usually read the shadows again, as they are already in model context.
+ // It will also work only for the items that are stored in shadow (usually not attributes, unless caching is enabled).
+ // But this is good enough for now.
+ FocusType focusType;
+ if (object.canRepresent(FocusType.class)) {
+ focusType = ((FocusType)object.asObjectable());
+ } else if (object.canRepresent(ShadowType.class)) {
+ ObjectQuery query = QueryBuilder
+ .queryFor(FocusType.class, getObject().getPrismContext())
+ .item(UserType.F_LINK_REF).ref(getObject().getOid())
+ .build();
+ final Holder focusTypeHolder = new Holder<>();
+ try {
+ objectResolver.searchIterative(FocusType.class, query,
+ SelectorOptions.createCollection(GetOperationOptions.createReadOnly()),
+ (foundObject, objectResult) -> {
+ focusTypeHolder.setValue(foundObject.asObjectable());
+ return true;
+ }, task, result);
+ } catch (CommunicationException | ConfigurationException | SecurityViolationException
+ | ExpressionEvaluationException e) {
+ throw new SystemException(e.getMessage(), e);
+ }
+ focusType = focusTypeHolder.getValue();
+ } else {
+ return;
+ }
+ ResourceShadowDiscriminator shadowDiscriminator = ResourceShadowDiscriminator.fromResourceShadowDiscriminatorType(prohibitedValueItemType.getProjectionDiscriminator());
+ for (ObjectReferenceType linkRef: focusType.getLinkRef()) {
+ GetOperationOptions options = GetOperationOptions.createReadOnly();
+ options.setNoFetch(true);
+ ShadowType shadowType = objectResolver.resolve(linkRef, ShadowType.class,
+ SelectorOptions.createCollection(options),
+ "resolving projection shadow in " + contextDescription, task, result);
+ if (shadowDiscriminator != null) {
+ if (!ShadowUtil.matches(shadowType.asPrismObject(), shadowDiscriminator)) {
+ LOGGER.trace("Skipping evaluation of projection {} in {} because it does not match discriminator", shadowType, contextDescription);
+ continue;
+ }
+ }
+ handler.handle((PrismObject) shadowType.asPrismObject(), result);
+ }
+ }
private
void handleOwner(ResultHandler
handler, String contextDescription, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
objectResolver.searchIterative(getOwnerClass(), getOwnerQuery(), SelectorOptions.createCollection(GetOperationOptions.createReadOnly()),
diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java
index fa682afeaab..d63fdba87c7 100644
--- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java
+++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java
@@ -459,7 +459,7 @@ private boolean checkProhibitedValu
return true;
};
- originResolver.resolve(handler, prohibitedItemType.getOrigin(), shortDesc, task, result);
+ originResolver.resolve(handler, prohibitedItemType, shortDesc, task, result);
}
return isAcceptable.booleanValue();
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java
index 774432cd779..f74ead8a775 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java
@@ -1227,11 +1227,13 @@ public static LensContext fromLensContextType(LensContextType lensContextType, P
return lensContext;
}
- protected void fixProvisioningTypeInDelta(ObjectDelta delta, Task task, OperationResult result)
+ private void fixProvisioningTypeInDelta(ObjectDelta delta, Task task, OperationResult result)
throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
if (delta != null && delta.getObjectTypeClass() != null
&& (ShadowType.class.isAssignableFrom(delta.getObjectTypeClass())
|| ResourceType.class.isAssignableFrom(delta.getObjectTypeClass()))) {
+ // TODO exception can be thrown here (MID-4391) e.g. if resource does not exist any more; consider what to do
+ // Currently we are on the safe side by making whole conversion fail
getProvisioningService().applyDefinition(delta, task, result);
}
}
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java
index 25108bbe608..fe982b26761 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.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.
@@ -48,6 +48,7 @@
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
+import com.evolveum.midpoint.provisioning.api.ItemComparisonResult;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
@@ -78,6 +79,10 @@ public abstract class AbstractPasswordTest extends AbstractInitializedModelInteg
protected static final String USER_PASSWORD_VALID_2 = "abcd223";
protected static final String USER_PASSWORD_VALID_3 = "abcd323";
protected static final String USER_PASSWORD_VALID_4 = "abcd423";
+
+ protected static final String PASSWORD_ALLIGATOR = "all1g4t0r";
+ protected static final String PASSWORD_CROCODILE = "cr0c0d1l3";
+ protected static final String PASSWORD_GIANT_LIZARD = "G14NTl1z4rd";
public static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "password");
@@ -88,9 +93,20 @@ public abstract class AbstractPasswordTest extends AbstractInitializedModelInteg
protected static final File RESOURCE_DUMMY_LIFECYCLE_FILE = new File(TEST_DIR, "resource-dummy-lifecycle.xml");
protected static final String RESOURCE_DUMMY_LIFECYCLE_OID = "519f131a-147b-11e7-a270-c38e2b225751";
protected static final String RESOURCE_DUMMY_LIFECYCLE_NAME = "lifecycle";
+
+ protected static final File RESOURCE_DUMMY_SOUVENIR_FILE = new File(TEST_DIR, "resource-dummy-souvenir.xml");
+ protected static final String RESOURCE_DUMMY_SOUVENIR_OID = "f4fd7e90-ff6a-11e7-a504-4b84f92fec0e";
+ protected static final String RESOURCE_DUMMY_SOUVENIR_NAME = "souvenir";
+
+ protected static final File RESOURCE_DUMMY_MAVERICK_FILE = new File(TEST_DIR, "resource-dummy-maverick.xml");
+ protected static final String RESOURCE_DUMMY_MAVERICK_OID = "72a928b6-ff7b-11e7-9643-7366d7749c31";
+ protected static final String RESOURCE_DUMMY_MAVERICK_NAME = "maverick";
protected static final File PASSWORD_POLICY_UGLY_FILE = new File(TEST_DIR, "password-policy-ugly.xml");
protected static final String PASSWORD_POLICY_UGLY_OID = "cfb3fa9e-027a-11e7-8e2c-dbebaacaf4ee";
+
+ protected static final File PASSWORD_POLICY_MAVERICK_FILE = new File(TEST_DIR, "password-policy-maverick.xml");
+ protected static final String PASSWORD_POLICY_MAVERICK_OID = "b26d2bd4-ff83-11e7-94b3-8fa7a87aac6c";
protected static final File SECURITY_POLICY_DEFAULT_STORAGE_HASHING_FILE = new File(TEST_DIR, "security-policy-default-storage-hashing.xml");
protected static final String SECURITY_POLICY_DEFAULT_STORAGE_HASHING_OID = "0ea3b93c-0425-11e7-bbc1-73566dc53d59";
@@ -104,9 +120,12 @@ public abstract class AbstractPasswordTest extends AbstractInitializedModelInteg
protected String accountJackOid;
protected String accountJackRedOid;
+ protected String accountJackBlueOid;
protected String accountJackUglyOid;
protected String accountJackBlackOid;
protected String accountJackYellowOid;
+ protected String accountJackSouvenirOid;
+ protected String accountJackMaverickOid;
protected XMLGregorianCalendar lastPasswordChangeStart;
protected XMLGregorianCalendar lastPasswordChangeEnd;
@@ -116,6 +135,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
super.initSystem(initTask, initResult);
importObjectFromFile(PASSWORD_POLICY_UGLY_FILE);
+ importObjectFromFile(PASSWORD_POLICY_MAVERICK_FILE);
importObjectFromFile(SECURITY_POLICY_DEFAULT_STORAGE_HASHING_FILE);
importObjectFromFile(SECURITY_POLICY_PASSWORD_STORAGE_NONE_FILE);
@@ -123,6 +143,8 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
initDummyResourcePirate(RESOURCE_DUMMY_UGLY_NAME, RESOURCE_DUMMY_UGLY_FILE, RESOURCE_DUMMY_UGLY_OID, initTask, initResult);
initDummyResourcePirate(RESOURCE_DUMMY_LIFECYCLE_NAME, RESOURCE_DUMMY_LIFECYCLE_FILE, RESOURCE_DUMMY_LIFECYCLE_OID, initTask, initResult);
+ initDummyResourcePirate(RESOURCE_DUMMY_SOUVENIR_NAME, RESOURCE_DUMMY_SOUVENIR_FILE, RESOURCE_DUMMY_SOUVENIR_OID, initTask, initResult);
+ initDummyResourcePirate(RESOURCE_DUMMY_MAVERICK_NAME, RESOURCE_DUMMY_MAVERICK_FILE, RESOURCE_DUMMY_MAVERICK_OID, initTask, initResult);
login(USER_ADMINISTRATOR_USERNAME);
}
@@ -295,8 +317,8 @@ public void test070AddUserHerman() throws Exception {
}
@Test
- public void test100ModifyUserJackAssignAccount() throws Exception {
- final String TEST_NAME = "test100ModifyUserJackAssignAccount";
+ public void test100JackAssignAccountDummy() throws Exception {
+ final String TEST_NAME = "test100JackAssignAccountDummy";
displayTestTitle(TEST_NAME);
// GIVEN
@@ -482,8 +504,8 @@ public void test112ModifyJackPasswordUserAndAccount() throws Exception {
* Add red and ugly dummy resource to the mix. This would be fun.
*/
@Test
- public void test120ModifyUserJackAssignAccountDummyRedAndUgly() throws Exception {
- final String TEST_NAME = "test120ModifyUserJackAssignAccountDummyRedAndUgly";
+ public void test120JackAssignAccountDummyRedAndUgly() throws Exception {
+ final String TEST_NAME = "test120JackAssignAccountDummyRedAndUgly";
displayTestTitle(TEST_NAME);
// GIVEN
@@ -705,8 +727,8 @@ public void test128ModifyJackEmployeeNumberGood() throws Exception {
* Black resource has minimum password length constraint (enforced by midPoint).
*/
@Test
- public void test130ModifyUserJackAssignAccountDummyBlack() throws Exception {
- final String TEST_NAME = "test130ModifyUserJackAssignAccountDummyBlack";
+ public void test130JackAssignAccountDummyBlack() throws Exception {
+ final String TEST_NAME = "test130JackAssignAccountDummyBlack";
displayTestTitle(TEST_NAME);
// GIVEN
@@ -772,8 +794,8 @@ public void test132ModifyAccountBlackJackPasswordBad() throws Exception {
}
@Test
- public void test139ModifyUserJackUnassignAccountDummyBlack() throws Exception {
- final String TEST_NAME = "test139ModifyUserJackUnassignAccountDummyBlack";
+ public void test139JackUnassignAccountDummyBlack() throws Exception {
+ final String TEST_NAME = "test139JackUnassignAccountDummyBlack";
displayTestTitle(TEST_NAME);
// GIVEN
@@ -814,8 +836,8 @@ public void test139ModifyUserJackUnassignAccountDummyBlack() throws Exception {
* But this time the password is OK.
*/
@Test
- public void test140ModifyUserJackAssignAccountDummyYellow() throws Exception {
- final String TEST_NAME = "test140ModifyUserJackAssignAccountDummyYellow";
+ public void test140JackAssignAccountDummyYellow() throws Exception {
+ final String TEST_NAME = "test140JackAssignAccountDummyYellow";
displayTestTitle(TEST_NAME);
// GIVEN
@@ -911,8 +933,8 @@ public void test142ModifyUserJackPasswordAA() throws Exception {
}
@Test
- public void test200ApplyPasswordPolicy() throws Exception {
- final String TEST_NAME = "test200ApplyPasswordPolicy";
+ public void test200ApplyPasswordPolicyHistoryLength() throws Exception {
+ final String TEST_NAME = "test200ApplyPasswordPolicyHistoryLength";
displayTestTitle(TEST_NAME);
// GIVEN
@@ -1394,14 +1416,13 @@ public void test310PreparePasswordStrengthTests() throws Exception {
SystemConfigurationType.F_GLOBAL_PASSWORD_POLICY_REF, task, result);
// WHEN
- TestUtil.displayWhen(TEST_NAME);
+ displayWhen(TEST_NAME);
assignAccount(USER_JACK_OID, RESOURCE_DUMMY_RED_OID, null, task, result);
assignAccount(USER_JACK_OID, RESOURCE_DUMMY_BLUE_OID, null, task, result);
// THEN
- TestUtil.displayThen(TEST_NAME);
- result.computeStatus();
- TestUtil.assertSuccess(result);
+ displayThen(TEST_NAME);
+ assertSuccess(result);
PrismObject userAfter = getUser(USER_JACK_OID);
display("User after change execution", userAfter);
@@ -1976,20 +1997,15 @@ public void test404InitializeRappDummyRed() throws Exception {
display("User before", userBefore);
String accountRedOid = getLinkRefOid(userBefore, RESOURCE_DUMMY_RED_OID);
- ObjectDelta shadowDelta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountRedOid, prismContext);
- ProtectedStringType passwordPs = new ProtectedStringType();
- passwordPs.setClearValue(USER_PASSWORD_VALID_1);
- shadowDelta.addModificationReplaceProperty(SchemaConstants.PATH_PASSWORD_VALUE, passwordPs);
- shadowDelta.addModificationReplaceProperty(ObjectType.F_LIFECYCLE_STATE, SchemaConstants.LIFECYCLE_ACTIVE);
+ ObjectDelta shadowDelta = createAccountInitializationDelta(accountRedOid, USER_PASSWORD_VALID_1);
// WHEN
- TestUtil.displayWhen(TEST_NAME);
+ displayWhen(TEST_NAME);
executeChanges(shadowDelta, null, task, result);
// THEN
- TestUtil.displayThen(TEST_NAME);
- result.computeStatus();
- TestUtil.assertSuccess(result);
+ displayThen(TEST_NAME);
+ assertSuccess(result);
PrismObject userAfter = getUser(USER_RAPP_OID);
display("User after", userAfter);
@@ -2360,6 +2376,456 @@ public void test416UserRappEmployeeTypeWreck() throws Exception {
}
// TODO: employeeType->WRECK
+
+ /**
+ * MID-4397
+ */
+ @Test
+ public void test500JackAssignResourceSouvenir() throws Exception {
+ final String TEST_NAME = "test500JackAssignResourceSouvenir";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ // preconditions
+ PrismObject userBefore = getUser(USER_JACK_OID);
+ display("User before", userBefore);
+ assertAssignedAccount(userBefore, RESOURCE_DUMMY_OID);
+ assertAssignedAccount(userBefore, RESOURCE_DUMMY_RED_OID);
+ assertAssignedAccount(userBefore, RESOURCE_DUMMY_BLUE_OID);
+ assertAssignedAccount(userBefore, RESOURCE_DUMMY_UGLY_OID);
+ assertAssignments(userBefore, 4);
+ assertAccount(userBefore, RESOURCE_DUMMY_OID);
+ assertAccount(userBefore, RESOURCE_DUMMY_RED_OID);
+ accountJackBlueOid = assertAccount(userBefore, RESOURCE_DUMMY_BLUE_OID);
+ assertAccount(userBefore, RESOURCE_DUMMY_UGLY_OID);
+ assertLinks(userBefore, 4);
+ assertUserPassword(userBefore, USER_PASSWORD_VALID_3);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ assignAccount(USER_JACK_OID, RESOURCE_DUMMY_SOUVENIR_OID, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 5);
+ assertAssignedAccount(userAfter, RESOURCE_DUMMY_OID);
+ assertAssignedAccount(userAfter, RESOURCE_DUMMY_RED_OID);
+ assertAssignedAccount(userAfter, RESOURCE_DUMMY_BLUE_OID);
+ assertAssignedAccount(userAfter, RESOURCE_DUMMY_UGLY_OID);
+ assertAssignedAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID);
+ assertLinks(userAfter, 5);
+ assertAccount(userAfter, RESOURCE_DUMMY_OID);
+ assertAccount(userAfter, RESOURCE_DUMMY_RED_OID);
+ assertAccount(userAfter, RESOURCE_DUMMY_BLUE_OID);
+ assertAccount(userAfter, RESOURCE_DUMMY_UGLY_OID);
+ accountJackSouvenirOid = assertAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID);
+ assertUserPassword(userAfter, USER_PASSWORD_VALID_3);
+
+ PrismObject shadowPasswordCachingModel = getShadowModel(accountJackSouvenirOid);
+ assertShadowLifecycle(shadowPasswordCachingModel, false);
+
+ assertDummyPasswordConditional(RESOURCE_DUMMY_SOUVENIR_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3);
+
+ displayAllNotifications();
+ assertSinglePasswordNotificationConditional(RESOURCE_DUMMY_SOUVENIR_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3);
+ assertAccountActivationNotification(RESOURCE_DUMMY_SOUVENIR_NAME, USER_JACK_USERNAME);
+ }
+
+ /**
+ * MID-4397
+ */
+ @Test
+ public void test502JackInitializeAccountSouvenir() throws Exception {
+ final String TEST_NAME = "test502JackInitializeAccountSouvenir";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ ObjectDelta shadowDelta = createAccountInitializationDelta(accountJackSouvenirOid, PASSWORD_ALLIGATOR);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ executeChanges(shadowDelta, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 5);
+ assertLinks(userAfter, 5);
+ assertUserPassword(userAfter, USER_PASSWORD_VALID_3);
+
+ PrismObject shadowPasswordCachingRepo = getShadowRepo(accountJackSouvenirOid);
+ display("Shadow repo", shadowPasswordCachingRepo);
+ assertShadowLifecycle(shadowPasswordCachingRepo, SchemaConstants.LIFECYCLE_ACTIVE);
+ assertCachedResourcePassword(shadowPasswordCachingRepo, PASSWORD_ALLIGATOR);
+
+ assertDummyPassword(RESOURCE_DUMMY_SOUVENIR_NAME, ACCOUNT_JACK_DUMMY_USERNAME, PASSWORD_ALLIGATOR);
+
+ ItemComparisonResult comparisonResult = provisioningService.compare(ShadowType.class, accountJackSouvenirOid, SchemaConstants.PATH_PASSWORD_VALUE,
+ PASSWORD_ALLIGATOR, task, result);
+ assertEquals("Wrong comparison result", ItemComparisonResult.MATCH, comparisonResult);
+
+ // TODO
+// assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator);
+ }
+
+ /**
+ * MID-4397
+ */
+ @Test
+ public void test510JackAssignResourceMaverick() throws Exception {
+ final String TEST_NAME = "test510JackAssignResourceMaverick";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ // preconditions
+ PrismObject userBefore = getUser(USER_JACK_OID);
+ display("User before", userBefore);
+ assertAssignments(userBefore, 5);
+ assertLinks(userBefore, 5);
+ assertUserPassword(userBefore, USER_PASSWORD_VALID_3);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ assignAccount(USER_JACK_OID, RESOURCE_DUMMY_MAVERICK_OID, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 6);
+ assertLinks(userAfter, 6);
+ accountJackMaverickOid = assertAccount(userAfter, RESOURCE_DUMMY_MAVERICK_OID);
+ assertUserPassword(userAfter, USER_PASSWORD_VALID_3);
+
+ assertDummyPasswordConditional(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3);
+
+ displayAllNotifications();
+ assertSinglePasswordNotificationConditional(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3);
+ assertAccountActivationNotification(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME);
+ }
+
+ /**
+ * Attempt to initialize account with password which is the same as on the souvenir
+ * resource should fail. Maverick resource password policy states that the password
+ * must be different that the password on souvenir resource.
+ * MID-4397
+ */
+ @Test
+ public void test512JackInitializeAccountMaverickAlligator() throws Exception {
+ final String TEST_NAME = "test512JackInitializeAccountMaverick";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ ObjectDelta shadowDelta = createAccountInitializationDelta(accountJackMaverickOid, PASSWORD_ALLIGATOR);
+
+ try {
+ // WHEN
+ displayWhen(TEST_NAME);
+ executeChanges(shadowDelta, null, task, result);
+
+ assertNotReached();
+
+ } catch (PolicyViolationException e) {
+ display("Expected exception", e);
+ }
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertFailure(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 6);
+ assertLinks(userAfter, 6);
+ assertUserPassword(userAfter, USER_PASSWORD_VALID_3);
+
+ assertDummyPasswordConditional(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3);
+
+ // TODO
+// assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator);
+ }
+
+ /**
+ * Attempt to initialize account with a different password should pass.
+ * MID-4397
+ */
+ @Test
+ public void test514JackInitializeAccountMaverickCrododile() throws Exception {
+ final String TEST_NAME = "test514JackInitializeAccountMaverickCrododile";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ ObjectDelta shadowDelta = createAccountInitializationDelta(accountJackMaverickOid, PASSWORD_CROCODILE);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ executeChanges(shadowDelta, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 6);
+ assertLinks(userAfter, 6);
+ assertUserPassword(userAfter, USER_PASSWORD_VALID_3);
+
+ PrismObject shadowMaverickRepo = getShadowRepo(accountJackMaverickOid);
+ display("Shadow repo", shadowMaverickRepo);
+ assertShadowLifecycle(shadowMaverickRepo, SchemaConstants.LIFECYCLE_ACTIVE);
+
+ assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, PASSWORD_CROCODILE);
+
+ // TODO
+// assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator);
+ }
+
+ /**
+ * Attempt to change account password to a conflicting one. It should fail.
+ * MID-4397
+ */
+ @Test
+ public void test516JackChangePasswordResourceMaverickAlligator() throws Exception {
+ final String TEST_NAME = "test516JackChangePasswordResourceMaverickAlligator";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ try {
+ // WHEN
+ displayWhen(TEST_NAME);
+ modifyAccountChangePassword(accountJackMaverickOid, PASSWORD_ALLIGATOR, task, result);
+
+ assertNotReached();
+
+ } catch (PolicyViolationException e) {
+ display("Expected exception", e);
+ }
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertFailure(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 6);
+ assertLinks(userAfter, 6);
+
+ assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, PASSWORD_CROCODILE);
+ }
+
+ /**
+ * Attempt to change account password to non conflicting one. It should pass.
+ * MID-4397
+ */
+ @Test
+ public void test518JackChangePasswordResourceMaverickGiantLizard() throws Exception {
+ final String TEST_NAME = "test518JackChangePasswordResourceMaverickGiantLizard";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ modifyAccountChangePassword(accountJackMaverickOid, PASSWORD_GIANT_LIZARD, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 6);
+ assertLinks(userAfter, 6);
+
+ assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, PASSWORD_GIANT_LIZARD);
+ }
+
+ /**
+ * MID-4397
+ */
+ @Test
+ public void test530JackUnassignResourceSouvenir() throws Exception {
+ final String TEST_NAME = "test530JackUnassignResourceSouvenir";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ // preconditions
+ PrismObject userBefore = getUser(USER_JACK_OID);
+ display("User before", userBefore);
+ assertAssignments(userBefore, 6);
+ assertLinks(userBefore, 6);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_SOUVENIR_OID, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 5);
+ assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID);
+ assertLinks(userAfter, 5);
+ }
+
+ /**
+ * Make it harder for the next test (test535ModifyUserJackPasswordAlligator).
+ * We set conflicting password on blue resource. But the password policy
+ * should NOT check blue resource. So the check should pass anyway.
+ * MID-4397
+ */
+ @Test
+ public void test532JackChangePasswordResourceBlueAlligator() throws Exception {
+ final String TEST_NAME = "test532JackChangePasswordResourceBlueAlligator";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ PrismObject userBefore = getUser(USER_JACK_OID);
+ display("User before", userBefore);
+ assertAssignments(userBefore, 5);
+ assertLinks(userBefore, 5);
+ accountJackBlueOid = assertAccount(userBefore, RESOURCE_DUMMY_BLUE_OID);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ modifyAccountChangePassword(accountJackBlueOid, PASSWORD_ALLIGATOR, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 5);
+ assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID);
+ assertLinks(userAfter, 5);
+
+ assertDummyPassword(RESOURCE_DUMMY_BLUE_NAME, USER_JACK_USERNAME, PASSWORD_ALLIGATOR);
+ }
+
+ /**
+ * Additional check: check that the Alligator password would be otherwise legal for user and
+ * maverick resource. This is additional check that it was really the presence of souvenir
+ * resource that caused the policy violation.
+ * MID-4397
+ */
+ @Test
+ public void test535ModifyUserJackPasswordAlligator() throws Exception {
+ final String TEST_NAME = "test535ModifyUserJackPasswordAlligator";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ modifyUserChangePassword(USER_JACK_OID, PASSWORD_ALLIGATOR, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 5);
+ assertLinks(userAfter, 5);
+ assertUserPassword(userAfter, PASSWORD_ALLIGATOR);
+
+ assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, PASSWORD_ALLIGATOR);
+ }
+
+ /**
+ * MID-4397
+ */
+ @Test
+ public void test539JackUnassignResourceMaverick() throws Exception {
+ final String TEST_NAME = "test539JackUnassignResourceMaverick";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ Task task = createTask(TEST_NAME);
+ OperationResult result = task.getResult();
+ prepareTest();
+
+ // preconditions
+ PrismObject userBefore = getUser(USER_JACK_OID);
+ display("User before", userBefore);
+ assertAssignments(userBefore, 5);
+ assertLinks(userBefore, 5);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_MAVERICK_OID, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ assertSuccess(result);
+
+ PrismObject userAfter = getUser(USER_JACK_OID);
+ display("User after", userAfter);
+ assertAssignments(userAfter, 4);
+ assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_MAVERICK_OID);
+ assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID);
+ assertLinks(userAfter, 4);
+ }
+
+ protected ObjectDelta createAccountInitializationDelta(String accountOid, String newAccountPassword) {
+ ObjectDelta shadowDelta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountOid, prismContext);
+ ProtectedStringType passwordPs = new ProtectedStringType();
+ passwordPs.setClearValue(newAccountPassword);
+ shadowDelta.addModificationReplaceProperty(SchemaConstants.PATH_PASSWORD_VALUE, passwordPs);
+ shadowDelta.addModificationReplaceProperty(ObjectType.F_LIFECYCLE_STATE, SchemaConstants.LIFECYCLE_ACTIVE);
+ return shadowDelta;
+ }
protected void assertDummyPassword(String userId, String expectedClearPassword) throws SchemaViolationException, ConflictException {
assertDummyPassword(null, userId, expectedClearPassword);
@@ -2425,6 +2891,8 @@ private void assertShadowPasswordMetadata(PrismObject shadow,
}
assertShadowPasswordMetadata(shadow, passwordCreated, startCal, endCal, USER_ADMINISTRATOR_OID, SchemaConstants.CHANNEL_GUI_USER_URI);
}
+
+ // 9XX tests: Password minimal age, no password, etc.
/**
* Let's have a baseline for other 90x tests.
@@ -2617,5 +3085,21 @@ protected PrismObject getBlueShadow(PrismObject userAfter)
protected boolean isPasswordEncryption() {
return getPasswordStorageType() == CredentialsStorageTypeType.ENCRYPTION;
}
+
+ protected void assertCachedResourcePassword(PrismObject shadow, String expectedPassword) throws Exception {
+ CredentialsType credentials = shadow.asObjectable().getCredentials();
+ if (expectedPassword == null && credentials == null) {
+ return;
+ }
+ assertNotNull("Missing credentendials in repo shadow "+shadow, credentials);
+ PasswordType passwordType = credentials.getPassword();
+ if (expectedPassword == null && passwordType == null) {
+ return;
+ }
+ assertNotNull("Missing password credential in repo shadow "+shadow, passwordType);
+ ProtectedStringType protectedStringType = passwordType.getValue();
+ assertNotNull("No password value in repo shadow "+shadow, protectedStringType);
+ assertProtectedString("Wrong password value in repo shadow "+shadow, expectedPassword, protectedStringType, CredentialsStorageTypeType.HASHING);
+ }
}
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityAdvanced.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityAdvanced.java
index 7c7be28701f..27aff6de607 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityAdvanced.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityAdvanced.java
@@ -1839,6 +1839,94 @@ public void test260AutzJackLimitedRoleAdministrator() throws Exception {
display("Empty role with exclusion (2)", roleEmptyExclusion);
AssignmentType exclusionAssignment = assertExclusion(roleEmptyExclusion, ROLE_PIRATE_OID);
+ assertAllow("delete exclusion (2)",
+ (task, result) -> modifyRoleDeleteAssignment(ROLE_EMPTY_OID, createAssignmentIdOnly(exclusionAssignment.getId()), task, result));
+
+ // TODO: add exclusion with metadata (should be denied)
+
+ assertDeny("add minAssignee",
+ (task, result) -> modifyRolePolicyRule(ROLE_EMPTY_OID, createMinAssigneePolicyRule(1), true, task, result));
+
+ assertDeny("delete maxAssignee 10 (by value)",
+ (task, result) -> modifyRolePolicyRule(ROLE_MAXASSIGNEES_10_OID, createMaxAssigneePolicyRule(10), false, task, result));
+
+ assertDeny("delete maxAssignee 10 (by id)",
+ (task, result) -> modifyRoleDeleteAssignment(ROLE_MAXASSIGNEES_10_OID, createAssignmentIdOnly(10L), task, result));
+
+ assertDeny("assign role pirate to empty role",
+ (task, result) -> assignRole(RoleType.class, ROLE_EMPTY_OID, ROLE_PIRATE_OID, task, result));
+
+ roleEmptyExclusion = assertGetAllow(RoleType.class, ROLE_EMPTY_OID);
+ display("Empty role without exclusion", roleEmptyExclusion);
+ assertAssignments(roleEmptyExclusion, 0);
+
+ assertGlobalStateUntouched();
+ }
+
+ /**
+ * MID-4399
+ */
+ @Test
+ public void test262AutzJackLimitedRoleAdministratorAndAssignApplicationRoles() throws Exception {
+ final String TEST_NAME = "test260AutzJackLimitedRoleAdministrator";
+ displayTestTitle(TEST_NAME);
+ // GIVEN
+ cleanupAutzTest(USER_JACK_OID);
+ assignRole(USER_JACK_OID, ROLE_LIMITED_ROLE_ADMINISTRATOR_OID);
+ assignRole(USER_JACK_OID, ROLE_ASSIGN_APPLICATION_ROLES_OID);
+ login(USER_JACK_USERNAME);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+
+ assertReadAllow();
+ assertReadDenyRaw();
+ assertAddDeny();
+ assertDeleteDeny();
+
+ // check ROLE_ASSIGN_APPLICATION_ROLES_OID authorizations
+
+ assertAllow("assign application role to jack",
+ (task, result) -> assignRole(USER_JACK_OID, ROLE_APPLICATION_1_OID, task, result)
+ );
+
+ PrismObject user = getUser(USER_JACK_OID);
+ assertAssignments(user, 3);
+ assertAssignedRole(user, ROLE_APPLICATION_1_OID);
+
+ assertDeny("assign business role to jack",
+ (task, result) -> assignRole(USER_JACK_OID, ROLE_BUSINESS_1_OID, task, result));
+
+ assertAllow("unassign application role from jack",
+ (task, result) -> unassignRole(USER_JACK_OID, ROLE_APPLICATION_1_OID, task, result)
+ );
+
+ // check ROLE_LIMITED_ROLE_ADMINISTRATOR_OID authorizations
+
+ assertAddAllow(ROLE_EXCLUSION_PIRATE_FILE);
+
+ PrismObject roleExclusion = assertGetAllow(RoleType.class, ROLE_EXCLUSION_PIRATE_OID);
+ display("Exclusion role", roleExclusion);
+ assertExclusion(roleExclusion, ROLE_PIRATE_OID);
+// display("Exclusion role def", roleExclusion.getDefinition());
+
+ assertAllow("add exclusion (1)",
+ (task, result) -> modifyRoleAddExclusion(ROLE_EMPTY_OID, ROLE_PIRATE_OID, task, result));
+
+ PrismObject roleEmptyExclusion = assertGetAllow(RoleType.class, ROLE_EMPTY_OID);
+ display("Empty role with exclusion (1)", roleEmptyExclusion);
+ assertExclusion(roleEmptyExclusion, ROLE_PIRATE_OID);
+
+ assertAllow("delete exclusion (1)",
+ (task, result) -> modifyRoleDeleteExclusion(ROLE_EMPTY_OID, ROLE_PIRATE_OID, task, result));
+
+ assertAllow("add exclusion (2)",
+ (task, result) -> modifyRoleAddExclusion(ROLE_EMPTY_OID, ROLE_PIRATE_OID, task, result));
+
+ roleEmptyExclusion = assertGetAllow(RoleType.class, ROLE_EMPTY_OID);
+ display("Empty role with exclusion (2)", roleEmptyExclusion);
+ AssignmentType exclusionAssignment = assertExclusion(roleEmptyExclusion, ROLE_PIRATE_OID);
+
display("TTTA1");
assertAllow("delete exclusion (2)",
(task, result) -> modifyRoleDeleteAssignment(ROLE_EMPTY_OID, createAssignmentIdOnly(exclusionAssignment.getId()), task, result));
@@ -1864,7 +1952,7 @@ public void test260AutzJackLimitedRoleAdministrator() throws Exception {
assertGlobalStateUntouched();
}
-
+
@Test
public void test270AutzJackModifyPolicyException() throws Exception {
final String TEST_NAME = "test270AutzJackModifyPolicyException";
@@ -2084,4 +2172,19 @@ private void assertDeputySearchAssignmentTarget(String delegatorOid, String... e
assertSearch(UserType.class, query, expectedDeputyOids);
}
+
+ @Override
+ protected void cleanupAutzTest(String userOid) throws ObjectNotFoundException, SchemaException,
+ ExpressionEvaluationException, CommunicationException, ConfigurationException,
+ ObjectAlreadyExistsException, PolicyViolationException, SecurityViolationException, IOException {
+ super.cleanupAutzTest(userOid);
+
+ Task task = taskManager.createTaskInstance(TestSecurityAdvanced.class.getName() + ".cleanupAutzTest");
+ OperationResult result = task.getResult();
+
+ cleanupDelete(RoleType.class, ROLE_EXCLUSION_PIRATE_OID, task, result);
+ }
+
+
+
}
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java
index 859e35fa82c..9b44466866f 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/TestSecurityBasic.java
@@ -1956,8 +1956,9 @@ public void test275aAutzJackAssignRequestableRoles() throws Exception {
/**
* MID-3636 partially
+ * MID-4399
*/
- @Test(enabled=false)
+ @Test
public void test275bAutzJackAssignRequestableOrgs() throws Exception {
final String TEST_NAME = "test275bAutzJackAssignRequestableOrgs";
displayTestTitle(TEST_NAME);
@@ -1987,7 +1988,7 @@ public void test275bAutzJackAssignRequestableOrgs() throws Exception {
ObjectQuery query = new ObjectQuery();
query.addFilter(spec.getFilter());
- assertSearch(AbstractRoleType.class, query, 6); // set to 6 with requestable org
+ assertSearch(AbstractRoleType.class, query, 9);
assertAllow("unassign business role from jack",
(task, result) -> unassignOrg(USER_JACK_OID, ORG_REQUESTABLE_OID, task, result));
diff --git a/model/model-intest/src/test/resources/password/password-policy-maverick.xml b/model/model-intest/src/test/resources/password/password-policy-maverick.xml
new file mode 100644
index 00000000000..774cf12b7b4
--- /dev/null
+++ b/model/model-intest/src/test/resources/password/password-policy-maverick.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+ Password Policy for Maverick resource
+
+ Testing string policy
+
+ 1
+ 30
+ 2
+
+ Alphas
+ 1
+ false
+
+ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+
+
+
+ Numbers
+ 1
+ false
+
+ 1234567890
+
+
+
+
+
+ -
+ projection
+ credentials/password/value
+
+
+ account
+
+
+
+
\ No newline at end of file
diff --git a/model/model-intest/src/test/resources/password/resource-dummy-maverick.xml b/model/model-intest/src/test/resources/password/resource-dummy-maverick.xml
new file mode 100644
index 00000000000..bc097947581
--- /dev/null
+++ b/model/model-intest/src/test/resources/password/resource-dummy-maverick.xml
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
+ Dummy Resource: Maverick
+
+
+
+
+ connectorType
+ com.evolveum.icf.dummy.connector.DummyConnector
+
+
+ connectorVersion
+ 2.0
+
+
+
+
+
+
+
+ maverick
+ true
+
+ whatever
+
+ USEless
+
+
+
+ false
+ false
+ false
+
+
+
+
+ http://midpoint.evolveum.com/xml/ns/public/resource/instance/10000000-0000-0000-0000-000000000004
+
+
+
+ account
+ default
+ Default Account
+ true
+ ri:AccountObjectClass
+
+ [icfs:name]
+ Username
+
+ strong
+
+
+
+
+
+
+
+ [ri:fullname]
+ Full Name
+
+
+
+
+
+ [ri:title]
+ true
+
+
+ [ri:location]
+ Location
+
+ strong
+
+
+
+
+ [ri:ship]
+ Ship
+
+
+ [ri:loot]
+ Loot
+ explicit
+
+ http://pirates.net/avast
+
+
+
+
+
+
+ [ri:weapon]
+ Weapon
+
+ weak
+
+
+
+
+ [ri:drink]
+ Drink
+ false
+
+ strong
+
+ rum
+
+
+
+
+ [ri:quote]
+ Quote
+ true
+
+ strong
+
+ Arr!
+
+
+
+
+ [ri:wealth]
+ Wealth
+ false
+
+
+ [ri:gossip]
+ Gossip
+ true
+
+
+ [ri:water]
+
+ true
+
+
+
+
+ daviejones
+
+
+ calypso
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ ri:AccountObjectClass
+ account
+ default
+ true
+
+
+ name
+
+ declare namespace icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3";
+ $account/attributes/icfs:name
+
+
+
+
+ linked
+ true
+
+
+ deleted
+ true
+
+ http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink
+
+
+
+ unlinked
+ true
+
+ http://midpoint.evolveum.com/xml/ns/public/model/action-3#link
+
+
+
+ unmatched
+ true
+
+ http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus
+
+
+
+
+
+
+
diff --git a/model/model-intest/src/test/resources/password/resource-dummy-souvenir.xml b/model/model-intest/src/test/resources/password/resource-dummy-souvenir.xml
new file mode 100644
index 00000000000..0b9a2e013d5
--- /dev/null
+++ b/model/model-intest/src/test/resources/password/resource-dummy-souvenir.xml
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+ Dummy Resource: Souvenir
+
+
+
+
+ connectorType
+ com.evolveum.icf.dummy.connector.DummyConnector
+
+
+ connectorVersion
+ 2.0
+
+
+
+
+
+
+
+ souvenir
+ true
+
+ whatever
+
+ USEless
+ true
+
+
+
+ false
+ false
+ false
+
+
+
+
+ http://midpoint.evolveum.com/xml/ns/public/resource/instance/10000000-0000-0000-0000-000000000004
+
+
+
+ account
+ default
+ Default Account
+ true
+ ri:AccountObjectClass
+
+ [icfs:name]
+ Username
+
+ strong
+
+
+
+
+
+
+
+ [ri:fullname]
+ Full Name
+
+
+
+
+
+ [ri:title]
+ true
+
+
+ [ri:location]
+ Location
+
+ strong
+
+
+
+
+ [ri:ship]
+ Ship
+
+
+ [ri:loot]
+ Loot
+ explicit
+
+ http://pirates.net/avast
+
+
+
+
+
+
+ [ri:weapon]
+ Weapon
+
+ weak
+
+
+
+
+ [ri:drink]
+ Drink
+ false
+
+ strong
+
+ rum
+
+
+
+
+ [ri:quote]
+ Quote
+ true
+
+ strong
+
+ Arr!
+
+
+
+
+ [ri:wealth]
+ Wealth
+ false
+
+
+ [ri:gossip]
+ Gossip
+ true
+
+
+ [ri:water]
+
+ true
+
+
+
+
+ daviejones
+
+
+ calypso
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cached
+
+
+
+
+
+
+ passive
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ ri:AccountObjectClass
+ account
+ default
+ true
+
+
+ name
+
+ declare namespace icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3";
+ $account/attributes/icfs:name
+
+
+
+
+ linked
+ true
+
+
+ deleted
+ true
+
+ http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink
+
+
+
+ unlinked
+ true
+
+ http://midpoint.evolveum.com/xml/ns/public/model/action-3#link
+
+
+
+ unmatched
+ true
+
+ http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus
+
+
+
+
+
+
+
diff --git a/model/model-intest/src/test/resources/security/role-modify-user.xml b/model/model-intest/src/test/resources/security/role-modify-user.xml
index e863315b762..6bdee385d2c 100644
--- a/model/model-intest/src/test/resources/security/role-modify-user.xml
+++ b/model/model-intest/src/test/resources/security/role-modify-user.xml
@@ -1,6 +1,6 @@
http://midpoint.evolveum.com/xml/ns/public/security/authorization-3#users
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java
index afca93fedbd..0a8591beb70 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java
@@ -584,6 +584,9 @@ public String addShadow(PrismObject shadowToAdd, OperationProvisioni
accessChecker.checkAdd(ctx, shadowToAdd, parentResult);
if (shouldExecuteResourceOperationDirectly(ctx)) {
+
+ LOGGER.trace("ADD {}: resource operation, execution starting", shadowToAdd);
+
try {
// RESOURCE OPERATION: add
@@ -603,7 +606,7 @@ public String addShadow(PrismObject shadowToAdd, OperationProvisioni
return addedShadow.getOid();
}
- LOGGER.debug("Resource operation executed (ADD {}), operation state: {}", shadowToAdd, opState.shortDumpLazily());
+ LOGGER.debug("ADD {}: resource operation executed, operation state: {}", shadowToAdd, opState.shortDumpLazily());
} else {
opState.setExecutionStatus(PendingOperationExecutionStatusType.EXECUTION_PENDING);
@@ -611,7 +614,7 @@ public String addShadow(PrismObject shadowToAdd, OperationProvisioni
// This will force the entire result (parent) to be IN_PROGRESS rather than SUCCESS.
OperationResult delayedSubresult = parentResult.createSubresult(OP_DELAYED_OPERATION);
delayedSubresult.setStatus(OperationResultStatus.IN_PROGRESS);
- LOGGER.debug("Resource operation NOT executed, execution pending (ADD {})", shadowToAdd);
+ LOGGER.debug("ADD {}: resource operation NOT executed, execution pending", shadowToAdd);
}
// REPO OPERATION: add
@@ -642,7 +645,7 @@ private ProvisioningOperationState> asyncReturnValue = resouceObjectConverter.addResourceObject(ctx, shadowToAdd, scripts, parentResult);
opState.processAsyncResult(asyncReturnValue);
- LOGGER.debug("Resource operation executed (ADD {}), operation state: {}", shadowToAdd, opState.shortDumpLazily());
+ LOGGER.debug("ADD {}: resource operation executed, operation state: {}", shadowToAdd, opState.shortDumpLazily());
return opState;
} catch (Exception ex) {
@@ -798,16 +801,16 @@ public String modifyShadow(PrismObject repoShadow,
if (shadowManager.isRepositoryOnlyModification(modifications)) {
opState.setExecutionStatus(PendingOperationExecutionStatusType.COMPLETED);
- LOGGER.debug("Repository-only modification (MODIFY {})", repoShadow);
+ LOGGER.debug("MODIFY {}: repository-only modification", repoShadow);
} else {
if (shouldExecuteResourceOperationDirectly(ctx)) {
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("MODIFY {}: resource modification, execution starting\n{}", repoShadow, DebugUtil.debugDump(modifications));
+ }
+
try {
-
- if (LOGGER.isTraceEnabled()) {
- LOGGER.trace("Applying change: {}", DebugUtil.debugDump(modifications));
- }
-
+
AsynchronousOperationReturnValue>> asyncReturnValue =
resouceObjectConverter.modifyResourceObject(ctx, repoShadow, scripts, modifications, parentResult);
opState.processAsyncResult(asyncReturnValue);
@@ -835,13 +838,15 @@ public String modifyShadow(PrismObject repoShadow,
return repoShadow.getOid();
}
+ LOGGER.debug("MODIFY {}: resource operation executed, operation state: {}", repoShadow, opState.shortDumpLazily());
+
} else {
opState.setExecutionStatus(PendingOperationExecutionStatusType.EXECUTION_PENDING);
// Create dummy subresult with IN_PROGRESS state.
// This will force the entire result (parent) to be IN_PROGRESS rather than SUCCESS.
OperationResult delayedSubresult = parentResult.createSubresult(OP_DELAYED_OPERATION);
delayedSubresult.setStatus(OperationResultStatus.IN_PROGRESS);
- LOGGER.debug("Resource operation NOT executed, execution pending (MODIFY {})", repoShadow);
+ LOGGER.debug("MODIFY {}: Resource operation NOT executed, execution pending", repoShadow);
}
}
@@ -982,6 +987,9 @@ public void deleteShadow(PrismObject shadow, ProvisioningOperationOp
if (shadow.asObjectable().getFailedOperationType() == null
|| (shadow.asObjectable().getFailedOperationType() != null
&& FailedOperationTypeType.ADD != shadow.asObjectable().getFailedOperationType())) {
+
+ LOGGER.trace("DELETE {}: resource deletion, execution starting", shadow);
+
try {
AsynchronousOperationResult asyncReturnValue = resouceObjectConverter.deleteResourceObject(ctx, shadow, scripts, parentResult);
@@ -997,6 +1005,11 @@ public void deleteShadow(PrismObject shadow, ProvisioningOperationOp
}
return;
}
+
+ LOGGER.debug("DELETE {}: resource operation executed, operation state: {}", shadow, opState.shortDumpLazily());
+
+ } else {
+ LOGGER.trace("DELETE {}: resource deletion skipped (failed ADD operation)", shadow);
}
} else {
@@ -1005,7 +1018,7 @@ public void deleteShadow(PrismObject shadow, ProvisioningOperationOp
// This will force the entire result (parent) to be IN_PROGRESS rather than SUCCESS.
OperationResult delayedSubresult = parentResult.createSubresult(OP_DELAYED_OPERATION);
delayedSubresult.setStatus(OperationResultStatus.IN_PROGRESS);
- LOGGER.debug("Resource operation NOT executed, execution pending (DELETE {})", shadow);
+ LOGGER.debug("DELETE {}: resource operation NOT executed, execution pending", shadow);
}
LOGGER.trace("Deting object with oid {} form repository.", shadow.getOid());
diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java
index 9c93d244238..e5b2bc09dde 100644
--- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java
+++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyCaching.java
@@ -186,15 +186,13 @@ public void test107BGetModifiedAccountFromCacheHighStaleness() throws Exception
XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar();
// WHEN
- TestUtil.displayWhen(TEST_NAME);
+ displayWhen(TEST_NAME);
PrismObject shadow = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, options, null, result);
// THEN
- TestUtil.displayThen(TEST_NAME);
- result.computeStatus();
- display("getObject result", result);
- TestUtil.assertSuccess(result);
+ displayThen(TEST_NAME);
+ assertSuccess(result);
assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0);
diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java
index 1409c91b0a2..81150fa2f26 100644
--- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java
+++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java
@@ -2293,4 +2293,11 @@ protected ObjectDelta createAccountPaswordDelta(String shadowOid, St
userPasswordPs.setClearValue(newPassword);
return ObjectDelta.createModificationReplaceProperty(ShadowType.class, shadowOid, SchemaConstants.PATH_PASSWORD_VALUE, prismContext, userPasswordPs);
}
+
+ protected PrismObject getShadowRepo(String shadowOid) throws ObjectNotFoundException, SchemaException {
+ OperationResult result = new OperationResult("getShadowRepo");
+ PrismObject shadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result);
+ assertSuccess(result);
+ return shadow;
+ }
}