jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r801594 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/security/authorization/ main/java/org/apache/jackrabbit/core/security/authorization/acl/ main/java/org/apache/jackrabbit/core/security/authorization/pr...
Date Thu, 06 Aug 2009 10:39:28 GMT
Author: angela
Date: Thu Aug  6 10:39:23 2009
New Revision: 801594

URL: http://svn.apache.org/viewvc?rev=801594&view=rev
Log:
 JCR-1588: JSR 283: Access Control

- move common acl code to abstract base class
- let group principals have deny entries again 
- add more tests

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java?rev=801594&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
Thu Aug  6 10:39:23 2009
@@ -0,0 +1,99 @@
+/*
+ * 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.core.security.authorization;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+
+import javax.jcr.security.Privilege;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFactory;
+import javax.jcr.Value;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * <code>AbstractACLTemplate</code>...
+ */
+public abstract class AbstractACLTemplate implements JackrabbitAccessControlList, AccessControlConstants
{
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(AbstractACLTemplate.class);
+
+    /**
+     * Path of the node this ACL template has been created for.
+     */
+    protected final String path;
+
+    /**
+     * The value factory
+     */
+    protected final ValueFactory valueFactory;
+
+    protected AbstractACLTemplate(String path, ValueFactory valueFactory) {
+        this.path = path;
+        this.valueFactory = valueFactory;
+    }
+
+    /**
+     * Validates the given parameters to create a new ACE and throws an
+     * <code>AccessControlException</code> if any of them is invalid. Otherwise
+     * this method returns silently.
+     *
+     * @param principal The principal to create the ACE for.
+     * @param privileges The privileges to be granted/denied by the ACE.
+     * @param isAllow Defines if the priveleges are allowed or denied.
+     * @param restrictions The additional restrictions.
+     * @throws AccessControlException If any of the given params is invalid.
+     */
+    protected abstract void checkValidEntry(Principal principal,
+                                            Privilege[] privileges,
+                                            boolean isAllow,
+                                            Map<String, Value> restrictions) throws
AccessControlException;
+
+    //--------------------------------------< JackrabbitAccessControlPolicy >---
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy#getPath()
+     */
+    public String getPath() {
+        return path;
+    }
+
+    //----------------------------------------< JackrabbitAccessControlList >---
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal,
Privilege[], boolean)
+     */
+    public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow)
+            throws AccessControlException, RepositoryException {
+        return addEntry(principal, privileges, isAllow, Collections.EMPTY_MAP);
+    }
+
+
+    //--------------------------------------------------< AccessControlList >---
+    /**
+     * @see javax.jcr.security.AccessControlList#addAccessControlEntry(java.security.Principal
, javax.jcr.security.Privilege[])
+     */
+    public boolean addAccessControlEntry(Principal principal, Privilege[] privileges)
+            throws AccessControlException, RepositoryException {
+        return addEntry(principal, privileges, true, Collections.EMPTY_MAP);
+    }
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java?rev=801594&r1=801593&r2=801594&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
Thu Aug  6 10:39:23 2009
@@ -26,6 +26,7 @@
 import org.apache.jackrabbit.core.security.authorization.AccessControlEntryImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,7 +41,6 @@
 import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.Privilege;
 import java.security.Principal;
-import java.security.acl.Group;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -54,16 +54,11 @@
  * {@link javax.jcr.security.AccessControlManager#setPolicy(String, javax.jcr.security.AccessControlPolicy)
reapplied}
  * to the <code>AccessControlManager</code> and the changes are saved.
  */
