You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/04/17 18:27:20 UTC

svn commit: r649172 [2/2] - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/ main/java/org/apache/jackrabbit/core/observation/ main/java/org/apache/jackrabbit/core/query/lucene/ main/java/org/apache/jackrabbit/core/securi...

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java Thu Apr 17 09:27:09 2008
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.core.security.authorization.combined;
 
-import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.security.SecurityConstants;
@@ -34,11 +33,11 @@
 import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.ItemNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Node;
@@ -63,18 +62,30 @@
     private static Logger log = LoggerFactory.getLogger(CombinedProvider.class);
 
     // TODO: add means to show effective-policy to a user.
-    // TODO: TOBEFIXED add means to create user-based ACLs (currently editor is not exposed in the API)
     // TODO: TOBEFIXED proper evaluation of permissions respecting resource-based ACLs.
     // TODO: TOBEFIXED assert proper evaluation order of group/non-group principal-ACLs
 
     private CombinedEditor editor;
     private NodeImpl acRoot;
 
-    private String policyName;
-
     public CombinedProvider() {
         super("Combined AC policy", "Policy evaluating user-based and resource-based ACLs.");
     }
+
+    //--------------------------------------< AbstractAccessControlProvider >---
+    /**
+     * @see AbstractAccessControlProvider#isAcItem(Path)
+     */
+    protected boolean isAcItem(Path absPath) throws RepositoryException {
+        Path.Element[] elems = absPath.getElements();
+        for (int i = 0; i < elems.length; i++) {
+            if (N_POLICY.equals(elems[i].getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     //----------------------------------------------< AccessControlProvider >---
     /**
      * @see AccessControlProvider#init(javax.jcr.Session, java.util.Map)
@@ -92,8 +103,6 @@
             acRoot = root.addNode(N_ACCESSCONTROL, NT_REP_ACCESS_CONTROL, null);
         }
 
-        policyName = session.getJCRName(AccessControlConstants.N_POLICY);
-
         editor = new CombinedEditor(session, resolver, resolver.getQPath(acRoot.getPath()));
         try {
             log.info("Install initial ACL:...");
@@ -131,9 +140,10 @@
     }
 
     /**
-     * @see AccessControlProvider#getAccessControlEntries(org.apache.jackrabbit.core.NodeId)
+     * @see AccessControlProvider#getAccessControlEntries(Path)
+     * @param absPath
      */
-    public AccessControlEntry[] getAccessControlEntries(NodeId nodeId) throws RepositoryException {
+    public AccessControlEntry[] getAccessControlEntries(Path absPath) throws RepositoryException {
         checkInitialized();
         // TODO: TOBEFIXED
         return new AccessControlEntry[0];
@@ -162,16 +172,29 @@
     /**
      * @see AccessControlProvider#compilePermissions(Set)
      */
-    public CompiledPermissions compilePermissions(Set principals) throws ItemNotFoundException, RepositoryException {
+    public CompiledPermissions compilePermissions(Set principals) throws RepositoryException {
         checkInitialized();
         if (isAdminOrSystem(principals)) {
             return getAdminPermissions();
+        } else if (isReadOnly(principals)) {
+            return getReadOnlyPermissions();
         } else {
-            // TODO: TOBEFIXED include the resource-based ACLs!
             return new CompiledPermissionImpl(principals);
         }
     }
 
+    /**
+     * @see AccessControlProvider#canAccessRoot(Set)
+     */
+    public boolean canAccessRoot(Set principals) throws RepositoryException {
+        checkInitialized();
+        if (isAdminOrSystem(principals)) {
+            return true;
+        } else {
+            return new CompiledPermissionImpl(principals, false).grants(PathFactoryImpl.getInstance().getRootPath(), Permission.READ);
+        }
+    }
+
     //-----------------------------------------------------< CompiledPolicy >---
     /**
      *
@@ -188,18 +211,28 @@
          * @throws RepositoryException
          */
         private CompiledPermissionImpl(Set principals) throws RepositoryException {
+            this(principals, true);
+        }
+
+        /**
+         * @param principals
+         * @throws RepositoryException
+         */
+        private CompiledPermissionImpl(Set principals, boolean listenToEvents) throws RepositoryException {
 
             this.principals = principals;
             acPaths = new HashSet(principals.size());
             entries = reload();
 
             // TODO: describe
-            int events = Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED |
-                    Event.PROPERTY_REMOVED | Event.NODE_ADDED | Event.NODE_REMOVED;
-            String[] ntNames = new String[] {
-                    session.getJCRName(NT_REP_ACE)
-            };
-            observationMgr.addEventListener(this, events, acRoot.getPath(), true, null, ntNames, false);
+            if (listenToEvents) {
+                int events = Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED |
+                        Event.PROPERTY_REMOVED | Event.NODE_ADDED | Event.NODE_REMOVED;
+                String[] ntNames = new String[] {
+                        session.getJCRName(NT_REP_ACE)
+                };
+                observationMgr.addEventListener(this, events, acRoot.getPath(), true, null, ntNames, false);
+            }
         }
 
         //------------------------------------< AbstractCompiledPermissions >---
@@ -211,19 +244,12 @@
                 throw new RepositoryException("Absolute path expected.");
             }
 
-            String jcrPath = session.getJCRPath(absPath);
-            boolean isAclItem = false;
             /* Test if the given path points to a Node (or an existing or non
              * existing direct decendant of an existing Node) that stores
              * AC-information
              */
-            String[] segments = Text.explode(jcrPath, '/', false);
-            if (segments.length > 0) {
-                for (int i = segments.length - 1; i >= 0 && !isAclItem; i--) {
-                    isAclItem = policyName.equals(segments[i]);
-                }
-            }
-
+            boolean isAclItem = isAcItem(absPath);
+            String jcrPath = session.getJCRPath(absPath);            
             int permissions;
             if (session.itemExists(jcrPath)) {
                 permissions = entries.getPermissions(session.getItem(jcrPath), isAclItem);
@@ -255,7 +281,7 @@
             try {
                 observationMgr.removeEventListener(this);
             } catch (RepositoryException e) {
-                log.error("Internal error: ", e.getMessage());
+                log.debug("Unable to unregister listener: ", e.getMessage());
             }
             super.close();
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java Thu Apr 17 09:27:09 2008
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.security.authorization.PolicyEntry;
 import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -69,6 +70,8 @@
     public boolean setEntry(PolicyEntry entry) throws AccessControlException, RepositoryException {
         if (entry instanceof PolicyEntryImpl &&
             principal.equals(entry.getPrincipal())) {
+            // make sure valid privileges are provided.
+            PrivilegeRegistry.getBits(entry.getPrivileges());
             return internalAddEntry((PolicyEntryImpl) entry);
         } else {
             throw new AccessControlException("Invalid entry.");
@@ -76,7 +79,14 @@
     }
 
     public boolean removeEntry(PolicyEntry entry) throws AccessControlException, RepositoryException {
-        return entries.remove(entry);
+        if (entry instanceof PolicyEntryImpl &&
+            principal.equals(entry.getPrincipal())) {
+            // make sure valid privileges are provided.
+            PrivilegeRegistry.getBits(entry.getPrivileges());
+            return entries.remove(entry);
+        } else {
+            throw new AccessControlException("Invalid entry.");
+        }
     }
 
     //------------------------------------------------< AccessControlPolicy >---

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java Thu Apr 17 09:27:09 2008
@@ -75,7 +75,7 @@
      * @throws RepositoryException if an error accessing the repository occurs.
      */
     public DefaultPrincipalProvider(Session securitySession,
-                             UserManagerImpl userManager) throws RepositoryException {
+                                    UserManagerImpl userManager) throws RepositoryException {
 
         this.userManager = userManager;
         everyonePrincipal = EveryonePrincipal.getInstance();

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java Thu Apr 17 09:27:09 2008
@@ -157,6 +157,10 @@
         return internalIsGranted(parentPath, permissions);
     }
 
+    public boolean canRead(Path itemPath) throws ItemNotFoundException, RepositoryException {
+        return true;
+    }
+
     private boolean internalIsGranted(Path absPath, int permissions) throws ItemNotFoundException, RepositoryException {
         if (!absPath.isAbsolute()) {
             throw new RepositoryException("Absolute path expected");

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Thu Apr 17 09:27:09 2008
@@ -78,6 +78,17 @@
               "Policy that defines the general access control rules for the security workspace.");
     }
 
+    //--------------------------------------< AbstractAccessControlProvider >---
+    /**
+     * Always returns false, since this ac provider does not use content stored
+     * in items to evaluate AC information.
+     * 
+     * @see AbstractAccessControlProvider#isAcItem(Path)
+     */
+    protected boolean isAcItem(Path absPath) throws RepositoryException {
+        return false;
+    }
+
     //----------------------------------------------< AccessControlProvider >---
     /**
      * @see AccessControlProvider#init(Session, Map)
@@ -110,7 +121,7 @@
          }
      }
 
-    public CompiledPermissions compilePermissions(Set principals) throws ItemNotFoundException, RepositoryException {
+    public CompiledPermissions compilePermissions(Set principals) throws RepositoryException {
         checkInitialized();
         if (isAdminOrSystem(principals)) {
             return getAdminPermissions();
@@ -127,6 +138,11 @@
         }
     }
 
+    public boolean canAccessRoot(Set principals) throws RepositoryException {
+        checkInitialized();
+        return true;
+    }
+
     //------------------------------------------------------------< private >---
 
     private ItemBasedPrincipal getUserPrincipal(Set principals) {
@@ -387,10 +403,15 @@
                 // read is always granted
                 return true;
             }
-            // TODO: additional simple checks.... (last accessed... etc)
-
-            // finally retrieve from cache (or build)
+            // otherwise: retrieve from cache (or build)
             return super.grants(absPath, permissions);
+        }
+
+        /**
+         * @see CompiledPermissions#canReadAll()
+         */
+        public boolean canReadAll() throws RepositoryException {
+            return true;
         }
 
         //--------------------------------------------------< EventListener >---

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java?rev=649172&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java Thu Apr 17 09:27:09 2008
@@ -0,0 +1,511 @@
+/*
+ * 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.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.TestPrincipal;
+import org.apache.jackrabbit.core.security.jsr283.security.AbstractAccessControlTest;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.nodetype.ConstraintViolationException;
+import java.security.Principal;
+
+/**
+ * <code>AbstractEvaluationTest</code>...
+ */
+public abstract class AbstractEvaluationTest extends AbstractAccessControlTest {
+
+    private static Logger log = LoggerFactory.getLogger(AbstractEvaluationTest.class);
+
+    protected Credentials creds;
+    protected User testUser;
+    protected SessionImpl testSession;
+    protected AccessControlManager testAcMgr;
+
+    protected String path;
+    protected String childNPath;
+    protected String childNPath2;
+    protected String childPPath;
+    protected String childchildPPath;
+    protected String siblingPath;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        UserManager uMgr = getUserManager(superuser);
+        Principal princ = new TestPrincipal("anyUser");
+        creds = new SimpleCredentials("anyUser", "anyUser".toCharArray());
+
+        Authorizable a = uMgr.getAuthorizable(princ);
+        if (a == null) {
+            testUser = uMgr.createUser("anyUser", creds, princ);
+        } else if (a.isGroup()) {
+            throw new NotExecutableException();
+        } else {
+            testUser = (User) a;
+        }
+
+        // TODO: remove cast once 283 is released.
+        testSession = (SessionImpl) helper.getRepository().login(creds);
+        testAcMgr = getAccessControlManager(testSession);
+
+        // create some nodes below the test root in order to apply ac-stuff
+        Node node = testRootNode.addNode(nodeName1, testNodeType);
+        Node cn1 = node.addNode(nodeName2, testNodeType);
+        Property cp1 = node.setProperty(propertyName1, "anyValue");
+        Node cn2 = node.addNode(nodeName3, testNodeType);
+
+        Property ccp1 = cn1.setProperty(propertyName1, "childNodeProperty");
+
+        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
+        superuser.save();
+
+        path = node.getPath();
+        childNPath = cn1.getPath();
+        childNPath2 = cn2.getPath();
+        childPPath = cp1.getPath();
+        childchildPPath = ccp1.getPath();
+        siblingPath = n2.getPath();
+    }
+
+    protected void tearDown() throws Exception {
+        if (testSession != null && testSession.isLive()) {
+            testSession.logout();
+        }
+        // make sure all ac info is removed
+        clearACInfo();
+        // remove the test user again.
+        if (testUser != null) {
+            testUser.remove();
+        }
+        super.tearDown();
+    }
+
+    private static UserManager getUserManager(Session session) throws NotExecutableException {
+        if (!(session instanceof JackrabbitSession)) {
+            throw new NotExecutableException();
+        }
+
+        try {
+            return ((JackrabbitSession) session).getUserManager();
+        } catch (RepositoryException e) {
+            throw new NotExecutableException();
+        }
+    }
+
+    protected abstract void clearACInfo();
+
+    protected abstract PolicyTemplate getPolicyTemplate(AccessControlManager acM, String path) throws RepositoryException, AccessDeniedException, NotExecutableException;
+
+    protected abstract PolicyEntry createEntry(Principal principal, int privileges, boolean isAllow, String[] restrictions);
+
+    protected abstract String[] getRestrictions(String path);
+
+    protected PolicyTemplate givePrivileges(String nPath, int privileges, String[] restrictions) throws NotExecutableException, RepositoryException {
+        PolicyTemplate tmpl = getPolicyTemplate(acMgr, nPath);
+        tmpl.setEntry(createEntry(testUser.getPrincipal(), privileges, true, restrictions));
+        acMgr.setPolicy(tmpl.getPath(), tmpl);
+        superuser.save();
+        return tmpl;
+    }
+
+    protected PolicyTemplate withdrawPrivileges(String nPath, int privileges, String[] restrictions) throws NotExecutableException, RepositoryException {
+        PolicyTemplate tmpl = getPolicyTemplate(acMgr, nPath);
+        tmpl.setEntry(createEntry(testUser.getPrincipal(), privileges, false, restrictions));
+        acMgr.setPolicy(tmpl.getPath(), tmpl);
+        superuser.save();
+        return tmpl;
+    }
+
+    protected void checkReadOnly(String path) throws RepositoryException {
+        Privilege[] privs = testAcMgr.getPrivileges(path);
+        assertTrue(privs.length == 1);
+        assertEquals(PrivilegeRegistry.READ_PRIVILEGE, privs[0]);
+    }
+
+    public void testGrantedPermissions() throws RepositoryException, AccessDeniedException, NotExecutableException {
+        /* precondition:
+           testuser must have READ-only permission on test-node and below
+         */
+        checkReadOnly(path);
+
+        // give 'testUser' ADD_CHILD_NODES|MODIFY_PROPERTIES privileges at 'path'
+        givePrivileges(path, PrivilegeRegistry.ADD_CHILD_NODES |
+                PrivilegeRegistry.MODIFY_PROPERTIES, getRestrictions(path));
+        /*
+         testuser must now have
+         - ADD_NODE permission for child node
+         - SET_PROPERTY permission for child props
+         - REMOVE permission for child-props
+         - READ-only permission for the node at 'path'
+
+         testuser must not have
+         - REMOVE permission for child node
+        */
+        String nonExChildPath = path + "/anyItem";
+        assertTrue(testSession.hasPermission(nonExChildPath, "read,add_node,set_property"));
+        assertFalse(testSession.hasPermission(nonExChildPath, "remove"));
+
+        Node testN = testSession.getNode(path);
+
+        // must be allowed to add child node
+        testN.addNode(nodeName3, testNodeType);
+        testSession.save();
+
+        // must be allowed to remove child-property
+        testSession.getProperty(childPPath).remove();
+        testSession.save();
+
+        // must be allowed to set child property again
+        testN.setProperty(Text.getName(childPPath), "othervalue");
+        testSession.save();
+
+        // must not be allowed to remove child nodes
+        try {
+            testSession.getNode(childNPath).remove();
+            testSession.save();
+            fail("test-user is not allowed to remove a node below " + path);
+        } catch (AccessDeniedException e) {
+            // success
+        }
+
+        // must have read-only access on 'testN' and it's sibling
+        assertTrue(testSession.hasPermission(path, "read"));
+        assertFalse(testSession.hasPermission(path, "add_node,set_property,remove"));
+        checkReadOnly(siblingPath);
+    }
+
+    public void testDeniedPermission() throws RepositoryException, NotExecutableException, InterruptedException {
+         /* precondition:
+           testuser must have READ-only permission on test-node and below
+         */
+        checkReadOnly(path);
+
+        // withdraw READ privilege to 'testUser' at 'path'
+        withdrawPrivileges(childNPath, PrivilegeRegistry.READ, getRestrictions(childNPath));
+        /*
+         testuser must now have
+         - READ-only permission for the child-props of path
+
+         testuser must not have
+         - any permission on child-node and all its subtree
+        */
+
+        // must still have read-access to path, ...
+        assertTrue(testSession.hasPermission(path, "read"));
+        Node n = testSession.getNode(path);
+        // ... siblings of childN
+        testSession.getNode(childNPath2);
+        // ... and props of path
+        assertTrue(n.getProperties().hasNext());
+
+        /*
+        testSession must not have access to 'childNPath'
+        */
+        assertFalse(testSession.itemExists(childNPath));
+        try {
+            Node testN = testSession.getNode(childNPath);
+            fail("Read access has been denied -> cannot retrieve child node.");
+        } catch (PathNotFoundException e) {
+            // ok.
+        }
+        /*
+        -> must not have access to subtree below 'childNPath'
+        */
+        assertFalse(testSession.itemExists(childchildPPath));
+        try {
+            testSession.getItem(childchildPPath);
+            fail("Read access has been denied -> cannot retrieve prop below child node.");
+        } catch (PathNotFoundException e) {
+            // ok.
+        }
+    }
+
+    public void testAccessControlRead() throws NotExecutableException, RepositoryException {
+        checkReadOnly(path);
+
+        // re-grant READ in order to have an ACL-node
+        PolicyTemplate tmpl = givePrivileges(path, PrivilegeRegistry.READ, getRestrictions(path));
+        // make sure the 'rep:policy' node has been created.
+        assertTrue(superuser.itemExists(tmpl.getPath() + "/rep:policy"));
+
+        /*
+         Testuser must still have READ-only access only and must not be
+         allowed to view the acl-node that has been created.
+        */
+        assertFalse(testAcMgr.hasPrivileges(path, new Privilege[] {
+                PrivilegeRegistry.READ_AC_PRIVILEGE
+        }));
+        assertFalse(testSession.itemExists(path + "/rep:policy"));
+
+        Node n = testSession.getNode(tmpl.getPath());
+        assertFalse(n.hasNode("rep:policy"));
+        try {
+            n.getNode("rep:policy");
+            fail("Accessing the rep:policy node must throw PathNotFoundException.");
+        } catch (PathNotFoundException e) {
+            // ok.
+        }
+
+        /* Finally the test user must not be allowed to remove the policy. */
+        try {
+            testAcMgr.removePolicy(path);
+            fail("Test user must not be allowed to remove the access control policy.");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+    }
+
+    public void testAccessControlModification() throws RepositoryException, NotExecutableException {
+        /* precondition:
+          testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+
+        // give 'testUser' ADD_CHILD_NODES|MODIFY_PROPERTIES| REMOVE_CHILD_NODES privileges at 'path'
+        PolicyTemplate tmpl = givePrivileges(path,
+                PrivilegeRegistry.ADD_CHILD_NODES |
+                PrivilegeRegistry.REMOVE_CHILD_NODES |
+                PrivilegeRegistry.MODIFY_PROPERTIES, getRestrictions(path));
+        /*
+         testuser must not have
+         - permission to view AC items
+         - permission to modify AC items
+        */
+
+        // make sure the 'rep:policy' node has been created.
+        assertTrue(superuser.itemExists(tmpl.getPath() + "/rep:policy"));
+        // the policy node however must not be visible to the test-user
+        assertFalse(testSession.itemExists(tmpl.getPath() + "/rep:policy"));
+        try {
+            testAcMgr.getPolicy(tmpl.getPath());
+            fail("test user must not have READ_AC privilege.");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+        try {
+            testAcMgr.getEffectivePolicy(tmpl.getPath());
+            fail("test user must not have READ_AC privilege.");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+        try {
+            testAcMgr.getEffectivePolicy(path);
+            fail("test user must not have READ_AC privilege.");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+        try {
+            testAcMgr.getAccessControlEntries(tmpl.getPath());
+            fail("test user must not have READ_AC privilege.");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+        try {
+            testAcMgr.removePolicy(tmpl.getPath());
+            fail("test user must not have MODIFY_AC privilege.");
+        } catch (AccessDeniedException e) {
+            // success
+        }
+    }
+
+
+    public void testWithDrawRead() throws RepositoryException, NotExecutableException {
+        /*
+         precondition:
+         testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+
+        // give 'testUser' READ_AC|MODIFY_AC privileges at 'path'
+        givePrivileges(path, PrivilegeRegistry.WRITE, getRestrictions(path));
+        // withdraw the READ privilege
+        withdrawPrivileges(path, PrivilegeRegistry.READ, getRestrictions(path));
+
+        //assertFalse(testSession.itemExists(path));
+
+        Session s = null;
+        try {
+            s = helper.getRepository().login(creds);
+            assertFalse(s.itemExists(path));
+        } finally {
+            if (s != null) {
+                s.logout();
+            }
+        }
+    }
+
+    public void testInheritance() throws RepositoryException, NotExecutableException {
+        /* precondition:
+          testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+
+        // give 'modify-properties' privilege on 'path'
+        givePrivileges(path, PrivilegeRegistry.MODIFY_PROPERTIES, getRestrictions(path));
+        // give 'add-child-nodes' and 'remove-child-nodes' privilege on 'child-path'
+        givePrivileges(childNPath, PrivilegeRegistry.ADD_CHILD_NODES |
+                PrivilegeRegistry.REMOVE_CHILD_NODES, getRestrictions(childNPath));
+
+        /*
+        since permission evaluation respects inheritance through the node
+        hierarchy, the following privileges must now be given at 'childNPath':
+        - read
+        - modify-properties
+        - add-child-nodes
+        - remove-child-nodes
+        -> read + write
+        */
+        Privilege[] privs = new Privilege[] {
+                PrivilegeRegistry.READ_PRIVILEGE,
+                PrivilegeRegistry.WRITE_PRIVILEGE
+        };
+        assertTrue(testAcMgr.hasPrivileges(childNPath, privs));
+        /*
+        ... and the following permissions must be granted at any child item
+        of child-path:
+        - read
+        - set-property
+        - add-node
+        - remove
+        */
+        String nonExistingItemPath = childNPath + "/anyItem";
+        String actions = SessionImpl.ADD_NODE_ACTION + "," +
+                SessionImpl.REMOVE_ACTION + "," +
+                SessionImpl.SET_PROPERTY_ACTION + "," +
+                SessionImpl.READ_ACTION;
+        assertTrue(testSession.hasPermission(nonExistingItemPath, actions));
+
+        /* try adding a new child node -> must succeed. */
+        Node childN = testSession.getNode(childNPath);
+        Node testChild = childN.addNode(nodeName2, testNodeType);
+
+        /* test privileges on the 'new' child node */
+        privs = testAcMgr.getPrivileges(testChild.getPath());
+        int exptectedPrivs = PrivilegeRegistry.WRITE | PrivilegeRegistry.READ;
+        assertTrue(exptectedPrivs == PrivilegeRegistry.getBits(privs));
+
+        /* repeate test after save. */
+        testSession.save();
+        privs = testAcMgr.getPrivileges(testChild.getPath());
+        assertTrue(exptectedPrivs == PrivilegeRegistry.getBits(privs));
+    }
+
+    public void testNewNodes() throws RepositoryException {
+        /*
+         precondition:
+         testuser must have READ-only permission on test-node and below
+        */
+        checkReadOnly(path);
+
+        /* create some new nodes below 'path' */
+        Node n = testSession.getNode(path);
+        for (int i = 0; i < 5; i++) {
+            n = n.addNode(nodeName2, testNodeType);
+        }
+
+        /* make sure the same privileges/permissions are granted as at path. */
+        Privilege[] privs = testAcMgr.getPrivileges(n.getPath());
+        assertTrue(PrivilegeRegistry.READ == PrivilegeRegistry.getBits(privs));
+        testSession.checkPermission(n.getPath(), SessionImpl.READ_ACTION);
+    }
+
+    public void testNonExistingItem() throws RepositoryException {
+        /*
+          precondition:
+          testuser must have READ-only permission on the root node and below
+        */
+        String rootPath = testSession.getRootNode().getPath();
+        checkReadOnly(rootPath);
+        testSession.checkPermission(rootPath + "nonExistingItem", SessionImpl.READ_ACTION);
+    }
+
+    public void testACItemsAreProtected() throws NotExecutableException, RepositoryException {
+        // search for a rep:policy node
+        Node policyNode = findPolicyNode(superuser.getRootNode());
+        if (policyNode == null) {
+            throw new NotExecutableException("no policy node found.");
+        }
+
+        assertTrue("The rep:Policy node must be protected", policyNode.getDefinition().isProtected());
+        try {
+            policyNode.remove();
+            fail("rep:Policy node must be protected.");
+        } catch (ConstraintViolationException e) {
+            // success
+        }
+
+        for (NodeIterator it = policyNode.getNodes(); it.hasNext();) {
+            Node n = it.nextNode();
+            if (n.isNodeType("rep:ACE")) {
+                try {
+                    n.remove();
+                    fail("ACE node must be protected.");
+                } catch (ConstraintViolationException e) {
+                    // success
+                }
+                break;
+            }
+        }
+
+        try {
+            policyNode.setProperty("test", "anyvalue");
+            fail("rep:policy node must be protected.");
+        } catch (ConstraintViolationException e) {
+            // success
+        }
+        try {
+            policyNode.addNode("test", "rep:ACE");
+            fail("rep:policy node must be protected.");
+        } catch (ConstraintViolationException e) {
+            // success
+        }
+    }
+
+    private static Node findPolicyNode(Node start) throws RepositoryException {
+        Node policyNode = null;
+        if (start.isNodeType("rep:ACL")) {
+            policyNode = start;
+        }
+        for (NodeIterator it = start.getNodes(); it.hasNext() && policyNode == null;) {
+            policyNode = findPolicyNode(it.nextNode());
+        }
+        return policyNode;
+    }
+
+    // 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
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractPolicyTemplateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractPolicyTemplateTest.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractPolicyTemplateTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractPolicyTemplateTest.java Thu Apr 17 09:27:09 2008
@@ -17,6 +17,8 @@
 package org.apache.jackrabbit.core.security.authorization;
 
 import org.apache.jackrabbit.test.JUnitTest;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,15 +52,113 @@
 
         assertNotNull(pt.getEntries());
         assertTrue(pt.getEntries().length == 0);
+        assertTrue(pt.size() == pt.getEntries().length);
         assertTrue(pt.isEmpty());
         assertNotNull(pt.getName());
     }
 
-
     public void testGetPath() {
         PolicyTemplate pt = (PolicyTemplate) createEmptyTemplate(getTestPath());
         assertEquals(getTestPath(), pt.getPath());
     }
 
-    // TODO: add more tests
+    public void testSetInvalidEntry() throws RepositoryException {
+        PolicyTemplate pt = (PolicyTemplate) createEmptyTemplate(getTestPath());
+        try {
+            pt.setEntry(new PolicyEntry() {
+                public boolean isAllow() {
+                    return false;
+                }
+                public int getPrivilegeBits() {
+                    return PrivilegeRegistry.READ;
+                }
+
+                public Principal getPrincipal() {
+                    return testPrincipal;
+                }
+
+                public Privilege[] getPrivileges() {
+                    return new Privilege[] {PrivilegeRegistry.READ_PRIVILEGE};
+                }
+            });
+            fail("Passing an unknown PolicyEntry should fail");
+        } catch (AccessControlException e) {
+            // success
+        }
+    }
+
+    public void testSetInvalidEntry2() throws RepositoryException {
+        PolicyTemplate pt = (PolicyTemplate) createEmptyTemplate(getTestPath());
+        try {
+            pt.setEntry(new PolicyEntry() {
+                public boolean isAllow() {
+                    return false;
+                }
+                public int getPrivilegeBits() {
+                    return 0;
+                }
+
+                public Principal getPrincipal() {
+                    return testPrincipal;
+                }
+
+                public Privilege[] getPrivileges() {
+                    return new Privilege[0];
+                }
+            });
+            fail("Passing a PolicyEntry with invalid privileges should fail");
+        } catch (AccessControlException e) {
+            // success
+        }
+    }
+
+        public void testRemoveInvalidEntry() throws RepositoryException {
+        PolicyTemplate pt = (PolicyTemplate) createEmptyTemplate(getTestPath());
+        try {
+            pt.removeEntry(new PolicyEntry() {
+                public boolean isAllow() {
+                    return false;
+                }
+                public int getPrivilegeBits() {
+                    return PrivilegeRegistry.READ;
+                }
+
+                public Principal getPrincipal() {
+                    return testPrincipal;
+                }
+
+                public Privilege[] getPrivileges() {
+                    return new Privilege[] {PrivilegeRegistry.READ_PRIVILEGE};
+                }
+            });
+            fail("Passing an unknown PolicyEntry should fail");
+        } catch (AccessControlException e) {
+            // success
+        }
+    }
+
+    public void testRemoveInvalidEntry2() throws RepositoryException {
+        PolicyTemplate pt = (PolicyTemplate) createEmptyTemplate(getTestPath());
+        try {
+            pt.removeEntry(new PolicyEntry() {
+                public boolean isAllow() {
+                    return false;
+                }
+                public int getPrivilegeBits() {
+                    return 0;
+                }
+
+                public Principal getPrincipal() {
+                    return testPrincipal;
+                }
+
+                public Privilege[] getPrivileges() {
+                    return new Privilege[0];
+                }
+            });
+            fail("Passing a PolicyEntry with invalid privileges should fail");
+        } catch (AccessControlException e) {
+            // success
+        }
+    }
 }

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=649172&r1=649171&r2=649172&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 Apr 17 09:27:09 2008
@@ -18,9 +18,14 @@
 
 import org.apache.jackrabbit.core.security.authorization.AbstractPolicyTemplateTest;
 import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.PolicyEntry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+
 /**
  * <code>ACLTemplateTest</code>...
  */
@@ -34,5 +39,129 @@
 
     protected PolicyTemplate createEmptyTemplate(String path) {
         return new ACLTemplate(path);
+    }
+
+    public void testAddEntry() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+
+        assertTrue(pt.setEntry(new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true)));
+    }
+
+    public void testAddEntryTwice() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+
+        pt.setEntry(pe);
+        assertFalse(pt.setEntry(pe));
+    }
+
+    public void testRevokeEffect() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+
+        pt.setEntry(pe);
+
+        // same entry but with revers 'isAllow' flag
+        pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, false);
+        assertTrue(pt.setEntry(pe));
+
+        // net-effect: only a single deny-read entry
+        assertTrue(pt.size() == 1);
+        assertEquals(pt.getEntries()[0], pe);
+    }
+
+    public void testEffect() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+
+        pt.setEntry(pe);
+
+        // new entry extends privs.
+        pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ | PrivilegeRegistry.ADD_CHILD_NODES, true);
+        assertTrue(pt.setEntry(pe));
+
+        // net-effect: only a single allow-entry with both privileges
+        assertTrue(pt.size() == 1);
+        assertEquals(pt.getEntries()[0], pe);
+
+        // new entry revokes READ priv
+        pe = new ACEImpl(testPrincipal, PrivilegeRegistry.ADD_CHILD_NODES, true);
+        assertTrue(pt.setEntry(pe));
+        // net-effect: only a single allow-entry with add_child_nodes priv
+        assertTrue(pt.size() == 1);
+        assertEquals(pt.getEntries()[0], pe);
+    }
+
+    public void testEffect2() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+        pt.setEntry(pe);
+
+        // add deny entry for mod_props
+        PolicyEntry pe2 = new ACEImpl(testPrincipal, PrivilegeRegistry.MODIFY_PROPERTIES, false);
+        assertTrue(pt.setEntry(pe2));
+
+        // net-effect: 2 entries
+        assertTrue(pt.size() == 2);
+        assertEquals(pt.getEntries()[0], pe);
+        assertEquals(pt.getEntries()[1], pe2);
+    }
+
+    public void testEffect3() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.WRITE, true);
+
+        pt.setEntry(pe);
+
+        // add deny entry for mod_props
+        PolicyEntry pe2 = new ACEImpl(testPrincipal, PrivilegeRegistry.MODIFY_PROPERTIES, false);
+        assertTrue(pt.setEntry(pe2));
+
+        // net-effect: 2 entries with the allow entry being adjusted
+        assertTrue(pt.size() == 2);
+        PolicyEntry[] entries = pt.getEntries();
+        for (int i = 0; i < entries.length; i++) {
+            int privs = entries[i].getPrivilegeBits();
+            if (entries[i].isAllow()) {
+                assertTrue(privs == (PrivilegeRegistry.ADD_CHILD_NODES | PrivilegeRegistry.REMOVE_CHILD_NODES));
+            } else {
+                assertTrue(privs == PrivilegeRegistry.MODIFY_PROPERTIES);
+            }
+        }
+    }
+
+    public void testMultiplePrincipals() throws RepositoryException {
+        Principal princ2 = new Principal() {
+            public String getName() {
+                return "AnotherPrincipal";
+            }
+        };
+
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+        pt.setEntry(pe);
+
+        // add deny entry for mod_props
+        pe = new ACEImpl(princ2, PrivilegeRegistry.READ, true);
+        assertTrue(pt.setEntry(pe));
+        assertTrue(pt.getEntries().length == 2);
+    }
+
+    public void testRemoveEntry() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+        pt.setEntry(pe);
+
+        assertTrue(pt.removeEntry(pe));
+    }
+
+    public void testRemoveNonExisting() throws RepositoryException {
+        PolicyTemplate pt = createEmptyTemplate(getTestPath());
+        PolicyEntry pe = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, true);
+        pt.setEntry(pe);
+        PolicyEntry pe2 = new ACEImpl(testPrincipal, PrivilegeRegistry.READ, false);
+        pt.setEntry(pe2);
+
+        assertFalse(pt.removeEntry(pe));
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EvaluationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EvaluationTest.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EvaluationTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EvaluationTest.java Thu Apr 17 09:27:09 2008
@@ -16,113 +16,46 @@
  */
 package org.apache.jackrabbit.core.security.authorization.acl;
 
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.User;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.security.TestPrincipal;
+import org.apache.jackrabbit.core.security.authorization.AbstractEvaluationTest;
+import org.apache.jackrabbit.core.security.authorization.PolicyEntry;
+import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
-import org.apache.jackrabbit.core.security.jsr283.security.AbstractAccessControlTest;
 import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
 import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
 import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy;
 import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicyIterator;
 import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
 import org.apache.jackrabbit.test.NotExecutableException;
