/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2011-2015 ForgeRock AS. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * http://forgerock.org/license/CDDLv1.0.html * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at http://forgerock.org/license/CDDLv1.0.html * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" */ package org.forgerock.openidm.provisioner.openicf.commons; import static org.assertj.core.api.Assertions.assertThat; import static org.forgerock.json.JsonValue.json; import static org.forgerock.json.JsonValue.object; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.refEq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.net.URISyntaxException; import java.net.URL; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import org.forgerock.json.JsonValue; import org.forgerock.json.crypto.JsonCryptoException; import org.forgerock.json.schema.validator.exceptions.SchemaException; import org.forgerock.openidm.crypto.CryptoService; import org.forgerock.openidm.provisioner.openicf.connector.TestConfiguration; import org.forgerock.openidm.provisioner.openicf.connector.TestConnector; import org.forgerock.openidm.util.FileUtil; import org.forgerock.util.encode.Base64; import org.identityconnectors.common.Assertions; import org.identityconnectors.framework.api.APIConfiguration; import org.identityconnectors.framework.api.ConnectorFacade; import org.identityconnectors.framework.api.ConnectorFacadeFactory; import org.identityconnectors.framework.api.operations.APIOperation; import org.identityconnectors.framework.common.objects.ObjectClass; import org.identityconnectors.framework.common.objects.Schema; import org.identityconnectors.framework.common.serializer.SerializerUtil; import org.identityconnectors.framework.impl.api.APIConfigurationImpl; import org.identityconnectors.test.common.TestHelpers; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; /** * Sample Class Doc. */ public class ConnectorUtilTest { private APIConfiguration runtimeAPIConfiguration = null; private JsonValue jsonConfiguration; private static final JsonValue schema = new JsonValue(new HashMap<String, Object>()); private static final String OBJECT_TYPES = "objectTypes"; @BeforeTest public void beforeTest() throws Exception { TestConfiguration configuration = new TestConfiguration(); runtimeAPIConfiguration = TestHelpers.createTestConfiguration(TestConnector.class, configuration); InputStream inputStream = null; try { inputStream = ConnectorUtilTest.class.getResourceAsStream("/config/TestSystemConnectorConfiguration.json"); ObjectMapper mapper = new ObjectMapper(); Map map = mapper.readValue(inputStream, Map.class); jsonConfiguration = new JsonValue(map); } finally { if (null != inputStream) { inputStream.close(); } } assertThat(jsonConfiguration).isNotNull(); } protected ConnectorFacade getFacade() { ConnectorFacadeFactory factory = ConnectorFacadeFactory.getInstance(); // **test only** return factory.newInstance(runtimeAPIConfiguration); } @Test public void testConfigureConfigurationProperties() { Map<String, Object> result = new HashMap<String, Object>(); CryptoService cryptoServiceMock = mock(CryptoService.class); /** * Values from runtimeAPIConfigurations to mock */ JsonValue password = json("Password"); JsonValue passw0rd = json("Passw0rd"); JsonValue password1 = json("Passw0rd1"); JsonValue password2 = json("Passw0rd2"); JsonValue password3 = json("Password3"); JsonValue password4 = json("Password4"); try { /** * Used so that if refEq() is not one of the mocked out cases, * an empty object will be returned instead of NPE */ when(cryptoServiceMock.encrypt(any(JsonValue.class), anyString(), anyString())).thenReturn(json(object())); when(cryptoServiceMock.encrypt(refEq(password) , anyString(), anyString())).thenReturn(json("..encrypted..")); when(cryptoServiceMock.encrypt(refEq(passw0rd) , anyString(), anyString())).thenReturn(json("..encrypted0..")); when(cryptoServiceMock.encrypt(refEq(password1) , anyString(), anyString())).thenReturn(json("..encrypted1..")); when(cryptoServiceMock.encrypt(refEq(password2) , anyString(), anyString())).thenReturn(json("..encrypted2..")); when(cryptoServiceMock.encrypt(refEq(password3) , anyString(), anyString())).thenReturn(json("..encrypted3..")); when(cryptoServiceMock.encrypt(refEq(password4) , anyString(), anyString())).thenReturn(json("..encrypted4..")); ConnectorUtil.setConfigurationProperties(runtimeAPIConfiguration.getConfigurationProperties(), result, cryptoServiceMock); JsonValue jsonResult = new JsonValue(result); assertThat(jsonResult.get("guardedByteArrayArrayValue").isList()).isTrue(); assertThat(jsonResult.get("guardedByteArrayValue").asString()).isEqualTo("..encrypted0.."); assertThat(jsonResult.get("guardedByteArrayArrayValue").get(0).asString()).isEqualTo("..encrypted1.."); assertThat(jsonResult.get("guardedByteArrayArrayValue").get(1).asString()).isEqualTo("..encrypted2.."); assertThat(jsonResult.get("guardedStringValue").asString()).isEqualTo("..encrypted.."); assertThat(jsonResult.get("guardedStringArrayValue").get(0).asString()).isEqualTo("..encrypted3.."); assertThat(jsonResult.get("guardedStringArrayValue").get(1).asString()).isEqualTo("..encrypted4.."); } catch (JsonCryptoException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } //@Test public void testGetConfiguration() throws Exception { JsonValue target = new JsonValue(new LinkedHashMap<String, Object>()); ConnectorUtil.createSystemConfigurationFromAPIConfiguration(runtimeAPIConfiguration, target, null); APIConfiguration clonedConfiguration = getRuntimeAPIConfiguration(); ConnectorUtil.configureDefaultAPIConfiguration(new JsonValue(target), clonedConfiguration, null); //Assert.assertEquals(clonedConfiguration, runtimeAPIConfiguration); ObjectMapper mapper = new ObjectMapper(); URL root = ConnectorUtilTest.class.getResource("/"); mapper.writeValue(new File((new URL(root, "runtimeAPIConfiguration.json")).toURI()), target); } @Test public void testGetAPIConfiguration() throws Exception { APIConfiguration clonedConfiguration = getRuntimeAPIConfiguration(); ConnectorUtil.configureDefaultAPIConfiguration(jsonConfiguration, clonedConfiguration, null); // "enableFilteredResultsHandler":false" assertThat(clonedConfiguration.getResultsHandlerConfiguration().isEnableFilteredResultsHandler()).isFalse(); } @Test public void testGetSchema() { ConnectorFacade connectorFacade = getFacade(); Schema schema = connectorFacade.schema(); assertThat(schema).isNotNull(); JsonValue schemaMAP = new JsonValue(new LinkedHashMap<String, Object>(2)); ConnectorUtil.setObjectAndOperationConfiguration(schema, schemaMAP); try { ObjectMapper mapper = new ObjectMapper(); URL root = ConnectorUtilTest.class.getResource("/"); mapper.writeValue(new File((new URL(root, "schema.json")).toURI()), schemaMAP); } catch (Exception e) { e.printStackTrace(); } } // @Test // public void testOperationalSchema() throws Exception { // InputStream inputStream = ConnectorUtilTest.class.getResourceAsStream("/config/SystemSchemaConfiguration.json"); // Assert.assertNotNull(inputStream); // ObjectMapper mapper = new ObjectMapper(); // JsonValue configuration = new JsonValue(mapper.readValue(inputStream, Map.class)); // Map<String, Map<Class<? extends APIOperation>, OperationOptionInfoHelper>> operationOptionHelpers = ConnectorUtil.getOperationOptionConfiguration(configuration); // ObjectClassInfoHelper objectClassInfoHelper = org.mockito.Mockito.mock(ObjectClassInfoHelper.class); // org.mockito.Mockito.when(objectClassInfoHelper.getObjectClass()).thenReturn(new ObjectClass("__ACCOUNT__")); // OperationHelper helper = new OperationHelper(new Id("system/TEST/account"), objectClassInfoHelper, operationOptionHelpers.get("__ACCOUNT__"), null); // // Assert.assertTrue(helper.isOperationPermitted(CreateApiOp.class), "Create - ALLOWED"); // Assert.assertFalse(helper.isOperationPermitted(SyncApiOp.class), "Sync - DENIED"); // // boolean authenticated = true; // try { // helper.isOperationPermitted(AuthenticationApiOp.class); // } catch (JsonResourceException e) { // authenticated = false; // } // Assert.assertFalse(authenticated, "Authentication - DENIED(Exception)"); // // boolean operationSupported = true; // try { // helper.isOperationPermitted(ScriptOnResourceApiOp.class); // } catch (JsonResourceException e) { // operationSupported = false; // } // Assert.assertFalse(operationSupported, "ScriptOnResource - NotSupported(Exception)"); // // Assert.assertFalse(helper.isOperationPermitted(ScriptOnConnectorApiOp.class), "ScriptOnConnector - DENIED"); // Assert.assertFalse(helper.isOperationPermitted(SearchApiOp.class), "Search - DENIED"); // } // // // @Test // public void testAPIConfiguration() throws JsonValueException, SchemaException, URISyntaxException, JsonResourceException { // ConnectorReference connectorReference = ConnectorUtil.getConnectorReference(jsonConfiguration); // Assert.assertEquals(connectorReference.getConnectorHost(), ConnectorReference.SINGLE_LOCAL_CONNECTOR_MANAGER); // ConnectorKey key = connectorReference.getConnectorKey(); // Assert.assertEquals(key.getBundleName(), "org.identityconnectors.ldap"); // Assert.assertEquals(key.getBundleVersion(), "1.0.5531"); // Assert.assertEquals(key.getConnectorName(), "org.identityconnectors.ldap.LdapConnector"); // // SystemIdentifier systemIdentifier = new SimpleSystemIdentifier(jsonConfiguration); // Assert.assertTrue(systemIdentifier.is(new Id("http://openidm.forgerock.org/openidm/system/LDAP_Central/user/CA2B382A-6FFB-11E0-80B7-902C4824019B"))); // Assert.assertTrue(systemIdentifier.is(new Id("system/LDAP_Central/account/"))); // Assert.assertFalse(systemIdentifier.is(new Id("http://openidm.forgerock.org/openidm/system/LDAP_None/user/CA2B382A-6FFB-11E0-80B7-902C4824019B"))); // Assert.assertFalse(systemIdentifier.is(new Id("system/LDAP_None/account"))); // // OperationHelperBuilder operationHelperBuilder = new OperationHelperBuilder(((SimpleSystemIdentifier) systemIdentifier).getName(), jsonConfiguration, runtimeAPIConfiguration); // // OperationHelper helper = operationHelperBuilder.build("__ACCOUNT__", null, null); // Assert.assertEquals(helper.getObjectClass().getObjectClassValue(), "__ACCOUNT__"); // } // // @Test(expectedExceptions = JsonResourceException.class, expectedExceptionsMessageRegExp = ".*__NONE__.*") // public void testUnsupportedObjectType() throws JsonValueException, SchemaException, URISyntaxException, JsonResourceException { // OperationHelperBuilder operationHelperBuilder = new OperationHelperBuilder("test", jsonConfiguration, runtimeAPIConfiguration); // OperationHelper helper = operationHelperBuilder.build("__NONE__", null, null); // } @Test public void testCoercedTypeCasting() throws Exception { BigInteger bigInteger = ConnectorUtil.coercedTypeCasting(new Integer(20), BigInteger.class); assertThat(bigInteger.intValue()).isEqualTo(20); Boolean booleanValue = ConnectorUtil.coercedTypeCasting("true",boolean.class); assertThat(booleanValue).isTrue(); Integer integerValue = ConnectorUtil.coercedTypeCasting("636",int.class); assertThat(integerValue).isEqualTo((Integer) 636); float floatValue = ConnectorUtil.coercedTypeCasting("636",float.class); assertThat(floatValue).isEqualTo(636.0f); } @Test void testCoercedTypeCastingForByte() { // String -> Byte Byte byteValueFromString = ConnectorUtil.coercedTypeCasting("100", Byte.class); assertThat(byteValueFromString.byteValue()).isEqualTo(new Byte("100")); // Integer -> Byte Byte byteValueFromNumber = ConnectorUtil.coercedTypeCasting(10, Byte.class); assertThat(byteValueFromNumber.byteValue()).isEqualTo(new Byte("10")); // Byte -> Byte Byte byteValueFromBoxedByte = ConnectorUtil.coercedTypeCasting(new Byte("124"), Byte.class); assertThat(byteValueFromBoxedByte.byteValue()).isEqualTo(new Byte("124")); // byte -> Byte Byte byteValueFromPrimitiveByte = ConnectorUtil.coercedTypeCasting((byte) 10, Byte.class); assertThat(byteValueFromPrimitiveByte.byteValue()).isEqualTo((byte) 10); // Byte -> String String stringFromBoxedByte = ConnectorUtil.coercedTypeCasting(new Byte("10"), String.class); assertThat(stringFromBoxedByte).isEqualTo(Base64.encode(new byte[] {new Byte("10")})); // byte -> String String stringFromPrimitiveByte = ConnectorUtil.coercedTypeCasting((byte) 10, String.class); assertThat(stringFromPrimitiveByte).isEqualTo(Base64.encode(new byte[] {(byte)10})); } @Test void testCoercedTypeCastingForByteType() { // String -> byte byte byteValueFromString = ConnectorUtil.coercedTypeCasting("100", Byte.TYPE); assertThat(byteValueFromString).isEqualTo(Byte.parseByte("100")); //Integer -> byte byte byteValueFromNumber = ConnectorUtil.coercedTypeCasting(10, Byte.TYPE); assertThat(byteValueFromNumber).isEqualTo(Byte.parseByte("10")); // Byte -> byte byte byteValueFromBoxedByte = ConnectorUtil.coercedTypeCasting(new Byte("124"), Byte.TYPE); assertThat(byteValueFromBoxedByte).isEqualTo(new Byte("124")); // byte -> byte byte byteValueFromPrimitiveByte = ConnectorUtil.coercedTypeCasting((byte) 10, Byte.TYPE); assertThat(byteValueFromPrimitiveByte).isEqualTo((byte) 10); } public APIConfiguration getRuntimeAPIConfiguration() { Assertions.nullCheck(runtimeAPIConfiguration, "runtimeAPIConfiguration"); //clone in case application tries to modify //after the fact. this is necessary to //ensure thread-safety of a ConnectorFacade //also, runtimeAPIConfiguration is used as a key in the //pool, so it is important that it not be modified. APIConfigurationImpl _configuration = (APIConfigurationImpl) SerializerUtil.cloneObject(runtimeAPIConfiguration); //parent ref not included in the clone _configuration.setConnectorInfo(((APIConfigurationImpl) runtimeAPIConfiguration).getConnectorInfo()); return _configuration; } private static JsonValue toJsonValue(String json) throws IOException { final ObjectMapper mapper = new ObjectMapper(); return new JsonValue(mapper.readValue(json, Map.class)); } @Test public void testGetObjectTypes() throws URISyntaxException, IOException { //GIVEN schema.put(OBJECT_TYPES, toJsonValue(FileUtil.readFile(new File( new File(ConnectorUtilTest.class.getResource("/").toURI()), "/config/objectClassSchema.json")))); schema.get(OBJECT_TYPES).remove("ALL_FAIL"); //change name of __ALL__ object class schema.get(OBJECT_TYPES).put("all", schema.get(OBJECT_TYPES).get(ObjectClass.ALL_NAME)); schema.get(OBJECT_TYPES).remove(ObjectClass.ALL_NAME); //WHEN Map<String, ObjectClassInfoHelper> objectTypes = ConnectorUtil.getObjectTypes(schema); //THEN //check that the object classes in the schema exist assertThat(objectTypes.containsKey("all")); assertThat(objectTypes.containsKey(ObjectClass.GROUP_NAME)); assertThat(objectTypes.containsKey(ObjectClass.ACCOUNT_NAME)); assertThat(objectTypes.containsKey("__TEST__")); assertThat(objectTypes.containsKey("CUSTOM")); } @Test public void testGetObjectTypesAddsAllObjectClassByDefault() throws URISyntaxException, IOException { //GIVEN schema.put(OBJECT_TYPES, toJsonValue(FileUtil.readFile(new File( new File(ConnectorUtilTest.class.getResource("/").toURI()), "/config/objectClassSchema.json")))); schema.get(OBJECT_TYPES).remove("ALL_FAIL"); //remove __ALL__ object class from schema schema.get(OBJECT_TYPES).remove(ObjectClass.ALL_NAME); //WHEN Map<String, ObjectClassInfoHelper> objectTypes = ConnectorUtil.getObjectTypes(schema); //THEN //check that the __ALL__ object class was added by default assertThat(objectTypes.containsKey(ObjectClass.ALL_NAME)); } @Test(expectedExceptions = SchemaException.class) public void testGetObjectTypesWithoutAllObjectClassWithTheAllObjectClassNameTaken() throws URISyntaxException, IOException { //GIVEN schema.put(OBJECT_TYPES, toJsonValue(FileUtil.readFile(new File( new File(ConnectorUtilTest.class.getResource("/").toURI()), "/config/objectClassSchema.json")))); schema.get(OBJECT_TYPES).remove("ALL_FAIL"); //use the __ALL__ object class name on another objectclass schema.get(OBJECT_TYPES).remove(ObjectClass.ALL_NAME); schema.get(OBJECT_TYPES).put(ObjectClass.ALL_NAME, schema.get(OBJECT_TYPES).get("CUSTOM")); schema.get(OBJECT_TYPES).remove("CUSTOM"); //WHEN //try to get object types and fail ConnectorUtil.getObjectTypes(schema); //THEN } @Test public void testGetOperationOptionConfiguration() throws URISyntaxException, IOException { //GIVEN schema.put(OBJECT_TYPES, toJsonValue(FileUtil.readFile(new File( new File(ConnectorUtilTest.class.getResource("/").toURI()), "/config/objectClassSchema.json")))); schema.get(OBJECT_TYPES).remove("ALL_FAIL"); //WHEN Map<String, Map<Class<? extends APIOperation>, OperationOptionInfoHelper>> operationOptionConfiguration = ConnectorUtil.getOperationOptionConfiguration(schema); //THEN assertThat(operationOptionConfiguration.keySet().contains("all")); assertThat(operationOptionConfiguration.keySet().contains(ObjectClass.GROUP_NAME)); assertThat(operationOptionConfiguration.keySet().contains(ObjectClass.ACCOUNT_NAME)); assertThat(operationOptionConfiguration.keySet().contains("__TEST__")); assertThat(operationOptionConfiguration.keySet().contains("CUSTOM")); } }