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;
+ }
}