Author: mduerig
Date: Wed Nov 20 17:06:38 2013
New Revision: 1543881

URL: http://svn.apache.org/r1543881
Log:
OAK-1163: Observation events should respect permissions
First draft for AC filtering of observation events

Added:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/FilterProvider.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java?rev=1543881&r1=1543880&r2=1543881&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
 Wed Nov 20 17:06:38 2013
@@ -34,6 +34,7 @@ import org.apache.jackrabbit.api.jmx.Eve
 import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
 import org.apache.jackrabbit.commons.observation.ListenerTracker;
 import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.core.ImmutableRoot;
 import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
@@ -41,6 +42,8 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.Observable;
 import org.apache.jackrabbit.oak.spi.commit.Observer;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
@@ -59,6 +62,7 @@ public class ChangeProcessor implements 
     private static final Logger log = 
LoggerFactory.getLogger(ChangeProcessor.class);
 
     private final ContentSession contentSession;
+    private final PermissionProvider permissionProvider;
     private final NamePathMapper namePathMapper;
     private final ListenerTracker tracker;
     private final EventListener eventListener;
@@ -69,10 +73,13 @@ public class ChangeProcessor implements 
     private NodeState previousRoot;
 
     public ChangeProcessor(
-            ContentSession contentSession, NamePathMapper namePathMapper,
+            ContentSession contentSession,
+            PermissionProvider permissionProvider,
+            NamePathMapper namePathMapper,
             ListenerTracker tracker, FilterProvider filter) {
         checkArgument(contentSession instanceof Observable);
         this.contentSession = contentSession;
+        this.permissionProvider = permissionProvider;
         this.namePathMapper = namePathMapper;
         this.tracker = tracker;
         eventListener = tracker.getTrackedListener();
@@ -126,9 +133,10 @@ public class ChangeProcessor implements 
                     String path = 
namePathMapper.getOakPath(provider.getPath());
                     ImmutableTree beforeTree = getTree(previousRoot, path);
                     ImmutableTree afterTree = getTree(root, path);
+                    TreePermission treePermission = 
getTreePermission(afterTree);
                     EventIterator<Event> events = new EventIterator<Event>(
                             beforeTree.getNodeState(), 
afterTree.getNodeState(), path,
-                            provider.getFilter(beforeTree, afterTree),
+                            provider.getFilter(beforeTree, afterTree, 
treePermission),
                             new JcrListener(beforeTree, afterTree, 
namePathMapper, info));
                     if (events.hasNext()) {
                         eventListener.onEvent(new 
EventIteratorAdapter(events));
@@ -145,4 +153,7 @@ public class ChangeProcessor implements 
         return new ImmutableRoot(nodeState).getTree(path);
     }
 
+    private TreePermission getTreePermission(Tree tree) {
+        return permissionProvider.getTreePermission(tree, 
TreePermission.EMPTY);
+    }
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/FilterProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/FilterProvider.java?rev=1543881&r1=1543880&r2=1543881&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/FilterProvider.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/FilterProvider.java
 Wed Nov 20 17:06:38 2013
@@ -33,6 +33,7 @@ import com.google.common.base.Objects;
 import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
+import org.apache.jackrabbit.oak.plugins.observation.filter.ACFilter;
 import 
org.apache.jackrabbit.oak.plugins.observation.filter.EventGenerator.Filter;
 import org.apache.jackrabbit.oak.plugins.observation.filter.EventTypeFilter;
 import org.apache.jackrabbit.oak.plugins.observation.filter.Filters;
@@ -40,6 +41,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.observation.filter.PathFilter;
 import org.apache.jackrabbit.oak.plugins.observation.filter.UuidFilter;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
 
 /**
  * Provider for a filter filtering observation events according to a certain 
criterion.
@@ -92,7 +94,8 @@ public class FilterProvider {
             && (includeClusterExternal || !isExternal(info));
     }
 
-    public Filter getFilter(ImmutableTree beforeTree, ImmutableTree afterTree) 
{
+    public Filter getFilter(ImmutableTree beforeTree, ImmutableTree afterTree,
+            TreePermission treePermission) {
         List<Filter> filters = Lists.<Filter>newArrayList(
                 new PathFilter(beforeTree, afterTree, path, deep));
 
@@ -119,7 +122,7 @@ public class FilterProvider {
             }
         }
 
-        // TODO add filter based on access rights of the reading session. See 
OAK-1163
+        filters.add(new ACFilter(beforeTree, afterTree, treePermission));
         return Filters.all(filters.toArray(new Filter[filters.size()]));
     }
 

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java?rev=1543881&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ACFilter.java
 Wed Nov 20 17:06:38 2013
@@ -0,0 +1,96 @@
+/*
+ * 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.plugins.observation.filter;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.ImmutableTree;
+import 
org.apache.jackrabbit.oak.plugins.observation.filter.EventGenerator.Filter;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * {@code EventTypeFilter} filters based on the access rights of the observing 
session.
+ */
+public class ACFilter implements Filter {
+    private final ImmutableTree beforeTree;
+    private final ImmutableTree afterTree;
+    private final TreePermission treePermission;
+
+    /**
+     * Create a new {@code Filter} instance that includes an event when the
+     * observing session has sufficient permissions to read the associated 
item.
+     *
+     * @param beforeTree  before state of the node being filtered
+     * @param afterTree   after state of the node being filtered
+     * @param treePermission  tree permission for the node being filtered
+     */
+    public ACFilter(@Nonnull ImmutableTree beforeTree, @Nonnull ImmutableTree 
afterTree,
+            @Nonnull TreePermission treePermission) {
+        this.beforeTree = checkNotNull(beforeTree);
+        this.afterTree = checkNotNull(afterTree);
+        this.treePermission = checkNotNull(treePermission);
+    }
+
+    @Override
+    public boolean includeAdd(PropertyState after) {
+        return treePermission.canRead(after);
+    }
+
+    @Override
+    public boolean includeChange(PropertyState before, PropertyState after) {
+        return treePermission.canRead(after);
+    }
+
+    @Override
+    public boolean includeDelete(PropertyState before) {
+        return treePermission.canRead(before);
+    }
+
+    @Override
+    public boolean includeAdd(String name, NodeState after) {
+        return treePermission.getChildPermission(name, after).canRead();
+    }
+
+    @Override
+    public boolean includeChange(String name, NodeState before, NodeState 
after) {
+        return treePermission.getChildPermission(name, after).canRead();
+    }
+
+    @Override
+    public boolean includeDelete(String name, NodeState before) {
+        return treePermission.getChildPermission(name, before).canRead();
+    }
+
+    @Override
+    public boolean includeMove(String sourcePath, String destPath, NodeState 
moved) {
+        return treePermission.getChildPermission(PathUtils.getName(destPath), 
moved).canRead();
+    }
+
+    @Override
+    public Filter create(String name, NodeState before, NodeState after) {
+        return new ACFilter(beforeTree.getChild(name), 
afterTree.getChild(name),
+                treePermission.getChildPermission(name, after));
+    }
+}

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java?rev=1543881&r1=1543880&r2=1543881&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
 Wed Nov 20 17:06:38 2013
@@ -44,6 +44,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.observation.ExcludeExternal;
 import org.apache.jackrabbit.oak.plugins.observation.FilterProvider;
 import org.apache.jackrabbit.oak.spi.commit.Observable;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -65,6 +66,7 @@ public class ObservationManagerImpl impl
 
     private final SessionDelegate sessionDelegate;
     private final ReadOnlyNodeTypeManager ntMgr;
+    private final PermissionProvider permissionProvider;
     private final NamePathMapper namePathMapper;
     private final Whiteboard whiteboard;
 
@@ -81,10 +83,12 @@ public class ObservationManagerImpl impl
      */
     public ObservationManagerImpl(
             SessionDelegate sessionDelegate, ReadOnlyNodeTypeManager 
nodeTypeManager,
+            PermissionProvider permissionProvider,
             NamePathMapper namePathMapper, Whiteboard whiteboard) {
 
         this.sessionDelegate = sessionDelegate;
         this.ntMgr = nodeTypeManager;
+        this.permissionProvider = permissionProvider;
         this.namePathMapper = namePathMapper;
         this.whiteboard = whiteboard;
     }
@@ -124,7 +128,7 @@ public class ObservationManagerImpl impl
                 }
             };
             processor = new ChangeProcessor(
-                    sessionDelegate.getContentSession(), namePathMapper, 
tracker, filterProvider);
+                    sessionDelegate.getContentSession(), permissionProvider, 
namePathMapper, tracker, filterProvider);
             processors.put(listener, processor);
             processor.start(whiteboard);
         } else {

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java?rev=1543881&r1=1543880&r2=1543881&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
 Wed Nov 20 17:06:38 2013
@@ -96,6 +96,7 @@ public class SessionContext implements N
     private SessionImpl session = null;
     private WorkspaceImpl workspace = null;
 
+    private PermissionProvider permissionProvider;
     private AccessControlManager accessControlManager;
     private AccessManager accessManager;
     private PrincipalManager principalManager;
@@ -257,6 +258,7 @@ public class SessionContext implements N
             observationManager = new ObservationManagerImpl(
                 delegate,
                 ReadOnlyNodeTypeManager.getInstance(delegate.getRoot(), 
namePathMapper),
+                getPermissionProvider(),
                 namePathMapper, whiteboard);
         }
         return observationManager;
