You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2019/02/12 08:46:55 UTC

svn commit: r1853421 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/ oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/ oak-security-spi/src/main/java/org/...

Author: angela
Date: Tue Feb 12 08:46:55 2019
New Revision: 1853421

URL: http://svn.apache.org/viewvc?rev=1853421&view=rev
Log:
OAK-8027 : Extract public utility for handling jcr:all privilege bits

Added:
    jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtil.java
    jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreEditor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java
    jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBits.java
    jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java
    jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java
    jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java
    jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStore.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStore.java Tue Feb 12 08:46:55 2019
@@ -28,8 +28,6 @@ import org.jetbrains.annotations.Nullabl
  */
 interface PermissionStore {
 
-    long DYNAMIC_ALL_BITS = -1;
-
     /**
      * Loads the permission entries for the given principal and path. If no
      * entries can be found for the given principal or path, {@code null} is returned.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreEditor.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreEditor.java Tue Feb 12 08:46:55 2019
@@ -23,19 +23,17 @@ import java.util.Set;
 import com.google.common.base.Objects;
 import com.google.common.base.Strings;
 import com.google.common.collect.Maps;
-import com.google.common.primitives.Longs;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
 import org.apache.jackrabbit.oak.plugins.tree.TreeProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
 import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.JcrAllUtil;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
-import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.util.Text;
@@ -56,6 +54,7 @@ final class PermissionStoreEditor implem
     private final String nodeName;
     private final Map<String, List<AcEntry>> entries = Maps.newHashMap();
     private final NodeBuilder permissionRoot;
+    private final PrivilegeBitsProvider bitsProvider;
 
     PermissionStoreEditor(@NotNull String aclPath, @NotNull String name,
                           @NotNull NodeState node, @NotNull NodeBuilder permissionRoot,
@@ -64,6 +63,7 @@ final class PermissionStoreEditor implem
                           @NotNull RestrictionProvider restrictionProvider,
                           @NotNull TreeProvider treeProvider) {
         this.permissionRoot = permissionRoot;
+        this.bitsProvider = bitsProvider;
         if (name.equals(REP_REPO_POLICY)) {
             accessControlledPath = "";
         } else {
@@ -77,7 +77,6 @@ final class PermissionStoreEditor implem
             addAll(orderedChildNames, node.getChildNodeNames());
         }
 
-        PrivilegeBits jcrAll = bitsProvider.getBits(PrivilegeConstants.JCR_ALL);
         int index = 0;
         for (String childName : orderedChildNames) {
             NodeState ace = node.getChildNode(childName);
@@ -86,9 +85,7 @@ final class PermissionStoreEditor implem
                 PrivilegeBits privilegeBits = bitsProvider.getBits(ace.getNames(REP_PRIVILEGES));
                 Set<Restriction> restrictions = restrictionProvider.readRestrictions(Strings.emptyToNull(accessControlledPath), treeProvider.createReadOnlyTree(ace));
 
-                AcEntry entry = (privilegeBits.equals(jcrAll)) ?
-                        new JcrAllAcEntry(ace, accessControlledPath, index, isAllow, privilegeBits, restrictions) :
-                        new AcEntry(ace, accessControlledPath, index, isAllow, privilegeBits, restrictions);
+                AcEntry entry = new AcEntry(ace, accessControlledPath, index, isAllow, privilegeBits, restrictions);
                 List<AcEntry> list = entries.computeIfAbsent(entry.principalName, k -> new ArrayList<>());
                 list.add(entry);
                 index++;
@@ -247,22 +244,6 @@ final class PermissionStoreEditor implem
         }
     }
 
-    private final class JcrAllAcEntry extends AcEntry {
-
-        private JcrAllAcEntry(@NotNull NodeState node,
-                              @NotNull String accessControlledPath,
-                              int index, boolean isAllow,
-                              @NotNull PrivilegeBits privilegeBits,
-                              @NotNull Set<Restriction> restrictions) {
-            super(node, accessControlledPath, index, isAllow, privilegeBits, restrictions);
-        }
-
-        @Override
-        protected PropertyState getPrivilegeBitsProperty() {
-            return PropertyStates.createProperty(REP_PRIVILEGE_BITS, Longs.asList(PermissionStore.DYNAMIC_ALL_BITS), Type.LONGS);
-        }
-    }
-
     private class AcEntry {
 
         private final String accessControlledPath;
@@ -296,7 +277,7 @@ final class PermissionStoreEditor implem
         }
 
         PropertyState getPrivilegeBitsProperty() {
-            return privilegeBits.asPropertyState(REP_PRIVILEGE_BITS);
+            return JcrAllUtil.asPropertyState(REP_PRIVILEGE_BITS, privilegeBits, bitsProvider);
         }
 
         //-------------------------------------------------------------< Object >---

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImpl.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImpl.java Tue Feb 12 08:46:55 2019
@@ -23,13 +23,12 @@ import java.util.TreeSet;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.JcrAllUtil;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
-import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
@@ -52,7 +51,7 @@ class PermissionStoreImpl implements Per
     private final Map<String, Tree> principalTreeMap = new HashMap<>();
 
     private Tree permissionsTree;
-    private PrivilegeBits allBits;
+    private PrivilegeBitsProvider bitsProvider;
 
     PermissionStoreImpl(Root root, String permissionRootName, RestrictionProvider restrictionProvider) {
         this.permissionRootName = permissionRootName;
@@ -68,7 +67,7 @@ class PermissionStoreImpl implements Per
 
     private void reset(@NotNull Root root) {
         permissionsTree = PermissionUtil.getPermissionsRoot(root, permissionRootName);
-        allBits = new PrivilegeBitsProvider(root).getBits(PrivilegeConstants.JCR_ALL);
+        bitsProvider = new PrivilegeBitsProvider(root);
     }
 
     //----------------------------------------------------< PermissionStore >---
@@ -171,7 +170,7 @@ class PermissionStoreImpl implements Per
     }
 
     private Collection<PermissionEntry> loadPermissionEntries(@NotNull String path,
-                                       @NotNull Tree tree) {
+                                                              @NotNull Tree tree) {
         Collection<PermissionEntry> ret = new TreeSet<>();
         for (Tree ace : tree.getChildren()) {
             if (ace.getName().charAt(0) != 'c') {
@@ -185,7 +184,7 @@ class PermissionStoreImpl implements Per
     private PermissionEntry createPermissionEntry(@NotNull String path,
                                                   @NotNull Tree entryTree) {
         PropertyState ps = entryTree.getProperty(REP_PRIVILEGE_BITS);
-        PrivilegeBits bits = (isJcrAll(ps)) ? allBits : PrivilegeBits.getInstance(ps);
+        PrivilegeBits bits = JcrAllUtil.getPrivilegeBits(ps, bitsProvider);
         boolean isAllow = TreeUtil.getBoolean(entryTree, REP_IS_ALLOW);
         return new PermissionEntry(path,
                 isAllow,
@@ -193,8 +192,4 @@ class PermissionStoreImpl implements Per
                 bits,
                 restrictionProvider.getPattern(path, entryTree));
     }
-
-    private static boolean isJcrAll(@Nullable PropertyState property) {
-        return property != null && property.count() == 1 && property.getValue(Type.LONG, 0) == DYNAMIC_ALL_BITS;
-    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java Tue Feb 12 08:46:55 2019
@@ -45,6 +45,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.JcrAllUtil;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.util.NodeUtil;
@@ -382,7 +383,7 @@ public class PermissionHookTest extends
         assertTrue(allEntry.exists());
         PropertyState ps = allEntry.getProperty(PermissionConstants.REP_PRIVILEGE_BITS);
         assertEquals(1, ps.count());
-        assertEquals(PermissionStore.DYNAMIC_ALL_BITS, ps.getValue(Type.LONG, 0).longValue());
+        assertTrue(JcrAllUtil.denotesDynamicJcrAll(ps));
 
         // verify that the permission provider still exposes the correct privilege
         // (jcr:all) for the given childPath irrespective of the dynamic nature of

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java Tue Feb 12 08:46:55 2019
@@ -31,6 +31,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.jetbrains.annotations.NotNull;
@@ -39,6 +40,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_READ_NODES;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -116,7 +118,7 @@ public class PermissionStoreImplTest ext
                     Tree collision = TreeUtil.addChild(child, "c_"+child.getName(), NT_REP_PERMISSION_STORE);
                     collision.setProperty(REP_ACCESS_CONTROLLED_PATH, "/another/path");
                     Tree entry = TreeUtil.addChild(collision, "1", NT_REP_PERMISSIONS);
-                    entry.setProperty(REP_PRIVILEGE_BITS, PermissionStore.DYNAMIC_ALL_BITS);
+                    entry.setProperty(PrivilegeBits.BUILT_IN.get(REP_READ_NODES).asPropertyState(REP_PRIVILEGE_BITS));
                     entry.setProperty(REP_IS_ALLOW, false);
                     break;
                 }

Added: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtil.java?rev=1853421&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtil.java (added)
+++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtil.java Tue Feb 12 08:46:55 2019
@@ -0,0 +1,76 @@
+/*
+ * 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.privilege;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+
+public final class JcrAllUtil {
+
+    private JcrAllUtil() {}
+
+    public static final long DYNAMIC_JCR_ALL_VALUE = -1;
+
+    /**
+     * Get or create an instance of privilege bits for the given property state. In contrast to
+     * {@link PrivilegeBits#getInstance(PropertyState)} this implementation will respect the special marker used to
+     * reflect the dynamic nature of the {@link PrivilegeConstants#JCR_ALL} privilege.
+     *
+     * @param propertyState A property storing privilege bits as {@link Type#LONGS} representation or the
+     *                      dynamic {@link #DYNAMIC_JCR_ALL_VALUE marker} for {@code jcr:all}.
+     * @param provider An instanceof {@link PrivilegeBitsProvider} to compute the bits for the {@link PrivilegeConstants#JCR_ALL}, when
+     *                 the given property contains the dynamic {@link #DYNAMIC_JCR_ALL_VALUE marker} for {@code jcr:all}.
+     * @return an instance of {@code PrivilegeBits}
+     * @see #asPropertyState(String, PrivilegeBits, PrivilegeBitsProvider)
+     */
+    public static PrivilegeBits getPrivilegeBits(@Nullable PropertyState propertyState, @NotNull PrivilegeBitsProvider provider) {
+        return (denotesDynamicJcrAll(propertyState)) ? getAllBits(provider) : PrivilegeBits.getInstance(propertyState);
+    }
+
+    /**
+     * Returns a new multi-valued {@link PropertyState} of type {@link Type#LONGS} with the given {@code name} and the
+     * long representation of the given {@code bits} as values. If the bits present include {@code jcr:all} the value
+     * will be {@link #DYNAMIC_JCR_ALL_VALUE} instead to mark the dynamic nature of the {@code jcr:all} privilege.
+     * For any other bits this method is equivalent to {@link PrivilegeBits#asPropertyState(String)}.
+     *
+     * @param name The name of the property to be created.
+     * @param bits The privilege bits from which the values will be retrieved.
+     * @param provider The {@link PrivilegeBitsProvider} needed to check if the given bits include {@code jcr:all}.
+     * @return The property state equivalent to {@link PrivilegeBits#asPropertyState(String)} or a state with the
+     * {@link #DYNAMIC_JCR_ALL_VALUE dynamic value marker} in case the given bits represent {@code jcr:all}.
+     */
+    public static PropertyState asPropertyState(@NotNull String name, @NotNull PrivilegeBits bits, @NotNull PrivilegeBitsProvider provider) {
+        if (!bits.isBuiltin() && bits.includes(getAllBits(provider))) {
+            return PropertyStates.createProperty(name, Collections.singletonList(DYNAMIC_JCR_ALL_VALUE), Type.LONGS);
+        } else {
+            return bits.asPropertyState(name);
+        }
+    }
+
+    public static boolean denotesDynamicJcrAll(@Nullable PropertyState property) {
+        return property != null && Type.LONGS == property.getType() && property.count() == 1 && property.getValue(Type.LONG, 0) == DYNAMIC_JCR_ALL_VALUE;
+    }
+
+    private static PrivilegeBits getAllBits(@NotNull PrivilegeBitsProvider provider) {
+        return provider.getBits(Collections.singleton(PrivilegeConstants.JCR_ALL));
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBits.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBits.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBits.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBits.java Tue Feb 12 08:46:55 2019
@@ -419,6 +419,14 @@ public final class PrivilegeBits impleme
     }
 
     /**
+     * @return {@code true} if this instance represents one of the built-in privilege
+     * @see #BUILT_IN
+     */
+    public boolean isBuiltin() {
+        return d.isSimple() && BUILT_IN_BITS.containsKey(d.longValue());
+    }
+
+    /**
      * Adds the other privilege bits to this instance.
      *
      * @param other The other privilege bits to be added.
@@ -493,7 +501,7 @@ public final class PrivilegeBits impleme
     }
 
     @NotNull
-    public PropertyState asPropertyState(String name) {
+    public PropertyState asPropertyState(@NotNull String name) {
         return PropertyStates.createProperty(name, Longs.asList(d.longValues()), Type.LONGS);
     }
 

Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java Tue Feb 12 08:46:55 2019
@@ -22,7 +22,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import javax.jcr.RepositoryException;
 import javax.jcr.security.Privilege;
 
 import com.google.common.base.Function;
@@ -49,6 +48,7 @@ public final class PrivilegeBitsProvider
     private static final Logger log = LoggerFactory.getLogger(PrivilegeBitsProvider.class);
 
     private final Map<PrivilegeBits, Set<String>> bitsToNames = new HashMap<>();
+    private final Map<String, PrivilegeBits> nameToBits = new HashMap<>();
     private final Map<String, Set<String>> aggregation = new HashMap<>();
 
     private final Root root;
@@ -99,13 +99,17 @@ public final class PrivilegeBitsProvider
             PrivilegeBits builtIn = PrivilegeBits.BUILT_IN.get(privilegeName);
             if (builtIn != null) {
                 bits.add(builtIn);
-            } else {
+            } else if (nameToBits.containsKey(privilegeName)) {
+                bits.add(nameToBits.get(privilegeName));
+            }  else {
                 if (privilegesTree == null) {
                     privilegesTree = getPrivilegesTree();
                 }
                 if (privilegesTree.exists() && privilegesTree.hasChild(privilegeName)) {
                     Tree defTree = privilegesTree.getChild(privilegeName);
-                    bits.add(PrivilegeBits.getInstance(defTree));
+                    PrivilegeBits bitsFromDefTree = PrivilegeBits.getInstance(defTree);
+                    nameToBits.put(privilegeName, bitsFromDefTree);
+                    bits.add(bitsFromDefTree);
                 } else {
                     log.debug("Ignoring privilege name " + privilegeName);
                 }

Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java Tue Feb 12 08:46:55 2019
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.2.1")
+@Version("1.3.0")
 package org.apache.jackrabbit.oak.spi.security.privilege;
 
 import org.osgi.annotation.versioning.Version;

Added: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java?rev=1853421&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java (added)
+++ jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java Tue Feb 12 08:46:55 2019
@@ -0,0 +1,141 @@
+/*
+ * 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.privilege;
+
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Longs;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.apache.jackrabbit.oak.spi.security.privilege.JcrAllUtil.DYNAMIC_JCR_ALL_VALUE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+public class JcrAllUtilTest implements PrivilegeConstants {
+
+    private static final Long ALL = Long.valueOf(Long.MAX_VALUE);
+
+    private static final PropertyState ALL_PROPERTY = PropertyStates.createProperty(REP_BITS, Longs.asList(Long.MAX_VALUE), Type.LONGS);
+    private final PrivilegeBits ALL_BITS = PrivilegeBits.getInstance(ALL_PROPERTY);
+
+    private static final PropertyState DYNAMIC_ALL_PROPERTY = PropertyStates.createProperty("anyName", Longs.asList(DYNAMIC_JCR_ALL_VALUE), Type.LONGS);
+
+    private Tree privTree;
+    private Tree jcrAllDefTree;
+    private Root root;
+    private PrivilegeBitsProvider bitsProvider;
+
+    @Before
+    public void before() {
+        jcrAllDefTree = Mockito.mock(Tree.class);
+        when(jcrAllDefTree.exists()).thenReturn(true);
+        when(jcrAllDefTree.getName()).thenReturn(JCR_ALL);
+        when(jcrAllDefTree.getProperty(REP_BITS)).thenReturn(ALL_PROPERTY);
+
+        privTree = Mockito.mock(Tree.class);
+        when(privTree.exists()).thenReturn(true);
+        when(privTree.hasChild(JCR_ALL)).thenReturn(true);
+        when(privTree.getChild(JCR_ALL)).thenReturn(jcrAllDefTree);
+
+        root = Mockito.mock(Root.class);
+        when(root.getTree(PRIVILEGES_PATH)).thenReturn(privTree);
+
+        bitsProvider = new PrivilegeBitsProvider(root);
+    }
+
+    @Test
+    public void testGetInstanceBuiltin() {
+        PrivilegeBits readBits = PrivilegeBits.BUILT_IN.get(REP_READ_NODES);
+        PropertyState propState = readBits.asPropertyState(("anyName"));
+
+        assertSame(readBits, JcrAllUtil.getPrivilegeBits(propState, bitsProvider));
+    }
+
+    @Test
+    public void testAsPropertyStateBuiltin() {
+        PrivilegeBits readBits = PrivilegeBits.BUILT_IN.get(REP_READ_NODES);
+        PropertyState propertyState = JcrAllUtil.asPropertyState("anyName", readBits, bitsProvider);
+
+        assertEquals(readBits.asPropertyState("anyName"), propertyState);
+    }
+
+    @Test
+    public void testGetInstanceCombined() {
+        PrivilegeBits bits = PrivilegeBits.getInstance();
+        bits.add(PrivilegeBits.BUILT_IN.get(REP_READ_NODES));
+        bits.add(PrivilegeBits.BUILT_IN.get(REP_WRITE));
+        PropertyState propState = bits.asPropertyState("anyName");
+
+        assertEquals(bits.unmodifiable(), JcrAllUtil.getPrivilegeBits(propState, bitsProvider));
+    }
+
+    @Test
+    public void testAsPropertyStateCombined() {
+        PrivilegeBits bits = PrivilegeBits.getInstance();
+        bits.add(PrivilegeBits.BUILT_IN.get(REP_READ_NODES));
+        bits.add(PrivilegeBits.BUILT_IN.get(REP_WRITE));
+        PropertyState expected = bits.asPropertyState("anyName");
+
+        assertEquals(expected, JcrAllUtil.asPropertyState("anyName", bits, bitsProvider));
+    }
+
+    @Test
+    public void testGetInstanceDynamicAll() {
+        assertEquals(ALL_BITS, JcrAllUtil.getPrivilegeBits(DYNAMIC_ALL_PROPERTY, bitsProvider));
+    }
+
+    @Test
+    public void testAsPropertyStateDynamicAll() {
+        assertEquals(DYNAMIC_ALL_PROPERTY, JcrAllUtil.asPropertyState("anyName", ALL_BITS, bitsProvider));
+    }
+
+    @Test
+    public void testDenotesDynamicAllNullPropertyState() {
+        assertFalse(JcrAllUtil.denotesDynamicJcrAll(null));
+    }
+
+    @Test
+    public void testDenotesDynamicAllNotLongsPropertyState() {
+        assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", "String")));
+        assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any",  Lists.newArrayList("mv", "strings"), Type.STRINGS)));
+        assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", "-1")));
+    }
+
+    @Test
+    public void testDenotesDynamicAllMVLongPropertyState() {
+        assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", Lists.newArrayList(-1, 2, 3), Type.LONGS)));
+    }
+
+    @Test
+    public void testDenotesDynamicAllSingleLongPropertyState() {
+        assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", DYNAMIC_JCR_ALL_VALUE)));
+    }
+
+    @Test
+    public void testDenotesDynamicAll() {
+        assertTrue(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", Lists.newArrayList(DYNAMIC_JCR_ALL_VALUE), Type.LONGS)));
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java Tue Feb 12 08:46:55 2019
@@ -16,10 +16,6 @@
  */
 package org.apache.jackrabbit.oak.spi.security.privilege;
 
-import java.util.Set;
-import javax.jcr.RepositoryException;
-import javax.jcr.security.Privilege;
-
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -34,12 +30,19 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
 
+import javax.jcr.security.Privilege;
+import java.util.Set;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class PrivilegeBitsProviderTest implements PrivilegeConstants {
@@ -56,15 +59,19 @@ public class PrivilegeBitsProviderTest i
 
     @Before
     public void before() {
+        pTree = Mockito.mock(Tree.class);
+        when(pTree.getName()).thenReturn(KNOWN_PRIV_NAME);
+        when(pTree.getProperty(REP_BITS)).thenReturn(ps);
+
         privTree = Mockito.mock(Tree.class);
+        when(privTree.exists()).thenReturn(true);
+        when(privTree.hasChild(KNOWN_PRIV_NAME)).thenReturn(true);
+        when(privTree.getChild(KNOWN_PRIV_NAME)).thenReturn(pTree);
+        when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree));
 
         root = Mockito.mock(Root.class);
         when(root.getTree(PRIVILEGES_PATH)).thenReturn(privTree);
 
-        pTree = Mockito.mock(Tree.class);
-        when(pTree.getName()).thenReturn(KNOWN_PRIV_NAME);
-        when(pTree.getProperty(REP_BITS)).thenReturn(ps);
-
         bitsProvider = new PrivilegeBitsProvider(root);
     }
 
