| /* |
| * 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 org.apache.jackrabbit.oak.api.PropertyState; |
| import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory; |
| 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.jetbrains.annotations.NotNull; |
| |
| /** |
| * {@code EventTypeFilter} filters based on the access rights of the observing session. |
| */ |
| public final class ACFilter implements EventFilter { |
| |
| private final NodeState before; |
| |
| private final NodeState after; |
| |
| private final String name; |
| |
| private final ACFilter parentFilter; |
| |
| private final PermissionProvider permissionProvider; |
| |
| private TreePermission treePermission; |
| |
| private ACFilter(@NotNull NodeState before, |
| @NotNull NodeState after, |
| @NotNull String name, |
| @NotNull PermissionProvider permissionProvider, |
| @NotNull ACFilter parentFilter) { |
| this.before = checkNotNull(before); |
| this.after = checkNotNull(after); |
| this.name = checkNotNull(name); |
| this.permissionProvider = checkNotNull(permissionProvider); |
| this.parentFilter = checkNotNull(parentFilter); |
| } |
| |
| /** |
| * Create a new {@code Filter} instance that includes an event when the |
| * observing session has sufficient permissions to read the associated item. |
| * |
| * @param before before state |
| * @param after after state |
| * @param permissionProvider permission provider for access control evaluation |
| */ |
| public ACFilter(@NotNull NodeState before, |
| @NotNull NodeState after, |
| @NotNull PermissionProvider permissionProvider) { |
| this.before = checkNotNull(before); |
| this.after = checkNotNull(after); |
| this.name = null; |
| this.permissionProvider = checkNotNull(permissionProvider); |
| this.parentFilter = null; |
| } |
| |
| @Override |
| public boolean includeAdd(PropertyState after) { |
| return getTreePermission().canRead(after); |
| } |
| |
| @Override |
| public boolean includeChange(PropertyState before, PropertyState after) { |
| return getTreePermission().canRead(after); |
| } |
| |
| @Override |
| public boolean includeDelete(PropertyState before) { |
| return getTreePermission().canRead(before); |
| } |
| |
| @Override |
| public boolean includeAdd(String name, NodeState after) { |
| return getTreePermission().getChildPermission(name, after).canRead(); |
| } |
| |
| @Override |
| public boolean includeDelete(String name, NodeState before) { |
| return getTreePermission().getChildPermission(name, before).canRead(); |
| } |
| |
| @Override |
| public boolean includeMove(String sourcePath, String name, NodeState moved) { |
| // TODO: check access to the source path, it might not be accessible |
| return getTreePermission().getChildPermission(name, moved).canRead(); |
| } |
| |
| @Override |
| public boolean includeReorder(String destName, String name, NodeState reordered) { |
| // TODO: check access to the dest name, it might not be accessible |
| return getTreePermission().getChildPermission(name, reordered).canRead(); |
| } |
| |
| @Override |
| public EventFilter create(String name, NodeState before, NodeState after) { |
| return new ACFilter(before, after, name, permissionProvider, this); |
| } |
| |
| //-----------------------------< internal >--------------------------------- |
| |
| private TreePermission getTreePermission() { |
| TreePermission tp = treePermission; |
| if (tp == null) { |
| if (parentFilter == null) { |
| tp = permissionProvider.getTreePermission( |
| TreeFactory.createReadOnlyTree((after.exists() ? after : before)), TreePermission.EMPTY); |
| } else { |
| tp = parentFilter.getTreePermission().getChildPermission(name, after); |
| } |
| treePermission = tp; |
| } |
| return tp; |
| } |
| } |