You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2013/04/23 15:40:21 UTC

svn commit: r1470950 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/security/authorization/ main/java/org/apache/jackrabbit/oak/security/authorization/restriction/ test/java/org/apache/jackrabbit/oak/security/authorization/

Author: angela
Date: Tue Apr 23 13:40:21 2013
New Revision: 1470950

URL: http://svn.apache.org/r1470950
Log:
OAK-758 : Implement AC-editing by principal (Jackrabbit API)

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/PrincipalRestrictionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java?rev=1470950&r1=1470949&r2=1470950&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java Tue Apr 23 13:40:21 2013
@@ -20,9 +20,11 @@ import java.security.Principal;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -31,10 +33,10 @@ import javax.jcr.AccessDeniedException;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
 import javax.jcr.query.Query;
 import javax.jcr.security.AccessControlEntry;
 import javax.jcr.security.AccessControlException;
-import javax.jcr.security.AccessControlList;
 import javax.jcr.security.AccessControlPolicy;
 import javax.jcr.security.AccessControlPolicyIterator;
 import javax.jcr.security.Privilege;
@@ -216,58 +218,69 @@ public class AccessControlManagerImpl im
         checkValidPolicy(oakPath, policy);
 
         if (policy instanceof PrincipalACL) {
-            PrincipalACL principalAcl = (PrincipalACL) policy;
-            AccessControlPolicy[] plcs = getPolicies(principalAcl.principal);
-            PrincipalACL existing = (plcs.length == 0) ? null : (PrincipalACL) plcs[0];
+            setPrincipalBasedAcl((PrincipalACL) policy);
+        } else {
+            Tree tree = getTree(oakPath, Permissions.MODIFY_ACCESS_CONTROL);
+            setNodeBasedAcl(oakPath, tree, (ACL) policy);
+        }
+    }
 
