Author: enorman Date: Wed Feb 24 04:44:43 2010 New Revision: 915670 URL: http://svn.apache.org/viewvc?rev=915670&view=rev Log: SLING-997 handle merges involving aggregate privileges properly
Modified: sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java Modified: sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java?rev=915670&r1=915669&r2=915670&view=diff ============================================================================== --- sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java (original) +++ sling/trunk/bundles/jcr/jackrabbit-accessmanager/src/main/java/org/apache/sling/jcr/jackrabbit/accessmanager/post/ModifyAceServlet.java Wed Feb 24 04:44:43 2010 @@ -100,7 +100,6 @@ /* (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) */ - @SuppressWarnings("unchecked") @Override protected void handleOperation(SlingHttpServletRequest request, HtmlResponse htmlResponse, List<Modification> changes) @@ -133,12 +132,70 @@ } } + try { + AccessControlManager accessControlManager = AccessControlUtil.getAccessControlManager(session); - List<String> grantedPrivilegeNames = new ArrayList<String>(); - List<String> deniedPrivilegeNames = new ArrayList<String>(); - //SLING-997: keep track of the privilege names that were posted, so the others can be preserved - Set<String> postedPrivilegeNames = new HashSet<String>(); - Enumeration parameterNames = request.getParameterNames(); + //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); + } + } + + //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 { + + Enumeration<?> parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { Object nextElement = parameterNames.nextElement(); if (nextElement instanceof String) { @@ -146,144 +203,236 @@ if (paramName.startsWith("privilege@")) { String privilegeName = paramName.substring(10); //keep track of which privileges should be changed - postedPrivilegeNames.add(privilegeName); + privilegesInfo.postedPrivilegeNames.add(privilegeName); String parameterValue = request.getParameter(paramName); if (parameterValue != null && parameterValue.length() > 0) { if ("granted".equals(parameterValue)) { - grantedPrivilegeNames.add(privilegeName); + 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); + } } else if ("denied".equals(parameterValue)) { - deniedPrivilegeNames.add(privilegeName); + 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); - try { - AccessControlManager accessControlManager = AccessControlUtil.getAccessControlManager(session); - AccessControlList updatedAcl = getAccessControlList(accessControlManager, resourcePath, true); - - StringBuilder oldPrivileges = null; - StringBuilder newPrivileges = null; - if (log.isDebugEnabled()) { - oldPrivileges = new StringBuilder(); - newPrivileges = new StringBuilder(); - } + boolean isAllow = AccessControlUtil.isAllow(ace); + Privilege[] privileges = ace.getPrivileges(); - List<Privilege> preserveGrantedPrivileges = new ArrayList<Privilege>(); - List<Privilege> preserveDeniedPrivileges = new ArrayList<Privilege>(); - - //keep track of the existing Aces for the target principal - 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}); + //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); } - oldAces.add(ace); - - boolean isAllow = AccessControlUtil.isAllow(ace); - Privilege[] privileges = ace.getPrivileges(); - for (Privilege privilege : privileges) { - String privilegeName = privilege.getName(); - if (!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) { - preserveGrantedPrivileges.add(privilege); - } else { - preserveDeniedPrivileges.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 (oldPrivileges.length() > 0) { - oldPrivileges.append(", "); //separate entries by commas - } + 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="); + } else { + privilegesInfo.oldPrivileges.append("denied="); } + 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); + } + } - //remove the old aces - if (!oldAces.isEmpty()) { - for (AccessControlEntry ace : oldAces) { - updatedAcl.removeAccessControlEntry(ace); + 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()])); + } - //add a fresh ACE with the granted privileges - List<Privilege> grantedPrivilegeList = new ArrayList<Privilege>(); - for (String name : grantedPrivilegeNames) { + //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); - grantedPrivilegeList.add(privilege); + deniedPrivilegeList.add(privilege); } - //add the privileges that should be preserved - grantedPrivilegeList.addAll(preserveGrantedPrivileges); - + if (log.isDebugEnabled()) { - for (Privilege privilege : grantedPrivilegeList) { - if (newPrivileges.length() > 0) { - newPrivileges.append(", "); //separate entries by commas - } - newPrivileges.append("granted="); - 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 : deniedPrivilegeNames) { - if (name.length() == 0) { - continue; //empty, skip it. - } - Privilege privilege = accessControlManager.privilegeFromName(name); - deniedPrivilegeList.add(privilege); - } - //add the privileges that should be preserved - deniedPrivilegeList.addAll(preserveDeniedPrivileges); - - if (log.isDebugEnabled()) { - for (Privilege privilege : deniedPrivilegeList) { - if (newPrivileges.length() > 0) { - newPrivileges.append(", "); //separate entries by commas - } - newPrivileges.append("denied="); - newPrivileges.append(privilege.getName()); + for (Privilege privilege : deniedPrivilegeList) { + if (privilegesInfo.newPrivileges.length() > 0) { + privilegesInfo.newPrivileges.append(", "); //separate entries by commas } - } - - if (deniedPrivilegeList.size() > 0) { - Principal principal = authorizable.getPrincipal(); - AccessControlUtil.addEntry(updatedAcl, principal, deniedPrivilegeList.toArray(new Privilege[deniedPrivilegeList.size()]), false); + privilegesInfo.newPrivileges.append("denied="); + privilegesInfo.newPrivileges.append(privilege.getName()); } } - - accessControlManager.setPolicy(resourcePath, updatedAcl); - if (session.hasPendingChanges()) { - session.save(); + + 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; - if (log.isDebugEnabled()) { - log.debug("Updated ACE for principalId {0} for resource {1) from {2} to {3}", new Object [] { - authorizable.getID(), resourcePath, oldPrivileges.toString(), newPrivileges.toString() - }); + public PrivilegesState(boolean isDebugEnabled) { + if (isDebugEnabled) { + oldPrivileges = new StringBuilder(); + newPrivileges = new StringBuilder(); } - } catch (RepositoryException re) { - throw new RepositoryException("Failed to create ace.", re); } } } Modified: sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java?rev=915670&r1=915669&r2=915670&view=diff ============================================================================== --- sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java (original) +++ sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java Wed Feb 24 04:44:43 2010 @@ -243,5 +243,197 @@ assertTrue(deniedPrivilegeNames2.contains("jcr:modifyAccessControl")); assertTrue(deniedPrivilegeNames2.contains("jcr:removeNode")); } + + + /** + * Test for SLING-997, preserve privileges that were not posted with the modifyAce + * request. + */ + public void testMergeAceForUserSplitAggregatePrincipal() throws IOException, JSONException { + testUserId = createTestUser(); + testFolderUrl = createTestFolder(); + + String postUrl = testFolderUrl + ".modifyAce.html"; + + //1. create an initial set of privileges + List<NameValuePair> postParams = new ArrayList<NameValuePair>(); + postParams.add(new NameValuePair("principalId", testUserId)); + postParams.add(new NameValuePair("privil...@jcr:read", "granted")); + postParams.add(new NameValuePair("privil...@jcr:write", "denied")); + + Credentials creds = new UsernamePasswordCredentials("admin", "admin"); + assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null); + + //fetch the JSON for the acl to verify the settings. + String getUrl = testFolderUrl + ".acl.json"; + + String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK); + assertNotNull(json); + JSONObject jsonObj = new JSONObject(json); + String aceString = jsonObj.getString(testUserId); + assertNotNull(aceString); + + JSONObject aceObject = new JSONObject(aceString); + assertNotNull(aceObject); + + JSONArray grantedArray = aceObject.getJSONArray("granted"); + assertNotNull(grantedArray); + assertEquals(1, grantedArray.length()); + Set<String> grantedPrivilegeNames = new HashSet<String>(); + for (int i=0; i < grantedArray.length(); i++) { + grantedPrivilegeNames.add(grantedArray.getString(i)); + } + assertTrue(grantedPrivilegeNames.contains("jcr:read")); + + JSONArray deniedArray = aceObject.getJSONArray("denied"); + assertNotNull(deniedArray); + assertEquals(1, deniedArray.length()); + Set<String> deniedPrivilegeNames = new HashSet<String>(); + for (int i=0; i < deniedArray.length(); i++) { + deniedPrivilegeNames.add(deniedArray.getString(i)); + } + assertTrue(deniedPrivilegeNames.contains("jcr:write")); + + + + //2. post a new set of privileges to merge with the existing privileges + List<NameValuePair> postParams2 = new ArrayList<NameValuePair>(); + postParams2.add(new NameValuePair("principalId", testUserId)); + //jcr:read is not posted, so it should remain in the granted ACE + postParams2.add(new NameValuePair("privil...@jcr:modifyProperties", "granted")); //add a new privilege + //jcr:write is not posted, but one of the aggregate privileges is now granted, so the aggregate priviledge should be disagreaged into + // the remaining denied privileges in the denied ACE + + assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams2, null); + + + //fetch the JSON for the acl to verify the settings. + String json2 = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK); + + assertNotNull(json2); + JSONObject jsonObj2 = new JSONObject(json2); + String aceString2 = jsonObj2.getString(testUserId); + assertNotNull(aceString2); + + JSONObject aceObject2 = new JSONObject(aceString2); + assertNotNull(aceObject2); + + JSONArray grantedArray2 = aceObject2.getJSONArray("granted"); + assertNotNull(grantedArray2); + assertEquals(2, grantedArray2.length()); + Set<String> grantedPrivilegeNames2 = new HashSet<String>(); + for (int i=0; i < grantedArray2.length(); i++) { + grantedPrivilegeNames2.add(grantedArray2.getString(i)); + } + assertTrue(grantedPrivilegeNames2.contains("jcr:read")); + assertTrue(grantedPrivilegeNames2.contains("jcr:modifyProperties")); + + JSONArray deniedArray2 = aceObject2.getJSONArray("denied"); + assertNotNull(deniedArray2); + assertEquals(3, deniedArray2.length()); + Set<String> deniedPrivilegeNames2 = new HashSet<String>(); + for (int i=0; i < deniedArray2.length(); i++) { + deniedPrivilegeNames2.add(deniedArray2.getString(i)); + } + assertFalse(deniedPrivilegeNames2.contains("jcr:write")); + //only the remaining privileges from the disaggregated jcr:write collection should remain. + assertTrue(deniedPrivilegeNames2.contains("jcr:addChildNodes")); + assertTrue(deniedPrivilegeNames2.contains("jcr:removeNode")); + assertTrue(deniedPrivilegeNames2.contains("jcr:removeChildNodes")); + } + + /** + * Test for SLING-997, preserve privileges that were not posted with the modifyAce + * request. + */ + public void testMergeAceForUserCombineAggregatePrincipal() throws IOException, JSONException { + testUserId = createTestUser(); + testFolderUrl = createTestFolder(); + + String postUrl = testFolderUrl + ".modifyAce.html"; + + //1. create an initial set of privileges + List<NameValuePair> postParams = new ArrayList<NameValuePair>(); + postParams.add(new NameValuePair("principalId", testUserId)); + postParams.add(new NameValuePair("privil...@jcr:read", "granted")); + postParams.add(new NameValuePair("privil...@jcr:removeNode", "denied")); + + Credentials creds = new UsernamePasswordCredentials("admin", "admin"); + assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null); + + //fetch the JSON for the acl to verify the settings. + String getUrl = testFolderUrl + ".acl.json"; + + String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK); + assertNotNull(json); + JSONObject jsonObj = new JSONObject(json); + String aceString = jsonObj.getString(testUserId); + assertNotNull(aceString); + + JSONObject aceObject = new JSONObject(aceString); + assertNotNull(aceObject); + + JSONArray grantedArray = aceObject.getJSONArray("granted"); + assertNotNull(grantedArray); + assertEquals(1, grantedArray.length()); + Set<String> grantedPrivilegeNames = new HashSet<String>(); + for (int i=0; i < grantedArray.length(); i++) { + grantedPrivilegeNames.add(grantedArray.getString(i)); + } + assertTrue(grantedPrivilegeNames.contains("jcr:read")); + + JSONArray deniedArray = aceObject.getJSONArray("denied"); + assertNotNull(deniedArray); + assertEquals(1, deniedArray.length()); + Set<String> deniedPrivilegeNames = new HashSet<String>(); + for (int i=0; i < deniedArray.length(); i++) { + deniedPrivilegeNames.add(deniedArray.getString(i)); + } + assertTrue(deniedPrivilegeNames.contains("jcr:removeNode")); + + + + //2. post a new set of privileges to merge with the existing privileges + List<NameValuePair> postParams2 = new ArrayList<NameValuePair>(); + postParams2.add(new NameValuePair("principalId", testUserId)); + //jcr:read is not posted, so it should remain in the granted ACE + + //post the remaining privileges that when combined, correspond to the jcr:write aggregate privilege + postParams2.add(new NameValuePair("privil...@jcr:addChildNodes", "denied")); //add a new privilege + postParams2.add(new NameValuePair("privil...@jcr:removeChildNodes", "denied")); //add a new privilege + postParams2.add(new NameValuePair("privil...@jcr:modifyProperties", "denied")); //add a new privilege + + assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams2, null); + + + //fetch the JSON for the acl to verify the settings. + String json2 = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK); + + assertNotNull(json2); + JSONObject jsonObj2 = new JSONObject(json2); + String aceString2 = jsonObj2.getString(testUserId); + assertNotNull(aceString2); + + JSONObject aceObject2 = new JSONObject(aceString2); + assertNotNull(aceObject2); + + JSONArray grantedArray2 = aceObject2.getJSONArray("granted"); + assertNotNull(grantedArray2); + assertEquals(1, grantedArray2.length()); + Set<String> grantedPrivilegeNames2 = new HashSet<String>(); + for (int i=0; i < grantedArray2.length(); i++) { + grantedPrivilegeNames2.add(grantedArray2.getString(i)); + } + assertTrue(grantedPrivilegeNames2.contains("jcr:read")); + + JSONArray deniedArray2 = aceObject2.getJSONArray("denied"); + assertNotNull(deniedArray2); + assertEquals(1, deniedArray2.length()); + Set<String> deniedPrivilegeNames2 = new HashSet<String>(); + for (int i=0; i < deniedArray2.length(); i++) { + deniedPrivilegeNames2.add(deniedArray2.getString(i)); + } + assertTrue(deniedPrivilegeNames2.contains("jcr:write")); + } }