You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2023/10/04 07:58:20 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-721 check for rep:AuthorizableFolder nodetype before principal policy search (#314)

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

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git


The following commit(s) were added to refs/heads/master by this push:
     new 3fd74955 JCRVLT-721 check for rep:AuthorizableFolder nodetype before principal policy search (#314)
3fd74955 is described below

commit 3fd7495594126785f5220bd8e3e3ef6ab6026d98
Author: Mark Adamcin <ad...@users.noreply.github.com>
AuthorDate: Wed Oct 4 00:58:13 2023 -0700

    JCRVLT-721 check for rep:AuthorizableFolder nodetype before principal policy search (#314)
---
 .../spi/impl/jcr20/JackrabbitACLManagementIT.java  | 52 +++++++++++++++++++++
 .../fs/spi/impl/jcr20/JackrabbitACLManagement.java | 53 ++++++++--------------
 2 files changed, 70 insertions(+), 35 deletions(-)

diff --git a/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagementIT.java b/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagementIT.java
new file mode 100644
index 00000000..29c7d29b
--- /dev/null
+++ b/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagementIT.java
@@ -0,0 +1,52 @@
+/*
+ * 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.jackrabbit.vault.fs.spi.impl.jcr20;
+
+import org.apache.jackrabbit.vault.packaging.integration.IntegrationTestBase;
+import org.junit.Test;
+
+import javax.jcr.GuestCredentials;
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlPolicy;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Testcase for {@link JackrabbitACLManagement}
+ */
+public class JackrabbitACLManagementIT extends IntegrationTestBase {
+
+    @Test
+    public void testReadOnlyPermissionsOverHome() throws Exception {
+        Session session = repository.login(new GuestCredentials());
+        final String userId = session.getUserID();
+        JackrabbitACLManagement service = new JackrabbitACLManagement();
+        JackrabbitUserManagement userManagement = new JackrabbitUserManagement();
+        final String userPath = userManagement.getAuthorizablePath(session, userId);
+        assertNodeExists(userPath);
+        final Node userNode = session.getNode(userPath);
+        final Map<String, List<? extends AccessControlPolicy>> policies = service.getPrincipalAcls(userNode);
+        assertNotNull(policies);
+        assertTrue(policies.isEmpty());
+    }
+}
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagement.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagement.java
index 2fb3f5f1..eff7c7a1 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagement.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitACLManagement.java
@@ -24,12 +24,10 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 import java.util.function.Consumer;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
-import javax.jcr.Session;
 import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.AccessControlPolicy;
 
@@ -37,11 +35,8 @@ import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
 import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.JcrUtils;
-import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.fs.spi.ACLManagement;
 import org.apache.jackrabbit.vault.fs.spi.UserManagement;
 import org.apache.jackrabbit.vault.util.UncheckedRepositoryException;
@@ -73,6 +68,11 @@ public class JackrabbitACLManagement implements ACLManagement {
      * The primary node type name of the principal based access control policy node.
      */
     public static final String NT_REP_PRINCIPAL_POLICY = "rep:PrincipalPolicy";
+
+    /**
+     * The primary node type name of intermediate folders within which authorizables might be found.
+     */
+    public static final String NT_REP_AUTHORIZABLE_FOLDER = "rep:AuthorizableFolder";
    
     /** the name of the repository wide ACL policy node (both principal and resource based) */
     public static final String REP_REPO_POLICY = "rep:repoPolicy";
@@ -103,32 +103,12 @@ public class JackrabbitACLManagement implements ACLManagement {
      */
     public static final String MIX_REP_PRINCIPAL_BASED_MIXIN = "rep:PrincipalBasedMixin";
 
-    private String groupsRootPath;
-    private String usersRootPath;
     private final UserManagement userManagement;
 
     public JackrabbitACLManagement() {
         userManagement = new JackrabbitUserManagement();
     }
 
-    /**
-     * Determines the authorizable root paths (as Jackrabbit/Oak stores authorizables inside the repo below a dedicated root path)
-     * @param session
-     * @throws RepositoryException
-     */
-    private synchronized void determineAuthorizableRootPaths(Session session) throws RepositoryException {
-        JackrabbitSession jrSession = (JackrabbitSession)session;
-        UserManager userMgr = jrSession.getUserManager();
-        // userMgr.autoSave(false) is not supported by Oak
-        String testAuthorizableId = UUID.randomUUID().toString();
-        Group group = userMgr.createGroup(new SimplePrincipal(testAuthorizableId), "intermediate");
-        groupsRootPath = Text.getRelativeParent(group.getPath(), 2);
-        group.remove();
-        User user = userMgr.createUser(testAuthorizableId, "test", new SimplePrincipal(testAuthorizableId), "intermediate");
-        usersRootPath = Text.getRelativeParent(user.getPath(), 2);
-        user.remove();
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -202,18 +182,22 @@ public class JackrabbitACLManagement implements ACLManagement {
         return node.getDepth() == 0;
     }
 
-    private boolean areAuthorizablesAllowedBelowPath(Session session, String nodePath) throws RepositoryException {
-        if (usersRootPath == null || groupsRootPath == null) {
-            determineAuthorizableRootPaths(session);
-        }
-        return nodePath.startsWith(usersRootPath) || nodePath.startsWith(groupsRootPath);
+    private boolean isAuthorizable(Node node) throws RepositoryException {
+        return userManagement.isAuthorizableNodeType(node.getPrimaryNodeType().getName());
+    }
+
+    private boolean isAuthorizableFolder(Node node) throws RepositoryException {
+        return node.isNodeType(NT_REP_AUTHORIZABLE_FOLDER);
+    }
+
+    private boolean areAuthorizablesAllowed(Node node) throws RepositoryException {
+        return isAuthorizableFolder(node) || isAuthorizable(node);
     }
 
     @Override
     public @NotNull Map<String, List<? extends AccessControlPolicy>> getPrincipalAcls(Node node) throws RepositoryException {
         // first do a quick check if path may contain principal ACLs at all before triggering expensive traversal
-        if (!areAuthorizablesAllowedBelowPath(node.getSession(), node.getPath())) {
-            // TODO: Oak does not allow principal based authorizables everywhere, so we may restrict further
+        if (!areAuthorizablesAllowed(node)) {
             return Collections.emptyMap();
         }
         JackrabbitSession jrSession = (JackrabbitSession)node.getSession();
@@ -260,13 +244,12 @@ public class JackrabbitACLManagement implements ACLManagement {
     }
 
     private void findPrincipalsRecursively(UserManager userMgr, Node node, Consumer<Principal> principalConsumer) throws RepositoryException {
-        // TODO: check if the additional check with UserManagement isAuthorizableNodeType really speeds things up...
-        if (userManagement.isAuthorizableNodeType(node.getPrimaryNodeType().getName())) {
+        if (isAuthorizable(node)) {
             Authorizable authorizable = userMgr.getAuthorizableByPath(node.getPath());
             if (authorizable != null) {
                 principalConsumer.accept(authorizable.getPrincipal());
             }
-        } else {
+        } else if (isAuthorizableFolder(node)) {
             for (Node child : JcrUtils.in(((Iterator<Node>)node.getNodes()))) {
                 findPrincipalsRecursively(userMgr, child, principalConsumer);
             }