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 2009/08/11 10:28:23 UTC

svn commit: r803026 - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/ jackrabbit-core/sr...

Author: angela
Date: Tue Aug 11 08:28:22 2009
New Revision: 803026

URL: http://svn.apache.org/viewvc?rev=803026&view=rev
Log:
JCR-2253: Discovery of privileges of any set of Principals

Added:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManagerTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/TestAll.java
Modified:
    jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java

Modified: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java?rev=803026&r1=803025&r2=803026&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java (original)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.java Tue Aug 11 08:28:22 2009
@@ -19,9 +19,12 @@
 import javax.jcr.AccessDeniedException;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
 import java.security.Principal;
+import java.util.Set;
 
 /**
  * <code>JackrabbitAccessControlManager</code> provides extensions to the
@@ -62,4 +65,76 @@
      * @throws RepositoryException
      */
     JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
+
+    /**
+     * Returns whether the given set of <code>Principal</code>s has the specified
+     * privileges for absolute path <code>absPath</code>, which must be an
+     * existing node.
+     * <p>
+     * Testing an aggregate privilege is equivalent to testing each non
+     * aggregate privilege among the set returned by calling
+     * <code>Privilege.getAggregatePrivileges()</code> for that privilege.
+     * <p>
+     * The results reported by the this method reflect the net <i>effect</i> of
+     * the currently applied control mechanisms. It does not reflect unsaved
+     * access control policies or unsaved access control entries. Changes to
+     * access control status caused by these mechanisms only take effect on
+     * <code>Session.save()</code> and are only then reflected in the results of
+     * the privilege test methods.
+     * <p>
+     * Since this method allows to view the privileges of principals other
+     * than included in the editing session, this method must throw
+     * <code>AccessDeniedException</code> if the session lacks
+     * <code>READ_ACCESS_CONTROL</code> privilege for the <code>absPath</code>
+     * node.
+     *
+     * @param absPath    an absolute path.
+     * @param principals a set of <code>Principal</code>s for which is the
+     * given privileges are tested.
+     * @param privileges an array of <code>Privilege</code>s.
+     * @return <code>true</code> if the session has the specified privileges;
+     *         <code>false</code> otherwise.
+     * @throws javax.jcr.PathNotFoundException if no node at <code>absPath</code> exists
+     * or the session does not have sufficent access to retrieve a node at that location.
+     * @throws AccessDeniedException if the session lacks
+     * <code>READ_ACCESS_CONTROL</code> privilege for the <code>absPath</code> node.
+     * @throws RepositoryException  if another error occurs.
+     */
+    public boolean hasPrivileges(String absPath, Set<Principal> principals, Privilege[] privileges)
+            throws PathNotFoundException, AccessDeniedException, RepositoryException;
+
+    /**
+     * Returns the privileges the given set of <code>Principal</code>s has for
+     * absolute path <code>absPath</code>, which must be an existing node.
+     * <p>
+     * The returned privileges are those for which {@link #hasPrivileges} would
+     * return <code>true</code>.
+     * <p>
+     * The results reported by the this method reflect the net <i>effect</i> of
+     * the currently applied control mechanisms. It does not reflect unsaved
+     * access control policies or unsaved access control entries. Changes to
+     * access control status caused by these mechanisms only take effect on
+     * <code>Session.save()</code> and are only then reflected in the results of
+     * the privilege test methods.
+     * <p>
+     * Since this method allows to view the privileges of principals other
+     * than included in the editing session, this method must throw
+     * <code>AccessDeniedException</code> if the session lacks
+     * <code>READ_ACCESS_CONTROL</code> privilege for the <code>absPath</code>
+     * node.
+     *
+     *
+     * @param absPath an absolute path.
+     * @param principals a set of <code>Principal</code>s for which is the
+     * privileges are retrieved.
+     * @return an array of <code>Privilege</code>s.
+     * @throws PathNotFoundException if no node at <code>absPath</code> exists
+     * or the session does not have sufficient access to retrieve a node at that
+     * location.
+     * @throws AccessDeniedException if the session lacks <code>READ_ACCESS_CONTROL</code>
+     * privilege for the <code>absPath</code> node.
+     * @throws RepositoryException  if another error occurs.
+     */
+    public Privilege[] getPrivileges(String absPath, Set<Principal> principals)
+            throws PathNotFoundException, AccessDeniedException, RepositoryException;
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=803026&r1=803025&r2=803026&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Tue Aug 11 08:28:22 2009
@@ -19,6 +19,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+import java.security.Principal;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.PathNotFoundException;
@@ -274,5 +275,19 @@
             // cannot determine the effective policies for the system session.
             return new AccessControlPolicy[0];
         }
