/*
 * 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.security.authorization.composite;

import java.security.Principal;
import java.util.List;
import java.util.Set;
import javax.jcr.Session;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.JackrabbitSession;
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.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
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.principal.EveryonePrincipal;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 * Test the {@link org.apache.jackrabbit.oak.security.authorization.composite.CompositePermissionProvider}
 * where permissions are granted but not all permissions/privileges have been
 * covered by the call. This might be the case when combining different
 * providers that don't cover the full set of permissions/privileges.
 *
 * For simplicity the test only lists a single provider which only supports a
 * limited set of permissions|privileges.
 *
 * The expected result is:
 * - testing for the supported privileges|permissions must reveal that it is granted
 * - any other combination of permissions|privileges must be denied.
 */
public class CompositeProviderCoverageTest extends AbstractCompositeProviderTest {

    private CompositePermissionProvider cpp;
    private CompositePermissionProvider cppO;

    @Override
    public void before() throws Exception {
        super.before();

        cpp = createPermissionProvider();
        cppO = createPermissionProviderOR();
    }

    @Override
    AggregatedPermissionProvider getTestPermissionProvider() {
        return new LimitCoverageProvider(root);
    }

    @Override
    List<AggregatedPermissionProvider> getAggregatedProviders(@NotNull String workspaceName, @NotNull AuthorizationConfiguration config, @NotNull Set<Principal> principals) {
        return ImmutableList.of(getTestPermissionProvider());
    }

