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 2013/10/21 12:24:50 UTC

svn commit: r1534081 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/security/authorization/ main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/ main/java/org/apache/jackrabbit/oak/security/authorizati...

Author: angela
Date: Mon Oct 21 10:24:50 2013
New Revision: 1534081

URL: http://svn.apache.org/r1534081
Log:
OAK-527: permissions (wip)

- move readable-path handling to separate class

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
    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/spi/security/authorization/permission/PermissionConstants.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/ReadPolicyTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImplTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java?rev=1534081&r1=1534080&r2=1534081&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java Mon Oct 21 10:24:50 2013
@@ -58,7 +58,7 @@ import org.apache.jackrabbit.oak.spi.xml
  */
 @Component()
 @Service({AuthorizationConfiguration.class, SecurityConfiguration.class})
-public class AuthorizationConfigurationImpl extends ConfigurationBase implements AuthorizationConfiguration {
+public class  AuthorizationConfigurationImpl extends ConfigurationBase implements AuthorizationConfiguration {
 
     public AuthorizationConfigurationImpl() {
         super();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java?rev=1534081&r1=1534080&r2=1534081&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java Mon Oct 21 10:24:50 2013
@@ -43,7 +43,6 @@ import javax.jcr.security.NamedAccessCon
 import javax.jcr.security.Privilege;
 
 import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
@@ -128,7 +127,7 @@ public class AccessControlManagerImpl im
         restrictionProvider = acConfig.getRestrictionProvider();
         ntMgr = ReadOnlyNodeTypeManager.getInstance(root, namePathMapper);
 
-        readPaths = ImmutableSet.copyOf(acConfig.getParameters().getConfigValue(PermissionConstants.PARAM_READ_PATHS, PermissionConstants.DEFAULT_READ_PATHS));
+        readPaths = acConfig.getParameters().getConfigValue(PermissionConstants.PARAM_READ_PATHS, PermissionConstants.DEFAULT_READ_PATHS);
     }
 
     private static <T> T getConfig(SecurityProvider sp, Class<T> clss) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java?rev=1534081&r1=1534080&r2=1534081&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java Mon Oct 21 10:24:50 2013
@@ -30,7 +30,6 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterators;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.PropertyState;
@@ -79,7 +78,7 @@ class CompiledPermissionImpl implements 
     private final Map<String, Tree> userTrees;
     private final Map<String, Tree> groupTrees;
 
-    private final String[] readPathsCheckList;
+    private final ReadPolicy readPolicy;
 
     private final PermissionStore userStore;
     private final PermissionStore groupStore;
@@ -96,12 +95,7 @@ class CompiledPermissionImpl implements 
         this.workspaceName = workspaceName;
 
         bitsProvider = new PrivilegeBitsProvider(root);
-        readPathsCheckList = new String[readPaths.size() * 2];
-        int i = 0;
-        for (String p : readPaths) {
-            readPathsCheckList[i++] = p;
-            readPathsCheckList[i++] = p + '/';
-        }
+        readPolicy = (readPaths.isEmpty()) ? EmptyReadPolicy.INSTANCE : new DefaultReadPolicy(readPaths);
 
         userTrees = new HashMap<String, Tree>(principals.size());
         groupTrees = new HashMap<String, Tree>(principals.size());
@@ -128,10 +122,9 @@ class CompiledPermissionImpl implements 
         if (!permissionsTree.exists() || principals.isEmpty()) {
             return NoPermissions.getInstance();
         } else {
-            String[] readPaths = acConfig.getParameters().getConfigValue(PARAM_READ_PATHS, DEFAULT_READ_PATHS);
+            Set<String> readPaths = acConfig.getParameters().getConfigValue(PARAM_READ_PATHS, DEFAULT_READ_PATHS);
             return new CompiledPermissionImpl(principals, root, workspaceName,
-                    permissionsTree, acConfig.getRestrictionProvider(),
-                    ImmutableSet.copyOf(readPaths));
+                    permissionsTree, acConfig.getRestrictionProvider(), readPaths);
         }
     }
 
@@ -181,7 +174,7 @@ class CompiledPermissionImpl implements 
         return new RepositoryPermission() {
             @Override
             public boolean isGranted(long repositoryPermissions) {
-                return hasPermissions(getEntryIterator(new EntryPredicate()), repositoryPermissions, null, null);
+                return hasPermissions(getEntryIterator(new EntryPredicate()), repositoryPermissions, null);
             }
         };
     }
@@ -271,7 +264,7 @@ class CompiledPermissionImpl implements 
     @Override
     public boolean isGranted(@Nonnull String path, long permissions) {
         Iterator<PermissionEntry> it = getEntryIterator(new EntryPredicate(path));
-        return hasPermissions(it, permissions, null, path);
+        return hasPermissions(it, permissions, path);
     }
 
     @Override
