You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2021/07/27 12:53:25 UTC

[jackrabbit-oak] branch trunk updated: OAK-9514 : Add RestrictionPattern.matches(@NotNull String path, boolean isProperty)

This is an automated email from the ASF dual-hosted git repository.

angela pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 65ef656  OAK-9514 : Add RestrictionPattern.matches(@NotNull String path, boolean isProperty)
65ef656 is described below

commit 65ef6569aa395fa62368d7b763b194bf03951147
Author: angela <an...@adobe.com>
AuthorDate: Tue Jul 27 14:53:11 2021 +0200

    OAK-9514 : Add RestrictionPattern.matches(@NotNull String path, boolean isProperty)
---
 .../principalbased/impl/EntryCache.java            |  11 +-
 .../principalbased/impl/EntryPredicate.java        |  22 +-
 .../principalbased/impl/PermissionEntry.java       |   2 +
 .../impl/PrincipalBasedPermissionProvider.java     |   6 +-
 .../principalbased/impl/EntryPredicateTest.java    | 130 +++++-------
 .../authorization/permission/AllPermissions.java   |   5 +
 .../permission/CompiledPermissionImpl.java         |   8 +-
 .../permission/CompiledPermissions.java            |  12 ++
 .../authorization/permission/EntryPredicate.java   |  20 +-
 .../authorization/permission/NoPermissions.java    |   5 +
 .../authorization/permission/PermissionEntry.java  |   6 +-
 .../permission/EntryPredicateTest.java             | 225 +++++++++++++++++++--
 .../permission/PermissionEntryTest.java            |  30 ++-
 .../restriction/CompositePattern.java              |  10 +
 .../restriction/RestrictionPattern.java            |  27 ++-
 .../authorization/restriction/package-info.java    |   2 +-
 16 files changed, 403 insertions(+), 118 deletions(-)

