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/SubResourceImpl.java |   39 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 38 insertions(+), 1 deletions(-)

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);
     }

--
Gitblit v1.10.0