This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-repoinit.git


The following commit(s) were added to refs/heads/master by this push:
     new c26f293  SLING-8602 - Add support for PrincipalAccessControlList and 
ac-management by principal
c26f293 is described below

commit c26f293e465469f8b46fa2469e757d11138136e7
Author: Angela Schreiber <[email protected]>
AuthorDate: Fri Sep 20 10:56:18 2019 +0200

    SLING-8602 - Add support for PrincipalAccessControlList and ac-management 
by principal
---
 pom.xml                                            |  19 +
 .../apache/sling/jcr/repoinit/impl/AclUtil.java    |  56 +++
 .../apache/sling/jcr/repoinit/impl/AclVisitor.java |  13 +
 .../sling/jcr/repoinit/impl/DoNothingVisitor.java  |   5 +
 .../sling/jcr/repoinit/PrincipalBasedAclTest.java  | 393 +++++++++++++++++++++
 .../apache/sling/jcr/repoinit/impl/TestUtil.java   |   6 +
 6 files changed, 492 insertions(+)

diff --git a/pom.xml b/pom.xml
index 9db292d..2e83a88 100644
--- a/pom.xml
+++ b/pom.xml
@@ -264,7 +264,26 @@
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-security-spi</artifactId>
+            <version>${oak.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-core</artifactId>
+            <version>${oak.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
             <artifactId>oak-core</artifactId>
+            <classifier>tests</classifier>
+            <version>${oak.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-authorization-principalbased</artifactId>
             <version>${oak.version}</version>
             <scope>provided</scope>
         </dependency>
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java 
b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
index 4128dbb..da409d1 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclUtil.java
@@ -18,6 +18,7 @@ package org.apache.sling.jcr.repoinit.impl;
 
 import java.security.Principal;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -30,12 +31,15 @@ import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
 import javax.jcr.security.Privilege;
 
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 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.commons.jackrabbit.authorization.AccessControlUtils;
 import org.apache.sling.repoinit.parser.operations.AclLine;
@@ -43,6 +47,9 @@ import 
org.apache.sling.repoinit.parser.operations.RestrictionClause;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sling.repoinit.parser.operations.AclLine.PROP_PATHS;
+import static 
org.apache.sling.repoinit.parser.operations.AclLine.PROP_PRIVILEGES;
+
 /** Utilities for ACL management */
 public class AclUtil {
 
@@ -155,6 +162,55 @@ public class AclUtil {
         setAcl(session, principals, (String)null, privileges, isAllow, 
restrictionClauses);
     }
 
+    public static void setPrincipalAcl(Session session, String principalName, 
Collection<AclLine> lines) throws RepositoryException {
+        JackrabbitAccessControlManager acMgr = getJACM(session);
+        Principal principal = AccessControlUtils.getPrincipal(session, 
principalName);
+        checkState(principal != null, "Principal not found: " + principalName);
+
+        PrincipalAccessControlList acl = getPrincipalAccessControlList(acMgr, 
principal);
+        boolean modified = false;
+        for (AclLine line : lines) {
+            if (line.getAction() == AclLine.Action.DENY) {
+                throw new AccessControlException("PrincipalAccessControlList 
doesn't support 'deny' entries.");
+            }
+            LocalRestrictions restrictions = 
createLocalRestrictions(line.getRestrictions(), acl, session);
+            Privilege[] privileges = 
AccessControlUtils.privilegesFromNames(session, 
line.getProperty(PROP_PRIVILEGES).toArray(new String[0]));
+
+            for (String path : line.getProperty(PROP_PATHS)) {
+                String effectivePath = (path == null || path.isEmpty() || 
AclLine.PATH_REPOSITORY.equals(path)) ? null : path;
+                boolean added = acl.addEntry(effectivePath, privileges, 
restrictions.getRestrictions(), restrictions.getMVRestrictions());
+                if (!added) {
+                    LOG.info("Equivalent principal-based entry already exists 
for principal {} and effective path {} ", principalName, path);
+                } else {
+                    modified = true;
+                }
+            }
+        }
+        if (modified) {
+            acMgr.setPolicy(acl.getPath(), acl);
+        }
+    }
+
+    private static PrincipalAccessControlList 
getPrincipalAccessControlList(JackrabbitAccessControlManager acMgr, Principal 
principal) throws RepositoryException {
+        PrincipalAccessControlList acl = null;
+        for (AccessControlPolicy policy : acMgr.getPolicies(principal)) {
+            if (policy instanceof PrincipalAccessControlList) {
+                acl = (PrincipalAccessControlList) policy;
+                break;
+            }
+        }
+        if (acl == null) {
+            for (AccessControlPolicy policy : 
acMgr.getApplicablePolicies(principal)) {
+                if (policy instanceof PrincipalAccessControlList) {
+                    acl = (PrincipalAccessControlList) policy;
+                    break;
+                }
+            }
+        }
+        checkState(acl != null, "No PrincipalAccessControlList available for 
principal " + principal);
+        return acl;
+    }
+
     // visible for testing
     static boolean contains(AccessControlEntry[] existingAces, 
LocalAccessControlEntry newAce) throws RepositoryException {
         for (int i = 0 ; i < existingAces.length; i++) {
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java 
b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
index 8cc392d..b1a0c57 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/AclVisitor.java
@@ -30,6 +30,7 @@ import org.apache.sling.repoinit.parser.operations.CreatePath;
 import org.apache.sling.repoinit.parser.operations.PathSegmentDefinition;
 import org.apache.sling.repoinit.parser.operations.RestrictionClause;
 import org.apache.sling.repoinit.parser.operations.SetAclPaths;
+import org.apache.sling.repoinit.parser.operations.SetAclPrincipalBased;
 import org.apache.sling.repoinit.parser.operations.SetAclPrincipals;
 
 /** OperationVisitor which processes only operations related to ACLs.
@@ -99,6 +100,18 @@ class AclVisitor extends DoNothingVisitor {
     }
 
     @Override
+    public void visitSetAclPrincipalBased(SetAclPrincipalBased s) {
+        for (String principalName : s.getPrincipals()) {
+            try {
+                log.info("Adding principal-based access control entry for {}", 
principalName);
+                AclUtil.setPrincipalAcl(session, principalName, s.getLines());
+            } catch(Exception e) {
+                throw new RuntimeException("Failed to set principal-based ACL 
(" + e.getMessage() + ")", e);
+            }
+        }
+    }
+
+    @Override
     public void visitCreatePath(CreatePath cp) {
         String parentPath = "";
             for(PathSegmentDefinition psd : cp.getDefinitions()) {
diff --git 
a/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java 
b/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
index 340fc62..7a28010 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
@@ -31,6 +31,7 @@ import 
org.apache.sling.repoinit.parser.operations.RegisterNamespace;
 import org.apache.sling.repoinit.parser.operations.RegisterNodetypes;
 import org.apache.sling.repoinit.parser.operations.RegisterPrivilege;
 import org.apache.sling.repoinit.parser.operations.SetAclPaths;
+import org.apache.sling.repoinit.parser.operations.SetAclPrincipalBased;
 import org.apache.sling.repoinit.parser.operations.SetAclPrincipals;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -88,6 +89,10 @@ class DoNothingVisitor implements OperationVisitor {
     }
 
     @Override
+    public void visitSetAclPrincipalBased(SetAclPrincipalBased operation) {
+    }
+
+    @Override
     public void visitCreatePath(CreatePath cp) {
     }
 
diff --git 
a/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java 
b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
new file mode 100644
index 0000000..ad42344
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
@@ -0,0 +1,393 @@
+/*
+ * 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.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.TestUtil;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+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.security.auth.Subject;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class PrincipalBasedAclTest {
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+
+    private Repository repository;
+    private Session adminSession;
+
+    private TestUtil U;
+
+    private String path;
+    private String propPath;
+
+    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 = repository.login(new SimpleCredentials(uid, 
uid.toCharArray()), null);
+        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();
+
+        U.parseAndExecute("create service user " + U.username);
+
+        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)));
+
+        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 = new SystemUserPrincipal() {
+            @Override
+            public String getName() {
+                return systemUserPrincipalName;
+            }
+        };
+        Subject subject = new Subject(true, Collections.singleton(principal), 
Collections.emptySet(), Collections.emptySet());
+        return Subject.doAs(subject, new PrivilegedExceptionAction<Session>() {
+            @Override
+            public Session run() throws Exception {
+                return 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));
+    }
+
+    @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 = RuntimeException.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 = RuntimeException.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 = RuntimeException.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");
+            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);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java 
b/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java
index b1b86e9..9067a6d 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java
@@ -56,6 +56,12 @@ public class TestUtil {
         username = "user_" + id;
     }
 
+    public TestUtil(Session adminSession) {
+        this.adminSession = adminSession;
+        id = UUID.randomUUID().toString();
+        username = "user_" + id;
+    }
+
     public List<Operation> parse(String input) throws RepoInitParsingException 
{
         final Reader r = new StringReader(input);
         try {

Reply via email to