@@ -86,7 +93,7 @@ public class PrivilegeBitsProviderTest i
 
     @Test
     public void testGetBitsEmptyArray() {
-        assertEquals(PrivilegeBits.EMPTY, bitsProvider.getBits());
+        assertEquals(PrivilegeBits.EMPTY, bitsProvider.getBits(new String[0]));
     }
 
     @Test
@@ -151,6 +158,72 @@ public class PrivilegeBitsProviderTest i
     }
 
     @Test
+    public void testGetBitsTwiceSingleBuiltIn() {
+        Iterable<String> names = ImmutableList.of(JCR_ADD_CHILD_NODES);
+        PrivilegeBits bits1 = bitsProvider.getBits(names);
+        PrivilegeBits bits2 = bitsProvider.getBits(names);
+
+        assertSame(bits1, bits2);
+        assertEquals(bits1, bits2);
+
+        verify(root, never()).getTree(PRIVILEGES_PATH);
+        verify(privTree, never()).getChild(KNOWN_PRIV_NAME);
+    }
+
+    @Test
+    public void testGetBitsTwiceMultipleBuiltIn() {
+        Iterable<String> names = ImmutableList.of(JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES);
+        PrivilegeBits bits1 = bitsProvider.getBits(names);
+        PrivilegeBits bits2 = bitsProvider.getBits(names);
+
+        assertNotSame(bits1, bits2);
+        assertEquals(bits1, bits2);
+
+        verify(root, never()).getTree(PRIVILEGES_PATH);
+        verify(privTree, never()).getChild(KNOWN_PRIV_NAME);
+    }
+
+    @Test
+    public void testGetBitsTwiceKnown() {
+        Iterable<String> names = ImmutableList.of(KNOWN_PRIV_NAME);
+        PrivilegeBits bits1 = bitsProvider.getBits(names);
+        PrivilegeBits bits2 = bitsProvider.getBits(names);
+
+        assertNotSame(bits1, bits2);
+        assertEquals(bits1, bits2);
+
+        verify(root, times(1)).getTree(PRIVILEGES_PATH);
+        verify(privTree, times(1)).getChild(KNOWN_PRIV_NAME);
+    }
+
+    @Test
+    public void testGetBitsTwiceBuitInKnown() {
+        Iterable<String> names = ImmutableList.of(KNOWN_PRIV_NAME, JCR_ADD_CHILD_NODES);
+        PrivilegeBits bits1 = bitsProvider.getBits(names);
+        PrivilegeBits bits2 = bitsProvider.getBits(names);
+
+        assertNotSame(bits1, bits2);
+        assertEquals(bits1, bits2);
+
+        verify(root, times(1)).getTree(PRIVILEGES_PATH);
+        verify(privTree, times(1)).getChild(KNOWN_PRIV_NAME);
+    }
+
+    @Test
+    public void testGetBitsTwiceKnownUnknown() {
+        Iterable<String> names = ImmutableList.of(KNOWN_PRIV_NAME, "unknown");
+        PrivilegeBits bits1 = bitsProvider.getBits(names);
+        PrivilegeBits bits2 = bitsProvider.getBits(names);
+
+        assertNotSame(bits1, bits2);
+        assertEquals(bits1, bits2);
+        assertEquals(bitsProvider.getBits(KNOWN_PRIV_NAME), bits1);
+
+        verify(root, times(2)).getTree(PRIVILEGES_PATH);
+        verify(privTree, times(1)).getChild(KNOWN_PRIV_NAME);
+    }
+
+    @Test
     public void testGetBitsFromEmptyPrivileges() {
         assertSame(PrivilegeBits.EMPTY, bitsProvider.getBits(new Privilege[0], NamePathMapper.DEFAULT));
     }