@@ -351,10 +353,7 @@ public class SessionContext implements N
     @Nonnull
     public AccessManager getAccessManager() throws RepositoryException {
         if (accessManager == null) {
-            PermissionProvider pp = checkNotNull(securityProvider)
-                    .getConfiguration(AuthorizationConfiguration.class)
-                    .getPermissionProvider(delegate.getRoot(), 
delegate.getAuthInfo().getPrincipals());
-            accessManager = new AccessManager(delegate, pp);
+            accessManager = new AccessManager(delegate, 
getPermissionProvider());
         }
         return accessManager;
     }
@@ -411,4 +410,15 @@ public class SessionContext implements N
         return securityProvider.getConfiguration(clss);
     }
 
+    private PermissionProvider getPermissionProvider() {
+        // FIXME: review whether 'auto-refresh' should rather be made on a 
wrapping
+        //        permission provider instead of doing this in the access 
manager
+        //        since this permission provider is also passed to the 
observation manager.
+        if (permissionProvider == null) {
+            permissionProvider = checkNotNull(securityProvider)
+                    .getConfiguration(AuthorizationConfiguration.class)
+                    .getPermissionProvider(delegate.getRoot(), 
delegate.getAuthInfo().getPrincipals());
+        }
+        return permissionProvider;
+    }
 }


Reply via email to