@@ -288,18 +281,18 @@ class CompiledPermissionImpl implements 
 
     private boolean internalIsGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
         Iterator<PermissionEntry> it = getEntryIterator(new EntryPredicate(tree, property));
-        return hasPermissions(it, permissions, tree, null);
+        return hasPermissions(it, permissions, tree.getPath());
     }
 
     private boolean hasPermissions(@Nonnull Iterator<PermissionEntry> entries,
-                                   long permissions, @Nullable Tree tree, @Nullable String path) {
+                                   long permissions, @Nullable String path) {
         // calculate readable paths if the given permissions includes any read permission.
-        boolean isReadable = Permissions.diff(Permissions.READ, permissions) != Permissions.READ && isReadablePath(tree, path, false);
+        boolean isReadable = Permissions.diff(Permissions.READ, permissions) != Permissions.READ && readPolicy.isReadablePath(path, false);
         if (!entries.hasNext() && !isReadable) {
             return false;
         }
 
-        boolean respectParent = (tree != null || path != null) &&
+        boolean respectParent = (path != null) &&
                 (Permissions.includes(permissions, Permissions.ADD_NODE) ||
                         Permissions.includes(permissions, Permissions.REMOVE_NODE) ||
                         Permissions.includes(permissions, Permissions.MODIFY_CHILD_NODE_COLLECTION));
@@ -319,7 +312,7 @@ class CompiledPermissionImpl implements 
         if (respectParent) {
             parentAllowBits = PrivilegeBits.getInstance();
             parentDenyBits = PrivilegeBits.getInstance();
-            parentPath = PermissionUtil.getParentPathOrNull((path != null) ? path : tree.getPath());
+            parentPath = PermissionUtil.getParentPathOrNull(path);
         } else {
             parentAllowBits = PrivilegeBits.EMPTY;
             parentDenyBits = PrivilegeBits.EMPTY;
@@ -404,7 +397,7 @@ class CompiledPermissionImpl implements 
         }
 
         // special handling for paths that are always readable
-        if (isReadablePath(tree, null, false)) {
+        if (tree != null && readPolicy.isReadableTree(tree, false)) {
             allowBits.add(bitsProvider.getBits(PrivilegeConstants.JCR_READ));
         }
         return allowBits;
@@ -417,23 +410,6 @@ class CompiledPermissionImpl implements 
         return concat(userEntries, groupEntries);
     }
 
-    private boolean isReadablePath(@Nullable Tree tree, @Nullable String treePath, boolean exactMatch) {
-        if (readPathsCheckList.length > 0) {
-            String targetPath = (tree != null) ? tree.getPath() : treePath;
-            if (targetPath != null) {
-                for (int i = 0; i < readPathsCheckList.length; i++) {
-                    if (targetPath.equals(readPathsCheckList[i++])) {
-                        return true;
-                    }
-                    if (!exactMatch && targetPath.startsWith(readPathsCheckList[i])) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
     @CheckForNull
     private TreeLocation getLocation(@Nonnull Tree versionStoreTree, @Nullable PropertyState property) {
         String relPath = "";
@@ -491,8 +467,8 @@ class CompiledPermissionImpl implements 
             } else {
                 parent = null;
             }
+            readableTree = readPolicy.isReadableTree(tree, parent);
             isAcTree = (treeType == TreeTypeProvider.TYPE_AC);
-            readableTree = (parent != null && parent.readableTree) || isReadablePath(tree, null, true);
         }
 
         @Override
@@ -543,12 +519,12 @@ class CompiledPermissionImpl implements 
 
         @Override
         public boolean isGranted(long permissions) {
-            return hasPermissions(getIterator(null), permissions, tree, null);
+            return hasPermissions(getIterator(null), permissions, tree.getPath());
         }
 
         @Override
         public boolean isGranted(long permissions, @Nonnull PropertyState property) {
-            return hasPermissions(getIterator(property), permissions, tree, null);
+            return hasPermissions(getIterator(property), permissions, tree.getPath());
         }
 
         private Iterator<PermissionEntry> getIterator(@Nullable PropertyState property) {
@@ -597,4 +573,100 @@ class CompiledPermissionImpl implements 
             }
         }
     }
+
+    private interface ReadPolicy {
+
+        boolean isReadableTree(@Nonnull Tree tree, @Nullable TreePermissionImpl parent);
+        boolean isReadableTree(@Nonnull Tree tree, boolean exactMatch);
+        boolean isReadablePath(@Nullable String treePath, boolean exactMatch);
+    }
+
+    private static final class EmptyReadPolicy implements ReadPolicy {
+
+        private static final ReadPolicy INSTANCE = new EmptyReadPolicy();
+
+        private EmptyReadPolicy() {}
+
+        @Override
+        public boolean isReadableTree(@Nonnull Tree tree, @Nullable TreePermissionImpl parent) {
+            return false;
+        }
+
+        public boolean isReadableTree(@Nonnull Tree tree, boolean exactMatch) {
+            return false;
+        }
+
+        @Override
+        public boolean isReadablePath(@Nullable String treePath, boolean exactMatch) {
+            return false;
+        }
+    }
+
+    private static final class DefaultReadPolicy implements ReadPolicy {
+
+        private final String[] readPaths;
+        private final String[] altReadPaths;
+        private final boolean isDefaultPaths;
+
+        private DefaultReadPolicy(Set<String> readPaths) {
+            this.readPaths = readPaths.toArray(new String[readPaths.size()]);
+            altReadPaths = new String[readPaths.size()];
+            int i = 0;
+            for (String p : this.readPaths) {
+                altReadPaths[i++] = p + '/';
+            }
+            // optimize evaluation for default setup where all readable paths
+            // are located underneath /jcr:system
+            isDefaultPaths = (readPaths.size() == DEFAULT_READ_PATHS.size()) && readPaths.containsAll(DEFAULT_READ_PATHS);
+        }
+
+        public boolean isReadableTree(@Nonnull Tree tree, @Nullable TreePermissionImpl parent) {
+            if (parent != null) {
+                if (parent.readableTree) {
+                    return true;
+                } else if (!isDefaultPaths || parent.tree.getName().equals(JcrConstants.JCR_SYSTEM)) {
+                    return isReadableTree(tree, true);
+                } else  {
+                    return false;
+                }
+            } else {
+                return isReadableTree(tree, true);
+            }
+        }
+
+        public boolean isReadableTree(@Nonnull Tree tree, boolean exactMatch) {
+            String targetPath = tree.getPath();
+            for (String path : readPaths) {
+                if (targetPath.equals(path)) {
+                    return true;
+                }
+            }
+            if (!exactMatch) {
+                for (String path : altReadPaths) {
+                    if (targetPath.startsWith(path)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        public boolean isReadablePath(@Nullable String treePath, boolean exactMatch) {
+            if (treePath != null) {
+                for (String path : readPaths) {
+                    if (treePath.equals(path)) {
+                        return true;
+                    }
+                }
+                if (!exactMatch) {
+                    for (String path : altReadPaths) {
+                        if (treePath.startsWith(path)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+    }
 }

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=1534081&r1=1534080&r2=1534081&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 Mon Oct 21 10:24:50 2013
@@ -39,7 +39,7 @@ import org.apache.jackrabbit.oak.util.Tr
  * permissions use 2 stores, one for the user principals and one for the
  * group principals).
  */
-class PermissionStore implements PermissionConstants {
+final class PermissionStore implements PermissionConstants {
 
     private static final long MAX_SIZE = 250; // TODO define size or make configurable
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/PermissionConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/PermissionConstants.java?rev=1534081&r1=1534080&r2=1534081&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/PermissionConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/PermissionConstants.java Mon Oct 21 10:24:50 2013
@@ -107,9 +107,9 @@ public interface PermissionConstants {
      *
      * @since OAK 1.0
      */
-    String[] DEFAULT_READ_PATHS = new String[] {
+    Set<String> DEFAULT_READ_PATHS = ImmutableSet.of(
             NamespaceConstants.NAMESPACES_PATH,
             NodeTypeConstants.NODE_TYPES_PATH,
             PrivilegeConstants.PRIVILEGES_PATH
-    };
+    );
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/ReadPolicyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/ReadPolicyTest.java?rev=1534081&r1=1534080&r2=1534081&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/ReadPolicyTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/ReadPolicyTest.java Mon Oct 21 10:24:50 2013
@@ -16,11 +16,12 @@
  */
 package org.apache.jackrabbit.oak.security.authorization.accesscontrol;
 
+import java.util.Set;
 import javax.jcr.security.AccessControlPolicy;
 
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
-import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AbstractAccessControlTest;
 import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AbstractAccessControlTest;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,7 +35,7 @@ import static org.junit.Assert.assertTru
  */
 public class ReadPolicyTest extends AbstractAccessControlTest {
 
-    private String[] readPaths;
+    private Set<String> readPaths;
 
     @Override
     @Before

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImplTest.java?rev=1534081&r1=1534080&r2=1534081&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImplTest.java Mon Oct 21 10:24:50 2013
@@ -19,8 +19,10 @@ package org.apache.jackrabbit.oak.securi
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.UserManager;
@@ -52,12 +54,12 @@ import static org.junit.Assert.assertTru
 public class PermissionProviderImplTest extends AbstractSecurityTest implements AccessControlConstants {
 
     private static final String ADMINISTRATOR_GROUP = "administrators";
-    private static final String[] READ_PATHS = new String[] {
+    private static final Set<String> READ_PATHS = ImmutableSet.of(
             NamespaceConstants.NAMESPACES_PATH,
             NodeTypeConstants.NODE_TYPES_PATH,
             PrivilegeConstants.PRIVILEGES_PATH,
             "/test"
-    };
+    );
 
     private Group adminstrators;