Merge pull request #7 from anchela/master
SLING-9091 : Principal-based AC-setup fails for transient service users
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 f09c7de..17e3e9c 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
@@ -47,7 +47,6 @@
import org.apache.sling.repoinit.parser.operations.AclLine;
import org.apache.sling.repoinit.parser.operations.RestrictionClause;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -169,7 +168,13 @@
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);
+ if (principal == null) {
+ // due to transient nature of the repo-init the principal lookup may not succeed if completed through query
+ // -> save transitent changes and retry principal lookup
+ session.save();
+ principal = AccessControlUtils.getPrincipal(session, principalName);
+ checkState(principal != null, "Principal not found: " + principalName);
+ }
PrincipalAccessControlList acl = getPrincipalAccessControlList(acMgr, principal);
boolean modified = false;
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
index aeb33b4..bcb11c0 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
@@ -21,6 +21,7 @@
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;
@@ -62,6 +63,7 @@
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;
@@ -558,6 +560,34 @@
}
@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 testHomePath() throws Exception {
UserManager uMgr = ((JackrabbitSession) U.adminSession).getUserManager();
Authorizable a = uMgr.getAuthorizable(U.username);
@@ -580,6 +610,30 @@
assertEquals(a.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(), AclUtil.getJACM(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();
+ }
+ }
+ }
+
@Nullable
private static PrincipalAccessControlList getAcl(@NotNull Principal principal, @NotNull JackrabbitAccessControlManager jacm) throws RepositoryException {
for (AccessControlPolicy policy : jacm.getPolicies(principal)) {