-import org.apache.jackrabbit.util.Text;
 
 import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
 import javax.jcr.RepositoryException;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.NodeIterator;
-import javax.jcr.Session;
-import javax.jcr.nodetype.ConstraintViolationException;
 import java.security.Principal;
 
 /**
  * <code>EvaluationTest</code>...
  */
-public class EvaluationTest extends AbstractAccessControlTest {
+public class EvaluationTest extends AbstractEvaluationTest {
 
-    private User testUser;
-    private SessionImpl testSession;
-    private AccessControlManager testAcMgr;
-
-    private String path;
-    private String childNPath;
-    private String childNPath2;
-    private String childPPath;
-    private String childchildPPath;
-    private String siblingPath;
+    private String[] restrictions = new String[0];
 
     protected void setUp() throws Exception {
         super.setUp();
 
-        UserManager uMgr = getUserManager(superuser);
-        Principal princ = new TestPrincipal("anyUser");
-        Credentials creds = new SimpleCredentials("anyUser", "anyUser".toCharArray());
-
-        Authorizable a = uMgr.getAuthorizable(princ);
-        if (a == null) {
-            testUser = uMgr.createUser("anyUser", creds, princ);
-        } else if (a.isGroup()) {
-            throw new NotExecutableException();
-        } else {
-            testUser = (User) a;
-        }
-
-        // TODO: remove cast once 283 is released.
-        testSession = (SessionImpl) helper.getRepository().login(creds);
-        testAcMgr = getAccessControlManager(testSession);
-
-        // create some nodes below the test root in order to apply ac-stuff
-        Node node = testRootNode.addNode(nodeName1, testNodeType);
-        Node cn1 = node.addNode(nodeName2, testNodeType);
-        Property cp1 = node.setProperty(propertyName1, "anyValue");
-        Node cn2 = node.addNode(nodeName3, testNodeType);
-
-        Property ccp1 = cn1.setProperty(propertyName1, "childNodeProperty");
-
-        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
-        superuser.save();
-
-        path = node.getPath();
-        childNPath = cn1.getPath();
-        childNPath2 = cn2.getPath();
-        childPPath = cp1.getPath();
-        childchildPPath = ccp1.getPath();
-        siblingPath = n2.getPath();
-    }
-
-    protected void tearDown() throws Exception {
-        super.tearDown();
-
-        if (testSession != null && testSession.isLive()) {
-            testSession.logout();
-        }
-        if (testUser != null) {
-            testUser.remove();
-        }
-    }
-
-    private static UserManager getUserManager(Session session) throws NotExecutableException {
-        if (!(session instanceof JackrabbitSession)) {
-            throw new NotExecutableException();
-        }
-
         try {
-            return ((JackrabbitSession) session).getUserManager();
+            AccessControlPolicy rootPolicy = acMgr.getPolicy("/");
+            if (!(rootPolicy instanceof ACLTemplate)) {
+                throw new NotExecutableException();
+            }
         } catch (RepositoryException e) {
             throw new NotExecutableException();
         }
     }
 
-    private static ACLTemplate getACLTemplate(AccessControlManager acM, String path) throws RepositoryException, AccessDeniedException {
+    protected void clearACInfo() {
+        // nop
+    }
+
+    protected PolicyTemplate getPolicyTemplate(AccessControlManager acM, String path) throws RepositoryException, AccessDeniedException, NotExecutableException {
         AccessControlPolicyIterator it = acM.getApplicablePolicies(path);
         while (it.hasNext()) {
             AccessControlPolicy acp = it.nextAccessControlPolicy();
@@ -130,208 +63,27 @@
                 return (ACLTemplate) acp;
             }
         }
-        // TODO: change to NotExecutableException
-        throw new RepositoryException();
+        throw new NotExecutableException("ACLTemplate expected.");
     }
 
-    private void givePrivileges(String nPath, int privileges) throws NotExecutableException, RepositoryException {
-        ACLTemplate tmpl = getACLTemplate(acMgr, nPath);
-        tmpl.setEntry(new ACEImpl(testUser.getPrincipal(), privileges, true));
-        acMgr.setPolicy(nPath, tmpl);
-        superuser.save();
-    }
-
-    private void withdrawPrivileges(String nPath, int privileges) throws NotExecutableException, RepositoryException {
-        ACLTemplate tmpl = getACLTemplate(acMgr, nPath);
-        tmpl.setEntry(new ACEImpl(testUser.getPrincipal(), privileges, false));
-        acMgr.setPolicy(nPath, tmpl);
-        superuser.save();
-    }
-
-    private void checkReadOnly(String path) throws RepositoryException {
-        Privilege[] privs = testAcMgr.getPrivileges(path);
-        assertTrue(privs.length == 1);
-        assertEquals(PrivilegeRegistry.READ_PRIVILEGE, privs[0]);
-    }
-
-    public void testGrantedPermissions() throws RepositoryException, AccessDeniedException, NotExecutableException {
-        /* precondition:
-           testuser must have READ-only permission on test-node and below
-         */
-        checkReadOnly(path);
-
-        // give 'testUser' ADD_CHILD_NODES|MODIFY_PROPERTIES privileges at 'path'
-        givePrivileges(path, PrivilegeRegistry.ADD_CHILD_NODES | PrivilegeRegistry.MODIFY_PROPERTIES);
-        /*
-         testuser must now have
-         - ADD_NODE permission for child node
-         - SET_PROPERTY permission for child props
-         - REMOVE permission for child-props
-         - READ-only permission for the node at 'path'
-
-         testuser must not have
-         - REMOVE permission for child node
-        */
-        String nonExChildPath = path + "/anyItem";
-        assertTrue(testSession.hasPermission(nonExChildPath, "read,add_node,set_property"));
-        assertFalse(testSession.hasPermission(nonExChildPath, "remove"));
-
-        Node testN = testSession.getNode(path);
-
-        // must be allowed to add child node
-        testN.addNode(nodeName3, testNodeType);
-        testSession.save();
-
-        // must be allowed to remove child-property
-        testSession.getProperty(childPPath).remove();
-        testSession.save();
-
-        // must be allowed to set child property again
-        testN.setProperty(Text.getName(childPPath), "othervalue");
-        testSession.save();
-
-        // must not be allowed to remove child nodes
-        try {
-            testSession.getNode(childNPath).remove();
-            testSession.save();
-            fail("test-user is not allowed to remove a node below " + path);
-        } catch (AccessDeniedException e) {
-            // success
-        }
-
-        // must have read-only access on 'testN' and it's sibling
-        assertTrue(testSession.hasPermission(path, "read"));
-        assertFalse(testSession.hasPermission(path, "add_node,set_property,remove"));
-        checkReadOnly(siblingPath);
-    }
-
-    public void testDeniedPermission() throws RepositoryException, NotExecutableException, InterruptedException {
-         /* precondition:
-           testuser must have READ-only permission on test-node and below
-         */
-        checkReadOnly(path);
-
-        // withdraw READ privilege to 'testUser' at 'path'
-        withdrawPrivileges(childNPath, PrivilegeRegistry.READ);
-        /*
-         testuser must now have
-         - READ-only permission for the child-props of path
-
-         testuser must not have
-         - any permission on child-node and all its subtree
-        */
-
-        // must still have read-access to path, ...
-        assertTrue(testSession.hasPermission(path, "read"));
-        Node n = testSession.getNode(path);
-        // ... siblings of childN
-        testSession.getNode(childNPath2);
-        // ... and props of path
-        assertTrue(n.getProperties().hasNext());
-
-        // must not have access to 'childNPath'
-        assertFalse(testSession.itemExists(childNPath));
-        try {
-            Node testN = testSession.getNode(childNPath);
-            fail("Read access has been denied -> cannot retrieve child node.");
-        } catch (PathNotFoundException e) {
-            // ok.
-        }
-
-        // must not have access to subtree below 'childNPath'
-        assertFalse(testSession.itemExists(childchildPPath));
-        try {
-            testSession.getItem(childchildPPath);
-            fail("Read access has been denied -> cannot retrieve prop below child node.");
-        } catch (PathNotFoundException e) {
-            // ok.
-        }
-    }
-
-    public void testAccessControlRead() throws NotExecutableException, RepositoryException {
-        checkReadOnly(path);
-
-        // re-grant READ in order to have an ACL-node
-        givePrivileges(path, PrivilegeRegistry.READ);
-        // make sure the 'rep:policy' node has been created.
-        assertTrue(superuser.itemExists(path + "/rep:policy"));
-
-        /*
-         Testuser must still have READ-only access only and must not be
-         allowed to view the acl-node that has been created.
-        */
-        assertFalse(testAcMgr.hasPrivileges(path, new Privilege[] {PrivilegeRegistry.READ_AC_PRIVILEGE}));
-        assertFalse(testSession.itemExists(path + "/rep:policy"));
-        Node n = testSession.getNode(path);
-        assertFalse(n.hasNode("rep:policy"));
-        try {
-            n.getNode("rep:policy");
-            fail("Accessing the rep:policy node must throw PathNotFoundException.");
-        } catch (PathNotFoundException e) {
-            // ok.
-        }
-
-        /* Finally the test user must not be allowed to remove the policy. */
-        try {
-            testAcMgr.removePolicy(path);
-            fail("Test user must not be allowed to remove the access control policy.");
-        } catch (AccessDeniedException e) {
-            // success
-        }
+    protected PolicyEntry createEntry(Principal principal, int privileges, boolean isAllow, String[] restrictions) {
+        return new ACEImpl(principal, privileges, isAllow);
     }
 
-    public void testAccessControlModification() throws RepositoryException, NotExecutableException {
-        /* precondition:
-          testuser must have READ-only permission on test-node and below
-        */
-        checkReadOnly(path);
-
-        // give 'testUser' ADD_CHILD_NODES|MODIFY_PROPERTIES| REMOVE_CHILD_NODES privileges at 'path'
-        givePrivileges(path, PrivilegeRegistry.ADD_CHILD_NODES | PrivilegeRegistry.REMOVE_CHILD_NODES | PrivilegeRegistry.MODIFY_PROPERTIES);
-        /*
-         testuser must not have
-         - permission to view AC items
-         - permission to modify AC items
-        */
-
-        // make sure the 'rep:policy' node has been created.
-        assertTrue(superuser.itemExists(path + "/rep:policy"));
-
-        assertFalse(testSession.itemExists(path + "/rep:policy"));
-        try {
-            testAcMgr.getPolicy(path);
-            fail("test user must not have READ_AC privilege.");
-        } catch (AccessDeniedException e) {
-            // success
-        }
-        try {
-            testAcMgr.getEffectivePolicy(path);
-            fail("test user must not have READ_AC privilege.");
-        } catch (AccessDeniedException e) {
-            // success
-        }
-        try {
-            testAcMgr.getAccessControlEntries(path);
-            fail("test user must not have READ_AC privilege.");
-        } catch (AccessDeniedException e) {
-            // success
-        }
-        try {
-            testAcMgr.removePolicy(path);
-            fail("test user must not have MODIFY_AC privilege.");
-        } catch (AccessDeniedException e) {
-            // success
-        }
+    protected String[] getRestrictions(String path) {
+        return restrictions;
     }
 
     public void testAccessControlModification2() throws RepositoryException, NotExecutableException {
-        /* precondition:
-          testuser must have READ-only permission on test-node and below
+        /*
+         precondition:
+         testuser must have READ-only permission on test-node and below
         */
         checkReadOnly(path);
 
         // give 'testUser' READ_AC|MODIFY_AC privileges at 'path'
-        givePrivileges(path, PrivilegeRegistry.READ_AC | PrivilegeRegistry.MODIFY_AC);
+        PolicyTemplate tmpl = givePrivileges(path, PrivilegeRegistry.READ_AC |
+                PrivilegeRegistry.MODIFY_AC, getRestrictions(path));
         /*
          testuser must
          - still have the inherited READ permission.
@@ -343,7 +95,11 @@
         */
 
         // make sure the 'rep:policy' node has been created.
-        assertTrue(testSession.itemExists(path + "/rep:policy"));
+        assertTrue(superuser.itemExists(tmpl.getPath() + "/rep:policy"));
+
+        // test: MODIFY_AC granted at 'path'
+        assertTrue(testAcMgr.hasPrivileges(path, new Privilege[] {
+                PrivilegeRegistry.MODIFY_AC_PRIVILEGE}));
 
         // test: READ_AC privilege does not apply outside of the tree.
         try {
@@ -356,8 +112,8 @@
         // test: MODIFY_AC privilege does not apply outside of the tree.
         try {
             testAcMgr.addAccessControlEntry(siblingPath,
-                testUser.getPrincipal(),
-                new Privilege[] {PrivilegeRegistry.WRITE_PRIVILEGE});
+                    testUser.getPrincipal(),
+                    new Privilege[] {PrivilegeRegistry.WRITE_PRIVILEGE});
             fail("MODIFY_AC privilege must not apply outside of the tree it has applied to.");
         } catch (AccessDeniedException e) {
             // success
@@ -366,6 +122,7 @@
         // test if testuser can READ access control on the path and on the
         // entire subtree that gets the policy inherited.
         AccessControlPolicy policy = testAcMgr.getPolicy(path);
+        AccessControlPolicy effPolicy = testAcMgr.getEffectivePolicy(path);
         AccessControlPolicy effPOnChild = testAcMgr.getEffectivePolicy(childNPath);
 
         // test if testuser can modify AC-items
@@ -374,7 +131,6 @@
                 testUser.getPrincipal(),
                 new Privilege[] {PrivilegeRegistry.WRITE_PRIVILEGE});
         testSession.save();
-
         assertTrue(testAcMgr.hasPrivileges(path,
                 new Privilege[] {PrivilegeRegistry.REMOVE_CHILD_NODES_PRIVILEGE}));
 
@@ -394,55 +150,5 @@
         // ... and since the ACE is stored with the policy all right except
         // READ must be gone.
         checkReadOnly(path);
-    }
-
-    public void testACItemsAreProtected() throws NotExecutableException, RepositoryException {
-        // make sure a rep:policy node is present at 'path'
-        givePrivileges(path, PrivilegeRegistry.WRITE);
-        Node n = ((SessionImpl) superuser).getNode(path);
-        Node policyNode = n.getNode("rep:policy");
-
-        assertTrue("The rep:policy node must be protected", policyNode.getDefinition().isProtected());
-        try {
-            policyNode.remove();
-            fail("rep:policy node must be protected.");
-        } catch (ConstraintViolationException e) {
-            // success
-        }
-        Node aceNode = null;
-        for (NodeIterator it = policyNode.getNodes(); it.hasNext();) {
-            n = it.nextNode();
-            if (n.isNodeType("rep:ACE")) {
-                aceNode = n;
-                break;
-            }
-        }
-        if (aceNode == null) {
-            fail("Child-node expected below rep:policy node.");
-        }
-        try {
-            aceNode.remove();
-            fail("ACE node must be protected.");
-        } catch (ConstraintViolationException e) {
-            // success
-        }
-        try {
-            aceNode.setProperty("anyProperty", "anyValue");
-            fail("ACE node must be protected.");
-        } catch (ConstraintViolationException e) {
-            // success
-        }
-        try {
-            policyNode.setProperty("test", "anyvalue");
-            fail("rep:policy node must be protected.");
-        } catch (ConstraintViolationException e) {
-            // success
-        }
-        try {
-            policyNode.addNode("test", aceNode.getPrimaryNodeType().getName());
-            fail("rep:policy node must be protected.");
-        } catch (ConstraintViolationException e) {
-            // success
-        }
     }
 }

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java?rev=649172&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java Thu Apr 17 09:27:09 2008
@@ -0,0 +1,95 @@
+/*
+ * 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.combined;
+
+import org.apache.jackrabbit.core.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.core.security.authorization.AbstractEvaluationTest;
+import org.apache.jackrabbit.core.security.authorization.PolicyEntry;
+import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+
+/**
+ * <code>EvaluationTest</code>...
+ */
+public class EvaluationTest extends AbstractEvaluationTest {
+
+    private static Logger log = LoggerFactory.getLogger(EvaluationTest.class);
+
+    private String testPolicyPath;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        JackrabbitAccessControlManager jam;
+        if (acMgr instanceof JackrabbitAccessControlManager) {
+            jam = (JackrabbitAccessControlManager) acMgr;
+        } else {
+            throw new NotExecutableException();
+        }
+        try {
+            AccessControlPolicy rootPolicy = acMgr.getPolicy("/");
+            if (!(rootPolicy instanceof PolicyTemplateImpl)) {
+                throw new NotExecutableException();
+            }
+        } catch (RepositoryException e) {
+            throw new NotExecutableException();
+        }
+
+
+        StringBuffer b = new StringBuffer("/rep:accesscontrol");
+        Principal principal = testUser.getPrincipal();
+        testPolicyPath = jam.editPolicy(principal).getPath();
+    }
+
+    protected void clearACInfo() {
+        try {
+            acMgr.removePolicy(testPolicyPath);
+            superuser.save();
+        } catch (RepositoryException e) {
+            // log error and ignore
+            log.error(e.getMessage());
+        }
+    }
+
+    protected PolicyTemplate getPolicyTemplate(AccessControlManager acM, String path) throws RepositoryException, AccessDeniedException, NotExecutableException {
+        if (acM instanceof JackrabbitAccessControlManager) {
+            PolicyTemplate pt = ((JackrabbitAccessControlManager) acM).editPolicy(testPolicyPath);
+            if (pt instanceof PolicyTemplateImpl) {
+                return (PolicyTemplateImpl) pt;
+            }
+        }
+        throw new NotExecutableException();
+    }
+
+    protected PolicyEntry createEntry(Principal principal, int privileges, boolean isAllow, String[] restrictions) {
+        String nodePath = restrictions[0];
+        String glob = restrictions[1];
+        return new PolicyEntryImpl(principal, privileges, isAllow, nodePath, glob);
+    }
+
+    protected String[] getRestrictions(String path) {
+        return new String[] {path, "*"};
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/TestAll.java?rev=649172&r1=649171&r2=649172&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/TestAll.java Thu Apr 17 09:27:09 2008
@@ -23,8 +23,8 @@
         suite.addTestSuite(PolicyEntryImplTest.class);
         suite.addTestSuite(GlobPatternTest.class);
 
-        //todo: add evaluation tests.
-        
+        suite.addTestSuite(EvaluationTest.class);
+
         return suite;
     }
 }