Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (working copy) @@ -127,7 +127,7 @@ return new ExecutionContext( rootTree.getNodeState(), ImmutableRoot.this, new QueryEngineSettings(), - new PropertyIndexProvider()); + new PropertyIndexProvider(), null); } }; } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java (working copy) @@ -306,7 +306,7 @@ provider, getBaseState(), getRootState()); } return new ExecutionContext( - getBaseState(), MutableRoot.this, queryEngineSettings, provider); + getBaseState(), MutableRoot.this, queryEngineSettings, provider, permissionProvider.get()); } }; } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/query/ExecutionContext.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/query/ExecutionContext.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ExecutionContext.java (working copy) @@ -19,10 +19,12 @@ package org.apache.jackrabbit.oak.query; +import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; +import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; import org.apache.jackrabbit.oak.spi.state.NodeState; /** @@ -43,14 +45,17 @@ private final QueryIndexProvider indexProvider; + private final PermissionProvider permissionProvider; + public ExecutionContext( NodeState baseState, Root root, QueryEngineSettings settings, - QueryIndexProvider indexProvider) { + QueryIndexProvider indexProvider, PermissionProvider permissionProvider) { this.baseState = baseState; this.root = root; this.settings = settings; this.indexProvider = indexProvider; + this.permissionProvider = permissionProvider; } /** @@ -87,5 +92,9 @@ public QueryEngineSettings getSettings() { return settings; } - + + @CheckForNull + public PermissionProvider getPermissionProvider() { + return permissionProvider; + } } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (working copy) @@ -22,6 +22,8 @@ import java.util.List; import java.util.Set; +import javax.annotation.CheckForNull; + import org.apache.jackrabbit.oak.api.PropertyValue; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.Type; @@ -77,6 +79,7 @@ import org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry; import org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry.Order; import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; +import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStateUtils; import org.slf4j.Logger; @@ -987,6 +990,11 @@ public QueryEngineSettings getSettings() { return settings; } + + @CheckForNull + public PermissionProvider getPermissionProvider() { + return context.getPermissionProvider(); + } @Override public void setInternal(boolean isInternal) { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (working copy) @@ -37,6 +37,7 @@ import java.util.List; import java.util.Set; +import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import org.apache.jackrabbit.oak.api.PropertyState; @@ -57,6 +58,7 @@ import org.apache.jackrabbit.oak.spi.query.QueryIndex; import org.apache.jackrabbit.oak.spi.query.QueryIndex.AdvancedQueryIndex; import org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan; +import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -635,13 +637,9 @@ } else if (oakPropertyName.equals(QueryImpl.REP_EXCERPT)) { result = currentRow.getValue(QueryImpl.REP_EXCERPT); } else if (oakPropertyName.equals(QueryImpl.REP_SPELLCHECK)) { - // TODO : filter spellcheck corrections by ACLs ? result = currentRow.getValue(QueryImpl.REP_SPELLCHECK); } else if (oakPropertyName.equals(QueryImpl.REP_SUGGEST)) { - // TODO : filter suggestions by ACLs - PropertyValue value = currentRow.getValue(QueryImpl.REP_SUGGEST); - - result = value; + result = currentRow.getValue(QueryImpl.REP_SUGGEST); } else { result = PropertyValues.create(t.getProperty(oakPropertyName)); } @@ -752,4 +750,9 @@ return this.outerJoinRightHandSide; } + @CheckForNull + public PermissionProvider getPermissionProvider() { + return query.getPermissionProvider(); + } + } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java (working copy) @@ -29,6 +29,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.jcr.PropertyType; +import javax.jcr.Session; import org.apache.jackrabbit.oak.api.PropertyValue; import org.apache.jackrabbit.oak.commons.PathUtils; @@ -39,6 +40,7 @@ import org.apache.jackrabbit.oak.query.ast.SelectorImpl; import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression; import org.apache.jackrabbit.oak.spi.query.Filter; +import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; /** * A filter or lookup condition. @@ -594,4 +596,9 @@ return settings; } + public boolean isAccessible(String path) { + PermissionProvider permissionProvider = selector.getPermissionProvider(); + // TODO : once OAK-2423 is fixed change this to PP#canRead + return permissionProvider != null && permissionProvider.isGranted(path, Session.ACTION_READ); + } } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java (revision 1658909) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java (working copy) @@ -74,6 +74,8 @@ FullTextExpression getFullTextConstraint(); QueryEngineSettings getQueryEngineSettings(); + + boolean isAccessible(String path); /** * Whether the filter contains a native condition. Index: oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java =================================================================== --- oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (revision 1658909) +++ oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (working copy) @@ -27,7 +27,6 @@ import javax.annotation.CheckForNull; import com.google.common.collect.AbstractIterator; -import com.google.common.collect.Iterables; import com.google.common.collect.Queues; import com.google.common.collect.Sets; import org.apache.jackrabbit.oak.api.PropertyValue; @@ -296,6 +295,9 @@ NamedList response = queryResponse.getResponse(); Map suggest = (Map) response.get("suggest"); if (suggest != null) { + + Collection> retrievedSuggestions = new HashSet>(); + Set> suggestEntries = suggest.entrySet(); if (!suggestEntries.isEmpty()) { SolrDocument fakeDoc = new SolrDocument(); @@ -308,10 +310,9 @@ ArrayList> suggestions = ((ArrayList>) suggestionResult.getValue()); if (suggestions.isEmpty()) { fakeDoc.addField(QueryImpl.REP_SUGGEST, "[]"); - } - else { + } else { for (SimpleOrderedMap suggestion : suggestions) { - fakeDoc.addField(QueryImpl.REP_SUGGEST, "{term=" + suggestion.get("term") + ",weight=" + suggestion.get("weight") + "}"); + retrievedSuggestions.add(suggestion); } } } @@ -318,6 +319,27 @@ } } } + + // ACL filter suggestions + for (SimpleOrderedMap suggestion : retrievedSuggestions) { + SolrQuery solrQuery = new SolrQuery(); + solrQuery.setParam("q", String.valueOf(suggestion.get("term"))); + solrQuery.setParam("df", configuration.getCatchAllField()); + solrQuery.setParam("q.op", "AND"); + solrQuery.setParam("rows", "100"); + QueryResponse suggestQueryResponse = solrServer.query(solrQuery); + SolrDocumentList results = suggestQueryResponse.getResults(); + if (results != null && results.getNumFound() > 0) { + for (SolrDocument doc : results) { + filter. + if (exists(String.valueOf(doc.getFieldValue(configuration.getPathField())), root)) { + fakeDoc.addField(QueryImpl.REP_SUGGEST, "{term=" + suggestion.get("term") + ",weight=" + suggestion.get("weight") + "}"); + break; + } + } + } + } + queue.add(new SolrResultRow("/", 1.0, fakeDoc)); noDocs = true; } @@ -346,10 +368,10 @@ // do nothing } - private boolean exists(SolrResultRow row, NodeState root) { + private boolean exists(String path, NodeState root) { boolean result = true; NodeState nodeState = root; - for (String n : PathUtils.elements(row.path)) { + for (String n : PathUtils.elements(path)) { if (nodeState.hasChildNode(n)) { nodeState = nodeState.getChildNode(n); } else {