SLING-11245 : AclUtil.removePolicies(Session, List<String> paths) will fail if no policy exists
SLING-11246 : Avoid repeated calls to Session.getAccessControlManager in AclUtil
SLING-11249 : Missing test for removing entries at non-existing path
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 407c8a7..cc8dd9f 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
@@ -129,10 +129,12 @@
private static void setAcl(Session session, List<String> principals, String jcrPath, List<String> privileges, boolean isAllow, List<RestrictionClause> restrictionClauses)
throws RepositoryException {
- final String [] privArray = privileges.toArray(new String[privileges.size()]);
- final Privilege[] jcrPriv = AccessControlUtils.privilegesFromNames(session, privArray);
+ AccessControlManager acMgr = session.getAccessControlManager();
- JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, jcrPath);
+ final String [] privArray = privileges.toArray(new String[privileges.size()]);
+ final Privilege[] jcrPriv = AccessControlUtils.privilegesFromNames(acMgr, privArray);
+
+ JackrabbitAccessControlList acl = getAccessControlList(acMgr, jcrPath, true);
checkState(acl != null, "No JackrabbitAccessControlList available for path " + jcrPath);
LocalRestrictions localRestrictions = createLocalRestrictions(restrictionClauses, acl, session);
@@ -159,7 +161,7 @@
changed = true;
}
if ( changed ) {
- session.getAccessControlManager().setPolicy(jcrPath, acl);
+ acMgr.setPolicy(jcrPath, acl);
}
}
@@ -202,24 +204,30 @@
* @throws RepositoryException
*/
public static void removePolicies(@NotNull Session session, @NotNull List<String> paths) throws RepositoryException {
+ AccessControlManager acMgr = session.getAccessControlManager();
for (String jcrPath : getJcrPaths(session, paths)) {
- LOG.info("Removing access control policy on {}", jcrPath);
- JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, jcrPath);
+ if (!isValidPath(session, jcrPath)) {
+ LOG.info("Cannot remove ACL; no node at {} ", jcrPath);
+ continue;
+ }
+ LOG.info("Removing access control policy at {}", jcrPath);
+ JackrabbitAccessControlList acl = getAccessControlList(acMgr, jcrPath, false);
if (acl == null) {
LOG.info("No ACL to remove at path {}", jcrPath);
} else {
- session.getAccessControlManager().removePolicy(jcrPath, acl);
+ acMgr.removePolicy(jcrPath, acl);
}
}
}
public static void removeEntries(@NotNull Session session, @NotNull List<String> principals, @NotNull List<String> paths) throws RepositoryException {
Set<String> principalNames = new HashSet<>(principals);
+ AccessControlManager acMgr = session.getAccessControlManager();
for (String jcrPath : getJcrPaths(session, paths)) {
- if (jcrPath != null && !session.nodeExists(jcrPath)) {
+ if (!isValidPath(session, jcrPath)) {
LOG.info("Cannot remove access control entries on non-existent path {}", jcrPath);
} else {
- JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, jcrPath);
+ JackrabbitAccessControlList acl = getAccessControlList(acMgr, jcrPath, false);
if (acl != null) {
boolean modified = false;
for (AccessControlEntry ace : acl.getAccessControlEntries()) {
@@ -229,7 +237,7 @@
}
}
if (modified) {
- session.getAccessControlManager().setPolicy(jcrPath, acl);
+ acMgr.setPolicy(jcrPath, acl);
}
} else {
LOG.info("Cannot remove access control entries for principal(s) {}. No ACL at {}", principalNames, jcrPath);
@@ -240,16 +248,17 @@
public static void removeEntries(@NotNull Session session, @NotNull List<String> principals, @NotNull List<String> paths, List<String> privileges, boolean isAllow, List<RestrictionClause> restrictionClauses) throws RepositoryException {
Set<String> principalNames = new HashSet<>(principals);
+ AccessControlManager acMgr = session.getAccessControlManager();
for (String jcrPath : getJcrPaths(session, paths)) {
- if (jcrPath != null && !session.nodeExists(jcrPath)) {
+ if (!isValidPath(session, jcrPath)) {
LOG.info("Cannot remove access control entries on non-existent path {}", jcrPath);
} else {
- JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(session, jcrPath);
+ JackrabbitAccessControlList acl = getAccessControlList(acMgr, jcrPath, false);
if (acl != null) {
boolean modified = false;
LocalRestrictions restr = createLocalRestrictions(restrictionClauses, acl, session);
- Privilege[] privs = AccessControlUtils.privilegesFromNames(session, privileges.toArray(new String[0]));
+ Privilege[] privs = AccessControlUtils.privilegesFromNames(acMgr, privileges.toArray(new String[0]));
for (AccessControlEntry ace : acl.getAccessControlEntries()) {
Principal principal = ace.getPrincipal();
@@ -263,7 +272,7 @@
}
}
if (modified) {
- session.getAccessControlManager().setPolicy(jcrPath, acl);
+ acMgr.setPolicy(jcrPath, acl);
} else {
LOG.info("No matching access control entry found to remove for principals {} at {}. Expected entry with isAllow={}, privileges={}, restrictions={}", principalNames, jcrPath, isAllow, privileges, restrictionClauses);
}
@@ -299,7 +308,7 @@
modified = true;
}
} else if (action == AclLine.Action.ALLOW) {
- final Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, line.getProperty(PROP_PRIVILEGES).toArray(new String[0]));
+ final Privilege[] privileges = AccessControlUtils.privilegesFromNames(acMgr, line.getProperty(PROP_PRIVILEGES).toArray(new String[0]));
for (String effectivePath : jcrPaths) {
if (acl == null) {
// no PrincipalAccessControlList available: don't fail if an equivalent path-based entry with the same definition exists
@@ -345,7 +354,7 @@
List<String> jcrPaths = getJcrPaths(session, line.getProperty(PROP_PATHS));
LocalRestrictions restr = createLocalRestrictions(line.getRestrictions(), acl, session);
List<String> privNames = line.getProperty(PROP_PRIVILEGES);
- Privilege[] privs = AccessControlUtils.privilegesFromNames(session, privNames.toArray(new String[0]));
+ Privilege[] privs = AccessControlUtils.privilegesFromNames(acMgr, privNames.toArray(new String[0]));
Predicate<PrincipalAccessControlList.Entry> predicate = entry -> {
if (!jcrPaths.contains(entry.getEffectivePath())) {
return false;
@@ -386,6 +395,25 @@
acMgr.removePolicy(acl.getPath(), acl);
}
}
+
+ private static boolean isValidPath(@NotNull Session session, @Nullable String jcrPath) throws RepositoryException {
+ return jcrPath == null || session.nodeExists(jcrPath);
+ }
+
+ @Nullable
+ private static JackrabbitAccessControlList getAccessControlList(@NotNull AccessControlManager acMgr,
+ @Nullable String path, boolean includeApplicable) throws RepositoryException {
+ if (includeApplicable) {
+ return AccessControlUtils.getAccessControlList(acMgr, path);
+ } else {
+ for (AccessControlPolicy policy : acMgr.getPolicies(path)) {
+ if (policy instanceof JackrabbitAccessControlList) {
+ return (JackrabbitAccessControlList) policy;
+ }
+ }
+ return null;
+ }
+ }
@Nullable
private static PrincipalAccessControlList getPrincipalAccessControlList(@NotNull JackrabbitAccessControlManager acMgr,
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/DeleteAclTest.java b/src/test/java/org/apache/sling/jcr/repoinit/DeleteAclTest.java
index 306e63f..ed19535 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/DeleteAclTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/DeleteAclTest.java
@@ -50,7 +50,9 @@
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.assertTrue;
@RunWith(Parameterized.class)
public class DeleteAclTest {
@@ -94,6 +96,7 @@
U.parseAndExecute(""
+ "create path (nt:unstructured) /content\n"
+ "create path (nt:unstructured) /var\n"
+ + "create path (nt:unstructured) /no/policy\n"
+ "set ACL for " + U.username + "\n"
+ "allow jcr:read on /content, /var, home("+userA+")\n"
+ "allow jcr:namespaceManagement on :repository\n"
@@ -131,9 +134,22 @@
assertArrayEquals(new AccessControlPolicy[0], acMgr.getPolicies((String) null));
}
- @Test(expected = RuntimeException.class)
+ @Test
public void testDeleteAclNonExistingPath() throws Exception {
+ assertFalse(adminSession.nodeExists("/nonExisting"));
U.parseAndExecute("delete ACL on /nonExisting\n");
+ assertFalse(adminSession.nodeExists("/nonExisting"));
+ }
+
+ @Test
+ public void testDeleteNonExistingAcl() throws Exception {
+ assertTrue(adminSession.nodeExists("/no/policy"));
+ assertArrayEquals(new AccessControlPolicy[0], acMgr.getPolicies("/no/policy"));
+
+ U.parseAndExecute("delete ACL on /no/policy\n");
+
+ assertTrue(adminSession.nodeExists("/no/policy"));
+ assertArrayEquals(new AccessControlPolicy[0], acMgr.getPolicies("/no/policy"));
}
@Test
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java b/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java
index aa13145..cdce414 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java
@@ -41,6 +41,7 @@
import java.util.UUID;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
public class RemoveTest {
@@ -170,6 +171,28 @@
"end";
U.parseAndExecute(setup);
}
+
+ @Test
+ public void testRemoveByNonExistingPath() throws Exception {
+ String path = "/non/existing";
+ String setup = "remove ACE for " + U.username + "\n"
+ + "deny jcr:read on "+path+"\n"
+ + "end";
+ U.parseAndExecute(setup);
+ assertFalse(U.adminSession.nodeExists(path));
+
+ setup = "remove ACE on "+path+"\n"
+ + "deny jcr:read for " + U.username + "\n"
+ + "end";
+ U.parseAndExecute(setup);
+ assertFalse(U.adminSession.nodeExists(path));
+
+ setup = "set ACL on "+path+"\n" +
+ "remove * for "+U.username+"\n" +
+ "end";
+ U.parseAndExecute(setup);
+ assertFalse(U.adminSession.nodeExists(path));
+ }
@Test
public void testRemoveByPath() throws RepoInitParsingException, RepositoryException {