This is an automated email from the ASF dual-hosted git repository. dklco pushed a commit to branch SLING-10649 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-clients.git
commit 32bafcf1192b020e143c82fd82d6a684c9785ba9 Author: Dan Klco <[email protected]> AuthorDate: Thu Jul 22 11:06:42 2021 -0400 SLING-10649 - Adding support for impersonation --- README.md | 4 + .../apache/sling/testing/clients/SlingClient.java | 36 +++++++ .../sling/testing/clients/email/package-info.java | 2 +- .../sling/testing/clients/html/package-info.java | 2 +- .../apache/sling/testing/clients/package-info.java | 2 +- .../clients/SlingClientImpersonationTest.java | 106 +++++++++++++++++++++ 6 files changed, 149 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2f862e7..8fe63b4 100644 --- a/README.md +++ b/README.md @@ -214,3 +214,7 @@ We have tried to make these methods as robust as possible. Their job is very cle Any input that does not respect the contract might not work. Check `AbstractSlingClientGetPathTest` and `AbstractSlingClientGetUrlTest` for an extensive list of cases that we have considered when writing these methods. + +##### How can I impersonate a user? +* `client.impersonate(userId)` to impersonate +* `client.impersonate(null)` to clear impersonation \ No newline at end of file diff --git a/src/main/java/org/apache/sling/testing/clients/SlingClient.java b/src/main/java/org/apache/sling/testing/clients/SlingClient.java index baa3a0c..0785840 100644 --- a/src/main/java/org/apache/sling/testing/clients/SlingClient.java +++ b/src/main/java/org/apache/sling/testing/clients/SlingClient.java @@ -22,7 +22,9 @@ import static org.apache.http.HttpStatus.SC_OK; import java.io.File; import java.net.URI; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -41,6 +43,7 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.sling.testing.clients.interceptors.DelayRequestInterceptor; import org.apache.sling.testing.clients.interceptors.HttpRequestResponseInterceptor; import org.apache.sling.testing.clients.interceptors.TestDescriptionInterceptor; @@ -64,6 +67,7 @@ public class SlingClient extends AbstractSlingClient { public static final String DEFAULT_NODE_TYPE = "sling:OrderedFolder"; public static final String CLIENT_CONNECTION_TIMEOUT_PROP = "sling.client.connection.timeout.seconds"; + public static final String SUDO_COOKIE_NAME = "sling.sudo.cookie.name"; /** * Constructor used by Builders and adaptTo(). <b>Should never be called directly from the code.</b> @@ -543,6 +547,10 @@ public class SlingClient extends AbstractSlingClient { return importContent(parentPath, "json", json.toString(), expectedStatus); } + private String getSudoCookieName() { + return Optional.ofNullable(this.getValue(SUDO_COOKIE_NAME)).orElse("sling.sudo"); + } + /** * Get the UUID of a repository path * @@ -580,6 +588,34 @@ public class SlingClient extends AbstractSlingClient { return uuidNode.getValueAsText(); } + @Override + public String getUser() { + // get the username from the sudo cookie or default from client config + return getCookieStore().getCookies().stream().filter(c -> c.getName().equals(getSudoCookieName())).findFirst() + .map(c -> c.getValue().replace("\"", "")).orElse(super.getUser()); + } + + /** + * Impersonate user with the given <code>userId</code> + * <p> + * By impersonating a user SlingClient can access content from that user eye view. + * </p> + *Passing a <code>null</code> will clear impersonation. + * + * @param userId the user to impersonate. A <code>null</code> value clears impersonation + */ + public SlingClient impersonate(String userId) { + BasicClientCookie c = new BasicClientCookie(getSudoCookieName(), "\"" + userId + "\""); + c.setPath("/"); + c.setDomain(getUrl().getHost()); + if(userId == null || "-".equals(userId)){ + // setting expiry date in the past will remove the cookie + c.setExpiryDate(new Date(0)); + } + getCookieStore().addCookie(c); + return this; + } + // // InternalBuilder class and builder related methods // diff --git a/src/main/java/org/apache/sling/testing/clients/email/package-info.java b/src/main/java/org/apache/sling/testing/clients/email/package-info.java index 906392d..01de7b2 100644 --- a/src/main/java/org/apache/sling/testing/clients/email/package-info.java +++ b/src/main/java/org/apache/sling/testing/clients/email/package-info.java @@ -17,7 +17,7 @@ * under the License. */ -@Version("1.2.0") +@Version("1.3.0") package org.apache.sling.testing.clients.email; import org.osgi.annotation.versioning.Version; diff --git a/src/main/java/org/apache/sling/testing/clients/html/package-info.java b/src/main/java/org/apache/sling/testing/clients/html/package-info.java index 7c795ae..2723070 100644 --- a/src/main/java/org/apache/sling/testing/clients/html/package-info.java +++ b/src/main/java/org/apache/sling/testing/clients/html/package-info.java @@ -17,7 +17,7 @@ * under the License. */ -@Version("2.3.0") +@Version("2.4.0") package org.apache.sling.testing.clients.html; import org.osgi.annotation.versioning.Version; diff --git a/src/main/java/org/apache/sling/testing/clients/package-info.java b/src/main/java/org/apache/sling/testing/clients/package-info.java index 9e17199..8b3a108 100644 --- a/src/main/java/org/apache/sling/testing/clients/package-info.java +++ b/src/main/java/org/apache/sling/testing/clients/package-info.java @@ -17,7 +17,7 @@ * under the License. */ -@Version("2.3.0") +@Version("2.4.0") package org.apache.sling.testing.clients; import org.osgi.annotation.versioning.Version; diff --git a/src/test/java/org/apache/sling/testing/clients/SlingClientImpersonationTest.java b/src/test/java/org/apache/sling/testing/clients/SlingClientImpersonationTest.java new file mode 100644 index 0000000..789a646 --- /dev/null +++ b/src/test/java/org/apache/sling/testing/clients/SlingClientImpersonationTest.java @@ -0,0 +1,106 @@ +/* + * 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.testing.clients; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.cookie.Cookie; +import org.junit.Before; +import org.junit.Test; + +public class SlingClientImpersonationTest { + + private SlingClient slingClient; + + @Before + public void setup() throws ClientException, URISyntaxException { + slingClient = new SlingClient(new URI("http://localhost:8080"), "admin", "pass"); + assertEquals("admin", slingClient.getUser()); + } + + private Cookie getSudoCookie(String cookieName) { + return slingClient.getCookieStore().getCookies().stream().filter(c -> c.getName().equals(cookieName)).findAny() + .orElse(null); + } + + @Test + public void testImpersonate() throws Exception { + + slingClient.impersonate("user"); + + assertEquals("user", slingClient.getUser()); + + Cookie sudoCookie = getSudoCookie("sling.sudo"); + + assertNotNull(sudoCookie); + assertEquals("\"user\"", sudoCookie.getValue()); + } + + @Test + public void testUndoImpersonation() throws Exception { + + slingClient.impersonate("user"); + + assertEquals("user", slingClient.getUser()); + + slingClient.impersonate("-"); + assertEquals("admin", slingClient.getUser()); + + Cookie sudoCookie = getSudoCookie("sling.sudo"); + + assertNull(sudoCookie); + } + + @Test + public void testNullImpersonation() throws Exception { + + slingClient.impersonate("user"); + + assertEquals("user", slingClient.getUser()); + + slingClient.impersonate(null); + assertEquals("admin", slingClient.getUser()); + + Cookie sudoCookie = getSudoCookie("sling.sudo"); + + assertNull(sudoCookie); + } + + @Test + public void testDifferentSudoCookie() throws Exception { + String sudoCookieName = "sudo.make.me.a.sandwich"; + + slingClient.addValue(SlingClient.SUDO_COOKIE_NAME, sudoCookieName); + + slingClient.impersonate("user"); + + assertEquals("user", slingClient.getUser()); + + Cookie defaultSudoCookie = getSudoCookie("sling.sudo"); + assertNull(defaultSudoCookie); + + Cookie customSudoCookie = getSudoCookie(sudoCookieName); + assertNotNull(customSudoCookie); + assertEquals("\"user\"", customSudoCookie.getValue()); + } + +}
