This is an automated email from the ASF dual-hosted git repository.
bdelacretaz 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 bd3e865 SLING-9090 - apply patch provided by angela, with minor
changes, thanks!
bd3e865 is described below
commit bd3e865442ffbf02722a5f36020ca75dab4906f6
Author: Bertrand Delacretaz <[email protected]>
AuthorDate: Fri Feb 12 14:08:32 2021 +0100
SLING-9090 - apply patch provided by angela, with minor changes, thanks!
---
.../apache/sling/jcr/repoinit/impl/AclUtil.java | 90 ++++++--
.../apache/sling/jcr/repoinit/impl/AclVisitor.java | 44 ++--
.../apache/sling/jcr/repoinit/GeneralAclTest.java | 3 +-
.../sling/jcr/repoinit/PrincipalBasedAclTest.java | 256 +++++++++++++++++++--
.../org/apache/sling/jcr/repoinit/RemoveTest.java | 173 ++++++++++++++
5 files changed, 505 insertions(+), 61 deletions(-)
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 a57a042..90d1bfe 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,6 +47,7 @@ import org.apache.jackrabbit.util.Text;
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;
@@ -165,8 +166,33 @@ public class AclUtil {
setAcl(session, principals, (String)null, privileges, isAllow,
restrictionClauses);
}
+ public static void removeEntries(@NotNull Session session, @NotNull
List<String> principals, @NotNull List<String> paths) throws
RepositoryException {
+ Set<String> principalNames = new HashSet<>(principals);
+ for (String jcrPath : getJcrPaths(session, paths)) {
+ if (jcrPath != null && !session.nodeExists(jcrPath)) {
+ LOG.info("Cannot remove access control entries on non-existent
path {}", jcrPath);
+ } else {
+ JackrabbitAccessControlList acl =
AccessControlUtils.getAccessControlList(session, jcrPath);
+ if (acl != null) {
+ boolean modified = false;
+ for (AccessControlEntry ace :
acl.getAccessControlEntries()) {
+ if
(principalNames.contains(ace.getPrincipal().getName())) {
+ acl.removeAccessControlEntry(ace);
+ modified = true;
+ }
+ }
+ if (modified) {
+ session.getAccessControlManager().setPolicy(jcrPath,
acl);
+ }
+ } else {
+ LOG.info("Cannot remove access control entries for
principal(s) {}. No ACL at {}", principalNames, jcrPath);
+ }
+ }
+ }
+ }
+
public static void setPrincipalAcl(Session session, String principalName,
Collection<AclLine> lines) throws RepositoryException {
- JackrabbitAccessControlManager acMgr = getJACM(session);
+ final JackrabbitAccessControlManager acMgr = getJACM(session);
Principal principal = AccessControlUtils.getPrincipal(session,
principalName);
if (principal == null) {
// due to transient nature of the repo-init the principal lookup
may not succeed if completed through query
@@ -176,29 +202,35 @@ public class AclUtil {
checkState(principal != null, "Principal not found: " +
principalName);
}
- PrincipalAccessControlList acl = getPrincipalAccessControlList(acMgr,
principal);
+ final PrincipalAccessControlList acl =
getPrincipalAccessControlList(acMgr, principal);
boolean modified = false;
for (AclLine line : lines) {
- if (line.getAction() == AclLine.Action.DENY) {
+ AclLine.Action action = line.getAction();
+ if (action == AclLine.Action.DENY) {
throw new AccessControlException("PrincipalAccessControlList
doesn't support 'deny' entries.");
- }
- Privilege[] privileges =
AccessControlUtils.privilegesFromNames(session,
line.getProperty(PROP_PRIVILEGES).toArray(new String[0]));
- for (String effectivePath : getJcrPaths(session,
line.getProperty(PROP_PATHS))) {
- if (acl == null) {
- // no PrincipalAccessControlList available: don't fail if
an equivalent path-based entry with the same definition exists
- // or if there exists no node at the effective path
(unable to evaluate path-based entries).
- LOG.info("No PrincipalAccessControlList available for
principal {}", principal);
- if (!containsEquivalentEntry(session, effectivePath,
principal, privileges, true, line.getRestrictions())) {
- LOG.warn("No equivalent path-based entry exists for
principal {} and effective path {} ", principal.getName(), effectivePath);
- return;
- }
- } else {
- LocalRestrictions restrictions =
createLocalRestrictions(line.getRestrictions(), acl, session);
- 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, effectivePath);
+ } else if (action == AclLine.Action.REMOVE) {
+ throw new RuntimeException(AclLine.Action.REMOVE + " is not
supported");
+ } else if (action == AclLine.Action.REMOVE_ALL) {
+ modified = removePrincipalEntries(acl, principalName,
getJcrPaths(session, line.getProperty(PROP_PATHS)));
+ } else {
+ final Privilege[] privileges =
AccessControlUtils.privilegesFromNames(session,
line.getProperty(PROP_PRIVILEGES).toArray(new String[0]));
+ for (String effectivePath : getJcrPaths(session,
line.getProperty(PROP_PATHS))) {
+ if (acl == null) {
+ // no PrincipalAccessControlList available: don't fail
if an equivalent path-based entry with the same definition exists
+ // or if there exists no node at the effective path
(unable to evaluate path-based entries).
+ LOG.info("No PrincipalAccessControlList available for
principal {}", principal);
+ if (!containsEquivalentEntry(session, effectivePath,
principal, privileges, true, line.getRestrictions())) {
+ LOG.warn("No equivalent path-based entry exists
for principal {} and effective path {} ", principal.getName(), effectivePath);
+ return;
+ }
} else {
- modified = true;
+ final LocalRestrictions restrictions =
createLocalRestrictions(line.getRestrictions(), acl, session);
+ final 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, effectivePath);
+ } else {
+ modified = true;
+ }
}
}
}
@@ -227,6 +259,24 @@ public class AclUtil {
return acl;
}
+ private static boolean removePrincipalEntries(@Nullable
PrincipalAccessControlList acl, @NotNull String principalName, @NotNull
List<String> paths) throws RepositoryException {
+ boolean modified = false;
+ if (acl == null) {
+ LOG.info("Cannot remove entries for paths(s) {}. No
principal-based ACL for {}", paths, principalName);
+ } else {
+ for (AccessControlEntry ace : acl.getAccessControlEntries()) {
+ if (ace instanceof PrincipalAccessControlList.Entry) {
+ PrincipalAccessControlList.Entry entry =
(PrincipalAccessControlList.Entry) ace;
+ if (paths.contains(entry.getEffectivePath())) {
+ acl.removeAccessControlEntry(ace);
+ modified = true;
+ }
+ }
+ }
+ }
+ return modified;
+ }
+
@NotNull
private static List<String> getJcrPaths(@NotNull Session session, @NotNull
List<String> paths) throws RepositoryException {
List<String> jcrPaths = new ArrayList<>(paths.size());
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 b1a0c57..965bd80 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
@@ -20,6 +20,7 @@ import static
org.apache.sling.repoinit.parser.operations.AclLine.PROP_PATHS;
import static
org.apache.sling.repoinit.parser.operations.AclLine.PROP_PRINCIPALS;
import static
org.apache.sling.repoinit.parser.operations.AclLine.PROP_PRIVILEGES;
+import java.util.Collections;
import java.util.List;
import javax.jcr.Node;
@@ -55,21 +56,35 @@ class AclVisitor extends DoNothingVisitor {
return result;
}
- private void setAcl(AclLine line, Session s, List<String> principals,
List<String> paths, List<String> privileges, boolean isAllow) {
+ private void setAcl(AclLine line, Session s, List<String> principals,
List<String> paths, List<String> privileges, AclLine.Action action) {
try {
- log.info("Adding ACL '{}' entry '{}' for {} on {}", isAllow ?
"allow" : "deny", privileges, principals, paths);
- List<RestrictionClause> restrictions = line.getRestrictions();
- AclUtil.setAcl(s, principals, paths, privileges, isAllow,
restrictions);
+ if (action == AclLine.Action.REMOVE) {
+ throw new RuntimeException("remove not supported");
+ } else if (action == AclLine.Action.REMOVE_ALL) {
+ AclUtil.removeEntries(s, principals, paths);
+ } else {
+ final boolean isAllow =
line.getAction().equals(AclLine.Action.ALLOW);
+ log.info("Adding ACL '{}' entry '{}' for {} on {}", isAllow ?
"allow" : "deny", privileges, principals, paths);
+ List<RestrictionClause> restrictions = line.getRestrictions();
+ AclUtil.setAcl(s, principals, paths, privileges, isAllow,
restrictions);
+ }
} catch(Exception e) {
throw new RuntimeException("Failed to set ACL (" + e.toString() +
") " + line, e);
}
}
- private void setRepositoryAcl(AclLine line, Session s, List<String>
principals, List<String> privileges, boolean isAllow) {
+ private void setRepositoryAcl(AclLine line, Session s, List<String>
principals, List<String> privileges, AclLine.Action action) {
try {
- log.info("Adding repository level ACL '{}' entry '{}' for {}",
isAllow ? "allow" : "deny", privileges, principals);
- List<RestrictionClause> restrictions = line.getRestrictions();
- AclUtil.setRepositoryAcl(s, principals, privileges, isAllow,
restrictions);
+ if (action == AclLine.Action.REMOVE) {
+ throw new RuntimeException("remove not supported");
+ } else if (action == AclLine.Action.REMOVE_ALL) {
+ AclUtil.removeEntries(s, principals,
Collections.singletonList(null));
+ } else {
+ final boolean isAllow =
line.getAction().equals(AclLine.Action.ALLOW);
+ log.info("Adding repository level ACL '{}' entry '{}' for {}",
isAllow ? "allow" : "deny", privileges, principals);
+ List<RestrictionClause> restrictions = line.getRestrictions();
+ AclUtil.setRepositoryAcl(s, principals, privileges, isAllow,
restrictions);
+ }
} catch(Exception e) {
throw new RuntimeException("Failed to set repository level ACL ("
+ e.toString() + ") " + line, e);
}
@@ -78,24 +93,21 @@ class AclVisitor extends DoNothingVisitor {
@Override
public void visitSetAclPrincipal(SetAclPrincipals s) {
final List<String> principals = s.getPrincipals();
- for(AclLine line : s.getLines()) {
- final boolean isAllow =
line.getAction().equals(AclLine.Action.ALLOW);
+ for (AclLine line : s.getLines()) {
final List<String> paths = line.getProperty(PROP_PATHS);
if (paths != null && ! paths.isEmpty()) {
- setAcl(line, session, principals, paths, require(line,
PROP_PRIVILEGES), isAllow);
+ setAcl(line, session, principals, paths, require(line,
PROP_PRIVILEGES), line.getAction());
} else {
- setRepositoryAcl(line, session, principals, require(line,
PROP_PRIVILEGES), isAllow);
+ setRepositoryAcl(line, session, principals, require(line,
PROP_PRIVILEGES), line.getAction());
}
-
}
}
@Override
public void visitSetAclPaths(SetAclPaths s) {
final List<String> paths = s.getPaths();
- for(AclLine line : s.getLines()) {
- final boolean isAllow =
line.getAction().equals(AclLine.Action.ALLOW);
- setAcl(line, session, require(line, PROP_PRINCIPALS), paths,
require(line, PROP_PRIVILEGES), isAllow);
+ for (AclLine line : s.getLines()) {
+ setAcl(line, session, require(line, PROP_PRINCIPALS), paths,
require(line, PROP_PRIVILEGES), line.getAction());
}
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java
b/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java
index c395f81..090fbfb 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/GeneralAclTest.java
@@ -135,7 +135,6 @@ public class GeneralAclTest {
+ "allow jcr:all on /\n"
+ "end"
;
-
U.parseAndExecute(aclSetup);
try {
assertFalse(s.itemExists(path));
@@ -342,7 +341,7 @@ public class GeneralAclTest {
/**
* Verifies success/failure of adding a properties
* @param userSession
- * @param nodeName
+ * @param relativePath
* @param propertyName
* @param successExpected
* @throws RepositoryException
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 751a420..56921f7 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/PrincipalBasedAclTest.java
@@ -71,10 +71,12 @@ 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();
@@ -165,25 +167,19 @@ public class PrincipalBasedAclTest {
* @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;
- }
- };
+ SystemUserPrincipal principal = () -> 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);
- }
- });
+ 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));
+ }
+
@Test
public void readGranted() throws Exception {
String setup =
@@ -610,12 +606,10 @@ public class PrincipalBasedAclTest {
@Test
public void testHomePath() throws Exception {
- UserManager uMgr = ((JackrabbitSession)
U.adminSession).getUserManager();
- Authorizable a = uMgr.getAuthorizable(U.username);
- Principal principal = a.getPrincipal();
+ Authorizable su = getServiceUser(U.adminSession, U.username);
+ Principal principal = su.getPrincipal();
- JackrabbitAccessControlManager accessControlManager =
AclUtil.getJACM(U.adminSession);
- assertNull(getAcl(principal, accessControlManager));
+ assertNull(getAcl(principal, U.adminSession));
AclLine line = new AclLine(AclLine.Action.ALLOW);
line.setProperty(AclLine.PROP_PRINCIPALS,
Collections.singletonList(principal.getName()));
@@ -623,12 +617,12 @@ public class PrincipalBasedAclTest {
line.setProperty(AclLine.PROP_PATHS,
Collections.singletonList(":home:"+U.username+"#"));
AclUtil.setPrincipalAcl(U.adminSession, U.username,
Collections.singletonList(line));
- PrincipalAccessControlList acl = getAcl(principal,
accessControlManager);
+ PrincipalAccessControlList acl = getAcl(principal, U.adminSession);
assertNotNull(acl);
assertEquals(1, acl.size());
PrincipalAccessControlList.Entry entry =
(PrincipalAccessControlList.Entry) acl.getAccessControlEntries()[0];
-
assertArrayEquals(AccessControlUtils.privilegesFromNames(accessControlManager,
Privilege.JCR_READ), entry.getPrivileges());
- assertEquals(a.getPath(), entry.getEffectivePath());
+
assertArrayEquals(AccessControlUtils.privilegesFromNames(AclUtil.getJACM(U.adminSession),
Privilege.JCR_READ), entry.getPrivileges());
+ assertEquals(su.getPath(), entry.getEffectivePath());
}
@Test
@@ -642,7 +636,7 @@ public class PrincipalBasedAclTest {
+ "end";
U.parseAndExecute(setup);
- PrincipalAccessControlList acl = getAcl(su.getPrincipal(),
AclUtil.getJACM(U.adminSession));
+ PrincipalAccessControlList acl = getAcl(su.getPrincipal(),
U.adminSession);
assertNotNull(acl);
assertEquals(1, acl.size());
} finally {
@@ -655,9 +649,225 @@ public class PrincipalBasedAclTest {
}
}
+ @Test(expected = RuntimeException.class)
+ public void testRemoveNoExistingPolicy() throws Exception {
+ String setup = "set principal ACL for " + U.username + "\n"
+ + "remove jcr:read on " + path + "\n"
+ + "end";
+ U.parseAndExecute(setup);
+ }
+
+ @Test
+ public void testRemoveMatchingEntry() 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 testRemoveNoMatchingEntry() 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:read on " + path + "\n"
+ + "end";
+ try {
+ U.parseAndExecute(setup);
+ fail("Expecting REMOVE to fail");
+ } catch(RuntimeException rex) {
+ assertRegex(REMOVE_NOT_SUPPORTED_REGEX, rex.getMessage());
+ }
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testRemoveNonExistingPrincipal() throws Exception {
+ String setup = "set principal ACL for nonExistingPrincipal\n"
+ + "remove 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");
+
+ try {
+ setup = "set principal ACL for otherSystemPrincipal\n"
+ + "remove jcr:write on " + path + "\n"
+ + "end";
+ U.parseAndExecute(setup);
+ fail("Expecting REMOVE to fail");
+ } catch(RuntimeException rex) {
+ assertRegex(REMOVE_NOT_SUPPORTED_REGEX, rex.getMessage());
+ }
+ }
+
+ @Test
+ public void testRemoveAllNoExistingPolicy() throws Exception {
+ String setup = "set principal ACL for " + U.username + "\n"
+ + "remove * on " + path + "\n"
+ + "end";
+ U.parseAndExecute(setup);
+
+ assertNull(getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession));
+ }
+
+ @Test(expected = RuntimeException.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);
+
+ PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertTrue(acl.isEmpty());
+ }
+
+ @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);
+
+ PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertEquals(2, acl.size());
+
+ setup = "set principal ACL for " + U.username + "\n"
+ + "remove * on :repository\n"
+ + "end";
+ U.parseAndExecute(setup);
+
+ acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertEquals(1, acl.size());
+ }
+
+ @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);
+
+ PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertEquals(2, acl.size());
+
+ setup = "set principal ACL for " + U.username + "\n"
+ + "remove * on " + path + "\n"
+ + "end";
+ U.parseAndExecute(setup);
+
+ acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertEquals(1, acl.size());
+ }
+
+ @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);
+
+ PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertEquals(2, acl.size());
+
+ setup = "set principal ACL for " + U.username + "\n"
+ + "remove * on " + path + ", home("+U.username+")\n"
+ + "end";
+ U.parseAndExecute(setup);
+
+ acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertTrue(acl.isEmpty());
+ }
+
+ @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);
+
+ PrincipalAccessControlList acl = getAcl(getServiceUser(U.adminSession,
U.username).getPrincipal(), U.adminSession);
+ assertNotNull(acl);
+ assertEquals(2, acl.size());
+ }
+
+ @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);
+ }
+
+ private static Authorizable getServiceUser(@NotNull Session session,
@NotNull String uid) throws RepositoryException {
+ UserManager uMgr = ((JackrabbitSession) session).getUserManager();
+ Authorizable a = uMgr.getAuthorizable(uid);
+ if (a != null) {
+ return a;
+ } else {
+ throw new RepositoryException("Expected service user " + uid + "
to exist.");
+ }
+ }
+
@Nullable
- private static PrincipalAccessControlList getAcl(@NotNull Principal
principal, @NotNull JackrabbitAccessControlManager jacm) throws
RepositoryException {
- for (AccessControlPolicy policy : jacm.getPolicies(principal)) {
+ 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;
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java
b/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java
new file mode 100644
index 0000000..e3c87af
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/RemoveTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.jcr.repoinit.impl.AclUtil;
+import org.apache.sling.jcr.repoinit.impl.TestUtil;
+import org.apache.sling.jcr.repoinit.impl.UserUtil;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+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.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlPolicy;
+
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class RemoveTest {
+
+ @Rule
+ public final SlingContext context = new
SlingContext(ResourceResolverType.JCR_OAK);
+
+ private TestUtil U;
+ private String path;
+ private String userHomePath;
+ private String groupId;
+ private String groupPrincipalName;
+
+ @Before
+ public void before() throws RepositoryException, RepoInitParsingException {
+ U = new TestUtil(context);
+ U.parseAndExecute("create service user " + U.username);
+
+ Node n = U.adminSession.getRootNode().addNode("tmp_" + U.id);
+ path = n.getPath();
+
+ UserManager uMgr = UserUtil.getUserManager(U.adminSession);
+ Group gr = uMgr.createGroup("group_"+UUID.randomUUID().toString());
+ groupId = gr.getID();
+ groupPrincipalName = gr.getPrincipal().getName();
+
+ U.adminSession.save();
+
+ String setup = "set ACL for " + U.username + "\n"
+ + "deny jcr:read on "+path+"\n"
+ + "deny jcr:all on :repository\n"
+ + "allow jcr:read on home(" + U.username + ")\n"
+ + "end\n"
+ + "\n"
+ + "set ACL for " + groupPrincipalName + "\n"
+ + "allow jcr:read on "+path+"\n"
+ + "allow jcr:namespaceManagement on :repository\n"
+ + "allow jcr:read on home(" + U.username + ")\n"
+ + "end";
+ U.parseAndExecute(setup);
+
+ userHomePath = uMgr.getAuthorizable(U.username).getPath();
+ assertPolicy(path, U.adminSession, 2);
+ assertPolicy(null, U.adminSession, 2);
+ assertPolicy(userHomePath, U.adminSession, 2);
+
+ }
+
+ @After
+ public void after() throws RepositoryException, RepoInitParsingException {
+ try {
+ U.adminSession.removeItem(path);
+
UserUtil.getUserManager(U.adminSession).getAuthorizable(groupId).remove();
+ U.adminSession.save();
+ } finally {
+ U.cleanupUser();
+ }
+ }
+
+ private static void assertPolicy(@Nullable String path, @NotNull Session
session, int expectedSize) throws RepositoryException {
+ AccessControlPolicy[] policies =
session.getAccessControlManager().getPolicies(path);
+ for (AccessControlPolicy policy : policies) {
+ if (policy instanceof AccessControlList) {
+ assertEquals(expectedSize, ((AccessControlList)
policy).getAccessControlEntries().length);
+ return;
+ }
+ }
+ fail("No access control list found at " + path);
+ }
+
+ @Test
+ public void testRemoveAllByPath() throws RepoInitParsingException,
RepositoryException {
+ String setup = "set ACL for " + U.username + "\n"
+ + "remove * on "+path+",:repository, home("+U.username+")\n"
+ + "end";
+ U.parseAndExecute(setup);
+
+ assertPolicy(path, U.adminSession, 1);
+ assertPolicy(null, U.adminSession, 1);
+ assertPolicy(userHomePath, U.adminSession, 1);
+ }
+
+ @Test
+ public void testRemoveAllByPrincipal() throws RepoInitParsingException,
RepositoryException {
+ String setup = "set ACL on "+path+", home("+U.username+"),
:repository\n"
+ + "remove * for "+U.username+"\n" +
+ "end";
+ U.parseAndExecute(setup);
+
+ assertPolicy(path, U.adminSession, 1);
+ assertPolicy(null, U.adminSession, 1);
+ assertPolicy(userHomePath, U.adminSession, 1);
+ }
+
+ @Test
+ public void testRemoveAllByMultiplePrincipals() throws
RepoInitParsingException, RepositoryException {
+ String setup = "set ACL on "+path+"\n"
+ + "remove * for "+U.username+", "+groupPrincipalName+"\n" +
+ "end";
+ U.parseAndExecute(setup);
+
+ assertPolicy(path, U.adminSession, 0);
+ assertPolicy(null, U.adminSession, 2);
+ assertPolicy(userHomePath, U.adminSession, 2);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testRemoveByPath() throws RepoInitParsingException,
RepositoryException {
+ String setup = "set ACL for " + U.username + "\n"
+ + "remove jcr:read on "+path+"\n"
+ + "end";
+ U.parseAndExecute(setup);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testRemoveByPath2() throws RepoInitParsingException,
RepositoryException {
+ String setup = "set ACL for " + groupPrincipalName + "\n"
+ + "remove jcr:versionManagement on :repository\n"
+ + "end";
+ U.parseAndExecute(setup);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testRemoveByPrincipal() throws RepoInitParsingException,
RepositoryException {
+ String setup = "set ACL on home("+U.username+")\n"
+ + "remove jcr:all for "+U.username+"\n" +
+ "end";
+ U.parseAndExecute(setup);
+ }
+}
\ No newline at end of file