/*
 * 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.principalbased.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.oak.api.CommitFailedException;
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.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.ImmutableACL;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Before;
import org.junit.Test;

import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlException;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.Privilege;
import java.security.Principal;

import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.NT_REP_PRINCIPAL_ENTRY;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_EFFECTIVE_PATH;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_PRINCIPAL_POLICY;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

/**
 * Tests for PrincipalBasedAccessControlManager where the editing session (based on a regular user with default
 * permission evaluation) lacks permissions to read/modify access control on the target system-principal.
 */
public class AccessControlManagerLimitedUserTest extends AbstractPrincipalBasedTest implements PrivilegeConstants {

    Principal systemPrincipal;
    String systemPrincipalPath;

    Principal testPrincipal;
    Root testRoot;
    JackrabbitAccessControlManager testAcMgr;

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

        User systemUser = getTestSystemUser();
        systemPrincipalPath = systemUser.getPath();
        systemPrincipal = getTestSystemUser().getPrincipal();

        testPrincipal = createTestPrincipal();

        setupContentTrees(TEST_OAK_PATH);

        // grant test-user full read access (but not read-access control!)
        grant(testPrincipal, PathUtils.ROOT_PATH, JCR_READ);

        // trigger creation of principal policy with testPrincipal with 2 random entries
        PrincipalPolicyImpl policy = setupPrincipalBasedAccessControl(systemPrincipal, testContentJcrPath, JCR_NODE_TYPE_MANAGEMENT);
        addPrincipalBasedEntry(policy, null, JCR_NAMESPACE_MANAGEMENT);
        root.commit();

