You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:48:09 UTC

[sling-org-apache-sling-jcr-jackrabbit-accessmanager] 05/24: SLING-1411 Add replaceAccessControlEntry method to AccessControlUtil Thanks to Ray Davis for the contribution.

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.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-accessmanager.git

commit 533a4bad82a9402b1526c9d8d9de94f0ff60793d
Author: Eric Norman <en...@apache.org>
AuthorDate: Sat Feb 27 02:02:09 2010 +0000

    SLING-1411 Add replaceAccessControlEntry method to AccessControlUtil
    Thanks to Ray Davis for the contribution.
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/jackrabbit-accessmanager@916893 13f79535-47bb-0310-9956-ffa450edef68
---
 .../accessmanager/post/ModifyAceServlet.java       | 370 +++------------------
 1 file changed, 44 insertions(+), 326 deletions(-)

diff --git a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
index 432387e..d9e998a 100644
--- a/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
+++ b/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java
@@ -16,8 +16,15 @@
  */
 package org.apache.sling.jcr.jackrabbit.accessmanager.post;
 
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.servlets.post.Modification;
+
 import java.security.Principal;
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
@@ -26,31 +33,16 @@ import java.util.Set;
 import javax.jcr.Item;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.AccessControlList;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.Privilege;
-
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceNotFoundException;
-import org.apache.sling.api.servlets.HtmlResponse;
-import org.apache.sling.jcr.base.util.AccessControlUtil;
-import org.apache.sling.servlets.post.Modification;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * <p>
- * Sling Post Servlet implementation for modifying the ACE for a principal on a JCR
+ * Sling Post Servlet implementation for modifying the ACEs for a principal on a JCR
  * resource.
  * </p>
  * <h2>Rest Service Description</h2>
  * <p>
- * Delete a set of Ace's from a node, the node is identified as a resource by the request
- * url &gt;resource&lt;.modifyAce.html
+ * Modify a principal's ACEs for the node identified as a resource by the request
+ * URL &gt;resource&lt;.modifyAce.html
  * </p>
  * <h4>Methods</h4>
  * <ul>
@@ -59,11 +51,11 @@ import org.slf4j.LoggerFactory;
  * <h4>Post Parameters</h4>
  * <dl>
  * <dt>principalId</dt>
- * <dd>The principal of the Ace to modify in the ACL specified by the path.</dd>
+ * <dd>The principal of the ACEs to modify in the ACL specified by the path.</dd>
  * <dt>privilege@*</dt>
- * <dd>One of more privileges, either granted or denied, where set the permission in the
- * stored ACE is modified to match the request. Any permissions that are present in the
- * stored ACE, but are not in the request are left untouched.</dd>
+ * <dd>One or more privileges, either granted or denied or none, which will be applied
+ * to (or removed from) the node ACL. Any permissions that are present in an
+ * existing ACE for the principal but not in the request are left untouched.</dd>
  * </dl>
  *
  * <h4>Response</h4>