-class ACLTemplate implements JackrabbitAccessControlList {
+class ACLTemplate extends AbstractACLTemplate {
 
     private static final Logger log = LoggerFactory.getLogger(ACLTemplate.class);
 
     /**
-     * Path of the node this ACL template has been created for.
-     */
-    private final String path;
-
-    /**
      * Map containing the entries of this ACL Template using the principal
      * name as key. The value represents a List containing maximal one grant
      * and one deny ACE per principal.
@@ -81,11 +76,6 @@
     private final PrivilegeRegistry privilegeRegistry;
 
     /**
-     * The value factory
-     */
-    private final ValueFactory valueFactory;
-
-    /**
      * Construct a new empty {@link ACLTemplate}.
      *
      * @param path
@@ -94,10 +84,10 @@
      */
     ACLTemplate(String path, PrincipalManager principalMgr, 
                 PrivilegeRegistry privilegeRegistry, ValueFactory valueFactory) {
-        this.path = path;
+        super(path, valueFactory);
+
         this.principalMgr = principalMgr;
         this.privilegeRegistry = privilegeRegistry;
-        this.valueFactory = valueFactory;
     }
 
     /**
@@ -109,13 +99,12 @@
      * @throws RepositoryException
      */
     ACLTemplate(NodeImpl aclNode, PrivilegeRegistry privilegeRegistry) throws RepositoryException
{
+        super((aclNode != null) ? aclNode.getParent().getPath() : null, (aclNode != null)
? aclNode.getSession().getValueFactory() : null);
         if (aclNode == null || !aclNode.isNodeType(AccessControlConstants.NT_REP_ACL)) {
             throw new IllegalArgumentException("Node must be of type 'rep:ACL'");
         }
         SessionImpl sImpl = (SessionImpl) aclNode.getSession();
-        path = aclNode.getParent().getPath();
         principalMgr = sImpl.getPrincipalManager();
-        valueFactory = sImpl.getValueFactory();
         
         this.privilegeRegistry = privilegeRegistry;
 
@@ -288,22 +277,21 @@
         }
     }
 
+    //------------------------------------------------< AbstractACLTemplate >---
     /**
-     *
-     * @param principal
-     * @param privileges
-     * @param isAllow
-     * @throws AccessControlException
+     * @see AbstractACLTemplate#checkValidEntry(java.security.Principal, javax.jcr.security.Privilege[],
boolean, java.util.Map) 
      */
-    private void checkValidEntry(Principal principal, Privilege[] privileges, boolean isAllow)
throws AccessControlException {
+    protected void checkValidEntry(Principal principal, Privilege[] privileges,
+                                 boolean isAllow, Map<String, Value> restrictions)
+            throws AccessControlException {
+        if (restrictions != null && !restrictions.isEmpty()) {
+            throw new AccessControlException("This AccessControlList does not allow for additional
restrictions.");
+        }
+
         // validate principal
         if (!principalMgr.hasPrincipal(principal.getName())) {
             throw new AccessControlException("Principal " + principal.getName() + " does
not exist.");
         }
-        // additional validation: a group may not have 'denied' permissions
-        if (!isAllow && principal instanceof Group) {
-            throw new AccessControlException("For group principals permissions can only be
added but not denied.");
-        }
     }
 
     //--------------------------------------------------< AccessControlList >---
@@ -316,14 +304,6 @@
     }
 
     /**
-     * @see javax.jcr.security.AccessControlList#addAccessControlEntry(Principal, Privilege[])
-     */
-    public boolean addAccessControlEntry(Principal principal, Privilege[] privileges)
-            throws AccessControlException, RepositoryException {
-        return addEntry(principal, privileges, true, Collections.EMPTY_MAP);
-    }
-
-    /**
      * @see javax.jcr.security.AccessControlList#removeAccessControlEntry(AccessControlEntry)
      */
     public synchronized void removeAccessControlEntry(AccessControlEntry ace)
@@ -341,14 +321,7 @@
         }
     }
 
-    //-----------------------------------------------------< JackrabbitAccessControlList
>---
-    /**
-     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#getPath()
-     */
-    public String getPath() {
-        return path;
-    }
-
+    //----------------------------------------< JackrabbitAccessControlList >---
     /**
      * Returns an empty String array.
      *
@@ -383,24 +356,12 @@
     }
 
     /**
-     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal,
Privilege[], boolean)
-     */
-    public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow)
-            throws AccessControlException, RepositoryException {
-        return addEntry(principal, privileges, isAllow, null);
-    }
-
-    /**
      * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal,
Privilege[], boolean, Map)
      */
     public boolean addEntry(Principal principal, Privilege[] privileges,
                             boolean isAllow, Map<String, Value> restrictions)
             throws AccessControlException, RepositoryException {
-        if (restrictions != null && !restrictions.isEmpty()) {
-            throw new AccessControlException("This AccessControlList does not allow for additional
restrictions.");
-        }
-
-        checkValidEntry(principal, privileges, isAllow);
+        checkValidEntry(principal, privileges, isAllow, restrictions);
         Entry ace = new Entry(principal, privileges, isAllow, valueFactory);
         return internalAdd(ace);
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java?rev=801594&r1=801593&r2=801594&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
Thu Aug  6 10:39:23 2009
@@ -19,8 +19,8 @@
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
 import org.apache.jackrabbit.core.security.authorization.AccessControlEntryImpl;
+import org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.slf4j.Logger;
@@ -38,7 +38,6 @@
 import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.Privilege;
 import java.security.Principal;
-import java.security.acl.Group;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -53,7 +52,7 @@
  * {@link javax.jcr.security.AccessControlManager#setPolicy(String, javax.jcr.security.AccessControlPolicy)
reapplied}
  * to the <code>AccessControlManager</code> and the changes are saved.
  */
-class ACLTemplate implements JackrabbitAccessControlList, AccessControlConstants {
+class ACLTemplate extends AbstractACLTemplate {
 
     private static Logger log = LoggerFactory.getLogger(ACLTemplate.class);
 
@@ -70,8 +69,6 @@
     static final Name P_GLOB = NF.create(Name.NS_REP_URI, "glob");
 
     private final Principal principal;
-    private final String path;
-    private final ValueFactory valueFactory;
 
     private final List entries = new ArrayList();
 
@@ -89,9 +86,9 @@
     private ACLTemplate(Principal principal, String path, NodeImpl acNode,
                         NamePathResolver resolver, ValueFactory vf)
             throws RepositoryException {
+        super(path, vf);
+
         this.principal = principal;
-        this.path = path;
-        this.valueFactory = vf;
 
         jcrNodePathName = resolver.getJCRName(P_NODE_PATH);
         jcrGlobName = resolver.getJCRName(P_GLOB);
@@ -134,17 +131,7 @@
 
     AccessControlEntry createEntry(Principal princ, Privilege[] privileges,
                                    boolean allow, Map<String, Value> restrictions)
throws RepositoryException {
-        if (!principal.equals(princ)) {
-            throw new AccessControlException("Invalid principal. Expected: " + principal);
-        }
-        if (!allow && principal instanceof Group) {
-            throw new AccessControlException("For group principals permissions can only be
added but not denied.");
-        }
-
-        Set rNames = restrictions.keySet();
-        if (!rNames.contains(jcrNodePathName)) {
-            throw new AccessControlException("Missing mandatory restriction: " + jcrNodePathName);
-        }
+        checkValidEntry(princ, privileges, allow, restrictions);
 
         // make sure the nodePath restriction is of type PATH
         Value v = restrictions.get(jcrNodePathName);
@@ -161,14 +148,24 @@
         return new Entry(princ, privileges, allow, restrictions);
     }
 
-    //-----------------------------------------------------< JackrabbitAccessControlList
>---
+    //------------------------------------------------< AbstractACLTemplate >---
     /**
-     * @see JackrabbitAccessControlList#getPath()
+     * @see AbstractACLTemplate#checkValidEntry(java.security.Principal, javax.jcr.security.Privilege[],
boolean, java.util.Map)
      */
-    public String getPath() {
-        return path;
-    }
+    protected void checkValidEntry(Principal principal, Privilege[] privileges,
+                                 boolean isAllow, Map<String, Value> restrictions)
+            throws AccessControlException {
+        if (!this.principal.equals(principal)) {
+            throw new AccessControlException("Invalid principal. Expected: " + principal);
+        }
 
+        Set rNames = restrictions.keySet();
+        if (!rNames.contains(jcrNodePathName)) {
+            throw new AccessControlException("Missing mandatory restriction: " + jcrNodePathName);
+        }
+    }
+    
+    //----------------------------------------< JackrabbitAccessControlList >---
     /**
      * @see JackrabbitAccessControlList#getRestrictionNames()
      */
@@ -204,14 +201,6 @@
     }
 
     /**
-     * @see JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean)
-     */
-    public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow)
-            throws AccessControlException, RepositoryException {
-        return addEntry(principal, privileges, isAllow, null);
-    }
-
-    /**
      * Known restrictions are:
      * <pre>
      *   rep:nodePath  (mandatory) value-type: PATH
@@ -250,15 +239,6 @@
     }
 
     /**
-     * @see javax.jcr.security.AccessControlList#addAccessControlEntry(Principal, Privilege[])
-     */
-    public boolean addAccessControlEntry(Principal principal,
-                                         Privilege[] privileges)
-            throws AccessControlException, RepositoryException {
-        return addEntry(principal, privileges, true, Collections.EMPTY_MAP);
-    }
-
-    /**
      * @see javax.jcr.security.AccessControlList#removeAccessControlEntry(AccessControlEntry)
      */
     public void removeAccessControlEntry(AccessControlEntry ace)

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java?rev=801594&r1=801593&r2=801594&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java
Thu Aug  6 10:39:23 2009
@@ -51,7 +51,7 @@
 
     protected static final long DEFAULT_WAIT_TIMEOUT = 5000;
 
-    private Group testGroup;
+    protected Group testGroup;
 
     protected String path;
     protected String childNPath;
@@ -62,7 +62,6 @@
 
     // TODO: test AC for moved node
     // TODO: test AC for moved AC-controlled node
-    // TODO: test if combination of group and user permissions are properly evaluated
 
     protected void setUp() throws Exception {
         super.setUp();
@@ -795,6 +794,37 @@
         assertFalse(getTestSession().hasPermission(path, actions));
         assertFalse(testAcMgr.hasPrivileges(path, privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES)));
     }
+    
+    public void testInheritanceAndMixedUserGroupPermissions() throws RepositoryException,
NotExecutableException {
+        Group testGroup = getTestGroup();
+        AccessControlManager testAcMgr = getTestACManager();
+        /*
+         precondition:
+         testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+
+        Privilege[] privileges = privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES);
+
+        /* give MODIFY_PROPERTIES privilege for testGroup at 'path' */
+        givePrivileges(path, testGroup.getPrincipal(), privileges, getRestrictions(superuser,
path));
+
+        /* withdraw MODIFY_PROPERTIES for the user at 'path' */
+        withdrawPrivileges(path, testUser.getPrincipal(), privileges, getRestrictions(superuser,
path));
+
+        /*
+         since user-permissions overrule the group permissions, testuser must
+         not have set_property action / modify_properties privilege.
+         */
+        assertFalse(testAcMgr.hasPrivileges(path, privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES)));
+
+        /*
+         give MODIFY_PROPERTIES privilege for everyone at 'childNPath'
+         -> user-privileges still overrule group privs
+         */
+        givePrivileges(childNPath, testGroup.getPrincipal(), privileges, getRestrictions(superuser,
path));
+        assertFalse(testAcMgr.hasPrivileges(childNPath, privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES)));
+    }
 
     public void testNewNodes() throws RepositoryException, NotExecutableException {
         AccessControlManager testAcMgr = getTestACManager();

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java?rev=801594&r1=801593&r2=801594&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java
Thu Aug  6 10:39:23 2009
@@ -27,7 +27,6 @@
 
 import javax.jcr.RepositoryException;
 import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.AccessControlException;
 import javax.jcr.security.Privilege;
 import java.security.Principal;
 import java.security.acl.Group;
@@ -153,12 +152,7 @@
         assertTrue(pt.addAccessControlEntry(grPrincipal, privs));
 
         // adding deny-entry must succeed
-        try {
-            pt.addEntry(grPrincipal, privs, false, null);
-            fail("Adding DENY-ace for a group principal should fail.");
-        } catch (AccessControlException e) {
-            // success
-        }
+        pt.addEntry(grPrincipal, privs, false, null);
     }
 
     public void testRevokeEffect() throws RepositoryException, NotExecutableException {

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java?rev=801594&r1=801593&r2=801594&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java
Thu Aug  6 10:39:23 2009
@@ -169,4 +169,48 @@
         it = acMgr.getApplicablePolicies(childNPath);
         assertTrue(it.hasNext());
     }
+
+    public void testInheritance2() throws RepositoryException, NotExecutableException {
+        Session testSession = getTestSession();
+        AccessControlManager testAcMgr = getTestACManager();
+
+        /*
+          precondition:
+          testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+        checkReadOnly(childNPath);
+
+        // give jcr:write privilege on 'path' and withdraw them on 'childNPath'
+        Privilege[] privileges = privilegesFromNames(new String[] {Privilege.JCR_WRITE});
+        givePrivileges(path, privileges, getRestrictions(superuser, path));
+        withdrawPrivileges(childNPath, privileges, getRestrictions(superuser, path));
+
+        /*
+        since evaluation respects inheritance through the node
+        hierarchy, the jcr:write privilege must not be granted at childNPath
+        */
+        assertFalse(testAcMgr.hasPrivileges(childNPath, privileges));
+
+        /*
+         ... same for permissions at 'childNPath'
+         */
+        String actions = Session.ACTION_SET_PROPERTY + "," + Session.ACTION_REMOVE + ","
+ Session.ACTION_ADD_NODE;
+
+        String nonExistingItemPath = childNPath + "/anyItem";
+        assertFalse(testSession.hasPermission(nonExistingItemPath, actions));
+
+        // yet another level in the hierarchy
+        Node grandChild = superuser.getNode(childNPath).addNode(nodeName3);
+        superuser.save();
+        String gcPath = grandChild.getPath();
+
+        // grant write privilege again
+        givePrivileges(gcPath, privileges, getRestrictions(superuser, path));
+        assertTrue(testAcMgr.hasPrivileges(gcPath, privileges));
+        assertTrue(testSession.hasPermission(gcPath + "/anyProp", Session.ACTION_SET_PROPERTY));
+        // however: removing the grand-child nodes must not be allowed as
+        // remove_child_node privilege is missing on the direct ancestor.
+        assertFalse(testSession.hasPermission(gcPath, Session.ACTION_REMOVE));
+    }
 }
\ No newline at end of file



Mime
View raw message