From d313d3e9a328e457bbb25bc2b8a6c748b5802267 Mon Sep 17 00:00:00 2001 From: Sonia Zorba <sonia.zorba@inaf.it> Date: Mon, 26 Oct 2020 18:05:56 +0100 Subject: [PATCH] GMS client improvements --- .gitignore | 4 +- gms-client/gms-cli/gms.properties | 6 +- gms-client/gms-cli/pom.xml | 2 +- .../main/java/it/inaf/ia2/gms/cli/CLI.java | 28 +- gms-client/gms-client-lib/pom.xml | 32 --- .../it/inaf/ia2/gms/client/GmsClient.java | 91 ------- .../inaf/ia2/gms/client/GmsClientBuilder.java | 40 --- .../ia2/gms/client/call/AddMemberCall.java | 35 --- .../gms/client/call/AddPermissionCall.java | 40 --- .../inaf/ia2/gms/client/call/BaseGmsCall.java | 44 --- .../ia2/gms/client/call/CreateGroupCall.java | 30 --- .../ia2/gms/client/call/DeleteGroupCall.java | 28 -- .../gms/client/call/HttpClientWrapper.java | 105 -------- .../ia2/gms/client/call/RemoveMemberCall.java | 34 --- .../gms/client/call/RemovePermissionCall.java | 35 --- .../gms/client/call/SetPermissionCall.java | 39 --- .../it/inaf/ia2/gms/client/GmsClientTest.java | 255 ------------------ .../client/call/HttpClientWrapperTest.java | 15 -- .../client/call/MockedHttpClientWrapper.java | 18 -- gms-client/gms-client/pom.xml | 85 ++++++ .../it/inaf/ia2/gms/client/GmsClient.java | 159 +++++++++++ .../call/AddInvitedRegistrationCall.java | 24 +- .../ia2/gms/client/call/AddMemberCall.java | 30 +++ .../gms/client/call/AddPermissionCall.java | 35 +++ .../ia2/gms/client/call/CreateGroupCall.java | 25 ++ .../ia2/gms/client/call/DeleteGroupCall.java | 23 ++ .../client/call/GetGroupPermissionsCall.java | 27 +- .../client/call/GetMemberEmailAddresses.java | 27 +- .../gms/client/call/GetUserGroupsCall.java | 44 ++- .../client/call/GetUserPermissionsCall.java | 27 +- .../ia2/gms/client/call/ListGroupsCall.java | 27 +- .../ia2/gms/client/call/RemoveMemberCall.java | 29 ++ .../gms/client/call/RemovePermissionCall.java | 29 ++ .../gms/client/call/SetPermissionCall.java | 33 +++ .../ia2/gms/client/model/GroupPermission.java | 0 .../inaf/ia2/gms/client/model/Permission.java | 0 .../ia2/gms/client/model/UserPermission.java | 0 .../ia2/gms/client/BaseGmsClientTest.java | 101 +++++++ .../ia2/gms/client/call/AddMemberTest.java | 33 +++ .../gms/client/call/AddPermissionTest.java | 34 +++ .../ia2/gms/client/call/CreateGroupTest.java | 33 +++ .../ia2/gms/client/call/DeleteGroupTest.java | 33 +++ .../gms/client/call/GetUserGroupsTest.java | 61 +++++ .../client/call/InvitedRegistrationTest.java | 98 +++++++ .../ia2/gms/client/call/RemoveMemberTest.java | 33 +++ .../gms/client/call/RemovePermissionTest.java | 33 +++ .../java/it/inaf/ia2/gms/model/Identity.java | 59 ---- .../it/inaf/ia2/gms/model/IdentityType.java | 38 --- .../java/it/inaf/ia2/gms/model/RapUser.java | 63 ----- 49 files changed, 999 insertions(+), 1125 deletions(-) delete mode 100644 gms-client/gms-client-lib/pom.xml delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClientBuilder.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/BaseGmsCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/HttpClientWrapper.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java delete mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java delete mode 100644 gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/GmsClientTest.java delete mode 100644 gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/HttpClientWrapperTest.java delete mode 100644 gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/MockedHttpClientWrapper.java create mode 100644 gms-client/gms-client/pom.xml create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/GmsClient.java rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java (66%) create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java (60%) rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java (53%) rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java (57%) rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java (60%) rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java (55%) create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java create mode 100644 gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/model/GroupPermission.java (100%) rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/model/Permission.java (100%) rename gms-client/{gms-client-lib => gms-client}/src/main/java/it/inaf/ia2/gms/client/model/UserPermission.java (100%) create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/BaseGmsClientTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddMemberTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddPermissionTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/CreateGroupTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/DeleteGroupTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/GetUserGroupsTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/InvitedRegistrationTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemoveMemberTest.java create mode 100644 gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemovePermissionTest.java delete mode 100644 gms/src/main/java/it/inaf/ia2/gms/model/Identity.java delete mode 100644 gms/src/main/java/it/inaf/ia2/gms/model/IdentityType.java delete mode 100644 gms/src/main/java/it/inaf/ia2/gms/model/RapUser.java diff --git a/.gitignore b/.gitignore index 410aba1..793bc23 100644 --- a/.gitignore +++ b/.gitignore @@ -54,12 +54,10 @@ nbactions.xml ### VS Code ### .vscode/ -/gms-ui/target/ /gms/nbactions-release-profile.xml -/gms-client/gms-client-lib/target/ -/gms-client/gms-cli/target/ /gms/node/ +**/target/* nb-configuration.xml dependency-reduced-pom.xml diff --git a/gms-client/gms-cli/gms.properties b/gms-client/gms-cli/gms.properties index facdd47..b7f4928 100644 --- a/gms-client/gms-cli/gms.properties +++ b/gms-client/gms-cli/gms.properties @@ -1,2 +1,4 @@ -base_url=http://localhost:8082/gms/ws/jwt -token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjM0ZmU4MDcwMDVhNTcxMTYifQ.eyJpc3MiOiJzc28uaWEyLmluYWYuaXQiLCJzdWIiOiIyMzg2IiwiaWF0IjoxNTg3NjU5NzYxLCJleHAiOjE1ODc3NDYxNjEsImF1ZCI6ImdtcyJ9.KcXRAciG3ApqlE8MFM8VYW9WAX3hEZb7Vk8jB9uJtWsOMU48ha_Ybb4k_f0nrD2jhOxwaNn2QMxWZuflwCf1N-KiCj5Ff9f8xKOrrXZrl-w1H3_dwtMlIS8t2b0-w0WwRJ7UIhrwVBzmCcWinD3qJhFPzyO2pi-A4aXV57RpJ68VXfALQXeHK0sslrf-RgAU3xWYOgjGTUoGB5BQYC9huA_bZ0eV1HFcancs9pDdoTusqZs8OkPFCJbo7-L5eibsuykqnLHztYdCcP2Vtvtwb0pww-ofWZblIHzoMI8i-ipnfLJETG8Dpc7FrhjCYLw3AEGZg4U1wYTeqG3HRbPXSQ +gms_url=http://localhost:8082/gms/ws/jwt +client_id=gms_cli +client_secret=gms +rap_url=http://localhost/rap-ia2 diff --git a/gms-client/gms-cli/pom.xml b/gms-client/gms-cli/pom.xml index cfaad41..2bfb5e9 100644 --- a/gms-client/gms-cli/pom.xml +++ b/gms-client/gms-cli/pom.xml @@ -17,7 +17,7 @@ <dependencies> <dependency> <groupId>${project.groupId}</groupId> - <artifactId>gms-client-lib</artifactId> + <artifactId>gms-client</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> diff --git a/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java b/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java index 4d4ff78..118e2be 100644 --- a/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java +++ b/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java @@ -1,8 +1,9 @@ package it.inaf.ia2.gms.cli; +import it.inaf.ia2.client.ClientException; import it.inaf.ia2.gms.client.GmsClient; -import it.inaf.ia2.gms.client.GmsClientBuilder; import it.inaf.ia2.gms.client.model.Permission; +import it.inaf.ia2.rap.client.RapClient; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -61,7 +62,11 @@ public class CLI { default: verifyConfigLoaded(); createClient(); - parseCommand(); + try { + parseCommand(); + } catch (ClientException ex) { + System.err.println(ex.getMessage()); + } commandParsed = true; break; } @@ -96,17 +101,16 @@ public class CLI { } private void createClient() { - GmsClientBuilder clientBuilder = new GmsClientBuilder() - .setGmsBaseUrl(gmsBaseUrl); + + client = new GmsClient(gmsBaseUrl); if (token != null) { - client = clientBuilder.build(); client.setAccessToken(token); - } else { - client = clientBuilder.setClientId(clientId) - .setClientSecret(clientSecret) - .setRapBaseUrl(rapBaseUrl) - .build(); + } else { + RapClient rapClient = new RapClient(rapBaseUrl) + .setClientId(clientId) + .setClientSecret(clientSecret); + client.setAccessToken(rapClient.getAccessTokenFromClientCredentials()); } } @@ -118,7 +122,7 @@ public class CLI { } Properties properties = new Properties(); - try (InputStream in = new FileInputStream(config)) { + try ( InputStream in = new FileInputStream(config)) { properties.load(in); } catch (IOException ex) { throw new UncheckedIOException(ex); @@ -141,7 +145,7 @@ public class CLI { System.exit(1); } - try (InputStream in = new FileInputStream(tokenFile)) { + try ( InputStream in = new FileInputStream(tokenFile)) { java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\A"); token = s.next().trim(); } catch (IOException ex) { diff --git a/gms-client/gms-client-lib/pom.xml b/gms-client/gms-client-lib/pom.xml deleted file mode 100644 index 571ed7f..0000000 --- a/gms-client/gms-client-lib/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <groupId>it.inaf.ia2</groupId> - <artifactId>gms-client-lib</artifactId> - <version>1.0-SNAPSHOT</version> - <packaging>jar</packaging> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <maven.compiler.source>12</maven.compiler.source> - <maven.compiler.target>12</maven.compiler.target> - </properties> - <dependencies> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-to-slf4j</artifactId> - <version>2.12.1</version> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.12</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <version>2.23.4</version> - <scope>test</scope> - </dependency> - </dependencies> -</project> \ No newline at end of file diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java deleted file mode 100644 index 8dcf041..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java +++ /dev/null @@ -1,91 +0,0 @@ -package it.inaf.ia2.gms.client; - -import it.inaf.ia2.gms.client.call.AddInvitedRegistrationCall; -import it.inaf.ia2.gms.client.call.HttpClientWrapper; -import it.inaf.ia2.gms.client.call.AddMemberCall; -import it.inaf.ia2.gms.client.call.AddPermissionCall; -import it.inaf.ia2.gms.client.call.CreateGroupCall; -import it.inaf.ia2.gms.client.call.DeleteGroupCall; -import it.inaf.ia2.gms.client.call.GetGroupPermissionsCall; -import it.inaf.ia2.gms.client.call.GetMemberEmailAddresses; -import it.inaf.ia2.gms.client.call.GetUserGroupsCall; -import it.inaf.ia2.gms.client.call.GetUserPermissionsCall; -import it.inaf.ia2.gms.client.call.ListGroupsCall; -import it.inaf.ia2.gms.client.call.RemoveMemberCall; -import it.inaf.ia2.gms.client.call.RemovePermissionCall; -import it.inaf.ia2.gms.client.call.SetPermissionCall; -import it.inaf.ia2.gms.client.model.GroupPermission; -import it.inaf.ia2.gms.client.model.Permission; -import it.inaf.ia2.gms.client.model.UserPermission; -import java.util.List; -import java.util.Map; - -public class GmsClient { - - private final HttpClientWrapper httpClientWrapper; - - GmsClient(HttpClientWrapper httpClientWrapper) { - this.httpClientWrapper = httpClientWrapper; - } - - public GmsClient setAccessToken(String accessToken) { - httpClientWrapper.setAccessToken(accessToken); - return this; - } - - public List<String> getMyGroups(String prefix) { - return new GetUserGroupsCall(httpClientWrapper).getUserGroups(prefix); - } - - public List<String> listGroups(String prefix) { - return new ListGroupsCall(httpClientWrapper).listGroups(prefix); - } - - public List<String> getUserGroups(String userId, String prefix) { - return new GetUserGroupsCall(httpClientWrapper).getUserGroups(userId, prefix); - } - - public void createGroup(String completeGroupName, boolean leaf) { - new CreateGroupCall(httpClientWrapper).createGroup(completeGroupName, leaf); - } - - public void deleteGroup(String completeGroupName) { - new DeleteGroupCall(httpClientWrapper).deleteGroup(completeGroupName); - } - - public void addMember(String completeGroupName, String userId) { - new AddMemberCall(httpClientWrapper).addMember(completeGroupName, userId); - } - - public void removeMember(String completeGroupName, String userId) { - new RemoveMemberCall(httpClientWrapper).removeMember(completeGroupName, userId); - } - - public void addPermission(String completeGroupName, String userId, Permission permission) { - new AddPermissionCall(httpClientWrapper).addPermission(completeGroupName, userId, permission); - } - - public void setPermission(String completeGroupName, String userId, Permission permission) { - new SetPermissionCall(httpClientWrapper).setPermission(completeGroupName, userId, permission); - } - - public void removePermission(String completeGroupName, String userId) { - new RemovePermissionCall(httpClientWrapper).removePermission(completeGroupName, userId); - } - - public List<UserPermission> getUserPermissions(String userId) { - return new GetUserPermissionsCall(httpClientWrapper).getUserPermissions(userId); - } - - public List<GroupPermission> getGroupPermissions(String groupId) { - return new GetGroupPermissionsCall(httpClientWrapper).getGroupPermissions(groupId); - } - - public void addInvitedRegistration(String token, String email, Map<String, Permission> groupsPermissions) { - new AddInvitedRegistrationCall(httpClientWrapper).addInvitedRegistration(token, email, groupsPermissions); - } - - public List<String> getMemberEmailAddresses(String groupId, Permission permission) { - return new GetMemberEmailAddresses(httpClientWrapper).getMemberEmailAddresses(groupId, permission); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClientBuilder.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClientBuilder.java deleted file mode 100644 index 002081d..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClientBuilder.java +++ /dev/null @@ -1,40 +0,0 @@ -package it.inaf.ia2.gms.client; - -import it.inaf.ia2.gms.client.call.HttpClientWrapper; - -public class GmsClientBuilder { - - private String gmsBaseUrl; - private String rapBaseUrl; - private String clientId; - private String clientSecret; - - public GmsClientBuilder setGmsBaseUrl(String gmsBaseUrl) { - this.gmsBaseUrl = gmsBaseUrl; - return this; - } - - public GmsClientBuilder setRapBaseUrl(String rapBaseUrl) { - this.rapBaseUrl = rapBaseUrl; - return this; - } - - public GmsClientBuilder setClientId(String clientId) { - this.clientId = clientId; - return this; - } - - public GmsClientBuilder setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - return this; - } - - public GmsClient build() { - HttpClientWrapper clientWrapper = new HttpClientWrapper(gmsBaseUrl); - if (rapBaseUrl != null && clientId != null && clientSecret != null) { - clientWrapper.setRapBaseUrl(rapBaseUrl) - .setClientId(clientId).setClientSecret(clientSecret); - } - return new GmsClient(clientWrapper); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java deleted file mode 100644 index e76242d..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java +++ /dev/null @@ -1,35 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.BodyPublishers; -import java.net.http.HttpResponse; - -public class AddMemberCall extends BaseGmsCall { - - public AddMemberCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean addMember(String completeGroupName, String userId) { - - String endpoint = "membership"; - if (completeGroupName != null && !completeGroupName.isBlank()) { - endpoint += "/" + completeGroupName; - } - - HttpRequest groupsRequest = newHttpRequest(endpoint) - .header("Accept", "text/plain") - .header("Content-Type", "application/x-www-form-urlencoded") - .POST(BodyPublishers.ofString("user_id=" + userId)) - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to add member to group"); - }).join(); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java deleted file mode 100644 index 42acad9..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java +++ /dev/null @@ -1,40 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import it.inaf.ia2.gms.client.model.Permission; -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.BodyPublisher; -import java.net.http.HttpRequest.BodyPublishers; -import java.net.http.HttpResponse; - -public class AddPermissionCall extends BaseGmsCall { - - public AddPermissionCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean addPermission(String completeGroupName, String userId, Permission permission) { - - String endpoint = "permission"; - if (completeGroupName != null && !completeGroupName.isBlank()) { - endpoint += "/" + completeGroupName; - } - - BodyPublisher requestBody = BodyPublishers.ofString( - "user_id=" + userId + "&permission=" + permission); - - HttpRequest groupsRequest = newHttpRequest(endpoint) - .header("Accept", "text/plain") - .header("Content-Type", "application/x-www-form-urlencoded") - .POST(requestBody) - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to add permission"); - }).join(); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/BaseGmsCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/BaseGmsCall.java deleted file mode 100644 index f5304b7..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/BaseGmsCall.java +++ /dev/null @@ -1,44 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.io.InputStream; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.Builder; -import java.net.http.HttpResponse; -import java.util.Scanner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class BaseGmsCall { - - private static final Logger LOGGER = LoggerFactory.getLogger(BaseGmsCall.class); - - protected final HttpClientWrapper clientWrapper; - - public BaseGmsCall(HttpClientWrapper clientWrapper) { - this.clientWrapper = clientWrapper; - } - - protected HttpClient getClient() { - return clientWrapper.getClient(); - } - - protected Builder newHttpRequest(String endpoint) { - return clientWrapper.newHttpRequest(endpoint); - } - - protected static void logServerError(HttpRequest request, HttpResponse<String> response) { - LOGGER.error("Error while reading " + request.uri() - + "\nServer response status code is " + response.statusCode() - + "\nServer response text is " + response.body()); - } - - protected static void logServerErrorInputStream(HttpRequest request, HttpResponse<InputStream> response) { - Scanner s = new Scanner(response.body()).useDelimiter("\\A"); - String responseBody = s.hasNext() ? s.next() : ""; - String error = "Error while reading " + request.uri() - + "\nServer response status code is " + response.statusCode() - + "\nServer response text is " + responseBody; - LOGGER.error(error); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java deleted file mode 100644 index 1cbb2e1..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.BodyPublishers; -import java.net.http.HttpResponse; - -public class CreateGroupCall extends BaseGmsCall { - - public CreateGroupCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean createGroup(String completeGroupName, boolean leaf) { - - HttpRequest groupsRequest = newHttpRequest(completeGroupName) - .header("Accept", "text/plain") - .header("Content-Type", "application/x-www-form-urlencoded") - .POST(BodyPublishers.ofString("leaf=" + leaf)) - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 201) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to create group"); - }).join(); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java deleted file mode 100644 index 56b7b98..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java +++ /dev/null @@ -1,28 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -public class DeleteGroupCall extends BaseGmsCall { - - public DeleteGroupCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean deleteGroup(String completeGroupName) { - - HttpRequest groupsRequest = newHttpRequest(completeGroupName) - .header("Accept", "text/plain") - .DELETE() - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 204) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to delete group"); - }).join(); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/HttpClientWrapper.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/HttpClientWrapper.java deleted file mode 100644 index 7d90d72..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/HttpClientWrapper.java +++ /dev/null @@ -1,105 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.Builder; -import java.net.http.HttpResponse; -import java.util.Base64; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class HttpClientWrapper { - - private final String baseGmsUri; - private final HttpClient client; - - private String rapBaseUrl; - private String clientId; - private String clientSecret; - - private String accessToken; - - public HttpClientWrapper(String baseGmsUri) { - String uri = baseGmsUri; - if (!uri.endsWith("/")) { - uri += "/"; - } - this.baseGmsUri = uri; - - this.client = HttpClient.newBuilder() - .followRedirects(HttpClient.Redirect.ALWAYS) - .build(); - } - - public HttpClientWrapper setAccessToken(String accessToken) { - this.accessToken = accessToken; - return this; - } - - public HttpClientWrapper setRapBaseUrl(String rapBaseUrl) { - if (!rapBaseUrl.endsWith("/")) { - rapBaseUrl += "/"; - } - this.rapBaseUrl = rapBaseUrl; - return this; - } - - public HttpClientWrapper setClientId(String clientId) { - this.clientId = clientId; - return this; - } - - public HttpClientWrapper setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - return this; - } - - Builder newHttpRequest(String endpoint) { - if (accessToken == null) { - accessToken = getAccessTokenFromClientCredentials(); - } - return HttpRequest.newBuilder() - .uri(URI.create(baseGmsUri + endpoint)) - .header("Authorization", "Bearer " + accessToken); - } - - private String getAccessTokenFromClientCredentials() { - if (rapBaseUrl == null || clientId == null || clientSecret == null) { - throw new IllegalStateException("Access token is null and client credentials are not configured"); - } - - String basicAuthHeader = clientId + ":" + clientSecret; - - HttpRequest tokenRequest = HttpRequest.newBuilder() - .uri(URI.create(rapBaseUrl + "auth/oauth2/token")) - .header("Authorization", "Basic " + Base64.getEncoder().encodeToString(basicAuthHeader.getBytes())) - .header("Accept", "application/json") - .header("Content-Type", "application/x-www-form-urlencoded") - .POST(HttpRequest.BodyPublishers.ofString("grant_type=client_credentials")) - .build(); - - return client.sendAsync(tokenRequest, HttpResponse.BodyHandlers.ofString()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return getAccessTokenFromResponse(response.body()); - } - BaseGmsCall.logServerError(tokenRequest, response); - - throw new IllegalStateException("Unable to retrieve access token"); - }).join(); - } - - protected String getAccessTokenFromResponse(String body) { - Pattern codePattern = Pattern.compile(".*\"access_token\":\\s*\"([^\"]+).*"); - Matcher matcher = codePattern.matcher(body); - if (matcher.find()) { - return matcher.group(1); - } - throw new IllegalStateException("Unable to extract access token from body"); - } - - HttpClient getClient() { - return client; - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java deleted file mode 100644 index cc5b01a..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java +++ /dev/null @@ -1,34 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -public class RemoveMemberCall extends BaseGmsCall { - - public RemoveMemberCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean removeMember(String completeGroupName, String userId) { - - String endpoint = "membership"; - if (completeGroupName != null && !completeGroupName.isBlank()) { - endpoint += "/" + completeGroupName; - } - endpoint += "?user_id=" + userId; - - HttpRequest groupsRequest = newHttpRequest(endpoint) - .header("Accept", "text/plain") - .DELETE() - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 204) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to remove member from group"); - }).join(); - } -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java deleted file mode 100644 index 7f17e76..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java +++ /dev/null @@ -1,35 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -public class RemovePermissionCall extends BaseGmsCall { - - public RemovePermissionCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean removePermission(String completeGroupName, String userId) { - - String endpoint = "permission"; - if (completeGroupName != null && !completeGroupName.isBlank()) { - endpoint += "/" + completeGroupName; - } - endpoint += "?user_id=" + userId; - - HttpRequest groupsRequest = newHttpRequest(endpoint) - .header("Accept", "text/plain") - .DELETE() - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 204) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to remove permission"); - }).join(); - } - -} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java deleted file mode 100644 index c7eee10..0000000 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java +++ /dev/null @@ -1,39 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import static it.inaf.ia2.gms.client.call.BaseGmsCall.logServerErrorInputStream; -import it.inaf.ia2.gms.client.model.Permission; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -public class SetPermissionCall extends BaseGmsCall { - - public SetPermissionCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); - } - - public boolean setPermission(String completeGroupName, String userId, Permission permission) { - - String endpoint = "permission"; - if (completeGroupName != null && !completeGroupName.isBlank()) { - endpoint += "/" + completeGroupName; - } - - HttpRequest.BodyPublisher requestBody = HttpRequest.BodyPublishers.ofString( - "user_id=" + userId + "&permission=" + permission); - - HttpRequest groupsRequest = newHttpRequest(endpoint) - .header("Accept", "text/plain") - .header("Content-Type", "application/x-www-form-urlencoded") - .PUT(requestBody) - .build(); - - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to set permission"); - }).join(); - } -} diff --git a/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/GmsClientTest.java b/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/GmsClientTest.java deleted file mode 100644 index ce84caa..0000000 --- a/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/GmsClientTest.java +++ /dev/null @@ -1,255 +0,0 @@ -package it.inaf.ia2.gms.client; - -import it.inaf.ia2.gms.client.call.HttpClientWrapper; -import it.inaf.ia2.gms.client.call.MockedHttpClientWrapper; -import it.inaf.ia2.gms.client.model.Permission; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Flow; -import static org.junit.Assert.assertEquals; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalMatchers; -import org.mockito.ArgumentMatcher; -import org.mockito.ArgumentMatchers; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class GmsClientTest { - - private static final String BASE_URL = "http://base-url"; - - private HttpClient httpClient; - private GmsClient client; - - @Before - public void setUp() { - - httpClient = mock(HttpClient.class); - - HttpClientWrapper clientWrapper = new MockedHttpClientWrapper(BASE_URL, httpClient); - clientWrapper.setAccessToken("foo"); - - client = new GmsClient(clientWrapper); - } - - @Test - public void testGetMyGroups() { - - String body = "LBT.INAF\n" - + "LBT.AZ"; - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(200, body)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - List<String> groups = client.getMyGroups("LBT."); - - verify(httpClient, times(1)).sendAsync(endpointEq("GET", "search"), any()); - - assertEquals(2, groups.size()); - assertEquals("INAF", groups.get(0)); - assertEquals("AZ", groups.get(1)); - } - - @Test - public void testListGroups() { - - String body = "INAF\n" - + "AZ"; - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(200, body)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - List<String> groups = client.listGroups("LBT."); - - verify(httpClient, times(1)).sendAsync(endpointEq("GET", "list/LBT."), any()); - - assertEquals(2, groups.size()); - assertEquals("INAF", groups.get(0)); - assertEquals("AZ", groups.get(1)); - } - - @Test - public void testCreateGroup() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(201)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - client.createGroup("LBT.INAF", false); - - verify(httpClient, times(1)).sendAsync(endpointEq("POST", "LBT.INAF"), any()); - } - - @Test - public void testDeleteGroup() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(204)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - client.deleteGroup("LBT.INAF"); - - verify(httpClient, times(1)).sendAsync(endpointEq("DELETE", "LBT.INAF"), any()); - } - - @Test - public void testAddMember() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(200)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - client.addMember("LBT.INAF", "user"); - - verify(httpClient, times(1)).sendAsync(endpointEq("POST", "membership/LBT.INAF"), any()); - } - - @Test - public void testRemoveMember() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(204)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - client.removeMember("LBT.INAF", "user"); - - verify(httpClient, times(1)).sendAsync(endpointEq("DELETE", "membership/LBT.INAF?user_id=user"), any()); - } - - @Test - public void testAddPermission() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(200)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - client.addPermission("LBT.INAF", "user", Permission.ADMIN); - - verify(httpClient, times(1)).sendAsync(endpointEq("POST", "permission/LBT.INAF"), any()); - } - - @Test - public void testRemovePermission() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(204)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - client.removePermission("LBT.INAF", "user"); - - verify(httpClient, times(1)).sendAsync(endpointEq("DELETE", "permission/LBT.INAF?user_id=user"), any()); - } - - @Test - public void testInvitedRegistration() { - - CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(201)); - - when(httpClient.sendAsync(any(), any())).thenReturn(response); - Map<String, Permission> permissionsMap = new HashMap<>(); - permissionsMap.put("group1", Permission.MANAGE_MEMBERS); - permissionsMap.put("group2", Permission.MANAGE_MEMBERS); - client.addInvitedRegistration("bvjsgqu423", "email", permissionsMap); - // hash = AOyojiwaRR7BHPde6Tomg3+BMoQQggNM3wUHEarXuNQ= - - verify(httpClient, times(1)).sendAsync( - AdditionalMatchers.and( - endpointEq("POST", "invited-registration"), - ArgumentMatchers.argThat(req -> { - String reqbody = req.bodyPublisher().map(p -> { - var bodySubscriber = BodySubscribers.ofString(StandardCharsets.UTF_8); - var flowSubscriber = new StringSubscriber(bodySubscriber); - p.subscribe(flowSubscriber); - return bodySubscriber.getBody().toCompletableFuture().join(); - }).get(); - - // If the resulting hash contains a + symbol it has to be encoded to %2B, - // otherwise it will be interpreted as a space and wrong value will be - // stored into the database - String expectedBody = "token_hash=AOyojiwaRR7BHPde6Tomg3%2BBMoQQggNM3wUHEarXuNQ=" - + "&email=email&groups=group2 MANAGE_MEMBERS\n" - + "group1 MANAGE_MEMBERS"; - - return reqbody.equals(expectedBody); - })), any()); - } - - /** - * Credit: https://stackoverflow.com/a/55816685/771431 - */ - static final class StringSubscriber implements Flow.Subscriber<ByteBuffer> { - - final BodySubscriber<String> wrapped; - - StringSubscriber(BodySubscriber<String> wrapped) { - this.wrapped = wrapped; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - wrapped.onSubscribe(subscription); - } - - @Override - public void onNext(ByteBuffer item) { - wrapped.onNext(List.of(item)); - } - - @Override - public void onError(Throwable throwable) { - wrapped.onError(throwable); - } - - @Override - public void onComplete() { - wrapped.onComplete(); - } - } - - private HttpResponse getMockedResponse(int statusCode, String body) { - HttpResponse response = getMockedResponse(statusCode); - InputStream in = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)); - when(response.body()).thenReturn(in); - return response; - } - - private HttpResponse getMockedResponse(int statusCode) { - HttpResponse response = mock(HttpResponse.class); - when(response.statusCode()).thenReturn(statusCode); - return response; - } - - private HttpRequest endpointEq(String expectedMethod, String expectedEndpoint) { - return ArgumentMatchers.argThat(endpointEqArgumentMatcher(expectedMethod, expectedEndpoint)); - } - - private ArgumentMatcher<HttpRequest> endpointEqArgumentMatcher(String expectedMethod, String expectedEndpoint) { - - return new ArgumentMatcher<HttpRequest>() { - - private final String expectedUri = BASE_URL + "/" + expectedEndpoint; - - @Override - public boolean matches(HttpRequest request) { - return expectedMethod.equals(request.method()) && expectedUri.equals(request.uri().toString()); - } - - @Override - public String toString() { - return expectedMethod + " " + expectedUri; - } - }; - } -} diff --git a/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/HttpClientWrapperTest.java b/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/HttpClientWrapperTest.java deleted file mode 100644 index 4bc0924..0000000 --- a/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/HttpClientWrapperTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import static org.junit.Assert.assertEquals; -import org.junit.Test; - -public class HttpClientWrapperTest { - - @Test - public void testExtractAccessToken() { - String response = "{\"access_token\":\"TEST_TOKEN\",\"token_type\":\"Bearer\",\"expires_in\":3600}"; - - HttpClientWrapper clientWrapper = new HttpClientWrapper("http://localhost"); - assertEquals("TEST_TOKEN", clientWrapper.getAccessTokenFromResponse(response)); - } -} diff --git a/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/MockedHttpClientWrapper.java b/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/MockedHttpClientWrapper.java deleted file mode 100644 index d287f90..0000000 --- a/gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/MockedHttpClientWrapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package it.inaf.ia2.gms.client.call; - -import java.net.http.HttpClient; - -public class MockedHttpClientWrapper extends HttpClientWrapper { - - private final HttpClient mockedClient; - - public MockedHttpClientWrapper(String baseGmsUri, HttpClient mockedClient) { - super(baseGmsUri); - this.mockedClient = mockedClient; - } - - @Override - HttpClient getClient() { - return mockedClient; - } -} diff --git a/gms-client/gms-client/pom.xml b/gms-client/gms-client/pom.xml new file mode 100644 index 0000000..4edf264 --- /dev/null +++ b/gms-client/gms-client/pom.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>it.inaf.ia2</groupId> + <artifactId>gms-client</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>jar</packaging> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>14</maven.compiler.source> + <maven.compiler.target>14</maven.compiler.target> + <junit-jupiter.version>5.6.0</junit-jupiter.version> + <mockito.version>3.5.13</mockito.version> + </properties> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>rap-client</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>${junit-jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <version>${junit-jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit-jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-inline</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.8.6</version> + <executions> + <execution> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>report</id> + <phase>test</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.22.2</version> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/GmsClient.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/GmsClient.java new file mode 100644 index 0000000..cfe275a --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/GmsClient.java @@ -0,0 +1,159 @@ +package it.inaf.ia2.gms.client; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.inaf.ia2.client.BaseClient; +import it.inaf.ia2.gms.client.call.AddInvitedRegistrationCall; +import it.inaf.ia2.gms.client.call.AddMemberCall; +import it.inaf.ia2.gms.client.call.AddPermissionCall; +import it.inaf.ia2.gms.client.call.CreateGroupCall; +import it.inaf.ia2.gms.client.call.DeleteGroupCall; +import it.inaf.ia2.gms.client.call.GetGroupPermissionsCall; +import it.inaf.ia2.gms.client.call.GetMemberEmailAddresses; +import it.inaf.ia2.gms.client.call.GetUserGroupsCall; +import it.inaf.ia2.gms.client.call.GetUserPermissionsCall; +import it.inaf.ia2.gms.client.call.ListGroupsCall; +import it.inaf.ia2.gms.client.call.RemoveMemberCall; +import it.inaf.ia2.gms.client.call.RemovePermissionCall; +import it.inaf.ia2.gms.client.call.SetPermissionCall; +import it.inaf.ia2.gms.client.model.GroupPermission; +import it.inaf.ia2.gms.client.model.Permission; +import it.inaf.ia2.gms.client.model.UserPermission; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; + +public class GmsClient extends BaseClient { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private String accessToken; + + public GmsClient(String gmsBaseUri) { + super(gmsBaseUri); + } + + public GmsClient setAccessToken(String accessToken) { + this.accessToken = accessToken; + return this; + } + + public List<String> getMyGroups(String prefix) { + return new GetUserGroupsCall(this).getUserGroups(prefix); + } + + @Override + public HttpRequest.Builder newRequest(String endpoint) { + if (accessToken == null) { + throw new IllegalStateException("Access token is null"); + } + return super.newRequest(getUri(endpoint)) + .setHeader("Authorization", "Bearer " + accessToken); + } + + @Override + public HttpRequest.Builder newRequest(URI uri) { + if (accessToken == null) { + throw new IllegalStateException("Access token is null"); + } + return super.newRequest(uri) + .setHeader("Authorization", "Bearer " + accessToken); + } + + @Override + protected <T> String getInvalidStatusCodeExceptionMessage(HttpRequest request, HttpResponse<T> response) { + return response.headers().firstValue("Content-Type") + .map(contentType -> { + try { + if (contentType.startsWith("text/plain")) { + String errorResponseBody = null; + if (response.body() instanceof String) { + errorResponseBody = (String) response.body(); + } else if (response.body() instanceof InputStream) { + errorResponseBody = new String(((InputStream) response.body()).readAllBytes(), StandardCharsets.UTF_8); + } + if (errorResponseBody != null && !errorResponseBody.isBlank()) { + return errorResponseBody; + } + } else if (contentType.startsWith("application/json") + || contentType.startsWith("text/json")) { + Map<String, Object> errorResponseBody = null; + if (response.body() instanceof String) { + errorResponseBody = MAPPER.readValue((String) response.body(), Map.class); + } else if (response.body() instanceof InputStream) { + errorResponseBody = MAPPER.readValue((InputStream) response.body(), Map.class); + } + if (errorResponseBody != null && errorResponseBody.containsKey("error")) { + return (String) errorResponseBody.get("error"); + } + } + } catch (IOException ex) { + } + return null; + }).orElse(super.getInvalidStatusCodeExceptionMessage(request, response)); + } + + public List<String> listGroups(String prefix) { + return new ListGroupsCall(this).listGroups(prefix); + } + + public List<String> getUserGroups(String userId) { + return new GetUserGroupsCall(this).getUserGroups(userId); + } + + public List<String> getUserGroups(String userId, String prefix) { + return new GetUserGroupsCall(this).getUserGroups(userId, prefix); + } + + public void createGroup(String completeGroupName, boolean leaf) { + new CreateGroupCall(this).createGroup(completeGroupName, leaf); + } + + public void deleteGroup(String completeGroupName) { + new DeleteGroupCall(this).deleteGroup(completeGroupName); + } + + public void addMember(String completeGroupName, String userId) { + new AddMemberCall(this).addMember(completeGroupName, userId); + } + + public void removeMember(String completeGroupName, String userId) { + new RemoveMemberCall(this).removeMember(completeGroupName, userId); + } + + public String addPermission(String completeGroupName, String userId, Permission permission) { + return new AddPermissionCall(this).addPermission(completeGroupName, userId, permission); + } + + public String setPermission(String completeGroupName, String userId, Permission permission) { + return new SetPermissionCall(this).setPermission(completeGroupName, userId, permission); + } + + public void removePermission(String completeGroupName, String userId) { + new RemovePermissionCall(this).removePermission(completeGroupName, userId); + } + + public List<UserPermission> getUserPermissions(String userId) { + return new GetUserPermissionsCall(this).getUserPermissions(userId); + } + + public List<GroupPermission> getGroupPermissions(String groupId) { + return new GetGroupPermissionsCall(this).getGroupPermissions(groupId); + } + + public void addInvitedRegistration(String token, String email, Map<String, Permission> groupsPermissions) { + new AddInvitedRegistrationCall(this).addInvitedRegistration(token, email, groupsPermissions); + } + + public List<String> getMemberEmailAddresses(String groupId, Permission permission) { + return new GetMemberEmailAddresses(this).getMemberEmailAddresses(groupId, permission); + } + + public Object call(HttpRequest groupsRequest, HttpResponse.BodyHandler<InputStream> ofInputStream) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } +} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java similarity index 66% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java index d0a1ad4..533eea8 100644 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddInvitedRegistrationCall.java @@ -1,8 +1,11 @@ package it.inaf.ia2.gms.client.call; +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; import it.inaf.ia2.gms.client.model.Permission; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -10,10 +13,10 @@ import java.util.Base64; import java.util.Map; import java.util.stream.Collectors; -public class AddInvitedRegistrationCall extends BaseGmsCall { +public class AddInvitedRegistrationCall extends BaseCall<GmsClient> { - public AddInvitedRegistrationCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); + public AddInvitedRegistrationCall(GmsClient client) { + super(client); } public void addInvitedRegistration(String token, String email, Map<String, Permission> groupsPermissions) { @@ -29,20 +32,13 @@ public class AddInvitedRegistrationCall extends BaseGmsCall { .stream().map(e -> e.getKey() + " " + e.getValue()) .collect(Collectors.toList())); - HttpRequest groupsRequest = newHttpRequest(endpoint) + HttpRequest groupsRequest = client.newRequest(endpoint) .header("Accept", "text/plain") .header("Content-Type", "application/x-www-form-urlencoded") - .POST(HttpRequest.BodyPublishers.ofString(bodyParams)) + .POST(BodyPublishers.ofString(bodyParams)) .build(); - getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 201) { - return true; - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to create invited registration"); - }).join(); + client.call(groupsRequest, BodyHandlers.ofInputStream(), 201, res -> true); } private String getTokenHash(String token) { diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java new file mode 100644 index 0000000..1a414cd --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddMemberCall.java @@ -0,0 +1,30 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse.BodyHandlers; + +public class AddMemberCall extends BaseCall<GmsClient> { + + public AddMemberCall(GmsClient client) { + super(client); + } + + public boolean addMember(String completeGroupName, String userId) { + + String endpoint = "membership"; + if (completeGroupName != null && !completeGroupName.isBlank()) { + endpoint += "/" + completeGroupName; + } + + HttpRequest groupsRequest = client.newRequest(endpoint) + .header("Accept", "text/plain") + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(BodyPublishers.ofString("user_id=" + userId)) + .build(); + + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 200, res -> true); + } +} diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java new file mode 100644 index 0000000..01562e6 --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/AddPermissionCall.java @@ -0,0 +1,35 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import it.inaf.ia2.gms.client.model.Permission; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublisher; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse.BodyHandlers; + +public class AddPermissionCall extends BaseCall<GmsClient> { + + public AddPermissionCall(GmsClient client) { + super(client); + } + + public String addPermission(String completeGroupName, String userId, Permission permission) { + + String endpoint = "permission"; + if (completeGroupName != null && !completeGroupName.isBlank()) { + endpoint += "/" + completeGroupName; + } + + BodyPublisher requestBody = BodyPublishers.ofString( + "user_id=" + userId + "&permission=" + permission); + + HttpRequest groupsRequest = client.newRequest(endpoint) + .header("Accept", "text/plain") + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(requestBody) + .build(); + + return client.call(groupsRequest, BodyHandlers.ofString(), 200, res -> res); + } +} diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java new file mode 100644 index 0000000..1d7a6db --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/CreateGroupCall.java @@ -0,0 +1,25 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse.BodyHandlers; + +public class CreateGroupCall extends BaseCall<GmsClient> { + + public CreateGroupCall(GmsClient client) { + super(client); + } + + public boolean createGroup(String completeGroupName, boolean leaf) { + + HttpRequest groupsRequest = client.newRequest(completeGroupName) + .header("Accept", "text/plain") + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(BodyPublishers.ofString("leaf=" + leaf)) + .build(); + + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 201, res -> true); + } +} diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java new file mode 100644 index 0000000..4b9f0d4 --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/DeleteGroupCall.java @@ -0,0 +1,23 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse.BodyHandlers; + +public class DeleteGroupCall extends BaseCall<GmsClient> { + + public DeleteGroupCall(GmsClient client) { + super(client); + } + + public boolean deleteGroup(String completeGroupName) { + + HttpRequest groupsRequest = client.newRequest(completeGroupName) + .header("Accept", "text/plain") + .DELETE() + .build(); + + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 204, res -> true); + } +} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java similarity index 60% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java index 6c0b996..d4c6838 100644 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetGroupPermissionsCall.java @@ -1,17 +1,19 @@ package it.inaf.ia2.gms.client.call; +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; import it.inaf.ia2.gms.client.model.GroupPermission; import it.inaf.ia2.gms.client.model.Permission; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Scanner; -public class GetGroupPermissionsCall extends BaseGmsCall { +public class GetGroupPermissionsCall extends BaseCall<GmsClient> { - public GetGroupPermissionsCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); + public GetGroupPermissionsCall(GmsClient client) { + super(client); } public List<GroupPermission> getGroupPermissions(String groupId) { @@ -21,21 +23,14 @@ public class GetGroupPermissionsCall extends BaseGmsCall { String endpoint = "permission"; endpoint += "/" + groupId; - HttpRequest groupsRequest = newHttpRequest(endpoint) + HttpRequest groupsRequest = client.newRequest(endpoint) .header("Accept", "text/plain") .GET() .build(); - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return response.body(); - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to retrieve groups"); - }) - .thenApply(inputStream -> { - try (Scanner scan = new Scanner(inputStream)) { + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 200, + inputStream -> { + try ( Scanner scan = new Scanner(inputStream)) { while (scan.hasNextLine()) { String line = scan.nextLine(); if (!line.isEmpty()) { @@ -48,6 +43,6 @@ public class GetGroupPermissionsCall extends BaseGmsCall { } } return groupPermissions; - }).join(); + }); } } diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java similarity index 53% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java index a69913b..c240bcc 100644 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java @@ -1,16 +1,18 @@ package it.inaf.ia2.gms.client.call; +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; import it.inaf.ia2.gms.client.model.Permission; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Scanner; -public class GetMemberEmailAddresses extends BaseGmsCall { +public class GetMemberEmailAddresses extends BaseCall<GmsClient> { - public GetMemberEmailAddresses(HttpClientWrapper clientWrapper) { - super(clientWrapper); + public GetMemberEmailAddresses(GmsClient client) { + super(client); } public List<String> getMemberEmailAddresses(String group, Permission permission) { @@ -22,21 +24,14 @@ public class GetMemberEmailAddresses extends BaseGmsCall { endpoint += "?permission=" + permission; } - HttpRequest request = newHttpRequest(endpoint) + HttpRequest request = client.newRequest(endpoint) .header("Accept", "text/plain") .GET() .build(); - return getClient().sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return response.body(); - } - logServerErrorInputStream(request, response); - throw new IllegalStateException("Unable to retrieve groups"); - }) - .thenApply(inputStream -> { - try (Scanner scan = new Scanner(inputStream)) { + return client.call(request, BodyHandlers.ofInputStream(), 200, + inputStream -> { + try ( Scanner scan = new Scanner(inputStream)) { while (scan.hasNextLine()) { String line = scan.nextLine(); if (!line.isEmpty()) { @@ -45,6 +40,6 @@ public class GetMemberEmailAddresses extends BaseGmsCall { } } return emailAddresses; - }).join(); + }); } } diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java similarity index 57% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java index 57ab0ff..a2c4934 100644 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetUserGroupsCall.java @@ -1,15 +1,17 @@ package it.inaf.ia2.gms.client.call; +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Scanner; -public class GetUserGroupsCall extends BaseGmsCall { +public class GetUserGroupsCall extends BaseCall<GmsClient> { - public GetUserGroupsCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); + public GetUserGroupsCall(GmsClient client) { + super(client); } /** @@ -20,21 +22,14 @@ public class GetUserGroupsCall extends BaseGmsCall { List<String> groups = new ArrayList<>(); - HttpRequest groupsRequest = newHttpRequest("search") + HttpRequest groupsRequest = client.newRequest("search") .header("Accept", "text/plain") .GET() .build(); - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return response.body(); - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to retrieve groups"); - }) - .thenApply(inputStream -> { - try (Scanner scan = new Scanner(inputStream)) { + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 200, + inputStream -> { + try ( Scanner scan = new Scanner(inputStream)) { while (scan.hasNextLine()) { String line = scan.nextLine(); if (!line.isEmpty()) { @@ -50,7 +45,7 @@ public class GetUserGroupsCall extends BaseGmsCall { } } return groups; - }).join(); + }); } public List<String> getUserGroups(String userId, String prefix) { @@ -63,21 +58,14 @@ public class GetUserGroupsCall extends BaseGmsCall { } endpoint += "?user_id=" + userId; - HttpRequest groupsRequest = newHttpRequest(endpoint) + HttpRequest groupsRequest = client.newRequest(endpoint) .header("Accept", "text/plain") .GET() .build(); - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return response.body(); - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to retrieve groups"); - }) - .thenApply(inputStream -> { - try (Scanner scan = new Scanner(inputStream)) { + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 200, + inputStream -> { + try ( Scanner scan = new Scanner(inputStream)) { while (scan.hasNextLine()) { String line = scan.nextLine(); if (!line.isEmpty()) { @@ -86,6 +74,6 @@ public class GetUserGroupsCall extends BaseGmsCall { } } return groups; - }).join(); + }); } } diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java similarity index 60% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java index 34db2f1..67aa39a 100644 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/GetUserPermissionsCall.java @@ -1,17 +1,19 @@ package it.inaf.ia2.gms.client.call; +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; import it.inaf.ia2.gms.client.model.Permission; import it.inaf.ia2.gms.client.model.UserPermission; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Scanner; -public class GetUserPermissionsCall extends BaseGmsCall { +public class GetUserPermissionsCall extends BaseCall<GmsClient> { - public GetUserPermissionsCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); + public GetUserPermissionsCall(GmsClient client) { + super(client); } public List<UserPermission> getUserPermissions(String userId) { @@ -21,21 +23,14 @@ public class GetUserPermissionsCall extends BaseGmsCall { String endpoint = "permission"; endpoint += "?user_id=" + userId; - HttpRequest groupsRequest = newHttpRequest(endpoint) + HttpRequest groupsRequest = client.newRequest(endpoint) .header("Accept", "text/plain") .GET() .build(); - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return response.body(); - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to retrieve groups"); - }) - .thenApply(inputStream -> { - try (Scanner scan = new Scanner(inputStream)) { + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 200, + inputStream -> { + try ( Scanner scan = new Scanner(inputStream)) { while (scan.hasNextLine()) { String line = scan.nextLine(); if (!line.isEmpty()) { @@ -48,6 +43,6 @@ public class GetUserPermissionsCall extends BaseGmsCall { } } return userPermissions; - }).join(); + }); } } diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java similarity index 55% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java index 7170eba..4b3411c 100644 --- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/ListGroupsCall.java @@ -1,15 +1,17 @@ package it.inaf.ia2.gms.client.call; +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Scanner; -public class ListGroupsCall extends BaseGmsCall { +public class ListGroupsCall extends BaseCall<GmsClient> { - public ListGroupsCall(HttpClientWrapper clientWrapper) { - super(clientWrapper); + public ListGroupsCall(GmsClient client) { + super(client); } /** @@ -26,21 +28,14 @@ public class ListGroupsCall extends BaseGmsCall { uri += "/" + prefix; } - HttpRequest groupsRequest = newHttpRequest(uri) + HttpRequest groupsRequest = client.newRequest(uri) .header("Accept", "text/plain") .GET() .build(); - return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream()) - .thenApply(response -> { - if (response.statusCode() == 200) { - return response.body(); - } - logServerErrorInputStream(groupsRequest, response); - throw new IllegalStateException("Unable to list groups"); - }) - .thenApply(inputStream -> { - try (Scanner scan = new Scanner(inputStream)) { + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 200, + inputStream -> { + try ( Scanner scan = new Scanner(inputStream)) { while (scan.hasNextLine()) { String line = scan.nextLine(); if (!line.isEmpty()) { @@ -49,6 +44,6 @@ public class ListGroupsCall extends BaseGmsCall { } } return groups; - }).join(); + }); } } diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java new file mode 100644 index 0000000..546ccfe --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemoveMemberCall.java @@ -0,0 +1,29 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse.BodyHandlers; + +public class RemoveMemberCall extends BaseCall<GmsClient> { + + public RemoveMemberCall(GmsClient client) { + super(client); + } + + public boolean removeMember(String completeGroupName, String userId) { + + String endpoint = "membership"; + if (completeGroupName != null && !completeGroupName.isBlank()) { + endpoint += "/" + completeGroupName; + } + endpoint += "?user_id=" + userId; + + HttpRequest groupsRequest = client.newRequest(endpoint) + .header("Accept", "text/plain") + .DELETE() + .build(); + + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 204, res -> true); + } +} diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java new file mode 100644 index 0000000..f950614 --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/RemovePermissionCall.java @@ -0,0 +1,29 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse.BodyHandlers; + +public class RemovePermissionCall extends BaseCall<GmsClient> { + + public RemovePermissionCall(GmsClient client) { + super(client); + } + + public boolean removePermission(String completeGroupName, String userId) { + + String endpoint = "permission"; + if (completeGroupName != null && !completeGroupName.isBlank()) { + endpoint += "/" + completeGroupName; + } + endpoint += "?user_id=" + userId; + + HttpRequest groupsRequest = client.newRequest(endpoint) + .header("Accept", "text/plain") + .DELETE() + .build(); + + return client.call(groupsRequest, BodyHandlers.ofInputStream(), 204, res -> true); + } +} diff --git a/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java new file mode 100644 index 0000000..9f62ebe --- /dev/null +++ b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java @@ -0,0 +1,33 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.client.BaseCall; +import it.inaf.ia2.gms.client.GmsClient; +import it.inaf.ia2.gms.client.model.Permission; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse.BodyHandlers; + +public class SetPermissionCall extends BaseCall<GmsClient> { + + public SetPermissionCall(GmsClient client) { + super(client); + } + + public String setPermission(String completeGroupName, String userId, Permission permission) { + + String endpoint = "permission"; + if (completeGroupName != null && !completeGroupName.isBlank()) { + endpoint += "/" + completeGroupName; + } + + HttpRequest.BodyPublisher requestBody = HttpRequest.BodyPublishers.ofString( + "user_id=" + userId + "&permission=" + permission); + + HttpRequest groupsRequest = client.newRequest(endpoint) + .header("Accept", "text/plain") + .header("Content-Type", "application/x-www-form-urlencoded") + .PUT(requestBody) + .build(); + + return client.call(groupsRequest, BodyHandlers.ofString(), 200, res -> res); + } +} diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/GroupPermission.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/model/GroupPermission.java similarity index 100% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/GroupPermission.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/model/GroupPermission.java diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Permission.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/model/Permission.java similarity index 100% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/Permission.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/model/Permission.java diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/UserPermission.java b/gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/model/UserPermission.java similarity index 100% rename from gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/model/UserPermission.java rename to gms-client/gms-client/src/main/java/it/inaf/ia2/gms/client/model/UserPermission.java diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/BaseGmsClientTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/BaseGmsClientTest.java new file mode 100644 index 0000000..69e22fe --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/BaseGmsClientTest.java @@ -0,0 +1,101 @@ +package it.inaf.ia2.gms.client; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import org.mockito.ArgumentMatcher; +import org.mockito.ArgumentMatchers; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BaseGmsClientTest { + + private static final String BASE_URL = "http://base-url"; + + protected HttpClient httpClient; + protected GmsClient gmsClient; + + public void init() { + httpClient = mock(HttpClient.class); + gmsClient = getMockedGmsClient(httpClient); + } + + protected static String getResourceFileContent(String fileName) { + try ( InputStream in = BaseGmsClientTest.class.getClassLoader().getResourceAsStream(fileName)) { + return new String(in.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + protected static GmsClient getMockedGmsClient(HttpClient mockedHttpClient) { + + HttpClient.Builder builder = mock(HttpClient.Builder.class); + when(builder.followRedirects(any())).thenReturn(builder); + when(builder.version(any())).thenReturn(builder); + when(builder.build()).thenReturn(mockedHttpClient); + + try ( MockedStatic<HttpClient> staticMock = Mockito.mockStatic(HttpClient.class)) { + staticMock.when(HttpClient::newBuilder).thenReturn(builder); + return new GmsClient(BASE_URL).setAccessToken("foo"); + } + } + + protected static CompletableFuture<HttpResponse<InputStream>> getMockedStreamResponseFuture(int statusCode, String body) { + return CompletableFuture.completedFuture(getMockedStreamResponse(200, body)); + } + + protected static CompletableFuture<HttpResponse<String>> getMockedStringResponseFuture(int statusCode, String body) { + return CompletableFuture.completedFuture(getMockedStringResponse(200, body)); + } + + protected static HttpResponse<InputStream> getMockedStreamResponse(int statusCode, String body) { + HttpResponse response = getMockedResponse(statusCode); + InputStream in = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)); + when(response.body()).thenReturn(in); + return response; + } + + protected static HttpResponse<String> getMockedStringResponse(int statusCode, String body) { + HttpResponse response = getMockedResponse(statusCode); + when(response.body()).thenReturn(body); + return response; + } + + protected static HttpResponse getMockedResponse(int statusCode) { + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(statusCode); + return response; + } + + protected static HttpRequest endpointEq(String expectedMethod, String expectedEndpoint) { + return ArgumentMatchers.argThat(endpointEqArgumentMatcher(expectedMethod, expectedEndpoint)); + } + + protected static ArgumentMatcher<HttpRequest> endpointEqArgumentMatcher(String expectedMethod, String expectedEndpoint) { + + return new ArgumentMatcher<HttpRequest>() { + + private final String expectedUri = BASE_URL + "/" + expectedEndpoint; + + @Override + public boolean matches(HttpRequest request) { + return expectedMethod.equals(request.method()) && expectedUri.equals(request.uri().toString()); + } + + @Override + public String toString() { + return expectedMethod + " " + expectedUri; + } + }; + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddMemberTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddMemberTest.java new file mode 100644 index 0000000..250eec2 --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddMemberTest.java @@ -0,0 +1,33 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class AddMemberTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testAddMember() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(200)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + gmsClient.addMember("LBT.INAF", "user"); + + verify(httpClient, times(1)).sendAsync(endpointEq("POST", "membership/LBT.INAF"), any()); + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddPermissionTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddPermissionTest.java new file mode 100644 index 0000000..04131a8 --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/AddPermissionTest.java @@ -0,0 +1,34 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import it.inaf.ia2.gms.client.model.Permission; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class AddPermissionTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testAddPermission() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(200)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + gmsClient.addPermission("LBT.INAF", "user", Permission.ADMIN); + + verify(httpClient, times(1)).sendAsync(endpointEq("POST", "permission/LBT.INAF"), any()); + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/CreateGroupTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/CreateGroupTest.java new file mode 100644 index 0000000..dfd3fd0 --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/CreateGroupTest.java @@ -0,0 +1,33 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class CreateGroupTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testCreateGroup() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(201)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + gmsClient.createGroup("LBT.INAF", false); + + verify(httpClient, times(1)).sendAsync(endpointEq("POST", "LBT.INAF"), any()); + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/DeleteGroupTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/DeleteGroupTest.java new file mode 100644 index 0000000..dd87b4e --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/DeleteGroupTest.java @@ -0,0 +1,33 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class DeleteGroupTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testDeleteGroup() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(204)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + gmsClient.deleteGroup("LBT.INAF"); + + verify(httpClient, times(1)).sendAsync(endpointEq("DELETE", "LBT.INAF"), any()); + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/GetUserGroupsTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/GetUserGroupsTest.java new file mode 100644 index 0000000..7741eb4 --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/GetUserGroupsTest.java @@ -0,0 +1,61 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class GetUserGroupsTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testGetMyGroups() { + + String body = "LBT.INAF\n" + + "LBT.AZ\n" + + ""; + + CompletableFuture response = CompletableFuture.completedFuture(getMockedStreamResponse(200, body)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + List<String> groups = gmsClient.getMyGroups("LBT."); + + verify(httpClient, times(1)).sendAsync(endpointEq("GET", "search"), any()); + + assertEquals(2, groups.size()); + assertEquals("INAF", groups.get(0)); + assertEquals("AZ", groups.get(1)); + } + + @Test + public void testListGroups() { + + String body = "INAF\n" + + "AZ"; + + CompletableFuture response = CompletableFuture.completedFuture(getMockedStreamResponse(200, body)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + List<String> groups = gmsClient.listGroups("LBT."); + + verify(httpClient, times(1)).sendAsync(endpointEq("GET", "list/LBT."), any()); + + assertEquals(2, groups.size()); + assertEquals("INAF", groups.get(0)); + assertEquals("AZ", groups.get(1)); + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/InvitedRegistrationTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/InvitedRegistrationTest.java new file mode 100644 index 0000000..b234777 --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/InvitedRegistrationTest.java @@ -0,0 +1,98 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import it.inaf.ia2.gms.client.model.Permission; +import java.net.http.HttpResponse; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Flow; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.AdditionalMatchers; +import org.mockito.ArgumentMatchers; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class InvitedRegistrationTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testInvitedRegistration() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(201)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + Map<String, Permission> permissionsMap = new HashMap<>(); + permissionsMap.put("group1", Permission.MANAGE_MEMBERS); + permissionsMap.put("group2", Permission.MANAGE_MEMBERS); + gmsClient.addInvitedRegistration("bvjsgqu423", "email", permissionsMap); + // hash = AOyojiwaRR7BHPde6Tomg3+BMoQQggNM3wUHEarXuNQ= + + verify(httpClient, times(1)).sendAsync( + AdditionalMatchers.and( + endpointEq("POST", "invited-registration"), + ArgumentMatchers.argThat(req -> { + String reqbody = req.bodyPublisher().map(p -> { + var bodySubscriber = HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8); + var flowSubscriber = new StringSubscriber(bodySubscriber); + p.subscribe(flowSubscriber); + return bodySubscriber.getBody().toCompletableFuture().join(); + }).get(); + + // If the resulting hash contains a + symbol it has to be encoded to %2B, + // otherwise it will be interpreted as a space and wrong value will be + // stored into the database + String expectedBody = "token_hash=AOyojiwaRR7BHPde6Tomg3%2BBMoQQggNM3wUHEarXuNQ=" + + "&email=email&groups=group2 MANAGE_MEMBERS\n" + + "group1 MANAGE_MEMBERS"; + + return reqbody.equals(expectedBody); + })), any()); + } + + /** + * Credit: https://stackoverflow.com/a/55816685/771431 + */ + static final class StringSubscriber implements Flow.Subscriber<ByteBuffer> { + + final HttpResponse.BodySubscriber<String> wrapped; + + StringSubscriber(HttpResponse.BodySubscriber<String> wrapped) { + this.wrapped = wrapped; + } + + @Override + public void onSubscribe(Flow.Subscription subscription) { + wrapped.onSubscribe(subscription); + } + + @Override + public void onNext(ByteBuffer item) { + wrapped.onNext(List.of(item)); + } + + @Override + public void onError(Throwable throwable) { + wrapped.onError(throwable); + } + + @Override + public void onComplete() { + wrapped.onComplete(); + } + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemoveMemberTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemoveMemberTest.java new file mode 100644 index 0000000..298909e --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemoveMemberTest.java @@ -0,0 +1,33 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class RemoveMemberTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testRemoveMember() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(204)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + gmsClient.removeMember("LBT.INAF", "user"); + + verify(httpClient, times(1)).sendAsync(endpointEq("DELETE", "membership/LBT.INAF?user_id=user"), any()); + } +} diff --git a/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemovePermissionTest.java b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemovePermissionTest.java new file mode 100644 index 0000000..d48577c --- /dev/null +++ b/gms-client/gms-client/src/test/java/it/inaf/ia2/gms/client/call/RemovePermissionTest.java @@ -0,0 +1,33 @@ +package it.inaf.ia2.gms.client.call; + +import it.inaf.ia2.gms.client.BaseGmsClientTest; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class RemovePermissionTest extends BaseGmsClientTest { + + @BeforeEach + @Override + public void init() { + super.init(); + } + + @Test + public void testRemovePermission() { + + CompletableFuture response = CompletableFuture.completedFuture(getMockedResponse(204)); + + when(httpClient.sendAsync(any(), any())).thenReturn(response); + gmsClient.removePermission("LBT.INAF", "user"); + + verify(httpClient, times(1)).sendAsync(endpointEq("DELETE", "permission/LBT.INAF?user_id=user"), any()); + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/Identity.java b/gms/src/main/java/it/inaf/ia2/gms/model/Identity.java deleted file mode 100644 index c879da9..0000000 --- a/gms/src/main/java/it/inaf/ia2/gms/model/Identity.java +++ /dev/null @@ -1,59 +0,0 @@ -package it.inaf.ia2.gms.model; - -public class Identity { - - private IdentityType type; - private String typedId; - private String email; - private String name; - private String surname; - private boolean primary; - - public IdentityType getType() { - return type; - } - - public void setType(IdentityType type) { - this.type = type; - } - - public String getTypedId() { - return typedId; - } - - public void setTypedId(String typedId) { - this.typedId = typedId; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getSurname() { - return surname; - } - - public void setSurname(String surname) { - this.surname = surname; - } - - public boolean isPrimary() { - return primary; - } - - public void setPrimary(boolean primary) { - this.primary = primary; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/IdentityType.java b/gms/src/main/java/it/inaf/ia2/gms/model/IdentityType.java deleted file mode 100644 index f5c80c8..0000000 --- a/gms/src/main/java/it/inaf/ia2/gms/model/IdentityType.java +++ /dev/null @@ -1,38 +0,0 @@ -package it.inaf.ia2.gms.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Arrays; - -public enum IdentityType { - - EDU_GAIN("eduGAIN"), - X509("X.509"), - ORCID("OrcID"), - GOOGLE("Google"), - LINKEDIN("LinkedIn"), - FACEBOOK("Facebook"), - LOCAL_IDP("LocalIdP"); - - private final String value; - - IdentityType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - @JsonCreator - public static IdentityType forValue(String value) { - return Arrays.stream(IdentityType.values()) - .filter(it -> value.equals(it.value)).findFirst() - .orElseThrow(() -> new IllegalArgumentException("Unsupported IdentityType " + value)); - } - - @JsonValue - public String toValue() { - return value; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/RapUser.java b/gms/src/main/java/it/inaf/ia2/gms/model/RapUser.java deleted file mode 100644 index 846b317..0000000 --- a/gms/src/main/java/it/inaf/ia2/gms/model/RapUser.java +++ /dev/null @@ -1,63 +0,0 @@ -package it.inaf.ia2.gms.model; - -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -public class RapUser { - - private String id; - private List<Identity> identities; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public List<Identity> getIdentities() { - return identities; - } - - public void setIdentities(List<Identity> identities) { - this.identities = identities; - } - - public String getDisplayName() { - - String displayName = null; - - // trying to extract name and surname - for (Identity identity : identities) { - if (identity.getName() != null && identity.getSurname() != null) { - displayName = String.format("%s %s", identity.getName(), identity.getSurname()); - if (identity.isPrimary()) { // prefer always primary - break; - } - } - } - - if (displayName == null) { // No name and surname --> using primary email - displayName = getPrimaryEmail(); - } - - // Adding types - Set<String> types = identities.stream().map(i -> { - if (i.getType() == IdentityType.EDU_GAIN && i.getTypedId().endsWith("@ia2.inaf.it")) { - return "IA2"; - } - return i.getType().getValue(); - }).collect(Collectors.toSet()); - displayName += String.format(" (%s)", String.join(", ", types)); - - return displayName; - } - - public String getPrimaryEmail() { - Identity primaryIdentity = identities.stream().filter(i -> i.isPrimary()).findFirst() - .orElseThrow(() -> new IllegalStateException("No primary identity for user " + id)); - return primaryIdentity.getEmail(); - } -} -- GitLab