mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Guy Paddock
27.26.2017 71a180997c65b0b5d23453e1985ecc6225bb4a42
Extends configurator for search filter support

- Adds logic to configure base search filter using the new `baseSearchFilter` option for collection sub-resources.
- Re-factors a bit of sub-resource configuration to make the code easier to follow and less of a mess.
4 files modified
154 ■■■■ changed files
opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/example-v1.json 6 ●●●●● patch | view | raw | blame | history
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfigurator.java 37 ●●●● patch | view | raw | blame | history
opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfiguratorTest.java 105 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/resource/config/rest2ldap/endpoints/api/example-v1.json 6 ●●●●● patch | view | raw | blame | history
opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/example-v1.json
@@ -35,7 +35,8 @@
                },
                // This resource provides a read-only view of all users in the system, including
                // users nested underneath entries like org units, organizations, etc., starting
                // from "ou=people,dc=example,dc=com" and working down.
                // from "ou=people,dc=example,dc=com" and working down. It filters out any other
                // structural elements, including organizations, org units, etc.
                "all-users": {
                    "type": "collection",
                    "dnTemplate": "ou=people,dc=example,dc=com",
@@ -45,7 +46,8 @@
                        "dnAttribute": "uid"
                    },
                    "isReadOnly": true,
                    "flattenSubtree": true
                    "flattenSubtree": true,
                    "baseSearchFilter": "(objectClass=person)"
                },
                "groups": {
                    "type": "collection",
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfigurator.java
@@ -311,27 +311,49 @@
        final String dnTemplate = config.get("dnTemplate").defaultTo("").asString();
        final Boolean isReadOnly = config.get("isReadOnly").defaultTo(false).asBoolean();
        final String resourceId = config.get("resource").required().asString();
        final Boolean flattenSubtree =
            config.get("flattenSubtree").defaultTo(false).asBoolean();
        final SubResourceType subResourceType =
          config.get("type").required().as(enumConstant(SubResourceType.class));
        if (subResourceType == SubResourceType.COLLECTION) {
            return configureCollectionSubResource(
                config, resourceId, urlTemplate, dnTemplate, isReadOnly);
        } else {
            return configureSingletonSubResource(
                config, resourceId, urlTemplate, dnTemplate, isReadOnly);
        }
    }
    private static SubResource configureCollectionSubResource(final JsonValue config,
                                                              final String resourceId,
                                                              final String urlTemplate,
                                                              final String dnTemplate,
                                                              final Boolean isReadOnly) {
            final String[] glueObjectClasses =
                config.get("glueObjectClasses")
                    .defaultTo(emptyList())
                    .asList(String.class)
                    .toArray(new String[0]);
        final Boolean flattenSubtree = config.get("flattenSubtree").defaultTo(false).asBoolean();
        final String searchFilter = config.get("baseSearchFilter").asString();
            final SubResourceCollection collection =
                collectionOf(resourceId)
                    .urlTemplate(urlTemplate)
                    .dnTemplate(dnTemplate)
                    .isReadOnly(isReadOnly)
                    .glueObjectClasses(glueObjectClasses)
                    .flattenSubtree(flattenSubtree);
                .flattenSubtree(flattenSubtree)
                .baseSearchFilter(searchFilter);
        configureCollectionNamingStrategy(config, collection);
        return collection;
    }
    private static void configureCollectionNamingStrategy(final JsonValue config,
                                                          final SubResourceCollection collection) {
            final JsonValue namingStrategy = config.get("namingStrategy").required();
            final NamingStrategyType namingStrategyType =
                namingStrategy.get("type").required().as(enumConstant(NamingStrategyType.class));
@@ -349,15 +371,18 @@
                                           namingStrategy.get("idAttribute").required().asString());
                break;
            }
    }
            return collection;
        } else {
    private static SubResource configureSingletonSubResource(final JsonValue config,
                                                             final String resourceId,
                                                             final String urlTemplate,
                                                             final String dnTemplate,
                                                             final Boolean isReadOnly) {
            return singletonOf(resourceId)
                        .urlTemplate(urlTemplate)
                        .dnTemplate(dnTemplate)
                        .isReadOnly(isReadOnly);
        }
    }
    private static PropertyMapper configurePropertyMapper(final JsonValue mapper, final String defaultLdapAttribute) {
        switch (mapper.get("type").required().asString()) {
opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Rest2LdapJsonConfiguratorTest.java
@@ -41,6 +41,7 @@
import org.forgerock.json.JsonValue;
import org.forgerock.json.resource.Request;
import org.forgerock.json.resource.RequestHandler;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.services.context.Context;
import org.forgerock.services.context.RootContext;
import org.forgerock.testng.ForgeRockTestCase;
@@ -136,7 +137,7 @@
    }
    @DataProvider
    public Object[][] invalidSubResourceConfigurations() {
    public Object[][] invalidSubResourceSubtreeFlatteningConfigurations() {
        // @Checkstyle:off
        return new Object[][] {
                {
@@ -187,6 +188,48 @@
                {
                        false,
                        false,
                        null,
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
                                                + "'all-users': {"
                                                        + "'type': 'collection',"
                                                        + "'dnTemplate': 'ou=people,dc=example,dc=com',"
                                                        + "'resource': 'frapi:opendj:rest2ldap:user:1.0',"
                                                        + "'namingStrategy': {"
                                                            + "'type': 'clientDnNaming',"
                                                            + "'dnAttribute': 'uid'"
                                                        + "}"
                                                + "}"
                                        + "}"
                                + "}"
                        + "}"
                },
                {
                        false,
                        false,
                        "(objectClass=person)",
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
                                                + "'all-users': {"
                                                        + "'type': 'collection',"
                                                        + "'dnTemplate': 'ou=people,dc=example,dc=com',"
                                                        + "'resource': 'frapi:opendj:rest2ldap:user:1.0',"
                                                        + "'namingStrategy': {"
                                                            + "'type': 'clientDnNaming',"
                                                            + "'dnAttribute': 'uid'"
                                                        + "},"
                                                        + "'baseSearchFilter': '(objectClass=person)'"
                                                + "}"
                                        + "}"
                                + "}"
                        + "}"
                },
                {
                        false,
                        false,
                        null,
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
@@ -207,6 +250,7 @@
                {
                        true,
                        false,
                        null,
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
@@ -227,6 +271,7 @@
                {
                        true,
                        false,
                        null,
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
@@ -248,6 +293,7 @@
                {
                        false,
                        false,
                        null,
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
@@ -269,6 +315,7 @@
                {
                        true,
                        true,
                        null,
                        "{"
                                + "'example-v1': {"
                                        + "'subResources': {"
@@ -291,8 +338,9 @@
        // @Checkstyle:on
    }
    @Test(dataProvider = "invalidSubResourceConfigurations")
    public void testInvalidSubResourceConfigurations(final String rawJson) throws Exception {
    @Test(dataProvider = "invalidSubResourceSubtreeFlatteningConfigurations")
    public void testInvalidSubResourceSubtreeFlatteningConfigurations(final String rawJson)
    throws Exception {
        try {
            Rest2LdapJsonConfigurator.configureResources(parseJson(rawJson));
@@ -304,9 +352,44 @@
        }
    }
    @Test
    public void testInvalidSubResourceSearchFilterConfigurations()
    throws Exception {
        final String rawJson =
            "{"
                    + "'example-v1': {"
                            + "'subResources': {"
                                    + "'all-users': {"
                                            + "'type': 'collection',"
                                            + "'dnTemplate': 'ou=people,dc=example,dc=com',"
                                            + "'resource': 'frapi:opendj:rest2ldap:user:1.0',"
                                            + "'namingStrategy': {"
                                                + "'type': 'clientDnNaming',"
                                                + "'dnAttribute': 'uid'"
                                            + "},"
                                            + "'baseSearchFilter': 'badFilter'"
                                    + "}"
                            + "}"
                    + "}"
            + "}";
        try {
            Rest2LdapJsonConfigurator.configureResources(parseJson(rawJson));
            fail("Expected an IllegalArgumentException");
        }
        catch (IllegalArgumentException ex) {
            assertThat(ex.getMessage())
                .isEqualTo(
                    "The provided search filter \"badFilter\" was missing an equal sign in the " +
                    "suspected simple filter component between positions 0 and 9");
        }
    }
    @Test(dataProvider = "validSubResourceConfigurations")
    public void testValidSubResourceConfigurations(final boolean expectingReadOnly,
                                                   final boolean expectingSubtreeFlattened,
    public void testValidSubResourceConfigurations(final boolean expectedReadOnly,
                                                   final boolean expectedSubtreeFlattened,
                                                   final String expectedSearchFilter,
                                                   final String rawJson) throws Exception {
        final List<org.forgerock.opendj.rest2ldap.Resource> resources =
            Rest2LdapJsonConfigurator.configureResources(parseJson(rawJson));
@@ -326,8 +409,16 @@
        allUsersSubResource = (SubResourceCollection)subResources.get("all-users");
        assertThat(allUsersSubResource.isReadOnly()).isEqualTo(expectingReadOnly);
        assertThat(allUsersSubResource.shouldFlattenSubtree()).isEqualTo(expectingSubtreeFlattened);
        assertThat(allUsersSubResource.isReadOnly()).isEqualTo(expectedReadOnly);
        assertThat(allUsersSubResource.shouldFlattenSubtree()).isEqualTo(expectedSubtreeFlattened);
        if (expectedSearchFilter == null) {
            assertThat(allUsersSubResource.getBaseSearchFilter()).isNull();
        }
        else {
            assertThat(allUsersSubResource.getBaseSearchFilter().toString())
                .isEqualTo(expectedSearchFilter);
        }
    }
    private RequestHandler createRequestHandler(final File endpointsDir) throws IOException {
opendj-server-legacy/resource/config/rest2ldap/endpoints/api/example-v1.json
@@ -35,7 +35,8 @@
                },
                // This resource provides a read-only view of all users in the system, including
                // users nested underneath entries like org units, organizations, etc., starting
                // from "ou=people,dc=example,dc=com" and working down.
                // from "ou=people,dc=example,dc=com" and working down. It filters out any other
                // structural elements, including organizations, org units, etc.
                "all-users": {
                    "type": "collection",
                    "dnTemplate": "ou=people,dc=example,dc=com",
@@ -45,7 +46,8 @@
                        "dnAttribute": "uid"
                    },
                    "isReadOnly": true,
                    "flattenSubtree": true
                    "flattenSubtree": true,
                    "baseSearchFilter": "(objectClass=person)"
                },
                "groups": {
                    "type": "collection",