/* * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.testing.sanity; import static com.evolveum.midpoint.prism.util.PrismAsserts.assertEqualsPolyString; import static com.evolveum.midpoint.prism.util.PrismAsserts.assertParentConsistency; import static com.evolveum.midpoint.test.IntegrationTestTools.assertAttribute; import static com.evolveum.midpoint.test.IntegrationTestTools.assertAttributeNotNull; import static com.evolveum.midpoint.test.IntegrationTestTools.assertNoRepoCache; import static com.evolveum.midpoint.test.IntegrationTestTools.assertNotEmpty; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static com.evolveum.midpoint.test.IntegrationTestTools.displayJaxb; import static com.evolveum.midpoint.test.IntegrationTestTools.getAttributeValue; import static com.evolveum.midpoint.test.IntegrationTestTools.getAttributeValues; import static com.evolveum.midpoint.test.IntegrationTestTools.waitFor; import static com.evolveum.midpoint.test.util.TestUtil.assertSuccess; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import javax.xml.ws.Holder; import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.task.api.TaskManagerException; import com.evolveum.midpoint.util.exception.*; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.opends.server.core.ModifyOperation; import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.types.*; import org.opends.server.types.ModificationType; import org.opends.server.util.ChangeRecordEntry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; import com.evolveum.midpoint.model.test.AbstractModelIntegrationTest; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.match.MatchingRule; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; import com.evolveum.midpoint.prism.marshaller.XNodeProcessorUtil; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xnode.MapXNode; import com.evolveum.midpoint.prism.xnode.PrimitiveXNode; import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.schema.CapabilityUtil; import com.evolveum.midpoint.schema.DeltaConvertor; import com.evolveum.midpoint.schema.ResultHandler; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; import com.evolveum.midpoint.schema.processor.ResourceSchema; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.schema.util.SchemaDebugUtil; import com.evolveum.midpoint.schema.util.SchemaTestConstants; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.test.Checker; import com.evolveum.midpoint.test.IntegrationTestTools; import com.evolveum.midpoint.test.ObjectChecker; import com.evolveum.midpoint.test.ldap.OpenDJController; import com.evolveum.midpoint.test.util.DerbyController; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.JAXBUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaOperationListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PropertyReferenceListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.SelectorQualifiedGetOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilityCollectionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; import com.evolveum.midpoint.xml.ns._public.common.common_3.GenericObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ModelExecuteOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectDeltaOperationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ProjectionPolicyType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectShadowChangeDescriptionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectTypeDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SchemaHandlingType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultType; import com.evolveum.midpoint.xml.ns._public.common.fault_3.ObjectAlreadyExistsFaultType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CredentialsCapabilityType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; import com.evolveum.prism.xml.ns._public.types_3.EncryptedDataType; import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import com.evolveum.prism.xml.ns._public.types_3.RawType; /** * Sanity test suite. * <p/> * It tests the very basic representative test cases. It does not try to be * complete. It rather should be quick to execute and pass through the most * representative cases. It should test all the system components except for * GUI. Therefore the test cases are selected to pass through most of the * components. * <p/> * It is using embedded H2 repository and embedded OpenDJ instance as a testing * resource. The repository is instantiated from the Spring context in the * same way as all other components. OpenDJ instance is started explicitly using * BeforeClass method. Appropriate resource definition to reach the OpenDJ * instance is provided in the test data and is inserted in the repository as * part of test initialization. * * @author Radovan Semancik */ @ContextConfiguration(locations = {"classpath:ctx-sanity-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class TestSanity extends AbstractModelIntegrationTest { private static final String REPO_DIR_NAME = "src/test/resources/repo/"; private static final String REQUEST_DIR_NAME = "src/test/resources/request/"; private static final File REQUEST_DIR = new File(REQUEST_DIR_NAME); private static final String SYSTEM_CONFIGURATION_FILENAME = REPO_DIR_NAME + "system-configuration.xml"; private static final String SYSTEM_CONFIGURATION_OID = "00000000-0000-0000-0000-000000000001"; private static final String ROLE_SUPERUSER_FILENAME = REPO_DIR_NAME + "role-superuser.xml"; private static final String ROLE_SUPERUSER_OID = "00000000-0000-0000-0000-000000000004"; private static final String RESOURCE_OPENDJ_FILENAME = REPO_DIR_NAME + "resource-opendj.xml"; private static final String RESOURCE_OPENDJ_OID = "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; private static final String RESOURCE_OPENDJ_NS = "http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; protected static final QName RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS = new QName(RESOURCE_OPENDJ_NS,"inetOrgPerson"); private static final String RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME = "entryUUID"; private static final String RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME = "dn"; private static final String RESOURCE_DERBY_FILENAME = REPO_DIR_NAME + "resource-derby.xml"; private static final String RESOURCE_DERBY_OID = "ef2bc95b-76e0-59e2-86d6-999902d3abab"; private static final String RESOURCE_BROKEN_FILENAME = REPO_DIR_NAME + "resource-broken.xml"; private static final String RESOURCE_BROKEN_OID = "ef2bc95b-76e0-59e2-ffff-ffffffffffff"; private static final String RESOURCE_DUMMY_FILENAME = REPO_DIR_NAME + "resource-dummy.xml"; private static final String RESOURCE_DUMMY_OID = "10000000-0000-0000-0000-000000000004"; private static final String CONNECTOR_LDAP_NAMESPACE = "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.LdapConnector"; private static final String CONNECTOR_DBTABLE_NAMESPACE = "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-databasetable/org.identityconnectors.databasetable.DatabaseTableConnector"; private static final String CONNECTOR_BROKEN_FILENAME = REPO_DIR_NAME + "connector-broken.xml"; private static final String CONNECTOR_BROKEN_OID = "cccccccc-76e0-59e2-ffff-ffffffffffff"; private static final String TASK_OPENDJ_SYNC_FILENAME = REPO_DIR_NAME + "task-opendj-sync.xml"; private static final String TASK_OPENDJ_SYNC_OID = "91919191-76e0-59e2-86d6-3d4f02d3ffff"; private static final String TASK_USER_RECOMPUTE_FILENAME = REPO_DIR_NAME + "task-user-recompute.xml"; private static final String TASK_USER_RECOMPUTE_OID = "91919191-76e0-59e2-86d6-3d4f02d3aaaa"; private static final String TASK_OPENDJ_RECON_FILENAME = REPO_DIR_NAME + "task-opendj-reconciliation.xml"; private static final String TASK_OPENDJ_RECON_OID = "91919191-76e0-59e2-86d6-3d4f02d30000"; private static final String SAMPLE_CONFIGURATION_OBJECT_FILENAME = REPO_DIR_NAME + "sample-configuration-object.xml"; private static final String SAMPLE_CONFIGURATION_OBJECT_OID = "c0c010c0-d34d-b33f-f00d-999111111111"; private static final String USER_TEMPLATE_FILENAME = REPO_DIR_NAME + "user-template.xml"; private static final String USER_TEMPLATE_OID = "c0c010c0-d34d-b33f-f00d-777111111111"; private static final String USER_ADMINISTRATOR_FILENAME = REPO_DIR_NAME + "user-administrator.xml"; private static final String USER_ADMINISTRATOR_NAME = "administrator"; private static final String USER_ADMINISTRATOR_OID = "00000000-0000-0000-0000-000000000002"; private static final String USER_JACK_FILENAME = REPO_DIR_NAME + "user-jack.xml"; private static final File USER_JACK_FILE = new File(USER_JACK_FILENAME); private static final String USER_JACK_OID = "c0c010c0-d34d-b33f-f00d-111111111111"; private static final String USER_JACK_LDAP_UID = "jack"; private static final String USER_JACK_LDAP_DN = "uid=" + USER_JACK_LDAP_UID + "," + OPENDJ_PEOPLE_SUFFIX; private static final String USER_GUYBRUSH_FILENAME = REPO_DIR_NAME + "user-guybrush.xml"; private static final File USER_GUYBRUSH_FILE = new File(USER_GUYBRUSH_FILENAME); private static final String USER_GUYBRUSH_OID = "c0c010c0-d34d-b33f-f00d-111111111222"; private static final String USER_GUYBRUSH_USERNAME = "guybrush"; private static final String USER_GUYBRUSH_LDAP_UID = "guybrush"; private static final String USER_GUYBRUSH_LDAP_DN = "uid=" + USER_GUYBRUSH_LDAP_UID + "," + OPENDJ_PEOPLE_SUFFIX; private static final String USER_E_LINK_ACTION_FILENAME = REPO_DIR_NAME + "user-e.xml"; private static final File USER_E_LINK_ACTION_FILE = new File(USER_E_LINK_ACTION_FILENAME); private static final String LDIF_E_FILENAME_LINK = "src/test/resources/request/e-create.ldif"; private static final String ROLE_PIRATE_FILENAME = REPO_DIR_NAME + "role-pirate.xml"; private static final String ROLE_PIRATE_OID = "12345678-d34d-b33f-f00d-987987987988"; private static final String ROLE_SAILOR_FILENAME = REPO_DIR_NAME + "role-sailor.xml"; private static final String ROLE_SAILOR_OID = "12345678-d34d-b33f-f00d-987955553535"; private static final String ROLE_CAPTAIN_FILENAME = REPO_DIR_NAME + "role-captain.xml"; private static final String ROLE_CAPTAIN_OID = "12345678-d34d-b33f-f00d-987987cccccc"; private static final String ROLE_JUDGE_FILENAME = REPO_DIR_NAME + "role-judge.xml"; private static final String ROLE_JUDGE_OID = "12345111-1111-2222-1111-121212111111"; private static final String REQUEST_USER_MODIFY_ADD_ACCOUNT_OPENDJ_FILENAME = REQUEST_DIR_NAME + "user-modify-add-account.xml"; private static final String REQUEST_USER_MODIFY_ADD_ACCOUNT_DERBY_FILENAME = REQUEST_DIR_NAME + "user-modify-add-account-derby.xml"; private static final String USER_JACK_DERBY_LOGIN = "jsparrow"; private static final String REQUEST_USER_MODIFY_FULLNAME_LOCALITY_FILENAME = REQUEST_DIR_NAME + "user-modify-fullname-locality.xml"; private static final String REQUEST_USER_MODIFY_GIVENNAME_FILENAME = REQUEST_DIR_NAME + "user-modify-givenname.xml"; private static final String REQUEST_USER_MODIFY_PASSWORD_FILENAME = REQUEST_DIR_NAME + "user-modify-password.xml"; private static final String REQUEST_USER_MODIFY_ACTIVATION_DISABLE_FILENAME = REQUEST_DIR_NAME + "user-modify-activation-disable.xml"; private static final String REQUEST_USER_MODIFY_ACTIVATION_ENABLE_FILENAME = REQUEST_DIR_NAME + "user-modify-activation-enable.xml"; private static final String REQUEST_USER_MODIFY_NAME_FILENAME = REQUEST_DIR_NAME + "user-modify-name.xml"; private static final String REQUEST_USER_MODIFY_ADD_ROLE_PIRATE_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-pirate.xml"; private static final String REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_1_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-captain-1.xml"; private static final String REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_2_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-captain-2.xml"; private static final String REQUEST_USER_MODIFY_ADD_ROLE_JUDGE_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-judge.xml"; private static final String REQUEST_USER_MODIFY_DELETE_ROLE_PIRATE_FILENAME = REQUEST_DIR_NAME + "user-modify-delete-role-pirate.xml"; private static final String REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_1_FILENAME = REQUEST_DIR_NAME + "user-modify-delete-role-captain-1.xml"; private static final String REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_2_FILENAME = REQUEST_DIR_NAME + "user-modify-delete-role-captain-2.xml"; private static final File REQUEST_ACCOUNT_MODIFY_ATTRS_FILE = new File(REQUEST_DIR, "account-modify-attrs.xml"); private static final File REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_FILE = new File(REQUEST_DIR, "account-modify-roomnumber.xml"); private static final File REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_EXPLICIT_TYPE_FILE = new File(REQUEST_DIR, "account-modify-roomnumber-explicit-type.xml"); private static final File REQUEST_ACCOUNT_MODIFY_BAD_PATH_FILE = new File(REQUEST_DIR, "account-modify-bad-path.xml"); private static final String LDIF_WILL_FILENAME = REQUEST_DIR_NAME + "will.ldif"; private static final File LDIF_WILL_MODIFY_FILE = new File (REQUEST_DIR_NAME, "will-modify.ldif"); private static final String LDIF_WILL_WITHOUT_LOCATION_FILENAME = REQUEST_DIR_NAME + "will-without-location.ldif"; private static final String WILL_NAME = "wturner"; private static final String LDIF_ANGELIKA_FILENAME = REQUEST_DIR_NAME + "angelika.ldif"; private static final String ANGELIKA_NAME = "angelika"; private static final String ACCOUNT_ANGELIKA_FILENAME = REQUEST_DIR_NAME + "account-angelika.xml"; private static final String LDIF_ELAINE_FILENAME = REQUEST_DIR_NAME + "elaine.ldif"; private static final String ELAINE_NAME = "elaine"; private static final File LDIF_GIBBS_MODIFY_FILE = new File (REQUEST_DIR_NAME, "gibbs-modify.ldif"); private static final String LDIF_HERMAN_FILENAME = REQUEST_DIR_NAME + "herman.ldif"; private static final Trace LOGGER = TraceManager.getTrace(TestSanity.class); private static final String NS_MY = "http://whatever.com/my"; private static final QName MY_SHIP_STATE = new QName(NS_MY, "shipState"); private static final QName MY_DEAD = new QName(NS_MY, "dead"); private static final long WAIT_FOR_LOOP_SLEEP_MILIS = 1000; /** * Unmarshalled resource definition to reach the embedded OpenDJ instance. * Used for convenience - the tests method may find it handy. */ private static ResourceType resourceTypeOpenDjrepo; private static ResourceType resourceDerby; private static String accountShadowOidOpendj; private static String accountShadowOidDerby; private static String accountShadowOidGuybrushOpendj; private static String accountGuybrushOpendjEntryUuuid = null; private static String originalJacksLdapPassword; private static String lastJacksLdapPassword = null; private int lastSyncToken; @Autowired(required = true) private MatchingRuleRegistry matchingRuleRegistry; // This will get called from the superclass to init the repository // It will be called only once public void initSystem(Task initTask, OperationResult initResult) throws Exception { LOGGER.trace("initSystem"); try{ super.initSystem(initTask, initResult); repoAddObjectFromFile(ROLE_SUPERUSER_FILENAME, initResult); repoAddObjectFromFile(USER_ADMINISTRATOR_FILENAME, initResult); // This should discover the connectors LOGGER.trace("initSystem: trying modelService.postInit()"); modelService.postInit(initResult); LOGGER.trace("initSystem: modelService.postInit() done"); login(USER_ADMINISTRATOR_NAME); // We need to add config after calling postInit() so it will not be applied. // we want original logging configuration from the test logback config file, not // the one from the system config. repoAddObjectFromFile(SYSTEM_CONFIGURATION_FILENAME, initResult); // Add broken connector before importing resources repoAddObjectFromFile(CONNECTOR_BROKEN_FILENAME, initResult); // Need to import instead of add, so the (dynamic) connector reference // will be resolved // correctly importObjectFromFile(RESOURCE_OPENDJ_FILENAME, initResult); importObjectFromFile(RESOURCE_BROKEN_FILENAME, initResult); repoAddObjectFromFile(SAMPLE_CONFIGURATION_OBJECT_FILENAME, initResult); repoAddObjectFromFile(USER_TEMPLATE_FILENAME, initResult); repoAddObjectFromFile(ROLE_SAILOR_FILENAME, initResult); repoAddObjectFromFile(ROLE_PIRATE_FILENAME, initResult); repoAddObjectFromFile(ROLE_CAPTAIN_FILENAME, initResult); repoAddObjectFromFile(ROLE_JUDGE_FILENAME, initResult); } catch (Exception ex){ LOGGER.error("erro: {}", ex); throw ex; } } /** * Initialize embedded OpenDJ instance Note: this is not in the abstract * superclass so individual tests may avoid starting OpenDJ. */ @Override public void startResources() throws Exception { openDJController.startCleanServer(); derbyController.startCleanServer(); } /** * Shutdown embedded OpenDJ instance Note: this is not in the abstract * superclass so individual tests may avoid starting OpenDJ. */ @AfterClass public static void stopResources() throws Exception { openDJController.stop(); derbyController.stop(); } /** * Test integrity of the test setup. * * @throws SchemaException * @throws ObjectNotFoundException * @throws CommunicationException */ @Test public void test000Integrity() throws Exception { final String TEST_NAME = "test000Integrity"; TestUtil.displayTestTile(this, TEST_NAME); assertNotNull(modelWeb); assertNotNull(modelService); assertNotNull(repositoryService); assertTrue(isSystemInitialized()); assertNotNull(taskManager); assertNotNull(prismContext); SchemaRegistry schemaRegistry = prismContext.getSchemaRegistry(); assertNotNull(schemaRegistry); // This is defined in extra schema. So this effectively checks whether the extra schema was loaded PrismPropertyDefinition shipStateDefinition = schemaRegistry.findPropertyDefinitionByElementName(MY_SHIP_STATE); assertNotNull("No my:shipState definition", shipStateDefinition); assertEquals("Wrong maxOccurs in my:shipState definition", 1, shipStateDefinition.getMaxOccurs()); assertNoRepoCache(); Task task = taskManager.createTaskInstance(TestSanity.class.getName() + ".test000Integrity"); OperationResult result = task.getResult(); // Check if OpenDJ resource was imported correctly PrismObject<ResourceType> openDjResource = repositoryService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, result); display("Imported OpenDJ resource (repository)", openDjResource); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, openDjResource.getOid()); assertNoRepoCache(); String ldapConnectorOid = openDjResource.asObjectable().getConnectorRef().getOid(); PrismObject<ConnectorType> ldapConnector = repositoryService.getObject(ConnectorType.class, ldapConnectorOid, null, result); display("LDAP Connector: ", ldapConnector); // TODO: test if OpenDJ and Derby are running repositoryService.getObject(GenericObjectType.class, SAMPLE_CONFIGURATION_OBJECT_OID, null, result); } /** * Repeat self-test when we have all the dependencies on the classpath. */ @Test public void test001SelfTests() throws Exception { final String TEST_NAME = "test001SelfTests"; TestUtil.displayTestTile(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSanity.class.getName()+"."+TEST_NAME); // WHEN OperationResult repositorySelfTestResult = modelDiagnosticService.repositorySelfTest(task); // THEN assertSuccess("Repository self test", repositorySelfTestResult); // WHEN OperationResult provisioningSelfTestResult = modelDiagnosticService.provisioningSelfTest(task); // THEN display("Repository self test result", provisioningSelfTestResult); // There may be warning about illegal key size on some platforms. As far as it is warning and not error we are OK // the system will fall back to a interoperable key size if (provisioningSelfTestResult.getStatus() != OperationResultStatus.SUCCESS && provisioningSelfTestResult.getStatus() != OperationResultStatus.WARNING) { AssertJUnit.fail("Provisioning self-test failed: "+provisioningSelfTestResult); } } /** * Test the testResource method. Expect a complete success for now. */ @Test public void test001TestConnectionOpenDJ() throws Exception { final String TEST_NAME = "test001TestConnectionOpenDJ"; TestUtil.displayTestTile(TEST_NAME); // GIVEN try{ assertNoRepoCache(); // WHEN OperationResultType result = modelWeb.testResource(RESOURCE_OPENDJ_OID); // THEN assertNoRepoCache(); displayJaxb("testResource result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("testResource has failed", result); OperationResult opResult = new OperationResult(TestSanity.class.getName() + ".test001TestConnectionOpenDJ"); PrismObject<ResourceType> resourceOpenDjRepo = repositoryService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, opResult); resourceTypeOpenDjrepo = resourceOpenDjRepo.asObjectable(); assertNoRepoCache(); assertEquals(RESOURCE_OPENDJ_OID, resourceTypeOpenDjrepo.getOid()); display("Initialized OpenDJ resource (respository)", resourceTypeOpenDjrepo); assertNotNull("Resource schema was not generated", resourceTypeOpenDjrepo.getSchema()); Element resourceOpenDjXsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(resourceTypeOpenDjrepo); assertNotNull("Resource schema was not generated", resourceOpenDjXsdSchemaElement); PrismObject<ResourceType> openDjResourceProvisioninig = provisioningService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, null, opResult); display("Initialized OpenDJ resource resource (provisioning)", openDjResourceProvisioninig); PrismObject<ResourceType> openDjResourceModel = provisioningService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, null, opResult); display("Initialized OpenDJ resource OpenDJ resource (model)", openDjResourceModel); checkOpenDjResource(resourceTypeOpenDjrepo, "repository"); System.out.println("------------------------------------------------------------------"); display("OpenDJ resource schema (repo XML)", DOMUtil.serializeDOMToString(ResourceTypeUtil.getResourceXsdSchema(resourceOpenDjRepo))); System.out.println("------------------------------------------------------------------"); checkOpenDjResource(openDjResourceProvisioninig.asObjectable(), "provisioning"); checkOpenDjResource(openDjResourceModel.asObjectable(), "model"); // TODO: model web } catch (Exception ex){ LOGGER.info("exception: " + ex); throw ex; } } private void checkRepoOpenDjResource() throws ObjectNotFoundException, SchemaException { OperationResult result = new OperationResult(TestSanity.class.getName()+".checkRepoOpenDjResource"); PrismObject<ResourceType> resource = repositoryService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, result); checkOpenDjResource(resource.asObjectable(), "repository"); } /** * Checks if the resource is internally consistent, if it has everything it should have. * * @throws SchemaException */ private void checkOpenDjResource(ResourceType resource, String source) throws SchemaException { assertNotNull("Resource from " + source + " is null", resource); ObjectReferenceType connectorRefType = resource.getConnectorRef(); assertNotNull("Resource from " + source + " has null connectorRef", connectorRefType); assertFalse("Resource from " + source + " has no OID in connectorRef", StringUtils.isBlank(connectorRefType.getOid())); assertNotNull("Resource from " + source + " has null description in connectorRef", connectorRefType.getDescription()); assertNotNull("Resource from " + source + " has null filter in connectorRef", connectorRefType.getFilter()); assertNotNull("Resource from " + source + " has null filter element in connectorRef", connectorRefType.getFilter().getFilterClauseXNode()); assertNotNull("Resource from " + source + " has null configuration", resource.getConnectorConfiguration()); assertNotNull("Resource from " + source + " has null schema", resource.getSchema()); checkOpenDjSchema(resource, source); assertNotNull("Resource from " + source + " has null schemahandling", resource.getSchemaHandling()); checkOpenDjSchemaHandling(resource, source); if (!source.equals("repository")) { // This is generated on the fly in provisioning assertNotNull("Resource from " + source + " has null nativeCapabilities", resource.getCapabilities().getNative()); assertFalse("Resource from " + source + " has empty nativeCapabilities", resource.getCapabilities().getNative().getAny().isEmpty()); } assertNotNull("Resource from " + source + " has null configured capabilities", resource.getCapabilities().getConfigured()); assertFalse("Resource from " + source + " has empty capabilities", resource.getCapabilities().getConfigured().getAny().isEmpty()); assertNotNull("Resource from " + source + " has null synchronization", resource.getSynchronization()); checkOpenDjConfiguration(resource.asPrismObject(), source); } private void checkOpenDjSchema(ResourceType resource, String source) throws SchemaException { ResourceSchema schema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); ObjectClassComplexTypeDefinition accountDefinition = schema.findObjectClassDefinition(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS); assertNotNull("Schema does not define any account (resource from " + source + ")", accountDefinition); Collection<? extends ResourceAttributeDefinition> identifiers = accountDefinition.getPrimaryIdentifiers(); assertFalse("No account identifiers (resource from " + source + ")", identifiers == null || identifiers.isEmpty()); // TODO: check for naming attributes and display names, etc ActivationCapabilityType capActivation = ResourceTypeUtil.getEffectiveCapability(resource, ActivationCapabilityType.class); if (capActivation != null && capActivation.getStatus() != null && capActivation.getStatus().getAttribute() != null) { // There is simulated activation capability, check if the attribute is in schema. QName enableAttrName = capActivation.getStatus().getAttribute(); ResourceAttributeDefinition enableAttrDef = accountDefinition.findAttributeDefinition(enableAttrName); display("Simulated activation attribute definition", enableAttrDef); assertNotNull("No definition for enable attribute " + enableAttrName + " in account (resource from " + source + ")", enableAttrDef); assertTrue("Enable attribute " + enableAttrName + " is not ignored (resource from " + source + ")", enableAttrDef.isIgnored()); } } private void checkOpenDjSchemaHandling(ResourceType resource, String source) { SchemaHandlingType schemaHandling = resource.getSchemaHandling(); for (ResourceObjectTypeDefinitionType resObjectTypeDef: schemaHandling.getObjectType()) { if (resObjectTypeDef.getKind() == ShadowKindType.ACCOUNT) { String name = resObjectTypeDef.getIntent(); assertNotNull("Resource "+resource+" from "+source+" has an schemaHandlig account definition without intent", name); assertNotNull("Account type "+name+" in "+resource+" from "+source+" does not have object class", resObjectTypeDef.getObjectClass()); } if (resObjectTypeDef.getKind() == ShadowKindType.ENTITLEMENT) { String name = resObjectTypeDef.getIntent(); assertNotNull("Resource "+resource+" from "+source+" has an schemaHandlig entitlement definition without intent", name); assertNotNull("Entitlement type "+name+" in "+resource+" from "+source+" does not have object class", resObjectTypeDef.getObjectClass()); } } } private void checkOpenDjConfiguration(PrismObject<ResourceType> resource, String source) { checkOpenResourceConfiguration(resource, CONNECTOR_LDAP_NAMESPACE, "bindPassword", 8, source); } private void checkOpenResourceConfiguration(PrismObject<ResourceType> resource, String connectorNamespace, String credentialsPropertyName, int numConfigProps, String source) { PrismContainer<Containerable> configurationContainer = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); assertNotNull("No configuration container in "+resource+" from "+source, configurationContainer); PrismContainer<Containerable> configPropsContainer = configurationContainer.findContainer(SchemaTestConstants.ICFC_CONFIGURATION_PROPERTIES); assertNotNull("No configuration properties container in "+resource+" from "+source, configPropsContainer); List<? extends Item<?,?>> configProps = configPropsContainer.getValue().getItems(); assertEquals("Wrong number of config properties in "+resource+" from "+source, numConfigProps, configProps.size()); PrismProperty<Object> credentialsProp = configPropsContainer.findProperty(new QName(connectorNamespace,credentialsPropertyName)); if (credentialsProp == null) { // The is the heisenbug we are looking for. Just dump the entire damn thing. display("Configuration with the heisenbug", configurationContainer.debugDump()); } assertNotNull("No "+credentialsPropertyName+" property in "+resource+" from "+source, credentialsProp); assertEquals("Wrong number of "+credentialsPropertyName+" property value in "+resource+" from "+source, 1, credentialsProp.getValues().size()); PrismPropertyValue<Object> credentialsPropertyValue = credentialsProp.getValues().iterator().next(); assertNotNull("No "+credentialsPropertyName+" property value in "+resource+" from "+source, credentialsPropertyValue); if (credentialsPropertyValue.isRaw()) { Object rawElement = credentialsPropertyValue.getRawElement(); assertTrue("Wrong element class "+rawElement.getClass()+" in "+resource+" from "+source, rawElement instanceof MapXNode); // Element rawDomElement = (Element)rawElement; MapXNode xmap = (MapXNode) rawElement; try{ ProtectedStringType protectedType = new ProtectedStringType(); XNodeProcessorUtil.parseProtectedType(protectedType, xmap, prismContext); // display("LDAP credentials raw element", DOMUtil.serializeDOMToString(rawDomElement)); // assertEquals("Wrong credentials element namespace in "+resource+" from "+source, connectorNamespace, rawDomElement.getNamespaceURI()); // assertEquals("Wrong credentials element local name in "+resource+" from "+source, credentialsPropertyName, rawDomElement.getLocalName()); // Element encryptedDataElement = DOMUtil.getChildElement(rawDomElement, new QName(DOMUtil.NS_XML_ENC, "EncryptedData")); EncryptedDataType encryptedDataType = protectedType.getEncryptedDataType(); assertNotNull("No EncryptedData element", encryptedDataType); } catch (SchemaException ex){ throw new IllegalArgumentException(ex); } // assertEquals("Wrong EncryptedData element namespace in "+resource+" from "+source, DOMUtil.NS_XML_ENC, encryptedDataType.getNamespaceURI()); // assertEquals("Wrong EncryptedData element local name in "+resource+" from "+source, "EncryptedData", encryptedDataType.getLocalName()); } else { Object credentials = credentialsPropertyValue.getValue(); assertTrue("Wrong type of credentials configuration property in "+resource+" from "+source+": "+credentials.getClass(), credentials instanceof ProtectedStringType); ProtectedStringType credentialsPs = (ProtectedStringType)credentials; EncryptedDataType encryptedData = credentialsPs.getEncryptedDataType(); assertNotNull("No EncryptedData element", encryptedData); } } @Test public void test002AddDerbyResource() throws Exception { final String TEST_NAME = "test002AddDerbyResource"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); checkRepoOpenDjResource(); assertNoRepoCache(); PrismObject<ResourceType> resource = PrismTestUtil.parseObject(new File(RESOURCE_DERBY_FILENAME)); assertParentConsistency(resource); fillInConnectorRef(resource, IntegrationTestTools.DBTABLE_CONNECTOR_TYPE, result); OperationResultType resultType = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(resultType); Holder<String> oidHolder = new Holder<String>(); display("Adding Derby Resource", resource); // WHEN addObjectViaModelWS(resource.asObjectable(), null, oidHolder, resultHolder); // THEN // Check if Derby resource was imported correctly PrismObject<ResourceType> derbyResource = repositoryService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, result); AssertJUnit.assertEquals(RESOURCE_DERBY_OID, derbyResource.getOid()); assertNoRepoCache(); String dbConnectorOid = derbyResource.asObjectable().getConnectorRef().getOid(); PrismObject<ConnectorType> dbConnector = repositoryService.getObject(ConnectorType.class, dbConnectorOid, null, result); display("DB Connector: ", dbConnector); // Check if password was encrypted during import // via JAXB Object configurationPropertiesElement = JAXBUtil.findElement(derbyResource.asObjectable().getConnectorConfiguration().getAny(), new QName(dbConnector.asObjectable().getNamespace(), "configurationProperties")); Object passwordElement = JAXBUtil.findElement(JAXBUtil.listChildElements(configurationPropertiesElement), new QName(dbConnector.asObjectable().getNamespace(), "password")); System.out.println("Password element: " + passwordElement); // via prisms PrismContainerValue configurationProperties = derbyResource.findContainer( new ItemPath( ResourceType.F_CONNECTOR_CONFIGURATION, new QName("configurationProperties"))) .getValue(); PrismProperty password = configurationProperties.findProperty(new QName(dbConnector.asObjectable().getNamespace(), "password")); System.out.println("Password property: " + password); } private void addObjectViaModelWS(ObjectType objectType, ModelExecuteOptionsType options, Holder<String> oidHolder, Holder<OperationResultType> resultHolder) throws FaultMessage { ObjectDeltaListType deltaList = new ObjectDeltaListType(); ObjectDeltaType objectDelta = new ObjectDeltaType(); objectDelta.setObjectToAdd(objectType); QName type = objectType.asPrismObject().getDefinition().getTypeName(); objectDelta.setObjectType(type); objectDelta.setChangeType(ChangeTypeType.ADD); deltaList.getDelta().add(objectDelta); ObjectDeltaOperationListType objectDeltaOperationListType = modelWeb.executeChanges(deltaList, options); ObjectDeltaOperationType objectDeltaOperationType = getOdoFromDeltaOperationList(objectDeltaOperationListType, objectDelta); resultHolder.value = objectDeltaOperationType.getExecutionResult(); oidHolder.value = ((ObjectType) objectDeltaOperationType.getObjectDelta().getObjectToAdd()).getOid(); } // ugly hack... private static ObjectDeltaOperationType getOdoFromDeltaOperationList(ObjectDeltaOperationListType operationListType, ObjectDeltaType originalDelta) { Validate.notNull(operationListType); Validate.notNull(originalDelta); for (ObjectDeltaOperationType operationType : operationListType.getDeltaOperation()) { ObjectDeltaType objectDeltaType = operationType.getObjectDelta(); if (originalDelta.getChangeType() == ChangeTypeType.ADD) { if (objectDeltaType.getChangeType() == originalDelta.getChangeType() && objectDeltaType.getObjectToAdd() != null) { ObjectType objectAdded = (ObjectType) objectDeltaType.getObjectToAdd(); if (objectAdded.getClass().equals(originalDelta.getObjectToAdd().getClass())) { return operationType; } } } else { if (objectDeltaType.getChangeType() == originalDelta.getChangeType() && originalDelta.getOid().equals(objectDeltaType.getOid())) { return operationType; } } } throw new IllegalStateException("No suitable ObjectDeltaOperationType found"); } private void checkRepoDerbyResource() throws ObjectNotFoundException, SchemaException { OperationResult result = new OperationResult(TestSanity.class.getName()+".checkRepoDerbyResource"); PrismObject<ResourceType> resource = repositoryService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, result); checkDerbyResource(resource, "repository"); } private void checkDerbyResource(PrismObject<ResourceType> resource, String source) { checkDerbyConfiguration(resource, source); } private void checkDerbyConfiguration(PrismObject<ResourceType> resource, String source) { checkOpenResourceConfiguration(resource, CONNECTOR_DBTABLE_NAMESPACE, "password", 10, source); } /** * Test the testResource method. Expect a complete success for now. */ @Test public void test003TestConnectionDerby() throws Exception { TestUtil.displayTestTile("test003TestConnectionDerby"); // GIVEN checkRepoDerbyResource(); assertNoRepoCache(); // WHEN OperationResultType result = modelWeb.testResource(RESOURCE_DERBY_OID); // THEN assertNoRepoCache(); displayJaxb("testResource result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("testResource has failed", result.getPartialResults().get(0)); OperationResult opResult = new OperationResult(TestSanity.class.getName() + ".test002TestConnectionDerby"); PrismObject<ResourceType> rObject = repositoryService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, opResult); resourceDerby = rObject.asObjectable(); checkDerbyResource(rObject, "repository(after test)"); assertNoRepoCache(); assertEquals(RESOURCE_DERBY_OID, resourceDerby.getOid()); display("Initialized Derby resource (respository)", resourceDerby); assertNotNull("Resource schema was not generated", resourceDerby.getSchema()); Element resourceDerbyXsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(resourceDerby); assertNotNull("Resource schema was not generated", resourceDerbyXsdSchemaElement); PrismObject<ResourceType> derbyResourceProvisioninig = provisioningService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, null, opResult); display("Initialized Derby resource (provisioning)", derbyResourceProvisioninig); PrismObject<ResourceType> derbyResourceModel = provisioningService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, null, opResult); display("Initialized Derby resource (model)", derbyResourceModel); // TODO: check // checkOpenDjResource(resourceOpenDj,"repository"); // checkOpenDjResource(openDjResourceProvisioninig,"provisioning"); // checkOpenDjResource(openDjResourceModel,"model"); // TODO: model web } @Test public void test004Capabilities() throws ObjectNotFoundException, CommunicationException, SchemaException, FaultMessage { TestUtil.displayTestTile("test004Capabilities"); // GIVEN checkRepoOpenDjResource(); assertNoRepoCache(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<ObjectType> objectHolder = new Holder<ObjectType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); // WHEN modelWeb.getObject(ObjectTypes.RESOURCE.getTypeQName(), RESOURCE_OPENDJ_OID, options , objectHolder, resultHolder); ResourceType resource = (ResourceType) objectHolder.value; // THEN display("Resource", resource); assertNoRepoCache(); CapabilityCollectionType nativeCapabilities = resource.getCapabilities().getNative(); List<Object> capabilities = nativeCapabilities.getAny(); assertFalse("Empty capabilities returned", capabilities.isEmpty()); for (Object capability : nativeCapabilities.getAny()) { System.out.println("Native Capability: " + CapabilityUtil.getCapabilityDisplayName(capability) + " : " + capability); } if (resource.getCapabilities() != null) { for (Object capability : resource.getCapabilities().getConfigured().getAny()) { System.out.println("Configured Capability: " + CapabilityUtil.getCapabilityDisplayName(capability) + " : " + capability); } } List<Object> effectiveCapabilities = ResourceTypeUtil.getEffectiveCapabilities(resource); for (Object capability : effectiveCapabilities) { System.out.println("Efective Capability: " + CapabilityUtil.getCapabilityDisplayName(capability) + " : " + capability); } CredentialsCapabilityType capCred = CapabilityUtil.getCapability(capabilities, CredentialsCapabilityType.class); assertNotNull("password capability not present", capCred.getPassword()); // Connector cannot do activation, this should be null ActivationCapabilityType capAct = CapabilityUtil.getCapability(capabilities, ActivationCapabilityType.class); assertNull("Found activation capability while not expecting it", capAct); capCred = ResourceTypeUtil.getEffectiveCapability(resource, CredentialsCapabilityType.class); assertNotNull("password capability not found", capCred.getPassword()); // Although connector does not support activation, the resource specifies a way how to simulate it. // Therefore the following should succeed capAct = ResourceTypeUtil.getEffectiveCapability(resource, ActivationCapabilityType.class); assertNotNull("activation capability not found", capAct); } @Test public void test005resolveConnectorRef() throws Exception{ TestUtil.displayTestTile("test005resolveConnectorRef"); PrismObject<ResourceType> resource = PrismTestUtil.parseObject(new File(RESOURCE_DUMMY_FILENAME)); ModelExecuteOptionsType options = new ModelExecuteOptionsType(); options.setIsImport(Boolean.TRUE); addObjectViaModelWS(resource.asObjectable(), options, new Holder<String>(), new Holder<OperationResultType>()); OperationResult repoResult = new OperationResult("getObject"); PrismObject<ResourceType> uObject = repositoryService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, repoResult); assertNotNull(uObject); ResourceType resourceType = uObject.asObjectable(); assertNotNull("Reference on the connector must not be null in resource.",resourceType.getConnectorRef()); assertNotNull("Missing oid reference on the connector",resourceType.getConnectorRef().getOid()); } @Test public void test006reimportResourceDummy() throws Exception{ TestUtil.displayTestTile("test006reimportResourceDummy"); //get object from repo (with version set and try to add it - it should be re-added, without error) OperationResult repoResult = new OperationResult("getObject"); PrismObject<ResourceType> resource = repositoryService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, repoResult); assertNotNull(resource); ModelExecuteOptionsType options = new ModelExecuteOptionsType(); options.setOverwrite(Boolean.TRUE); options.setIsImport(Boolean.TRUE); addObjectViaModelWS(resource.asObjectable(), options, new Holder<String>(), new Holder<OperationResultType>()); //TODO: add some asserts //parse object from file again and try to add it - this should fail, becasue the same object already exists) resource = PrismTestUtil.parseObject(new File(RESOURCE_DUMMY_FILENAME)); try { Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); options = new ModelExecuteOptionsType(); options.setIsImport(Boolean.TRUE); addObjectViaModelWS(resource.asObjectable(), options, new Holder<String>(), resultHolder); OperationResultType result = resultHolder.value; TestUtil.assertFailure(result); fail("Expected object already exists exception, but haven't got one."); } catch (FaultMessage ex) { LOGGER.info("fault {}", ex.getFaultInfo()); LOGGER.info("fault {}", ex.getCause()); if (ex.getFaultInfo() instanceof ObjectAlreadyExistsFaultType){ // this is OK, we expect this } else{ fail("Expected object already exists exception, but haven't got one."); } } // ResourceType resourceType = uObject.asObjectable(); // assertNotNull("Reference on the connector must not be null in resource.",resourceType.getConnectorRef()); // assertNotNull("Missing oid reference on the connector",resourceType.getConnectorRef().getOid()); } /** * Attempt to add new user. It is only added to the repository, so check if * it is in the repository after the operation. */ @Test public void test010AddUser() throws Exception { final String TEST_NAME = "test010AddUser"; TestUtil.displayTestTile(TEST_NAME); // GIVEN checkRepoOpenDjResource(); assertNoRepoCache(); PrismObject<UserType> user = PrismTestUtil.parseObject(USER_JACK_FILE); UserType userType = user.asObjectable(); assertParentConsistency(user); // Encrypt Jack's password protector.encrypt(userType.getCredentials().getPassword().getValue()); assertParentConsistency(user); OperationResultType result = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(result); Holder<String> oidHolder = new Holder<String>(); display("Adding user object", userType); // WHEN addObjectViaModelWS(userType, null, oidHolder, resultHolder); // THEN assertNoRepoCache(); displayJaxb("addObject result:", resultHolder.value, SchemaConstants.C_RESULT); TestUtil.assertSuccess("addObject has failed", resultHolder.value); // AssertJUnit.assertEquals(USER_JACK_OID, oid); OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("repository.getObject result", repoResult); TestUtil.assertSuccess("getObject has failed", repoResult); AssertJUnit.assertEquals(USER_JACK_OID, repoUser.getOid()); assertEqualsPolyString("fullName", userType.getFullName(), repoUser.getFullName()); // TODO: better checks } /** * Add account to user. This should result in account provisioning. Check if * that happens in repo and in LDAP. */ @Test public void test013AddOpenDjAccountToUser() throws Exception { final String TEST_NAME = "test013AddOpenDjAccountToUser"; TestUtil.displayTestTile(TEST_NAME); try{ // GIVEN checkRepoOpenDjResource(); assertNoRepoCache(); // IMPORTANT! SWITCHING OFF ASSIGNMENT ENFORCEMENT HERE! setAssignmentEnforcement(AssignmentPolicyEnforcementType.NONE); // This is not redundant. It checks that the previous command set the policy correctly assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType.NONE); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ACCOUNT_OPENDJ_FILENAME, ObjectDeltaType.class); // WHEN TestUtil.displayWhen(TEST_NAME); OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN TestUtil.displayThen(TEST_NAME); assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals("No accountRefs", 1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); accountShadowOidOpendj = accountRef.getOid(); assertFalse(accountShadowOidOpendj.isEmpty()); // Check if shadow was created in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("Shadow (repository)", repoShadow); assertNotNull(repoShadowType); assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); assertNotNull("Shadow stored in repository has no name", repoShadowType.getName()); // Check the "name" property, it should be set to DN, not entryUUID assertEquals("Wrong name property", USER_JACK_LDAP_DN.toLowerCase(), repoShadowType.getName().getOrig().toLowerCase()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // check if account was created in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(uid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "jack"); OpenDJController.assertAttribute(entry, "givenName", "Jack"); OpenDJController.assertAttribute(entry, "sn", "Sparrow"); OpenDJController.assertAttribute(entry, "cn", "Jack Sparrow"); OpenDJController.assertAttribute(entry, "displayName", "Jack Sparrow"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Black Pearl"); assertTrue("LDAP account is not enabled", openDJController.isAccountEnabled(entry)); originalJacksLdapPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword was not set on create", originalJacksLdapPassword); System.out.println("password after create: " + originalJacksLdapPassword); // Use getObject to test fetch of complete shadow assertNoRepoCache(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<ObjectType> objectHolder = new Holder<ObjectType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); // WHEN modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidOpendj, options, objectHolder, resultHolder); // THEN assertNoRepoCache(); displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); TestUtil.assertSuccess("getObject has failed", resultHolder.value); ShadowType modelShadow = (ShadowType) objectHolder.value; display("Shadow (model)", modelShadow); AssertJUnit.assertNotNull(modelShadow); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, modelShadow.getResourceRef().getOid()); assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "uid", "jack"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "givenName", "Jack"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "sn", "Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "cn", "Jack Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "displayName", "Jack Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "l", "Black Pearl"); assertNull("carLicense attribute sneaked to LDAP", OpenDJController.getAttributeValue(entry, "carLicense")); assertNull("postalAddress attribute sneaked to LDAP", OpenDJController.getAttributeValue(entry, "postalAddress")); assertNotNull("Activation is null (model)", modelShadow.getActivation()); assertEquals("Wrong administrativeStatus in the shadow (model)", ActivationStatusType.ENABLED, modelShadow.getActivation().getAdministrativeStatus()); } catch (Exception ex){ LOGGER.info("ERROR: {}", ex); throw ex; } } private OperationResultType modifyObjectViaModelWS(ObjectDeltaType objectChange) throws FaultMessage { ObjectDeltaListType deltaList = new ObjectDeltaListType(); deltaList.getDelta().add(objectChange); ObjectDeltaOperationListType list = modelWeb.executeChanges(deltaList, null); return getOdoFromDeltaOperationList(list, objectChange).getExecutionResult(); } /** * Add Derby account to user. This should result in account provisioning. Check if * that happens in repo and in Derby. */ @Test public void test014AddDerbyAccountToUser() throws IOException, JAXBException, FaultMessage, ObjectNotFoundException, SchemaException, DirectoryException, SQLException { TestUtil.displayTestTile("test014AddDerbyAccountToUser"); // GIVEN checkRepoDerbyResource(); assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ACCOUNT_DERBY_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); // OpenDJ account was added in previous test, hence 2 accounts assertEquals(2, accountRefs.size()); ObjectReferenceType accountRef = null; for (ObjectReferenceType ref : accountRefs) { if (!ref.getOid().equals(accountShadowOidOpendj)) { accountRef = ref; } } accountShadowOidDerby = accountRef.getOid(); assertFalse(accountShadowOidDerby.isEmpty()); // Check if shadow was created in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidDerby, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("addObject has failed", repoResult); display("Shadow (repository)", repoShadowType); assertNotNull(repoShadowType); assertEquals(RESOURCE_DERBY_OID, repoShadowType.getResourceRef().getOid()); // Check the "name" property, it should be set to DN, not entryUUID assertEquals("Wrong name property", PrismTestUtil.createPolyStringType(USER_JACK_DERBY_LOGIN), repoShadowType.getName()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // check if account was created in DB Table Statement stmt = derbyController.getExecutedStatementWhereLoginName(uid); ResultSet rs = stmt.getResultSet(); System.out.println("RS: " + rs); assertTrue("No records found for login name " + uid, rs.next()); assertEquals(USER_JACK_DERBY_LOGIN, rs.getString(DerbyController.COLUMN_LOGIN)); assertEquals("Cpt. Jack Sparrow", rs.getString(DerbyController.COLUMN_FULL_NAME)); // TODO: check password //assertEquals("3lizab3th",rs.getString(DerbyController.COLUMN_PASSWORD)); System.out.println("Password: " + rs.getString(DerbyController.COLUMN_PASSWORD)); assertFalse("Too many records found for login name " + uid, rs.next()); rs.close(); stmt.close(); // Use getObject to test fetch of complete shadow assertNoRepoCache(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<ObjectType> objectHolder = new Holder<ObjectType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType (); // WHEN modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidDerby, options, objectHolder, resultHolder); // THEN assertNoRepoCache(); displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); TestUtil.assertSuccess("getObject has failed", resultHolder.value); ShadowType modelShadow = (ShadowType) objectHolder.value; display("Shadow (model)", modelShadow); AssertJUnit.assertNotNull(modelShadow); AssertJUnit.assertEquals(RESOURCE_DERBY_OID, modelShadow.getResourceRef().getOid()); assertAttribute(modelShadow, SchemaConstants.ICFS_UID, USER_JACK_DERBY_LOGIN); assertAttribute(modelShadow, SchemaConstants.ICFS_NAME, USER_JACK_DERBY_LOGIN); assertAttribute(resourceDerby, modelShadow, "FULL_NAME", "Cpt. Jack Sparrow"); } @Test public void test015AccountOwner() throws FaultMessage, ObjectNotFoundException, SchemaException, JAXBException { TestUtil.displayTestTile("test015AccountOwner"); // GIVEN checkRepoOpenDjResource(); assertNoRepoCache(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<UserType> userHolder = new Holder<UserType>(); // WHEN modelWeb.findShadowOwner(accountShadowOidOpendj, userHolder, resultHolder); // THEN display("listAccountShadowOwner result", resultHolder.value); TestUtil.assertSuccess("listAccountShadowOwner has failed (result)", resultHolder.value); UserType user = userHolder.value; assertNotNull("No owner", user); assertEquals(USER_JACK_OID, user.getOid()); System.out.println("Account " + accountShadowOidOpendj + " has owner " + ObjectTypeUtil.toShortString(user)); } @Test public void test016ProvisioningSearchAccountsIterative() throws Exception { TestUtil.displayTestTile("test016ProvisioningSearchAccountsIterative"); // GIVEN OperationResult result = new OperationResult(TestSanity.class.getName() + ".test016ProvisioningSearchAccountsIterative"); RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resourceTypeOpenDjrepo, prismContext); final RefinedObjectClassDefinition refinedAccountDefinition = refinedSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); QName objectClass = refinedAccountDefinition.getObjectClassDefinition().getTypeName(); ObjectQuery q = ObjectQueryUtil.createResourceAndObjectClassQuery(resourceTypeOpenDjrepo.getOid(), objectClass, prismContext); // ObjectQuery q = QueryConvertor.createObjectQuery(ResourceObjectShadowType.class, query, prismContext); final Collection<ObjectType> objects = new HashSet<ObjectType>(); final MatchingRule caseIgnoreMatchingRule = matchingRuleRegistry.getMatchingRule(StringIgnoreCaseMatchingRule.NAME, DOMUtil.XSD_STRING); ResultHandler handler = new ResultHandler<ObjectType>() { @Override public boolean handle(PrismObject<ObjectType> prismObject, OperationResult parentResult) { ObjectType objectType = prismObject.asObjectable(); objects.add(objectType); display("Found object", objectType); assertTrue(objectType instanceof ShadowType); ShadowType shadow = (ShadowType) objectType; assertNotNull(shadow.getOid()); assertNotNull(shadow.getName()); assertEquals(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS, shadow.getObjectClass()); assertEquals(RESOURCE_OPENDJ_OID, shadow.getResourceRef().getOid()); String icfUid = getAttributeValue(shadow, getOpenDjPrimaryIdentifierQName()); assertNotNull("No ICF UID", icfUid); String icfName = getNormalizedAttributeValue(shadow, refinedAccountDefinition, getOpenDjSecondaryIdentifierQName()); assertNotNull("No ICF NAME", icfName); try { PrismAsserts.assertEquals("Wrong shadow name", caseIgnoreMatchingRule, shadow.getName().getOrig(), icfName); } catch (SchemaException e) { throw new IllegalArgumentException(e.getMessage(),e); } assertNotNull("Missing LDAP uid", getAttributeValue(shadow, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "uid"))); assertNotNull("Missing LDAP cn", getAttributeValue(shadow, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "cn"))); assertNotNull("Missing LDAP sn", getAttributeValue(shadow, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "sn"))); assertNotNull("Missing activation", shadow.getActivation()); assertNotNull("Missing activation status", shadow.getActivation().getAdministrativeStatus()); return true; } }; // WHEN provisioningService.searchObjectsIterative(ShadowType.class, q, null, handler, null, result); // THEN display("Count", objects.size()); } /** * We are going to modify the user. As the user has an account, the user * changes should be also applied to the account (by schemaHandling). */ @Test public void test020ModifyUser() throws Exception { final String TEST_NAME = "test020ModifyUser"; TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_FULLNAME_LOCALITY_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); display("repository user", repoUser); PrismAsserts.assertEqualsPolyString("wrong value for fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); PrismAsserts.assertEqualsPolyString("wrong value for locality", "somewhere", repoUserType.getLocality()); assertEquals("wrong value for employeeNumber", "1", repoUserType.getEmployeeNumber()); // Check if appropriate accountRef is still there List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(2, accountRefs.size()); for (ObjectReferenceType accountRef : accountRefs) { assertTrue("No OID in "+accountRef+" in "+repoUserType, accountRef.getOid().equals(accountShadowOidOpendj) || accountRef.getOid().equals(accountShadowOidDerby)); } // Check if shadow is still in the repo and that it is untouched repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); display("repository shadow", repoShadow); AssertJUnit.assertNotNull(repoShadow); ShadowType repoShadowType = repoShadow.asObjectable(); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated assertOpenDJAccountJack(uid, "jack"); } private Entry assertOpenDJAccountJack(String entryUuid, String uid) throws DirectoryException { Entry entry = openDJController.searchAndAssertByEntryUuid(entryUuid); return assertOpenDJAccountJack(entry, uid); } private Entry assertOpenDJAccountJack(Entry entry, String uid) throws DirectoryException { return assertOpenDJAccountJack(entry, uid, "Jack"); } private Entry assertOpenDJAccountJack(Entry entry, String uid, String givenName) throws DirectoryException { display(entry); OpenDJController.assertDn(entry, "uid="+uid+",ou=people,dc=example,dc=com"); OpenDJController.assertAttribute(entry, "uid", uid); if (givenName == null) { OpenDJController.assertAttribute(entry, "givenName"); } else { OpenDJController.assertAttribute(entry, "givenName", givenName); } OpenDJController.assertAttribute(entry, "sn", "Sparrow"); // These two should be assigned from the User modification by // schemaHandling OpenDJController.assertAttribute(entry, "cn", "Cpt. Jack Sparrow"); OpenDJController.assertAttribute(entry, "displayName", "Cpt. Jack Sparrow"); // This will get translated from "somewhere" to this (outbound // expression in schemeHandling) -> this is not more supported...we // don't support complex run-time properties. the value will be // evaluated from outbound expression OpenDJController.assertAttribute(entry, "l", "somewhere"); OpenDJController.assertAttribute(entry, "postalAddress", "Number 1"); return entry; } /** * We are going to change user's password. As the user has an account, the password change * should be also applied to the account (by schemaHandling). */ @Test public void test022ChangeUserPassword() throws Exception { final String TEST_NAME = "test022ChangeUserPassword"; TestUtil.displayTestTile(TEST_NAME); // GIVEN ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_PASSWORD_FILENAME, ObjectDeltaType.class); System.out.println("In modification: " + objectChange.getItemDelta().get(0).getValue().get(0)); assertNoRepoCache(); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertUserPasswordChange("butUnd3dM4yT4lkAL0t", result); } /** * Similar to previous test just the request is constructed a bit differently. */ @Test public void test023ChangeUserPasswordJAXB() throws Exception { final String TEST_NAME = "test023ChangeUserPasswordJAXB"; TestUtil.displayTestTile(TEST_NAME); // GIVEN final String NEW_PASSWORD = "abandonSHIP"; Document doc = ModelClientUtil.getDocumnent(); ObjectDeltaType userDelta = new ObjectDeltaType(); userDelta.setOid(USER_JACK_OID); userDelta.setChangeType(ChangeTypeType.MODIFY); userDelta.setObjectType(UserType.COMPLEX_TYPE); ItemDeltaType passwordDelta = new ItemDeltaType(); passwordDelta.setModificationType(ModificationTypeType.REPLACE); passwordDelta.setPath(ModelClientUtil.createItemPathType("credentials/password/value")); ProtectedStringType pass = new ProtectedStringType(); pass.setClearValue(NEW_PASSWORD); XNode passValue = ((PrismContextImpl) prismContext).getBeanMarshaller().marshall(pass); System.out.println("PASSWORD VALUE: " + passValue.debugDump()); RawType passwordValue = new RawType(passValue, prismContext); passwordDelta.getValue().add(passwordValue); userDelta.getItemDelta().add(passwordDelta); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(userDelta); // THEN assertUserPasswordChange(NEW_PASSWORD, result); } private void assertUserPasswordChange(String expectedUserPassword, OperationResultType result) throws JAXBException, ObjectNotFoundException, SchemaException, DirectoryException, EncryptionException { assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); display("repository user", repoUser); // Check if nothing else was modified PrismAsserts.assertEqualsPolyString("wrong repo fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); PrismAsserts.assertEqualsPolyString("wrong repo locality", "somewhere", repoUserType.getLocality()); // Check if appropriate accountRef is still there assertLinks(repoUser, 2); assertLinked(repoUser, accountShadowOidOpendj); assertLinked(repoUser, accountShadowOidDerby); assertPassword(repoUser, expectedUserPassword); // Check if shadow is still in the repo and that it is untouched repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); display("repository shadow", repoShadow); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); AssertJUnit.assertNotNull(repoShadowType); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated Entry entry = assertOpenDJAccountJack(uid, "jack"); String ldapPasswordAfter = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull(ldapPasswordAfter); display("LDAP password after change", ldapPasswordAfter); assertFalse("No change in password (original)", ldapPasswordAfter.equals(originalJacksLdapPassword)); if (lastJacksLdapPassword != null) { assertFalse("No change in password (last)", ldapPasswordAfter.equals(lastJacksLdapPassword)); } lastJacksLdapPassword = ldapPasswordAfter; } @Test public void test027ModifyAccountDj() throws Exception { final String TEST_NAME = "test027ModifyAccountDj"; testModifyAccountDjRoomNumber(TEST_NAME, REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_FILE, "quarterdeck"); } @Test public void test028ModifyAccountDjExplicitType() throws Exception { final String TEST_NAME = "test028ModifyAccountDjExplicitType"; testModifyAccountDjRoomNumber(TEST_NAME, REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_EXPLICIT_TYPE_FILE, "upperdeck"); } public void testModifyAccountDjRoomNumber(final String TEST_NAME, File reqFile, String expectedVal) throws Exception { TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile(reqFile, ObjectDeltaType.class); objectChange.setOid(accountShadowOidOpendj); // WHEN OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); OperationResult repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); display("repository shadow", repoShadow); AssertJUnit.assertNotNull(repoShadow); ShadowType repoShadowType = repoShadow.asObjectable(); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated Entry jackLdapEntry = assertOpenDJAccountJack(uid, "jack"); OpenDJController.assertAttribute(jackLdapEntry, "roomNumber", expectedVal); } @Test public void test029ModifyAccountDjBadPath() throws Exception { final String TEST_NAME = "test029ModifyAccountDjBadPath"; TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_ACCOUNT_MODIFY_BAD_PATH_FILE, ObjectDeltaType.class); objectChange.setOid(accountShadowOidOpendj); OperationResultType result; try { // WHEN result = modifyObjectViaModelWS(objectChange); AssertJUnit.fail("Unexpected success"); } catch (FaultMessage f) { // this is expected FaultType faultInfo = f.getFaultInfo(); result = faultInfo.getOperationResult(); } // THEN assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertFailure(result); OperationResult repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); display("repository shadow", repoShadow); AssertJUnit.assertNotNull(repoShadow); ShadowType repoShadowType = repoShadow.asObjectable(); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated Entry jackLdapEntry = assertOpenDJAccountJack(uid, "jack"); OpenDJController.assertAttribute(jackLdapEntry, "roomNumber", "upperdeck"); } /** * Try to disable user. As the user has an account, the account should be disabled as well. */ @Test public void test030DisableUser() throws Exception { final String TEST_NAME = "test030DisableUser"; TestUtil.displayTestTile(TEST_NAME); // GIVEN ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ACTIVATION_DISABLE_FILENAME, ObjectDeltaType.class); Entry entry = openDJController.searchByUid("jack"); assertOpenDJAccountJack(entry, "jack"); String pwpAccountDisabled = OpenDJController.getAttributeValue(entry, "ds-pwp-account-disabled"); display("ds-pwp-account-disabled before change", pwpAccountDisabled); assertTrue("LDAP account is not enabled (precondition)", openDJController.isAccountEnabled(entry)); assertNoRepoCache(); // WHEN TestUtil.displayWhen(TEST_NAME); OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN TestUtil.displayThen(TEST_NAME); assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); display("repository user", repoUser); UserType repoUserType = repoUser.asObjectable(); // Check if nothing else was modified assertEqualsPolyString("wrong repo fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); assertEqualsPolyString("wrong repo locality", "somewhere", repoUserType.getLocality()); // Check if appropriate accountRef is still there List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(2, accountRefs.size()); for (ObjectReferenceType accountRef : accountRefs) { assertTrue("No OID in "+accountRef+" in "+repoUserType, accountRef.getOid().equals(accountShadowOidOpendj) || accountRef.getOid().equals(accountShadowOidDerby)); } // Check if shadow is still in the repo and that it is untouched repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); display("repo shadow", repoShadow); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); AssertJUnit.assertNotNull(repoShadowType); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated entry = openDJController.searchAndAssertByEntryUuid(uid); assertOpenDJAccountJack(entry, "jack"); pwpAccountDisabled = OpenDJController.getAttributeValue(entry, "ds-pwp-account-disabled"); display("ds-pwp-account-disabled after change", pwpAccountDisabled); assertFalse("LDAP account was not disabled", openDJController.isAccountEnabled(entry)); // Use getObject to test fetch of complete shadow Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<ObjectType> objectHolder = new Holder<ObjectType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); assertNoRepoCache(); // WHEN TestUtil.displayWhen(TEST_NAME); modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidOpendj, options, objectHolder, resultHolder); // THEN TestUtil.displayThen(TEST_NAME); assertNoRepoCache(); displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); TestUtil.assertSuccess("getObject has failed", resultHolder.value); ShadowType modelShadow = (ShadowType) objectHolder.value; display("Shadow (model)", modelShadow); AssertJUnit.assertNotNull(modelShadow); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, modelShadow.getResourceRef().getOid()); assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "uid", "jack"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "givenName", "Jack"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "sn", "Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "cn", "Cpt. Jack Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "displayName", "Cpt. Jack Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "l", "somewhere"); assertNotNull("The account activation is null in the shadow", modelShadow.getActivation()); assertNotNull("The account activation status was not present in shadow", modelShadow.getActivation().getAdministrativeStatus()); assertEquals("The account was not disabled in the shadow", ActivationStatusType.DISABLED, modelShadow.getActivation().getAdministrativeStatus()); } /** * Try to enable user after it has been disabled. As the user has an account, the account should be enabled as well. */ @Test public void test031EnableUser() throws Exception { final String TEST_NAME = "test031EnableUser"; TestUtil.displayTestTile(TEST_NAME); // GIVEN ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ACTIVATION_ENABLE_FILENAME, ObjectDeltaType.class); assertNoRepoCache(); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); display("repo user", repoUser); // Check if nothing else was modified PrismAsserts.assertEqualsPolyString("wrong repo fullName", "Cpt. Jack Sparrow", repoUser.getFullName()); PrismAsserts.assertEqualsPolyString("wrong repo locality", "somewhere", repoUser.getLocality()); // Check if appropriate accountRef is still there List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals(2, accountRefs.size()); for (ObjectReferenceType accountRef : accountRefs) { assertTrue("No OID in "+accountRef+" in "+repoUser, accountRef.getOid().equals(accountShadowOidOpendj) || accountRef.getOid().equals(accountShadowOidDerby)); } // Check if shadow is still in the repo and that it is untouched repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); display("repo shadow", repoShadowType); AssertJUnit.assertNotNull(repoShadowType); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Use getObject to test fetch of complete shadow Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<ObjectType> objectHolder = new Holder<ObjectType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); assertNoRepoCache(); // WHEN modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidOpendj, options, objectHolder, resultHolder); // THEN assertNoRepoCache(); displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); TestUtil.assertSuccess("getObject has failed", resultHolder.value); ShadowType modelShadow = (ShadowType) objectHolder.value; display("Shadow (model)", modelShadow); AssertJUnit.assertNotNull(modelShadow); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, modelShadow.getResourceRef().getOid()); assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "uid", "jack"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "givenName", "Jack"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "sn", "Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "cn", "Cpt. Jack Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "displayName", "Cpt. Jack Sparrow"); assertAttribute(resourceTypeOpenDjrepo, modelShadow, "l", "somewhere"); assertNotNull("The account activation is null in the shadow", modelShadow.getActivation()); assertNotNull("The account activation status was not present in shadow", modelShadow.getActivation().getAdministrativeStatus()); assertEquals("The account was not enabled in the shadow", ActivationStatusType.ENABLED, modelShadow.getActivation().getAdministrativeStatus()); // Check if LDAP account was updated Entry entry = openDJController.searchAndAssertByEntryUuid(uid); assertOpenDJAccountJack(entry, "jack"); // The value of ds-pwp-account-disabled should have been removed String pwpAccountDisabled = OpenDJController.getAttributeValue(entry, "ds-pwp-account-disabled"); System.out.println("ds-pwp-account-disabled after change: " + pwpAccountDisabled); assertTrue("LDAP account was not enabled", openDJController.isAccountEnabled(entry)); } /** * Unlink account by removing the accountRef from the user. * The account will not be deleted, just the association to user will be broken. */ @Test public void test040UnlinkDerbyAccountFromUser() throws FileNotFoundException, JAXBException, FaultMessage, ObjectNotFoundException, SchemaException, DirectoryException, SQLException { TestUtil.displayTestTile("test040UnlinkDerbyAccountFromUser"); // GIVEN ObjectDeltaType objectChange = new ObjectDeltaType(); objectChange.setOid(USER_JACK_OID); ItemDeltaType modificationDeleteAccountRef = new ItemDeltaType(); modificationDeleteAccountRef.setModificationType(ModificationTypeType.DELETE); ObjectReferenceType accountRefToDelete = new ObjectReferenceType(); accountRefToDelete.setOid(accountShadowOidDerby); RawType modificationValue = new RawType(((PrismContextImpl) prismContext).getBeanMarshaller().marshall(accountRefToDelete), prismContext); modificationDeleteAccountRef.getValue().add(modificationValue); modificationDeleteAccountRef.setPath(new ItemPathType(new ItemPath(UserType.F_LINK_REF))); objectChange.getItemDelta().add(modificationDeleteAccountRef); objectChange.setChangeType(ChangeTypeType.MODIFY); objectChange.setObjectType(UserType.COMPLEX_TYPE); displayJaxb("modifyObject input", objectChange, new QName(SchemaConstants.NS_C, "change")); assertNoRepoCache(); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); // only OpenDJ account should be left now assertEquals(1, accountRefs.size()); ObjectReferenceType ref = accountRefs.get(0); assertEquals("Wrong OID in accountRef in "+repoUser, accountShadowOidOpendj, ref.getOid()); } /** * Delete the shadow which will cause deletion of associated account. * The account was unlinked in the previous test, therefore no operation with user is needed. */ @Test public void test041DeleteDerbyAccount() throws FileNotFoundException, JAXBException, FaultMessage, ObjectNotFoundException, SchemaException, DirectoryException, SQLException { TestUtil.displayTestTile("test041DeleteDerbyAccount"); // GIVEN assertNoRepoCache(); // WHEN OperationResultType result = deleteObjectViaModelWS(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidDerby); // THEN assertNoRepoCache(); displayJaxb("deleteObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("deleteObject has failed", result); // Check if shadow was deleted OperationResult repoResult = new OperationResult("getObject"); try { repositoryService.getObject(ShadowType.class, accountShadowOidDerby, null, repoResult); AssertJUnit.fail("Shadow was not deleted"); } catch (ObjectNotFoundException ex) { display("Caught expected exception from getObject(shadow): " + ex); } // check if account was deleted in DB Table Statement stmt = derbyController.getExecutedStatementWhereLoginName(USER_JACK_DERBY_LOGIN); ResultSet rs = stmt.getResultSet(); System.out.println("RS: " + rs); assertFalse("Account was not deleted in database", rs.next()); } private OperationResultType deleteObjectViaModelWS(QName typeQName, String oid) throws FaultMessage { ObjectDeltaListType deltaList = new ObjectDeltaListType(); ObjectDeltaType objectDelta = new ObjectDeltaType(); objectDelta.setOid(oid); objectDelta.setObjectType(typeQName); objectDelta.setChangeType(ChangeTypeType.DELETE); deltaList.getDelta().add(objectDelta); ObjectDeltaOperationListType list = modelWeb.executeChanges(deltaList, null); return getOdoFromDeltaOperationList(list, objectDelta).getExecutionResult(); } @Test public void test047RenameUser() throws Exception { final String TEST_NAME = "test047RenameUser"; TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_NAME_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); display("repository user", repoUser); PrismAsserts.assertEqualsPolyString("wrong value for User name", "jsparrow", repoUserType.getName()); PrismAsserts.assertEqualsPolyString("wrong value for User fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); PrismAsserts.assertEqualsPolyString("wrong value for User locality", "somewhere", repoUserType.getLocality()); assertEquals("wrong value for employeeNumber", "1", repoUserType.getEmployeeNumber()); // Check if appropriate accountRef is still there List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.iterator().next(); assertEquals("Wrong OID in "+accountRef+" in "+repoUserType, accountShadowOidOpendj, accountRef.getOid()); // Check if shadow is still in the repo and that it is untouched repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); display("repository shadow", repoShadow); AssertJUnit.assertNotNull(repoShadow); ShadowType repoShadowType = repoShadow.asObjectable(); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated assertOpenDJAccountJack(uid, "jsparrow"); } /** * We are going to modify the user. As the user has an account, the user * changes should be also applied to the account (by schemaHandling). * * @throws DirectoryException */ @Test public void test048ModifyUserRemoveGivenName() throws Exception { final String TEST_NAME = "test048ModifyUserRemoveGivenName"; TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_GIVENNAME_FILENAME, ObjectDeltaType.class); displayJaxb("objectChange:", objectChange, SchemaConstants.T_OBJECT_DELTA); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); display("repository user", repoUser); PrismAsserts.assertEqualsPolyString("wrong value for fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); assertNull("Value for givenName still present", repoUserType.getGivenName()); // Check if appropriate accountRef is still there List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.iterator().next(); accountRef.getOid().equals(accountShadowOidOpendj); // Check if shadow is still in the repo and that it is untouched repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); repoResult.computeStatus(); TestUtil.assertSuccess("getObject(repo) has failed", repoResult); display("repository shadow", repoShadow); AssertJUnit.assertNotNull(repoShadow); ShadowType repoShadowType = repoShadow.asObjectable(); AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check attributes in the shadow: should be only identifiers (ICF UID) String uid = checkRepoShadow(repoShadow); // Check if LDAP account was updated Entry entry = openDJController.searchAndAssertByEntryUuid(uid); assertOpenDJAccountJack(entry, "jsparrow", null); } /** * The user should have an account now. Let's try to delete the user. The * account should be gone as well. * * @throws JAXBException */ @Test public void test049DeleteUser() throws SchemaException, FaultMessage, DirectoryException, JAXBException { TestUtil.displayTestTile("test049DeleteUser"); // GIVEN assertNoRepoCache(); // WHEN OperationResultType result = deleteObjectViaModelWS(ObjectTypes.USER.getTypeQName(), USER_JACK_OID); // THEN assertNoRepoCache(); displayJaxb("deleteObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("deleteObject has failed", result); // User should be gone from the repository OperationResult repoResult = new OperationResult("getObject"); try { repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); AssertJUnit.fail("User still exists in repo after delete"); } catch (ObjectNotFoundException e) { // This is expected } // Account shadow should be gone from the repository repoResult = new OperationResult("getObject"); try { repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); AssertJUnit.fail("Shadow still exists in repo after delete"); } catch (ObjectNotFoundException e) { // This is expected, but check also the result AssertJUnit.assertFalse("getObject failed as expected, but the result indicates success", repoResult.isSuccess()); } // Account should be deleted from LDAP InternalSearchOperation op = openDJController.getInternalConnection().processSearch( "dc=example,dc=com", SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 100, 100, false, "(uid=" + USER_JACK_LDAP_UID + ")", null); AssertJUnit.assertEquals(0, op.getEntriesSent()); } @Test public void test100AssignRolePirate() throws Exception { final String TEST_NAME = "test100AssignRolePirate"; TestUtil.displayTestTile(TEST_NAME); // GIVEN // IMPORTANT! Assignment enforcement is FULL now setAssignmentEnforcement(AssignmentPolicyEnforcementType.FULL); // This is not redundant. It checks that the previous command set the policy correctly assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType.FULL); PrismObject<UserType> user = PrismTestUtil.parseObject(USER_GUYBRUSH_FILE); UserType userType = user.asObjectable(); // Encrypt the password protector.encrypt(userType.getCredentials().getPassword().getValue()); OperationResultType result = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(result); Holder<String> oidHolder = new Holder<String>(); assertNoRepoCache(); addObjectViaModelWS(userType, null, oidHolder, resultHolder); assertNoRepoCache(); TestUtil.assertSuccess("addObject has failed", resultHolder.value); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ROLE_PIRATE_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); accountShadowOidGuybrushOpendj = accountRef.getOid(); assertFalse(accountShadowOidGuybrushOpendj.isEmpty()); // Check if shadow was created in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("Shadow (repository)", repoShadowType); assertNotNull(repoShadowType); assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); accountGuybrushOpendjEntryUuuid = checkRepoShadow(repoShadow); // check if account was created in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Bloody Pirate"); OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword was not set on create", guybrushPassword); // TODO: Derby } @Test public void test101AccountOwnerAfterRole() throws Exception { final String TEST_NAME = "test101AccountOwnerAfterRole"; TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<UserType> userHolder = new Holder<UserType>(); // WHEN modelWeb.findShadowOwner(accountShadowOidGuybrushOpendj, userHolder, resultHolder); // THEN TestUtil.assertSuccess("listAccountShadowOwner has failed (result)", resultHolder.value); UserType user = userHolder.value; assertNotNull("No owner", user); assertEquals(USER_GUYBRUSH_OID, user.getOid()); System.out.println("Account " + accountShadowOidGuybrushOpendj + " has owner " + ObjectTypeUtil.toShortString(user)); } @Test public void test102AssignRoleCaptain() throws Exception { final String TEST_NAME = "test102AssignRoleCaptain"; TestUtil.displayTestTile(TEST_NAME); // GIVEN ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_1_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); // Check if shadow is still in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> aObject = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadow = aObject.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("Shadow (repository)", repoShadow); assertNotNull(repoShadow); assertEquals(RESOURCE_OPENDJ_OID, repoShadow.getResourceRef().getOid()); // check if account is still in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Bloody Pirate", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder", "cruise"); // Expression in the role taking that from the user OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); // Expression in the role taking that from the assignment OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword disappeared", guybrushPassword); // TODO: Derby } /** * Assign the same "captain" role again, this time with a slightly different assignment parameters. */ @Test public void test103AssignRoleCaptainAgain() throws Exception { final String TEST_NAME = "test103AssignRoleCaptainAgain"; TestUtil.displayTestTile(TEST_NAME); // GIVEN ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_2_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); // Check if shadow is still in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> aObject = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadow = aObject.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("Shadow (repository)", repoShadow); assertNotNull(repoShadow); assertEquals(RESOURCE_OPENDJ_OID, repoShadow.getResourceRef().getOid()); // check if account is still in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Bloody Pirate", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder", "cruise"); // Expression in the role taking that from the user OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); // Expression in the role taking that from the assignments (both of them) OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey", "The Dainty Lady"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword disappeared", guybrushPassword); // TODO: Derby } @Test public void test105ModifyAccount() throws Exception { final String TEST_NAME = "test105ModifyAccount"; TestUtil.displayTestTile(TEST_NAME); // GIVEN ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_ACCOUNT_MODIFY_ATTRS_FILE, ObjectDeltaType.class); objectChange.setOid(accountShadowOidGuybrushOpendj); // WHEN ObjectTypes.SHADOW.getTypeQName(), OperationResultType result = modifyObjectViaModelWS(objectChange); Task task = taskManager.createTaskInstance(); OperationResult parentResult = new OperationResult(TEST_NAME + "-get after first modify"); PrismObject<ShadowType> shadow= modelService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, task, parentResult); assertNotNull("shadow must not be null", shadow); ShadowType shadowType = shadow.asObjectable(); QName employeeTypeQName = new QName(resourceTypeOpenDjrepo.getNamespace(), "employeeType"); ItemPath employeeTypePath = new ItemPath(ShadowType.F_ATTRIBUTES, employeeTypeQName); PrismProperty item = shadow.findProperty(employeeTypePath); PropertyDelta deleteDelta = new PropertyDelta(new ItemPath(ShadowType.F_ATTRIBUTES), item.getDefinition().getName(), item.getDefinition(), prismContext); // PropertyDelta deleteDelta = PropertyDelta.createDelta(employeeTypePath, shadow.getDefinition()); // PrismPropertyValue valToDelte = new PrismPropertyValue("A"); // valToDelte.setParent(deleteDelta); Collection<PrismPropertyValue> values= item.getValues(); for (PrismPropertyValue val : values){ if ("A".equals(val.getValue())){ deleteDelta.addValueToDelete(val.clone()); } } ObjectDelta delta = new ObjectDelta(ShadowType.class, ChangeType.MODIFY, prismContext); delta.addModification(deleteDelta); delta.setOid(accountShadowOidGuybrushOpendj); Collection<ObjectDelta<? extends ObjectType>> deltas = new ArrayList<ObjectDelta<? extends ObjectType>>(); deltas.add(delta); LOGGER.info("-------->>EXECUTE DELETE MODIFICATION<<------------"); modelService.executeChanges(deltas, null, task, parentResult); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // check if LDAP account was modified Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); OpenDJController.assertAttribute(entry, "roomNumber", "captain's cabin"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Bloody Pirate", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder", "cruise", "fighting", "capsize"); // Expression in the role taking that from the user OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); // Expression in the role taking that from the assignments (both of them) OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey", "The Dainty Lady"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword disappeared", guybrushPassword); } /** * Judge role excludes pirate role. This assignment should fail. */ @Test public void test104AssignRoleJudge() throws Exception { final String TEST_NAME = "test104AssignRoleJudge"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResultType result = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(result); Holder<String> oidHolder = new Holder<String>(); assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ROLE_JUDGE_FILENAME, ObjectDeltaType.class); try { // WHEN ObjectTypes.USER.getTypeQName(), result = modifyObjectViaModelWS(objectChange); // THEN AssertJUnit.fail("Expected a failure after assigning conflicting roles but nothing happened and life goes on"); } catch (FaultMessage f) { // This is expected // TODO: check if the fault is the right one } assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object remain unmodified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals("Unexpected number or accountRefs", 1, accountRefs.size()); } @Test public void test107UnassignRolePirate() throws Exception { final String TEST_NAME = "test107UnassignRolePirate"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResultType result = new OperationResultType(); assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_DELETE_ROLE_PIRATE_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); // Check if shadow is still in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> aObject = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadow = aObject.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("Shadow (repository)", repoShadow); assertNotNull(repoShadow); assertEquals(RESOURCE_OPENDJ_OID, repoShadow.getResourceRef().getOid()); // check if account is still in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "cruise", "fighting", "capsize"); // Expression in the role taking that from the user OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); // Expression in the role taking that from the assignments (both of them) OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey", "The Dainty Lady"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword disappeared", guybrushPassword); // TODO: Derby } @Test public void test108UnassignRoleCaptain() throws Exception { final String TEST_NAME = "test108UnassignRoleCaptain"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResultType result = new OperationResultType(); assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_1_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); TestUtil.assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUser); List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); // Check if shadow is still in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); display("Shadow (repository)", repoShadow); assertNotNull(repoShadowType); assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); // check if account is still in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "cruise", "fighting", "capsize"); // Expression in the role taking that from the user OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); // Expression in the role taking that from the assignments (both of them) OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Dainty Lady"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword disappeared", guybrushPassword); // TODO: Derby } /** * Captain role was assigned twice. It has to also be unassigned twice. */ @Test public void test109UnassignRoleCaptainAgain() throws Exception { final String TEST_NAME = "test109UnassignRoleCaptainAgain"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResultType result = new OperationResultType(); assertNoRepoCache(); ObjectDeltaType objectChange = unmarshallValueFromFile( REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_2_FILENAME, ObjectDeltaType.class); // WHEN ObjectTypes.USER.getTypeQName(), result = modifyObjectViaModelWS(objectChange); // THEN assertNoRepoCache(); displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); //TODO TODO TODO TODO operation result from repostiory.getObject is unknown...find out why.. // assertSuccess("modifyObject has failed", result); // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PropertyReferenceListType resolve = new PropertyReferenceListType(); PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUserType = repoUser.asObjectable(); repoResult.computeStatus(); display("User (repository)", repoUserType); List<ObjectReferenceType> accountRefs = repoUserType.getLinkRef(); assertEquals(0, accountRefs.size()); // Check if shadow was deleted from the repo repoResult = new OperationResult("getObject"); try { PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); AssertJUnit.fail("Account shadow was not deleted from repo"); } catch (ObjectNotFoundException ex) { // This is expected } // check if account was deleted from LDAP Entry entry = openDJController.searchByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); assertNull("LDAP account was not deleted", entry); // TODO: Derby } // Synchronization tests /** * Test initialization of synchronization. It will create a cycle task and * check if the cycle executes No changes are synchronized yet. */ @Test public void test300LiveSyncInit() throws Exception { final String TEST_NAME = "test300LiveSyncInit"; TestUtil.displayTestTile(TEST_NAME); // Now it is the right time to add task definition to the repository // We don't want it there any sooner, as it may interfere with the // previous tests checkAllShadows(); // IMPORTANT! Assignment enforcement is POSITIVE now setAssignmentEnforcement(AssignmentPolicyEnforcementType.POSITIVE); // This is not redundant. It checks that the previous command set the policy correctly assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType.POSITIVE); final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); repoAddObjectFromFile(TASK_OPENDJ_SYNC_FILENAME, result); // We need to wait for a sync interval, so the task scanner has a chance // to pick up this // task waitFor("Waiting for task manager to pick up the task", new Checker() { public boolean check() throws ObjectNotFoundException, SchemaException { Task task = taskManager.getTask(TASK_OPENDJ_SYNC_OID, result); display("Task while waiting for task manager to pick up the task", task); // wait until the task is picked up return task.getLastRunFinishTimestamp() != null; // if (TaskExclusivityStatus.CLAIMED == task.getExclusivityStatus()) { // // wait until the first run is finished // if (task.getLastRunFinishTimestamp() == null) { // return false; // } // return true; // } // return false; } @Override public void timeout() { // No reaction, the test will fail right after return from this } }, 20000); // Check task status Task task = taskManager.getTask(TASK_OPENDJ_SYNC_OID, result); result.computeStatus(); display("getTask result", result); TestUtil.assertSuccess("getTask has failed", result); AssertJUnit.assertNotNull(task); display("Task after pickup", task); PrismObject<TaskType> o = repositoryService.getObject(TaskType.class, TASK_OPENDJ_SYNC_OID, null, result); display("Task after pickup in the repository", o.asObjectable()); // .. it should be running AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus()); // .. and claimed // AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus()); // .. and last run should not be zero assertNotNull("No lastRunStartTimestamp", task.getLastRunStartTimestamp()); assertFalse("Zero lastRunStartTimestamp", task.getLastRunStartTimestamp().longValue() == 0); assertNotNull("No lastRunFinishedTimestamp", task.getLastRunFinishTimestamp()); assertFalse("Zero lastRunFinishedTimestamp", task.getLastRunFinishTimestamp().longValue() == 0); // Test for extension. This will also roughly test extension processor // and schema processor PrismContainer<?> taskExtension = task.getExtension(); AssertJUnit.assertNotNull(taskExtension); display("Task extension", taskExtension); PrismProperty<String> shipStateProp = taskExtension.findProperty(MY_SHIP_STATE); AssertJUnit.assertEquals("Wrong 'shipState' property value", "capsized", shipStateProp.getValue().getValue()); PrismProperty<Integer> deadProp = taskExtension.findProperty(MY_DEAD); PrismPropertyValue<Integer> deadPVal = deadProp.getValues().iterator().next(); AssertJUnit.assertEquals("Wrong 'dead' property class", Integer.class, deadPVal.getValue().getClass()); AssertJUnit.assertEquals("Wrong 'dead' property value", Integer.valueOf(42), deadPVal.getValue()); // The progress should be 0, as there were no changes yet AssertJUnit.assertEquals(0, task.getProgress()); // Test for presence of a result. It should be there and it should // indicate success OperationResult taskResult = task.getResult(); AssertJUnit.assertNotNull(taskResult); assertTrue(taskResult.isSuccess()); final Object tokenAfter = findSyncToken(task); display("Sync token after", tokenAfter.toString()); lastSyncToken = (Integer)tokenAfter; checkAllShadows(); } /** * Create LDAP object. That should be picked up by liveSync and a user * should be created in repo. */ @Test public void test301LiveSyncCreate() throws Exception { final String TEST_NAME = "test301LiveSyncCreate"; TestUtil.displayTestTile(TEST_NAME); // Sync task should be running (tested in previous test), so just create // new LDAP object. final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); final Task syncCycle = taskManager.getTask(TASK_OPENDJ_SYNC_OID, result); AssertJUnit.assertNotNull(syncCycle); final Object tokenBefore = findSyncToken(syncCycle); display("Sync token before", tokenBefore.toString()); // WHEN Entry entry = openDJController.addEntryFromLdifFile(LDIF_WILL_FILENAME); display("Entry from LDIF", entry); // THEN // Wait a bit to give the sync cycle time to detect the change basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 4, result); // Search for the user that should be created now UserType user = searchUserByName(WILL_NAME); PrismAsserts.assertEqualsPolyString("Wrong name.", WILL_NAME, user.getName()); assertNotNull(user.getLinkRef()); assertFalse(user.getLinkRef().isEmpty()); // AssertJUnit.assertEquals(user.getName(), WILL_NAME); // TODO: more checks assertAndStoreSyncTokenIncrement(syncCycle, 4); checkAllShadows(); } @Test public void test302LiveSyncModify() throws Exception { final String TEST_NAME = "test302LiveSyncModify"; TestUtil.displayTestTile(TEST_NAME); final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); final Task syncCycle = taskManager.getTask(TASK_OPENDJ_SYNC_OID, result); AssertJUnit.assertNotNull(syncCycle); int tokenBefore = findSyncToken(syncCycle); display("Sync token before", tokenBefore); // WHEN display("Modifying LDAP entry"); ChangeRecordEntry entry = openDJController.executeLdifChange(LDIF_WILL_MODIFY_FILE); // THEN display("Entry from LDIF", entry); // Wait a bit to give the sync cycle time to detect the change basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 1, result); // Search for the user that should be created now UserType user = searchUserByName (WILL_NAME); // AssertJUnit.assertEquals(WILL_NAME, user.getName()); PrismAsserts.assertEqualsPolyString("Wrong name.", WILL_NAME, user.getName()); PrismAsserts.assertEqualsPolyString("wrong givenName", "asdf", user.getGivenName()); assertAndStoreSyncTokenIncrement(syncCycle, 1); checkAllShadows(); } @Test public void test303LiveSyncLink() throws Exception { final String TEST_NAME = "test303LiveSyncLink"; TestUtil.displayTestTile(TEST_NAME); // GIVEN assertNoRepoCache(); PrismObject<UserType> user = PrismTestUtil.parseObject(USER_E_LINK_ACTION_FILE); UserType userType = user.asObjectable(); final String userOid = userType.getOid(); // Encrypt e's password protector.encrypt(userType.getCredentials().getPassword().getValue()); // create user in repository OperationResultType resultType = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(resultType); Holder<String> oidHolder = new Holder<String>(); display("Adding user object", userType); addObjectViaModelWS(userType, null, oidHolder, resultHolder); //check results assertNoRepoCache(); displayJaxb("addObject result:", resultHolder.value, SchemaConstants.C_RESULT); TestUtil.assertSuccess("addObject has failed", resultHolder.value); // AssertJUnit.assertEquals(userOid, oidHolder.value); //WHEN //create account for e which should be correlated final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); final Task syncCycle = taskManager.getTask(TASK_OPENDJ_SYNC_OID, result); AssertJUnit.assertNotNull(syncCycle); int tokenBefore = findSyncToken(syncCycle); display("Sync token before", tokenBefore); Entry entry = openDJController.addEntryFromLdifFile(LDIF_E_FILENAME_LINK); display("Entry from LDIF", entry); // THEN // Wait a bit to give the sync cycle time to detect the change basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 4, result); //check user and account ref userType = searchUserByName("e"); List<ObjectReferenceType> accountRefs = userType.getLinkRef(); assertEquals("Account ref not found, or found too many", 1, accountRefs.size()); //check account defined by account ref String accountOid = accountRefs.get(0).getOid(); ShadowType account = searchAccountByOid(accountOid); assertEqualsPolyString("Name doesn't match", "uid=e,ou=People,dc=example,dc=com", account.getName()); assertAndStoreSyncTokenIncrement(syncCycle, 4); checkAllShadows(); } /** * Create LDAP object. That should be picked up by liveSync and a user * should be created in repo. * Also location (ldap l) should be updated through outbound */ @Test public void test304LiveSyncCreateNoLocation() throws Exception { final String TEST_NAME = "test304LiveSyncCreateNoLocation"; TestUtil.displayTestTile(TEST_NAME); // Sync task should be running (tested in previous test), so just create // new LDAP object. final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); final Task syncCycle = taskManager.getTask(TASK_OPENDJ_SYNC_OID, result); AssertJUnit.assertNotNull(syncCycle); int tokenBefore = findSyncToken(syncCycle); display("Sync token before", tokenBefore); // WHEN Entry entry = openDJController.addEntryFromLdifFile(LDIF_WILL_WITHOUT_LOCATION_FILENAME); display("Entry from LDIF", entry); // THEN // Wait a bit to give the sync cycle time to detect the change basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 3, result, 60000); // Search for the user that should be created now final String userName = "wturner1"; UserType user = searchUserByName(userName); List<ObjectReferenceType> accountRefs = user.getLinkRef(); assertEquals("Account ref not found, or found too many", 1, accountRefs.size()); //check account defined by account ref String accountOid = accountRefs.get(0).getOid(); ShadowType account = searchAccountByOid(accountOid); assertEqualsPolyString("Name doesn't match", "uid=" + userName + ",ou=People,dc=example,dc=com", account.getName()); // assertEquals("Name doesn't match", "uid=" + userName + ",ou=People,dc=example,dc=com", account.getName()); Collection<String> localities = getAttributeValues(account, new QName(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS.getNamespaceURI(), "l")); assertNotNull("null value list for attribute 'l'", localities); assertEquals("unexpected number of values of attribute 'l'", 1, localities.size()); assertEquals("Locality doesn't match", "middle of nowhere", localities.iterator().next()); assertAndStoreSyncTokenIncrement(syncCycle, 3); checkAllShadows(); } private void assertAndStoreSyncTokenIncrement(Task syncCycle, int increment) { final Object tokenAfter = findSyncToken(syncCycle); display("Sync token after", tokenAfter.toString()); int tokenAfterInt = (Integer)tokenAfter; int expectedToken = lastSyncToken + increment; lastSyncToken = tokenAfterInt; assertEquals("Unexpected sync toke value", expectedToken, tokenAfterInt); } private int findSyncToken(Task syncCycle) { return (Integer)findSyncTokenObject(syncCycle); } private Object findSyncTokenObject(Task syncCycle) { Object token = null; PrismProperty<?> tokenProperty = syncCycle.getExtension().findProperty(SchemaConstants.SYNC_TOKEN); if (tokenProperty != null) { Collection<?> values = tokenProperty.getRealValues(); if (values.size() > 1) { throw new IllegalStateException("Too must values in token "+tokenProperty); } token = values.iterator().next(); } return token; } /** * Not really a test. Just cleans up after live sync. */ @Test public void test399LiveSyncCleanup() throws Exception { final String TEST_NAME = "test399LiveSyncCleanup"; TestUtil.displayTestTile(TEST_NAME); final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); taskManager.deleteTask(TASK_OPENDJ_SYNC_OID, result); // TODO: check if the task is really stopped } @Test public void test400ImportFromResource() throws Exception { final String TEST_NAME = "test400ImportFromResource"; TestUtil.displayTestTile(TEST_NAME); // GIVEN checkAllShadows(); assertNoRepoCache(); OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); // Make sure Mr. Gibbs has "l" attribute set to the same value as an outbound expression is setting ChangeRecordEntry entry = openDJController.executeLdifChange(LDIF_GIBBS_MODIFY_FILE); display("Entry from LDIF", entry); // Let's add an entry with multiple uids. Entry addEntry = openDJController.addEntryFromLdifFile(LDIF_HERMAN_FILENAME); display("Entry from LDIF", addEntry); // WHEN TestUtil.displayWhen(TEST_NAME); TaskType taskType = modelWeb.importFromResource(RESOURCE_OPENDJ_OID, RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS); // THEN TestUtil.displayThen(TEST_NAME); assertNoRepoCache(); displayJaxb("importFromResource result", taskType.getResult(), SchemaConstants.C_RESULT); AssertJUnit.assertEquals("importFromResource has failed", OperationResultStatusType.IN_PROGRESS, taskType.getResult().getStatus()); // Convert the returned TaskType to a more usable Task Task task = taskManager.createTaskInstance(taskType.asPrismObject(), result); AssertJUnit.assertNotNull(task); assertNotNull(task.getOid()); AssertJUnit.assertTrue(task.isAsynchronous()); AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus()); // AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus()); display("Import task after launch", task); PrismObject<TaskType> tObject = repositoryService.getObject(TaskType.class, task.getOid(), null, result); TaskType taskAfter = tObject.asObjectable(); display("Import task in repo after launch", taskAfter); result.computeStatus(); TestUtil.assertSuccess("getObject has failed", result); final String taskOid = task.getOid(); waitFor("Waiting for import to complete", new Checker() { @Override public boolean check() throws CommonException { Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); Holder<ObjectType> objectHolder = new Holder<ObjectType>(); OperationResult opResult = new OperationResult("import check"); assertNoRepoCache(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); try { modelWeb.getObject(ObjectTypes.TASK.getTypeQName(), taskOid, options, objectHolder, resultHolder); } catch (FaultMessage faultMessage) { throw new SystemException(faultMessage); } assertNoRepoCache(); // display("getObject result (wait loop)",resultHolder.value); TestUtil.assertSuccess("getObject has failed", resultHolder.value); Task task = taskManager.createTaskInstance((PrismObject<TaskType>) objectHolder.value.asPrismObject(), opResult); System.out.println(new Date() + ": Import task status: " + task.getExecutionStatus() + ", progress: " + task.getProgress()); if (task.getExecutionStatus() == TaskExecutionStatus.CLOSED) { // Task closed, wait finished return true; } // IntegrationTestTools.display("Task result while waiting: ", task.getResult()); return false; } @Override public void timeout() { // No reaction, the test will fail right after return from this } }, 180000); // wait a second until the task will be definitely saved Thread.sleep(1000); //### Check task state after the task is finished ### Holder<ObjectType> objectHolder = new Holder<ObjectType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); assertNoRepoCache(); modelWeb.getObject(ObjectTypes.TASK.getTypeQName(), task.getOid(), options, objectHolder, resultHolder); assertNoRepoCache(); TestUtil.assertSuccess("getObject has failed", resultHolder.value); task = taskManager.createTaskInstance((PrismObject<TaskType>) objectHolder.value.asPrismObject(), result); display("Import task after finish (fetched from model)", task); AssertJUnit.assertEquals(TaskExecutionStatus.CLOSED, task.getExecutionStatus()); assertNotNull("Null lastRunStartTimestamp in "+task, task.getLastRunStartTimestamp()); assertNotNull("Null lastRunFinishTimestamp in "+task, task.getLastRunFinishTimestamp()); long importDuration = task.getLastRunFinishTimestamp() - task.getLastRunStartTimestamp(); double usersPerSec = (task.getProgress() * 1000) / importDuration; display("Imported " + task.getProgress() + " users in " + importDuration + " milliseconds (" + usersPerSec + " users/sec)"); OperationResult taskResult = task.getResult(); AssertJUnit.assertNotNull("Task has no result", taskResult); TestUtil.assertSuccess("Import task result is not success", taskResult); AssertJUnit.assertTrue("Task failed", taskResult.isSuccess()); AssertJUnit.assertTrue("No progress", task.getProgress() > 0); //### Check if the import created users and shadows ### // Listing of shadows is not supported by the provisioning. So we need // to look directly into repository List<PrismObject<ShadowType>> sobjects = repositoryService.searchObjects(ShadowType.class, null, null, result); result.computeStatus(); TestUtil.assertSuccess("listObjects has failed", result); AssertJUnit.assertFalse("No shadows created", sobjects.isEmpty()); for (PrismObject<ShadowType> aObject : sobjects) { ShadowType shadow = aObject.asObjectable(); display("Shadow object after import (repo)", shadow); assertNotEmpty("No OID in shadow", shadow.getOid()); // This would be really strange ;-) assertNotEmpty("No name in shadow", shadow.getName()); AssertJUnit.assertNotNull("No objectclass in shadow", shadow.getObjectClass()); AssertJUnit.assertNotNull("Null attributes in shadow", shadow.getAttributes()); String resourceOid = shadow.getResourceRef().getOid(); if (resourceOid.equals(RESOURCE_OPENDJ_OID)) { assertAttributeNotNull("No identifier in shadow", shadow, getOpenDjPrimaryIdentifierQName()); } else { assertAttributeNotNull("No UID in shadow", shadow, SchemaConstants.ICFS_UID); } } Holder<ObjectListType> listHolder = new Holder<>(); assertNoRepoCache(); modelWeb.searchObjects(ObjectTypes.USER.getTypeQName(), null, null, listHolder, resultHolder); assertNoRepoCache(); ObjectListType uobjects = listHolder.value; TestUtil.assertSuccess("listObjects has failed", resultHolder.value); AssertJUnit.assertFalse("No users created", uobjects.getObject().isEmpty()); // TODO: use another account, not guybrush display("Users after import "+uobjects.getObject().size()); for (ObjectType oo : uobjects.getObject()) { UserType user = (UserType) oo; if (SystemObjectsType.USER_ADMINISTRATOR.value().equals(user.getOid())) { //skip administrator check continue; } display("User after import (repo)", user); assertNotEmpty("No OID in user", user.getOid()); // This would be // really // strange ;-) assertNotEmpty("No name in user", user.getName()); assertNotNull("No fullName in user", user.getFullName()); assertNotEmpty("No fullName in user", user.getFullName().getOrig()); assertNotEmpty("No familyName in user", user.getFamilyName().getOrig()); // givenName is not mandatory in LDAP, therefore givenName may not // be present on user if (user.getName().getOrig().equals(USER_GUYBRUSH_USERNAME)) { // skip the rest of checks for guybrush, he does not have LDAP account now continue; } assertTrue("User "+user.getName()+" is disabled ("+user.getActivation().getAdministrativeStatus()+")", user.getActivation() == null || user.getActivation().getAdministrativeStatus() == ActivationStatusType.ENABLED); List<ObjectReferenceType> accountRefs = user.getLinkRef(); AssertJUnit.assertEquals("Wrong accountRef for user " + user.getName(), 1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); boolean found = false; for (PrismObject<ShadowType> aObject : sobjects) { ShadowType acc = aObject.asObjectable(); if (accountRef.getOid().equals(acc.getOid())) { found = true; break; } } if (!found) { AssertJUnit.fail("accountRef does not point to existing account " + accountRef.getOid()); } PrismObject<ShadowType> aObject = modelService.getObject(ShadowType.class, accountRef.getOid(), null, task, result); ShadowType account = aObject.asObjectable(); display("Account after import ", account); String attributeValueL = ShadowUtil.getMultiStringAttributeValueAsSingle(account, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "l")); // assertEquals("Unexcpected value of l", "middle of nowhere", attributeValueL); assertEquals("Unexcpected value of l", getUserLocality(user), attributeValueL); } // This also includes "idm" user imported from LDAP. Later we need to ignore that one. assertEquals("Wrong number of users after import", 10, uobjects.getObject().size()); checkAllShadows(); } private String getUserLocality(UserType user){ return user.getLocality() != null ? user.getLocality().getOrig() :"middle of nowhere"; } @Test public void test420RecomputeUsers() throws Exception { final String TEST_NAME = "test420RecomputeUsers"; TestUtil.displayTestTile(TEST_NAME); // GIVEN final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); // Assign role to a user, but we do this using a repository instead of model. // The role assignment will not be executed and this created an inconsistent state. ObjectDeltaType changeAddRoleCaptain = unmarshallValueFromFile( REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_1_FILENAME, ObjectDeltaType.class); Collection<? extends ItemDelta> modifications = DeltaConvertor.toModifications(changeAddRoleCaptain.getItemDelta(), getUserDefinition()); repositoryService.modifyObject(UserType.class, changeAddRoleCaptain.getOid(), modifications, result); // TODO: setup more "inconsistent" state // Add reconciliation task. This will trigger reconciliation importObjectFromFile(TASK_USER_RECOMPUTE_FILENAME, result); // We need to wait for a sync interval, so the task scanner has a chance // to pick up this // task waitFor("Waiting for task to finish", new Checker() { public boolean check() throws ObjectNotFoundException, SchemaException { Task task = taskManager.getTask(TASK_USER_RECOMPUTE_OID, result); //display("Task while waiting for task manager to pick up the task", task); // wait until the task is finished if (TaskExecutionStatus.CLOSED == task.getExecutionStatus()) { return true; } return false; } @Override public void timeout() { // No reaction, the test will fail right after return from this } }, 40000); // wait a second until the task will be definitely saved Thread.sleep(1000); // Check task status Task task = taskManager.getTask(TASK_USER_RECOMPUTE_OID, result); result.computeStatus(); display("getTask result", result); TestUtil.assertSuccess("getTask has failed", result); AssertJUnit.assertNotNull(task); display("Task after finish", task); AssertJUnit.assertNotNull(task.getTaskIdentifier()); assertFalse(task.getTaskIdentifier().isEmpty()); PrismObject<TaskType> o = repositoryService.getObject(TaskType.class, TASK_USER_RECOMPUTE_OID, null, result); display("Task after pickup in the repository", o.asObjectable()); AssertJUnit.assertEquals(TaskExecutionStatus.CLOSED, task.getExecutionStatus()); // .. and last run should not be zero assertNotNull(task.getLastRunStartTimestamp()); AssertJUnit.assertFalse(task.getLastRunStartTimestamp().longValue() == 0); assertNotNull(task.getLastRunFinishTimestamp()); AssertJUnit.assertFalse(task.getLastRunFinishTimestamp().longValue() == 0); AssertJUnit.assertEquals(10, task.getProgress()); // Test for presence of a result. It should be there and it should // indicate success OperationResult taskResult = task.getResult(); display("Recompute task result", taskResult); AssertJUnit.assertNotNull(taskResult); TestUtil.assertSuccess("Recompute task result", taskResult); // STOP the task. We don't need it any more and we don't want to give it a chance to run more than once taskManager.deleteTask(TASK_USER_RECOMPUTE_OID, result); // CHECK RESULT: account created for user guybrush // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> object = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUser = object.asObjectable(); repoResult.computeStatus(); displayJaxb("User (repository)", repoUser, new QName("user")); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals("Wrong number of accountRefs after recompute for user "+repoUser.getName(), 1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); accountShadowOidGuybrushOpendj = accountRef.getOid(); assertFalse(accountShadowOidGuybrushOpendj.isEmpty()); // Check if shadow was created in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); displayJaxb("Shadow (repository)", repoShadowType, new QName("shadow")); assertNotNull(repoShadowType); assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); accountGuybrushOpendjEntryUuuid = checkRepoShadow(repoShadow); // check if account was created in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); OpenDJController.assertAttribute(entry, "title", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "cruise"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword was not set on create", guybrushPassword); checkAllShadows(); } @Test public void test440ReconcileResourceOpenDj() throws Exception { final String TEST_NAME = "test440ReconcileResourceOpenDj"; TestUtil.displayTestTile(TEST_NAME); // GIVEN final OperationResult result = new OperationResult(TestSanity.class.getName() + "." + TEST_NAME); // Create LDAP account without an owner. The liveSync is off, so it will not be picked up Entry ldifEntry = openDJController.addEntryFromLdifFile(LDIF_ELAINE_FILENAME); display("Entry from LDIF", ldifEntry); // Guybrush's attributes were set up by a role in the previous test. Let's mess the up a bit. Recon should sort it out. List<RawModification> modifications = new ArrayList<RawModification>(); // Expect that a correct title will be added to this one RawModification titleMod = RawModification.create(ModificationType.REPLACE, "title", "Scurvy earthworm"); modifications.add(titleMod); // Expect that the correct location will replace this one RawModification lMod = RawModification.create(ModificationType.REPLACE, "l", "Davie Jones' locker"); modifications.add(lMod); // Expect that this will be untouched RawModification poMod = RawModification.create(ModificationType.REPLACE, "postOfficeBox", "X marks the spot"); modifications.add(poMod); ModifyOperation modifyOperation = openDJController.getInternalConnection().processModify(USER_GUYBRUSH_LDAP_DN, modifications); if (ResultCode.SUCCESS != modifyOperation.getResultCode()) { AssertJUnit.fail("LDAP operation failed: " + modifyOperation.getErrorMessage()); } // TODO: setup more "inconsistent" state // Add reconciliation task. This will trigger reconciliation repoAddObjectFromFile(TASK_OPENDJ_RECON_FILENAME, result); // We need to wait for a sync interval, so the task scanner has a chance // to pick up this // task waitFor("Waiting for task to finish first run", new Checker() { public boolean check() throws ObjectNotFoundException, SchemaException { Task task = taskManager.getTask(TASK_OPENDJ_RECON_OID, result); display("Task while waiting for task manager to pick up the task", task); // wait until the task is finished return task.getLastRunFinishTimestamp() != null; } @Override public void timeout() { // No reaction, the test will fail right after return from this } }, 180000); // Check task status Task task = taskManager.getTask(TASK_OPENDJ_RECON_OID, result); result.computeStatus(); display("getTask result", result); TestUtil.assertSuccess("getTask has failed", result); AssertJUnit.assertNotNull(task); display("Task after pickup", task); PrismObject<TaskType> o = repositoryService.getObject(TaskType.class, TASK_OPENDJ_RECON_OID, null, result); display("Task after pickup in the repository", o.asObjectable()); // .. it should be running AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus()); // .. and claimed // AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus()); // .. and last run should not be zero assertNotNull("Null last run start in recon task", task.getLastRunStartTimestamp()); AssertJUnit.assertFalse("Zero last run start in recon task", task.getLastRunStartTimestamp().longValue() == 0); assertNotNull("Null last run finish in recon task", task.getLastRunFinishTimestamp()); AssertJUnit.assertFalse("Zero last run finish in recon task", task.getLastRunFinishTimestamp().longValue() == 0); // The progress should be 0, as there were no changes yet // [pm] commented out, as progress in recon task is now determined not only using # of changes //AssertJUnit.assertEquals(0, task.getProgress()); // Test for presence of a result. It should be there and it should // indicate success OperationResult taskResult = task.getResult(); AssertJUnit.assertNotNull(taskResult); // STOP the task. We don't need it any more and we don't want to give it a chance to run more than once taskManager.deleteTask(TASK_OPENDJ_RECON_OID, result); // CHECK RESULT: account for user guybrush should be still there and unchanged // Check if user object was modified in the repo OperationResult repoResult = new OperationResult("getObject"); PrismObject<UserType> uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); UserType repoUser = uObject.asObjectable(); repoResult.computeStatus(); displayJaxb("User (repository)", repoUser, new QName("user")); List<ObjectReferenceType> accountRefs = repoUser.getLinkRef(); assertEquals("Guybrush has wrong number of accounts", 1, accountRefs.size()); ObjectReferenceType accountRef = accountRefs.get(0); accountShadowOidGuybrushOpendj = accountRef.getOid(); assertFalse(accountShadowOidGuybrushOpendj.isEmpty()); // Check if shadow was created in the repo repoResult = new OperationResult("getObject"); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, repoResult); ShadowType repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); displayJaxb("Shadow (repository)", repoShadowType, new QName("shadow")); assertNotNull(repoShadowType); assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); accountGuybrushOpendjEntryUuuid = checkRepoShadow(repoShadow); // check if account was created in LDAP Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", "guybrush"); OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); OpenDJController.assertAttribute(entry, "sn", "Threepwood"); OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); // The "l" attribute is assigned indirectly through schemaHandling and // config object. It is not tolerant, therefore the other value should be gone now OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "sailor"); // "title" is tolerant, so it will retain the original value as well as the one provided by the role OpenDJController.assertAttribute(entry, "title", "Scurvy earthworm", "Honorable Captain"); OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); OpenDJController.assertAttribute(entry, "businessCategory", "cruise"); // No setting for "postOfficeBox", so the value should be unchanged OpenDJController.assertAttribute(entry, "postOfficeBox", "X marks the spot"); String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Pasword was not set on create", guybrushPassword); // QueryType query = QueryUtil.createNameQuery(ELAINE_NAME); // ObjectQuery query = ObjectQuery.createObjectQuery(EqualsFilter.createEqual(UserType.class, prismContext, UserType.F_NAME, ELAINE_NAME)); ObjectQuery query = ObjectQueryUtil.createNameQuery(ELAINE_NAME, prismContext); List<PrismObject<UserType>> users = repositoryService.searchObjects(UserType.class, query, null, repoResult); assertEquals("Wrong number of Elaines", 1, users.size()); repoUser = users.get(0).asObjectable(); repoResult.computeStatus(); displayJaxb("User Elaine (repository)", repoUser, new QName("user")); assertNotNull(repoUser.getOid()); assertEquals(PrismTestUtil.createPolyStringType(ELAINE_NAME), repoUser.getName()); PrismAsserts.assertEqualsPolyString("wrong repo givenName", "Elaine", repoUser.getGivenName()); PrismAsserts.assertEqualsPolyString("wrong repo familyName", "Marley", repoUser.getFamilyName()); PrismAsserts.assertEqualsPolyString("wrong repo fullName", "Elaine Marley", repoUser.getFullName()); accountRefs = repoUser.getLinkRef(); assertEquals("Elaine has wrong number of accounts", 1, accountRefs.size()); accountRef = accountRefs.get(0); String accountShadowOidElaineOpendj = accountRef.getOid(); assertFalse(accountShadowOidElaineOpendj.isEmpty()); // Check if shadow was created in the repo repoResult = new OperationResult("getObject"); repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidElaineOpendj, null, repoResult); repoShadowType = repoShadow.asObjectable(); repoResult.computeStatus(); TestUtil.assertSuccess("getObject has failed", repoResult); displayJaxb("Shadow (repository)", repoShadowType, new QName("shadow")); assertNotNull(repoShadowType); assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); String accountElainehOpendjEntryUuuid = checkRepoShadow(repoShadow); // check if account is still in LDAP entry = openDJController.searchAndAssertByEntryUuid(accountElainehOpendjEntryUuuid); display("LDAP account", entry); OpenDJController.assertAttribute(entry, "uid", ELAINE_NAME); OpenDJController.assertAttribute(entry, "givenName", "Elaine"); OpenDJController.assertAttribute(entry, "sn", "Marley"); OpenDJController.assertAttribute(entry, "cn", "Elaine Marley"); OpenDJController.assertAttribute(entry, "displayName", "Elaine Marley"); // The "l" attribute is assigned indirectly through schemaHandling and // config object // FIXME //OpenDJController.assertAttribute(entry, "l", "middle of nowhere"); // Set by the role OpenDJController.assertAttribute(entry, "employeeType", "governor"); OpenDJController.assertAttribute(entry, "title", "Governor"); OpenDJController.assertAttribute(entry, "businessCategory", "state"); String elainePassword = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull("Password of Elaine has disappeared", elainePassword); checkAllShadows(); } @Test public void test480ListResources() throws Exception { final String TEST_NAME = "test480ListResources"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResultType result = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(result); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); // WHEN modelWeb.searchObjects(ObjectTypes.RESOURCE.getTypeQName(), null, options, objectListHolder, resultHolder); // THEN display("Resources", objectListHolder.value); assertEquals("Unexpected number of resources", 4, objectListHolder.value.getObject().size()); // TODO for(ObjectType object: objectListHolder.value.getObject()) { // Marshalling may fail even though the Java object is OK so test for it String xml = prismContext.serializeObjectToString(object.asPrismObject(), PrismContext.LANG_XML); } } @Test public void test485ListResourcesWithBrokenResource() throws Exception { TestUtil.displayTestTile("test485ListResourcesWithBrokenResource"); // GIVEN Task task = taskManager.createTaskInstance(TestSanity.class.getName() + ".test410ListResourcesWithBrokenResource"); final OperationResult result = task.getResult(); // WHEN List<PrismObject<ResourceType>> resources = modelService.searchObjects(ResourceType.class, new ObjectQuery(), null, task, result); // THEN assertNotNull("listObjects returned null list", resources); for (PrismObject<ResourceType> object : resources) { ResourceType resource = object.asObjectable(); //display("Resource found",resource); display("Found " + ObjectTypeUtil.toShortString(resource) + ", result " + (resource.getFetchResult() == null ? "null" : resource.getFetchResult().getStatus())); assertNotNull(resource.getOid()); assertNotNull(resource.getName()); if (resource.getOid().equals(RESOURCE_BROKEN_OID)) { assertTrue("No error in fetchResult in " + ObjectTypeUtil.toShortString(resource), resource.getFetchResult() != null && (resource.getFetchResult().getStatus() == OperationResultStatusType.PARTIAL_ERROR || resource.getFetchResult().getStatus() == OperationResultStatusType.FATAL_ERROR)); } else { assertTrue("Unexpected error in fetchResult in " + ObjectTypeUtil.toShortString(resource), resource.getFetchResult() == null || resource.getFetchResult().getStatus() == OperationResultStatusType.SUCCESS); } } } @Test public void test500NotifyChangeCreateAccount() throws Exception{ final String TEST_NAME = "test500NotifyChangeCreateAccount"; TestUtil.displayTestTile(TEST_NAME); Entry ldifEntry = openDJController.addEntryFromLdifFile(LDIF_ANGELIKA_FILENAME); display("Entry from LDIF", ldifEntry); List<Attribute> attributes = ldifEntry.getAttributes(); // for (Attribute a : attributes){ // display("attr anem : ", a.getAttributeType().toString()); // } List<Attribute> attrs = ldifEntry.getAttribute("entryUUID"); AttributeValue val = null; if (attrs == null){ for (Attribute a : attributes){ if (a.getName().equals("entryUUID")){ val = a.iterator().next(); } } } else{ val = attrs.get(0).iterator().next(); } String entryUuid = val.toString(); ShadowType anglicaAccount = parseObjectType(new File(ACCOUNT_ANGELIKA_FILENAME), ShadowType.class); PrismProperty<String> prop = anglicaAccount.asPrismObject().findContainer(ShadowType.F_ATTRIBUTES).getValue().createProperty( new PrismPropertyDefinitionImpl<>(getOpenDjPrimaryIdentifierQName(), DOMUtil.XSD_STRING, prismContext)); prop.setValue(new PrismPropertyValue<>(entryUuid)); anglicaAccount.setResourceRef(ObjectTypeUtil.createObjectRef(RESOURCE_OPENDJ_OID, ObjectTypes.RESOURCE)); display("Angelica shadow: ", anglicaAccount.asPrismObject().debugDump()); ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); ObjectDeltaType delta = new ObjectDeltaType(); delta.setChangeType(ChangeTypeType.ADD); delta.setObjectToAdd(anglicaAccount); delta.setObjectType(ShadowType.COMPLEX_TYPE); changeDescription.setObjectDelta(delta); changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); // WHEN TaskType task = modelWeb.notifyChange(changeDescription); // THEN OperationResult result = OperationResult.createOperationResult(task.getResult()); display(result); assertSuccess(result); PrismObject<UserType> userAngelika = findUserByUsername(ANGELIKA_NAME); assertNotNull("User with the name angelika must exist.", userAngelika); UserType user = userAngelika.asObjectable(); assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); String oid = user.getLinkRef().get(0).getOid(); PrismObject<ShadowType> modelShadow = modelService.getObject(ShadowType.class, oid, null, taskManager.createTaskInstance(), result); assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); assertAttribute(modelShadow, "uid", "angelika"); assertAttribute(modelShadow, "givenName", "Angelika"); assertAttribute(modelShadow, "sn", "Marley"); assertAttribute(modelShadow, "cn", "Angelika Marley"); assertShadowLdapPassword(modelShadow, "piranhaDogs"); } @Test public void test501NotifyChangeModifyAccount() throws Exception{ final String TEST_NAME = "test501NotifyChangeModifyAccount"; TestUtil.displayTestTile(TEST_NAME); OperationResult parentResult = new OperationResult(TEST_NAME); PrismObject<UserType> userAngelika = findUserByUsername(ANGELIKA_NAME); assertNotNull("User with the name angelika must exist.", userAngelika); UserType user = userAngelika.asObjectable(); assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); String oid = user.getLinkRef().get(0).getOid(); ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); ObjectDeltaType delta = new ObjectDeltaType(); delta.setChangeType(ChangeTypeType.MODIFY); delta.setObjectType(ShadowType.COMPLEX_TYPE); ItemDeltaType mod1 = new ItemDeltaType(); mod1.setModificationType(ModificationTypeType.REPLACE); ItemPathType path = new ItemPathType(new ItemPath(ShadowType.F_ATTRIBUTES, new QName(resourceTypeOpenDjrepo.getNamespace(), "givenName"))); mod1.setPath(path); RawType value = new RawType(new PrimitiveXNode<String>("newAngelika"), prismContext); mod1.getValue().add(value); delta.getItemDelta().add(mod1); delta.setOid(oid); LOGGER.info("item delta: {}", SchemaDebugUtil.prettyPrint(mod1)); LOGGER.info("delta: {}", DebugUtil.dump(mod1)); changeDescription.setObjectDelta(delta); changeDescription.setOldShadowOid(oid); changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); // WHEN TaskType task = modelWeb.notifyChange(changeDescription); // THEN OperationResult result = OperationResult.createOperationResult(task.getResult()); display(result); assertSuccess(result); PrismObject<UserType> userAngelikaAfterSync = findUserByUsername(ANGELIKA_NAME); assertNotNull("User with the name angelika must exist.", userAngelikaAfterSync); UserType userAfterSync = userAngelikaAfterSync.asObjectable(); PrismAsserts.assertEqualsPolyString("wrong given name in user angelika", PrismTestUtil.createPolyStringType("newAngelika"), userAfterSync.getGivenName()); } @Test public void test502NotifyChangeModifyAccountPassword() throws Exception{ final String TEST_NAME = "test502NotifyChangeModifyAccountPassword"; TestUtil.displayTestTile(TEST_NAME); PrismObject<UserType> userAngelika = findUserByUsername(ANGELIKA_NAME); assertNotNull("User with the name angelika must exist.", userAngelika); UserType user = userAngelika.asObjectable(); assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); String oid = user.getLinkRef().get(0).getOid(); String newPassword = "newPassword"; openDJController.modifyReplace("uid="+ANGELIKA_NAME+","+openDJController.getSuffixPeople(), "userPassword", newPassword); ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); ObjectDeltaType delta = new ObjectDeltaType(); delta.setChangeType(ChangeTypeType.MODIFY); delta.setObjectType(ShadowType.COMPLEX_TYPE); ItemDeltaType passwordDelta = new ItemDeltaType(); passwordDelta.setModificationType(ModificationTypeType.REPLACE); passwordDelta.setPath(ModelClientUtil.createItemPathType("credentials/password/value")); RawType passwordValue = new RawType(((PrismContextImpl) prismContext).getBeanMarshaller().marshall(ModelClientUtil.createProtectedString(newPassword)), prismContext); passwordDelta.getValue().add(passwordValue); delta.getItemDelta().add(passwordDelta); delta.setOid(oid); LOGGER.info("item delta: {}", SchemaDebugUtil.prettyPrint(passwordDelta)); LOGGER.info("delta: {}", DebugUtil.dump(passwordDelta)); changeDescription.setObjectDelta(delta); changeDescription.setOldShadowOid(oid); // changeDescription.setCurrentShadow(angelicaShadowType); changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); // WHEN TaskType task = modelWeb.notifyChange(changeDescription); // THEN OperationResult result = OperationResult.createOperationResult(task.getResult()); display(result); assertSuccess(result); PrismObject<UserType> userAngelikaAfterSync = findUserByUsername(ANGELIKA_NAME); assertNotNull("User with the name angelika must exist.", userAngelikaAfterSync); assertUserLdapPassword(userAngelikaAfterSync, newPassword); } @Test public void test503NotifyChangeDeleteAccount() throws Exception{ final String TEST_NAME = "test503NotifyChangeDeleteAccount"; TestUtil.displayTestTile(TEST_NAME); PrismObject<UserType> userAngelika = findUserByUsername(ANGELIKA_NAME); assertNotNull("User with the name angelika must exist.", userAngelika); UserType user = userAngelika.asObjectable(); assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); String oid = user.getLinkRef().get(0).getOid(); ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); ObjectDeltaType delta = new ObjectDeltaType(); delta.setChangeType(ChangeTypeType.DELETE); delta.setObjectType(ShadowType.COMPLEX_TYPE); delta.setOid(oid); changeDescription.setObjectDelta(delta); changeDescription.setOldShadowOid(oid); changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); // WHEN TaskType task = modelWeb.notifyChange(changeDescription); // THEN OperationResult result = OperationResult.createOperationResult(task.getResult()); display(result); assertTrue(result.isAcceptable()); PrismObject<UserType> userAngelikaAfterSync = findUserByUsername(ANGELIKA_NAME); display("User after", userAngelikaAfterSync); assertNotNull("User with the name angelika must exist.", userAngelikaAfterSync); UserType userType = userAngelikaAfterSync.asObjectable(); assertNotNull("User with the name angelika must have one link ref.", userType.getLinkRef()); assertEquals("Expected no account ref in user", 0, userType.getLinkRef().size()); } @Test public void test999Shutdown() throws Exception { taskManager.shutdown(); waitFor("waiting for task manager shutdown", new Checker() { @Override public boolean check() throws CommonException { try { return taskManager.getLocallyRunningTasks(new OperationResult("dummy")).isEmpty(); } catch (TaskManagerException e) { throw new SystemException(e); } } @Override public void timeout() { // No reaction, the test will fail right after return from this } }, 10000); AssertJUnit.assertEquals("Some tasks left running after shutdown", new HashSet<Task>(), taskManager.getLocallyRunningTasks(new OperationResult("dummy"))); } // TODO: test for missing/corrupt system configuration // TODO: test for missing sample config (bad reference in expression // arguments) private String checkRepoShadow(PrismObject<ShadowType> repoShadow) { ShadowType repoShadowType = repoShadow.asObjectable(); String uid = null; boolean hasOthers = false; List<Object> xmlAttributes = repoShadowType.getAttributes().getAny(); for (Object element : xmlAttributes) { if (SchemaConstants.ICFS_UID.equals(JAXBUtil.getElementQName(element)) || getOpenDjPrimaryIdentifierQName().equals(JAXBUtil.getElementQName(element))) { if (uid != null) { AssertJUnit.fail("Multiple values for ICF UID in shadow attributes"); } else { uid = ((Element) element).getTextContent(); } } else if (SchemaConstants.ICFS_NAME.equals(JAXBUtil.getElementQName(element)) || getOpenDjSecondaryIdentifierQName().equals(JAXBUtil.getElementQName(element))) { // This is OK } else { hasOthers = true; } } assertFalse("Shadow "+repoShadow+" has unexpected elements", hasOthers); assertNotNull(uid); return uid; } private QName getOpenDjPrimaryIdentifierQName() { return new QName(RESOURCE_OPENDJ_NS, RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME); } private QName getOpenDjSecondaryIdentifierQName() { return new QName(RESOURCE_OPENDJ_NS, RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME); } private ShadowType searchAccountByOid(final String accountOid) throws Exception { OperationResultType resultType = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(resultType); Holder<ObjectType> accountHolder = new Holder<ObjectType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountOid, options, accountHolder, resultHolder); ObjectType object = accountHolder.value; TestUtil.assertSuccess("searchObjects has failed", resultHolder.value); assertNotNull("Account is null", object); if (!(object instanceof ShadowType)) { fail("Object is not account."); } ShadowType account = (ShadowType) object; assertEquals(accountOid, account.getOid()); return account; } private UserType searchUserByName(String name) throws Exception { // Document doc = DOMUtil.getDocument(); // Element nameElement = doc.createElementNS(SchemaConstants.C_NAME.getNamespaceURI(), // SchemaConstants.C_NAME.getLocalPart()); // nameElement.setTextContent(name); // Element filter = QueryUtil.createEqualFilter(doc, null, nameElement); // // QueryType query = new QueryType(); // query.setFilter(filter); ObjectQuery q = ObjectQueryUtil.createNameQuery(UserType.class, prismContext, name); QueryType query = QueryJaxbConvertor.createQueryType(q, prismContext); OperationResultType resultType = new OperationResultType(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(resultType); Holder<ObjectListType> listHolder = new Holder<ObjectListType>(); assertNoRepoCache(); modelWeb.searchObjects(ObjectTypes.USER.getTypeQName(), query, null, listHolder, resultHolder); assertNoRepoCache(); ObjectListType objects = listHolder.value; TestUtil.assertSuccess("searchObjects has failed", resultHolder.value); AssertJUnit.assertEquals("User not found (or found too many)", 1, objects.getObject().size()); UserType user = (UserType) objects.getObject().get(0); AssertJUnit.assertEquals(user.getName(), PrismTestUtil.createPolyStringType(name)); return user; } private void basicWaitForSyncChangeDetection(Task syncCycle, Object tokenBefore, int increment, final OperationResult result) throws Exception { basicWaitForSyncChangeDetection(syncCycle, (int)((Integer)tokenBefore), increment, result); } private void basicWaitForSyncChangeDetection(Task syncCycle, int tokenBefore, int increment, final OperationResult result) throws Exception { basicWaitForSyncChangeDetection(syncCycle, tokenBefore, increment, result, 40000); } private void basicWaitForSyncChangeDetection(final Task syncCycle, final int tokenBefore, final int increment, final OperationResult result, int timeout) throws Exception { waitFor("Waiting for sync cycle to detect change", new Checker() { @Override public boolean check() throws CommonException { syncCycle.refresh(result); display("SyncCycle while waiting for sync cycle to detect change", syncCycle); if (syncCycle.getExecutionStatus() != TaskExecutionStatus.RUNNABLE) { throw new IllegalStateException("Task not runnable: "+syncCycle.getExecutionStatus()+"; "+syncCycle); } int tokenNow = findSyncToken(syncCycle); display("tokenNow = " + tokenNow); if (tokenNow >= tokenBefore + increment) { return true; } else { return false; } } @Override public void timeout() { // No reaction, the test will fail right after return from this } }, timeout, WAIT_FOR_LOOP_SLEEP_MILIS); } private void setAssignmentEnforcement(AssignmentPolicyEnforcementType enforcementType) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { assumeAssignmentPolicy(enforcementType); // AccountSynchronizationSettingsType syncSettings = new AccountSynchronizationSettingsType(); // syncSettings.setAssignmentPolicyEnforcement(enforcementType); // applySyncSettings(SystemConfigurationType.class, syncSettings); } private void assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType assignmentPolicy) throws ObjectNotFoundException, SchemaException { OperationResult result = new OperationResult("Asserting sync settings"); PrismObject<SystemConfigurationType> systemConfigurationType = repositoryService.getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, result); result.computeStatus(); TestUtil.assertSuccess("Asserting sync settings failed (result)", result); ProjectionPolicyType globalAccountSynchronizationSettings = systemConfigurationType.asObjectable().getGlobalAccountSynchronizationSettings(); assertNotNull("globalAccountSynchronizationSettings is null", globalAccountSynchronizationSettings); AssignmentPolicyEnforcementType assignmentPolicyEnforcement = globalAccountSynchronizationSettings.getAssignmentPolicyEnforcement(); assertNotNull("assignmentPolicyEnforcement is null", assignmentPolicyEnforcement); assertEquals("Assignment policy mismatch", assignmentPolicy, assignmentPolicyEnforcement); } private void checkAllShadows() throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { LOGGER.trace("Checking all shadows"); System.out.println("Checking all shadows"); ObjectChecker<ShadowType> checker = null; IntegrationTestTools.checkAllShadows(resourceTypeOpenDjrepo, repositoryService, checker, prismContext); } public static String getNormalizedAttributeValue(ShadowType repoShadow, RefinedObjectClassDefinition objClassDef, QName name) { String value = getAttributeValue(repoShadow, name); RefinedAttributeDefinition idDef = objClassDef.getPrimaryIdentifiers().iterator().next(); if (idDef.getMatchingRuleQName() != null && idDef.getMatchingRuleQName().equals(StringIgnoreCaseMatchingRule.NAME)){ return value.toLowerCase(); } return value; } protected <T> void assertAttribute(ShadowType shadowType, String attrName, T... expectedValues) { assertAttribute(resourceTypeOpenDjrepo, shadowType, attrName, expectedValues); } protected <T> void assertAttribute(PrismObject<ShadowType> shadow, String attrName, T... expectedValues) { assertAttribute(resourceTypeOpenDjrepo, shadow.asObjectable(), attrName, expectedValues); } protected <T> void assertAttribute(ShadowType shadowType, QName attrName, T... expectedValues) { assertAttribute(resourceTypeOpenDjrepo, shadowType, attrName, expectedValues); } }