This is an automated email from the ASF dual-hosted git repository.
enorman pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-contentloader.git
The following commit(s) were added to refs/heads/master by this push:
new 7587c9c SLING-8118 Add support to set ACE restrictions from
contentloader
7587c9c is described below
commit 7587c9c06b1378fbf42751d65d68e7c14cbd97b4
Author: Eric Norman <[email protected]>
AuthorDate: Sun Dec 16 13:58:58 2018 -0800
SLING-8118 Add support to set ACE restrictions from contentloader
---
pom.xml | 12 +-
.../sling/jcr/contentloader/ContentCreator.java | 38 ++++
.../internal/DefaultContentCreator.java | 28 ++-
.../contentloader/internal/readers/JsonReader.java | 151 +++++++++++++++-
.../sling/jcr/contentloader/package-info.java | 2 +-
.../internal/readers/XmlReaderTest.java | 11 ++
.../contentloader/it/ContentloaderTestSupport.java | 3 +
.../it/SLING8118InitialContentIT.java | 193 +++++++++++++++++++++
src/test/resources/initial-content/SLING-8118.json | 46 +++++
9 files changed, 476 insertions(+), 8 deletions(-)
diff --git a/pom.xml b/pom.xml
index fd2cb52..290e80a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
</parent>
<artifactId>org.apache.sling.jcr.contentloader</artifactId>
- <version>2.2.7-SNAPSHOT</version>
+ <version>2.3.0-SNAPSHOT</version>
<name>Apache Sling Initial Content Loader</name>
<description>This bundle provides initial content installation through
bundles.</description>
@@ -158,10 +158,16 @@
<!-- for security content loader (users/groups/acls) -->
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.base</artifactId>
- <version>2.1.0</version>
+ <version>3.0.6</version>
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-security-spi</artifactId>
+ <version>1.8.0</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.mime</artifactId>
<version>2.1.2</version>
@@ -282,7 +288,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.sling-mock-oak</artifactId>
- <version>2.0.2</version>
+ <version>2.1.2</version>
<scope>test</scope>
</dependency>
<dependency>
diff --git
a/src/main/java/org/apache/sling/jcr/contentloader/ContentCreator.java
b/src/main/java/org/apache/sling/jcr/contentloader/ContentCreator.java
index b53e71a..a663c51 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/ContentCreator.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/ContentCreator.java
@@ -20,8 +20,11 @@ package org.apache.sling.jcr.contentloader;
import java.io.InputStream;
import java.util.Map;
+import java.util.Set;
+import javax.jcr.Node;
import javax.jcr.RepositoryException;
+import javax.jcr.Value;
import org.osgi.annotation.versioning.ProviderType;
@@ -165,4 +168,39 @@ public interface ContentCreator {
*/
void createAce(String principal, String[] grantedPrivileges, String[]
deniedPrivileges, String order) throws RepositoryException;
+ /**
+ * Creates an Access Control Entry for the current node for the specified
+ * principal and privileges.
+ *
+ * @param principal the user or group id for the ACE
+ * @param grantedPrivileges the set of privileges to grant the principal
+ * @param deniedPrivileges the set of privileges to deny the principal
(for users only)
+ * @param order specifies the position of the ACE in the
containing ACL. (may be null)
+ * Value should be one of these:
+ * <table>
+ * <caption>Values</caption>
+ * <tr><td>first</td><td>Place the target ACE as
the first amongst its siblings</td></tr>
+ * <tr><td>last</td><td>Place the target ACE as
the last amongst its siblings</td></tr>
+ * <tr><td>before xyz</td><td>Place the target
ACE immediately before the sibling whose name is xyz</td></tr>
+ * <tr><td>after xyz</td><td>Place the target ACE
immediately after the sibling whose name is xyz</td></tr>
+ * <tr><td>numeric</td><td>Place the target ACE
at the specified index</td></tr>
+ * </table>
+ * @param restrictions specifies additional Map of single-value
restrictions to apply. (optional)
+ * @param mvRestrictions specifies additional Map of multi-value
restrictions to apply. (optional)
+ * @param removedRestrictionNames optional set of restriction names that
should be removed (if they already exist).
+ * @throws RepositoryException
+ */
+ default void createAce(String principal, String[] grantedPrivileges,
String[] deniedPrivileges, String order,
+ Map<String, Value> restrictions, Map<String, Value[]>
mvRestrictions, Set<String> removedRestrictionNames) throws RepositoryException
{
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gets the current parent Node
+ * @return the current parent node or null
+ */
+ default Node getParent() {
+ throw new UnsupportedOperationException();
+ }
+
}
diff --git
a/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
b/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
index 03650d2..7ac6388 100644
---
a/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
+++
b/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
@@ -798,6 +798,16 @@ public class DefaultContentCreator implements
ContentCreator {
* @see
org.apache.sling.jcr.contentloader.ContentCreator#createAce(java.lang.String,
java.lang.String, java.lang.String[], java.lang.String[])
*/
public void createAce(String principalId, String[] grantedPrivilegeNames,
String[] deniedPrivilegeNames, String order) throws RepositoryException {
+ createAce(principalId, grantedPrivilegeNames, deniedPrivilegeNames,
order, null, null, null);
+ }
+
+ /* (non-Javadoc)
+ * @see
org.apache.sling.jcr.contentloader.ContentCreator#createAce(java.lang.String,
java.lang.String[], java.lang.String[], java.lang.String, java.util.Map,
java.util.Map, java.util.Set)
+ */
+ @Override
+ public void createAce(String principalId, String[]
grantedPrivilegeNames, String[] deniedPrivilegeNames, String order,
+ Map<String, Value> restrictions, Map<String, Value[]>
mvRestrictions, Set<String> removedRestrictionNames)
+ throws RepositoryException {
final Node parentNode = this.parentNodeStack.peek();
Session session = parentNode.getSession();
@@ -820,11 +830,23 @@ public class DefaultContentCreator implements
ContentCreator {
String resourcePath = parentNode.getPath();
if ((grantedPrivilegeNames != null) || (deniedPrivilegeNames != null))
{
- AccessControlUtil.replaceAccessControlEntry(session, resourcePath,
principal, grantedPrivilegeNames, deniedPrivilegeNames, null, order);
+ AccessControlUtil.replaceAccessControlEntry(session, resourcePath,
principal, grantedPrivilegeNames, deniedPrivilegeNames, null, order,
+ restrictions, mvRestrictions, removedRestrictionNames);
}
- }
+ }
- /**
+
+ /* (non-Javadoc)
+ * @see org.apache.sling.jcr.contentloader.ContentCreator#getParent()
+ */
+ @Override
+ public Node getParent() {
+ final Node parentNode = this.parentNodeStack.peek();
+ return parentNode;
+ }
+
+
+ /**
* used for the md5
*/
private static final char[] hexTable = "0123456789abcdef".toCharArray();
diff --git
a/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
b/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
index c14ba98..f004fcf 100644
---
a/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
+++
b/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
@@ -32,8 +32,12 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonException;
@@ -41,10 +45,17 @@ import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.json.JsonValue;
+import javax.json.JsonValue.ValueType;
+import
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
+import
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.sling.jcr.contentloader.ContentCreator;
import org.apache.sling.jcr.contentloader.ContentReader;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Component;
/**
@@ -464,8 +475,146 @@ public class JsonReader implements ContentReader {
}
String order = ace.getString("order", null);
+
+ Map<String, Value> restrictionsMap = null;
+ Map<String, Value[]> mvRestrictionsMap = null;
+ Set<String> removedRestrictionNames = null;
+ JsonObject restrictions = (JsonObject) ace.get("restrictions");
+ if (restrictions != null) {
+ //lazy initialized map for quick lookup when processing
restrictions
+ Map<String, RestrictionDefinition>
supportedRestrictionsMap = new HashMap<>();
+
+ Node parentNode = contentCreator.getParent();
+
+ RestrictionProvider restrictionProvider = null;
+ Bundle bundle = FrameworkUtil.getBundle(getClass());
+ BundleContext bundleContext = bundle.getBundleContext();
+ ServiceReference<RestrictionProvider> serviceReference
= null;
+ try {
+ serviceReference =
bundleContext.getServiceReference(RestrictionProvider.class);
+ restrictionProvider =
bundleContext.getService(serviceReference);
+
+ if (restrictionProvider == null) {
+ throw new JsonException("No restriction
provider is available so unable to process restriction values");
+ }
+
+ // populate the map
+ Set<RestrictionDefinition>
supportedRestrictions =
restrictionProvider.getSupportedRestrictions(parentNode.getPath());
+ for (RestrictionDefinition
restrictionDefinition : supportedRestrictions) {
+
supportedRestrictionsMap.put(restrictionDefinition.getName(),
restrictionDefinition);
+ }
+ } finally {
+ if (serviceReference != null) {
+
bundleContext.ungetService(serviceReference);
+ }
+ }
+
+ restrictionsMap = new HashMap<>();
+ mvRestrictionsMap = new HashMap<>();
+ removedRestrictionNames = new HashSet<>();
+
+ ValueFactory factory =
parentNode.getSession().getValueFactory();
+
+ Set<String> keySet = restrictions.keySet();
+ for (String rname : keySet) {
+ if (rname.endsWith("@Delete")) {
+ //add the key to the 'remove' set. the
value doesn't matter and is ignored.
+ String rname2 = rname.substring(9,
rname.length() - 7);
+ removedRestrictionNames.add(rname2);
+ } else {
+ RestrictionDefinition rd =
supportedRestrictionsMap.get(rname);
+ if (rd == null) {
+ //illegal restriction name?
+ throw new
JsonException("Invalid or not supported restriction name was supplied: " +
rname);
+ }
+
+ boolean multival =
rd.getRequiredType().isArray();
+ int restrictionType =
rd.getRequiredType().tag();
+
+ //read the requested restriction value
and apply it
+ JsonValue jsonValue =
restrictions.get(rname);
+
+ if (multival) {
+ if (jsonValue.getValueType() ==
ValueType.ARRAY) {
+ JsonArray jsonArray =
(JsonArray)jsonValue;
+ int size =
jsonArray.size();
+ Value [] values = new
Value[size];
+ for (int i = 0; i <
size; i++) {
+ values[i] =
toValue(factory, jsonArray.get(i), restrictionType);
+ }
+
mvRestrictionsMap.put(rname, values);
+ } else {
+ Value v =
toValue(factory, jsonValue, restrictionType);
+
mvRestrictionsMap.put(rname, new Value[] {v});
+ }
+ } else {
+ if (jsonValue.getValueType() ==
ValueType.ARRAY) {
+ JsonArray jsonArray =
(JsonArray)jsonValue;
+ int size =
jsonArray.size();
+ if (size == 1) {
+ Value v =
toValue(factory, jsonArray.get(0), restrictionType);
+
restrictionsMap.put(rname, v);
+ } else if (size > 1) {
+ throw new
JsonException("Unexpected multi value array data found for single-value
restriction value for name: " + rname);
+ }
+ } else {
+ Value v =
toValue(factory, jsonValue, restrictionType);
+
restrictionsMap.put(rname, v);
+ }
+ }
+ }
+ }
+ }
//do the work.
- contentCreator.createAce(principalID, grantedPrivileges,
deniedPrivileges, order);
+ if (restrictionsMap == null && mvRestrictionsMap == null &&
removedRestrictionNames == null) {
+ contentCreator.createAce(principalID,
grantedPrivileges, deniedPrivileges, order);
+ } else {
+ contentCreator.createAce(principalID,
grantedPrivileges, deniedPrivileges, order, restrictionsMap, mvRestrictionsMap,
+ removedRestrictionNames == null ? null
: removedRestrictionNames);
+ }
+ }
+
+ /**
+ * Attempt to convert the JsonValue to the equivalent JCR Value object
+ *
+ * @param factory the JCR value factory
+ * @param jsonValue the JSON value to convert
+ * @param restrictionType a hint for the expected property type of the
value
+ * @return the Value if converted or null otherwise
+ * @throws ValueFormatException
+ */
+ private Value toValue(ValueFactory factory, JsonValue jsonValue, int
restrictionType) throws ValueFormatException {
+ Value value = null;
+ ValueType valueType = jsonValue.getValueType();
+ switch (valueType) {
+ case TRUE:
+ value = factory.createValue(false);
+ break;
+ case FALSE:
+ value = factory.createValue(false);
+ break;
+ case NUMBER:
+ JsonNumber jsonNumber = (JsonNumber)jsonValue;
+ if (jsonNumber.isIntegral()) {
+ value =
factory.createValue(jsonNumber.longValue());
+ } else {
+ value =
factory.createValue(jsonNumber.doubleValue());
+ }
+ break;
+ case STRING:
+ value =
factory.createValue(((JsonString)jsonValue).getString(), restrictionType);
+ break;
+ case NULL:
+ value = null;
+ break;
+ case ARRAY:
+ case OBJECT:
+ default:
+ //illegal JSON?
+ break;
+ }
+
+ return value;
}
}
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/package-info.java
b/src/main/java/org/apache/sling/jcr/contentloader/package-info.java
index 64f75e4..155fe79 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/package-info.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/package-info.java
@@ -17,6 +17,6 @@
* under the License.
*/
[email protected]("0.2.2")
[email protected]("0.3.0")
package org.apache.sling.jcr.contentloader;
diff --git
a/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
b/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
index 77b1755..e4d9439 100644
---
a/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
+++
b/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
@@ -29,8 +29,10 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.jcr.RepositoryException;
+import javax.jcr.Value;
import org.apache.sling.jcr.contentloader.ContentCreator;
@@ -163,6 +165,15 @@ public class XmlReaderTest extends TestCase {
throws RepositoryException {
}
+ /* (non-Javadoc)
+ * @see
org.apache.sling.jcr.contentloader.ContentCreator#createAce(java.lang.String,
java.lang.String[], java.lang.String[], java.lang.String, java.util.Map,
java.util.Map, java.util.Set)
+ */
+ @Override
+ public void createAce(String principal, String[]
grantedPrivileges, String[] deniedPrivileges, String order,
+ Map<String, Value> restrictions, Map<String,
Value[]> mvRestrictions,
+ Set<String> removedRestrictionNames) throws
RepositoryException {
+ }
+
public void createGroup(String name, String[] members,
Map<String, Object> extraProperties) throws
RepositoryException {
}
diff --git
a/src/test/java/org/apache/sling/jcr/contentloader/it/ContentloaderTestSupport.java
b/src/test/java/org/apache/sling/jcr/contentloader/it/ContentloaderTestSupport.java
index 7e71609..5bc7617 100644
---
a/src/test/java/org/apache/sling/jcr/contentloader/it/ContentloaderTestSupport.java
+++
b/src/test/java/org/apache/sling/jcr/contentloader/it/ContentloaderTestSupport.java
@@ -97,6 +97,9 @@ public abstract class ContentloaderTestSupport extends
TestSupport {
@Configuration
public Option[] configuration() {
+ //workaround to get the required jcr.base bundle into the runtime
+ SlingOptions.versionResolver.setVersionFromProject("org.apache.sling",
"org.apache.sling.jcr.base");
+
CompositeOption quickstart = (CompositeOption) quickstart();
final Option[] options =
Arrays.stream(quickstart.getOptions()).filter(e -> !Objects.deepEquals(e,
mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.jcr.contentloader").version(SlingOptions.versionResolver.getVersion("org.apache.sling",
"org.apache.sling.jcr.contentloader"))
diff --git
a/src/test/java/org/apache/sling/jcr/contentloader/it/SLING8118InitialContentIT.java
b/src/test/java/org/apache/sling/jcr/contentloader/it/SLING8118InitialContentIT.java
new file mode 100644
index 0000000..dd08ec4
--- /dev/null
+++
b/src/test/java/org/apache/sling/jcr/contentloader/it/SLING8118InitialContentIT.java
@@ -0,0 +1,193 @@
+/*
+ * 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.contentloader.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlList;
+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.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.tinybundles.core.TinyBundle;
+import org.osgi.framework.Bundle;
+
+/**
+ * test of a bundle that provides initial content that defines an ace with
restrictions
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class SLING8118InitialContentIT extends ContentloaderTestSupport {
+
+ protected TinyBundle setupTestBundle(TinyBundle b) throws IOException {
+ b.set(SLING_INITIAL_CONTENT_HEADER, DEFAULT_PATH_IN_BUNDLE +
";path:=" + contentRootPath);
+ addContent(b, DEFAULT_PATH_IN_BUNDLE, "SLING-8118.json");
+ return b;
+ }
+
+ @Test
+ public void bundleStarted() {
+ final Bundle b = findBundle(bundleSymbolicName);
+ assertNotNull("Expecting bundle to be found:" +
bundleSymbolicName, b);
+ assertEquals("Expecting bundle to be active:" +
bundleSymbolicName, Bundle.ACTIVE, b.getState());
+ }
+
+ @Test
+ public void initialContentInstalled() throws RepositoryException {
+ final String folderPath = contentRootPath + "/SLING-8118";
+ assertTrue("Expecting initial content to be installed",
session.itemExists(folderPath));
+ assertEquals("folder has node type 'sling:Folder'",
"sling:Folder", session.getNode(folderPath).getPrimaryNodeType().getName());
+ }
+
+ @Test
+ public void userCreated() throws RepositoryException {
+ UserManager userManager =
AccessControlUtil.getUserManager(session);
+ Authorizable authorizable =
userManager.getAuthorizable("sling8118_user");
+ assertNotNull("Expecting test user to exist", authorizable);
+ }
+
+ @Test
+ public void groupCreated() throws RepositoryException {
+ UserManager userManager =
AccessControlUtil.getUserManager(session);
+ Authorizable authorizable =
userManager.getAuthorizable("sling8118_group");
+ assertNotNull("Expecting test group to exist", authorizable);
+ assertTrue(authorizable instanceof Group);
+ Iterator<Authorizable> members =
((Group)authorizable).getMembers();
+ assertTrue(members.hasNext());
+ Authorizable firstMember = members.next();
+ assertEquals("sling8118_user", firstMember.getID());
+ }
+
+ @Test
+ public void aceWithRestrictionsCreated() throws RepositoryException {
+ final String folderPath = contentRootPath + "/SLING-8118";
+ assertTrue("Expecting test folder to exist",
session.itemExists(folderPath));
+
+ AccessControlManager accessControlManager =
AccessControlUtil.getAccessControlManager(session);
+ AccessControlPolicy[] policies =
accessControlManager.getPolicies(folderPath);
+ List<AccessControlEntry> allEntries = new
ArrayList<AccessControlEntry>();
+ for (AccessControlPolicy accessControlPolicy : policies) {
+ if (accessControlPolicy instanceof AccessControlList) {
+ AccessControlEntry[] accessControlEntries =
((AccessControlList)accessControlPolicy).getAccessControlEntries();
+ for (AccessControlEntry accessControlEntry :
accessControlEntries) {
+ allEntries.add(accessControlEntry);
+ }
+ }
+ }
+ assertEquals(3, allEntries.size());
+ Map<String, AccessControlEntry> aceMap = new HashMap<>();
+ for (AccessControlEntry accessControlEntry : allEntries) {
+ aceMap.put(accessControlEntry.getPrincipal().getName(),
accessControlEntry);
+ }
+
+ //check ACE for sling8118_user
+ AccessControlEntry testUserAce = aceMap.get("sling8118_user");
+ assertNotNull("Expected ACE for test user", testUserAce);
+ assertEquals("sling8118_user",
testUserAce.getPrincipal().getName());
+ Privilege[] privileges = testUserAce.getPrivileges();
+ assertNotNull(privileges);
+ assertEquals(2, privileges.length);
+ Set<String> privilegeNames = new HashSet<>();
+ for (Privilege privilege : privileges) {
+ privilegeNames.add(privilege.getName());
+ }
+ assertTrue("Expecting granted read privilege",
privilegeNames.contains("jcr:read"));
+ assertTrue("Expecting granted write privilege",
privilegeNames.contains("jcr:write"));
+
+ //check restrictions
+ assertTrue(testUserAce instanceof JackrabbitAccessControlEntry);
+ JackrabbitAccessControlEntry testUserJAce =
(JackrabbitAccessControlEntry)testUserAce;
+ String[] testUserRestrictionNames =
testUserJAce.getRestrictionNames();
+ assertNotNull(testUserRestrictionNames);
+ assertEquals(1, testUserRestrictionNames.length);
+ assertEquals("rep:glob", testUserRestrictionNames[0]);
+ Value globRestriction = testUserJAce.getRestriction("rep:glob");
+ assertNotNull(globRestriction);
+ assertEquals("glob1", globRestriction.getString());
+
+ //check ACE for sling8118_group
+ AccessControlEntry testGroupAce = aceMap.get("sling8118_group");
+ assertNotNull("Expected ACE for test user", testGroupAce);
+ assertEquals("sling8118_group",
testGroupAce.getPrincipal().getName());
+ privileges = testGroupAce.getPrivileges();
+ assertNotNull(privileges);
+ assertEquals(1, privileges.length);
+ privilegeNames = new HashSet<>();
+ for (Privilege privilege : privileges) {
+ privilegeNames.add(privilege.getName());
+ }
+ assertTrue("Expecting granted modifyAccessControl privilege",
privilegeNames.contains("jcr:modifyAccessControl"));
+
+ //check restrictions
+ assertTrue(testGroupAce instanceof
JackrabbitAccessControlEntry);
+ JackrabbitAccessControlEntry testGroupJAce =
(JackrabbitAccessControlEntry)testGroupAce;
+ String[] testGroupRestrictionNames =
testGroupJAce.getRestrictionNames();
+ assertNotNull(testGroupRestrictionNames);
+ assertEquals(1, testGroupRestrictionNames.length);
+ assertEquals("rep:itemNames", testGroupRestrictionNames[0]);
+ Value[] restrictions =
testGroupJAce.getRestrictions("rep:itemNames");
+ assertNotNull(restrictions);
+ assertEquals(2, restrictions.length);
+ assertEquals("name1", restrictions[0].getString());
+ assertEquals("name2", restrictions[1].getString());
+
+
+
+ //check ACE for everyone group
+ AccessControlEntry everyoneAce = aceMap.get("everyone");
+ assertNotNull("Expected ACE for everyone", everyoneAce);
+ assertEquals("everyone", everyoneAce.getPrincipal().getName());
+ privileges = everyoneAce.getPrivileges();
+ assertNotNull(privileges);
+ assertEquals(1, privileges.length);
+
+ assertEquals("Expecting granted read privilege", "jcr:read",
privileges[0].getName());
+
+ //check restrictions
+ assertTrue(everyoneAce instanceof JackrabbitAccessControlEntry);
+ JackrabbitAccessControlEntry everyoneJAce =
(JackrabbitAccessControlEntry)everyoneAce;
+ String[] everyoneRestrictionNames =
everyoneJAce.getRestrictionNames();
+ assertNotNull(everyoneRestrictionNames);
+ assertEquals(0, everyoneRestrictionNames.length);
+ }
+}
diff --git a/src/test/resources/initial-content/SLING-8118.json
b/src/test/resources/initial-content/SLING-8118.json
new file mode 100644
index 0000000..8c84672
--- /dev/null
+++ b/src/test/resources/initial-content/SLING-8118.json
@@ -0,0 +1,46 @@
+{
+ "jcr:primaryType" : "sling:Folder",
+ "security:principals": [
+ {
+ "name": "sling8118_user",
+ "password": "mypassword"
+ },
+ {
+ "name": "sling8118_group",
+ "isgroup": true,
+ "members":[
+ "sling8118_user"
+ ]
+ }
+ ],
+ "security:acl": [
+ {
+ "principal": "everyone",
+ "granted": [
+ "jcr:read"
+ ]
+ },
+ {
+ "principal": "sling8118_user",
+ "granted": [
+ "jcr:read",
+ "jcr:write"
+ ],
+ "restrictions": {
+ "rep:glob": "glob1"
+ }
+ },
+ {
+ "principal": "sling8118_group",
+ "granted": [
+ "jcr:modifyAccessControl"
+ ],
+ "restrictions": {
+ "rep:itemNames": [
+ "name1",
+ "name2"
+ ]
+ }
+ }
+ ]
+}