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/02/28 19:27:07 UTC

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

Author: angela
Date: Thu Feb 28 18:27:06 2013
New Revision: 1451277

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

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/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/PermissionProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/OpenPermissionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/PermissionProvider.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java?rev=1451277&r1=1451276&r2=1451277&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java Thu Feb 28 18:27:06 2013
@@ -78,11 +78,10 @@ public class RootImpl implements Root {
 
     private final Subject subject;
 
-    /**
-     * The security provider.
-     */
     private final SecurityProvider securityProvider;
 
+    private final QueryIndexProvider indexProvider;
+
     /**
      * Current branch this root operates on
      */
@@ -99,7 +98,7 @@ public class RootImpl implements Root {
      */
     private int modCount;
 
-    private final QueryIndexProvider indexProvider;
+    private PermissionProvider permissionProvider;
 
     /**
      * New instance bases on a given {@link NodeStore} and a workspace
@@ -228,6 +227,7 @@ public class RootImpl implements Root {
             purgePendingChanges();
             branch.rebase();
             rootTree = TreeImpl.createRoot(this);
+            permissionProvider = createPermissionProvider();
         }
     }
 
@@ -237,6 +237,11 @@ public class RootImpl implements Root {
         branch = store.branch();
         rootTree = TreeImpl.createRoot(this);
         modCount = 0;
+        if (permissionProvider == null) {
+            permissionProvider = createPermissionProvider();
+        } else {
+            permissionProvider.refresh();
+        }
     }
 
     @Override
@@ -355,6 +360,7 @@ public class RootImpl implements Root {
         };
     }
 
+    @Nonnull
     private QueryIndexProvider getIndexProvider() {
         if (hasPendingChanges()) {
             return new UUIDDiffIndexProviderWrapper(indexProvider,
@@ -375,6 +381,7 @@ public class RootImpl implements Root {
         return branch.getBase();
     }
 
+    @Nonnull
     NodeBuilder createRootBuilder() {
         return branch.getHead().builder();
     }
@@ -387,8 +394,9 @@ public class RootImpl implements Root {
         }
     }
 
+    @Nonnull
     PermissionProvider getPermissionProvider() {
-        return securityProvider.getAccessControlConfiguration().getPermissionProvider(this, subject.getPrincipals());
+        return permissionProvider;
     }
 
     //------------------------------------------------------------< private >---
@@ -408,4 +416,7 @@ public class RootImpl implements Root {
         rootTree.getNodeBuilder().reset(branch.getHead());
     }
 
+    private PermissionProvider createPermissionProvider() {
+        return  securityProvider.getAccessControlConfiguration().getPermissionProvider(this, subject.getPrincipals());
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java?rev=1451277&r1=1451276&r2=1451277&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java Thu Feb 28 18:27:06 2013
@@ -109,7 +109,6 @@ public class AccessControlManagerImpl im
 
         Subject subject = Subject.getSubject(AccessController.getContext());
         Set<Principal> principals = (subject != null) ? subject.getPrincipals() : Collections.<Principal>emptySet();
-        // FIXME: keep permission provider up to date.
         permissionProvider = acConfig.getPermissionProvider(root, principals);
         restrictionProvider = acConfig.getRestrictionProvider(namePathMapper);
         ntMgr = ReadOnlyNodeTypeManager.getInstance(root, namePathMapper);
@@ -131,12 +130,14 @@ public class AccessControlManagerImpl im
 
     @Override
     public boolean hasPrivileges(@Nullable String absPath, @Nonnull Privilege[] privileges) throws RepositoryException {
+        permissionProvider.refresh();
         return hasPrivileges(absPath, privileges, permissionProvider);
     }
 
     @Nonnull
     @Override
     public Privilege[] getPrivileges(@Nullable String absPath) throws RepositoryException {
+        permissionProvider.refresh();
         return getPrivileges(absPath, permissionProvider);
     }
 

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=1451277&r1=1451276&r2=1451277&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 Thu Feb 28 18:27:06 2013
@@ -18,9 +18,11 @@ package org.apache.jackrabbit.oak.securi
 
 import java.security.Principal;
 import java.security.acl.Group;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -28,6 +30,7 @@ import com.google.common.collect.Immutab
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.core.ReadOnlyRoot;
 import org.apache.jackrabbit.oak.core.ReadOnlyTree;
 import org.apache.jackrabbit.oak.security.authorization.AccessControlConstants;
 import org.apache.jackrabbit.oak.security.privilege.PrivilegeBits;
@@ -35,6 +38,7 @@ import org.apache.jackrabbit.oak.securit
 import org.apache.jackrabbit.oak.spi.security.authorization.Permissions;
 import org.apache.jackrabbit.util.Text;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
@@ -43,28 +47,29 @@ import static com.google.common.base.Pre
 class CompiledPermissionImpl implements CompiledPermissions, AccessControlConstants {
 
     private final Set<Principal> principals;
-    private final PrivilegeBitsProvider bitsProvider;
+    private final Map<String, ReadOnlyTree> trees;
 
-    private final Map<Key, Entry> userEntries;
-    private final Map<Key, Entry> groupEntries;
+    private PrivilegeBitsProvider bitsProvider;
+    private Map<Key, Entry> userEntries;
+    private Map<Key, Entry> groupEntries;
 
     CompiledPermissionImpl(@Nonnull Set<Principal> principals,
-                           @Nonnull PrivilegeBitsProvider bitsProvider,
-                           @Nonnull ReadOnlyTree permissionsTree) {
+                           @Nonnull ReadOnlyTree permissionsTree,
+                           @Nonnull PrivilegeBitsProvider bitsProvider) {
         this.principals = checkNotNull(principals);
-        this.bitsProvider = bitsProvider;
+        checkArgument(!principals.isEmpty());
+        this.trees = new HashMap<String, ReadOnlyTree>(principals.size());
+        update(permissionsTree, bitsProvider);
+    }
 
-        EntriesBuilder builder = new EntriesBuilder();
-        for (Principal principal : principals) {
-            Tree t = permissionsTree.getChild(Text.escapeIllegalJcrChars(principal.getName()));
-            if (t != null) {
-                builder.addEntry(principal, t);
-            }
-        }
-        userEntries = builder.userEntries.build();
-        groupEntries = builder.groupEntries.build();
+    void update(@Nonnull ReadOnlyTree permissionsTree, @Nonnull PrivilegeBitsProvider bitsProvider) {
+        // TODO: determine if entries need to be reloaded due to changes to the
+        // TODO: affected permission-nodes.
+        this.bitsProvider = bitsProvider;
+        buildEntries(permissionsTree);
     }
 
+    //------------------------------------------------< CompiledPermissions >---
     @Override
     public boolean canRead(Tree tree) {
         return isGranted(tree, Permissions.READ_NODE);
@@ -108,6 +113,25 @@ class CompiledPermissionImpl implements 
     }
 
     //------------------------------------------------------------< private >---
+
+    private void buildEntries(ReadOnlyTree permissionsTree) {
+        EntriesBuilder builder = new EntriesBuilder();
+        for (Principal principal : principals) {
+            ReadOnlyTree t = getPrincipalRoot(permissionsTree, principal);
+            if (t != null) {
+                trees.put(principal.getName(), t);
+                builder.addEntry(principal, t);
+            }
+        }
+        userEntries = builder.userEntries.build();
+        groupEntries = builder.groupEntries.build();
+    }
+
+    @CheckForNull
+    private static ReadOnlyTree getPrincipalRoot(ReadOnlyTree permissionsTree, Principal principal) {
+        return permissionsTree.getChild(Text.escapeIllegalJcrChars(principal.getName()));
+    }
+
     private boolean hasPermissions(@Nonnull Tree tree, @Nullable PropertyState property,
                                    long permissions) {
         // TODO
@@ -150,6 +174,10 @@ class CompiledPermissionImpl implements 
         }
     }
 
+    /**
+     * Collects permission entries for different principals and asserts they are
+     * in the correct order for proper and efficient evaluation.
+     */
     private static final class EntriesBuilder {
 
         private ImmutableSortedMap.Builder<Key, Entry> userEntries = ImmutableSortedMap.naturalOrder();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java?rev=1451277&r1=1451276&r2=1451277&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java Thu Feb 28 18:27:06 2013
@@ -59,7 +59,7 @@ public class PermissionProviderImpl impl
 
     private static final Logger log = LoggerFactory.getLogger(PermissionProviderImpl.class);
 
-    private final ReadOnlyRoot root;
+    private final Root root;
 
     private final Context acContext;
 
@@ -69,22 +69,27 @@ public class PermissionProviderImpl impl
 
     public PermissionProviderImpl(@Nonnull Root root, @Nonnull Set<Principal> principals,
                                   @Nonnull SecurityProvider securityProvider) {
-        this.root = new ReadOnlyRoot(root);
+        this.root = root;
         this.acContext = securityProvider.getAccessControlConfiguration().getContext();
         if (principals.contains(SystemPrincipal.INSTANCE) || isAdmin(principals)) {
             compiledPermissions = AllPermissions.getInstance();
         } else {
-            String relativePath = PERMISSIONS_STORE_PATH + '/' + workspaceName;
-            ReadOnlyTree rootTree = this.root.getTree("/");
-            ReadOnlyTree permissionsTree = getPermissionsRoot(rootTree, relativePath);
-            if (permissionsTree == null) {
+            ReadOnlyTree permissionsTree = getPermissionsRoot();
+            if (permissionsTree == null || principals.isEmpty()) {
                 compiledPermissions = NoPermissions.getInstance();
             } else {
-                compiledPermissions = new CompiledPermissionImpl(principals, new PrivilegeBitsProvider(this.root), permissionsTree);
+                compiledPermissions = new CompiledPermissionImpl(principals, permissionsTree, getBitsProvider());
             }
         }
     }
 
+    @Override
+    public void refresh() {
+        if (compiledPermissions instanceof CompiledPermissionImpl) {
+            ((CompiledPermissionImpl) compiledPermissions).update(getPermissionsRoot(), getBitsProvider());
+        }
+    }
+
     @Nonnull
     @Override
     public Set<String> getPrivileges(@Nullable Tree tree) {
@@ -145,7 +150,7 @@ public class PermissionProviderImpl impl
 
     @Override
     public boolean hasPermission(@Nonnull String oakPath, @Nonnull String jcrActions) {
-        TreeLocation location = root.getLocation(oakPath);
+        TreeLocation location = getReadOnlyRoot().getLocation(oakPath);
         long permissions = Permissions.getPermissions(jcrActions, location);
         if (!location.exists()) {
             // TODO: deal with version content
@@ -173,12 +178,27 @@ public class PermissionProviderImpl impl
         return false;
     }
 
+    private ReadOnlyRoot getReadOnlyRoot() {
+        if (root instanceof ReadOnlyRoot) {
+            return (ReadOnlyRoot) root;
+        } else {
+            return new ReadOnlyRoot(root);
+        }
+    }
+
     @CheckForNull
-    private static ReadOnlyTree getPermissionsRoot(ReadOnlyTree rootTree, String relativePath) {
+    private ReadOnlyTree getPermissionsRoot() {
+        String relativePath = PERMISSIONS_STORE_PATH + '/' + workspaceName;
+        ReadOnlyTree rootTree = checkNotNull(getReadOnlyRoot().getTree("/"));
         Tree tree = rootTree.getLocation().getChild(relativePath).getTree();
         return (tree == null) ? null : (ReadOnlyTree) tree;
     }
 
+    @Nonnull
+    private PrivilegeBitsProvider getBitsProvider() {
+        return new PrivilegeBitsProvider(getReadOnlyRoot());
+    }
+
     private boolean isAccessControlContent(@Nonnull Tree tree) {
         return acContext.definesTree(tree);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/OpenPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/OpenPermissionProvider.java?rev=1451277&r1=1451276&r2=1451277&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/OpenPermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/OpenPermissionProvider.java Thu Feb 28 18:27:06 2013
@@ -39,6 +39,11 @@ public final class OpenPermissionProvide
         return INSTANCE;
     }
 
+    @Override
+    public void refresh() {
+        // nothing to do
+    }
+
     @Nonnull
     @Override
     public Set<String> getPrivileges(@Nullable Tree tree) {
@@ -79,4 +84,4 @@ public final class OpenPermissionProvide
     public boolean hasPermission(@Nonnull String oakPath, @Nonnull String jcrActions) {
         return true;
     }
-}
\ No newline at end of file
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/PermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/PermissionProvider.java?rev=1451277&r1=1451276&r2=1451277&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/PermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/PermissionProvider.java Thu Feb 28 18:27:06 2013
@@ -28,6 +28,8 @@ import org.apache.jackrabbit.oak.api.Tre
  */
 public interface PermissionProvider {
 
+    void refresh();
+
     @Nonnull
     Set<String> getPrivileges(@Nullable Tree tree);