Package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl

Source Code of org.apache.jackrabbit.oak.spi.security.authorization.cug.impl.CugPermissionProvider$EmptyCugPermission

/*
* 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.spi.security.authorization.cug.impl;

import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.jcr.Session;

import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.core.ImmutableRoot;
import org.apache.jackrabbit.oak.plugins.tree.ImmutableTree;
import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
import org.apache.jackrabbit.oak.spi.security.Context;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class CugPermissionProvider implements PermissionProvider, AggregatedPermissionProvider, CugConstants {

    private static final Logger log = LoggerFactory.getLogger(CugPermissionProvider.class);

    private static final Set<String> READ_NAMES = ImmutableSet.of(
            Session.ACTION_READ,
            Permissions.PERMISSION_NAMES.get(Permissions.READ),
            Permissions.PERMISSION_NAMES.get(Permissions.READ_NODE),
            Permissions.PERMISSION_NAMES.get(Permissions.READ_PROPERTY));

    private static final Set<String> READ_PRIVILEGE_NAMES = ImmutableSet.of(
            PrivilegeConstants.JCR_READ,
            PrivilegeConstants.REP_READ_NODES,
            PrivilegeConstants.REP_READ_PROPERTIES
    );

    private final Root root;
    private final Set<String> principalNames;

    private final ControlFlag flag;
    private final Context ctx;

    private final String[] supportedPaths;
    private final String[] supportedAltPaths;

    private ImmutableRoot immutableRoot;

    CugPermissionProvider(@Nonnull Root root,
                          @Nonnull Set<Principal> principals,
                          @Nonnull String[] supportedPaths,
                          @Nonnull ControlFlag flag,
                          @Nonnull Context ctx) {
        this.root = root;
        this.immutableRoot = ImmutableRoot.getInstance(root);
        principalNames = new HashSet<String>(principals.size());
        for (Principal p : Iterables.filter(principals, Predicates.notNull())) {
            principalNames.add(p.getName());
        }

        this.flag = flag;

        this.supportedPaths = supportedPaths;
        supportedAltPaths = new String[supportedPaths.length];
        int i = 0;
        for (String p : supportedPaths) {
            supportedAltPaths[i++] = p + '/';
        }

        this.ctx = ctx;
    }

    //---------------------------------------< AggregatedPermissionProvider >---

    public ControlFlag getFlag() {
        return flag;
    }

    public boolean handles(String path, String jcrAction) {
        return isReadAction(jcrAction) && includesCug(immutableRoot.getTree(path), path);
    }

    public boolean handles(Tree tree) {
        return includesCug(tree, tree.getPath());
    }

    public boolean handles(Tree tree, long permission) {
        return isRead(permission) && includesCug(tree, tree.getPath());
    }

    @Override
    public boolean handles(@Nonnull TreePermission treePermission, long permission) {
        if (isRead(permission)) {
            return treePermission instanceof CugTreePermission;
        } else {
            return false;
        }
    }

    public boolean handlesRepositoryPermissions() {
        return false;
    }

    //-------------------------------------------------< PermissionProvider >---
    public void refresh() {
        immutableRoot = ImmutableRoot.getInstance(root);
    }

    public Set<String> getPrivileges(Tree tree) {
        if (canRead(tree)) {
            return READ_PRIVILEGE_NAMES;
        } else {
            return Collections.emptySet();
        }
    }

    public boolean hasPrivileges(Tree tree, String... privilegeNames) {
        for (String privilegeName : privilegeNames) {
            if (!READ_PRIVILEGE_NAMES.contains(privilegeName)) {
                return false;
            }
        }
        return canRead(tree);
    }

    public RepositoryPermission getRepositoryPermission() {
        throw new UnsupportedOperationException("Not supported");
    }

    public TreePermission getTreePermission(Tree tree, TreePermission parentPermission) {
        ImmutableTree immutableTree = getImmutableTree(tree);
        if (ctx.definesContextRoot(immutableTree)) {
            return TreePermission.EMPTY;
        }
        if (parentPermission instanceof CugTreePermission) {
            if (hasCug(immutableTree)) {
                return createCugPermission(immutableTree);
            } else {
                return new CugTreePermission(immutableTree, ((CugTreePermission) parentPermission).allow);
            }
        } else if (parentPermission == TreePermission.EMPTY && !immutableTree.isRoot()) {
            return TreePermission.EMPTY;
        } else {
            String path = immutableTree.getPath();
            if (includes(path)) {
                return createCugPermission(immutableTree);
            } else if (mayContainCug(path)) {
                return new EmptyCugPermission(immutableTree);
            } else {
                return TreePermission.EMPTY;
            }
        }
    }

    public boolean isGranted(Tree tree, PropertyState property, long permissions) {
        long diff = Permissions.diff(permissions, Permissions.READ);
        if (diff != Permissions.NO_PERMISSION) {
            return false;
        } else {
            return canRead(tree);
        }
    }

    public boolean isGranted(String oakPath, String jcrActions) {
        TreeLocation location = TreeLocation.create(immutableRoot, oakPath);
        boolean isAcContent = ctx.definesLocation(location);
        long permissions = Permissions.getPermissions(jcrActions, location, isAcContent);

        PropertyState property = location.getProperty();
        Tree tree = (property == null) ? location.getTree() : location.getParent().getTree();
        while (tree == null && !PathUtils.denotesRoot(location.getPath())) {
            location = location.getParent();
            tree = location.getTree();
        }
        if (tree != null) {
            return isGranted(tree, property, permissions);
        } else {
            return false;
        }
    }

    //--------------------------------------------------------------------------
    private static boolean isRead(long permission) {
        return permission == Permissions.READ_NODE || permission == Permissions.READ_PROPERTY || permission == Permissions.READ;
    }

    private static boolean isReadAction(@Nonnull String jcrAction) {
        return READ_NAMES.contains(jcrAction);
    }

    private static boolean hasCug(@Nonnull ImmutableTree tree) {
        return tree.exists() && tree.hasChild(REP_CUG_POLICY);
    }

    private boolean includes(@Nonnull String path) {
        for (String p : supportedAltPaths) {
            if (p.startsWith(path)) {
                return true;
            }
        }
        for (String p : supportedPaths) {
            if (p.equals(path)) {
                return true;
            }
        }
        return false;
    }

    private boolean includesCug(@Nonnull Tree tree, @Nonnull String path) {
        return getCugRoot(tree, path) != null;
    }

    @CheckForNull
    private ImmutableTree getCugRoot(@Nonnull Tree tree, @Nonnull String path) {
        if (!includes(path)) {
            return null;
        }
        ImmutableTree immutableTree = getImmutableTree(tree);
        if (hasCug(immutableTree)) {
            return immutableTree;
        }
        while (!immutableTree.isRoot()) {
            immutableTree = immutableTree.getParent();
            if (hasCug(immutableTree)) {
                return immutableTree;
            }
        }
        return null;
    }

    private boolean mayContainCug(@Nonnull String path) {
        String path2 = path + '/';
        for (String sp : supportedPaths) {
            if (path.equals(sp) || sp.startsWith(path2)) {
                return true;
            }
        }
        return false;
    }

    private boolean canRead(@Nonnull Tree tree) {
        ImmutableTree immutableTree = getImmutableTree(tree);
        if (ctx.definesTree(immutableTree)) {
            return false;
        }
        ImmutableTree cugRoot = getCugRoot(immutableTree, immutableTree.getPath());
        return cugRoot != null && createCugPermission(cugRoot).canRead();
    }

    private ImmutableTree getImmutableTree(@Nonnull Tree tree) {
        if (tree instanceof ImmutableTree) {
            return (ImmutableTree) tree;
        } else {
            return immutableRoot.getTree(tree.getPath());
        }
    }

    private TreePermission createCugPermission(@Nonnull ImmutableTree tree) {
        Tree cugTree = tree.getChild(REP_CUG_POLICY);
        if (CugUtil.definesCug(cugTree)) {
            PropertyState pNameState = cugTree.getProperty(REP_PRINCIPAL_NAMES);
            if (pNameState != null) {
                boolean allow = false;
                for (String pName : pNameState.getValue(Type.STRINGS)) {
                    if (principalNames.contains(pName)) {
                        allow = true;
                        break;
                    }
                }
                return new CugTreePermission(tree, allow);
            } else {
                log.warn("Tree at {0} doesn't represent a valid CUG.", cugTree.getPath());
            }
        }
        return new EmptyCugPermission(tree);
    }

    //--------------------------------------------------------------------------
    private final class EmptyCugPermission implements TreePermission {

        private ImmutableTree tree;

        private EmptyCugPermission(@Nonnull ImmutableTree tree) {
            this.tree = tree;
        }

        @Override
        public TreePermission getChildPermission(String childName, NodeState childState) {
            return getTreePermission(tree.getChild(childName), this);
        }

        @Override
        public boolean canRead() {
            return false;
        }

        @Override
        public boolean canRead(@Nonnull PropertyState property) {
            return false;
        }

        @Override
        public boolean canReadAll() {
            return false;
        }

        @Override
        public boolean canReadProperties() {
            return false;
        }

        @Override
        public boolean isGranted(long permissions) {
            return false;
        }

        @Override
        public boolean isGranted(long permissions, @Nonnull PropertyState property) {
            return false;
        }
    }

    private final class CugTreePermission implements TreePermission {

        private final ImmutableTree tree;
        private final boolean allow;

        private CugTreePermission(@Nonnull ImmutableTree tree, boolean allow) {
            this.tree = tree;
            this.allow = allow;
        }

        @Override
        public TreePermission getChildPermission(String childName, NodeState childState) {
            return getTreePermission(tree.getChild(childName), this);
        }

        @Override
        public boolean canRead() {
            return allow;
        }

        @Override
        public boolean canRead(@Nonnull PropertyState property) {
            return allow;
        }

        @Override
        public boolean canReadAll() {
            return false;
        }

        @Override
        public boolean canReadProperties() {
            return false;
        }

        @Override
        public boolean isGranted(long permissions) {
            return allow && permissions == Permissions.READ_NODE;
        }

        @Override
        public boolean isGranted(long permissions, @Nonnull PropertyState property) {
            return allow && permissions == Permissions.READ_PROPERTY;
        }
    }
}
TOP

Related Classes of org.apache.jackrabbit.oak.spi.security.authorization.cug.impl.CugPermissionProvider$EmptyCugPermission

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.