@@ -192,9 +265,6 @@ public class PrivilegeBitsProviderTest i
 
     @Test
     public void testGetPrivilegeNames() {
-        when(privTree.exists()).thenReturn(true);
-        when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree));
-
         Set<String> names = bitsProvider.getPrivilegeNames(bits);
         assertFalse(names.isEmpty());
         assertEquals(ImmutableSet.of(KNOWN_PRIV_NAME), names);
@@ -202,18 +272,12 @@ public class PrivilegeBitsProviderTest i
 
     @Test
     public void testGetPrivilegeNamesFromCache() {
-        when(privTree.exists()).thenReturn(true);
-        when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree));
-
         Set<String> names = bitsProvider.getPrivilegeNames(bits);
         assertSame(names, bitsProvider.getPrivilegeNames(bits));
     }
 
     @Test
     public void testGetPrivilegeNamesWithAggregation() {
-        when(privTree.exists()).thenReturn(true);
-        when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree));
-
         Tree anotherPriv = Mockito.mock(Tree.class);
         when(anotherPriv.exists()).thenReturn(true);
         when(anotherPriv.getName()).thenReturn("name2");

Modified: jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java?rev=1853421&r1=1853420&r2=1853421&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java Tue Feb 12 08:46:55 2019
@@ -206,6 +206,39 @@ public class PrivilegeBitsTest implement
     }
 
     @Test
