You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:56:24 UTC
[sling-org-apache-sling-oak-restrictions] 01/03: Rename
sling-oak-restrictions folder to oak-restrictions
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.oak.restrictions-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-oak-restrictions.git
commit 49238f735e5ab846627db7f327e5daf890a3aa31
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Sep 27 20:25:42 2016 +0000
Rename sling-oak-restrictions folder to oak-restrictions
The sling prefix is redundant.
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/oak-restrictions@1762555 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 114 +++++++++++
.../oak/restrictions/impl/ResourceTypePattern.java | 199 ++++++++++++++++++++
.../impl/SlingRestrictionProviderImpl.java | 120 ++++++++++++
.../restrictions/impl/ResourceTypePatternTest.java | 209 +++++++++++++++++++++
.../impl/SlingRestrictionProviderImplTest.java | 133 +++++++++++++
5 files changed, 775 insertions(+)
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..271c4e5
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>26</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>org.apache.sling.oak.restrictions</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>Apache Sling Oak Restrictions</name>
+ <description>
+ Supports additional restrictions for OAK (e.g. for resource type).
+ </description>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/oak-restrictions</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/oak-restrictions</developerConnection>
+ <url>http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/oak-restrictions</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <!--
+ org.apache.jackrabbit.oak.api: Only the classes Tree, Type and PropertyState are used in a
+ very basic version to traverse the tree
+ org.apache.jackrabbit.oak.util: Has changed to "0.0.0" in newer versions (only TreeUtil is used)
+ -->
+ <Import-Package>
+ org.apache.jackrabbit.oak.api;version="[1.0,4)",
+ org.apache.jackrabbit.oak.util;version="0.0.0",
+ *
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-core</artifactId>
+ <version>1.2.7</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.api</artifactId>
+ <version>2.9.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/oak/restrictions/impl/ResourceTypePattern.java b/src/main/java/org/apache/sling/oak/restrictions/impl/ResourceTypePattern.java
new file mode 100644
index 0000000..1ab2ac2
--- /dev/null
+++ b/src/main/java/org/apache/sling/oak/restrictions/impl/ResourceTypePattern.java
@@ -0,0 +1,199 @@
+/*
+ * 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.oak.restrictions.impl;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern;
+import org.apache.jackrabbit.oak.util.TreeUtil;
+import org.apache.sling.api.SlingConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Implementation of the {@link RestrictionPattern} interface that returns {@code true} if the resource type of the target tree (or the
+ * parent of a target property) is contained in the configured resource type. */
+public class ResourceTypePattern implements RestrictionPattern {
+ private static final Logger LOG = LoggerFactory.getLogger(ResourceTypePattern.class);
+
+ static final String DEFAULT_PATH = ".";
+ static final String PATH_MARKER = "@";
+
+ static final String SLING_RESOURCE_TYPE = SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE;
+
+
+ private final String limitedToPath;
+ private final boolean matchChildren;
+
+ private final Map<String,Set<String>> resourceTypesByPath;
+
+
+ ResourceTypePattern(@Nonnull Iterable<String> resourceTypesRaw, String limitedToPath, boolean matchChildren) {
+
+ this.limitedToPath = limitedToPath;
+ this.matchChildren = matchChildren;
+
+ Map<String,Set<String>> resourceTypesByPath = new LinkedHashMap<String,Set<String>>();
+ for (String resourceTypeRaw : resourceTypesRaw) {
+ String path;
+ String resourceType;
+ if(resourceTypeRaw.contains(PATH_MARKER)) {
+ String[] bits = resourceTypeRaw.trim().split(PATH_MARKER, 2);
+ path = bits[1];
+ resourceType = bits[0];
+ } else {
+ path = DEFAULT_PATH;
+ resourceType = resourceTypeRaw;
+ }
+
+ Set<String> resourceTypesForPath = resourceTypesByPath.get(path);
+ if(resourceTypesForPath==null) {
+ resourceTypesForPath = new HashSet<String>();
+ resourceTypesByPath.put(path, resourceTypesForPath);
+ }
+ resourceTypesForPath.add(resourceType);
+ }
+
+ this.resourceTypesByPath = Collections.unmodifiableMap(resourceTypesByPath);
+ LOG.trace("pattern setup with resourceTypesByPath={}", this.resourceTypesByPath);
+ }
+
+ String getLimitedToPath() {
+ return limitedToPath;
+ }
+
+ boolean isMatchChildren() {
+ return matchChildren;
+ }
+
+ @Override
+ public boolean matches(@Nonnull Tree tree, @Nullable PropertyState property) {
+ boolean isMatch = matchesAtTree(tree);
+ if(!isMatch && matchChildren) { // try parent hierarchy
+ Tree treeCursor = tree;
+ while(!isMatch && !treeCursor.isRoot()) {
+ treeCursor = treeCursor.getParent();
+ if(!treeCursor.getPath().startsWith(limitedToPath)) {
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("Breaking parent traversal loop: tree={}, limitedToPath={}", treeCursor.getPath(), limitedToPath);
+ }
+ break;
+ }
+ isMatch = matchesAtTree(treeCursor);
+ }
+ }
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("Match for "+tree.getPath()+": "+ (isMatch ? "YES":"NO") + " ("+this+")");
+ }
+ return isMatch;
+ }
+
+ private boolean matchesAtTree(Tree tree) {
+ boolean isResourceTypeMatch = false;
+ for (String path : resourceTypesByPath.keySet()) {
+
+ Tree treeToCheck = tree; // the default if e.g. just the resource type without @path is given
+ if(!DEFAULT_PATH.equals(path)) {
+ try {
+ String[] segments = path.split("/");
+ for (String string : segments) {
+ treeToCheck = treeToCheck.getChild(string);
+ }
+ } catch (IllegalArgumentException e) {
+ continue; // continue and ignore if path is not found
+ }
+ }
+
+ Set<String> resourceTypesForPath = resourceTypesByPath.get(path);
+ String actualResourceType = TreeUtil.getString(treeToCheck, SLING_RESOURCE_TYPE);
+ isResourceTypeMatch = resourceTypesForPath.contains(actualResourceType);
+
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("isResourceTypeMatch={} (checked at path {} at sub path {})", new Object[]{isResourceTypeMatch, tree.getPath(), path});
+ }
+ if(isResourceTypeMatch) {
+ break; // return as quickly as possible
+ }
+
+ }
+ return isResourceTypeMatch;
+ }
+
+
+ @Override
+ public boolean matches(@Nonnull String path) {
+ return false;
+ }
+
+ @Override
+ public boolean matches() {
+ // node type pattern never matches for repository level permissions
+ return false;
+ }
+
+ // -------------------------------------------------------------< Object >---
+
+ @Override
+ public String toString() {
+ return "ResourceTypePattern [limitedToPath=" + limitedToPath + ", matchChildren=" + matchChildren + ", resourceTypesByPath="
+ + resourceTypesByPath + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((limitedToPath == null) ? 0 : limitedToPath.hashCode());
+ result = prime * result + (matchChildren ? 1231 : 1237);
+ result = prime * result + ((resourceTypesByPath == null) ? 0 : resourceTypesByPath.hashCode());
+ return result;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if(this == obj)
+ return true;
+ if(obj == null)
+ return false;
+ if(getClass() != obj.getClass())
+ return false;
+ ResourceTypePattern other = (ResourceTypePattern) obj;
+ if(limitedToPath == null) {
+ if(other.limitedToPath != null)
+ return false;
+ } else if(!limitedToPath.equals(other.limitedToPath))
+ return false;
+ if(matchChildren != other.matchChildren)
+ return false;
+ if(resourceTypesByPath == null) {
+ if(other.resourceTypesByPath != null)
+ return false;
+ } else if(!resourceTypesByPath.equals(other.resourceTypesByPath))
+ return false;
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/oak/restrictions/impl/SlingRestrictionProviderImpl.java b/src/main/java/org/apache/sling/oak/restrictions/impl/SlingRestrictionProviderImpl.java
new file mode 100644
index 0000000..b2867c9
--- /dev/null
+++ b/src/main/java/org/apache/sling/oak/restrictions/impl/SlingRestrictionProviderImpl.java
@@ -0,0 +1,120 @@
+/*
+ * 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.oak.restrictions.impl;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+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.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Sling restriction provider implementation that supports the following restrictions:
+ *
+ * <ul>
+ * <li>{@link #SLING_RESOURCE_TYPES}: A restriction that allows to match against resource types (matches are exact and do not include children).</li>
+ * <li>{@link #SLING_RESOURCE_TYPES_WITH_DESCENDANTS}: A restriction that allows to match against resource types and all sub nodes of matching resource types.</li>
+ * </ul>
+ *
+ * Further sling restriction can be added here in future.
+*/
+@Component
+@Service(RestrictionProvider.class)
+public class SlingRestrictionProviderImpl extends AbstractRestrictionProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SlingRestrictionProviderImpl.class);
+
+ public static final String SLING_RESOURCE_TYPES = "sling:resourceTypes";
+ public static final String SLING_RESOURCE_TYPES_WITH_DESCENDANTS = "sling:resourceTypesWithDescendants";
+
+ public SlingRestrictionProviderImpl() {
+ super(supportedRestrictions());
+ }
+
+ private static Map<String, RestrictionDefinition> supportedRestrictions() {
+ RestrictionDefinition slingResourceTypes = new RestrictionDefinitionImpl(SLING_RESOURCE_TYPES, Type.STRINGS, false);
+ RestrictionDefinition slingResourceTypesWithChildren = new RestrictionDefinitionImpl(SLING_RESOURCE_TYPES_WITH_DESCENDANTS, Type.STRINGS, false);
+ Map<String, RestrictionDefinition> supportedRestrictions = new HashMap<String, RestrictionDefinition>();
+ supportedRestrictions.put(slingResourceTypes.getName(), slingResourceTypes);
+ supportedRestrictions.put(slingResourceTypesWithChildren.getName(), slingResourceTypesWithChildren);
+ return Collections.unmodifiableMap(supportedRestrictions);
+ }
+
+ // ------------------------------------------------< RestrictionProvider >---
+
+ @Nonnull
+ @Override
+ public RestrictionPattern getPattern(String oakPath, @Nonnull Tree tree) {
+ if (oakPath != null) {
+ PropertyState resourceTypes = tree.getProperty(SLING_RESOURCE_TYPES);
+ if (resourceTypes != null) {
+ ResourceTypePattern resourceTypePattern = new ResourceTypePattern(resourceTypes.getValue(Type.STRINGS), oakPath, false);
+ LOG.trace("Returning resourceTypePattern={} for rep:slingResourceTypes in getPattern(String,Tree)", resourceTypePattern);
+ return resourceTypePattern;
+ }
+ PropertyState resourceTypesWithChildren = tree.getProperty(SLING_RESOURCE_TYPES_WITH_DESCENDANTS);
+ if (resourceTypesWithChildren != null) {
+ ResourceTypePattern resourceTypePattern = new ResourceTypePattern(resourceTypesWithChildren.getValue(Type.STRINGS), oakPath, true);
+ LOG.trace("Returning resourceTypePattern={} for rep:slingResourceTypesWithChildren in getPattern(String,Tree)", resourceTypePattern);
+ return resourceTypePattern;
+ }
+ }
+ return RestrictionPattern.EMPTY;
+ }
+
+ @Nonnull
+ @Override
+ public RestrictionPattern getPattern(@Nullable String oakPath, @Nonnull Set<Restriction> restrictions) {
+
+ if (oakPath != null && !restrictions.isEmpty()) {
+ for (Restriction r : restrictions) {
+ String name = r.getDefinition().getName();
+ if (SLING_RESOURCE_TYPES.equals(name)) {
+ ResourceTypePattern resourceTypePattern = new ResourceTypePattern(r.getProperty().getValue(Type.STRINGS), oakPath, false);
+ LOG.trace(
+ "Returning resourceTypePattern={} for rep:slingResourceTypes in getPattern(String,Set<Restriction>)",
+ resourceTypePattern);
+ return resourceTypePattern;
+ } else if(SLING_RESOURCE_TYPES_WITH_DESCENDANTS.equals(name)) {
+ ResourceTypePattern resourceTypePattern = new ResourceTypePattern(r.getProperty().getValue(Type.STRINGS), oakPath, true);
+ LOG.trace(
+ "Returning resourceTypePattern={} for rep:slingResourceTypesWithChildren in getPattern(String,Set<Restriction>)",
+ resourceTypePattern);
+ return resourceTypePattern;
+ }
+ }
+ }
+
+ return RestrictionPattern.EMPTY;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/oak/restrictions/impl/ResourceTypePatternTest.java b/src/test/java/org/apache/sling/oak/restrictions/impl/ResourceTypePatternTest.java
new file mode 100644
index 0000000..eaffda2
--- /dev/null
+++ b/src/test/java/org/apache/sling/oak/restrictions/impl/ResourceTypePatternTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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.oak.restrictions.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.util.Arrays;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+public class ResourceTypePatternTest {
+
+ private static final String TEST_PATH = "/content/path/to/test";
+
+ private static final String RESOURCE_TYPE_TEST_PATH = "myproj/comp1";
+ private static final String RESOURCE_TYPE_SUB1 = "myproj/comp2";
+ private static final String RESOURCE_TYPE_SUB2 = "myproj/comp3";
+ private static final String RESOURCE_TYPE_SUB3 = "myproj/comp4";
+ private static final String RESOURCE_TYPE_SUBSUB1 = "myproj/comp5";
+
+ private static final String RESOURCE_TYPE_OUTSIDE_SCOPE = "myproj/outsidescope";
+
+ private static final String TEST_NODE_SUB1 = "subfolder1";
+ private static final String TEST_NODE_SUB2 = "subfolder2";
+ private static final String TEST_NODE_SUB3 = "subfolder3";
+ private static final String TEST_NODE_SUBSUB1 = "subsubfolder1";
+ private static final String TEST_NODE_SUBSUB2 = "subsubfolder2";
+
+ @Mock
+ private Tree testTree;
+
+ @Mock
+ private Tree testTreeSub1;
+
+ @Mock
+ private Tree testTreeSub2;
+
+ @Mock
+ private Tree testTreeSub3;
+
+ @Mock
+ private Tree testTreeSub3Sub1;
+
+ @Mock
+ private Tree testTreeSub3Sub2;
+
+ @Mock
+ private Tree testTreeParentOutsideScope;
+
+
+ private ResourceTypePattern resourceTypePattern;
+
+
+ @Before
+ public void setup() {
+ initMocks(this);
+
+ setupTreeMock(testTreeParentOutsideScope, StringUtils.substringBeforeLast(TEST_PATH, "/"), null, RESOURCE_TYPE_OUTSIDE_SCOPE);
+ setupTreeMock(testTree, StringUtils.substringAfterLast(TEST_PATH, "/"), testTreeParentOutsideScope, RESOURCE_TYPE_TEST_PATH);
+
+ setupTreeMock(testTreeSub1, TEST_NODE_SUB1, testTree, RESOURCE_TYPE_SUB1);
+ setupTreeMock(testTreeSub2, TEST_NODE_SUB2, testTree, RESOURCE_TYPE_SUB2);
+ setupTreeMock(testTreeSub3, TEST_NODE_SUB3, testTree, RESOURCE_TYPE_SUB3);
+
+ setupTreeMock(testTreeSub3Sub1, TEST_NODE_SUBSUB1, testTreeSub3, RESOURCE_TYPE_SUBSUB1);
+ setupTreeMock(testTreeSub3Sub2, TEST_NODE_SUBSUB2, testTreeSub3, RESOURCE_TYPE_SUBSUB1);
+
+ }
+
+
+
+ @Test
+ public void testBasicMatchWithoutChildren() {
+
+ resourceTypePattern = new ResourceTypePattern(Arrays.asList(RESOURCE_TYPE_TEST_PATH, RESOURCE_TYPE_SUB1, RESOURCE_TYPE_SUB3), TEST_PATH, false);
+
+ assertNonTreeFunctionsReturnFalse();
+
+ assertTrue(resourceTypePattern.matches(testTree, null));
+ assertTrue(resourceTypePattern.matches(testTreeSub1, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub2, null));
+ assertTrue(resourceTypePattern.matches(testTreeSub3, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3Sub1, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3Sub2, null));
+
+ }
+
+ @Test
+ public void testMatchWithoutChildren() {
+
+ String restrictionWithPath = RESOURCE_TYPE_SUB2+"@"+TEST_NODE_SUB2;
+ resourceTypePattern = new ResourceTypePattern(Arrays.asList(restrictionWithPath, RESOURCE_TYPE_SUB3), TEST_PATH, false);
+
+ assertNonTreeFunctionsReturnFalse();
+
+ assertTrue("Has to match because of @path usage "+restrictionWithPath, resourceTypePattern.matches(testTree, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub1, null));
+ assertFalse("Must not match (although it has "+RESOURCE_TYPE_SUB2+", it does not have a child '"+TEST_NODE_SUB2+"' with this resource type)", resourceTypePattern.matches(testTreeSub2, null));
+ assertTrue("Has to match because of "+RESOURCE_TYPE_SUB3+" in list", resourceTypePattern.matches(testTreeSub3, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3Sub1, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3Sub2, null));
+ }
+
+ @Test
+ public void testMatchWithChildren() {
+
+ resourceTypePattern = new ResourceTypePattern(Arrays.asList(RESOURCE_TYPE_SUB3), TEST_PATH, true);
+
+ assertNonTreeFunctionsReturnFalse();
+
+ assertFalse("Not a node at or below "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTree, null));
+ assertFalse("Not a node at or below "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub1, null));
+ assertFalse("Not a node at or below "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub2, null));
+ assertTrue("The node with "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub3, null));
+ assertTrue("A node below a node with "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub3Sub1, null));
+ assertTrue("A node below a node with "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub3Sub2, null));
+ }
+
+ @Test
+ public void testMatchWithChildrenDoesNotLeaveBasePath() {
+
+ resourceTypePattern = new ResourceTypePattern(Arrays.asList(RESOURCE_TYPE_OUTSIDE_SCOPE), TEST_PATH, true);
+
+ assertNonTreeFunctionsReturnFalse();
+
+ // all false as RESOURCE_TYPE_OUTSIDE_SCOPE is only found above TEST_PATH
+ assertFalse(resourceTypePattern.matches(testTree, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub1, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub2, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3Sub1, null));
+ assertFalse(resourceTypePattern.matches(testTreeSub3Sub2, null));
+ }
+
+ @Test
+ public void testMatchWithChildrenAndPathUsage() {
+
+ String restrictionWithPath = RESOURCE_TYPE_SUBSUB1+"@"+TEST_NODE_SUBSUB1;
+ resourceTypePattern = new ResourceTypePattern(Arrays.asList(restrictionWithPath), TEST_PATH, true);
+
+ assertNonTreeFunctionsReturnFalse();
+
+ assertFalse("This node or any of its parents do not have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTree, null));
+ assertFalse("This node or any of its parents do not have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub1, null));
+ assertFalse("This node or any of its parents do not have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1,resourceTypePattern.matches(testTreeSub2, null));
+ assertTrue("This node does have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub3, null));
+ assertTrue("A node in parent hierarchy does have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub3Sub1, null));
+ assertTrue("A node in parent hierarchy does have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub3Sub2, null));
+ }
+
+
+ private void assertNonTreeFunctionsReturnFalse() {
+ assertFalse(resourceTypePattern.matches(TEST_PATH));
+ assertFalse(resourceTypePattern.matches());
+ }
+
+ private void setupTreeMock(Tree tree, String path, Tree parentTree, String resourceType) {
+
+ doReturn(parentTree==null).when(tree).isRoot();
+ doReturn(parentTree).when(tree).getParent();
+
+ mockGetStringProperty(tree, ResourceTypePattern.SLING_RESOURCE_TYPE, resourceType);
+
+ String effectivePath = path;
+ if(parentTree!=null) {
+ effectivePath = parentTree.getPath() + "/" + path;
+ String childNodeName = StringUtils.substringAfterLast(effectivePath, "/");
+ doReturn(tree).when(parentTree).getChild(childNodeName);
+ }
+ doReturn(effectivePath).when(tree).getPath();
+
+ // default for getChild
+ doThrow(new IllegalArgumentException()).when(tree).getChild(Mockito.anyString());
+
+ }
+
+ private void mockGetStringProperty(Tree tree, String propertyName, String value) {
+ PropertyState propertyState = mock(PropertyState.class);
+ doReturn(propertyState).when(tree).getProperty(propertyName);
+ doReturn(false).when(propertyState).isArray();
+ doReturn(value).when(propertyState).getValue(Type.STRING);
+ }
+}
diff --git a/src/test/java/org/apache/sling/oak/restrictions/impl/SlingRestrictionProviderImplTest.java b/src/test/java/org/apache/sling/oak/restrictions/impl/SlingRestrictionProviderImplTest.java
new file mode 100644
index 0000000..d1d58b5
--- /dev/null
+++ b/src/test/java/org/apache/sling/oak/restrictions/impl/SlingRestrictionProviderImplTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.oak.restrictions.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+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.Restriction;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+public class SlingRestrictionProviderImplTest {
+
+ private static final String TEST_PATH = "/content/path/to/test";
+
+ private static final String RESOURCE_TYPE1 = "myproj/comp1";
+ private static final String RESOURCE_TYPE2 = "myproj/comp2";
+
+ @Mock
+ private Tree restrictionNodeTree;
+
+ @Mock
+ private PropertyState restrictionProperty;
+
+ @Mock
+ private Restriction restriction;
+
+ @Mock
+ private RestrictionDefinition definition;
+
+ private SlingRestrictionProviderImpl slingRestrictionProviderImpl;
+
+ @Before
+ public void setup() {
+ initMocks(this);
+
+ doReturn(definition).when(restriction).getDefinition();
+ doReturn(restrictionProperty).when(restriction).getProperty();
+ }
+
+ @Test
+ public void testGetPatternFromTreeResourceTypes() {
+
+ doReturn(restrictionProperty).when(restrictionNodeTree).getProperty(SlingRestrictionProviderImpl.SLING_RESOURCE_TYPES);
+ doReturn(Arrays.asList(RESOURCE_TYPE1, RESOURCE_TYPE2)).when(restrictionProperty).getValue(Type.STRINGS);
+
+ slingRestrictionProviderImpl = new SlingRestrictionProviderImpl();
+
+ RestrictionPattern pattern = slingRestrictionProviderImpl.getPattern(TEST_PATH, restrictionNodeTree);
+ assertTrue(pattern instanceof ResourceTypePattern);
+ ResourceTypePattern resourceTypePattern = (ResourceTypePattern) pattern;
+
+ assertFalse(resourceTypePattern.isMatchChildren());
+ assertEquals(TEST_PATH, resourceTypePattern.getLimitedToPath());
+ }
+
+ @Test
+ public void testGetPatternFromTreeResourceTypesWithDescendants() {
+
+ doReturn(restrictionProperty).when(restrictionNodeTree).getProperty(SlingRestrictionProviderImpl.SLING_RESOURCE_TYPES_WITH_DESCENDANTS);
+ doReturn(Arrays.asList(RESOURCE_TYPE1, RESOURCE_TYPE2)).when(restrictionProperty).getValue(Type.STRINGS);
+
+ slingRestrictionProviderImpl = new SlingRestrictionProviderImpl();
+
+ RestrictionPattern pattern = slingRestrictionProviderImpl.getPattern(TEST_PATH, restrictionNodeTree);
+ assertTrue(pattern instanceof ResourceTypePattern);
+ ResourceTypePattern resourceTypePattern = (ResourceTypePattern) pattern;
+
+ assertTrue(resourceTypePattern.isMatchChildren());
+ assertEquals(TEST_PATH, resourceTypePattern.getLimitedToPath());
+ }
+
+ @Test
+ public void testGetPatternFromRestrictionsResourceTypes() {
+
+ doReturn(SlingRestrictionProviderImpl.SLING_RESOURCE_TYPES).when(definition).getName();
+ doReturn(Arrays.asList(RESOURCE_TYPE1, RESOURCE_TYPE2)).when(restrictionProperty).getValue(Type.STRINGS);
+
+ slingRestrictionProviderImpl = new SlingRestrictionProviderImpl();
+
+ RestrictionPattern pattern = slingRestrictionProviderImpl.getPattern(TEST_PATH, new HashSet<Restriction>(Arrays.asList(restriction)));
+ assertTrue(pattern instanceof ResourceTypePattern);
+ ResourceTypePattern resourceTypePattern = (ResourceTypePattern) pattern;
+
+ assertFalse(resourceTypePattern.isMatchChildren());
+ assertEquals(TEST_PATH, resourceTypePattern.getLimitedToPath());
+
+ }
+
+ @Test
+ public void testGetPatternFromRestrictionsResourceTypesWithDescendants() {
+
+ doReturn(SlingRestrictionProviderImpl.SLING_RESOURCE_TYPES_WITH_DESCENDANTS).when(definition).getName();
+ doReturn(Arrays.asList(RESOURCE_TYPE1, RESOURCE_TYPE2)).when(restrictionProperty).getValue(Type.STRINGS);
+
+ slingRestrictionProviderImpl = new SlingRestrictionProviderImpl();
+
+ RestrictionPattern pattern = slingRestrictionProviderImpl.getPattern(TEST_PATH, new HashSet<Restriction>(Arrays.asList(restriction)));
+ assertTrue(pattern instanceof ResourceTypePattern);
+ ResourceTypePattern resourceTypePattern = (ResourceTypePattern) pattern;
+
+ assertTrue(resourceTypePattern.isMatchChildren());
+ assertEquals(TEST_PATH, resourceTypePattern.getLimitedToPath());
+
+ }
+
+}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.