-            List<JackrabbitAccessControlEntry> toAdd = Lists.newArrayList(principalAcl.getEntries());
-            List<JackrabbitAccessControlEntry> toRemove = Collections.emptyList();
-            if (existing != null) {
-                toAdd.removeAll(existing.getEntries());
-                toRemove = existing.getEntries();
-                toRemove.removeAll(principalAcl.getEntries());
-            }
-            // add new entries
-            for (JackrabbitAccessControlEntry ace : toAdd) {
-                String path = getOakPath(ace.getRestriction(REP_NODE_PATH).getString());
-                Tree tree = getTree(path, Permissions.MODIFY_ACCESS_CONTROL);
-                NodeUtil aclNode = getAclNode(path, tree);
-                if (aclNode == null) {
-                    aclNode = createAclNode(path, tree);
-                }
-                aclNode.getTree().setOrderableChildren(true);
-                writeACE(path, aclNode, ace, principalAcl.rProvider);
-            }
+    private void setPrincipalBasedAcl(PrincipalACL principalAcl) throws RepositoryException {
+        AccessControlPolicy[] plcs = getPolicies(principalAcl.principal);
+        PrincipalACL existing = (plcs.length == 0) ? null : (PrincipalACL) plcs[0];
 
-            // remove entries that are not longer present in the acl to write
-            for (JackrabbitAccessControlEntry ace : toRemove) {
-                String path = getOakPath(ace.getRestriction(REP_NODE_PATH).getString());
-                NodeUtil aclNode = checkNotNull(getAclNode(path, getTree(path, Permissions.MODIFY_ACCESS_CONTROL)));
-                Iterator<Tree> children = aclNode.getTree().getChildren().iterator();
-                while (children.hasNext()) {
-                    Tree child = children.next();
-                    if (ace.equals(createACE(path, child, principalAcl.rProvider))) {
-                        child.remove();
-                    }
-                }
+        List<JackrabbitAccessControlEntry> toAdd = Lists.newArrayList(principalAcl.getEntries());
+        List<JackrabbitAccessControlEntry> toRemove = Collections.emptyList();
+        if (existing != null) {
+            toAdd.removeAll(existing.getEntries());
+            toRemove = existing.getEntries();
+            toRemove.removeAll(principalAcl.getEntries());
+        }
+        // add new entries
+        for (JackrabbitAccessControlEntry ace : toAdd) {
+            String path = getOakPath(ace.getRestriction(REP_NODE_PATH).getString());
+            Tree tree = getTree(path, Permissions.MODIFY_ACCESS_CONTROL);
+
+            ACL acl = (ACL) createACL(path, tree, false);
+            if (acl == null) {
+                acl = new NodeACL(path);
             }
-        } else {
-            Tree tree = getTree(oakPath, Permissions.MODIFY_ACCESS_CONTROL);
-            NodeUtil aclNode = getAclNode(oakPath, tree);
-            if (aclNode != null) {
-                // remove all existing aces
-                for (Tree aceTree : aclNode.getTree().getChildren()) {
-                    aceTree.remove();
+
+            Map<String, Value> restrictions = new HashMap();
+            for (String name : ace.getRestrictionNames()) {
+                if (!REP_NODE_PATH.equals(name)) {
+                    restrictions.put(name, ace.getRestriction(name));
                 }
-            } else {
-                aclNode = createAclNode(oakPath, tree);
             }
-            aclNode.getTree().setOrderableChildren(true);
+            acl.addEntry(ace.getPrincipal(), ace.getPrivileges(), ace.isAllow(), restrictions);
+            setNodeBasedAcl(path, tree, acl);
+        }
+
+        // remove entries that are not longer present in the acl to write
+        for (JackrabbitAccessControlEntry ace : toRemove) {
+            String path = getOakPath(ace.getRestriction(REP_NODE_PATH).getString());
+            Tree tree = getTree(path, Permissions.MODIFY_ACCESS_CONTROL);
+
+            ACL acl = (ACL) createACL(path, tree, false);
+            acl.removeAccessControlEntry(ace);
+            setNodeBasedAcl(path, tree, acl);
+        }
+    }
 
-            ACL acl = (ACL) policy;
-            for (JackrabbitAccessControlEntry ace : acl.getEntries()) {
-                writeACE(oakPath, aclNode, ace, restrictionProvider);
+    private void setNodeBasedAcl(@Nullable String oakPath, @Nonnull Tree tree,
+                                 @Nonnull ACL acl) throws RepositoryException {
+        NodeUtil aclNode = getAclNode(oakPath, tree);
+        if (aclNode != null) {
+            // remove all existing aces
+            for (Tree aceTree : aclNode.getTree().getChildren()) {
+                aceTree.remove();
             }
+        } else {
+            aclNode = createAclNode(oakPath, tree);
+        }
+        aclNode.getTree().setOrderableChildren(true);
+        for (JackrabbitAccessControlEntry ace : acl.getEntries()) {
+            writeACE(oakPath, aclNode, ace, restrictionProvider);
         }
     }
 
@@ -280,16 +293,21 @@ public class AccessControlManagerImpl im
             PrincipalACL principalAcl = (PrincipalACL) policy;
             for (JackrabbitAccessControlEntry ace : principalAcl.getEntries()) {
                 String path = getOakPath(ace.getRestriction(REP_NODE_PATH).getString());
-                Tree tree = getTree(path, Permissions.MODIFY_ACCESS_CONTROL);
-                NodeUtil aclNode = checkNotNull(getAclNode(oakPath, tree));
-
-                Iterator<Tree> children = aclNode.getTree().getChildren().iterator();
+                NodeUtil aclNode = getAclNode(path, getTree(path, Permissions.MODIFY_ACCESS_CONTROL));
+                if (aclNode == null) {
+                    throw new AccessControlException("Unable to retrieve policy node at " + path);
+                }
+                Tree aclTree = aclNode.getTree();
+                Iterator<Tree> children = aclTree.getChildren().iterator();
                 while (children.hasNext()) {
                     Tree child = children.next();
                     if (ace.equals(createACE(path, child, principalAcl.rProvider))) {
                         child.remove();
                     }
                 }
+                if (!aclTree.getChildren().iterator().hasNext()) {
+                    aclTree.remove();
+                }
             }
         } else {
             Tree tree = getTree(oakPath, Permissions.MODIFY_ACCESS_CONTROL);
@@ -480,10 +498,10 @@ public class AccessControlManagerImpl im
     }
 
     @CheckForNull
-    private AccessControlList createACL(@Nullable String oakPath,
-                                        @Nullable Tree accessControlledTree,
-                                        boolean isReadOnly) throws RepositoryException {
-        AccessControlList acl = null;
+    private JackrabbitAccessControlList createACL(@Nullable String oakPath,
+                                                  @Nullable Tree accessControlledTree,
+                                                  boolean isReadOnly) throws RepositoryException {
+        JackrabbitAccessControlList acl = null;
         String aclName = getAclName(oakPath);
         String mixinName = getMixinName(oakPath);
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/PrincipalRestrictionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/PrincipalRestrictionProvider.java?rev=1470950&r1=1470949&r2=1470950&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/PrincipalRestrictionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/PrincipalRestrictionProvider.java Tue Apr 23 13:40:21 2013
@@ -26,6 +26,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.security.AccessControlException;
 
+import com.google.common.collect.Sets;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
@@ -63,7 +64,12 @@ public class PrincipalRestrictionProvide
     @Nonnull
     @Override
     public Restriction createRestriction(@Nullable String oakPath, @Nonnull String jcrName, @Nonnull Value value) throws RepositoryException {
-        return base.createRestriction(oakPath, jcrName, value);
+        String oakName = namePathMapper.getOakName(jcrName);
+        if (REP_NODE_PATH.equals(oakName) && PropertyType.PATH == value.getType()) {
+            return new RestrictionImpl(PropertyStates.createProperty(oakName, value), true, namePathMapper);
+        } else {
+            return base.createRestriction(oakPath, jcrName, value);
+        }
     }
 
     @Override
@@ -77,7 +83,7 @@ public class PrincipalRestrictionProvide
 
     @Override
     public void writeRestrictions(String oakPath, Tree aceTree, Set<Restriction> restrictions) throws AccessControlException {
-        Iterator<Restriction> it = restrictions.iterator();
+        Iterator<Restriction> it = Sets.newHashSet(restrictions).iterator();
         while (it.hasNext()) {
             Restriction r = it.next();
             if (REP_NODE_PATH.equals(r.getName())) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java?rev=1470950&r1=1470949&r2=1470950&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java Tue Apr 23 13:40:21 2013
@@ -74,13 +74,13 @@ public class RestrictionProviderImpl imp
     @Override
     public Restriction createRestriction(String oakPath, String jcrName, Value value) throws RepositoryException {
         if (isUnsupportedPath(oakPath)) {
-            throw new AccessControlException("Unsupported restriction: " + oakPath);
+            throw new AccessControlException("Unsupported restriction at " + oakPath);
         }
 
         String oakName = namePathMapper.getOakName(jcrName);
         RestrictionDefinition definition = supported.get(oakName);
         if (definition == null) {
-            throw new AccessControlException("Unsupported restriction: " + oakPath);
+            throw new AccessControlException("Unsupported restriction: " + oakName);
         }
         int requiredType = definition.getRequiredType();
         if (requiredType != PropertyType.UNDEFINED && requiredType != value.getType()) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java?rev=1470950&r1=1470949&r2=1470950&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java Tue Apr 23 13:40:21 2013
@@ -20,6 +20,7 @@ import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -30,6 +31,7 @@ import javax.annotation.Nullable;
 import javax.jcr.AccessDeniedException;
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
@@ -45,6 +47,7 @@ import com.google.common.collect.Immutab
 import com.google.common.collect.ImmutableSet;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.oak.TestNameMapper;
@@ -1564,8 +1567,91 @@ public class AccessControlManagerImplTes
     }
 
     //-----------------------------------------------< setPrincipalPolicy() >---
-    // TODO
+    @Test
+    public void testSetPrincipalPolicy() throws Exception {
+        JackrabbitAccessControlPolicy[] applicable = acMgr.getApplicablePolicies(testPrincipal);
+        assertNotNull(applicable);
+        assertEquals(1, applicable.length);
+        assertTrue(applicable[0] instanceof ACL);
+
+        ACL acl = (ACL) applicable[0];
+        Value pathValue = getValueFactory().createValue(testPath, PropertyType.PATH);
+        assertTrue(acl.addEntry(testPrincipal, testPrivileges, true, Collections.singletonMap(REP_NODE_PATH, pathValue)));
+        acMgr.setPolicy(acl.getPath(), acl);
+        root.commit();
+
+        Root root2 = adminSession.getLatestRoot();
+        AccessControlPolicy[] policies = getAccessControlManager(root2).getPolicies(testPath);
+        assertEquals(1, policies.length);
+        assertEquals(1, ((ACL) policies[0]).getAccessControlEntries().length);
+
+        policies = getAccessControlManager(root2).getPolicies(testPrincipal);
+        assertEquals(1, policies.length);
+        assertArrayEquals(acl.getAccessControlEntries(), ((ACL) policies[0]).getAccessControlEntries());
+    }
+
+    @Test
+    public void testSetPrincipalPolicy2() throws Exception {
+        setupPolicy(testPath);
+        root.commit();
+
+        JackrabbitAccessControlPolicy[] policies = acMgr.getPolicies(testPrincipal);
+        assertNotNull(policies);
+        assertEquals(1, policies.length);
+        assertTrue(policies[0] instanceof ACL);
+
+        ACL acl = (ACL) policies[0];
+        Map<String, Value> restrictions = new HashMap<String, Value>();
+        restrictions.put(REP_NODE_PATH, getValueFactory().createValue(testPath, PropertyType.PATH));
+
+        assertTrue(acl.addEntry(testPrincipal, testPrivileges, true, restrictions));
+
+        restrictions.putAll(getGlobRestriction("*"));
+        assertFalse(acl.addEntry(testPrincipal, testPrivileges, true, restrictions));
+
+        acMgr.setPolicy(acl.getPath(), acl);
+        assertEquals(2, ((ACL) acMgr.getPolicies(testPath)[0]).getAccessControlEntries().length);
+    }
 
     //--------------------------------------------< removePrincipalPolicy() >---
-    // TODO
+
+    @Test
+    public void testRemovePrincipalPolicy() throws Exception {
+        JackrabbitAccessControlPolicy[] applicable = acMgr.getApplicablePolicies(testPrincipal);
+        assertNotNull(applicable);
+        assertEquals(1, applicable.length);
+        assertTrue(applicable[0] instanceof ACL);
+
+        ACL acl = (ACL) applicable[0];
+        Value pathValue = getValueFactory().createValue(testPath, PropertyType.PATH);
+        assertTrue(acl.addEntry(testPrincipal, testPrivileges, true, Collections.singletonMap(REP_NODE_PATH, pathValue)));
+        acMgr.setPolicy(acl.getPath(), acl);
+        root.commit();
+
+        acMgr.removePolicy(acl.getPath(), acl);
+        root.commit();
+
+        assertEquals(0, acMgr.getPolicies(testPrincipal).length);
+        assertEquals(0, acMgr.getPolicies(testPath).length);
+    }
+
+    @Test
+    public void testRemovePrincipalPolicy2() throws Exception {
+        setupPolicy(testPath);
+        root.commit();
+
+        AccessControlPolicy[] policies = acMgr.getPolicies(testPrincipal);
+        assertNotNull(policies);
+        assertEquals(1, policies.length);
+        assertTrue(policies[0] instanceof ACL);
+
+        ACL acl = (ACL) policies[0];
+        acMgr.removePolicy(acl.getPath(), acl);
+
+        policies = acMgr.getPolicies(testPath);
+        assertEquals(0, policies.length);
+
+        policies = acMgr.getPolicies(testPrincipal);
+        assertEquals(0, policies.length);
+    }
 }