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]>.
