Author: stillalex Date: Mon Feb 25 14:24:41 2019 New Revision: 1854314 URL: http://svn.apache.org/viewvc?rev=1854314&view=rev Log: OAK-7994 Principal Management APIs don't allow for search pagination
Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalQueryManager.java (with props) Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/PrincipalManagerDelegator.java jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalManagerImpl.java jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/PrincipalManagerDelegator.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/PrincipalManagerDelegator.java?rev=1854314&r1=1854313&r2=1854314&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/PrincipalManagerDelegator.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/PrincipalManagerDelegator.java Mon Feb 25 14:24:41 2019 @@ -26,6 +26,7 @@ import javax.jcr.RepositoryException; import org.apache.jackrabbit.api.security.principal.PrincipalIterator; import org.apache.jackrabbit.api.security.principal.PrincipalManager; import org.apache.jackrabbit.oak.jcr.session.operation.SessionOperation; +import org.apache.jackrabbit.oak.spi.security.principal.PrincipalQueryManager; import org.jetbrains.annotations.NotNull; /** @@ -34,7 +35,7 @@ import org.jetbrains.annotations.NotNull * * @see SessionDelegate#perform(SessionOperation) */ -public class PrincipalManagerDelegator implements PrincipalManager { +public class PrincipalManagerDelegator implements PrincipalManager, PrincipalQueryManager { private final SessionDelegate delegate; private final PrincipalManager principalManager; @@ -123,4 +124,22 @@ public class PrincipalManagerDelegator i } }); } + + @Override + public PrincipalIterator findPrincipals(String simpleFilter, int searchType, long offset, long limit) { + return delegate.safePerform(new SessionOperation<PrincipalIterator>("findPrincipals") { + @NotNull + @Override + public PrincipalIterator perform() { + if (principalManager instanceof PrincipalQueryManager) { + return ((PrincipalQueryManager) principalManager).findPrincipals(simpleFilter, searchType, offset, + limit); + } else { + PrincipalIterator pi = principalManager.findPrincipals(simpleFilter, searchType); + pi.skip(offset); + return pi; + } + } + }); + } } Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalManagerImpl.java?rev=1854314&r1=1854313&r2=1854314&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalManagerImpl.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalManagerImpl.java Mon Feb 25 14:24:41 2019 @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullabl /** * Default implementation of the {@code PrincipalManager} interface. */ -public class PrincipalManagerImpl implements PrincipalManager { +public class PrincipalManagerImpl implements PrincipalQueryManager, PrincipalManager { private final PrincipalProvider principalProvider; @@ -78,4 +78,9 @@ public class PrincipalManagerImpl implem } return everyone; } + + @Override + public PrincipalIterator findPrincipals(String simpleFilter, int searchType, long offset, long limit) { + return new PrincipalIteratorAdapter(principalProvider.findPrincipals(simpleFilter, searchType, offset, limit)); + } } Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java?rev=1854314&r1=1854313&r2=1854314&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java Mon Feb 25 14:24:41 2019 @@ -21,6 +21,11 @@ import java.security.acl.Group; import java.util.Collections; import java.util.Iterator; import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.osgi.annotation.versioning.ProviderType; @@ -116,6 +121,36 @@ public interface PrincipalProvider { @NotNull Iterator<? extends Principal> findPrincipals(@Nullable String nameHint, int searchType); + /** + * Find the principals that match the specified nameHint and search type. + * + * @param nameHint A name hint to use for non-exact matching. + * @param searchType Limit the search to certain types of principals. Valid + * values are any of + * <ul><li>{@link org.apache.jackrabbit.api.security.principal.PrincipalManager#SEARCH_TYPE_ALL}</li></ul> + * <ul><li>{@link org.apache.jackrabbit.api.security.principal.PrincipalManager#SEARCH_TYPE_NOT_GROUP}</li></ul> + * <ul><li>{@link org.apache.jackrabbit.api.security.principal.PrincipalManager#SEARCH_TYPE_GROUP}</li></ul> + * @param offset Offset from where to start returning results. <code>0</code> for no offset. + * @param limit Maximal number of results to return. -1 for no limit. + * @return An iterator of principals. + * @throws IllegalArgumentException if {@code offset} is negative + */ + @NotNull + default Iterator<? extends Principal> findPrincipals(@Nullable String nameHint, int searchType, long offset, long limit) { + if (offset < 0) { + throw new IllegalArgumentException(Long.toString(offset)); + } + Iterator<? extends Principal> principals = findPrincipals(nameHint, searchType); + Spliterator<? extends Principal> spliterator = Spliterators.spliteratorUnknownSize(principals, 0); + Stream<? extends Principal> stream = StreamSupport.stream(spliterator, false); + if (offset > 0) { + stream = stream.skip(offset); + } + if (limit >= 0) { + stream = stream.limit(limit); + } + return stream.iterator(); + } /** * Find all principals that match the search type. Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalQueryManager.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalQueryManager.java?rev=1854314&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalQueryManager.java (added) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalQueryManager.java Mon Feb 25 14:24:41 2019 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.oak.spi.security.principal; + +import java.security.Principal; + +import org.apache.jackrabbit.api.security.principal.PrincipalIterator; +import org.apache.jackrabbit.api.security.principal.PrincipalManager; +import org.osgi.annotation.versioning.ProviderType; + +/** + * Extension for the {@code PrincipalManager} that offers range search. + * + */ +@ProviderType +public interface PrincipalQueryManager { + + /** + * Gets the principals matching a simple filter expression applied against + * the {@link Principal#getName() principal name} AND the specified search + * type. + * Results are expected to be sorted by the principal name. + * An implementation may limit the number of principals returned. + * If there are no matching principals, an empty iterator is returned. + * @param simpleFilter + * @param searchType Any of the following constants: + * <ul> + * <li>{@link PrincipalManager#SEARCH_TYPE_ALL}</li> + * <li>{@link PrincipalManager#SEARCH_TYPE_GROUP}</li> + * <li>{@link PrincipalManager#SEARCH_TYPE_NOT_GROUP}</li> + * </ul> + * @param offset Offset from where to start returning results. <code>0</code> for no offset. + * @param limit Maximal number of results to return. -1 for no limit. + * @return a <code>PrincipalIterator</code> over the <code>Principal</code>s + * matching the given filter and search type. + */ + PrincipalIterator findPrincipals(String simpleFilter, int searchType, long offset, long limit); +} Propchange: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalQueryManager.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java?rev=1854314&r1=1854313&r2=1854314&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java Mon Feb 25 14:24:41 2019 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@Version("1.6.0") +@Version("1.7.0") package org.apache.jackrabbit.oak.spi.security.principal; import org.osgi.annotation.versioning.Version; Modified: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java?rev=1854314&r1=1854313&r2=1854314&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java (original) +++ jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java Mon Feb 25 14:24:41 2019 @@ -17,7 +17,12 @@ package org.apache.jackrabbit.oak.spi.security.principal; import java.security.Principal; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; +import java.util.List; +import java.util.Set; + import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -26,6 +31,7 @@ import com.google.common.collect.Iterabl import org.apache.jackrabbit.api.security.principal.GroupPrincipal; import org.apache.jackrabbit.api.security.principal.PrincipalManager; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -135,4 +141,62 @@ public class CompositePrincipalProviderT Iterator<? extends Principal> result = cpp.findPrincipals(PrincipalManager.SEARCH_TYPE_ALL); assertIterator(Iterables.concat(ImmutableSet.of(EveryonePrincipal.getInstance()), testPrincipals()), result); } + + /** + * Tests that the default implementation of range based + * {@code findPrincipals} methods of PrincipalProvider work properly. See + * OAK-7994 + */ + @Test + public void testRangeDefault() { + List<? extends Principal> pps = ImmutableList.of(new PrincipalImpl("p0"), new PrincipalImpl("p1"), + new PrincipalImpl("p2")); + + PrincipalProvider pp = new PrincipalProvider() { + @Override + @NotNull + public Set<? extends Principal> getPrincipals(@NotNull String userID) { + return Collections.emptySet(); + } + @Override + @Nullable + public Principal getPrincipal(@NotNull String principalName) { + return null; + } + @Override + @NotNull + public Iterator<? extends Principal> findPrincipals(int searchType) { + return pps.iterator(); + } + @Override + @NotNull + public Iterator<? extends Principal> findPrincipals(@Nullable String nameHint, int searchType) { + return pps.iterator(); + } + }; + + List<String> expected = getNames(pps.iterator()); + for (int offset = 0; offset < expected.size() + 1; offset++) { + for (int limit = -1; limit < expected.size() + 2; limit++) { + int to = expected.size(); + if (limit >= 0) { + to = Math.min(offset + limit, to); + } + List<String> sub = expected.subList(offset, to); + Iterator<? extends Principal> i0 = pp.findPrincipals(null, PrincipalManager.SEARCH_TYPE_ALL, offset, limit); + assertEquals(sub, getNames(i0)); + Iterator<? extends Principal> i1 = pp.findPrincipals("", PrincipalManager.SEARCH_TYPE_ALL, offset, + limit); + assertEquals(sub, getNames(i1)); + } + } + } + + private static List<String> getNames(Iterator<? extends Principal> i) { + List<String> l = new ArrayList<>(); + while (i.hasNext()) { + l.add(i.next().getName()); + } + return l; + } }