From fad88bae0655787d9030d4f313c0a0dfcf2e47bb Mon Sep 17 00:00:00 2001
From: Guy Paddock <guy@rosieapp.com>
Date: Fri, 27 Oct 2017 04:49:37 +0000
Subject: [PATCH] Sub-resource search filter support
---
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceCollection.java | 53 ++++++
opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/BasicRequestsTest.java | 330 +++++++++++++++++++++++++++++++---------
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceSingleton.java | 7
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java | 39 ++++
4 files changed, 344 insertions(+), 85 deletions(-)
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceCollection.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceCollection.java
index 85fd139..05b2720 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceCollection.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceCollection.java
@@ -15,6 +15,7 @@
*/
package org.forgerock.opendj.rest2ldap;
+import static org.forgerock.guava.common.base.Preconditions.checkNotNull;
import static org.forgerock.http.routing.RoutingMode.EQUALS;
import static org.forgerock.http.routing.RoutingMode.STARTS_WITH;
import static org.forgerock.json.resource.RouteMatchers.requestUriMatcher;
@@ -75,6 +76,7 @@
private NamingStrategy namingStrategy;
private boolean flattenSubtree;
+ private Filter baseSearchFilter;
SubResourceCollection(final String resourceId) {
super(resourceId);
@@ -94,6 +96,18 @@
}
/**
+ * Gets the base filter that always restricts what LDAP entries are accessible through this
+ * collection, before any filters are applied from the request itself.
+ *
+ * The default is {@code null} (no base filter restriction at all).
+ *
+ * @return Either a search filter; or {@code null} if no base search filter has been defined.
+ */
+ public Filter getBaseSearchFilter() {
+ return baseSearchFilter;
+ }
+
+ /**
* Indicates that the JSON resource ID must be provided by the user, and will be used for naming the associated LDAP
* entry. More specifically, LDAP entry names will be derived by appending a single RDN to the collection's base DN
* composed of the specified attribute type and LDAP value taken from the LDAP entry once attribute mapping has been
@@ -259,6 +273,42 @@
return this;
}
+ /**
+ * Sets the base filter that always restricts what LDAP entries are accessible through this
+ * collection, before any filters are applied from the request itself.
+ *
+ * The default is {@code null} (no base filter restriction at all).
+ *
+ * @param filter
+ * The filter which should be used to restrict which LDAP entries are returned.
+ * @return A reference to this object.
+ */
+ public SubResourceCollection baseSearchFilter(final Filter filter) {
+ this.baseSearchFilter = filter;
+ return this;
+ }
+
+ /**
+ * Sets the base filter that always restricts what LDAP entries are accessible through this
+ * collection, before any filters are applied from the request itself.
+ *
+ * The default is {@code null} (no base filter restriction at all).
+ *
+ * @param filter
+ * The filter which should be used to restrict which LDAP entries are returned.
+ * @return A reference to this object.
+ */
+ public SubResourceCollection baseSearchFilter(final String filter) {
+ if (filter == null) {
+ baseSearchFilter((Filter)null);
+ }
+ else {
+ baseSearchFilter(Filter.valueOf(filter));
+ }
+
+ return this;
+ }
+
@Override
Router addRoutes(final Router router) {
router.addRoute(requestUriMatcher(EQUALS, urlTemplate), readOnly(new CollectionHandler()));
@@ -299,7 +349,8 @@
dnTemplateString.isEmpty() ? null : glueObjectClasses,
namingStrategy,
resource,
- this.flattenSubtree);
+ flattenSubtree,
+ baseSearchFilter);
}
private String idFrom(final Context context) {
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java
index 127ee64..4b65ea9 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java
@@ -140,10 +140,16 @@
private final Resource resource;
private final Attribute glueObjectClasses;
private final boolean flattenSubtree;
+ private Filter baseSearchFilter;
+
+ SubResourceImpl(final Rest2Ldap rest2Ldap, final DN baseDn, final Attribute glueObjectClasses,
+ final NamingStrategy namingStrategy, final Resource resource) {
+ this(rest2Ldap, baseDn, glueObjectClasses, namingStrategy, resource, false, null);
+ }
SubResourceImpl(final Rest2Ldap rest2Ldap, final DN baseDn, final Attribute glueObjectClasses,
final NamingStrategy namingStrategy, final Resource resource,
- final boolean flattenSubtree) {
+ final boolean flattenSubtree, final Filter baseSearchFilter) {
this.readOnUpdatePolicy = rest2Ldap.getOptions().get(READ_ON_UPDATE_POLICY);
this.useSubtreeDelete = rest2Ldap.getOptions().get(USE_SUBTREE_DELETE);
this.usePermissiveModify = rest2Ldap.getOptions().get(USE_PERMISSIVE_MODIFY);
@@ -155,6 +161,7 @@
this.namingStrategy = namingStrategy;
this.resource = resource;
this.flattenSubtree = flattenSubtree;
+ this.baseSearchFilter = baseSearchFilter;
}
Promise<ActionResponse, ResourceException> action(
@@ -506,9 +513,34 @@
Promise<QueryResponse, ResourceException> query(
final Context context, final QueryRequest request, final QueryResourceHandler resourceHandler) {
return getLdapFilter(context, request.getQueryFilter())
+ .then(applyBaseSearchFilter())
.thenAsync(runQuery(context, request, resourceHandler));
}
+ /**
+ * Generates a function that applies any base filter that this sub-resource may have been
+ * initialized with.
+ *
+ * @return The function to invoke to apply a base filter, if one has been specified.
+ */
+ private Function<Filter, Filter, ResourceException> applyBaseSearchFilter() {
+ return new Function<Filter, Filter, ResourceException>() {
+ @Override
+ public Filter apply(final Filter requestFilter) throws ResourceException {
+ final Filter baseSearchFilter = SubResourceImpl.this.baseSearchFilter,
+ searchFilter;
+
+ if (baseSearchFilter != null) {
+ searchFilter = Filter.and(baseSearchFilter, requestFilter);
+ } else {
+ searchFilter = requestFilter;
+ }
+
+ return searchFilter;
+ }
+ };
+ }
+
// FIXME: supporting assertions against sub-type properties.
private Promise<Filter, ResourceException> getLdapFilter(
final Context context, final QueryFilter<JsonPointer> queryFilter) {
@@ -525,6 +557,7 @@
public Promise<Filter, ResourceException> visitAndFilter(
final Void unused, final List<QueryFilter<JsonPointer>> subFilters) {
final List<Promise<Filter, ResourceException>> promises = new ArrayList<>(subFilters.size());
+
for (final QueryFilter<JsonPointer> subFilter : subFilters) {
promises.add(subFilter.accept(this, unused));
}
@@ -534,14 +567,17 @@
public Filter apply(final List<Filter> value) {
// Check for unmapped filter components and optimize.
final Iterator<Filter> i = value.iterator();
+
while (i.hasNext()) {
final Filter f = i.next();
+
if (f == alwaysFalse()) {
return alwaysFalse();
} else if (f == alwaysTrue()) {
i.remove();
}
}
+
switch (value.size()) {
case 0:
return alwaysTrue();
@@ -675,6 +711,7 @@
parentDnAndType, resource, ROOT, field, STARTS_WITH, null, valueAssertion);
}
};
+
// Note that the returned LDAP filter may be null if it could not be mapped by any property mappers.
return queryFilter.accept(visitor, null);
}
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceSingleton.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceSingleton.java
index 1e8bc86..92a1f33 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceSingleton.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceSingleton.java
@@ -140,12 +140,7 @@
private SubResourceImpl singleton(final Context context) {
return new SubResourceImpl(
- rest2Ldap,
- dnFrom(context),
- null,
- SINGLETON_NAMING_STRATEGY,
- resource,
- false);
+ rest2Ldap, dnFrom(context), null, SINGLETON_NAMING_STRATEGY, resource);
}
/**
diff --git a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/BasicRequestsTest.java b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/BasicRequestsTest.java
index 208023f..cb1bab0 100644
--- a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/BasicRequestsTest.java
+++ b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/BasicRequestsTest.java
@@ -93,7 +93,7 @@
private static final QueryFilter<JsonPointer> NO_FILTER = QueryFilter.alwaysTrue();
@Test
- public void testQueryAllWithNoSubtreeFlattening() throws Exception {
+ public void testQueryAllWithNoSubtreeFlatteningAndNoSearchFilter() throws Exception {
final Connection connection = newConnection();
final List<ResourceResponse> resources = new LinkedList<>();
final QueryResponse result =
@@ -106,30 +106,75 @@
assertThat(result.getPagedResultsCookie()).isNull();
assertThat(result.getTotalPagedResults()).isEqualTo(-1);
- assertThat(resources.get(0).getContent().get("_ou").isNotNull());
- assertThat(resources.get(0).getContent().get("_ou").asString()).isEqualTo("level1");
+ checkThatOrgUnitsExist(resources, "level1");
- assertThat(resources.get(1).getContent().get("_ou").isNull());
- assertThat(resources.get(1).getId()).isEqualTo("test1");
-
- assertThat(resources.get(2).getContent().get("_ou").isNull());
- assertThat(resources.get(2).getId()).isEqualTo("test2");
-
- assertThat(resources.get(3).getContent().get("_ou").isNull());
- assertThat(resources.get(3).getId()).isEqualTo("test3");
-
- assertThat(resources.get(4).getContent().get("_ou").isNull());
- assertThat(resources.get(4).getId()).isEqualTo("test4");
-
- assertThat(resources.get(5).getContent().get("_ou").isNull());
- assertThat(resources.get(5).getId()).isEqualTo("test5");
-
- assertThat(resources.get(6).getContent().get("_ou").isNull());
- assertThat(resources.get(6).getId()).isEqualTo("test6");
+ checkThatUsersExist(resources, 1,
+ "test1",
+ "test2",
+ "test3",
+ "test4",
+ "test5",
+ "test6"
+ );
}
@Test
- public void testQueryAllWithSubtreeFlattening() throws Exception {
+ public void testQueryAllWithSearchFilterAndNoSubtreeFlattening() throws Exception {
+ final Connection connection = newConnection();
+ final List<ResourceResponse> resources = new LinkedList<>();
+ final QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("top-level-users").setQueryFilter(NO_FILTER),
+ resources);
+
+ assertThat(resources).hasSize(6);
+ assertThat(result.getPagedResultsCookie()).isNull();
+ assertThat(result.getTotalPagedResults()).isEqualTo(-1);
+
+ checkThatUsersExist(resources,
+ "test1",
+ "test2",
+ "test3",
+ "test4",
+ "test5",
+ "test6"
+ );
+ }
+
+ @Test
+ public void testQueryAllWithSubtreeFlatteningAndNoSearchFilter() throws Exception {
+ final Connection connection = newConnection();
+ final List<ResourceResponse> resources = new LinkedList<>();
+ final QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("all-entries").setQueryFilter(NO_FILTER),
+ resources);
+
+ assertThat(resources).hasSize(10);
+ assertThat(result.getPagedResultsCookie()).isNull();
+ assertThat(result.getTotalPagedResults()).isEqualTo(-1);
+
+ checkThatOrgUnitsExist(resources,
+ "level1",
+ "level2"
+ );
+
+ checkThatUsersExist(resources, 2,
+ "sub2",
+ "sub1",
+ "test1",
+ "test2",
+ "test3",
+ "test4",
+ "test5",
+ "test6"
+ );
+ }
+
+ @Test
+ public void testQueryAllWithSubtreeFlatteningAndSearchFilter() throws Exception {
final Connection connection = newConnection();
final List<ResourceResponse> resources = new LinkedList<>();
final QueryResponse result =
@@ -138,47 +183,31 @@
newQueryRequest("all-users").setQueryFilter(NO_FILTER),
resources);
- assertThat(resources).hasSize(10);
+ assertThat(resources).hasSize(8);
assertThat(result.getPagedResultsCookie()).isNull();
assertThat(result.getTotalPagedResults()).isEqualTo(-1);
- assertThat(resources.get(0).getContent().get("_ou").isNotNull());
- assertThat(resources.get(0).getContent().get("_ou").asString()).isEqualTo("level1");
-
- assertThat(resources.get(1).getContent().get("_ou").isNotNull());
- assertThat(resources.get(1).getContent().get("_ou").asString()).isEqualTo("level2");
-
- assertThat(resources.get(2).getContent().get("_ou").isNull());
- assertThat(resources.get(2).getId()).isEqualTo("sub2");
-
- assertThat(resources.get(3).getContent().get("_ou").isNull());
- assertThat(resources.get(3).getId()).isEqualTo("sub1");
-
- assertThat(resources.get(4).getContent().get("_ou").isNull());
- assertThat(resources.get(4).getId()).isEqualTo("test1");
-
- assertThat(resources.get(5).getContent().get("_ou").isNull());
- assertThat(resources.get(5).getId()).isEqualTo("test2");
-
- assertThat(resources.get(6).getContent().get("_ou").isNull());
- assertThat(resources.get(6).getId()).isEqualTo("test3");
-
- assertThat(resources.get(7).getContent().get("_ou").isNull());
- assertThat(resources.get(7).getId()).isEqualTo("test4");
-
- assertThat(resources.get(8).getContent().get("_ou").isNull());
- assertThat(resources.get(8).getId()).isEqualTo("test5");
-
- assertThat(resources.get(9).getContent().get("_ou").isNull());
- assertThat(resources.get(9).getId()).isEqualTo("test6");
+ checkThatUsersExist(resources,
+ "sub2",
+ "sub1",
+ "test1",
+ "test2",
+ "test3",
+ "test4",
+ "test5",
+ "test6"
+ );
}
@Test
- public void testQueryNoneWithNoSubtreeFlattening() throws Exception {
+ public void testQueryNoneWithNoSubtreeFlatteningAndNoSearchFilter() throws Exception {
final Connection connection = newConnection();
final List<ResourceResponse> resources = new LinkedList<>();
- final QueryResponse result = connection.query(newAuthConnectionContext(),
- newQueryRequest("").setQueryFilter(QueryFilter.<JsonPointer> alwaysFalse()), resources);
+ final QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("").setQueryFilter(QueryFilter.<JsonPointer> alwaysFalse()),
+ resources);
assertThat(resources).hasSize(0);
assertThat(result.getPagedResultsCookie()).isNull();
@@ -186,7 +215,39 @@
}
@Test
- public void testQueryNoneWithSubtreeFlattening() throws Exception {
+ public void testQueryNoneWithSearchFilterAndNoSubtreeFlattening() throws Exception {
+ final Connection connection = newConnection();
+ final List<ResourceResponse> resources = new LinkedList<>();
+ final QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("top-level-users")
+ .setQueryFilter(QueryFilter.<JsonPointer> alwaysFalse()),
+ resources);
+
+ assertThat(resources).hasSize(0);
+ assertThat(result.getPagedResultsCookie()).isNull();
+ assertThat(result.getTotalPagedResults()).isEqualTo(-1);
+ }
+
+ @Test
+ public void testQueryNoneWithSubtreeFlatteningAndNoSearchFilter() throws Exception {
+ final Connection connection = newConnection();
+ final List<ResourceResponse> resources = new LinkedList<>();
+ final QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("all-entries")
+ .setQueryFilter(QueryFilter.<JsonPointer> alwaysFalse()),
+ resources);
+
+ assertThat(resources).hasSize(0);
+ assertThat(result.getPagedResultsCookie()).isNull();
+ assertThat(result.getTotalPagedResults()).isEqualTo(-1);
+ }
+
+ @Test
+ public void testQueryNoneWithSubtreeFlatteningAndSearchFilter() throws Exception {
final Connection connection = newConnection();
final List<ResourceResponse> resources = new LinkedList<>();
final QueryResponse result = connection.query(newAuthConnectionContext(),
@@ -198,7 +259,8 @@
}
@Test
- public void testQueryPageResultsCookie() throws Exception {
+ public void testQueryPageResultsCookieWithNoSubtreeFlatteningAndNoSearchFilter()
+ throws Exception {
final Connection connection = newConnection();
final List<ResourceResponse> resources = new ArrayList<>();
@@ -214,14 +276,11 @@
assertThat(result.getPagedResultsCookie()).isNotNull();
assertThat(resources).hasSize(3);
- assertThat(resources.get(0).getContent().get("_ou").isNotNull());
- assertThat(resources.get(0).getContent().get("_ou").asString()).isEqualTo("level1");
+ checkThatOrgUnitsExist(resources, "level1");
- assertThat(resources.get(1).getContent().get("_ou").isNull());
- assertThat(resources.get(1).getId()).isEqualTo("test1");
-
- assertThat(resources.get(2).getContent().get("_ou").isNull());
- assertThat(resources.get(2).getId()).isEqualTo("test2");
+ checkThatUsersExist(resources, 1,
+ "test1",
+ "test2");
String cookie = result.getPagedResultsCookie();
@@ -240,14 +299,10 @@
assertThat(result.getPagedResultsCookie()).isNotNull();
assertThat(resources).hasSize(3);
- assertThat(resources.get(0).getContent().get("_ou").isNull());
- assertThat(resources.get(0).getId()).isEqualTo("test3");
-
- assertThat(resources.get(1).getContent().get("_ou").isNull());
- assertThat(resources.get(1).getId()).isEqualTo("test4");
-
- assertThat(resources.get(2).getContent().get("_ou").isNull());
- assertThat(resources.get(2).getId()).isEqualTo("test5");
+ checkThatUsersExist(resources,
+ "test3",
+ "test4",
+ "test5");
cookie = result.getPagedResultsCookie();
@@ -266,12 +321,62 @@
assertThat(result.getPagedResultsCookie()).isNull();
assertThat(resources).hasSize(1);
- assertThat(resources.get(0).getContent().get("_ou").isNull());
- assertThat(resources.get(0).getId()).isEqualTo("test6");
+ checkThatUsersExist(resources,
+ "test6");
}
@Test
- public void testQueryPageResultsIndexed() throws Exception {
+ public void testQueryPageResultsCookieWithSubtreeFlatteningAndSearchFilter() throws Exception {
+ final Connection connection = newConnection();
+ final List<ResourceResponse> resources = new ArrayList<>();
+
+ // Read first page.
+ QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("all-users")
+ .setQueryFilter(NO_FILTER)
+ .setPageSize(5),
+ resources);
+
+ assertThat(result.getPagedResultsCookie()).isNotNull();
+ assertThat(resources).hasSize(5);
+
+ checkThatUsersExist(resources,
+ "sub2",
+ "sub1",
+ "test1",
+ "test2",
+ "test3");
+
+ String cookie = result.getPagedResultsCookie();
+
+ resources.clear();
+
+ // Read second page.
+ result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("all-users")
+ .setQueryFilter(NO_FILTER)
+ .setPageSize(5)
+ .setPagedResultsCookie(cookie),
+ resources);
+
+ assertThat(result.getPagedResultsCookie()).isNull();
+ assertThat(resources).hasSize(3);
+
+ checkThatUsersExist(resources,
+ "test4",
+ "test5",
+ "test6");
+
+ resources.clear();
+ }
+
+ @Test
+ public void testQueryPageResultsIndexedWithNoSubtreeFlatteningAndNoSearchFilter()
+ throws Exception {
final Connection connection = newConnection();
final List<ResourceResponse> resources = new ArrayList<>();
@@ -286,8 +391,33 @@
assertThat(result.getPagedResultsCookie()).isNotNull();
assertThat(resources).hasSize(2);
- assertThat(resources.get(0).getId()).isEqualTo("test2");
- assertThat(resources.get(1).getId()).isEqualTo("test3");
+
+ checkThatUsersExist(resources,
+ "test2",
+ "test3");
+ }
+
+ @Test
+ public void testQueryPageResultsIndexedWithSubtreeFlatteningAndSearchFilter() throws Exception {
+ final Connection connection = newConnection();
+ final List<ResourceResponse> resources = new ArrayList<>();
+
+ QueryResponse result =
+ connection.query(
+ newAuthConnectionContext(),
+ newQueryRequest("all-users")
+ .setQueryFilter(NO_FILTER)
+ .setPageSize(3)
+ .setPagedResultsOffset(1),
+ resources);
+
+ assertThat(result.getPagedResultsCookie()).isNotNull();
+ assertThat(resources).hasSize(3);
+
+ checkThatUsersExist(resources,
+ "test2",
+ "test3",
+ "test4");
}
@Test(expectedExceptions = NotFoundException.class)
@@ -869,11 +999,25 @@
.useClientDnNaming("uid"))
.subResource(
collectionOf("user")
+ .urlTemplate("top-level-users")
+ .dnTemplate("dc=test")
+ .useClientDnNaming("uid")
+ .baseSearchFilter("(objectClass=person)"))
+ .subResource(
+ collectionOf("user")
+ .urlTemplate("all-entries")
+ .dnTemplate("dc=test")
+ .useClientDnNaming("uid")
+ .isReadOnly(true)
+ .flattenSubtree(true))
+ .subResource(
+ collectionOf("user")
.urlTemplate("all-users")
.dnTemplate("dc=test")
.useClientDnNaming("uid")
.isReadOnly(true)
- .flattenSubtree(true)),
+ .flattenSubtree(true)
+ .baseSearchFilter("(objectClass=person)")),
resource("user")
.objectClasses("top", "person")
.property(
@@ -915,6 +1059,38 @@
.isEqualTo(expectedResource.getContent().getObject());
}
+ private void checkThatOrgUnitsExist(final List<ResourceResponse> resources,
+ final String... orgUnitIds) {
+ checkThatOrgUnitsExist(resources, 0, orgUnitIds);
+ }
+
+ private void checkThatOrgUnitsExist(final List<ResourceResponse> resources,
+ final int startingIndex,
+ final String... expectedOrgUnitIds) {
+ for (int orgUnitIndex = 0; orgUnitIndex < expectedOrgUnitIds.length; ++orgUnitIndex) {
+ final ResourceResponse resource = resources.get(startingIndex + orgUnitIndex);
+ final JsonValue orgUnitId = resource.getContent().get("_ou");
+
+ assertThat(orgUnitId).isNotNull();
+ assertThat(orgUnitId.asString()).isEqualTo(expectedOrgUnitIds[orgUnitIndex]);
+ }
+ }
+
+ private void checkThatUsersExist(final List<ResourceResponse> resources,
+ final String... expectedUserIds) {
+ checkThatUsersExist(resources, 0, expectedUserIds);
+ }
+
+ private void checkThatUsersExist(final List<ResourceResponse> resources,
+ final int startingIndex, final String... expectedUserIds) {
+ for (int userIndex = 0; userIndex < expectedUserIds.length; ++userIndex) {
+ final ResourceResponse resource = resources.get(startingIndex + userIndex);
+
+ assertThat(resource.getContent().get("_ou").isNull());
+ assertThat(resource.getId()).isEqualTo(expectedUserIds[userIndex]);
+ }
+ }
+
private AuthenticatedConnectionContext newAuthConnectionContext() throws IOException {
return newAuthConnectionContext(new ArrayList<Request>());
}
--
Gitblit v1.10.0