This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch feature/console-improvements in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
commit 11f26ad706a350269e27ca42a2cbcf22a4724ce1 Author: Robert Munteanu <[email protected]> AuthorDate: Fri Aug 5 14:24:44 2022 +0300 SLING-11513 - Allow impersonating an user when checking the result of a map/resolve call - extend the form to optionally accept a user to impersonate - use the resolver of the current user as a basis for impersonation - make sure that we don't accidentally generate imports from the auth.core and jcr.resource bundles, they are only used for the constant values, which are inlined. --- bnd.bnd | 2 + pom.xml | 14 ++++++ .../console/ResourceResolverWebConsolePlugin.java | 58 +++++++++++++++++++--- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/bnd.bnd b/bnd.bnd index d4d7e52..2236400 100644 --- a/bnd.bnd +++ b/bnd.bnd @@ -1,6 +1,8 @@ Import-Package:\ javax.jcr;resolution:=optional,\ org.apache.sling.commons.metrics;resolution:=optional,\ + !org.apache.sling.auth.*,\ + !org.apache.sling.jcr.*,\ * Provide-Capability:\ diff --git a/pom.xml b/pom.xml index 86a48e1..e79ea3b 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,20 @@ <version>1.3.4</version> <scope>provided</scope> </dependency> + <!-- for constant values only --> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.auth.core</artifactId> + <version>1.0.0</version> + <scope>provided</scope> + </dependency> + <!-- for constant values only --> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.jcr.resource</artifactId> + <version>3.0.0</version> + <scope>provided</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java b/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java index 4ce1629..d453de8 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java @@ -26,12 +26,15 @@ import java.net.URLEncoder; import java.util.Arrays; import java.util.Collection; import java.util.Dictionary; +import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.jcr.Session; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -40,12 +43,16 @@ import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import org.apache.sling.api.request.ResponseUtil; +import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.api.resource.mapping.ResourceMapper; import org.apache.sling.api.resource.runtime.RuntimeService; import org.apache.sling.api.resource.runtime.dto.ResourceProviderDTO; import org.apache.sling.api.resource.runtime.dto.ResourceProviderFailureDTO; import org.apache.sling.api.resource.runtime.dto.RuntimeDTO; +import org.apache.sling.auth.core.AuthenticationSupport; +import org.apache.sling.jcr.resource.api.JcrResourceConstants; import org.apache.sling.resourceresolver.impl.CommonResourceResolverFactoryImpl; import org.apache.sling.resourceresolver.impl.helper.URI; import org.apache.sling.resourceresolver.impl.helper.URIException; @@ -63,11 +70,12 @@ public class ResourceResolverWebConsolePlugin extends HttpServlet { private static final long serialVersionUID = 0; private static final String ATTR_TEST = "plugin.test"; - private static final String ATTR_SUBMIT = "plugin.submit"; + private static final String ATTR_USER = "plugin.user"; private static final String PAR_MSG = "msg"; private static final String PAR_TEST = "test"; + private static final String PAR_USER = "user"; private final transient CommonResourceResolverFactoryImpl resolverFactory; @@ -116,6 +124,7 @@ public class ResourceResolverWebConsolePlugin extends HttpServlet { } else { test = null; } + final String user = request.getParameter(PAR_USER); final PrintWriter pw = response.getWriter(); @@ -160,14 +169,22 @@ public class ResourceResolverWebConsolePlugin extends HttpServlet { + "clearly marked, and the others listed for completeness."); pw.println("<tr class='content'>"); - pw.println("<td class='content'>Test</td>"); pw.print("<td class='content' colspan='2'>"); - pw.print("<form method='post'>"); + pw.println("<form method='post'>"); + pw.print("Test "); pw.print("<input type='text' name='" + ATTR_TEST + "' value='"); if (test != null) { pw.print(ResponseUtil.escapeXml(test)); } - pw.println("' class='input' size='50'>"); + pw.println("' class='input' size='20'>"); + pw.print("User (optional)"); + pw.print("<input type='text' name='" + ATTR_USER + "' value='"); + if ( user != null ) { + pw.print(ResponseUtil.escapeXml(user)); + } + pw.println("' class='input' size='20'>"); + pw.println("</td>"); + pw.print("<td class='content'>"); pw.println(" <input type='submit' name='" + ATTR_SUBMIT + "' value='Resolve' class='submit'>"); pw.println(" <input type='submit' name='" + ATTR_SUBMIT @@ -213,6 +230,7 @@ public class ResourceResolverWebConsolePlugin extends HttpServlet { HttpServletResponse response) throws ServletException, IOException { final String test = request.getParameter(ATTR_TEST); + final String user = request.getParameter(ATTR_USER); String msg = null; if (test != null) { @@ -221,7 +239,12 @@ public class ResourceResolverWebConsolePlugin extends HttpServlet { // prepare the request for the resource resolver HttpServletRequest helper = new ResolverRequest(request, test); - resolver = resolverFactory.getServiceResourceResolver(this.resolverFactory.getServiceUserAuthenticationInfo("console")); + // impersonate if asked + if ( user != null && user.length() > 0 ) { + resolver = getImpersonatedResourceResolver(request, user); + } else { + resolver = resolverFactory.getServiceResourceResolver(this.resolverFactory.getServiceUserAuthenticationInfo("console")); + } // map or resolve as instructed Object result; @@ -255,16 +278,39 @@ public class ResourceResolverWebConsolePlugin extends HttpServlet { // finally redirect final String path = request.getContextPath() + request.getServletPath() + request.getPathInfo(); - final String redirectTo; + String redirectTo; if (msg == null) { redirectTo = path; } else { redirectTo = path + '?' + PAR_MSG + '=' + encodeParam(msg) + '&' + PAR_TEST + '=' + encodeParam(test); + if ( user != null && user.length() > 0 ) { + redirectTo += '&' + PAR_USER + '=' + encodeParam(user); + } } response.sendRedirect(redirectTo); } + private ResourceResolver getImpersonatedResourceResolver(HttpServletRequest request, final String user) + throws LoginException { + + // resolver is set by the auth.core bundle in case of successful authentication, so it should + // always be there + Object resolverAttribute = request.getAttribute(AuthenticationSupport.REQUEST_ATTRIBUTE_RESOLVER); + if ( !(resolverAttribute instanceof ResourceResolver) ) { + throw new IllegalArgumentException("No " + ResourceResolver.class.getSimpleName() + " found in request, unable to proceed with impersonation"); + } + + @SuppressWarnings("resource") // not a leak, we don't own this resolver + ResourceResolver currentResolver = (ResourceResolver) resolverAttribute; + + Map<String, Object> authenticationInfo = new HashMap<>(); + authenticationInfo.put(ResourceResolverFactory.USER_IMPERSONATION, user); + authenticationInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, currentResolver.adaptTo(Session.class)); + + return resolverFactory.getResourceResolver(authenticationInfo); + } + private static String mappingsToString(Collection<String> allMappings) { if ( allMappings.size() == 0 ) return "(no mappings)"; // should not happen
