From bae86de2d7d4e12da2dda0dda6cca19c8d4a8202 Mon Sep 17 00:00:00 2001 From: Kevin Leturc Date: Mon, 27 Nov 2017 16:31:13 +0100 Subject: [PATCH] JAVACLIENT-142: Ensure there's only one authentication method on client and fix the portal sso method --- .../javaclient-portal-sso-login-contrib.xml | 3 + .../org/nuxeo/client/ITAuthentication.java | 6 +- .../test/java/org/nuxeo/client/ITBase.java | 30 +++++++++- .../test/java/org/nuxeo/client/ITUpload.java | 58 +++++++++++++------ .../java/org/nuxeo/client/NuxeoClient.java | 14 ++++- .../client/objects/upload/BatchUpload.java | 4 +- .../spi/NuxeoClientRemoteException.java | 13 +++++ .../spi/auth/PortalSSOAuthInterceptor.java | 15 ++--- 8 files changed, 110 insertions(+), 33 deletions(-) diff --git a/nuxeo-java-client-test/src/main/resources/OSGI-INF/javaclient-portal-sso-login-contrib.xml b/nuxeo-java-client-test/src/main/resources/OSGI-INF/javaclient-portal-sso-login-contrib.xml index 9cc2b1cb..84148858 100644 --- a/nuxeo-java-client-test/src/main/resources/OSGI-INF/javaclient-portal-sso-login-contrib.xml +++ b/nuxeo-java-client-test/src/main/resources/OSGI-INF/javaclient-portal-sso-login-contrib.xml @@ -26,7 +26,10 @@ + (.*)/automation.* + + (.*)/upload.* AUTOMATION_BASIC_AUTH diff --git a/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITAuthentication.java b/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITAuthentication.java index adf95cdb..49766fc5 100644 --- a/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITAuthentication.java +++ b/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITAuthentication.java @@ -27,7 +27,6 @@ import org.junit.Test; import org.nuxeo.client.objects.user.User; import org.nuxeo.client.spi.NuxeoClientRemoteException; -import org.nuxeo.client.spi.auth.PortalSSOAuthInterceptor; /** * @since 0.1 @@ -68,10 +67,7 @@ public void itCanFailOnLogin() { @Test public void itCanChangeAuthMethod() { - NuxeoClient client = new NuxeoClient.Builder().url(ITBase.BASE_URL) - .authentication(new PortalSSOAuthInterceptor("Administrator", - "nuxeo5secretkey")) - .connect(); + NuxeoClient client = ITBase.createClientPortalSSO(); User currentUser = client.getCurrentUser(); assertEquals("Administrator", currentUser.getUserName()); } diff --git a/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITBase.java b/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITBase.java index 92d6978e..e0331fc9 100644 --- a/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITBase.java +++ b/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITBase.java @@ -38,13 +38,14 @@ import org.nuxeo.client.objects.workflow.Workflow; import org.nuxeo.client.objects.workflow.Workflows; import org.nuxeo.client.spi.NuxeoClientRemoteException; +import org.nuxeo.client.spi.auth.PortalSSOAuthInterceptor; import org.nuxeo.common.utils.FileUtils; /** * Tests the basic operation of client. This test is isolated from test framework because it unit tests the operation * used in framework to init server and to clean it. * - * @since 3.0.0 + * @since 3.0 */ public class ITBase { @@ -228,22 +229,49 @@ public void itCanFetchWorkflowModelsFromRepository() { assertEquals("SerialDocumentReview", workflow.getName()); } + /** + * @return A {@link NuxeoClient} filled with Nuxeo Server URL and default basic authentication. + */ public static NuxeoClient createClient() { return createClient(LOGIN, PASSWORD); } + /** + * @return A {@link NuxeoClient} filled with Nuxeo Server URL and input basic authentication. + */ public static NuxeoClient createClient(String login, String password) { return createClientBuilder(login, password).connect(); } + /** + * @return A {@link NuxeoClient} filled with Nuxeo Server URL and default Portal SSO authentication. + */ + public static NuxeoClient createClientPortalSSO() { + return createClientBuilderPortalSSO().connect(); + } + + /** + * @return A {@link NuxeoClient.Builder} filled with Nuxeo Server URL and default basic authentication. + */ public static NuxeoClient.Builder createClientBuilder() { return createClientBuilder(LOGIN, PASSWORD); } + /** + * @return A {@link NuxeoClient.Builder} filled with Nuxeo Server URL and input basic authentication. + */ public static NuxeoClient.Builder createClientBuilder(String login, String password) { return new NuxeoClient.Builder().url(BASE_URL).authentication(login, password).timeout(60); } + /** + * @return A {@link NuxeoClient.Builder} filled with Nuxeo Server URL and default Portal SSO authentication. + */ + public static NuxeoClient.Builder createClientBuilderPortalSSO() { + return new NuxeoClient.Builder().url(BASE_URL).authentication( + new PortalSSOAuthInterceptor("Administrator", "nuxeo5secretkey")); + } + public static User createUser() { User user = new User(); user.setUserName(DEFAULT_USER_LOGIN); diff --git a/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITUpload.java b/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITUpload.java index 94f47286..974f1944 100644 --- a/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITUpload.java +++ b/nuxeo-java-client-test/src/test/java/org/nuxeo/client/ITUpload.java @@ -29,11 +29,13 @@ import java.util.Map; import org.junit.Test; +import org.nuxeo.client.methods.BatchUploadAPI; import org.nuxeo.client.objects.Document; import org.nuxeo.client.objects.blob.FileBlob; import org.nuxeo.client.objects.upload.BatchUpload; import org.nuxeo.client.objects.upload.BatchUploadManager; import org.nuxeo.client.spi.NuxeoClientRemoteException; +import org.nuxeo.client.spi.auth.PortalSSOAuthInterceptor; import org.nuxeo.common.utils.FileUtils; /** @@ -58,40 +60,60 @@ public void itCanManageBatch() { @Test public void itCanUploadFiles() { + itCanUploadFiles(nuxeoClient); + } + + /** + * JAVACLIENT-142: Checks that using {@link PortalSSOAuthInterceptor} doesn't erase HTTP headers set from + * {@link BatchUploadAPI}. + */ + @Test + public void itCanUploadFilesWithPortalSSOAuthentication() { + NuxeoClient nuxeoClient = ITBase.createClientPortalSSO(); + itCanUploadFiles(nuxeoClient); + } + + private void itCanUploadFiles(NuxeoClient nuxeoClient) { + String filename1 = "sample.jpg"; + String filename2 = "blob.json"; + // Upload the file BatchUploadManager batchUploadManager = nuxeoClient.batchUploadManager(); BatchUpload batchUpload = batchUploadManager.createBatch(); assertNotNull(batchUpload); String batchId = batchUpload.getBatchId(); assertNotNull(batchId); - File file = FileUtils.getResourceFileFromContext("sample.jpg"); + File file = FileUtils.getResourceFileFromContext(filename1); + batchUpload = batchUpload.upload("1", file); - assertNotNull(batchUpload); - assertEquals(batchId, batchUpload.getBatchId()); - assertEquals("1", batchUpload.getFileIdx()); - assertEquals(file.getName(), batchUpload.getName()); - assertEquals(ConstantsV1.UPLOAD_NORMAL_TYPE, batchUpload.getUploadType()); + assertBatchUpload(batchId, "1", filename1, batchUpload); // Check the batch by fetching it again batchUpload = batchUpload.fetchBatchUpload(); - assertNotNull(batchUpload); - assertEquals(batchId, batchUpload.getBatchId()); - assertEquals("1", batchUpload.getFileIdx()); - assertEquals(file.getName(), batchUpload.getName()); - assertEquals(ConstantsV1.UPLOAD_NORMAL_TYPE, batchUpload.getUploadType()); + assertBatchUpload(batchId, "1", filename1, batchUpload); + + // Check the batch by fetching it again and re-instantiating the batch upload (in BatchUpload we set back some + // properties in order to handle responses with light metadata) + batchUpload = batchUploadManager.fetchBatchUpload(batchId, "1"); + assertBatchUpload(batchId, "1", filename1, batchUpload); // Upload another file and check files - file = FileUtils.getResourceFileFromContext("blob.json"); + file = FileUtils.getResourceFileFromContext(filename2); batchUpload.upload("2", file); List batchUploads = batchUpload.fetchBatchUploads(); assertNotNull(batchUploads); assertEquals(2, batchUploads.size()); - assertEquals("sample.jpg", batchUploads.get(0).getName()); - assertEquals(batchId, batchUploads.get(0).getBatchId()); - assertEquals("1", batchUploads.get(0).getFileIdx()); - assertEquals("blob.json", batchUploads.get(1).getName()); - assertEquals(batchId, batchUploads.get(1).getBatchId()); - assertEquals("2", batchUploads.get(1).getFileIdx()); + assertBatchUpload(batchId, "1", filename1, batchUploads.get(0)); + assertBatchUpload(batchId, "2", filename2, batchUploads.get(1)); + } + + private void assertBatchUpload(String expectedBatchId, String expectedFileIdx, String expectedName, + BatchUpload actual) { + assertNotNull(actual); + assertEquals(expectedBatchId, actual.getBatchId()); + assertEquals(expectedFileIdx, actual.getFileIdx()); + assertEquals(expectedName, actual.getName()); + assertEquals(ConstantsV1.UPLOAD_NORMAL_TYPE, actual.getUploadType()); } @Test diff --git a/nuxeo-java-client/src/main/java/org/nuxeo/client/NuxeoClient.java b/nuxeo-java-client/src/main/java/org/nuxeo/client/NuxeoClient.java index a1ac1350..960afa33 100644 --- a/nuxeo-java-client/src/main/java/org/nuxeo/client/NuxeoClient.java +++ b/nuxeo-java-client/src/main/java/org/nuxeo/client/NuxeoClient.java @@ -369,6 +369,8 @@ public static class Builder extends AbstractBase { protected final NuxeoConverterFactory converterFactory; + protected Interceptor authenticationMethod; + protected NuxeoResponseCache cache; public Builder() { @@ -393,7 +395,12 @@ public Builder authentication(String username, String password) { } public Builder authentication(Interceptor authenticationMethod) { - okhttpBuilder.addInterceptor(authenticationMethod); + this.authenticationMethod = authenticationMethod; + return this; + } + + public Builder interceptor(Interceptor interceptor) { + okhttpBuilder.addInterceptor(interceptor); return this; } @@ -417,6 +424,11 @@ public Builder registerEntity(String entityType, Class clazz) { * Builds a {@link NuxeoClient} and log it, it will throw a {@link NuxeoClientException} if failed. */ public NuxeoClient connect() { + // check authentication + if (authenticationMethod == null) { + throw new NuxeoClientException("Your client need an authentication method to connect to Nuxeo server"); + } + okhttpBuilder.interceptors().add(0, authenticationMethod); // init client NuxeoClient client = new NuxeoClient(this); // login client on server diff --git a/nuxeo-java-client/src/main/java/org/nuxeo/client/objects/upload/BatchUpload.java b/nuxeo-java-client/src/main/java/org/nuxeo/client/objects/upload/BatchUpload.java index 74764330..e8d5b8ff 100644 --- a/nuxeo-java-client/src/main/java/org/nuxeo/client/objects/upload/BatchUpload.java +++ b/nuxeo-java-client/src/main/java/org/nuxeo/client/objects/upload/BatchUpload.java @@ -196,7 +196,9 @@ public BatchUpload fetchBatchUpload() { public BatchUpload fetchBatchUpload(String fileIdx) { BatchUpload response = fetchResponse(api.fetchBatchUpload(batchId, fileIdx)); - response.name = name; + if (name != null) { + response.name = name; + } response.batchId = batchId; response.fileIdx = fileIdx; return response; diff --git a/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/NuxeoClientRemoteException.java b/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/NuxeoClientRemoteException.java index c15fb382..2a5b644e 100644 --- a/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/NuxeoClientRemoteException.java +++ b/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/NuxeoClientRemoteException.java @@ -19,6 +19,8 @@ */ package org.nuxeo.client.spi; +import org.apache.commons.lang3.StringUtils; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -78,4 +80,15 @@ public String getErrorBody() { return errorBody; } + @Override + public String toString() { + StringBuilder s = new StringBuilder(getClass().getName()); + s.append(": HTTP/").append(status); + String message = getLocalizedMessage(); + if (StringUtils.isNotBlank(message)) { + s.append(": ").append(message); + } + return s.toString(); + } + } diff --git a/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/auth/PortalSSOAuthInterceptor.java b/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/auth/PortalSSOAuthInterceptor.java index 30fa46de..6547b0ad 100644 --- a/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/auth/PortalSSOAuthInterceptor.java +++ b/nuxeo-java-client/src/main/java/org/nuxeo/client/spi/auth/PortalSSOAuthInterceptor.java @@ -47,7 +47,7 @@ public PortalSSOAuthInterceptor(String username, String secret) { this.secret = secret; } - protected Headers computeHeaders() { + protected Headers computeHeaders(Headers headers) { // compute token long ts = new Date().getTime(); long random = new Random(ts).nextInt(); @@ -63,11 +63,12 @@ protected Headers computeHeaders() { } String base64HashedToken = Base64.encode(hashedToken); - return new Headers.Builder().add(HttpHeaders.NX_TS, String.valueOf(ts)) - .add(HttpHeaders.NX_RD, String.valueOf(random)) - .add(HttpHeaders.NX_TOKEN, base64HashedToken) - .add(HttpHeaders.NX_USER, username) - .build(); + return headers.newBuilder() + .add(HttpHeaders.NX_TS, String.valueOf(ts)) + .add(HttpHeaders.NX_RD, String.valueOf(random)) + .add(HttpHeaders.NX_TOKEN, base64HashedToken) + .add(HttpHeaders.NX_USER, username) + .build(); } @Override @@ -75,7 +76,7 @@ public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request request = chain.request() .newBuilder() - .headers(computeHeaders()) + .headers(computeHeaders(original.headers())) .method(original.method(), original.body()) .build(); return chain.proceed(request);