    @Override
    @Test
    public void testGetTreePermissionInstance() throws Exception {
        PermissionProvider pp = createPermissionProvider(EveryonePrincipal.getInstance());
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            TreePermission tp = pp.getTreePermission(readOnlyRoot.getTree(path), parentPermission);
            assertTrue(tp instanceof LimitedTreePermission);
            parentPermission = tp;
        }
    }

    @Override
    @Test
    public void testGetTreePermissionInstanceOR() throws Exception {
        PermissionProvider pp = createPermissionProviderOR(EveryonePrincipal.getInstance());
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            TreePermission tp = pp.getTreePermission(readOnlyRoot.getTree(path), parentPermission);
            assertTrue(tp instanceof LimitedTreePermission);
            parentPermission = tp;
        }
    }

    @Override
    @Test
    public void testTreePermissionGetChild() throws Exception {
        List<String> childNames = ImmutableList.of("test", "a", "b", "c", "nonexisting");

        Tree rootTree = readOnlyRoot.getTree(ROOT_PATH);
        NodeState ns = getTreeProvider().asNodeState(rootTree);
        TreePermission tp = createPermissionProvider().getTreePermission(rootTree, TreePermission.EMPTY);

        for (String cName : childNames) {
            ns = ns.getChildNode(cName);
            tp = tp.getChildPermission(cName, ns);
            assertTrue(tp instanceof LimitedTreePermission);
        }
    }

    @Override
    @Test
    public void testTreePermissionGetChildOR() throws Exception {
        List<String> childNames = ImmutableList.of("test", "a", "b", "c", "nonexisting");

        Tree rootTree = readOnlyRoot.getTree(ROOT_PATH);
        NodeState ns = getTreeProvider().asNodeState(rootTree);
        TreePermission tp = createPermissionProviderOR().getTreePermission(rootTree, TreePermission.EMPTY);

        for (String cName : childNames) {
            ns = ns.getChildNode(cName);
            tp = tp.getChildPermission(cName, ns);
            assertTrue(tp instanceof LimitedTreePermission);
        }
    }

    @Test
    public void testGetPrivileges() throws Exception {
        for (String p : NODE_PATHS) {
            assertEquals(ImmutableSet.of(REP_READ_NODES), cpp.getPrivileges(readOnlyRoot.getTree(p)));
            assertEquals(ImmutableSet.of(REP_READ_NODES), cppO.getPrivileges(readOnlyRoot.getTree(p)));
        }
    }

    @Test
    public void testGetPrivilegesOnRepo() throws Exception {
        assertEquals(ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT), cpp.getPrivileges(null));
        assertEquals(ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT), cppO.getPrivileges(null));
    }

    @Test
    public void testHasPrivileges() throws Exception {
        for (String p : NODE_PATHS) {
            Tree tree = readOnlyRoot.getTree(p);

            assertTrue(cpp.hasPrivileges(tree, REP_READ_NODES));
            assertFalse(cpp.hasPrivileges(tree, JCR_READ));
            assertFalse(cpp.hasPrivileges(tree, JCR_WRITE));
            assertFalse(cpp.hasPrivileges(tree, JCR_ALL));

            assertTrue(cppO.hasPrivileges(tree, REP_READ_NODES));
            assertFalse(cppO.hasPrivileges(tree, JCR_READ));
            assertFalse(cppO.hasPrivileges(tree, JCR_WRITE));
            assertFalse(cppO.hasPrivileges(tree, JCR_ALL));
        }
    }

    @Test
    public void testHasPrivilegesOnRepo() throws Exception {
        assertTrue(cpp.hasPrivileges(null, JCR_NAMESPACE_MANAGEMENT));
        assertFalse(cpp.hasPrivileges(null, JCR_NODE_TYPE_DEFINITION_MANAGEMENT));
        assertFalse(cpp.hasPrivileges(null, JCR_ALL));

        assertTrue(cppO.hasPrivileges(null, JCR_NAMESPACE_MANAGEMENT));
        assertFalse(cppO.hasPrivileges(null, JCR_NODE_TYPE_DEFINITION_MANAGEMENT));
        assertFalse(cppO.hasPrivileges(null, JCR_ALL));
    }


    @Test
    public void testIsGranted() throws Exception {
        for (String p : NODE_PATHS) {
            Tree tree = readOnlyRoot.getTree(p);

            assertTrue(cpp.isGranted(tree, null, Permissions.READ_NODE));
            assertFalse(cpp.isGranted(tree, null, Permissions.LOCK_MANAGEMENT));
            assertFalse(cpp.isGranted(tree, null, Permissions.ALL));
            assertFalse(cpp.isGranted(tree, null, Permissions.READ_NODE | Permissions.LOCK_MANAGEMENT));

            assertTrue(cppO.isGranted(tree, null, Permissions.READ_NODE));
            assertFalse(cppO.isGranted(tree, null, Permissions.LOCK_MANAGEMENT));
            assertFalse(cppO.isGranted(tree, null, Permissions.ALL));
            assertFalse(cppO.isGranted(tree, null, Permissions.READ_NODE | Permissions.LOCK_MANAGEMENT));
        }
    }

    @Test
    public void testIsGrantedProperty() throws Exception {
        for (String p : NODE_PATHS) {
            Tree tree = readOnlyRoot.getTree(p);

            assertTrue(cpp.isGranted(tree, PROPERTY_STATE, Permissions.READ_NODE));
            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, Permissions.READ_PROPERTY));
            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, Permissions.LOCK_MANAGEMENT));
            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, Permissions.ALL));
            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, Permissions.READ_NODE | Permissions.LOCK_MANAGEMENT));

            assertTrue(cppO.isGranted(tree, PROPERTY_STATE, Permissions.READ_NODE));
            assertFalse(cppO.isGranted(tree, PROPERTY_STATE, Permissions.READ_PROPERTY));
            assertFalse(cppO.isGranted(tree, PROPERTY_STATE, Permissions.LOCK_MANAGEMENT));
            assertFalse(cppO.isGranted(tree, PROPERTY_STATE, Permissions.ALL));
            assertFalse(cppO.isGranted(tree, PROPERTY_STATE, Permissions.READ_NODE | Permissions.LOCK_MANAGEMENT));
        }
    }

    @Test
    public void testIsGrantedAction() throws Exception {
        for (String nodePath : NODE_PATHS) {
            String propPath = PathUtils.concat(nodePath, JcrConstants.JCR_PRIMARYTYPE);

            assertTrue(cpp.isGranted(nodePath, Session.ACTION_READ));
            assertFalse(cpp.isGranted(propPath, Session.ACTION_READ));
            assertFalse(cpp.isGranted(nodePath, Session.ACTION_REMOVE));
            assertFalse(cpp.isGranted(propPath, JackrabbitSession.ACTION_MODIFY_PROPERTY));
            assertFalse(cpp.isGranted(nodePath, getActionString(JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL, JackrabbitSession.ACTION_READ_ACCESS_CONTROL)));

            assertTrue(cppO.isGranted(nodePath, Session.ACTION_READ));
            assertFalse(cppO.isGranted(propPath, Session.ACTION_READ));
            assertFalse(cppO.isGranted(nodePath, Session.ACTION_REMOVE));
            assertFalse(cppO.isGranted(propPath, JackrabbitSession.ACTION_MODIFY_PROPERTY));
            assertFalse(cppO.isGranted(nodePath, getActionString(JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL, JackrabbitSession.ACTION_READ_ACCESS_CONTROL)));

            String nonExisting = PathUtils.concat(nodePath, "nonExisting");
            assertFalse(cpp.isGranted(nonExisting, Session.ACTION_READ));
            assertFalse(cpp.isGranted(nonExisting, JackrabbitSession.ACTION_ADD_PROPERTY));
            assertFalse(cpp.isGranted(nonExisting, Session.ACTION_ADD_NODE));

            assertFalse(cppO.isGranted(nonExisting, Session.ACTION_READ));
            assertFalse(cppO.isGranted(nonExisting, JackrabbitSession.ACTION_ADD_PROPERTY));
            assertFalse(cppO.isGranted(nonExisting, Session.ACTION_ADD_NODE));
        }
    }

    @Test
    public void testRepositoryPermissionsIsGranted() throws Exception {
        RepositoryPermission rp = cpp.getRepositoryPermission();
        assertTrue(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT));
        assertFalse(rp.isGranted(Permissions.NODE_TYPE_DEFINITION_MANAGEMENT));
        assertFalse(rp.isGranted(Permissions.ALL));

        RepositoryPermission rpO = cppO.getRepositoryPermission();
        assertTrue(rpO.isGranted(Permissions.NAMESPACE_MANAGEMENT));
        assertFalse(rpO.isGranted(Permissions.NODE_TYPE_DEFINITION_MANAGEMENT));
        assertFalse(rpO.isGranted(Permissions.ALL));
    }

    @Test
    public void testTreePermissionIsGranted() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;
        for (String path : TP_PATHS) {
            TreePermission tp = cpp.getTreePermission(readOnlyRoot.getTree(path), parentPermission);

            assertTrue(tp.isGranted(Permissions.READ_NODE));
            assertFalse(tp.isGranted(Permissions.REMOVE_NODE));
            assertFalse(tp.isGranted(Permissions.READ));
            assertFalse(tp.isGranted(Permissions.ALL));

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionIsGrantedOR() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;
        for (String path : TP_PATHS) {
            TreePermission tp = cppO.getTreePermission(readOnlyRoot.getTree(path), parentPermission);

            assertTrue(tp.isGranted(Permissions.READ_NODE));
            assertFalse(tp.isGranted(Permissions.REMOVE_NODE));
            assertFalse(tp.isGranted(Permissions.READ));
            assertFalse(tp.isGranted(Permissions.ALL));

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionIsGrantedProperty() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            TreePermission tp = cpp.getTreePermission(readOnlyRoot.getTree(path), parentPermission);

            assertFalse(tp.isGranted(Permissions.READ_PROPERTY, PROPERTY_STATE));
            assertFalse(tp.isGranted(Permissions.REMOVE_PROPERTY, PROPERTY_STATE));
            assertFalse(tp.isGranted(Permissions.READ, PROPERTY_STATE));
            assertFalse(tp.isGranted(Permissions.ALL, PROPERTY_STATE));

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionIsGrantedPropertyOR() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            TreePermission tp = cppO.getTreePermission(readOnlyRoot.getTree(path), parentPermission);

            assertFalse(tp.isGranted(Permissions.READ_PROPERTY, PROPERTY_STATE));
            assertFalse(tp.isGranted(Permissions.REMOVE_PROPERTY, PROPERTY_STATE));
            assertFalse(tp.isGranted(Permissions.READ, PROPERTY_STATE));
            assertFalse(tp.isGranted(Permissions.ALL, PROPERTY_STATE));

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionCanRead() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            Tree t = readOnlyRoot.getTree(path);
            TreePermission tp = cpp.getTreePermission(t, parentPermission);

            assertTrue(tp.canRead());

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionCanReadOR() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            Tree t = readOnlyRoot.getTree(path);
            TreePermission tp = cppO.getTreePermission(t, parentPermission);

            assertTrue(tp.canRead());

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionCanReadProperty() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            Tree t = readOnlyRoot.getTree(path);
            TreePermission tp = cpp.getTreePermission(t, parentPermission);
            assertFalse(tp.canRead(PROPERTY_STATE));

            parentPermission = tp;
        }
    }

    @Test
    public void testTreePermissionCanReadPropertyOR() throws Exception {
        TreePermission parentPermission = TreePermission.EMPTY;

        for (String path : TP_PATHS) {
            Tree t = readOnlyRoot.getTree(path);
            TreePermission tp = cppO.getTreePermission(t, parentPermission);
            assertFalse(tp.canRead(PROPERTY_STATE));

            parentPermission = tp;
        }
    }

    private final class LimitCoverageProvider extends AbstractAggrProvider {

        LimitCoverageProvider(Root root) {
            super(root);
        }

        @NotNull
        @Override
        public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) {
            PrivilegeBits supported = PrivilegeBits.getInstance(
                    PrivilegeBits.BUILT_IN.get(JCR_NAMESPACE_MANAGEMENT),
                    PrivilegeBits.BUILT_IN.get(REP_READ_NODES));
            if (privilegeBits != null) {
                return PrivilegeBits.getInstance(privilegeBits).retain(supported);
            } else {
                return supported;
            }
        }

        @Override
        public long supportedPermissions(@Nullable Tree tree, @Nullable PropertyState property, long permissions) {
            if (tree == null) {
                return permissions & Permissions.NAMESPACE_MANAGEMENT;
            } else {
                return permissions & Permissions.READ_NODE;
            }
        }

        @Override
        public long supportedPermissions(@NotNull TreeLocation location, long permissions) {
            return permissions & Permissions.READ_NODE;
        }

        @Override
        public long supportedPermissions(@NotNull TreePermission treePermission, @Nullable PropertyState property, long permissions) {
            return permissions & Permissions.READ_NODE;
        }

        @Override
        public boolean isGranted(@NotNull TreeLocation location, long permissions) {
            return permissions == Permissions.READ_NODE;
        }

        @NotNull
        @Override
        public Set<String> getPrivileges(@Nullable Tree tree) {
            return (tree == null) ? ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT) : ImmutableSet.of(REP_READ_NODES);
        }

        @Override
        public boolean hasPrivileges(@Nullable Tree tree, @NotNull String... privilegeNames) {
            return true;
        }

        @NotNull
        @Override
        public RepositoryPermission getRepositoryPermission() {
            return new RepositoryPermission() {
                @Override
                public boolean isGranted(long repositoryPermissions) {
                    return Permissions.NAMESPACE_MANAGEMENT == repositoryPermissions;
                }
            };
        }

        @NotNull
        @Override
        public TreePermission getTreePermission(@NotNull Tree tree, @NotNull TreePermission parentPermission) {
            return new LimitedTreePermission();
        }

        @Override
        public boolean isGranted(@NotNull Tree tree, @Nullable PropertyState property, long permissions) {
            return permissions == Permissions.READ_NODE;
        }

        @Override
        public boolean isGranted(@NotNull String oakPath, @NotNull String jcrActions) {
            return true;
        }
    }

    private static final class LimitedTreePermission implements TreePermission {
        @NotNull
        @Override
        public TreePermission getChildPermission(@NotNull String childName, @NotNull NodeState childState) {
            return this;
        }

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

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

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

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

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

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