diff --git a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryCache.java b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryCache.java
index 200a1e0..329dc48 100644
--- a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryCache.java
+++ b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryCache.java
@@ -81,7 +81,7 @@ class EntryCache implements Constants {
 
         private final String effectivePath;
         private final PrivilegeBits privilegeBits;
-        private RestrictionPattern pattern;
+        private final RestrictionPattern pattern;
 
         private PermissionEntryImpl(@NotNull Tree entryTree) {
             effectivePath = Strings.emptyToNull(TreeUtil.getString(entryTree, REP_EFFECTIVE_PATH));
@@ -105,8 +105,13 @@ class EntryCache implements Constants {
         }
 
         @Override
-        public boolean matches(@NotNull String treePath) {
-            return pattern.matches(treePath);
+        public boolean matches(@NotNull String oakPath) {
+            return pattern.matches(oakPath);
+        }
+
+        @Override
+        public boolean matches(@NotNull String oakPath, boolean isProperty) {
+            return pattern.matches(oakPath, isProperty);
         }
 
         @Override
diff --git a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicate.java b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicate.java
index c207f9c..11cc53a 100644
--- a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicate.java
+++ b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicate.java
@@ -30,12 +30,18 @@ final class EntryPredicate {
     private EntryPredicate() {}
 
     @NotNull
-    static Predicate<PermissionEntry> create(@Nullable String oakPath) {
-        if (oakPath == null) {
-            return permissionEntry -> permissionEntry.matches();
-        } else {
-            return permissionEntry -> permissionEntry.matches(oakPath);
-        }
+    static Predicate<PermissionEntry> create() {
+        return permissionEntry -> permissionEntry.matches();
+    }
+
+    @NotNull
+    static Predicate<PermissionEntry> create(@NotNull String oakPath) {
+        return permissionEntry -> permissionEntry.matches(oakPath);
+    }
+    
+    @NotNull
+    static Predicate<PermissionEntry> create(@NotNull String oakPath, boolean isProperty) {
+        return permissionEntry -> permissionEntry.matches(oakPath, isProperty);
     }
 
     @NotNull
@@ -44,7 +50,7 @@ final class EntryPredicate {
             // target node does not exist (anymore) in this workspace
             // use best effort calculation based on the item path.
             String predicatePath = (property == null) ? tree.getPath() : PathUtils.concat(tree.getPath(), property.getName());
-            return create(predicatePath);
+            return create(predicatePath, property != null);
         } else {
             return permissionEntry -> permissionEntry.matches(tree, property);
         }
@@ -61,7 +67,7 @@ final class EntryPredicate {
             return permissionEntry -> permissionEntry.appliesTo(parentTree.getPath()) && permissionEntry.matches(parentTree, null);
         } else {
             String parentPath = PathUtils.getParentPath(treePath);
-            return permissionEntry -> permissionEntry.appliesTo(parentPath) && permissionEntry.matches(parentPath);
+            return permissionEntry -> permissionEntry.appliesTo(parentPath) && permissionEntry.matches(parentPath, false);
         }
     }
 
diff --git a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PermissionEntry.java b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PermissionEntry.java
index 5a2457f..b0ff318 100644
--- a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PermissionEntry.java
+++ b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PermissionEntry.java
@@ -29,6 +29,8 @@ interface PermissionEntry {
     boolean appliesTo(@NotNull String path);
 
     boolean matches(@NotNull String oakPath);
+    
+    boolean matches(@NotNull String oakPath, boolean isProperty);
 
     boolean matches(@NotNull Tree tree, @Nullable PropertyState property);
 
diff --git a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PrincipalBasedPermissionProvider.java b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PrincipalBasedPermissionProvider.java
index 8ff91fe..18895f3 100644
--- a/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PrincipalBasedPermissionProvider.java
+++ b/oak-authorization-principalbased/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/PrincipalBasedPermissionProvider.java
@@ -341,7 +341,7 @@ class PrincipalBasedPermissionProvider implements AggregatedPermissionProvider,
         Predicate<PermissionEntry> predicate;
         if (readOnly == null) {
             oakPath = REPOSITORY_PERMISSION_PATH;
-            predicate = EntryPredicate.create(null);
+            predicate = EntryPredicate.create();
         } else {
             oakPath = readOnly.getPath();
             predicate = EntryPredicate.create(readOnly, null);
@@ -366,7 +366,7 @@ class PrincipalBasedPermissionProvider implements AggregatedPermissionProvider,
         if (effectivePath == null) {
             return PrivilegeBits.EMPTY;
         } else {
-            return modAcBits.modifiable().diff(getGrantedPrivilegeBits(effectivePath, EntryPredicate.create(effectivePath)));
+            return modAcBits.modifiable().diff(getGrantedPrivilegeBits(effectivePath, EntryPredicate.create(effectivePath, false)));
         }
     }
 
@@ -430,7 +430,7 @@ class PrincipalBasedPermissionProvider implements AggregatedPermissionProvider,
 
         private long getGranted() {
             if (grantedPermissions == -1) {
-                PrivilegeBits pb = getGrantedPrivilegeBits(REPOSITORY_PERMISSION_PATH, EntryPredicate.create(null));
+                PrivilegeBits pb = getGrantedPrivilegeBits(REPOSITORY_PERMISSION_PATH, EntryPredicate.create());
                 grantedPermissions = PrivilegeBits.calculatePermissions(pb, PrivilegeBits.EMPTY, true);
             }
             return grantedPermissions;
diff --git a/oak-authorization-principalbased/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicateTest.java b/oak-authorization-principalbased/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicateTest.java
index 4578b7d..d0a923b 100644
--- a/oak-authorization-principalbased/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicateTest.java
+++ b/oak-authorization-principalbased/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/principalbased/impl/EntryPredicateTest.java
@@ -23,17 +23,18 @@ import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.Mockito;
 
 import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.MockUtility.mockTree;
 import static org.junit.Assert.assertSame;
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 public class EntryPredicateTest {
@@ -50,39 +51,56 @@ public class EntryPredicateTest {
     public void before() {
         tree = mockTree(TREE_PATH, false);
     }
+    
+    @After
+    public void after() {
+        reset(pe, tree);
+    }
 
     @Test
     public void testCreateNullPath() {
-        Predicate<PermissionEntry> predicate = EntryPredicate.create(null);
+        Predicate<PermissionEntry> predicate = EntryPredicate.create();
         predicate.apply(pe);
 
         verify(pe, times(1)).matches();
-        verify(pe, never()).matches(Mockito.anyString());
-        verify(pe, never()).matches(Mockito.any(Tree.class), Mockito.any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
     public void testCreatePath() {
-        Predicate<PermissionEntry> predicate = EntryPredicate.create(Mockito.anyString());
+        Predicate<PermissionEntry> predicate = EntryPredicate.create("/path");
+        predicate.apply(pe);
+
+        verify(pe, times(1)).matches("/path");
+        verifyNoMoreInteractions(pe);
+    }
+
+    @Test
+    public void testCreatePathNotIsProperty() {
+        Predicate<PermissionEntry> predicate = EntryPredicate.create("/path", false);
+        predicate.apply(pe);
+
+        verify(pe, times(1)).matches("/path", false);
+        verifyNoMoreInteractions(pe);
+    }
+
+    @Test
+    public void testCreatePathIsProperty() {
+        Predicate<PermissionEntry> predicate = EntryPredicate.create("/path", true);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, times(1)).matches(Mockito.anyString());
-        verify(pe, never()).matches(Mockito.any(Tree.class), Mockito.any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verify(pe, times(1)).matches("/path", true);
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
     public void testCreateNonExistingTree() {
+        doReturn(false).when(tree).exists();
         Predicate<PermissionEntry> predicate = EntryPredicate.create(tree, null);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, times(1)).matches(tree.getPath());
-        verify(pe, times(0)).matches(PathUtils.ROOT_PATH);
-        verify(pe, never()).matches(Mockito.any(Tree.class), Mockito.any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verify(pe, times(1)).matches(tree.getPath(), false);
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -90,11 +108,8 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.create(tree, propertyState);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, times(1)).matches(PROP_PATH);
-        verify(pe, never()).matches(tree.getPath());
-        verify(pe, never()).matches(Mockito.any(Tree.class), Mockito.any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verify(pe, times(1)).matches(PROP_PATH, true);
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -104,10 +119,8 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.create(tree, null);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
         verify(pe, times(1)).matches(tree, null);
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -117,11 +130,8 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.create(tree, propertyState);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(PROP_PATH);
         verify(pe, times(1)).matches(tree, propertyState);
-        verify(pe, never()).matches(tree, PropertyStates.createProperty("another", "value"));
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -147,13 +157,10 @@ public class EntryPredicateTest {
 
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(TREE_PATH, null, Permissions.ALL);
         predicate.apply(pe);
-
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
+        
         verify(pe, times(1)).appliesTo(PARENT_PATH);
-        verify(pe, times(1)).matches(PARENT_PATH);
-        verify(pe, never()).matches(any(Tree.class), any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verify(pe, times(1)).matches(PARENT_PATH, false);
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -164,12 +171,9 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(TREE_PATH, parentTree, Permissions.ALL);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
         verify(pe, times(1)).appliesTo(PARENT_PATH);
         verify(pe, times(1)).matches(parentTree, null);
-        verify(pe, never()).matches(PARENT_PATH);
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -179,12 +183,9 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(TREE_PATH, mockTree(PARENT_PATH, false), Permissions.ALL);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
         verify(pe, times(1)).appliesTo(PARENT_PATH);
-        verify(pe, times(1)).matches(PARENT_PATH);
-        verify(pe, never()).matches(any(Tree.class), any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verify(pe, times(1)).matches(PARENT_PATH, false);
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -193,12 +194,8 @@ public class EntryPredicateTest {
         predicate.apply(pe);
 
         String parentPath = PathUtils.getParentPath(TREE_PATH);
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
         verify(pe, times(1)).appliesTo(parentPath);
-        verify(pe, never()).matches(parentPath);
-        verify(pe, never()).matches(any(Tree.class), any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -209,13 +206,8 @@ public class EntryPredicateTest {
         predicate.apply(pe);
 
         String parentPath = PathUtils.getParentPath(TREE_PATH);
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
         verify(pe, times(1)).appliesTo(parentPath);
-        verify(pe, never()).matches(parentPath);
-        verify(pe, never()).matches(any(Tree.class), any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
-    }
+        verifyNoMoreInteractions(pe); }
 
     @Test
     public void testCreateParentTreeReadPermission() {
@@ -230,13 +222,10 @@ public class EntryPredicateTest {
 
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(tree, Permissions.ADD_NODE|Permissions.READ_NODE);
         predicate.apply(pe);
-
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
+        
         verify(pe, times(1)).appliesTo(PARENT_PATH);
-        verify(pe, times(1)).matches(PARENT_PATH);
-        verify(pe, never()).matches(any(Tree.class), any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verify(pe, times(1)).matches(PARENT_PATH, false);
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -244,12 +233,8 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(tree, Permissions.ADD_NODE|Permissions.READ_NODE);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
         verify(pe, times(1)).appliesTo(PARENT_PATH);
-        verify(pe, never()).matches(PARENT_PATH);
-        verify(pe, never()).matches(any(Tree.class), any(PropertyState.class));
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -270,13 +255,9 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(tree, Permissions.REMOVE_NODE|Permissions.READ_PROPERTY|Permissions.LOCK_MANAGEMENT);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
-        verify(pe, never()).matches(PARENT_PATH);
         verify(pe, times(1)).appliesTo(PARENT_PATH);
         verify(pe, times(1)).matches(parentTree, null);
-        verify(pe, never()).matches(tree, null);
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 
     @Test
@@ -289,12 +270,7 @@ public class EntryPredicateTest {
         Predicate<PermissionEntry> predicate = EntryPredicate.createParent(tree, Permissions.REMOVE_NODE|Permissions.READ_PROPERTY|Permissions.LOCK_MANAGEMENT);
         predicate.apply(pe);
 
-        verify(pe, never()).matches();
-        verify(pe, never()).matches(TREE_PATH);
-        verify(pe, never()).matches(PARENT_PATH);
         verify(pe, times(1)).appliesTo(PARENT_PATH);
-        verify(pe, never()).matches(parentTree, null);
-        verify(pe, never()).matches(tree, null);
-        verify(pe, never()).getPrivilegeBits();
+        verifyNoMoreInteractions(pe);
     }
 }
\ No newline at end of file
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/AllPermissions.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/AllPermissions.java
index f387e7a..2ecdc26 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/AllPermissions.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/AllPermissions.java
@@ -73,6 +73,11 @@ final class AllPermissions implements CompiledPermissions {
     }
 
     @Override
+    public boolean isGranted(@NotNull String path, boolean isProperty, long permissions) {
+        return true;
+    }
+
+    @Override
     public boolean isGranted(@NotNull String path, long permissions) {
         return true;
     }
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
index f3ea78c..57f9d5c 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissionImpl.java
@@ -271,7 +271,7 @@ final class CompiledPermissionImpl implements CompiledPermissions, PermissionCon
                     if (property != null) {
                         path = PathUtils.concat(path, property.getName());
                     }
-                    return isGranted(path, permissions);
+                    return isGranted(path, property != null, permissions);
                 }
             case INTERNAL:
                 return false;
@@ -281,6 +281,12 @@ final class CompiledPermissionImpl implements CompiledPermissions, PermissionCon
     }
 
     @Override
+    public boolean isGranted(@NotNull String path, boolean isProperty, long permissions) {
+        EntryPredicate predicate = EntryPredicate.create(path, isProperty, Permissions.respectParentPermissions(permissions));
+        return hasPermissions(getEntryIterator(predicate), predicate, permissions, path);
+    }
+
+    @Override
     public boolean isGranted(@NotNull String path, long permissions) {
         EntryPredicate predicate = EntryPredicate.create(path, Permissions.respectParentPermissions(permissions));
         return hasPermissions(getEntryIterator(predicate), predicate, permissions, path);
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissions.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissions.java
index 649b351..954e633 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissions.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/CompiledPermissions.java
@@ -97,6 +97,18 @@ interface CompiledPermissions {
      * Returns {@code true} if the given {@code permissions} are granted on the
      * tree identified by the specified {@code path}.
      *
+     * @param path Path of an item
+     * @param isProperty If the path points to an property
+     * @param permissions The permissions to be tested.
+     * @return {@code true} if granted.
+     * @see {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider#isGranted(String, String)}
+     */
+    boolean isGranted(@NotNull String path, boolean isProperty, long permissions);
+    
+    /**
+     * Returns {@code true} if the given {@code permissions} are granted on the
+     * tree identified by the specified {@code path}.
+     *
      * @param path Path of a tree
      * @param permissions The permissions to be tested.
      * @return {@code true} if granted.
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java
index 5536ea5..88d028b 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicate.java
@@ -71,6 +71,24 @@ interface EntryPredicate extends Predicate<PermissionEntry> {
         };
     }
 
+    static EntryPredicate create(@NotNull String path, boolean isProperty, boolean respectParent) {
+        String parentPath = (!respectParent || PathUtils.ROOT_PATH.equals(path)) ? null : PathUtils.getParentPath(path);
+        boolean rp = respectParent && parentPath != null;
+        return new EntryPredicate() {
+            @NotNull
+            @Override
+            public String getPath() {
+                return path;
+            }
+
+            @Override
+            public boolean apply(@NotNull PermissionEntry entry, boolean respectParent) {
+                respectParent &= rp;
+                return entry.matches(path, isProperty) || (respectParent && entry.matches(parentPath, false));
+            }
+        };
+    }
+    
     static EntryPredicate create(@NotNull String path, boolean respectParent) {
         String parentPath = (!respectParent || PathUtils.ROOT_PATH.equals(path)) ? null : PathUtils.getParentPath(path);
         boolean rp = respectParent && parentPath != null;
@@ -84,7 +102,7 @@ interface EntryPredicate extends Predicate<PermissionEntry> {
             @Override
             public boolean apply(@NotNull PermissionEntry entry, boolean respectParent) {
                 respectParent &= rp;
-                return entry.matches(path) || (respectParent && entry.matches(parentPath));
+                return entry.matches(path) || (respectParent && entry.matches(parentPath, false));
             }
         };
     }
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/NoPermissions.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/NoPermissions.java
index fcce733..d1d95dd 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/NoPermissions.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/NoPermissions.java
@@ -70,6 +70,11 @@ final class NoPermissions implements CompiledPermissions {
     }
 
     @Override
+    public boolean isGranted(@NotNull String path, boolean isProperty, long permissions) {
+        return false;
+    }
+
+    @Override
     public boolean isGranted(@NotNull String path, long permissions) {
         return false;
     }
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java
index 291939a..d4bdd1e 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntry.java
@@ -72,12 +72,16 @@ final class PermissionEntry implements Comparable<PermissionEntry>, PermissionCo
         return restriction == RestrictionPattern.EMPTY || restriction.matches(treePath);
     }
 
+    boolean matches(@NotNull String path, boolean isProperty) {
+        return restriction == RestrictionPattern.EMPTY || restriction.matches(path, isProperty);
+    }
+
     boolean matches() {
         return restriction == RestrictionPattern.EMPTY || restriction.matches();
     }
 
     boolean matchesParent(@NotNull String parentPath) {
-        return Text.isDescendantOrEqual(path, parentPath) && (restriction == RestrictionPattern.EMPTY || restriction.matches(parentPath));
+        return Text.isDescendantOrEqual(path, parentPath) && (restriction == RestrictionPattern.EMPTY || restriction.matches(parentPath, false));
     }
 
     @Override
diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicateTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicateTest.java
index eff053b..614b30c 100644
--- a/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicateTest.java
+++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/EntryPredicateTest.java
@@ -23,25 +23,30 @@ import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restrict
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.junit.After;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 public class EntryPredicateTest {
 
-    private String path = "/some/path";
-    private String parentPath = PathUtils.getParentPath(path);
+    private final String path = "/some/path";
+    private final String parentPath = PathUtils.getParentPath(path);
 
-    private RestrictionPattern pattern = mock(RestrictionPattern.class);
-    private PermissionEntry entry = new PermissionEntry(path, true, 1, PrivilegeBits.EMPTY, pattern);
+    private final RestrictionPattern pattern = mock(RestrictionPattern.class);
+    private final PermissionEntry entry = new PermissionEntry(path, true, 1, PrivilegeBits.EMPTY, pattern);
 
     private Tree mockTree(@NotNull String path, @Nullable Tree parent) {
         Tree t = mock(Tree.class);
@@ -51,6 +56,11 @@ public class EntryPredicateTest {
         when(t.getPath()).thenReturn(path);
         return t;
     }
+    
+    @After
+    public void after() {
+        reset(pattern);
+    }
 
     @Test
     public void testPredicateRepositoryLevel() {
@@ -66,6 +76,7 @@ public class EntryPredicateTest {
         assertTrue(pred.apply(entry, false));
 
         verify(pattern, times(3)).matches();
+        verifyNoMoreInteractions(pattern);
     }
 
     @Test
@@ -74,16 +85,26 @@ public class EntryPredicateTest {
         assertEquals(path, pred.getPath());
 
         // pattern neither matches path nor parent path
-        when(pattern.matches(path)).thenReturn(false);
-        when(pattern.matches(parentPath)).thenReturn(false);
+        when(pattern.matches(anyString())).thenReturn(false);
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(false);
 
+        assertFalse(pred.apply(null));
         assertFalse(pred.apply(entry));
         assertFalse(pred.apply(entry, true));
         assertFalse(pred.apply(entry, false));
 
+        verify(pattern, times(3)).matches(path);
+        verify(pattern, times(2)).matches(parentPath, false);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathRespectParent2() {
+        EntryPredicate pred = EntryPredicate.create(path, true);
+
         // pattern matches path and parent path
-        when(pattern.matches(path)).thenReturn(true);
-        when(pattern.matches(parentPath)).thenReturn(true);
+        when(pattern.matches(anyString())).thenReturn(true);
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(true);
 
         assertFalse(pred.apply(null));
 
@@ -91,24 +112,43 @@ public class EntryPredicateTest {
         assertTrue(pred.apply(entry, true));
         assertTrue(pred.apply(entry, false));
 
+        verify(pattern, times(3)).matches(path);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathRespectParent3() {
+        EntryPredicate pred = EntryPredicate.create(path, true);
+
         // pattern only matches path
         when(pattern.matches(path)).thenReturn(true);
         when(pattern.matches(parentPath)).thenReturn(false);
+        when(pattern.matches(parentPath, false)).thenReturn(false);
 
         assertTrue(pred.apply(entry));
         assertTrue(pred.apply(entry, true));
         assertTrue(pred.apply(entry, false));
 
+        verify(pattern, times(3)).matches(path);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathRespectParent4() {
+        EntryPredicate pred = EntryPredicate.create(path, true);
+
         // pattern only matches parent path
         when(pattern.matches(path)).thenReturn(false);
         when(pattern.matches(parentPath)).thenReturn(true);
+        when(pattern.matches(parentPath, false)).thenReturn(true);
 
         assertTrue(pred.apply(entry));
         assertTrue(pred.apply(entry, true));
         assertFalse(pred.apply(entry, false));
 
-        verify(pattern, times(12)).matches(path);
-        verify(pattern, times(4)).matches(parentPath);
+        verify(pattern, times(3)).matches(path);
+        verify(pattern, times(2)).matches(parentPath, false);
+        verifyNoMoreInteractions(pattern);
     }
 
     @Test
@@ -117,16 +157,24 @@ public class EntryPredicateTest {
         assertEquals(path, pred.getPath());
 
         // pattern neither matches path nor parent path
-        when(pattern.matches(path)).thenReturn(false);
-        when(pattern.matches(parentPath)).thenReturn(false);
+        when(pattern.matches(anyString())).thenReturn(false);
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(false);
 
         assertFalse(pred.apply(entry));
         assertFalse(pred.apply(entry, true));
         assertFalse(pred.apply(entry, false));
 
+        verify(pattern, times(3)).matches(path);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathDontRespectParent2() {
+        EntryPredicate pred = EntryPredicate.create(path, false);
+
         // pattern matches path and parent path
-        when(pattern.matches(path)).thenReturn(true);
-        when(pattern.matches(parentPath)).thenReturn(true);
+        when(pattern.matches(anyString())).thenReturn(true);
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(true);
 
         assertFalse(pred.apply(null));
 
@@ -134,6 +182,14 @@ public class EntryPredicateTest {
         assertTrue(pred.apply(entry, true));
         assertTrue(pred.apply(entry, false));
 
+        verify(pattern, times(3)).matches(path);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathDontRespectParent3() {
+        EntryPredicate pred = EntryPredicate.create(path, false);
+        
         // pattern only matches path
         when(pattern.matches(path)).thenReturn(true);
         when(pattern.matches(parentPath)).thenReturn(false);
@@ -142,16 +198,153 @@ public class EntryPredicateTest {
         assertTrue(pred.apply(entry, true));
         assertTrue(pred.apply(entry, false));
 
+        verify(pattern, times(3)).matches(path);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathDontRespectParent4() {
+        EntryPredicate pred = EntryPredicate.create(path, false);
+        
         // pattern only matches parent path
         when(pattern.matches(path)).thenReturn(false);
         when(pattern.matches(parentPath)).thenReturn(true);
+        when(pattern.matches(parentPath, false)).thenReturn(true);
+
+        assertFalse(pred.apply(entry));
+        assertFalse(pred.apply(entry, true));
+        assertFalse(pred.apply(entry, false));
+
+        verify(pattern, times(3)).matches(path);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyRespectParent() {
+        EntryPredicate pred = EntryPredicate.create(path, true, true);
+        assertEquals(path, pred.getPath());
+
+        // pattern neither matches path nor parent path
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(false);
+
+        assertFalse(pred.apply(entry));
+        assertFalse(pred.apply(entry, true));
+        assertFalse(pred.apply(entry, false));
+        
+        verify(pattern, times(3)).matches(path, true);
+        verify(pattern, times(2)).matches(parentPath, false);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyRespectParent2() {
+        EntryPredicate pred = EntryPredicate.create(path, true, true);
+
+        // pattern matches path and parent path
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(true);
+
+        assertFalse(pred.apply(null));
+        assertTrue(pred.apply(entry));
+        assertTrue(pred.apply(entry, true));
+        assertTrue(pred.apply(entry, false));
+
+        verify(pattern, times(3)).matches(path, true);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyRespectParent3() {
+        EntryPredicate pred = EntryPredicate.create(path, true, true);
+
+        // pattern only matches path
+        when(pattern.matches(path, true)).thenReturn(true);
+
+        assertTrue(pred.apply(entry));
+        assertTrue(pred.apply(entry, true));
+        assertTrue(pred.apply(entry, false));
+
+        verify(pattern, times(3)).matches(path, true);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyRespectParent4() {
+        EntryPredicate pred = EntryPredicate.create(path, true, true);    
+
+        // pattern only matches parent path
+        when(pattern.matches(parentPath, false)).thenReturn(true);
+
+        assertTrue(pred.apply(entry));
+        assertTrue(pred.apply(entry, true));
+        assertFalse(pred.apply(entry, false));
+
+        verify(pattern, times(3)).matches(path, true);
+        verify(pattern, times(2)).matches(parentPath, false);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyDontRespectParent() {
+        EntryPredicate pred = EntryPredicate.create(path, true, false);
+        assertEquals(path, pred.getPath());
+
+        // pattern neither matches path nor parent path
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(false);
+
+        assertFalse(pred.apply(entry));
+        assertFalse(pred.apply(entry, true));
+        assertFalse(pred.apply(entry, false));
+        
+        verify(pattern, times(3)).matches(path, true);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyDontRespectParent2() {
+        EntryPredicate pred = EntryPredicate.create(path, true, false);
+        
+        // pattern matches path and parent path
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(true);
+
+        assertFalse(pred.apply(null));
+
+        assertTrue(pred.apply(entry));
+        assertTrue(pred.apply(entry, true));
+        assertTrue(pred.apply(entry, false));
+        
+        verify(pattern, times(3)).matches(path, true);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyDontRespectParent3() {
+        EntryPredicate pred = EntryPredicate.create(path, true, false);
+
+        // pattern only matches path
+        when(pattern.matches(path, true)).thenReturn(true);
+
+        assertTrue(pred.apply(entry));
+        assertTrue(pred.apply(entry, true));
+        assertTrue(pred.apply(entry, false));
+
+        verify(pattern, times(3)).matches(path, true);
+        verifyNoMoreInteractions(pattern);
+    }
+
+    @Test
+    public void testPredicatePathIsPropertyDontRespectParent4() {
+        EntryPredicate pred = EntryPredicate.create(path, true, false);
+
+        // pattern only matches parent path
+        when(pattern.matches(path, true)).thenReturn(false);
+        when(pattern.matches(parentPath, false)).thenReturn(true);
 
         assertFalse(pred.apply(entry));
         assertFalse(pred.apply(entry, true));
         assertFalse(pred.apply(entry, false));
 
-        verify(pattern, times(12)).matches(path);
-        verify(pattern, never()).matches(parentPath);
+        verify(pattern, times(3)).matches(path, true);
+        verifyNoMoreInteractions(pattern);
     }
 
     @Test
diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntryTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntryTest.java
index ccd9011..5448e94 100644
--- a/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntryTest.java
+++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionEntryTest.java
@@ -29,7 +29,9 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -38,12 +40,12 @@ import static org.mockito.Mockito.when;
 
 public class PermissionEntryTest {
 
-    private String path = "/path";
-    private int index = 15;
-    private PermissionEntry entry = new PermissionEntry(path, true, index, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_NODES), RestrictionPattern.EMPTY);
+    private final String path = "/path";
+    private final int index = 15;
+    private final PermissionEntry entry = new PermissionEntry(path, true, index, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_NODES), RestrictionPattern.EMPTY);
 
-    private RestrictionPattern pattern = mock(RestrictionPattern.class);
-    private PermissionEntry entryWithNonEmptyPattern = new PermissionEntry(path, false, index, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_ADD_PROPERTIES), pattern);
+    private final RestrictionPattern pattern = mock(RestrictionPattern.class);
+    private final PermissionEntry entryWithNonEmptyPattern = new PermissionEntry(path, false, index, PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_ADD_PROPERTIES), pattern);
 
     @Test
     public void testMatchesEmptyPattern() {
@@ -125,6 +127,7 @@ public class PermissionEntryTest {
         // the entry matchesParent if the parent of the path to be evaluated is equal or a descendant of the entry-path
         // and the pattern evaluates to true (which is always the case here)
         when(pattern.matches(anyString())).thenReturn(true);
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(true);
         assertTrue(entryWithNonEmptyPattern.matchesParent(path));
         assertTrue(entryWithNonEmptyPattern.matchesParent(PathUtils.concat(path, "parent", "of", "target")));
         assertFalse(entryWithNonEmptyPattern.matchesParent(PathUtils.getParentPath(path)));
@@ -132,11 +135,28 @@ public class PermissionEntryTest {
 
         // pattern doesn't match => always false
         when(pattern.matches(anyString())).thenReturn(false);
+        when(pattern.matches(anyString(), anyBoolean())).thenReturn(false);
         assertFalse(entryWithNonEmptyPattern.matchesParent(path));
         assertFalse(entryWithNonEmptyPattern.matchesParent(PathUtils.concat(path, "parent", "of", "target")));
         assertFalse(entryWithNonEmptyPattern.matchesParent(PathUtils.getParentPath(path)));
         assertFalse(entryWithNonEmptyPattern.matchesParent("/another/path"));
     }
+    
+    @Test
+    public void testMatchesIsProperty() {
+        // empty restriction pattern
+        assertTrue(entry.matches(path, true));
+        assertTrue(entry.matches(path, false));
+
+        // pattern always returns false
+        assertFalse(entryWithNonEmptyPattern.matches(path, true));
+        assertFalse(entryWithNonEmptyPattern.matches(path, false));
+        
+        // mock pattern
+        when(pattern.matches(path, true)).thenReturn(true);
+        assertTrue(entryWithNonEmptyPattern.matches(path, true));
+        assertFalse(entryWithNonEmptyPattern.matches(path, false));
+    }
 
     @Test
     public void testCompareToEqualPath() {
diff --git a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/CompositePattern.java b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/CompositePattern.java
index c0a08f4..ce02687 100644
--- a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/CompositePattern.java
+++ b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/CompositePattern.java
@@ -65,6 +65,16 @@ public final class CompositePattern implements RestrictionPattern {
     }
 
     @Override
+    public boolean matches(@NotNull String path, boolean isProperty) {
+        for (RestrictionPattern pattern : patterns) {
+            if (!pattern.matches(path, isProperty)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    @Override
     public boolean matches() {
         for (RestrictionPattern pattern : patterns) {
             if (!pattern.matches()) {
diff --git a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/RestrictionPattern.java b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/RestrictionPattern.java
index 6fd55f6..70551f3 100644
--- a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/RestrictionPattern.java
+++ b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/RestrictionPattern.java
@@ -40,8 +40,9 @@ public interface RestrictionPattern {
     boolean matches(@NotNull Tree tree, @Nullable PropertyState property);
 
     /**
-     * Returns {@code true} if the underlying restriction matches the specified
-     * path.
+     * Returns {@code true} if the underlying restriction matches the specified path.
+     * Note, that if the nature of the item at {@code path} is know {@link #matches(String, boolean)} should be called 
+     * instead.
      *
      * @param path The path of the target item.
      * @return {@code true} if the underlying restriction matches the specified
@@ -50,6 +51,23 @@ public interface RestrictionPattern {
     boolean matches(@NotNull String path);
 
     /**
+     * Returns {@code true} if the underlying restriction matches the specified path and item type.
+     * If the nature of the item at {@code path} is unknown {@link #matches(String)} should be called instead.
+     * 
+     * Note, for backwards compatibility this method comes with a default implementation making it equivalent to {@link #matches(String)}.
+     * Implementations of the {@link RestrictionPattern} interface should overwrite the default if the underlying 
+     * restriction applies different behavior for nodes and properties.
+     *
+     * @param path The path of the target item.
+     * @param isProperty If {@code true} the target item is known to be a property, otherwise it is known to be a node.
+     * @return {@code true} if the underlying restriction matches the specified path and item type; {@code false} otherwise.
+     * @since OAK 1.42.0
+     */
+    default boolean matches(@NotNull String path, boolean isProperty) {
+        return matches(path);
+    }
+
+    /**
      * Returns {@code true} if the underlying restriction matches for repository
      * level permissions.
      *
@@ -75,6 +93,11 @@ public interface RestrictionPattern {
         }
 
         @Override
+        public boolean matches(@NotNull String path, boolean isProperty) {
+            return true;
+        }
+
+        @Override
         public boolean matches() {
             return true;
         }
diff --git a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/package-info.java b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/package-info.java
index 2f7258c..ef9b81a 100644
--- a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/package-info.java
+++ b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/restriction/package-info.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.1.2")
+@Version("1.2.0")
 package org.apache.jackrabbit.oak.spi.security.authorization.restriction;
 
 import org.osgi.annotation.versioning.Version;