From 75c003fe49cbe24563888332f3d2a94130fef7b8 Mon Sep 17 00:00:00 2001 From: Adam Korynta Date: Tue, 6 Jan 2026 15:16:53 -0800 Subject: [PATCH] add ability to get current user profile from CDA --- .../controllers/UserProfileController.java | 51 +++++ .../TestUserProfileController.java | 48 +++++ .../resources/radar/v1/json/user_profile.json | 31 +++ .../hec/cwms/data/api/client/model/User.java | 177 ++++++++++++++++++ 4 files changed, 307 insertions(+) create mode 100644 cwms-data-api-client/src/main/java/mil/army/usace/hec/cwms/data/api/client/controllers/UserProfileController.java create mode 100644 cwms-data-api-client/src/test/java/mil/army/usace/hec/cwms/data/api/client/controllers/TestUserProfileController.java create mode 100644 cwms-data-api-client/src/test/resources/radar/v1/json/user_profile.json create mode 100644 cwms-data-api-model/src/main/java/mil/army/usace/hec/cwms/data/api/client/model/User.java diff --git a/cwms-data-api-client/src/main/java/mil/army/usace/hec/cwms/data/api/client/controllers/UserProfileController.java b/cwms-data-api-client/src/main/java/mil/army/usace/hec/cwms/data/api/client/controllers/UserProfileController.java new file mode 100644 index 00000000..bb6f88d9 --- /dev/null +++ b/cwms-data-api-client/src/main/java/mil/army/usace/hec/cwms/data/api/client/controllers/UserProfileController.java @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (c) 2026 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package mil.army.usace.hec.cwms.data.api.client.controllers; + +import static mil.army.usace.hec.cwms.data.api.client.controllers.CdaEndpointConstants.ACCEPT_HEADER_JSON; +import static mil.army.usace.hec.cwms.data.api.client.controllers.CdaEndpointConstants.ACCEPT_QUERY_HEADER; + +import java.io.IOException; +import mil.army.usace.hec.cwms.data.api.client.model.RadarObjectMapper; +import mil.army.usace.hec.cwms.data.api.client.model.User; +import mil.army.usace.hec.cwms.http.client.ApiConnectionInfo; +import mil.army.usace.hec.cwms.http.client.HttpRequestBuilderImpl; +import mil.army.usace.hec.cwms.http.client.HttpRequestResponse; +import mil.army.usace.hec.cwms.http.client.request.HttpRequestExecutor; + +public final class UserProfileController { + + private static final String USER_PROFILE_ENDPOINT = "user/profile"; + + public User retrieveCurrentUserProfile(ApiConnectionInfo apiConnectionInfo) + throws IOException { + HttpRequestExecutor executor = new HttpRequestBuilderImpl(apiConnectionInfo, USER_PROFILE_ENDPOINT) + .addQueryHeader(ACCEPT_QUERY_HEADER, ACCEPT_HEADER_JSON) + .get(); + try (HttpRequestResponse response = executor.execute()) { + return RadarObjectMapper.mapJsonToObject(response.getBody(), User.class); + } + } +} diff --git a/cwms-data-api-client/src/test/java/mil/army/usace/hec/cwms/data/api/client/controllers/TestUserProfileController.java b/cwms-data-api-client/src/test/java/mil/army/usace/hec/cwms/data/api/client/controllers/TestUserProfileController.java new file mode 100644 index 00000000..6180046a --- /dev/null +++ b/cwms-data-api-client/src/test/java/mil/army/usace/hec/cwms/data/api/client/controllers/TestUserProfileController.java @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (c) 2026 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package mil.army.usace.hec.cwms.data.api.client.controllers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import mil.army.usace.hec.cwms.data.api.client.model.User; +import org.junit.jupiter.api.Test; + +class TestUserProfileController extends TestController { + + @Test + void testRetrieveCatalog() throws IOException { + String collect = readJsonFile("radar/v1/json/user_profile.json"); + mockHttpServer.enqueue(collect); + mockHttpServer.start(); + User user = new UserProfileController().retrieveCurrentUserProfile(buildConnectionInfo()); + assertNotNull(user); + assertEquals("M5HECTEST", user.getUserName()); + assertFalse(user.isCacAuth()); + assertFalse(user.getRoles().get("SWT").isEmpty()); + } +} diff --git a/cwms-data-api-client/src/test/resources/radar/v1/json/user_profile.json b/cwms-data-api-client/src/test/resources/radar/v1/json/user_profile.json new file mode 100644 index 00000000..ee01df2f --- /dev/null +++ b/cwms-data-api-client/src/test/resources/radar/v1/json/user_profile.json @@ -0,0 +1,31 @@ +{ + "user-name": "M5HECTEST", + "cac-auth": false, + "roles": { + "SWT": [ + "All Users", + "CWMS DBA Users", + "CWMS PD Users", + "CWMS Users", + "TS ID Creator" + ], + "MVP": [ + "All Users", + "CWMS DBA Users", + "CWMS PD Users", + "CWMS Users" + ], + "HQ": [ + "All Users", + "CWMS DBA Users", + "CWMS PD Users", + "CWMS Users" + ], + "SPK": [ + "All Users", + "CWMS DBA Users", + "CWMS PD Users", + "CWMS Users" + ] + } +} \ No newline at end of file diff --git a/cwms-data-api-model/src/main/java/mil/army/usace/hec/cwms/data/api/client/model/User.java b/cwms-data-api-model/src/main/java/mil/army/usace/hec/cwms/data/api/client/model/User.java new file mode 100644 index 00000000..31a75298 --- /dev/null +++ b/cwms-data-api-model/src/main/java/mil/army/usace/hec/cwms/data/api/client/model/User.java @@ -0,0 +1,177 @@ +/* + * MIT License + * + * Copyright (c) 2026 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package mil.army.usace.hec.cwms.data.api.client.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * User + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@jakarta.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2025-12-19T13:08:07.460137300-08:00[America/Los_Angeles]") +public class User { + + @JsonProperty("user-name") + private String userName = null; + + @JsonProperty("principal") + private String principal = null; + + @JsonProperty("cac-auth") + private Boolean cacAuth = null; + + @JsonProperty("email") + private String email = null; + + @JsonProperty("roles") + @Valid + private Map> roles = new HashMap<>(); + + public User userName(String userName) { + this.userName = userName; + return this; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public User principal(String principal) { + this.principal = principal; + return this; + } + + public String getPrincipal() { + return principal; + } + + public void setPrincipal(String principal) { + this.principal = principal; + } + + public User cacAuth(Boolean cacAuth) { + this.cacAuth = cacAuth; + return this; + } + + public Boolean isCacAuth() { + return cacAuth; + } + + public void setCacAuth(Boolean cacAuth) { + this.cacAuth = cacAuth; + } + + public User email(String email) { + this.email = email; + return this; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public User roles(Map> roles) { + this.roles = roles; + return this; + } + + public User putRolesItem(String key, List rolesItem) { + if (this.roles == null) { + this.roles = new HashMap<>(); + } + this.roles.put(key, rolesItem); + return this; + } + + public Map> getRoles() { + return roles; + } + + public void setRoles(Map> roles) { + this.roles = roles; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return this.userName == null || user.userName == null?Objects.equals(this.userName, user.userName):this.userName.equalsIgnoreCase(user.userName) + && this.principal == null || user.principal == null?Objects.equals(this.principal, user.principal):this.principal.equalsIgnoreCase(user.principal) + && Objects.equals(this.cacAuth, user.cacAuth) + && this.email == null || user.email == null?Objects.equals(this.email, user.email):this.email.equalsIgnoreCase(user.email) + && Objects.equals(this.roles, user.roles) + ; + } + + @Override + public int hashCode() { + return Objects.hash(userName==null?0:userName.toLowerCase(), principal==null?0:principal.toLowerCase(), cacAuth, email==null?0:email.toLowerCase(), roles); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" userName: ").append(toIndentedString(userName)).append("\n"); + sb.append(" principal: ").append(toIndentedString(principal)).append("\n"); + sb.append(" cacAuth: ").append(toIndentedString(cacAuth)).append("\n"); + sb.append(" email: ").append(toIndentedString(email)).append("\n"); + sb.append(" roles: ").append(toIndentedString(roles)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +}