/*
 * 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.sling.jcr.repoinit;

import org.apache.jackrabbit.api.JackrabbitRepository;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
import org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.jcr.Jcr;
import org.apache.jackrabbit.oak.security.internal.SecurityProviderBuilder;
import org.apache.jackrabbit.oak.security.internal.SecurityProviderHelper;
import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
import org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.FilterProviderImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.PrincipalBasedAuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.principal.SystemUserPrincipal;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.sling.jcr.repoinit.impl.AclUtil;
import org.apache.sling.jcr.repoinit.impl.RepoInitException;
import org.apache.sling.jcr.repoinit.impl.TestUtil;
import org.apache.sling.repoinit.parser.RepoInitParsingException;
import org.apache.sling.repoinit.parser.operations.AclLine;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.Privilege;
import javax.security.auth.Subject;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.UUID;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class PrincipalBasedAclTest {

    private static final String PRINCIPAL_BASED_SUBTREE = "principalbased";
    private static final String REMOVE_NOT_SUPPORTED_REGEX = ".*REMOVE[a-zA-Z ]+not supported.*";

    @Rule
    public final OsgiContext context = new OsgiContext();

    private Repository repository;
    private JackrabbitSession adminSession;
    private JackrabbitAccessControlManager acMgr;

    private TestUtil U;

    private String path;
    private String propPath;
    private String relPath;

    private Session testSession;

    @Before
    public void before() throws Exception {
        SecurityProvider sp = createSecurityProvider();
        repository = new Jcr().with(sp).createRepository();

        String uid = sp.getParameters(UserConfiguration.NAME).getConfigValue(UserConstants.PARAM_ADMIN_ID, UserConstants.DEFAULT_ADMIN_ID);
        adminSession = (JackrabbitSession) repository.login(new SimpleCredentials(uid, uid.toCharArray()), null);
        acMgr = AclUtil.getJACM(adminSession);
        U = new TestUtil(adminSession);

        Node tmp = adminSession.getRootNode().addNode("tmp_" + U.id);
        Property prop = tmp.setProperty("prop", "value");
        path = tmp.getPath();
        propPath = prop.getPath();
        adminSession.save();

        relPath = sp.getParameters(UserConfiguration.NAME).getConfigValue(UserConstants.PARAM_SYSTEM_RELATIVE_PATH, UserConstants.DEFAULT_SYSTEM_RELATIVE_PATH) + "/" + PRINCIPAL_BASED_SUBTREE;
        U.parseAndExecute("create service user " + U.username + " with path " + relPath);

        testSession = loginSystemUserPrincipal(U.username);

        assertPermission(testSession, PathUtils.ROOT_PATH, Session.ACTION_READ, false);
        assertPermission(testSession, path, Session.ACTION_READ, false);

    }

    @After
    public void after() throws Exception {
        try {
            adminSession.removeItem(path);
            adminSession.save();
            U.cleanupUser();
        } finally {
            adminSession.logout();
            testSession.logout();
            if (repository instanceof JackrabbitRepository) {
                ((JackrabbitRepository) repository).shutdown();
            }
        }
    }

    private SecurityProvider createSecurityProvider() {
        /*
         * use composition-type OR in order in order to simplify the permission setup. since the tests in this class
         * don't setup permissions using the default authorization, the OR-setup will be sufficient to check for permissions
         * granted with the principal-based module only.
         *
         * in an AND setup scenario one would need to inject the aggregation filter defined by oak-authorization-princialbased
         */
        SecurityProvider sp = SecurityProviderBuilder.newBuilder().with(ConfigurationParameters.of("authorizationCompositionType", "OR")).build();

        ConfigurationParameters userParams = sp.getParameters(UserConfiguration.NAME);
        String userRoot = userParams.getConfigValue(UserConstants.PARAM_USER_PATH, UserConstants.DEFAULT_USER_PATH);
        String systemRelPath = userParams.getConfigValue(UserConstants.PARAM_SYSTEM_RELATIVE_PATH, UserConstants.DEFAULT_SYSTEM_RELATIVE_PATH);

        FilterProviderImpl fp = new FilterProviderImpl();
        context.registerInjectActivateService(fp, Collections.singletonMap("path", PathUtils.concat(userRoot, systemRelPath, PRINCIPAL_BASED_SUBTREE)));

        PrincipalBasedAuthorizationConfiguration authorizationConfig = new PrincipalBasedAuthorizationConfiguration();
        authorizationConfig.bindMountInfoProvider(Mounts.defaultMountInfoProvider());
        authorizationConfig.bindFilterProvider(fp);
        SecurityProviderHelper.updateConfig(sp, authorizationConfig, AuthorizationConfiguration.class);
        return sp;
    }

    /**
     * Create a JCR Session for the given system principal that is based on a Subject that only contains SystemUserPrincipal(s).
     * The result from U.loginService with result in a Session that additionally contains group-membership, which is not
     * supported by the default FilterProvider implementation (i.e. access control setup and permission evaluation is not supported
     * by the PrincipalBasedAuthorizationConfiguration as needed for these tests).
     *
     * @param systemUserPrincipalName Name of a system user principal
     * @return A JCR Session
     * @throws Exception If the repository login fails.
     */
    private Session loginSystemUserPrincipal(final String systemUserPrincipalName) throws Exception {
        SystemUserPrincipal principal = () -> systemUserPrincipalName;
        Subject subject = new Subject(true, Collections.singleton(principal), Collections.emptySet(), Collections.emptySet());
        return Subject.doAs(subject, (PrivilegedExceptionAction<Session>) () -> repository.login(null, null));
    }

    private static void assertPermission(Session userSession, String absolutePath, String actions, boolean successExpected) throws RepositoryException {
        assertEquals("Expecting "+actions+" for path " + absolutePath + " to be " + (successExpected ? "granted" : "denied"), successExpected, userSession.hasPermission(absolutePath, actions));
    }

    private static void assertRegex(String regex, String shouldMatch) {
        assertTrue("Expecting '" +  shouldMatch + "'' to match " + regex, shouldMatch.matches(regex));
    }
    
    @NotNull
    private static PrincipalAccessControlList assertPolicy(@NotNull Principal principal, @NotNull Session session,  int expectedSize) throws RepositoryException {
        PrincipalAccessControlList acl = getAcl(principal, session);
        assertNotNull(acl);
        assertEquals(expectedSize, acl.size());
        return acl;
    }

    private Authorizable getServiceUser(@NotNull String uid) throws RepositoryException {
        UserManager uMgr = adminSession.getUserManager();
        Authorizable a = uMgr.getAuthorizable(uid);
        if (a != null) {
            return a;
        } else {
            throw new RepositoryException("Expected service user " + uid + " to exist.");
        }
    }
    
    private Principal getPrincipal(@NotNull String serviceUserId) throws RepositoryException {
        return getServiceUser(serviceUserId).getPrincipal();
    }

    @Test
    public void readGranted() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on " + path + "\n"
                        + "end";
        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, path, Session.ACTION_READ, true);
        assertPermission(testSession, propPath, Session.ACTION_READ, true);
        assertPermission(testSession, propPath, Session.ACTION_SET_PROPERTY, false);
    }

    @Test
    public void grantedNonExistingPath() throws Exception {
        String nonExistingPath = path +"/nonExisting";
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on " + nonExistingPath + "\n"
                        + "end";
        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, nonExistingPath, Session.ACTION_READ, true);
    }

    @Test
    public void grantAtRootPath() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:all on /\n"
                        + "end"
                ;

        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, "/newChild", Session.ACTION_READ +","+ Session.ACTION_ADD_NODE +","+  Session.ACTION_REMOVE, true);
    }

    @Test
    public void multiplePrivileges() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read, jcr:versionManagement on " + path + "\n"
                        + "end";
        U.parseAndExecute(setup);
        testSession.refresh(false);

        String permissions = Permissions.getString(Permissions.READ|Permissions.VERSION_MANAGEMENT);
        assertPermission(testSession, path, permissions, true);
        assertPermission(testSession, path + "/newchild", permissions, true);
    }

    @Test(expected = RepoInitException.class)
    public void invalidPrivilege() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow my:invalidPrivilege on " + path + "\n"
                        + "end";
        U.parseAndExecute(setup);
    }

    @Test(expected = RepoInitException.class)
    public void denyEntry() throws Exception  {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "deny jcr:read on " + path + "\n"
                        + "end";
        U.parseAndExecute(setup);
    }

    @Test
    public void repoLevelPermission() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:namespaceManagement on :repository\n"
                        + "end";
        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertTrue(testSession.getAccessControlManager().hasPrivileges(null, AccessControlUtils.privilegesFromNames(testSession, "jcr:namespaceManagement")));
    }

    @Test
    public void repoLevelAndPath() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:all on :repository, "+path+"\n"
                        + "end";
        U.parseAndExecute(setup);
        testSession.refresh(false);

        AccessControlManager acMgr = testSession.getAccessControlManager();
        assertTrue(acMgr.hasPrivileges(path, AccessControlUtils.privilegesFromNames(testSession, "jcr:all")));
        assertTrue(acMgr.hasPrivileges(null, AccessControlUtils.privilegesFromNames(testSession, "jcr:all")));
    }

    @Test
    public void globRestriction() throws Exception {
        String notAllowed = "/testxyz_" + U.id;
        String allowed = "/testabc_" + U.id;

        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on "+path+" restriction(rep:glob,*abc*)\n"
                        + "end"
                ;

        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, path + allowed, Session.ACTION_READ, true);
        assertPermission(testSession, path + notAllowed, Session.ACTION_READ, false);
    }

    @Test
    public void emptyGlobRestriction() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on "+path+" restriction (rep:glob)\n"
                        + "end";

        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, "/", Session.ACTION_READ, false);
        assertPermission(testSession, path, Session.ACTION_READ, true);
        assertPermission(testSession, propPath, Session.ACTION_READ, false);
        assertPermission(testSession, "/path/child", Session.ACTION_READ, false);
    }

    @Test
    public void mvItemNamesRestriction() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:modifyProperties on / restriction(rep:itemNames,propName,prop)\n"
                        + "end"
                ;

        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, propPath, Session.ACTION_SET_PROPERTY, true);
        assertPermission(testSession, path + "/propName", Session.ACTION_SET_PROPERTY, true);
    }

    @Test
    public void emptyMvRestrictionTest() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on "+path+" restriction(rep:ntNames)\n"
                        + "end"
                ;
        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, propPath, Session.ACTION_READ, false);
    }

    @Test(expected = RepoInitException.class)
    public void unsupportedRestriction() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on "+path+" restriction(jcr:unsupported,value)\n"
                        + "end"
                ;
        U.parseAndExecute(setup);
    }

    @Test
    public void multiplePaths() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on "+path+", /content\n"
                        + "end";

        U.parseAndExecute(setup);
        testSession.refresh(false);

        assertPermission(testSession, PathUtils.ROOT_PATH, Session.ACTION_READ, false);
        assertPermission(testSession, path, Session.ACTION_READ, true);
        assertPermission(testSession, "/content", Session.ACTION_READ, true);
    }

    @Test(expected = RepoInitParsingException.class)
    public void missingPath() throws Exception {
        String setup =
                "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on \n"
                        + "end";

        U.parseAndExecute(setup);
    }

    @Test
    public void multiplePrincipals() throws Exception {
        Session s = null;
        try {
            U.parseAndExecute("create service user otherSystemPrincipal with path " + relPath);
            String setup =
                    "set principal ACL for " + U.username + ",otherSystemPrincipal \n"
                            + "allow jcr:read on " + path + "\n"
                            + "end";
            U.parseAndExecute(setup);
            testSession.refresh(false);

            assertPermission(testSession, propPath, Session.ACTION_READ, true);
            s = loginSystemUserPrincipal("otherSystemPrincipal");
            assertPermission(s, propPath, Session.ACTION_READ, true);
        } finally {
            if (s != null) {
                s.logout();
            }
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test(expected = RepoInitParsingException.class)
    public void missingPrincipal() throws Exception {
        String setup =
                "set principal ACL for \n"
                        + "allow jcr:read on "+path+"\n"
                        + "end";

        U.parseAndExecute(setup);
    }

    @Test
    public void redundantEntry() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                        + "allow jcr:read on "+path+"\n"
                        + "allow jcr:read on "+path+"\n"
                        + "end";
        U.parseAndExecute(setup);

        Principal principal = adminSession.getUserManager().getAuthorizable(U.username).getPrincipal();
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        PrincipalAccessControlList pacl = null;
        for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
            if (policy instanceof  PrincipalAccessControlList) {
                pacl = (PrincipalAccessControlList) policy;
                break;
            }
        }
        assertNotNull(pacl);
        // an identical entry should only be present once
        assertEquals(1, pacl.size());
    }

    @Test
    public void grantWithSecondSetup() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:read on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);

        setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);

        Principal principal = adminSession.getUserManager().getAuthorizable(U.username).getPrincipal();
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        PrincipalAccessControlList pacl = null;
        for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
            if (policy instanceof  PrincipalAccessControlList) {
                pacl = (PrincipalAccessControlList) policy;
                break;
            }
        }
        assertNotNull(pacl);
        assertEquals(2, pacl.size());
    }

    @Test
    public void  principalAclNotAvailable() throws Exception {
        try {
            // create service user outside of supported tree for principal-based access control
            U.parseAndExecute("create service user otherSystemPrincipal");
            String setup = "set principal ACL for otherSystemPrincipal \n"
                            + "allow jcr:read on " + path + "\n"
                            + "end";
            U.parseAndExecute(setup);
        } finally {
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test
    public void  principalAclNotAvailableRestrictionMismatch() throws Exception {
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        try {
            // create service user outside of supported tree for principal-based access control
            U.parseAndExecute("create service user otherSystemPrincipal");
            // setup path-based access control to establish effective permission setup
            String setup = "set ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on " + path + "\n"
                    + "end";
            U.parseAndExecute(setup);

            Principal principal = adminSession.getUserManager().getAuthorizable("otherSystemPrincipal").getPrincipal();
            assertTrue(acMgr.hasPrivileges(path, Collections.singleton(principal), AccessControlUtils.privilegesFromNames(adminSession, Privilege.JCR_READ)));

            setup = "set principal ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on " + path + " restriction(rep:glob,*mismatch)\n"
                    + "end";
            U.parseAndExecute(setup);
        } finally {
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test
    public void  principalAclNotAvailableEntryPresent() throws Exception {
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        try {
            // create service user outside of supported tree for principal-based access control
            U.parseAndExecute("create service user otherSystemPrincipal");
            // setup path-based access control to establish effective permission setup
            String setup = "set ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on " + path + "\n"
                    + "end";
            U.parseAndExecute(setup);

            Principal principal = adminSession.getUserManager().getAuthorizable("otherSystemPrincipal").getPrincipal();
            assertTrue(acMgr.hasPrivileges(path, Collections.singleton(principal), AccessControlUtils.privilegesFromNames(adminSession, Privilege.JCR_READ)));

            // setting up principal-acl will not succeed (principal not located below supported path)
            // but there exists an effective entry with the same definition -> no exception
            setup = "set principal ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on " + path + "\n"
                    + "end";
            U.parseAndExecute(setup);

            for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
                assertFalse(policy instanceof PrincipalAccessControlList);
            }
        } finally {
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test
    public void  principalAclNotAvailableEntryWithRestrictionPresent() throws Exception {
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        try {
            // create service user outside of supported tree for principal-based access control
            U.parseAndExecute("create service user otherSystemPrincipal");
            // setup path-based access control to establish effective permission setup
            String setup = "set ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on " + path + " restriction(rep:glob,*abc*)\n"
                    + "end";
            U.parseAndExecute(setup);

            // setting up principal-acl will not succeed (principal not located below supported path)
            // but there exists an equivalent entry with the same definition -> no exception
            setup = "set principal ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on " + path + " restriction(rep:glob,*abc*)\n"
                    + "end";
            U.parseAndExecute(setup);

            Principal principal = adminSession.getUserManager().getAuthorizable("otherSystemPrincipal").getPrincipal();
            for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
                assertFalse(policy instanceof PrincipalAccessControlList);
            }
        } finally {
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test
    public void  principalAclNotAvailableRepoLevelPermissions() throws Exception {
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        try {
            // create service user outside of supported tree for principal-based access control
            U.parseAndExecute("create service user otherSystemPrincipal");
            // setup path-based access control to establish effective permission setup
            String setup = "set ACL for otherSystemPrincipal \n"
                    + "allow jcr:namespaceManagement on :repository\n"
                    + "end";
            U.parseAndExecute(setup);

            // setting up principal-acl will not succeed (principal not located below supported path)
            // but there exists an equivalent entry with the same definition -> no exception
            setup = "set principal ACL for otherSystemPrincipal \n"
                    + "allow jcr:namespaceManagement on :repository\n"
                    + "end";
            U.parseAndExecute(setup);

            Principal principal = adminSession.getUserManager().getAuthorizable("otherSystemPrincipal").getPrincipal();
            for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
                assertFalse(policy instanceof PrincipalAccessControlList);
            }
        } finally {
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test
    public void  principalAclNotAvailableNonExistingNode() throws Exception {
        JackrabbitAccessControlManager acMgr = (JackrabbitAccessControlManager) adminSession.getAccessControlManager();
        try {
            // create service user outside of supported tree for principal-based access control
            U.parseAndExecute("create service user otherSystemPrincipal");

            // setting up principal-acl will not succeed (principal not located below supported path)
            // but since the target node does not exist we cannot verify if an equivalent resource-based ac-setup exists
            // (AccessControlManager.getPolicies would fail with PathNotFoundException) => relaxed behavior (SLING-9412)
            String setup = "set principal ACL for otherSystemPrincipal \n"
                    + "allow jcr:read on /non/existing/path\n"
                    + "end";
            U.parseAndExecute(setup);

            Principal principal = getPrincipal("otherSystemPrincipal");
            for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
                assertFalse(policy instanceof PrincipalAccessControlList);
            }
        } finally {
            U.cleanupServiceUser("otherSystemPrincipal");
        }
    }

    @Test
    public void testHomePath() throws Exception {
        Authorizable su = getServiceUser(U.username);
        Principal principal = su.getPrincipal();

        assertNull(getAcl(principal, U.adminSession));

        AclLine line = new AclLine(AclLine.Action.ALLOW);
        line.setProperty(AclLine.PROP_PRINCIPALS, Collections.singletonList(principal.getName()));
        line.setProperty(AclLine.PROP_PRIVILEGES, Collections.singletonList(Privilege.JCR_READ));
        line.setProperty(AclLine.PROP_PATHS, Collections.singletonList(":home:"+U.username+"#"));
        AclUtil.setPrincipalAcl(U.adminSession, U.username, Collections.singletonList(line));

        PrincipalAccessControlList acl = getAcl(principal, U.adminSession);
        assertNotNull(acl);
        assertEquals(1, acl.size());
        PrincipalAccessControlList.Entry entry = (PrincipalAccessControlList.Entry) acl.getAccessControlEntries()[0];
        assertArrayEquals(AccessControlUtils.privilegesFromNames(AclUtil.getJACM(U.adminSession), Privilege.JCR_READ), entry.getPrivileges());
        assertEquals(su.getPath(), entry.getEffectivePath());
    }

    @Test
    public void testTransientUser() throws Exception {
        UserManager uMgr = ((JackrabbitSession) U.adminSession).getUserManager();
        String id = "systemUser_" + UUID.randomUUID().toString();
        try {
            User su = uMgr.createSystemUser(id, relPath);
            String setup = "set principal ACL for "+su.getPrincipal().getName()+" \n"
                    + "allow jcr:read on " + path + "\n"
                    + "end";
            U.parseAndExecute(setup);

            PrincipalAccessControlList acl = getAcl(su.getPrincipal(), U.adminSession);
            assertNotNull(acl);
            assertEquals(1, acl.size());
        } finally {
            U.adminSession.refresh(false);
            Authorizable a = uMgr.getAuthorizable(id);
            if (a != null) {
                a.remove();
                U.adminSession.save();
            }
        }
    }

    @Test
    public void testRemoveAction() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);

        setup = "set principal ACL for " + U.username + "\n"
                + "remove jcr:write on " + path + "\n"
                + "end";

        try {
            U.parseAndExecute(setup);
            fail("Expecting REMOVE to fail");
        } catch(RuntimeException rex) {
            assertRegex(REMOVE_NOT_SUPPORTED_REGEX, rex.getMessage());
        }
    }

    @Test
    public void testRemoveNoExistingPolicy() throws Exception {
        String setup = "remove principal ACE for " + U.username + "\n"
                + "allow jcr:read on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
    }

    @Test
    public void testRemoveMatchingEntry() throws Exception {
        Principal principal = getPrincipal(U.username);
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 1);

        setup = "remove principal ACE for " + U.username + "\n"
                + "allow jcr:write on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 0);
    }

    @Test
    public void testRemoveNoMatchingEntry() throws Exception {
        Principal principal = getPrincipal(U.username);
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 1);

        // privilege mismatch
        setup = "remove principal ACE for " + U.username + "\n"
                + "allow jcr:read on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 1);

        // privilege mismatch 2
        setup = "remove principal ACE for " + U.username + "\n"
                + "allow jcr:read,jcr:write on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 1);

        // path mismatch
        setup = "remove principal ACE for " + U.username + "\n"
                + "allow jcr:write on " + path + "/mismatch\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 1);

        // restriction mismatch
        setup = "remove principal ACE for " + U.username + "\n"
                + "allow jcr:write on " + path + " restriction(rep:glob, /*/jcr:content/*)\n"
                + "end";
        U.parseAndExecute(setup);
        assertPolicy(principal, U.adminSession, 1);
    }

    @Test(expected = RepoInitException.class)
    public void testRemoveNonExistingPrincipal() throws Exception {
        String setup = "remove principal ACE for nonExistingPrincipal\n"
                + "deny jcr:write on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
    }

    @Test
    public void testRemovePrincipalMismatch() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);
        U.parseAndExecute("create service user otherSystemPrincipal");
        assertPolicy(getPrincipal(U.username), U.adminSession, 1);

        setup = "remove principal ACE for otherSystemPrincipal\n"
                + "allow jcr:write on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);

        // ace must not have been removed
        assertPolicy(getPrincipal(U.username), U.adminSession, 1);
        assertNull(getAcl(getPrincipal("otherSystemPrincipal"), U.adminSession));
    }

    @Test
    public void testRemoveAllNoExistingPolicy() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "remove * on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);

        // removal must be ignored and no policy must be created
        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
    }

    @Test(expected = RepoInitException.class)
    public void testAllRemoveNonExistingPrincipal() throws Exception {
        String setup = "set principal ACL for nonExistingPrincipal\n"
                + "remove * on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
    }

    @Test
    public void testRemoveAll() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "allow jcr:read on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);

        setup = "set principal ACL for " + U.username + "\n"
                + "remove * on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 0);
    }

    @Test
    public void testRemoveAllRepositoryPath() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "allow jcr:namespaceManagement on :repository\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 2);

        setup = "set principal ACL for " + U.username + "\n"
                + "remove * on :repository\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 1);
    }

    @Test
    public void testRemoveAllPartialPathMatch() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "allow jcr:write on /another/path\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 2);

        setup = "set principal ACL for " + U.username + "\n"
                + "remove * on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 1);
    }

    @Test
    public void testRemoveAllMultiplePaths() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "allow jcr:write on home("+U.username+")\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 2);

        setup = "set principal ACL for " + U.username + "\n"
                + "remove * on " + path + ", home("+U.username+")\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 0);
    }

    @Test
    public void testRemoveAllPathMismatch() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "allow jcr:read on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);

        setup = "set principal ACL for " + U.username + "\n"
                + "remove * on /another/path\n"
                + "end";
        U.parseAndExecute(setup);

        assertPolicy(getPrincipal(U.username), U.adminSession, 2);
    }

    @Test
    public void testRemoveAllPrincipalMismatch() throws Exception {
        String setup = "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end";
        U.parseAndExecute(setup);
        U.parseAndExecute("create service user otherSystemPrincipal");

        setup = "set principal ACL for otherSystemPrincipal\n"
                + "remove * on " + path + "\n"
                + "end";
        U.parseAndExecute(setup);
    }

    @Test
    public void testRemoveAllPrincipalDuplicated() throws Exception {
        U.parseAndExecute(""
            + "set principal ACL for " + U.username + "\n"
            + "allow jcr:write on "+path+"\n"
            + "allow jcr:read on "+path+"\n"
            + "end\n"
            + "set principal ACL for " + U.username + "\n"
            // duplicating the remove statement exposes SLING-10145
            + "remove * on " + path + "\n"
            + "remove * on " + path + "\n"
            + "end\n"
        );

        assertPolicy(getPrincipal(U.username), U.adminSession, 0);
    }

    @Test
    public void testAddAndDeleteAcl() throws Exception {
        U.parseAndExecute(""
                + "set principal ACL for " + U.username + "\n"
                + "allow jcr:write on "+path+"\n"
                + "end\n"
                + "delete principal ACL for " + U.username + "\n"
        );

        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
    }

    @Test
    public void testDeleteAcl() throws Exception {
        PrincipalAccessControlList acl = getApplicableAcl(getPrincipal(U.username), U.adminSession);
        acl.addEntry("/content", AccessControlUtils.privilegesFromNames(U.adminSession, Privilege.JCR_READ));
        U.adminSession.getAccessControlManager().setPolicy(acl.getPath(), acl);
        U.adminSession.save();

        assertNotNull(getAcl(getPrincipal(U.username), U.adminSession));
        U.parseAndExecute("delete principal ACL for " + U.username + "\n");
        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
    }

    @Test
    public void testDeleteNonExistingAcl() throws Exception {
        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
        // removing non-existing policy must not fail
        U.parseAndExecute("delete principal ACL for " + U.username + "\n");
        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
    }

    @Test
    public void testDeleteAclNonExistingPrincipal() throws Exception {
        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
        // removing policy for non-existing principal must not fail
        U.parseAndExecute("delete principal ACL for non-existing-service-user\n");
        assertNull(getAcl(getPrincipal(U.username), U.adminSession));
    }

    @Test
    public void testDeleteResourceBasedAclByPrincipal() throws Exception {
        U.parseAndExecute(""
                + "create path (nt:unstructured) /var\n"
                + "set ACL for " + U.username + "\n"
                + "allow jcr:read on /var\n"
                + "end\n"
                + "set principal ACL for " + U.username + "\n"
                + "allow jcr:read on /var\n"
                + "end\n");

        assertEquals(1, acMgr.getPolicies("/var").length);

        U.parseAndExecute("delete ACL for "+U.username+"\n");
        // resource-based acl at /var must be removed as it only contains a single entry for U.userName
        assertEquals(0, acMgr.getPolicies("/var").length);

        // removing resource-based ac-setup by principal must not delete any principal-based ac setup.
        Principal p = getPrincipal(U.username);
        AccessControlPolicy[] policies = acMgr.getPolicies(p);
        assertEquals(1, policies.length);
        assertTrue(policies[0] instanceof PrincipalAccessControlList);
    }

    @Nullable
    private static PrincipalAccessControlList getApplicableAcl(@NotNull Principal principal, @NotNull Session session) throws RepositoryException {
        for (AccessControlPolicy policy : AclUtil.getJACM(session).getApplicablePolicies(principal)) {
            if (policy instanceof PrincipalAccessControlList) {
                return (PrincipalAccessControlList) policy;
            }
        }
        return null;
    }

    @Nullable
    private static PrincipalAccessControlList getAcl(@NotNull Principal principal, @NotNull Session session) throws RepositoryException {
        for (AccessControlPolicy policy : AclUtil.getJACM(session).getPolicies(principal)) {
            if (policy instanceof PrincipalAccessControlList) {
                return (PrincipalAccessControlList) policy;
            }
        }
        return null;
    }
}