+
+        /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#hasPrivileges(String, Set, Privilege[])
+     */
+        public boolean hasPrivileges(String absPath, Set<Principal> principals, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+            throw new UnsupportedOperationException("not implemented");
+        }
+
+        /**
+         * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getPrivileges(String, Set)
+         */
+        public Privilege[] getPrivileges(String absPath, Set<Principal> principals) throws PathNotFoundException, RepositoryException {
+            throw new UnsupportedOperationException("not implemented");
+        }
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java?rev=803026&r1=803025&r2=803026&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java Tue Aug 11 08:28:22 2009
@@ -326,7 +326,6 @@
         checkInitialized();
         checkPermission(absPath, Permission.READ_AC);
 
-        // TODO: acProvider may not retrieve the correct policy in case of transient modifications
         return acProvider.getEffectivePolicies(getPath(absPath));
     }
 
@@ -395,6 +394,40 @@
         }
         return editor.getPolicies(principal);
     }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#hasPrivileges(String, Set, Privilege[])
+     */
+    public boolean hasPrivileges(String absPath, Set<Principal> principals, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        checkValidNodePath(absPath);
+        checkPermission(absPath, Permission.READ_AC);
+
+        if (privileges == null || privileges.length == 0) {
+            // null or empty privilege array -> return true
+            log.debug("No privileges passed -> allowed.");
+            return true;
+        } else {
+            int privs = PrivilegeRegistry.getBits(privileges);
+            Path p = resolver.getQPath(absPath);
+            return (acProvider.compilePermissions(principals).getPrivileges(p) | ~privs) == -1;
+        }
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getPrivileges(String, Set)
+     */
+    public Privilege[] getPrivileges(String absPath, Set<Principal> principals) throws PathNotFoundException, RepositoryException {
+        checkInitialized();
+        checkValidNodePath(absPath);
+        checkPermission(absPath, Permission.READ_AC);
+
+        int bits = acProvider.compilePermissions(principals).getPrivileges(resolver.getQPath(absPath));
+        return (bits == PrivilegeRegistry.NO_PRIVILEGE) ?
+                new Privilege[0] :
+                privilegeRegistry.getPrivileges(bits);
+    }
+
     //---------------------------------------< AbstractAccessControlManager >---
     /**
      * @see AbstractAccessControlManager#checkInitialized()

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=803026&r1=803025&r2=803026&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 Tue Aug 11 08:28:22 2009
@@ -38,6 +38,8 @@
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Set;
 
 /**
  * <code>SimpleAccessManager</code> ...
@@ -295,4 +297,44 @@
             throw new PathNotFoundException(absPath);
         }
     }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#hasPrivileges(String, Set, Privilege[])
+     */
+    public boolean hasPrivileges(String absPath, Set<Principal> principals, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+        if (anonymous) {
+            // anonymous doesn't have READ_AC privilege
+            throw new AccessDeniedException();
+        }
+        
+        if (principals.size() == 1) {
+            Principal princ = principals.iterator().next();
+            if (princ instanceof AnonymousPrincipal) {
+                return privileges.length == 1 && privileges[0].equals(privilegeRegistry.getPrivilege(Privilege.JCR_READ));
+            }
+        }
+
+        // @todo check permission based on principals
+        return true;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getPrivileges(String, Set)
+     */
+    public Privilege[] getPrivileges(String absPath, Set<Principal> principals) throws PathNotFoundException, RepositoryException {
+        if (anonymous) {
+            // anonymous doesn't have READ_AC privilege
+            throw new AccessDeniedException();
+        }
+
+        if (principals.size() == 1) {
+            Principal princ = principals.iterator().next();
+            if (princ instanceof AnonymousPrincipal) {
+                return new Privilege[] {privilegeRegistry.getPrivilege(Privilege.JCR_READ)};
+            }
+        }
+
+        // @todo check permission based on principals
+        return new Privilege[] {privilegeRegistry.getPrivilege(Privilege.JCR_ALL)};
+    }
 }

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManagerTest.java?rev=803026&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManagerTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/JackrabbitAccessControlManagerTest.java Tue Aug 11 08:28:22 2009
@@ -0,0 +1,108 @@
+/*
+ * 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.api.security;
+
+import org.apache.jackrabbit.test.api.security.AbstractAccessControlTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.apache.jackrabbit.core.security.principal.EveryonePrincipal;
+
+import javax.jcr.Session;
+import javax.jcr.RepositoryException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.security.Privilege;
+import java.util.Collections;
+import java.util.Set;
+import java.security.Principal;
+
+/**
+ * <code>JackrabbitAccessControlManagerTest</code>...
+ */
+public class JackrabbitAccessControlManagerTest extends AbstractAccessControlTest {
+
+    Set<Principal> principals;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        if (!(acMgr instanceof JackrabbitAccessControlManager)) {
+            throw new NotExecutableException();
+        }
+
+        Principal principal = EveryonePrincipal.getInstance();
+        principals = Collections.singleton(principal);
+    }
+
+    public void testHasPrivilegeThrowsAccessDenied() throws RepositoryException {
+        Session readOnly = getHelper().getReadOnlySession();
+        JackrabbitAccessControlManager jacMgr = (JackrabbitAccessControlManager) readOnly.getAccessControlManager();
+        try {
+            jacMgr.hasPrivileges(testRoot, principals, new Privilege[] {jacMgr.privilegeFromName(Privilege.JCR_READ)});
+            fail("ReadOnly session isn't allowed to determine the privileges of other principals.");
+        } catch (AccessDeniedException e) {
+            // success
+        } finally {
+            readOnly.logout();
+        }
+    }
+
+    public void testGetPrivilegesThrowsAccessDenied() throws RepositoryException {
+        Session readOnly = getHelper().getReadOnlySession();
+        JackrabbitAccessControlManager jacMgr = (JackrabbitAccessControlManager) readOnly.getAccessControlManager();
+        try {
+            jacMgr.getPrivileges(testRoot, principals);
+            fail("ReadOnly session isn't allowed to determine the privileges of other principals.");
+        } catch (AccessDeniedException e) {
+            // success
+        } finally {
+            readOnly.logout();
+        }
+    }
+
+    public void testHasPrivilegesWithInvalidPath() throws RepositoryException {
+        JackrabbitAccessControlManager jacMgr = (JackrabbitAccessControlManager) acMgr;
+        String invalidPath = testRoot;
+        while (superuser.nodeExists(invalidPath)) {
+            invalidPath += "_";
+        }
+        
+        try {
+            jacMgr.hasPrivileges(invalidPath, principals, new Privilege[] {jacMgr.privilegeFromName(Privilege.JCR_READ)});
+            fail("Invalid path must be detected");
+        } catch (PathNotFoundException e) {
+            // success
+        }
+    }
+
+    public void testGetPrivilegesWithInvalidPath() throws RepositoryException {
+        JackrabbitAccessControlManager jacMgr = (JackrabbitAccessControlManager) acMgr;
+        String invalidPath = testRoot;
+        while (superuser.nodeExists(invalidPath)) {
+            invalidPath += "_";
+        }
+
+        try {
+            jacMgr.getPrivileges(invalidPath, principals);
+            fail("Invalid path must be detected");
+        } catch (PathNotFoundException e) {
+            // success
+        }
+    }
+
+    // TODO add more tests
+}
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/TestAll.java?rev=803026&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/TestAll.java Tue Aug 11 08:28:22 2009
@@ -0,0 +1,42 @@
+/*
+ * 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.api.security;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * <code>TestAll</code>...
+ */
+public class TestAll extends AbstractJCRTest {
+
+        /**
+     * Returns a <code>Test</code> suite that executes all tests inside this
+     * package.
+     *
+     * @return a <code>Test</code> suite that executes all tests inside this
+     *         package.
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite("api.security tests");
+
+        suite.addTestSuite(JackrabbitAccessControlManagerTest.class);
+
+        return suite;
+    }
+}
\ No newline at end of file