@@ -92,11 +84,6 @@ import org.slf4j.LoggerFactory;
 public class ModifyAceServlet extends AbstractAccessPostServlet {
 	private static final long serialVersionUID = -9182485466670280437L;
 
-	/**
-     * default log
-     */
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
 	/* (non-Javadoc)
 	 * @see org.apache.sling.jackrabbit.accessmanager.post.AbstractAccessPostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.api.servlets.HtmlResponse, java.util.List)
 	 */
@@ -113,88 +100,25 @@ public class ModifyAceServlet extends AbstractAccessPostServlet {
 		if (principalId == null) {
 			throw new RepositoryException("principalId was not submitted.");
 		}
-		UserManager userManager = AccessControlUtil.getUserManager(session);
-		Authorizable authorizable = userManager.getAuthorizable(principalId);
-		if (authorizable == null) {
-			throw new RepositoryException("No principal found for id: " + principalId);
-		}
-
-    	String resourcePath = null;
-    	Resource resource = request.getResource();
-    	if (resource == null) {
+		PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session);
+		Principal principal = principalManager.getPrincipal(principalId);
+		String resourcePath = null;
+		Resource resource = request.getResource();
+		if (resource == null) {
 			throw new ResourceNotFoundException("Resource not found.");
-    	} else {
-    		Item item = resource.adaptTo(Item.class);
-    		if (item != null) {
-    			resourcePath = item.getPath();
-    		} else {
-    			throw new ResourceNotFoundException("Resource is not a JCR Node");
-    		}
-    	}
-
-		try {
-			AccessControlManager accessControlManager = AccessControlUtil.getAccessControlManager(session);
-
-			//SLING-997: keep track of the privilege names that were posted, so the others can be preserved
-			PrivilegesState privilegesInfo = new PrivilegesState(log.isDebugEnabled());
-			
-			//calculate which privileges were POSTed.
-			collectPostedPrivilegeNames(request, 
-					accessControlManager,
-					privilegesInfo);	
-
-			//find the existing ACL
-			AccessControlList updatedAcl = getAccessControlList(accessControlManager, resourcePath, true);
-
-			//keep track of the existing ACEs for the target principal
-			List<AccessControlEntry> oldAces = processExistingAccessControlEntries(resourcePath, 
-					authorizable, 
-					accessControlManager, 
-					updatedAcl, 
-					privilegesInfo); 
-			
-			//remove the old ACEs.  Re-created below.
-			if (!oldAces.isEmpty()) {
-				for (AccessControlEntry ace : oldAces) {
-					updatedAcl.removeAccessControlEntry(ace);
-				}
+		} else {
+			Item item = resource.adaptTo(Item.class);
+			if (item != null) {
+				resourcePath = item.getPath();
+			} else {
+				throw new ResourceNotFoundException("Resource is not a JCR Node");
 			}
-			
-			//re-aggregate the granted/denied privileges into the best matched aggregate privilege
-			reaggregatePrivileges(resourcePath,
-					accessControlManager,
-					privilegesInfo);
-			
-			//add fresh ACEs with the granted privileges
-			buildFreshAccessControlEntries(authorizable, 
-					accessControlManager, 
-					updatedAcl, 
-					privilegesInfo);
-			
-			//store the updated ACL
-			accessControlManager.setPolicy(resourcePath, updatedAcl);
-			if (session.hasPendingChanges()) {
-				session.save();
-			}
-
-			if (log.isDebugEnabled()) {
-				log.debug("Updated ACE for principalId {0} for resource {1) from {2} to {3}", new Object [] {
-						authorizable.getID(), resourcePath, privilegesInfo.oldPrivileges.toString(), privilegesInfo.newPrivileges.toString()
-				});
-			}
-		} catch (RepositoryException re) {
-			throw new RepositoryException("Failed to create ace.", re);
 		}
-	}
-
-
-	/**
-	 * Collect the privileges to assign from the http request.
-	 */
-	private void collectPostedPrivilegeNames(SlingHttpServletRequest request,
-			AccessControlManager accessControlManager,
-			PrivilegesState privilegesInfo) throws RepositoryException {
-
+    
+		// Collect the modified privileges from the request.
+		Set<String> grantedPrivilegeNames = new HashSet<String>();
+		Set<String> deniedPrivilegeNames = new HashSet<String>();
+		Set<String> removedPrivilegeNames = new HashSet<String>();
 		Enumeration<?> parameterNames = request.getParameterNames();
 		while (parameterNames.hasMoreElements()) {
 			Object nextElement = parameterNames.nextElement();
@@ -202,237 +126,31 @@ public class ModifyAceServlet extends AbstractAccessPostServlet {
 				String paramName = (String)nextElement;
 				if (paramName.startsWith("privilege@")) {
 					String privilegeName = paramName.substring(10);
-					//keep track of which privileges should be changed
-					privilegesInfo.postedPrivilegeNames.add(privilegeName); 
-					
 					String parameterValue = request.getParameter(paramName);
 					if (parameterValue != null && parameterValue.length() > 0) {
 						if ("granted".equals(parameterValue)) {
-							Privilege privilege = accessControlManager.privilegeFromName(privilegeName);
-							if (privilege.isAggregate()) {
-								Privilege[] aggregatePrivileges = privilege.getAggregatePrivileges();
-								for (Privilege privilege2 : aggregatePrivileges) {
-									privilegesInfo.grantedPrivilegeNames.add(privilege2.getName());
-								}
-							} else {
-								privilegesInfo.grantedPrivilegeNames.add(privilegeName);
-							}
+							grantedPrivilegeNames.add(privilegeName);
 						} else if ("denied".equals(parameterValue)) {
-							Privilege privilege = accessControlManager.privilegeFromName(privilegeName);
-							if (privilege.isAggregate()) {
-								Privilege[] aggregatePrivileges = privilege.getAggregatePrivileges();
-								for (Privilege privilege2 : aggregatePrivileges) {
-									privilegesInfo.deniedPrivilegeNames.add(privilege2.getName());
-								}
-							} else {
-								privilegesInfo.deniedPrivilegeNames.add(privilegeName);
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	/**
-	 * Process the existing ACL to determine which privileges to preserve.
-	 */
-	private List<AccessControlEntry> processExistingAccessControlEntries(
-			String resourcePath,
-			Authorizable authorizable,
-			AccessControlManager accessControlManager,
-			AccessControlList updatedAcl,
-			PrivilegesState privilegesInfo) throws RepositoryException {
-		
-		String principalId = authorizable.getPrincipal().getName();
-		AccessControlEntry[] accessControlEntries = updatedAcl.getAccessControlEntries();
-		List<AccessControlEntry> oldAces = new ArrayList<AccessControlEntry>();
-		for (AccessControlEntry ace : accessControlEntries) {
-			if (principalId.equals(ace.getPrincipal().getName())) {
-				if (log.isDebugEnabled()) {
-					log.debug("Found Existing ACE for principal {0} on resource: ", new Object[] {principalId, resourcePath});
-				}
-				oldAces.add(ace);
-
-				boolean isAllow = AccessControlUtil.isAllow(ace);
-				Privilege[] privileges = ace.getPrivileges();
-
-				//build a list of (merged and expanded) privileges 
-				Set<Privilege> mergedExistingPrivileges = new HashSet<Privilege>();
-				for (Privilege privilege : privileges) {
-					if (privilege.isAggregate()) {
-						Privilege[] aggregatePrivileges = privilege.getAggregatePrivileges();
-						for (Privilege privilege2 : aggregatePrivileges) {
-							mergedExistingPrivileges.add(privilege2);
-						}
-					} else {
-						mergedExistingPrivileges.add(privilege);
-					}
-				}
-				
-				//now process the merged privileges set
-				for (Privilege privilege : mergedExistingPrivileges) {
-					String privilegeName = privilege.getName();
-					if (!privilegesInfo.postedPrivilegeNames.contains(privilegeName)) {
-						//this privilege was not posted, so record the existing state to be 
-						// preserved when the ACE is re-created below
-						if (isAllow) {
-							privilegesInfo.grantedPrivilegeNames.add(privilegeName);
-						} else {
-							privilegesInfo.deniedPrivilegeNames.add(privilegeName);
-						}
-					}
-
-					if (log.isDebugEnabled()) {
-						//collect the information for debug logging
-						if (privilegesInfo.oldPrivileges.length() > 0) {
-							privilegesInfo.oldPrivileges.append(", "); //separate entries by commas
-						}
-						if (isAllow) {
-							privilegesInfo.oldPrivileges.append("granted=");
+							deniedPrivilegeNames.add(privilegeName);
 						} else {
-							privilegesInfo.oldPrivileges.append("denied=");
+							removedPrivilegeNames.add(privilegeName);
 						}
-						privilegesInfo.oldPrivileges.append(privilege.getName());
-					}
-				}
-			}
-		}
-		
-		return oldAces;
-	}
-	
-	/**
-	 * Given the set of granted/denied privileges, try to combine them
-	 * into the best aggregate Privilege that contains them all.
-	 */
-	private void reaggregatePrivileges(
-			String resourcePath,
-			AccessControlManager accessControlManager,
-			PrivilegesState privilegesInfo) throws RepositoryException {
-		Privilege[] supportedPrivileges = accessControlManager.getSupportedPrivileges(resourcePath);
-		for (Privilege privilege : supportedPrivileges) {
-			if (privilege.isAggregate()) {
-				boolean grantedAggregatePrivilege = true;
-				boolean deniedAggregatePrivilege = true;
-				Privilege[] aggregatePrivileges = privilege.getAggregatePrivileges();
-				for (Privilege privilege2 : aggregatePrivileges) {
-					String name = privilege2.getName();
-					if (!privilegesInfo.grantedPrivilegeNames.contains(name)) {
-						grantedAggregatePrivilege = false;
-					}
-					if (!privilegesInfo.deniedPrivilegeNames.contains(name)) {
-						deniedAggregatePrivilege = false;
-					}
-				}
-				
-				if (grantedAggregatePrivilege) {
-					//add the aggregate privilege and remove the containing parts
-					privilegesInfo.grantedPrivilegeNames.add(privilege.getName());
-					for (Privilege privilege2 : aggregatePrivileges) {
-						String name = privilege2.getName();
-						privilegesInfo.grantedPrivilegeNames.remove(name);
-					}						
-				}
-
-				if (deniedAggregatePrivilege) {
-					//add the aggregate privilege and remove the containing parts
-					privilegesInfo.deniedPrivilegeNames.add(privilege.getName());
-					for (Privilege privilege2 : aggregatePrivileges) {
-						String name = privilege2.getName();
-						privilegesInfo.deniedPrivilegeNames.remove(name);
-					}						
-				}
-			}
-		}
-	}
-	
-	/**
-	 * Create new ACE for the granted and denied privileges.
-	 */
-	private void buildFreshAccessControlEntries(
-			Authorizable authorizable,
-			AccessControlManager accessControlManager,			
-			AccessControlList updatedAcl,
-			PrivilegesState privilegesInfo) throws RepositoryException {
-		List<Privilege> grantedPrivilegeList = new ArrayList<Privilege>();
-		for (String name : privilegesInfo.grantedPrivilegeNames) {
-			if (name.length() == 0) {
-				continue; //empty, skip it.
-			}
-			Privilege privilege = accessControlManager.privilegeFromName(name);
-			grantedPrivilegeList.add(privilege);
-		}
-		
-		if (log.isDebugEnabled()) {
-			for (Privilege privilege : grantedPrivilegeList) {
-				if (privilegesInfo.newPrivileges.length() > 0) {
-					privilegesInfo.newPrivileges.append(", "); //separate entries by commas
-				}
-				privilegesInfo.newPrivileges.append("granted=");
-				privilegesInfo.newPrivileges.append(privilege.getName());
-			}				
-		}
-
-		if (grantedPrivilegeList.size() > 0) {
-			Principal principal = authorizable.getPrincipal();
-			updatedAcl.addAccessControlEntry(principal, grantedPrivilegeList.toArray(new Privilege[grantedPrivilegeList.size()]));
-		}
-
-		//if the authorizable is a user (not a group) process any denied privileges
-		if (!authorizable.isGroup()) {
-			//add a fresh ACE with the denied privileges
-			List<Privilege> deniedPrivilegeList = new ArrayList<Privilege>();
-			for (String name : privilegesInfo.deniedPrivilegeNames) {
-				if (name.length() == 0) {
-					continue; //empty, skip it.
-				}
-				Privilege privilege = accessControlManager.privilegeFromName(name);
-				deniedPrivilegeList.add(privilege);
-			}
-			
-			if (log.isDebugEnabled()) {
-				for (Privilege privilege : deniedPrivilegeList) {
-					if (privilegesInfo.newPrivileges.length() > 0) {
-						privilegesInfo.newPrivileges.append(", "); //separate entries by commas
 					}
-					privilegesInfo.newPrivileges.append("denied=");
-					privilegesInfo.newPrivileges.append(privilege.getName());
 				}
 			}
-			
-			if (deniedPrivilegeList.size() > 0) {
-				Principal principal = authorizable.getPrincipal();
-				AccessControlUtil.addEntry(updatedAcl, principal, deniedPrivilegeList.toArray(new Privilege[deniedPrivilegeList.size()]), false);
-			}
 		}
-	}
-	
-	/**
-	 * Contains the information about the privilege state as it 
-	 * progresses through the update process. 
-	 */
-	private static class PrivilegesState {
-		//stores the names of the privileges that were POSTed
-		Set<String> postedPrivilegeNames = new HashSet<String>();
-		
-		//stores the names of the privileges to be granted 
-		Set<String> grantedPrivilegeNames = new HashSet<String>();
-
-		//stores the names of the privileges to be denied 
-		Set<String> deniedPrivilegeNames = new HashSet<String>();
-
-		//collects debug information about the previous privileges
-		StringBuilder oldPrivileges = null;
-		
-		//collects debug information about the new privileges
-		StringBuilder newPrivileges = null;
 
-		public PrivilegesState(boolean isDebugEnabled) {
-			if (isDebugEnabled) {
-				oldPrivileges = new StringBuilder();
-				newPrivileges = new StringBuilder();
+		// Make the actual changes.
+		try {
+			AccessControlUtil.replaceAccessControlEntry(session, resourcePath, principal,
+					grantedPrivilegeNames.toArray(new String[grantedPrivilegeNames.size()]),
+					deniedPrivilegeNames.toArray(new String[deniedPrivilegeNames.size()]),
+					removedPrivilegeNames.toArray(new String[removedPrivilegeNames.size()]));
+			if (session.hasPendingChanges()) {
+				session.save();
 			}
+		} catch (RepositoryException re) {
+			throw new RepositoryException("Failed to create ace.", re);
 		}
 	}
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.