| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.sling.jcr.repoinit; |
| |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import javax.jcr.AccessDeniedException; |
| import javax.jcr.Node; |
| import javax.jcr.PathNotFoundException; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.Session; |
| import javax.jcr.nodetype.NodeTypeManager; |
| import javax.jcr.nodetype.NodeTypeTemplate; |
| import javax.jcr.security.Privilege; |
| |
| import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; |
| import org.apache.sling.jcr.repoinit.impl.TestUtil; |
| import org.apache.sling.repoinit.parser.RepoInitParsingException; |
| import org.apache.sling.testing.mock.sling.ResourceResolverType; |
| import org.apache.sling.testing.mock.sling.junit.SlingContext; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Ignore; |
| import org.junit.Rule; |
| import org.junit.Test; |
| |
| /** Various ACL-related tests */ |
| public class GeneralAclTest { |
| |
| @Rule |
| public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK); |
| |
| private TestUtil U; |
| private String userA; |
| private String userB; |
| |
| private Session s; |
| |
| @Before |
| public void setup() throws RepositoryException, RepoInitParsingException { |
| U = new TestUtil(context); |
| userA = "userA_" + U.id; |
| userB = "userB_" + U.id; |
| U.parseAndExecute("create service user " + U.username); |
| U.parseAndExecute("create service user " + userA); |
| U.parseAndExecute("create service user " + userB); |
| |
| s = U.loginService(U.username); |
| } |
| |
| @After |
| public void cleanup() throws RepositoryException, RepoInitParsingException { |
| U.cleanupUser(); |
| s.logout(); |
| } |
| |
| @Test(expected=AccessDeniedException.class) |
| public void getRootNodeIntiallyFails() throws Exception { |
| s.getRootNode(); |
| } |
| |
| @Test |
| public void readOnlyThenWriteThenDeny() throws Exception { |
| final Node tmp = U.adminSession.getRootNode().addNode("tmp_" + U.id); |
| U.adminSession.save(); |
| final String path = tmp.getPath(); |
| |
| try { |
| s.getNode(path); |
| fail("Expected read access to be initially denied:" + path); |
| } catch(PathNotFoundException ignore) { |
| } |
| |
| final String allowRead = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:read on " + path + "\n" |
| + "end" |
| ; |
| U.parseAndExecute(allowRead); |
| final Node n = s.getNode(path); |
| |
| try { |
| n.setProperty("U.id", U.id); |
| s.save(); |
| fail("Expected write access to be initially denied:" + path); |
| } catch(AccessDeniedException ignore) { |
| } |
| s.refresh(false); |
| |
| final String allowWrite = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:write on " + path + "\n" |
| + "end" |
| ; |
| U.parseAndExecute(allowWrite); |
| n.setProperty("U.id", U.id); |
| s.save(); |
| |
| final String deny = |
| "set ACL for " + U.username + "\n" |
| + "deny jcr:all on " + path + "\n" |
| + "end" |
| ; |
| U.parseAndExecute(deny); |
| try { |
| s.getNode(path); |
| fail("Expected access to be denied again:" + path); |
| } catch(PathNotFoundException ignore) { |
| } |
| } |
| |
| @Test |
| public void addChildAtRoot() throws Exception { |
| final String nodename = "test_" + U.id; |
| final String path = "/" + nodename; |
| |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:all on /\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| try { |
| assertFalse(s.itemExists(path)); |
| s.getRootNode().addNode(nodename); |
| s.save(); |
| assertTrue(s.nodeExists(path)); |
| s.getNode(path).remove(); |
| s.save(); |
| assertFalse(s.itemExists(path)); |
| } finally { |
| s.logout(); |
| } |
| } |
| |
| @Test |
| public void addPathAclWithRepositoryPath() throws Exception { |
| final String aclSetup = |
| "set ACL on :repository\n" |
| + "allow jcr:namespaceManagement for "+U.username+"\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| try { |
| s.refresh(false); |
| assertTrue(s.getAccessControlManager().hasPrivileges(null, AccessControlUtils.privilegesFromNames(s, "jcr:namespaceManagement"))); |
| } finally { |
| s.logout(); |
| } |
| } |
| |
| @Test |
| public void addPrincipalAclWithRepositoryPath() throws Exception { |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:all on :repository,/\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| try { |
| s.refresh(false); |
| assertTrue(s.getAccessControlManager().hasPrivileges(null, AccessControlUtils.privilegesFromNames(s, Privilege.JCR_ALL))); |
| assertTrue(s.getAccessControlManager().hasPrivileges("/", AccessControlUtils.privilegesFromNames(s, Privilege.JCR_ALL))); |
| } finally { |
| s.logout(); |
| } |
| } |
| |
| @Test |
| public void addRepositoryAcl() throws Exception { |
| final String aclSetup = |
| "set repository ACL for " + userA + "," + userB + "\n" |
| + "allow jcr:namespaceManagement\n" |
| + "allow jcr:nodeTypeDefinitionManagement\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| verifyRegisterNamespace(userA, "a", "http://a", true); |
| verifyRegisterNamespace(userB, "b", "http://b", true); |
| verifyRegisterNamespace(U.username, "c", "http://c", false); |
| verifyRegisterNodeType(userA, "typeA", true); |
| verifyRegisterNodeType(userB, "typeB", true); |
| verifyRegisterNodeType(U.username, "typeC", false); |
| } |
| |
| @Test |
| public void addRepositoryAclInMultipleBlocks() throws Exception { |
| final String aclSetup = |
| "set repository ACL for " + userA + "\n" |
| + "allow jcr:namespaceManagement,jcr:nodeTypeDefinitionManagement\n" |
| + "end\n" |
| + "set repository ACL for " + userB + "\n" |
| + "allow jcr:namespaceManagement\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| verifyRegisterNamespace(userA, "a", "http://a", true); |
| verifyRegisterNamespace(userB, "b", "http://b", true); |
| verifyRegisterNodeType(userA, "typeA", true); |
| verifyRegisterNodeType(userB, "typeB", false); |
| } |
| |
| @Test |
| public void addRepositoryAclInSequence() throws Exception { |
| final String aclSetup = |
| "set repository ACL for " + U.username + "\n" |
| + "deny jcr:namespaceManagement,jcr:nodeTypeDefinitionManagement\n" |
| + "allow jcr:namespaceManagement,jcr:nodeTypeDefinitionManagement\n" |
| + "end\n" |
| + "set repository ACL for " + U.username + "\n" |
| + "deny jcr:namespaceManagement\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| verifyRegisterNodeType(U.username, "typeC", true); |
| verifyRegisterNamespace(U.username, "c", "http://c", false); |
| } |
| |
| /** |
| * Verify the success/failure when registering a node type. |
| * Registering a node type requires to be granted the jcr:nodeTypeDefinitionManagement privilege. |
| */ |
| private void verifyRegisterNodeType(String username, String typeName, boolean successExpected) { |
| Session userSession = null; |
| try { |
| userSession = U.loginService(username); |
| NodeTypeManager nodeTypeManager = userSession.getWorkspace().getNodeTypeManager(); |
| NodeTypeTemplate type = nodeTypeManager.createNodeTypeTemplate(); |
| type.setName(typeName); |
| nodeTypeManager.registerNodeType(type, true); |
| assertTrue("Register node type succeeded " + typeName, successExpected); |
| } catch (RepositoryException e) { |
| assertTrue("Error registering node type " + typeName + " " + e.getMessage(), !successExpected); |
| } finally { |
| if (userSession != null) { |
| userSession.logout(); |
| } |
| } |
| } |
| |
| |
| /** |
| * Verify the success/failure when registering a namespace. |
| * Registering a namespace successfully requires to be granted the jcr:namespaceManagement privilege. |
| */ |
| private void verifyRegisterNamespace(String username, String prefix, String uri, boolean successExpected) { |
| Session userSession = null; |
| try { |
| userSession = U.loginService(username); |
| userSession.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri); |
| assertTrue("Register namespace succeeded " + prefix + uri, successExpected); |
| } catch (RepositoryException e) { |
| assertTrue("Error registering namespace " + prefix + uri + " " + e.getMessage(), !successExpected); |
| } finally { |
| if (userSession != null) { |
| userSession.logout(); |
| } |
| } |
| } |
| |
| /** |
| * Verifies success/failure of adding a child |
| * @param username |
| * @param nodeName |
| * @param successExpected |
| * @throws RepositoryException |
| */ |
| private void verifyAddChildNode(String username,String nodeName, boolean successExpected) throws RepositoryException { |
| Session userSession = U.loginService(username); |
| try { |
| verifyAddChildNode(userSession,nodeName,successExpected); |
| } finally { |
| if(userSession != null) { |
| userSession.logout(); |
| } |
| } |
| } |
| |
| /** |
| * Verifies success/failure of adding a child |
| */ |
| private void verifyAddChildNode(Session userSession, String nodeName, boolean successExpected) throws RepositoryException{ |
| Node rootNode = userSession.getRootNode(); |
| verifyAddChildNode(rootNode, nodeName, successExpected); |
| } |
| |
| /** |
| * Verifies success/failure of adding a child |
| */ |
| private void verifyAddChildNode(Node node, String nodeName, boolean successExpected) throws RepositoryException{ |
| try { |
| node.addNode(nodeName); |
| node.getSession().save(); |
| assertTrue("Added child node succeeded "+nodeName,successExpected); |
| } catch(Exception e) { |
| node.getSession().refresh(false); |
| assertTrue("Error adding " + nodeName + " to " + node + e.getMessage(), !successExpected); |
| } |
| } |
| |
| /** |
| * Verifies success/failure of adding a properties |
| * @param username |
| * @param nodeName |
| * @param propertyName |
| * @param successExpected |
| * @throws RepositoryException |
| */ |
| private void verifyAddProperty(String username,String nodeName,String propertyName, boolean successExpected) throws RepositoryException { |
| Session userSession = U.loginService(username); |
| try { |
| verifyAddProperty(userSession, nodeName, propertyName, successExpected); |
| } finally { |
| if(userSession != null) { |
| userSession.logout(); |
| } |
| } |
| } |
| |
| /** |
| * Verifies success/failure of adding a properties |
| * @param userSession |
| * @param nodeName |
| * @param propertyName |
| * @param successExpected |
| * @throws RepositoryException |
| */ |
| private void verifyAddProperty(Session userSession,String relativePath,String propertyName,boolean successExpected) throws RepositoryException{ |
| try { |
| final Node n = userSession.getNode("/" + relativePath); |
| n.setProperty(propertyName,"test"); |
| userSession.save(); |
| assertTrue("Expected setProperty " + propertyName + " to fail on " + relativePath, successExpected); |
| } catch(RepositoryException e) { |
| userSession.refresh(false); // remove changes causing failure |
| assertFalse( |
| "Expected setProperty " + propertyName + " to to succeed on " + relativePath + " but got " + e.getMessage(), |
| successExpected); |
| } |
| } |
| |
| /** |
| * Verifies that a node is readable |
| */ |
| private void verifyCanRead(Session userSession, String relativePath, boolean successExpected) { |
| final String path = "/" + relativePath; |
| Node n = null; |
| try { |
| n = userSession.getNode(path); |
| assertTrue("Not expecting " + path + " to be readable but it was successfully read", successExpected); |
| } catch(RepositoryException notReadable) { |
| assertFalse("Expecting " + path + " to be readable but could not read it", successExpected); |
| } |
| } |
| |
| /** |
| * Verifies that ACEs for existing principal are replaced |
| */ |
| @Test |
| @Ignore("SLING-6423 - ACLOptions processing is not implemented yet") |
| public void mergeMode_ReplaceExistingPrincipalTest() throws Exception { |
| final String initialAclSetup = |
| " set ACL for " + userA + "\n" |
| + "allow jcr:read,jcr:addChildNodes on / \n" |
| + "end" |
| ; |
| |
| final String aclsToBeMerged = |
| " set ACL for " + userA + " (ACLOptions=merge)\n" |
| + "allow jcr:read on / \n" |
| + "allow jcr:modifyProperties on / \n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(initialAclSetup); |
| // verify that setup is correct |
| verifyAddChildNode(userA, "A1_" + U.id, true); // add node should succeed |
| verifyAddProperty(userA,"A1_"+U.id,"Prop1",false); // add property should fail |
| |
| //now merge acls |
| U.parseAndExecute(aclsToBeMerged); |
| |
| //verify merged ACLs |
| verifyAddChildNode(userA, "A2_" + U.id, false); // add node should fail |
| verifyAddProperty(userA,"A1_"+U.id,"prop2",true);// add property should succeed |
| |
| } |
| |
| |
| /** |
| * Verify that ACLs for new principal are added |
| * @throws Exception |
| */ |
| @Test |
| @Ignore("SLING-6423 - ACLOptions processing is not implemented yet") |
| public void mergeMode_AddAceTest() throws Exception { |
| final String initialAclSetup = |
| "set ACL for " + userA + "\n" |
| + "allow jcr:read,jcr:write on /\n" |
| + "end \n" |
| ; |
| |
| // userA,jcr:write ACE will be removed, |
| // userB ACE will be added |
| final String aclsToBeMerged = |
| "set ACL on / (ACLOptions=merge) \n" |
| + "allow jcr:read for " + userA + "\n" |
| + "allow jcr:read,jcr:write for " + userB + "\n" |
| + "end \n" |
| ; |
| |
| U.parseAndExecute(initialAclSetup); |
| // verify that setup is correct |
| verifyAddChildNode(userA, "A1_" + U.id, true); |
| verifyAddChildNode(userB, "B1_" + U.id, false); |
| //now merge acls |
| U.parseAndExecute(aclsToBeMerged); |
| |
| //verify merged ACLs |
| verifyAddChildNode(userA, "A2_" + U.id, false); |
| verifyAddChildNode(userB, "B2_" + U.id, true); |
| |
| } |
| |
| /** |
| * Verify that ACEs for unspecified principal are preserved |
| * @throws Exception |
| */ |
| @Test |
| @Ignore("SLING-6423 - ACLOptions processing is not implemented yet") |
| public void mergeMode_PreserveAceTest() throws Exception { |
| final String initialAclSetup = |
| "set ACL on / \n" |
| + "allow jcr:read,jcr:write for " + userA + "\n" |
| + "allow jcr:read,jcr:write for " + userB + "\n" |
| + "end \n" |
| ; |
| |
| // userB ACE will be preserved |
| final String aclsToBeMerged = |
| "set ACL on / (ACLOptions=merge) \n" |
| + "allow jcr:read for " + userA + "\n" |
| + "end \n" |
| ; |
| |
| U.parseAndExecute(initialAclSetup); |
| // verify that setup is correct |
| verifyAddChildNode(userA, "A1_" + U.id, true); |
| verifyAddChildNode(userB, "B1_" + U.id, true); |
| |
| //now merge acls |
| U.parseAndExecute(aclsToBeMerged); |
| |
| //verify merged ACLs |
| verifyAddChildNode(userA, "A2_" + U.id, false); |
| verifyAddChildNode(userB, "B2_" + U.id, true); |
| |
| } |
| |
| |
| /** |
| * Verifiy that ACE for non-existing principal are added |
| * @throws Exception |
| */ |
| @Test |
| @Ignore("SLING-6423 - ACLOptions processing is not implemented yet") |
| public void mergePreserveMode_AddAceTest() throws Exception{ |
| final String initialAclSetup = |
| " set ACL for " + userB + "\n" |
| + "allow jcr:read,jcr:write on /\n" |
| + "end \n" |
| ; |
| |
| final String aclsToBeMerged = |
| "set ACL for " + userA + " (ACLOptions=mergePreserve)\n" |
| + "allow jcr:read,jcr:write on / \n" |
| + "end \n" |
| ; |
| |
| U.parseAndExecute(initialAclSetup); |
| // verify that setup is correct |
| verifyAddChildNode(userA, "A1_" + U.id, false); |
| verifyAddChildNode(userB, "B1_" + U.id, true); |
| |
| //now merge acls |
| U.parseAndExecute(aclsToBeMerged); |
| |
| //verify merged ACLs |
| verifyAddChildNode(userA, "A2_" + U.id, true); |
| verifyAddChildNode(userB, "B2_" + U.id, true); |
| } |
| |
| |
| /** |
| * Verify that ACE for existing principal are ignored |
| * @throws Exception |
| */ |
| @Test |
| @Ignore("SLING-6423 - ACLOptions processing is not implemented yet") |
| public void mergePreserveMode_IgnoreAceTest() throws Exception { |
| final String initialAclSetup = |
| "set ACL for " + userA + "\n" |
| + "allow jcr:read,jcr:addChildNodes on /\n" |
| + "end" |
| ; |
| |
| final String aclsToBeMerged = |
| " set ACL for " + userA + " (ACLOptions=mergePreserve) \n" |
| + "allow jcr:read,jcr:modifyProperties on / \n" |
| + "end \n" |
| ; |
| |
| U.parseAndExecute(initialAclSetup); |
| // verify that setup is correct |
| verifyAddChildNode(userA, "A1_" + U.id, true); // add node should succeed |
| verifyAddProperty(userA, "A1_" + U.id, "Prop1", false); // add property should fail |
| |
| //now merge acls |
| U.parseAndExecute(aclsToBeMerged); |
| |
| //verify merged ACLs |
| verifyAddChildNode(userA, "A2_" + U.id, true); // add node should succeed |
| verifyAddProperty(userA, "A2_" + U.id, "Prop1", false); // add property should fail |
| } |
| |
| |
| /** |
| * Verify that ACE for unspecified principal are preserved |
| * @throws Exception |
| */ |
| @Test |
| @Ignore("SLING-6423 - ACLOptions processing is not implemented yet") |
| public void mergePreserveMode_PreserveAceTest() throws Exception { |
| final String initialAclSetup = |
| " set ACL on /\n" |
| + "allow jcr:read, jcr:write for " + userA + " , " + userB + "\n" |
| + "end \n" |
| ; |
| |
| // ACL for userA will be ignored but added for userB |
| final String aclsToBeMerged = |
| " set ACL for " + userA + " (ACLOptions=mergePreserve) \n" |
| + "allow jcr:read on / \n" |
| + "end \n" |
| ; |
| |
| U.parseAndExecute(initialAclSetup); |
| // verify that setup is correct |
| verifyAddChildNode(userA, "A1_" + U.id, true); |
| verifyAddChildNode(userB, "B1_" + U.id, true); |
| |
| //now merge acls |
| U.parseAndExecute(aclsToBeMerged); |
| |
| //verify merged ACLs |
| verifyAddChildNode(userA, "A2_" + U.id, true); |
| verifyAddChildNode(userB, "B2_" + U.id, true); |
| } |
| |
| /** |
| * Tests use of glob restriction in set ACL |
| * @throws Exception |
| */ |
| @Test |
| public void globRestrictionTest() throws Exception { |
| |
| final String allowedNodeName = "testxyz_" + U.id; |
| final String notAllowedNodeName = "testabc_" + U.id; |
| |
| U.adminSession.getRootNode().addNode(allowedNodeName); |
| U.adminSession.getRootNode().addNode(notAllowedNodeName); |
| U.adminSession.save(); |
| |
| |
| final String nodeName = "test_" + U.id; |
| |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:all on / \n" |
| + "deny jcr:addChildNodes on / restriction(rep:glob,*abc*)\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| |
| try { |
| verifyAddChildNode(s.getRootNode().getNode(allowedNodeName), nodeName, true); |
| verifyAddChildNode(s.getRootNode().getNode(notAllowedNodeName), nodeName, false); |
| |
| } finally { |
| s.logout(); |
| } |
| } |
| |
| |
| /** |
| * Tests use of rep:itemNames restriction in set ACL |
| * @throws Exception |
| */ |
| @Test |
| public void itemNamesRestrictionTest() throws Exception { |
| final String nodename = "test_" + U.id; |
| final String propName = "test2_" + U.id; |
| |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:all on / \n" |
| + "deny jcr:modifyProperties on / restriction(rep:itemNames,"+propName+")\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| |
| try { |
| |
| verifyAddChildNode(s, nodename, true); |
| verifyAddProperty(s, nodename, "someotherproperty", true); |
| verifyAddProperty(s, nodename, propName, false); // adding property propName should fail |
| |
| } finally { |
| s.logout(); |
| } |
| } |
| |
| /** |
| * Tests default merging of acls with restrictions |
| * @throws Exception |
| */ |
| @Test |
| public void multiRestrictionMergeTest() throws Exception { |
| final String nodeName = "test_" + U.id; |
| final String nodeName2 = "test2_" + U.id; |
| final String nodeName3 = "test3_" + U.id; |
| final String propName = "propName" + U.id; |
| |
| |
| U.adminSession.getRootNode().addNode(nodeName); |
| U.adminSession.getRootNode().addNode(nodeName2); |
| U.adminSession.getRootNode().addNode(nodeName3); |
| U.adminSession.save(); |
| |
| |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:all on / \n" |
| + "deny jcr:addChildNodes on / restriction(rep:glob,"+nodeName2+")\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| |
| final String aclSetup2 = |
| "set ACL for " + U.username + "\n" |
| + "deny jcr:addChildNodes on / restriction(rep:glob,"+nodeName3+")\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup2); |
| |
| final String aclSetup3 = |
| "set ACL for " + U.username + "\n" |
| + "deny jcr:modifyProperties on / restriction(rep:itemNames,"+propName+")\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup3); |
| |
| try { |
| |
| // now verify add child nodes perm |
| |
| verifyAddChildNode(s.getRootNode().getNode(nodeName), nodeName, true); |
| |
| verifyAddChildNode(s.getRootNode().getNode(nodeName2), nodeName, false); |
| verifyAddChildNode(s.getRootNode().getNode(nodeName3), nodeName, false); |
| |
| // verify property restriction |
| verifyAddProperty(s, nodeName, "someotherproperty", true); |
| verifyAddProperty(s, nodeName, propName, false); // adding property propName should fail |
| |
| } finally { |
| s.logout(); |
| } |
| } |
| |
| |
| @Test |
| public void emptyRestrictionTest() throws Exception { |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "allow jcr:all on / \n" |
| + "deny jcr:modifyProperties on / restriction(rep:itemNames)\n" |
| + "end" |
| ; |
| U.parseAndExecute(aclSetup); |
| } |
| |
| /** |
| * Tests empty rep:glob restriction which actually does something useful |
| * @throws Exception |
| */ |
| @Test |
| public void emptyGlobRestrictionTest() throws Exception { |
| final String parentName = "empty_glob_" + U.id; |
| final String childName = "child"; |
| final String childPath = parentName + "/" + childName; |
| |
| try { |
| U.adminSession.getRootNode().addNode(parentName).addNode(childName); |
| U.adminSession.save(); |
| |
| // Allow for reading the parent node but not its children with an empty glob restriction |
| // as per https://jackrabbit.apache.org/oak/docs/security/authorization/restriction.html |
| final String aclSetup = |
| "set ACL for " + U.username + "\n" |
| + "deny jcr:read on /\n" |
| + "allow jcr:read on /" + parentName + " restriction (rep:glob)\n" |
| + "end" |
| ; |
| |
| U.parseAndExecute(aclSetup); |
| |
| // Verify read access with a non-admin session opened with U.username |
| verifyCanRead(s, parentName, true); |
| verifyCanRead(s, childPath, false); |
| |
| } finally { |
| s.logout(); |
| } |
| } |
| } |