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/07 11:20:58 UTC

svn commit: r1443386 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java

Author: angela
Date: Thu Feb  7 10:20:56 2013
New Revision: 1443386

URL: http://svn.apache.org/viewvc?rev=1443386&view=rev
Log:
OAK-527: permissions (wip)

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java?rev=1443386&r1=1443385&r2=1443386&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java Thu Feb  7 10:20:56 2013
@@ -17,22 +17,185 @@
 package org.apache.jackrabbit.oak.security.authorization;
 
 import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.ReadOnlyTree;
+import org.apache.jackrabbit.oak.core.TreeImpl;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * {@code CommitHook} implementation that processes any modification made to
  * access control content and updates persisted permission caches associated
  * with access control related data stored in the repository.
  */
-class PermissionHook implements CommitHook {
+public class PermissionHook implements CommitHook, AccessControlConstants {
+
+    private static final Logger log = LoggerFactory.getLogger(PermissionHook.class);
 
     @Nonnull
     @Override
-    public NodeState processCommit(NodeState before, NodeState after) throws CommitFailedException {
-        // TODO OAK-526: add implementation
-        return after;
+    public NodeState processCommit(final NodeState before, NodeState after) throws CommitFailedException {
+        NodeBuilder rootBuilder = after.builder();
+
+        String workspaceName = "default"; // TODO
+        NodeBuilder permissionRoot = rootBuilder.child(NodeTypeConstants.JCR_SYSTEM).child(REP_PERMISSION_STORE).child(workspaceName);
+        ReadOnlyNodeTypeManager ntMgr = ReadOnlyNodeTypeManager.getInstance(before);
+
+        after.compareAgainstBaseState(before, new Diff(new Node(rootBuilder), permissionRoot, ntMgr));
+        return rootBuilder.getNodeState();
+    }
+
+    private static class Diff implements NodeStateDiff {
+
+        private final ReadOnlyNodeTypeManager ntMgr;
+        private final NodeBuilder permissionRoot;
+        private final Node parentAfter;
+
+        private Diff(@Nonnull Node node, NodeBuilder permissionRoot, ReadOnlyNodeTypeManager ntMgr) {
+            this.ntMgr = ntMgr;
+            this.permissionRoot = permissionRoot;
+            this.parentAfter = node;
+        }
+
+        @Override
+        public void propertyAdded(PropertyState after) {
+            // nothing to do
+        }
+
+        @Override
+        public void propertyChanged(PropertyState before, PropertyState after) {
+            if (isACL(parentAfter) && TreeImpl.OAK_CHILD_ORDER.equals(before.getName())) {
+                updateEntries();
+            }
+        }
+
+        @Override
+        public void propertyDeleted(PropertyState before) {
+            // nothing to do
+        }
+
+        @Override
+        public void childNodeAdded(String name, NodeState after) {
+            if (isACE(name, after)) {
+                addEntry(name, after);
+            } else {
+                NodeState before = MemoryNodeState.EMPTY_NODE;
+                Node node = new Node(parentAfter, name);
+                after.compareAgainstBaseState(before, new Diff(node, permissionRoot, ntMgr));
+            }
+        }
+
+        @Override
+        public void childNodeChanged(String name, NodeState before, NodeState after) {
+            if (isACE(name, before) || isACE(name, after)) {
+                updateEntry(name, before, after);
+            } else {
+                Node node = new Node(parentAfter, name);
+                after.compareAgainstBaseState(before, new Diff(node, permissionRoot, ntMgr));
+            }
+        }
+
+        @Override
+        public void childNodeDeleted(String name, NodeState before) {
+            if (isACE(name, before)) {
+                removeEntry(name, before);
+            } else {
+                Node after = new Node(parentAfter.path, name);
+                after.builder.getNodeState().compareAgainstBaseState(before, new Diff(after, permissionRoot, ntMgr));
+            }
+        }
+
+        //--------------------------------------------------------< private >---
+        private boolean isACL(Node parent) {
+            try {
+                return ntMgr.isNodeType(getTree(parent.getName(), parent.getNodeState()), NT_REP_POLICY);
+            } catch (RepositoryException e) {
+                return false;
+            }
+        }
+
+        private boolean isACE(String name, NodeState nodeState) {
+            try {
+                return ntMgr.isNodeType(getTree(name, nodeState), NT_REP_ACE);
+            } catch (RepositoryException e) {
+                return false;
+            }
+        }
+
+        private static String getAccessControlledPath(Node aclNode) {
+            return Text.getRelativeParent(aclNode.path, 1);
+        }
+
+        private static Tree getTree(String name, NodeState nodeState) {
+            // FIXME: this readonlytree is not properly connect to it's parent
+            return new ReadOnlyTree(null, name, nodeState);
+        }
+
+        private void addEntry(String name, NodeState after) {
+            String accessControlledPath = getAccessControlledPath(parentAfter);
+            // TODO
+            //log.info("add entry:" + name);
+        }
+
+        private void removeEntry(String name, NodeState after) {
+            String accessControlledPath = getAccessControlledPath(parentAfter);
+            // TODO
+            //log.info("remove entry" + name);
+        }
+
+        private void updateEntry(String name, NodeState after, NodeState before) {
+            String accessControlledPath = getAccessControlledPath(parentAfter);
+            // TODO
+            //log.info("update"+ name);
+        }
+
+        private void updateEntries() {
+            String accessControlledPath = getAccessControlledPath(parentAfter);
+            NodeState aclState = parentAfter.getNodeState();
+
+            // TODO
+        }
+    }
+
+    private static final class Node {
+
+        private final String path;
+        private final NodeBuilder builder;
+
+        private Node(NodeBuilder rootBuilder) {
+            this.path = "/";
+            this.builder = rootBuilder;
+        }
+
+        private Node(String parentPath, String name) {
+            this.path = PathUtils.concat(parentPath, name);
+            this.builder = MemoryNodeState.EMPTY_NODE.builder();
+        }
+
+        private Node(Node parent, String name) {
+            this.builder = parent.builder.child(name);
+            this.path = PathUtils.concat(parent.path, name);
+        }
+
+        private String getName() {
+            return Text.getName(path);
+        }
+
+        private NodeState getNodeState() {
+            return builder.getNodeState();
+        }
     }
 }
\ No newline at end of file