        testRoot = createTestRoot();
        testAcMgr = createAccessControlManager(testRoot);
    }

    @Override
    public void after() throws Exception {
        try {
            if (testRoot != null) {
                testRoot.getContentSession().close();
            }
        } finally {
            super.after();
        }
    }

    Principal createTestPrincipal() throws Exception {
        return getTestUser().getPrincipal();
    }

    Root createTestRoot() throws Exception {
        User testUser = getTestUser();
        return login(new SimpleCredentials(testUser.getID(), testUser.getID().toCharArray())).getLatestRoot();
    }

    void grant(@NotNull Principal principal, @Nullable String path, @NotNull String... privNames) throws Exception {
        addDefaultEntry(path, principal, privNames);
    }

    private static void assertEmptyPolicies(@NotNull AccessControlPolicy[] policies) {
        assertEquals(0, policies.length);
    }

    private static void assertPolicies(@NotNull AccessControlPolicy[] policies, Class<? extends JackrabbitAccessControlList> expectedClass, int expectedSize, int expectedEntrySize) {
        assertEquals(expectedSize, policies.length);
        if (expectedSize > 0) {
            assertTrue(expectedClass.isAssignableFrom(policies[0].getClass()));
            assertEquals(expectedEntrySize, ((JackrabbitAccessControlList) policies[0]).size());
        }
    }

    private static void assertEntry(@NotNull PrincipalPolicyImpl.EntryImpl entry, @Nullable String effectivePath, @NotNull PrivilegeBits expectedBits) {
        assertEquals(expectedBits, entry.getPrivilegeBits());
        if (effectivePath == null) {
            assertNull(entry.getEffectivePath());
        } else {
            assertEquals(effectivePath, entry.getEffectivePath());
        }
    }

    @NotNull
    private String getPolicyPath() throws Exception {
        JackrabbitAccessControlPolicy[] policies = createAccessControlManager(root).getPolicies(systemPrincipal);
        assertEquals(1, policies.length);
        return PathUtils.concat(((PrincipalPolicyImpl) policies[0]).getOakPath(), REP_PRINCIPAL_POLICY);
    }

    @NotNull
    private String getEntryPath() throws Exception {
        Tree policyTree = root.getTree(getPolicyPath());
        assertTrue(policyTree.exists());

        for (Tree child : policyTree.getChildren()) {
            if (Utils.isPrincipalEntry(child)) {
                return child.getPath();
            }
        }
        throw new RepositoryException("unable to locate policy entry");
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetApplicableByPath() throws RepositoryException {
        testAcMgr.getApplicablePolicies(testJcrPath);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetPoliciesByPath() throws RepositoryException {
        testAcMgr.getPolicies(testJcrPath);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetEffectiveByPathNoAccess() throws RepositoryException {
        testAcMgr.getEffectivePolicies(testJcrPath);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetEffectiveByNullPath() throws RepositoryException {
        testAcMgr.getEffectivePolicies((String) null);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetEffectiveByRooyPath() throws RepositoryException {
        testAcMgr.getEffectivePolicies(PathUtils.ROOT_PATH);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetEffectiveByPathReadAccessControlOnPrincipal() throws Exception {
        // grant testuser read-access control on testPrincipal-path but NOT on effective paths null and /oak:content
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // since default permission evaluation is in charge for 'testUser' -> access to full principal policy is now
        // granted
        AccessControlPolicy[] effective = testAcMgr.getEffectivePolicies((String) testJcrPath);
        assertEquals(1, effective.length);
        assertTrue(effective[0] instanceof PrincipalPolicyImpl);
    }

    @Test
    public void testGetEffectiveByPathMissingReadAccessControlOnPrincipal() throws Exception {
        // test-user: granted read-access-control on effective null-path
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL);
        // test-user: granted read-access-control on effective /oak:content
        grant(testPrincipal, PathUtils.getAncestorPath(testJcrPath, 3), JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        assertEmptyPolicies(testAcMgr.getEffectivePolicies((String) null));
        assertEmptyPolicies(testAcMgr.getEffectivePolicies(testJcrPath));
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetApplicableByPrincipalNoAccess() throws RepositoryException {
        testAcMgr.getApplicablePolicies(systemPrincipal);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetPoliciesByPrincipalNoAccess() throws RepositoryException {
        testAcMgr.getPolicies(systemPrincipal);
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetEffectiveByPrincipalNoAccess() throws RepositoryException {
        testAcMgr.getEffectivePolicies(ImmutableSet.of(systemPrincipal));
    }

    @Test
    public void testGetPoliciesByPrincipal() throws Exception {
        // grant testuser read-access control on testPrincipal-path but NOT on effective paths null and /oak:content
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // no read-ac permission on effective paths
        assertPolicies(testAcMgr.getPolicies(systemPrincipal), PrincipalPolicyImpl.class, 1, 2);

        // grant testuser read-access control on /oak:content
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();
        assertPolicies(testAcMgr.getPolicies(systemPrincipal), PrincipalPolicyImpl.class, 1, 2);

        // additionally grant testuser read-access control on null
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();
        assertPolicies(testAcMgr.getPolicies(systemPrincipal), PrincipalPolicyImpl.class, 1, 2);
    }

    @Test
    public void testGetEffectiveByPrincipal() throws Exception {
        // grant testuser read-access control on testPrincipal-path but NOT on effective paths null and /oak:content
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // read-access-control is only granted for the principalpolicy itself
        assertPolicies(testAcMgr.getEffectivePolicies(ImmutableSet.of(systemPrincipal)), ImmutableACL.class, 1, 2);

        // grant testuser read-access control on /oak:content
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();
        assertPolicies(testAcMgr.getEffectivePolicies(ImmutableSet.of(systemPrincipal)), ImmutableACL.class, 1, 2);

        // additionally grant testuser read-access control on null
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();
        assertPolicies(testAcMgr.getEffectivePolicies(ImmutableSet.of(systemPrincipal)), ImmutableACL.class, 1, 2);
    }

    @Test(expected = AccessDeniedException.class)
    public void testSetPolicyMissingModifyAccessControlOnPrincipal() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        policy.addEntry(null, privilegesFromNames(JCR_WORKSPACE_MANAGEMENT));

        testAcMgr.setPolicy(policy.getPath(), policy);
    }

    @Test(expected = AccessDeniedException.class)
    public void testSetPolicyMissingModifyAccessControlOnEffectivePath() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        policy.addEntry(null, privilegesFromNames(JCR_WORKSPACE_MANAGEMENT));
        policy.addEntry(testJcrPath, privilegesFromNames(JCR_READ));

        testAcMgr.setPolicy(policy.getPath(), policy);
    }

    @Test(expected = AccessDeniedException.class)
    public void testSetPolicyMissingModifyAccessControlOnEffectivePath2() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        policy.addEntry(null, privilegesFromNames(JCR_WORKSPACE_MANAGEMENT));
        policy.addEntry(testJcrPath, privilegesFromNames(JCR_READ));

        testAcMgr.setPolicy(policy.getPath(), policy);
    }

    @Test
    public void testSetPolicy() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        policy.addEntry(null, privilegesFromNames(JCR_WORKSPACE_MANAGEMENT));
        policy.addEntry(testJcrPath, privilegesFromNames(JCR_READ));

        testAcMgr.setPolicy(policy.getPath(), policy);
        testRoot.commit();
    }

    @Test(expected = AccessDeniedException.class)
    public void testRemovePolicyMissingModifyAccessControlOnPrincipal() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        testAcMgr.removePolicy(policy.getPath(), policy);
    }

    @Test(expected = AccessDeniedException.class)
    public void testRemovePolicyMissingModifyAccessControlOnEffectivePath() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        testAcMgr.removePolicy(policy.getPath(), policy);
    }

    @Test(expected = AccessDeniedException.class)
    public void testRemovePolicyMissingModifyAccessControlOnEffectivePath2() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        testAcMgr.removePolicy(policy.getPath(), policy);
    }

    @Test
    public void testRemovePolicy() throws Exception {
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        PrincipalPolicyImpl policy = (PrincipalPolicyImpl) testAcMgr.getPolicies(systemPrincipal)[0];
        testAcMgr.removePolicy(policy.getPath(), policy);
        testRoot.commit();
    }

    @Test
    public void testRemovePolicyWithNonEntryChild() throws Exception {
        // clear all entries from policy
        PrincipalPolicyImpl policy = getPrincipalPolicyImpl(systemPrincipal, getAccessControlManager(root));
        for (AccessControlEntry entry : policy.getAccessControlEntries()) {
            policy.removeAccessControlEntry(entry);
        }
        getAccessControlManager(root).setPolicy(policy.getPath(), policy);
        // grant permission to read/modify policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // transiently add non-entry tree
        Tree policyTree = testRoot.getTree(getPolicyPath());
        assertFalse(policyTree.getChildren().iterator().hasNext());
        TreeUtil.addChild(policyTree, "nonEntry", NodeTypeConstants.NT_OAK_UNSTRUCTURED);

        policy = getPrincipalPolicyImpl(systemPrincipal, testAcMgr);
        testAcMgr.removePolicy(policy.getPath(), policy);
        testRoot.commit();
    }

    @Test(expected = AccessControlException.class)
    public void testRemovePolicyMissingEffectivePaths() throws Exception {
        // grant permission to read/modify policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // first read policy
        PrincipalPolicyImpl policy = getPrincipalPolicyImpl(systemPrincipal, testAcMgr);

        // transiently remove rep:effectivePath properties from all entries.
        Tree policyTree = testRoot.getTree(getPolicyPath());
        for (Tree child : policyTree.getChildren()) {
            child.removeProperty(REP_EFFECTIVE_PATH);
        }

        // removing policy must fail, because effective paths cannot be evaluated
        testAcMgr.removePolicy(policy.getPath(), policy);
    }

    @Test(expected = AccessDeniedException.class)
    public void testHasPrivilegeSystemUser() throws Exception {
        // test session has no access
        testAcMgr.hasPrivileges(testContentJcrPath, ImmutableSet.of(systemPrincipal), privilegesFromNames(JCR_NODE_TYPE_MANAGEMENT));
    }

    @Test(expected = AccessDeniedException.class)
    public void testHasPrivilegeSystemUserWithPartialReadAc() throws Exception {
        // grant read-ac access on principal policy (but not on targetPath)
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        testAcMgr.hasPrivileges(testContentJcrPath, ImmutableSet.of(systemPrincipal), privilegesFromNames(JCR_NODE_TYPE_MANAGEMENT));
    }

    @Test
    public void testHasPrivilegeSystemUserWithPartialReadAc2() throws Exception {
        // grant read-ac access on effective path -> no entries accessible
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        assertFalse(testAcMgr.hasPrivileges(testContentJcrPath, ImmutableSet.of(systemPrincipal), privilegesFromNames(JCR_NODE_TYPE_MANAGEMENT)));
    }

    @Test
    public void testHasPrivilegeSystemUserWithReadAc() throws Exception {
        // grant read-ac access on effective path and on principal policy
        grant(testPrincipal, testContentJcrPath, JCR_READ_ACCESS_CONTROL);
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // default model lacks jcr:nodeTypeManagement privilege -> not granted
        assertFalse(testAcMgr.hasPrivileges(testContentJcrPath, ImmutableSet.of(systemPrincipal), privilegesFromNames(JCR_NODE_TYPE_MANAGEMENT)));

        addDefaultEntry(testContentJcrPath, systemPrincipal, JCR_READ, JCR_NODE_TYPE_MANAGEMENT);
        root.commit();
        testRoot.refresh();

        // once default model grants permissions as well -> granted
        assertTrue(testAcMgr.hasPrivileges(testContentJcrPath, ImmutableSet.of(systemPrincipal), privilegesFromNames(JCR_NODE_TYPE_MANAGEMENT)));

        // but combination read/nt-mgt is not granted because jcr:read is missing on principal-based setup.
        assertFalse(testAcMgr.hasPrivileges(testContentJcrPath, ImmutableSet.of(systemPrincipal), privilegesFromNames(JCR_READ, JCR_NODE_TYPE_MANAGEMENT)));
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetPrivilegeSystemUser() throws Exception {
        // test session has no access
        testAcMgr.getPrivileges(null, ImmutableSet.of(systemPrincipal));
    }

    @Test(expected = AccessDeniedException.class)
    public void testGetPrivilegeSystemUserWithPartialReadAc() throws Exception {
        // grant read ac on principal policy but not on target path
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        testAcMgr.getPrivileges(null, ImmutableSet.of(systemPrincipal));
    }

    @Test
    public void testGetPrivilegeSystemUserWithPartialReadAc2() throws Exception {
        // grant read-ac access on target path (but not on principal policy)
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        assertEquals(0, testAcMgr.getPrivileges(null, ImmutableSet.of(systemPrincipal)).length);
    }

    @Test
    public void testGetPrivilegeSystemUserWithWithReadAc() throws Exception {
        // grant read-ac access on effective path and on principal policy
        grant(testPrincipal, null, JCR_READ_ACCESS_CONTROL);
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        // default model lacks jcr:nodeTypeManagement privilege -> not granted
        assertArrayEquals(new Privilege[0], testAcMgr.getPrivileges(null, ImmutableSet.of(systemPrincipal)));

        addDefaultEntry(null, systemPrincipal, JCR_NAMESPACE_MANAGEMENT, REP_PRIVILEGE_MANAGEMENT);
        root.commit();
        testRoot.refresh();

        // once default model grants namespace-mgt privilege as well -> granted
        // but not rep:privilegeMgt because the principal-based model doesn't grant that one
        assertArrayEquals(privilegesFromNames(JCR_NAMESPACE_MANAGEMENT), testAcMgr.getPrivileges(null, ImmutableSet.of(systemPrincipal)));
    }

    @Test
    public void testReadPolicyTree() throws Exception {
        Tree policyTree = testRoot.getTree(getPolicyPath());
        assertNotNull(policyTree);
        assertFalse(policyTree.exists());
    }

    @Test
    public void testReadPolicyTreeWithReadAc() throws Exception {
        // grant read-ac access and check again
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        Tree policyTree = testRoot.getTree(getPolicyPath());
        assertNotNull(policyTree);
        assertTrue(policyTree.exists());
    }

    @Test
    public void testReadEntryTree() throws Exception {
        Tree entryTree = testRoot.getTree(getEntryPath());
        assertNotNull(entryTree);
        assertFalse(entryTree.exists());
    }

    @Test
    public void testReadEntryTreeWithReadAc() throws Exception {
        // grant read-ac access and check again
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        Tree entryTree = testRoot.getTree(getEntryPath());
        assertNotNull(entryTree);
        assertTrue(entryTree.exists());
    }

    @Test(expected = CommitFailedException.class)
    public void testAddEntryTree() throws Exception {
        // grant read-ac access on principal policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            Tree policyTree = testRoot.getTree(getPolicyPath());
            Tree entry = TreeUtil.addChild(policyTree, "entry", NT_REP_PRINCIPAL_ENTRY);
            entry.setProperty(REP_EFFECTIVE_PATH, TEST_OAK_PATH, Type.PATH);
            entry.setProperty(Constants.REP_PRIVILEGES, ImmutableList.of(JCR_ADD_CHILD_NODES), Type.NAMES);
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testAddEntryTreeModAcOnSystemPrincipal() throws Exception {
        // grant read-ac + mod-ac access on principal policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            Tree policyTree = testRoot.getTree(getPolicyPath());
            Tree entry = TreeUtil.addChild(policyTree, "entry", NT_REP_PRINCIPAL_ENTRY);
            entry.setProperty(REP_EFFECTIVE_PATH, TEST_OAK_PATH, Type.PATH);
            entry.setProperty(Constants.REP_PRIVILEGES, ImmutableList.of(JCR_ADD_CHILD_NODES), Type.NAMES);
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = IllegalStateException.class)
    public void testAddEntryTreeModAcOnEffectivePath() throws Exception {
        // grant read-ac + mod-ac access on effective path only -> cannot read principal policy
        grant(testPrincipal, testJcrPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        Tree policyTree = testRoot.getTree(getPolicyPath());
        Tree entry = TreeUtil.addChild(policyTree, "entry", NT_REP_PRINCIPAL_ENTRY);

    }

    @Test
    public void testAddEntryTreeFullModAc() throws Exception {
        grant(testPrincipal, testJcrPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        Tree policyTree = testRoot.getTree(getPolicyPath());
        Tree entry = TreeUtil.addChild(policyTree, "entry", NT_REP_PRINCIPAL_ENTRY);
        entry.setProperty(REP_EFFECTIVE_PATH, TEST_OAK_PATH, Type.PATH);
        entry.setProperty(Constants.REP_PRIVILEGES, ImmutableList.of(JCR_ADD_CHILD_NODES), Type.NAMES);
        testRoot.commit();
    }

    @Test(expected = CommitFailedException.class)
    public void testRemovePolicyTree() throws Exception {
        // grant read-ac access on principal policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getPolicyPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(0, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testRemovePolicyTreeWithModAcOnSystemPrincipal() throws Exception {
        // grant read-ac + mod-ac access on principal policy but not on target paths
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getPolicyPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testRemovePolicyTreeWithModAcOnOneEffectivePath() throws Exception {
        // grant read-ac + mod-ac access on principal policy and on testcontent target paths (but not on null path)
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getPolicyPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testRemovePolicyTreeWithModAcOnOneEffectivePath2() throws Exception {
        // grant read-ac + mod-ac access on principal policy and on nul target paths (but not on testcontent path)
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, null, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getPolicyPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testRemoveEmptyPolicyTree() throws Exception {
        PrincipalPolicyImpl policy = getPrincipalPolicyImpl(systemPrincipal, getAccessControlManager(root));
        for (AccessControlEntry entry : policy.getEntries()) {
            policy.removeAccessControlEntry(entry);
        }
        getAccessControlManager(root).setPolicy(policy.getPath(), policy);
        // grant permission to read policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);

        root.commit();
        testRoot.refresh();

        Tree policyTree = testRoot.getTree(getPolicyPath());
        assertTrue(policyTree.exists());
        policyTree.remove();
        testRoot.commit();
    }

    @Test(expected = CommitFailedException.class)
    public void testRemoveEntryTree() throws Exception {
        // grant read-ac access on principal policy
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getEntryPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testRemoveEntryTreeModAcOnSystemPrincipal() throws Exception {
        // grant read-ac + mod-ac access on principal policy but not on target path
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getEntryPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(3, e.getCode());
            throw e;
        }
    }

    @Test(expected = CommitFailedException.class)
    public void testRemoveEntryTreeModAcOnEffectivePath() throws Exception {
        // grant read-ac on principal policy but not mod-ac
        // on target path grant mod-ac
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        try {
            testRoot.getTree(getEntryPath()).remove();
            testRoot.commit();
        } catch (CommitFailedException e) {
            assertEquals(CommitFailedException.ACCESS, e.getType());
            assertEquals(0, e.getCode());
            throw e;
        }
    }

    @Test
    public void testRemoveEntryTreeFullModAc() throws Exception {
        // grant read-ac and mod-ac on principal policy
        // on target path grant mod-ac
        grant(testPrincipal, systemPrincipalPath, JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL);
        grant(testPrincipal, testContentJcrPath, JCR_MODIFY_ACCESS_CONTROL);
        root.commit();
        testRoot.refresh();

        testRoot.getTree(getEntryPath()).remove();
        testRoot.commit();
    }
}