+    public void testBuiltIn() {
+        for (PrivilegeBits bits : PrivilegeBits.BUILT_IN.values()) {
+            assertTrue(bits.isBuiltin());
+            assertTrue(PrivilegeBits.getInstance(bits).isBuiltin());
+        }
+    }
+
+    @Test
+    public void testCombinationNotBuiltIn() {
+        PrivilegeBits combination = PrivilegeBits.getInstance();
+        for (PrivilegeBits bits : PrivilegeBits.BUILT_IN.values()) {
+            combination.add(bits);
+        }
+        assertFalse(combination.isBuiltin());
+    }
+
+    @Test
+    public void testNextNotBuiltIn() {
+        assertFalse(PrivilegeBits.getInstance(PrivilegeBits.NEXT_AFTER_BUILT_INS).isBuiltin());
+    }
+
+    @Test
+    public void testCombinationWithNextNotBuiltIn() {
+        PrivilegeBits bits = PrivilegeBits.NEXT_AFTER_BUILT_INS;
+        PrivilegeBits toTest = PrivilegeBits.getInstance(PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ));
+
+        for (int i = 0; i<100; i++) {
+            bits = bits.nextBits();
+            assertFalse(toTest.add(bits).isBuiltin());
+        }
+    }
+
+    @Test
     public void testIsEmpty() {
         // empty
         assertTrue(PrivilegeBits.EMPTY.isEmpty());