This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.jcr.repoinit-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-repoinit.git
commit d7a5f83fda7e92c420a387cffc938059a3726fda Author: Bertrand Delacretaz <bdelacre...@apache.org> AuthorDate: Wed Dec 23 11:00:28 2015 +0000 SLING-5355 - AclOperationVisitor partially implemented, and webconsole plugin added git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/acldef/oak-jcr@1721521 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 24 ++- .../sling/acldef/jcr/AclOperationVisitor.java | 39 +++- .../java/org/apache/sling/acldef/jcr/AclUtil.java | 65 +++++++ .../apache/sling/acldef/jcr/ServiceUserUtil.java | 4 + .../jcr/webconsole/OakAclDefConsolePlugin.java | 203 +++++++++++++++++++++ src/main/resources/ui/acldef.css | 20 ++ .../sling/acldef/jcr/NonExistentPathTest.java | 70 +++++++ .../sling/acldef/jcr/RootAddChildNodeTest.java | 126 +++++++++++++ .../java/org/apache/sling/acldef/jcr/TestUtil.java | 12 +- 9 files changed, 554 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 31eda7e..e0a4b01 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,10 @@ Applies ACLs to an Oak JCR repository based on the output of the ACL Definition Language parser. </description> + + <properties> + <jackrabbit.version>2.10.0</jackrabbit.version> + </properties> <scm> <connection>scm:svn: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/acldef/oak-jcr</connection> @@ -75,13 +79,29 @@ <dependency> <groupId>org.apache.jackrabbit</groupId> <artifactId>jackrabbit-api</artifactId> - <version>2.11.3</version> + <version>${jackrabbit.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.jackrabbit</groupId> <artifactId>jackrabbit-jcr-commons</artifactId> - <version>2.2.9</version> + <version>${jackrabbit.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.api</artifactId> + <version>2.4.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.jcr.api</artifactId> + <version>2.0.4</version> <scope>provided</scope> </dependency> <dependency> diff --git a/src/main/java/org/apache/sling/acldef/jcr/AclOperationVisitor.java b/src/main/java/org/apache/sling/acldef/jcr/AclOperationVisitor.java index 48ff05e..e4748ec 100644 --- a/src/main/java/org/apache/sling/acldef/jcr/AclOperationVisitor.java +++ b/src/main/java/org/apache/sling/acldef/jcr/AclOperationVisitor.java @@ -16,8 +16,15 @@ */ package org.apache.sling.acldef.jcr; +import static org.apache.sling.acldef.parser.ACLDefinitions.PROP_PATHS; +import static org.apache.sling.acldef.parser.ACLDefinitions.PROP_PRINCIPALS; +import static org.apache.sling.acldef.parser.ACLDefinitions.PROP_PRIVILEGES; + +import java.util.List; + import javax.jcr.Session; +import org.apache.sling.acldef.parser.operations.AclLine; import org.apache.sling.acldef.parser.operations.CreateServiceUser; import org.apache.sling.acldef.parser.operations.DeleteServiceUser; import org.apache.sling.acldef.parser.operations.OperationVisitor; @@ -70,13 +77,37 @@ public class AclOperationVisitor implements OperationVisitor { } } + private List<String> require(AclLine line, String propertyName) { + final List<String> result = line.getProperty(propertyName); + if(result == null) { + throw new IllegalStateException("Missing property " + propertyName + " on " + line); + } + return result; + } + + private void setAcl(AclLine line, Session s, List<String> principals, List<String> paths, List<String> privileges, boolean isAllow) { + try { + AclUtil.setAcl(s, principals, paths, privileges, isAllow); + } catch(Exception e) { + throw new RuntimeException("Failed to set ACL (" + e.getClass().getSimpleName() + ") " + line, e); + } + } + @Override public void visitSetAclPrincipal(SetAclPrincipals s) { - log.warn("TODO - set ACL for Principals"); - } + final List<String> principals = s.getPrincipals(); + for(AclLine line : s.getLines()) { + final boolean isAllow = line.getAction().equals(AclLine.Action.ALLOW); + setAcl(line, session, principals, require(line, PROP_PATHS), require(line, PROP_PRIVILEGES), isAllow); + } + } @Override public void visitSetAclPaths(SetAclPaths s) { - log.warn("TODO - set ACL for Paths"); + final List<String> paths = s.getPaths(); + for(AclLine line : s.getLines()) { + final boolean isAllow = line.getAction().equals(AclLine.Action.ALLOW); + setAcl(line, session, require(line, PROP_PRINCIPALS), paths, require(line, PROP_PRIVILEGES), isAllow); + } } -} +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/acldef/jcr/AclUtil.java b/src/main/java/org/apache/sling/acldef/jcr/AclUtil.java new file mode 100644 index 0000000..1a70be4 --- /dev/null +++ b/src/main/java/org/apache/sling/acldef/jcr/AclUtil.java @@ -0,0 +1,65 @@ +/* + * 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.acldef.jcr; + +import java.security.Principal; +import java.util.List; + +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; +import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager; +import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; + +/** Utilities for ACL management */ +public class AclUtil { + + public static JackrabbitAccessControlManager getJACM(Session s) throws UnsupportedRepositoryOperationException, RepositoryException { + final AccessControlManager acm = s.getAccessControlManager(); + if(!(acm instanceof JackrabbitAccessControlManager)) { + throw new IllegalStateException( + "AccessControlManager is not a JackrabbitAccessControlManager:" + + acm.getClass().getName()); + } + return (JackrabbitAccessControlManager) acm; + } + + public static void setAcl(Session s, List<String> principals, List<String> paths, List<String> privileges, boolean isAllow) + throws UnsupportedRepositoryOperationException, RepositoryException { + + final String [] privArray = privileges.toArray(new String[privileges.size()]); + final Privilege[] jcrPriv = AccessControlUtils.privilegesFromNames(s, privArray); + + + for(String path : paths) { + if(!s.nodeExists(path)) { + throw new PathNotFoundException("Cannot set ACL on non-existent path " + path); + } + JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(s, path); + for(String principal : principals) { + final Principal p = ServiceUserUtil.getAuthorizable(s, principal).getPrincipal(); + acl.addEntry(p, jcrPriv, isAllow); + } + getJACM(s).setPolicy(path, acl); + } + } +} diff --git a/src/main/java/org/apache/sling/acldef/jcr/ServiceUserUtil.java b/src/main/java/org/apache/sling/acldef/jcr/ServiceUserUtil.java index 265c7df..09b6426 100644 --- a/src/main/java/org/apache/sling/acldef/jcr/ServiceUserUtil.java +++ b/src/main/java/org/apache/sling/acldef/jcr/ServiceUserUtil.java @@ -33,6 +33,10 @@ public class ServiceUserUtil { return ((JackrabbitSession)session).getUserManager(); } + public static Authorizable getAuthorizable(Session session, String username) throws RepositoryException { + return getUserManager(session).getAuthorizable(username); + } + public static void createServiceUser(Session s, String username) throws RepositoryException { getUserManager(s).createSystemUser(username, null); } diff --git a/src/main/java/org/apache/sling/acldef/jcr/webconsole/OakAclDefConsolePlugin.java b/src/main/java/org/apache/sling/acldef/jcr/webconsole/OakAclDefConsolePlugin.java new file mode 100644 index 0000000..16d3ff3 --- /dev/null +++ b/src/main/java/org/apache/sling/acldef/jcr/webconsole/OakAclDefConsolePlugin.java @@ -0,0 +1,203 @@ +/* + * 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.acldef.jcr.webconsole; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.acldef.jcr.AclOperationVisitor; +import org.apache.sling.acldef.parser.ACLDefinitions; +import org.apache.sling.acldef.parser.ParseException; +import org.apache.sling.acldef.parser.operations.Operation; +import org.apache.sling.acldef.parser.operations.OperationVisitor; +import org.apache.sling.api.request.ResponseUtil; +import org.apache.sling.jcr.api.SlingRepository; +import org.osgi.framework.Constants; + +@Component +@Service(value=Servlet.class) +@Properties({ + @Property(name=Constants.SERVICE_VENDOR, value="The Apache Software Foundation"), + @Property(name=Constants.SERVICE_DESCRIPTION, value="Apache Sling ACL Definitions Console Plugin"), + @Property(name="felix.webconsole.label", value=OakAclDefConsolePlugin.LABEL), + @Property(name="felix.webconsole.title", value="Set ACLs"), + @Property(name="felix.webconsole.css", value="/" + OakAclDefConsolePlugin.LABEL + "/res/ui/acldef.css"), + @Property(name="felix.webconsole.category", value="Sling"), +}) +public class OakAclDefConsolePlugin extends HttpServlet { + + private static final long serialVersionUID = 1234; + private static final String PAR_ACLDEF = "acldef"; + private static final String PAR_MSG = "msg"; + public static final String LABEL = "setACL"; + private static final String ATTR_SUBMIT = "plugin.submit"; + private AtomicInteger counter = new AtomicInteger(); + + private static final String EXAMPLE = + "# Example ACL definition\n" + + "# (with service user creation commented out)\n" + + "# create service user test_42\n" + + "set ACL for test_42\n" + + " allow jcr:read,jcr:modifyProperties on /tmp\n" + + "end\n" + ; + + @Reference + private SlingRepository repository; + + private String thisPath(HttpServletRequest request) { + return request.getContextPath() + request.getServletPath() + request.getPathInfo(); + } + + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException { + String aclDef = request.getParameter(PAR_ACLDEF); + if(aclDef == null || aclDef.trim().length() == 0) { + aclDef = EXAMPLE; + } + + String msg = request.getParameter(PAR_MSG); + if(msg == null) { + msg = ""; + } + + final PrintWriter pw = response.getWriter(); + pw.println("<table class='content' cellpadding='0' cellspacing='0' width='100%'>"); + titleHtml( + pw, + "ACL definitions", + "To create service users or set ACLs, enter a valid statement below." + ); + + pw.println("<tr class='content'>"); + pw.print("<td class='content' colspan='3'>"); + pw.print("<form method='post' action='" + thisPath(request) + "'>"); + pw.print("<input type='submit' name='" + ATTR_SUBMIT + "' value='Execute' class='submit'>"); + pw.print("<div class='msg'>"); + pw.print(msg); + pw.println("</div>"); + pw.print("<textarea type='text' name='" + PAR_ACLDEF + "' class='input' cols='80' rows='25'>"); + pw.print(ResponseUtil.escapeXml(aclDef)); + pw.println("</textarea>"); + pw.print("</form>"); + pw.print("</td>"); + pw.println("</tr>"); + pw.println("</table>"); + } + + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + String aclDef = request.getParameter(PAR_ACLDEF); + String msg = "No ACL definitions executed"; + if(aclDef == null || aclDef.trim().length() == 0) { + aclDef = ""; + } else { + try { + setAcl(aclDef); + msg = "ACL definitions successfully executed"; + } catch(Exception e) { + throw new ServletException("Error setting ACLs:\n" + e.getMessage(), e); + } + } + msg += " (" + counter.incrementAndGet() + ")"; + + // Redirect to GET on the same page + final StringBuilder target = new StringBuilder(); + target + .append(thisPath(request)) + .append("?").append(PAR_ACLDEF).append("=").append(encodeParam(aclDef)) + .append("&").append(PAR_MSG).append("=").append(encodeParam(msg)) + ; + response.sendRedirect(target.toString()); + } + + private static String encodeParam(final String value) { + try { + return URLEncoder.encode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Unexpected UnsupportedEncodingException", e); + } + } + + private void setAcl(String aclDef) throws RepositoryException, IOException, ParseException { + final Reader r = new StringReader(aclDef); + Session s = null; + try { + s = repository.loginAdministrative(null); + final OperationVisitor v = new AclOperationVisitor(s); + for(Operation op : new ACLDefinitions(r).parse()) { + op.accept(v); + } + s.save(); + } finally { + r.close(); + if(s != null) { + s.logout(); + } + } + } + + private void titleHtml(PrintWriter pw, String title, String description) { + pw.print("<tr class='content'>"); + pw.print("<th colspan='3'class='content container'>"); + pw.print(ResponseUtil.escapeXml(title)); + pw.println("</th></tr>"); + + if (description != null) { + pw.print("<tr class='content'>"); + pw.print("<td colspan='3'class='content'>"); + pw.print(ResponseUtil.escapeXml(description)); + pw.println("</th></tr>"); + } + } + + /** + * Method to retrieve static resources from this bundle. + */ + @SuppressWarnings("unused") + private URL getResource(final String path) { + final String prefix = "/" + LABEL + "/res"; + if(path.startsWith(prefix + "/ui")) { + return this.getClass().getResource(path.substring(prefix.length())); + } + return null; + } +} diff --git a/src/main/resources/ui/acldef.css b/src/main/resources/ui/acldef.css new file mode 100644 index 0000000..9181889 --- /dev/null +++ b/src/main/resources/ui/acldef.css @@ -0,0 +1,20 @@ +/* + * 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. + */ + + .msg { color:blue; } +td { vertical-align: top; } +textarea { width:100%; } \ No newline at end of file diff --git a/src/test/java/org/apache/sling/acldef/jcr/NonExistentPathTest.java b/src/test/java/org/apache/sling/acldef/jcr/NonExistentPathTest.java new file mode 100644 index 0000000..184853d --- /dev/null +++ b/src/test/java/org/apache/sling/acldef/jcr/NonExistentPathTest.java @@ -0,0 +1,70 @@ +/* + * 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.acldef.jcr; + +import static org.junit.Assert.fail; +import static org.junit.Assert.assertEquals; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.sling.acldef.parser.ParseException; +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.Rule; +import org.junit.Test; + +/** Test setting ACLS on non-existent paths */ +public class NonExistentPathTest { + + @Rule + public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK); + + private TestUtil U; + private Session s; + + @Before + public void setup() throws ParseException, RepositoryException { + U = new TestUtil(context); + U.parseAndExecute("create service user " + U.username); + s = U.loginService(U.username); + } + + @After + public void cleanup() throws ParseException, RepositoryException { + U.parseAndExecute("delete service user " + U.username); + s.logout(); + } + + @Test + public void setAclOnFoo() throws Exception { + final String aclDef = + "set ACL on /foo_" + U.id + "\n" + + " allow jcr:all for " + U.username + "\n" + + "end" + ; + try { + U.parseAndExecute(aclDef); + fail("Expecting a wrapped PathNotFoundException"); + } catch(RuntimeException rux) { + assertEquals(PathNotFoundException.class, rux.getCause().getClass()); + } + } + +} diff --git a/src/test/java/org/apache/sling/acldef/jcr/RootAddChildNodeTest.java b/src/test/java/org/apache/sling/acldef/jcr/RootAddChildNodeTest.java new file mode 100644 index 0000000..63d5b3e --- /dev/null +++ b/src/test/java/org/apache/sling/acldef/jcr/RootAddChildNodeTest.java @@ -0,0 +1,126 @@ +/* + * 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.acldef.jcr; + +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 org.apache.sling.acldef.parser.ParseException; +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.Rule; +import org.junit.Test; + +/** Test root node and node creation privileges */ +public class RootAddChildNodeTest { + + @Rule + public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK); + + private TestUtil U; + private Session s; + + @Before + public void setup() throws ParseException, RepositoryException { + U = new TestUtil(context); + U.parseAndExecute("create service user " + U.username); + s = U.loginService(U.username); + } + + @After + public void cleanup() throws ParseException, RepositoryException { + U.parseAndExecute("delete service user " + U.username); + s.logout(); + } + + @Test(expected=AccessDeniedException.class) + public void getRootNodeFails() throws Exception { + s.getRootNode(); + } + + @Test + public void readOnlyThenWrite() 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 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(); + } + + @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(); + } + } +} diff --git a/src/test/java/org/apache/sling/acldef/jcr/TestUtil.java b/src/test/java/org/apache/sling/acldef/jcr/TestUtil.java index c07dd21..70d5533 100644 --- a/src/test/java/org/apache/sling/acldef/jcr/TestUtil.java +++ b/src/test/java/org/apache/sling/acldef/jcr/TestUtil.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertNull; import java.io.Reader; import java.io.StringReader; import java.util.List; +import java.util.UUID; import javax.jcr.RepositoryException; import javax.jcr.Session; @@ -39,9 +40,13 @@ import org.apache.sling.testing.mock.sling.junit.SlingContext; class TestUtil { final Session adminSession; + final String id; + final String username; TestUtil(SlingContext ctx) { - adminSession = ctx.resourceResolver().adaptTo(Session.class); + adminSession = ctx.resourceResolver().adaptTo(Session.class); + id = UUID.randomUUID().toString(); + username = "user_" + id; } List<Operation> parse(String input) throws ParseException { @@ -64,14 +69,15 @@ class TestUtil { } } - void parseAndExecute(String input) throws ParseException { + void parseAndExecute(String input) throws ParseException, RepositoryException { final AclOperationVisitor v = new AclOperationVisitor(adminSession); for(Operation o : parse(input)) { o.accept(v); } + adminSession.save(); } - Session getServiceSession(String serviceUsername) throws RepositoryException { + Session loginService(String serviceUsername) throws RepositoryException { final SimpleCredentials cred = new SimpleCredentials(serviceUsername, new char[0]); return adminSession.impersonate(cred); } -- To stop receiving notification emails like this one, please contact "commits@sling.apache.org" <commits@sling.apache.org>.