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

rombert pushed a commit to annotated tag 
org.apache.sling.jcr.jackrabbit.accessmanager-2.1.2
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-accessmanager.git

commit 06bac528ce94682af6294603f584e6ec323d63bf
Author: Eric Norman <[email protected]>
AuthorDate: Thu Oct 11 04:12:29 2012 +0000

    SLING-2600 Attempt #2. Effective ACL servlet returns incorrect information. 
 Merge the information from the applicable access control entries to produce 
the eacl JSON output.  + a few unit tests
    
    git-svn-id: 
https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/jackrabbit-accessmanager@1396899
 13f79535-47bb-0310-9956-ffa450edef68
---
 .../accessmanager/post/AbstractGetAclServlet.java  | 147 ++++++++++++++++++---
 1 file changed, 132 insertions(+), 15 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
 
b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
index 8e87e7f..6b04f86 100644
--- 
a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
+++ 
b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/AbstractGetAclServlet.java
@@ -19,6 +19,9 @@ package org.apache.sling.jcr.jackrabbit.accessmanager.post;
 import java.io.IOException;
 import java.security.Principal;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -31,6 +34,7 @@ import javax.jcr.Item;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.Privilege;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
@@ -111,9 +115,29 @@ public abstract class AbstractGetAclServlet extends 
SlingAllMethodsServlet {
                        throw new ResourceNotFoundException("Resource is not a 
JCR Node");
                }
 
+               // Calculate a map of privileges to all the aggregate 
privileges it is contained in.
+               // Use for fast lookup during the mergePrivilegeSets calls 
below.
+        AccessControlManager accessControlManager = 
AccessControlUtil.getAccessControlManager(jcrSession);
+               Map<Privilege, Set<Privilege>> privilegeToAncestorMap = new 
HashMap<Privilege, Set<Privilege>>();
+        Privilege[] supportedPrivileges = 
accessControlManager.getSupportedPrivileges(item.getPath());
+        for (Privilege privilege : supportedPrivileges) {
+                       if (privilege.isAggregate()) {
+                               Privilege[] ap = 
privilege.getAggregatePrivileges();
+                               for (Privilege privilege2 : ap) {
+                                       Set<Privilege> set = 
privilegeToAncestorMap.get(privilege2);
+                                       if (set == null) {
+                                               set = new HashSet<Privilege>();
+                                               
privilegeToAncestorMap.put(privilege2, set);
+                                       }
+                                       set.add(privilege);
+                               }
+                       }
+               }
+
         AccessControlEntry[] declaredAccessControlEntries = 
getAccessControlEntries(jcrSession, resourcePath);
         Map<String, Map<String, Object>> aclMap = new LinkedHashMap<String, 
Map<String,Object>>();
-            int sequence = 0;
+        int sequence = 0;
+
         for (AccessControlEntry ace : declaredAccessControlEntries) {
             Principal principal = ace.getPrincipal();
             Map<String, Object> map = aclMap.get(principal.getName());
@@ -122,27 +146,39 @@ public abstract class AbstractGetAclServlet extends 
SlingAllMethodsServlet {
                 aclMap.put(principal.getName(), map);
                 map.put("order", sequence++);
             }
+        }
+        //evaluate these in reverse order so the most entries with highest 
specificity are last
+        for (int i = declaredAccessControlEntries.length - 1; i >= 0; i--) {
+                       AccessControlEntry ace = 
declaredAccessControlEntries[i];
+
+                       Principal principal = ace.getPrincipal();
+            Map<String, Object> map = aclMap.get(principal.getName());
+                       
+            Set<Privilege> grantedSet = (Set<Privilege>) map.get("granted");
+            if (grantedSet == null) {
+                grantedSet = new LinkedHashSet<Privilege>();
+                map.put("granted", grantedSet);
+            }
+            Set<Privilege> deniedSet = (Set<Privilege>) map.get("denied");
+            if (deniedSet == null) {
+                deniedSet = new LinkedHashSet<Privilege>();
+                map.put("denied", deniedSet);
+            }
 
             boolean allow = AccessControlUtil.isAllow(ace);
             if (allow) {
-                Set<String> grantedSet = (Set<String>) map.get("granted");
-                if (grantedSet == null) {
-                    grantedSet = new LinkedHashSet<String>();
-                    map.put("granted", grantedSet);
-                }
                 Privilege[] privileges = ace.getPrivileges();
                 for (Privilege privilege : privileges) {
-                    grantedSet.add(privilege.getName());
+                       mergePrivilegeSets(privilege, 
+                                       privilegeToAncestorMap,
+                                                       grantedSet, deniedSet);
                 }
             } else {
-                Set<String> deniedSet = (Set<String>) map.get("denied");
-                if (deniedSet == null) {
-                    deniedSet = new LinkedHashSet<String>();
-                    map.put("denied", deniedSet);
-                }
                 Privilege[] privileges = ace.getPrivileges();
                 for (Privilege privilege : privileges) {
-                    deniedSet.add(privilege.getName());
+                       mergePrivilegeSets(privilege, 
+                                       privilegeToAncestorMap,
+                                                       deniedSet, grantedSet);
                 }
             }
         }
@@ -157,12 +193,12 @@ public abstract class AbstractGetAclServlet extends 
SlingAllMethodsServlet {
             aceObject.put("principal", principalName);
 
             Set<String> grantedSet = (Set<String>) value.get("granted");
-            if (grantedSet != null) {
+            if (grantedSet != null && !grantedSet.isEmpty()) {
                 aceObject.put("granted", grantedSet);
             }
 
             Set<String> deniedSet = (Set<String>) value.get("denied");
-            if (deniedSet != null) {
+            if (deniedSet != null && !deniedSet.isEmpty()) {
                 aceObject.put("denied", deniedSet);
             }
             aceObject.put("order", value.get("order"));
@@ -175,6 +211,87 @@ public abstract class AbstractGetAclServlet extends 
SlingAllMethodsServlet {
         
         return jsonAclMap;
     }
+
+       /**
+        * Update the granted and denied privilege sets by merging the result 
of adding
+        * the supplied privilege.
+        */
+       private void mergePrivilegeSets(Privilege privilege,
+                       Map<Privilege, Set<Privilege>> privilegeToAncestorMap,
+                       Set<Privilege> firstSet, Set<Privilege> secondSet) {
+               //1. remove duplicates and invalid privileges from the list
+               if (privilege.isAggregate()) {
+                       Privilege[] aggregatePrivileges = 
privilege.getAggregatePrivileges();
+                       //remove duplicates from the granted set
+                       List<Privilege> asList = 
Arrays.asList(aggregatePrivileges);
+                       firstSet.removeAll(asList);
+                       
+                       //remove from the denied set
+                       secondSet.removeAll(asList);
+               }
+               secondSet.remove(privilege);
+
+               //2. check if the privilege is already contained in another 
granted privilege
+               boolean isAlreadyGranted = false;
+               Set<Privilege> ancestorSet = 
privilegeToAncestorMap.get(privilege);
+               if (ancestorSet != null) {
+                       for (Privilege privilege2 : ancestorSet) {
+                               if (firstSet.contains(privilege2)) {
+                                       isAlreadyGranted = true;
+                                       break;
+                               }
+                       }
+               }
+
+               //3. add the privilege
+               if (!isAlreadyGranted) {
+                   firstSet.add(privilege);
+               }
+
+               //4. Deal with expanding existing aggregate privileges to 
remove the invalid
+               //  items and add the valid ones.
+               Set<Privilege> filterSet = 
privilegeToAncestorMap.get(privilege);
+               if (filterSet != null) {        
+               //re-pack the denied set to compensate 
+               for (Privilege privilege2 : filterSet) {
+                       if (secondSet.contains(privilege2)) {
+                               secondSet.remove(privilege2);
+                               if (privilege2.isAggregate()) {
+                                       
filterAndMergePrivilegesFromAggregate(privilege2, 
+                                                       firstSet, secondSet, 
filterSet, privilege);
+                               }
+                       }
+                       }
+               }
+       }
+
+       /**
+        * Add all the declared aggregate privileges from the supplied 
privilege to the secondSet
+        * unless the privilege is already in the firstSet and not contained in 
the supplied filterSet.
+        */
+       private void filterAndMergePrivilegesFromAggregate(Privilege privilege, 
Set<Privilege> firstSet,
+                       Set<Privilege> secondSet, Set<Privilege> filterSet, 
Privilege ignorePrivilege) {
+               Privilege[] declaredAggregatePrivileges = 
privilege.getDeclaredAggregatePrivileges();
+               for (Privilege privilege3 : declaredAggregatePrivileges) {
+                       if (ignorePrivilege.equals(privilege3)) {
+                               continue; //skip it.
+                       }
+                       if (!firstSet.contains(privilege3) && 
!filterSet.contains(privilege3)) {
+                               secondSet.add(privilege3);
+                       }
+                       if (privilege3.isAggregate()) {
+                               Privilege[] declaredAggregatePrivileges2 = 
privilege3.getDeclaredAggregatePrivileges();
+                               for (Privilege privilege2 : 
declaredAggregatePrivileges2) {
+                                       if 
(!ignorePrivilege.equals(privilege2)) {
+                                               if (privilege2.isAggregate()) {
+                                                       
filterAndMergePrivilegesFromAggregate(privilege2, 
+                                                                       
firstSet, secondSet, filterSet, ignorePrivilege);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
     
     protected abstract AccessControlEntry[] getAccessControlEntries(Session 
session, String absPath) throws RepositoryException;
 

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to