SLING-11340 Custom restriction fails validation during modifyAce call (#14)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessGetServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessGetServlet.java
index 6adc061..dc2bcda 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessGetServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessGetServlet.java
@@ -50,11 +50,9 @@
import org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
-import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceNotFoundException;
-import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.jcr.base.util.AccessControlUtil;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
@@ -64,21 +62,7 @@
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("serial")
-public abstract class AbstractAccessGetServlet extends SlingAllMethodsServlet {
-
- private transient RestrictionProvider restrictionProvider;
-
- // @Reference
- protected void bindRestrictionProvider(RestrictionProvider rp) {
- this.restrictionProvider = rp;
- }
-
- /**
- * Return the RestrictionProvider service
- */
- protected RestrictionProvider getRestrictionProvider() {
- return restrictionProvider;
- }
+public abstract class AbstractAccessGetServlet extends AbstractAccessServlet {
/* (non-Javadoc)
* @see org.apache.sling.api.servlets.SlingSafeMethodsServlet#doGet(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.SlingHttpServletResponse)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessPostServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessPostServlet.java
index 50bead1..95d2bf3 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessPostServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessPostServlet.java
@@ -39,7 +39,6 @@
import org.apache.sling.api.request.header.MediaRangeList;
import org.apache.sling.api.resource.ResourceNotFoundException;
import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.wrappers.SlingRequestPaths;
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.PrincipalAceHelper;
import org.apache.sling.servlets.post.AbstractPostResponse;
@@ -57,7 +56,7 @@
/**
* Base class for all the POST servlets for the AccessManager operations
*/
-public abstract class AbstractAccessPostServlet extends SlingAllMethodsServlet {
+public abstract class AbstractAccessPostServlet extends AbstractAccessServlet {
private static final long serialVersionUID = -5918670409789895333L;
/**
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessServlet.java
new file mode 100644
index 0000000..a330d96
--- /dev/null
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessServlet.java
@@ -0,0 +1,63 @@
+/*
+ * 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.jackrabbit.accessmanager.post;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+
+/**
+ * Base class for all the servlets for the AccessManager operations
+ */
+public abstract class AbstractAccessServlet extends SlingAllMethodsServlet {
+ private static final long serialVersionUID = 6615497265938616188L;
+
+ private transient RestrictionProvider compositeRestrictionProvider = null;
+ private transient Set<RestrictionProvider> restrictionProviders = new HashSet<>();
+
+ // @Reference
+ protected void bindRestrictionProvider(RestrictionProvider rp) {
+ synchronized (restrictionProviders) {
+ if (restrictionProviders.add(rp)) {
+ compositeRestrictionProvider = null;
+ }
+ }
+ }
+ protected void unbindRestrictionProvider(RestrictionProvider rp) {
+ synchronized (restrictionProviders) {
+ if (restrictionProviders.remove(rp)) {
+ compositeRestrictionProvider = null;
+ }
+ }
+ }
+
+ /**
+ * Return the RestrictionProvider service
+ */
+ protected RestrictionProvider getRestrictionProvider() {
+ synchronized (restrictionProviders) {
+ if (compositeRestrictionProvider == null) {
+ compositeRestrictionProvider = CompositeRestrictionProvider.newInstance(restrictionProviders);
+ }
+ return compositeRestrictionProvider;
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAceServlet.java
index a200611..906c3aa 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAceServlet.java
@@ -39,7 +39,7 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert;
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.PrivilegesHelper;
-@SuppressWarnings("serial")
+@SuppressWarnings({"serial", "java:S110"})
public abstract class AbstractGetAceServlet extends AbstractAccessGetServlet {
@Override
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
index 910c364..684f734 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
@@ -44,7 +44,7 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert;
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.PrivilegesHelper;
-@SuppressWarnings("serial")
+@SuppressWarnings({"serial", "java:S110"})
public abstract class AbstractGetAclServlet extends AbstractAccessGetServlet {
/**
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/DeleteAcesServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/DeleteAcesServlet.java
index 62cf981..167dc45 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/DeleteAcesServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/DeleteAcesServlet.java
@@ -92,6 +92,7 @@
policyOption = ReferencePolicyOption.GREEDY,
service = PostResponseCreator.class)
})
+@SuppressWarnings("java:S110")
public class DeleteAcesServlet extends AbstractAccessPostServlet implements DeleteAces {
private static final long serialVersionUID = 3784866802938282971L;
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAceServlet.java
index 17cc42c..af8ba7a 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAceServlet.java
@@ -35,6 +35,8 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.GetAce;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* <p>
@@ -79,6 +81,8 @@
reference = {
@Reference(name="RestrictionProvider",
bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
service = RestrictionProvider.class)
}
)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAclServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAclServlet.java
index d325c42..8a84876 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAclServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetAclServlet.java
@@ -33,6 +33,8 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.GetAcl;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* <p>
@@ -107,6 +109,8 @@
reference = {
@Reference(name="RestrictionProvider",
bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
service = RestrictionProvider.class)
}
)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAceServlet.java
index 738bd8a..de04f85 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAceServlet.java
@@ -38,6 +38,8 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* <p>
@@ -82,6 +84,8 @@
reference = {
@Reference(name="RestrictionProvider",
bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
service = RestrictionProvider.class)
}
)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAclServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAclServlet.java
index 224de8b..ed7677f 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAclServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetEffectiveAclServlet.java
@@ -35,6 +35,8 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* <p>
@@ -109,6 +111,8 @@
reference = {
@Reference(name="RestrictionProvider",
bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
service = RestrictionProvider.class)
}
)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetPrincipalAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetPrincipalAceServlet.java
index 4d40d88..44610c4 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetPrincipalAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/GetPrincipalAceServlet.java
@@ -43,6 +43,8 @@
import org.jetbrains.annotations.Nullable;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* <p>
@@ -87,6 +89,8 @@
reference = {
@Reference(name="RestrictionProvider",
bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
service = RestrictionProvider.class)
}
)
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
index 13abd0a..9669aa4 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
@@ -71,7 +71,6 @@
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
@@ -135,7 +134,20 @@
"sling.servlet.methods=POST",
"sling.servlet.selectors=modifyAce",
"sling.servlet.prefix:Integer=-1"
+},
+reference = {
+ @Reference(name="RestrictionProvider",
+ bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
+ service = RestrictionProvider.class),
+ @Reference(name = "PostResponseCreator",
+ bind = "bindPostResponseCreator",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
+ service = PostResponseCreator.class)
})
+@SuppressWarnings("java:S110")
public class ModifyAceServlet extends AbstractAccessPostServlet implements ModifyAce {
private static final long serialVersionUID = -9182485466670280437L;
private static final String INVALID_OR_NOT_SUPPORTED_RESTRICTION_NAME_WAS_SUPPLIED = "Invalid restriction name was supplied";
@@ -196,38 +208,6 @@
private static final Pattern RESTRICTION_PATTERN_DELETE = Pattern.compile(String.format("^restriction@([^@]+)(@([^@]+))?%s$",
SlingPostConstants.SUFFIX_DELETE));
- private transient RestrictionProvider restrictionProvider = null;
-
- // NOTE: the @Reference annotation is not inherited, so subclasses will need to override the #bindRestrictionProvider
- // and #unbindRestrictionProvider methods to provide the @Reference annotation.
- //
- @Reference(cardinality=ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, policyOption=ReferencePolicyOption.GREEDY)
- protected void bindRestrictionProvider(RestrictionProvider rp) {
- this.restrictionProvider = rp;
- }
- protected void unbindRestrictionProvider(RestrictionProvider rp) { //NOSONAR
- this.restrictionProvider = null;
- }
-
- /**
- * Overridden since the @Reference annotation is not inherited from the super method
- */
- @Override
- @Reference(service = PostResponseCreator.class,
- cardinality = ReferenceCardinality.MULTIPLE,
- policy = ReferencePolicy.DYNAMIC)
- protected void bindPostResponseCreator(PostResponseCreator creator, Map<String, Object> properties) {
- super.bindPostResponseCreator(creator, properties);
- }
-
- /* (non-Javadoc)
- * @see org.apache.sling.jackrabbit.usermanager.impl.post.AbstractPostServlet#unbindPostResponseCreator(org.apache.sling.servlets.post.PostResponseCreator, java.util.Map)
- */
- @Override
- protected void unbindPostResponseCreator(PostResponseCreator creator, Map<String, Object> properties) { //NOSONAR
- super.unbindPostResponseCreator(creator, properties);
- }
-
/* (non-Javadoc)
* @see org.apache.sling.jackrabbit.accessmanager.post.AbstractAccessPostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.servlets.post.PostResponse, java.util.List)
*/
@@ -277,7 +257,7 @@
throw new RepositoryException("JCR Session not found");
}
- if (restrictionProvider == null) {
+ if (RestrictionProvider.EMPTY.equals(getRestrictionProvider())) {
throw new IllegalStateException("No restriction provider is available so unable to process POSTed restriction values");
}
@@ -310,7 +290,7 @@
* @return map of restriction names to definition
*/
protected @NotNull Map<String, RestrictionDefinition> buildRestrictionNameToDefinitionMap(@NotNull String resourcePath) {
- Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions(resourcePath);
+ Set<RestrictionDefinition> supportedRestrictions = getRestrictionProvider().getSupportedRestrictions(resourcePath);
Map<String, RestrictionDefinition> srMap = new HashMap<>();
for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
srMap.put(restrictionDefinition.getName(), restrictionDefinition);
diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyPrincipalAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyPrincipalAceServlet.java
index 8799ddb..4963693 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyPrincipalAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyPrincipalAceServlet.java
@@ -112,6 +112,8 @@
reference = {
@Reference(name="RestrictionProvider",
bind = "bindRestrictionProvider",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
service = RestrictionProvider.class),
@Reference(name = "PostResponseCreator",
bind = "bindPostResponseCreator",
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/JsonConvertTest.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/JsonConvertTest.java
index 1ad476f..f64bf77 100644
--- a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/JsonConvertTest.java
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/JsonConvertTest.java
@@ -46,6 +46,7 @@
import org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
@@ -56,6 +57,7 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -86,7 +88,9 @@
private RestrictionDefinition rd(String restrictionName) {
if (srMap == null) {
//make a temp map for quick lookup below
- RestrictionProvider restrictionProvider = context.getService(RestrictionProvider.class);
+ @NotNull
+ RestrictionProvider[] services = context.getServices(RestrictionProvider.class, null);
+ RestrictionProvider restrictionProvider = CompositeRestrictionProvider.newInstance(services);
Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions("/");
srMap = new HashMap<>();
for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/PrivilegesHelperTest.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/PrivilegesHelperTest.java
index 1d085b0..666082a 100644
--- a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/PrivilegesHelperTest.java
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/impl/PrivilegesHelperTest.java
@@ -42,6 +42,7 @@
import org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
@@ -51,6 +52,7 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
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.Before;
import org.junit.Rule;
@@ -82,7 +84,9 @@
private RestrictionDefinition rd(String restrictionName) {
if (srMap == null) {
//make a temp map for quick lookup below
- RestrictionProvider restrictionProvider = context.getService(RestrictionProvider.class);
+ @NotNull
+ RestrictionProvider[] services = context.getServices(RestrictionProvider.class, null);
+ RestrictionProvider restrictionProvider = CompositeRestrictionProvider.newInstance(services);
Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions("/");
srMap = new HashMap<>();
for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/CustomRestrictionProviderImpl.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/CustomRestrictionProviderImpl.java
new file mode 100644
index 0000000..252d62c
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/CustomRestrictionProviderImpl.java
@@ -0,0 +1,106 @@
+/*
+ * 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.jackrabbit.accessmanager.it;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.AbstractRestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinitionImpl;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sample implementation of the RestrictionProvider interface to test that
+ * custom restrictions can be used.
+ */
+public class CustomRestrictionProviderImpl extends AbstractRestrictionProvider {
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ public static final String SLING_CUSTOM_RESTRICTION = "sling:customRestriction";
+
+ public CustomRestrictionProviderImpl() {
+ super(supportedRestrictions());
+ }
+
+ private static Map<String, RestrictionDefinition> supportedRestrictions() {
+ RestrictionDefinition slingCustomRestriction = new RestrictionDefinitionImpl(SLING_CUSTOM_RESTRICTION, Type.STRINGS, false);
+ Map<String, RestrictionDefinition> supportedRestrictions = new HashMap<String, RestrictionDefinition>();
+ supportedRestrictions.put(slingCustomRestriction.getName(), slingCustomRestriction);
+ return Collections.unmodifiableMap(supportedRestrictions);
+ }
+
+ @Override
+ public RestrictionPattern getPattern(String oakPath, Tree tree) {
+ if (oakPath != null) {
+ PropertyState resourceTypes = tree.getProperty(SLING_CUSTOM_RESTRICTION);
+ if (resourceTypes != null) {
+ CustomRestrictionPattern resourceTypePattern = new CustomRestrictionPattern();
+ logger.trace("Returning resourceTypePattern={} for sling:customRestriction in getPattern(String,Tree)", resourceTypePattern);
+ return resourceTypePattern;
+ }
+ }
+ return RestrictionPattern.EMPTY;
+ }
+
+ @Override
+ public RestrictionPattern getPattern(String oakPath, Set<Restriction> restrictions) {
+ if (oakPath != null && !restrictions.isEmpty()) {
+ for (Restriction r : restrictions) {
+ String name = r.getDefinition().getName();
+ if (SLING_CUSTOM_RESTRICTION.equals(name)) {
+ CustomRestrictionPattern resourceTypePattern = new CustomRestrictionPattern();
+ logger.trace(
+ "Returning resourceTypePattern={} for sling:customRestriction in getPattern(String,Set<Restriction>)",
+ resourceTypePattern);
+ return resourceTypePattern;
+ }
+ }
+ }
+
+ return RestrictionPattern.EMPTY;
+ }
+
+ /** Implementation of the {@link RestrictionPattern} interface that returns {@code false} */
+ public static class CustomRestrictionPattern implements RestrictionPattern {
+
+ @Override
+ public boolean matches(Tree tree, PropertyState property) {
+ return false;
+ }
+
+ @Override
+ public boolean matches(String path) {
+ return false;
+ }
+
+ @Override
+ public boolean matches() {
+ return false;
+ }
+
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/ModifyAceIT.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/ModifyAceIT.java
index 0f36503..63266ec 100644
--- a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/ModifyAceIT.java
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/it/ModifyAceIT.java
@@ -41,6 +41,7 @@
import org.apache.http.NameValuePair;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.sling.servlets.post.JSONResponse;
import org.apache.sling.servlets.post.PostResponseCreator;
@@ -63,6 +64,7 @@
public class ModifyAceIT extends AccessManagerClientTestSupport {
private ServiceRegistration<PostResponseCreator> serviceReg;
+ private ServiceRegistration<RestrictionProvider> serviceReg2;
private VerifyAce verifyTrue = jsonValue -> assertEquals(ValueType.TRUE, jsonValue.getValueType());
@Before
@@ -72,6 +74,8 @@
Dictionary<String, Object> props = new Hashtable<>(); // NOSONAR
serviceReg = bundle.getBundleContext().registerService(PostResponseCreator.class,
new CustomPostResponseCreatorImpl(), props);
+ serviceReg2 = bundle.getBundleContext().registerService(RestrictionProvider.class,
+ new CustomRestrictionProviderImpl(), props);
super.before();
}
@@ -82,6 +86,9 @@
if (serviceReg != null) {
serviceReg.unregister();
}
+ if (serviceReg2 != null) {
+ serviceReg2.unregister();
+ }
super.after();
}
@@ -2312,4 +2319,50 @@
assertEquals("javax.jcr.security.AccessControlException: No such privilege invalid_name", jsonObject.getString("status.message"));
}
+ /**
+ * Test to verify adding an ACE with a custom restriction to
+ * the ACL
+ */
+ @Test
+ public void testAddAceWithCustomRestriction() throws IOException, JsonException {
+ testUserId = createTestUser();
+ testFolderUrl = createTestFolder();
+
+ // update the ACE
+ List<NameValuePair> postParams = new AcePostParamsBuilder(testUserId)
+ .withOrder("first")
+ .withPrivilegeRestriction(PrivilegeValues.ALLOW, PrivilegeConstants.JCR_READ,
+ CustomRestrictionProviderImpl.SLING_CUSTOM_RESTRICTION, new String[] {"item1", "item2"})
+ .withPrivilegeRestriction(PrivilegeValues.DENY, PrivilegeConstants.JCR_WRITE,
+ CustomRestrictionProviderImpl.SLING_CUSTOM_RESTRICTION, new String[] {"item1", "item2"})
+ .build();
+ addOrUpdateAce(testFolderUrl, postParams);
+
+ JsonObject user = getAce(testFolderUrl, testUserId);
+ assertNotNull(user);
+ assertEquals(testUserId, user.getString("principal"));
+ assertEquals(0, user.getInt("order"));
+
+ JsonObject privilegesObject = user.getJsonObject("privileges");
+ assertNotNull(privilegesObject);
+ assertEquals(2, privilegesObject.size());
+
+ VerifyAce verifyRestrictions = jsonValue -> {
+ assertNotNull(jsonValue);
+ assertTrue(jsonValue instanceof JsonObject);
+ JsonObject restrictionsObj = (JsonObject)jsonValue;
+
+ JsonValue customValue = restrictionsObj.get(CustomRestrictionProviderImpl.SLING_CUSTOM_RESTRICTION);
+ assertNotNull(customValue);
+ assertTrue(customValue instanceof JsonArray);
+ assertEquals(2, ((JsonArray)customValue).size());
+ assertEquals("item1", ((JsonArray)customValue).getString(0));
+ assertEquals("item2", ((JsonArray)customValue).getString(1));
+ };
+ //allow privilege
+ assertPrivilege(privilegesObject, true, PrivilegeValues.ALLOW, PrivilegeConstants.JCR_READ, verifyRestrictions);
+ //deny privilege
+ assertPrivilege(privilegesObject, true, PrivilegeValues.DENY, PrivilegeConstants.JCR_WRITE, verifyRestrictions);
+ }
+
}
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessServletTest.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessServletTest.java
new file mode 100644
index 0000000..a684e02
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractAccessServletTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.jackrabbit.accessmanager.post;
+
+import static org.junit.Assert.*;
+
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.apache.sling.jcr.jackrabbit.accessmanager.it.CustomRestrictionProviderImpl;
+import org.junit.Test;
+
+/**
+ * Simple test of the common AbstractAccessServlet
+ */
+public class AbstractAccessServletTest {
+
+ @Test
+ public void testBindRestrictionProvider() {
+ TestAccessServlet tas = new TestAccessServlet();
+
+ //starts out empty
+ assertEquals("Expected the empty RestrictionProvider", RestrictionProvider.EMPTY, tas.getRestrictionProvider());
+
+ //switch from empty to the single custom restriction provider
+ CustomRestrictionProviderImpl customRestrictionProvider = new CustomRestrictionProviderImpl();
+ tas.bindRestrictionProvider(customRestrictionProvider);
+ assertEquals("Expected the custom RestrictionProvider", customRestrictionProvider, tas.getRestrictionProvider());
+
+ //binding the same again doesn't change the state
+ tas.bindRestrictionProvider(customRestrictionProvider);
+ assertEquals("Expected the custom RestrictionProvider", customRestrictionProvider, tas.getRestrictionProvider());
+
+ // binding a second unique obj switces to a CompositeRestrictionProvider
+ CustomRestrictionProviderImpl customRestrictionProvider2 = new CustomRestrictionProviderImpl();
+ tas.bindRestrictionProvider(customRestrictionProvider2);
+ assertNotEquals("Expected the custom RestrictionProvider", customRestrictionProvider, tas.getRestrictionProvider());
+ assertTrue(tas.getRestrictionProvider() instanceof CompositeRestrictionProvider);
+ }
+
+ @Test
+ public void testUnbindRestrictionProvider() {
+ TestAccessServlet tas = new TestAccessServlet();
+ CustomRestrictionProviderImpl customRestrictionProvider = new CustomRestrictionProviderImpl();
+ tas.bindRestrictionProvider(customRestrictionProvider);
+ CustomRestrictionProviderImpl customRestrictionProvider2 = new CustomRestrictionProviderImpl();
+ tas.bindRestrictionProvider(customRestrictionProvider2);
+
+ //unbinding one of them switches back to last one left
+ tas.unbindRestrictionProvider(customRestrictionProvider2);
+ assertEquals("Expected the custom RestrictionProvider", customRestrictionProvider, tas.getRestrictionProvider());
+
+ //unbinding the same again doesn't change the state
+ tas.unbindRestrictionProvider(customRestrictionProvider2);
+ assertEquals("Expected the custom RestrictionProvider", customRestrictionProvider, tas.getRestrictionProvider());
+
+ //unbinding the second one switches back to empty
+ tas.unbindRestrictionProvider(customRestrictionProvider);
+ assertEquals("Expected the empty RestrictionProvider", RestrictionProvider.EMPTY, tas.getRestrictionProvider());
+ }
+
+ @Test
+ public void testGetRestrictionProvider() {
+ TestAccessServlet tas = new TestAccessServlet();
+ assertNotNull(tas.getRestrictionProvider());
+ }
+
+ private class TestAccessServlet extends AbstractAccessServlet {
+ private static final long serialVersionUID = -2948341218853558959L;
+ }
+}
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalPrivilegeTest.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalPrivilegeTest.java
index 857db6b..b2d6ef4 100644
--- a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalPrivilegeTest.java
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalPrivilegeTest.java
@@ -37,6 +37,7 @@
import org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
@@ -46,6 +47,7 @@
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -75,7 +77,9 @@
private RestrictionDefinition rd(String restrictionName) throws Exception {
if (srMap == null) {
//make a temp map for quick lookup below
- RestrictionProvider restrictionProvider = context.getService(RestrictionProvider.class);
+ @NotNull
+ RestrictionProvider[] services = context.getServices(RestrictionProvider.class, null);
+ RestrictionProvider restrictionProvider = CompositeRestrictionProvider.newInstance(services);
Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions("/");
srMap = new HashMap<>();
for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
diff --git a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalRestrictionTest.java b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalRestrictionTest.java
index dc75978..b0d87ca 100644
--- a/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalRestrictionTest.java
+++ b/src/test/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/LocalRestrictionTest.java
@@ -34,12 +34,14 @@
import javax.jcr.ValueFactory;
import org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.CompositeRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.value.ValueFactoryImpl;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -63,7 +65,9 @@
private RestrictionDefinition rd(String restrictionName) throws Exception {
if (srMap == null) {
//make a temp map for quick lookup below
- RestrictionProvider restrictionProvider = context.getService(RestrictionProvider.class);
+ @NotNull
+ RestrictionProvider[] services = context.getServices(RestrictionProvider.class, null);
+ RestrictionProvider restrictionProvider = CompositeRestrictionProvider.newInstance(services);
Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions("/");
srMap = new HashMap<>();
for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {