From 8c206b398a5f517aa59edd9a01b1d8487f2e2670 Mon Sep 17 00:00:00 2001 From: JordenReuter <149687553+JordenReuter@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:30:52 +0100 Subject: [PATCH] feat: get specific user-menu by key (#46) --- .../UserMenuInternalController.java | 15 +++- .../rs/user/mappers/UserMenuMapper.java | 13 +++- .../rs/user/services/ClaimService.java | 2 +- .../rs/user/services/MenuMappingConfig.java | 27 ++++++++ .../rs/user/services/TokenConfig.java | 68 +++++++++++++------ .../rs/user/services/TokenService.java | 8 +-- .../openapi/onecx-user-internal-openapi.yaml | 4 ++ src/main/resources/application.properties | 6 ++ .../UserMenuInternalControllerTest.java | 58 ++++++++++++++++ 9 files changed, 172 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/tkit/onecx/workspace/rs/user/services/MenuMappingConfig.java diff --git a/src/main/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalController.java b/src/main/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalController.java index 681f140..2202b66 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalController.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalController.java @@ -23,6 +23,7 @@ import org.tkit.onecx.workspace.domain.models.AssignmentMenu; import org.tkit.onecx.workspace.rs.user.mappers.ExceptionMapper; import org.tkit.onecx.workspace.rs.user.mappers.UserMenuMapper; +import org.tkit.onecx.workspace.rs.user.services.MenuMappingConfig; import org.tkit.onecx.workspace.rs.user.services.TokenService; import org.tkit.quarkus.log.cdi.LogExclude; import org.tkit.quarkus.log.cdi.LogService; @@ -53,9 +54,20 @@ public class UserMenuInternalController implements UserMenuInternalApi { @Inject UserMenuMapper mapper; + @Inject + MenuMappingConfig mappingConfig; + @Override public Response getUserMenu(String workspaceName, @LogExclude UserWorkspaceMenuRequestDTO userWorkspaceMenuRequestDTO) { var roles = tokenService.getTokenRoles(userWorkspaceMenuRequestDTO.getToken()); + HashSet menuKeys = new HashSet<>(); + if (userWorkspaceMenuRequestDTO.getMenuKeys() != null) { + userWorkspaceMenuRequestDTO.getMenuKeys().forEach(s -> { + if (mappingConfig.userConfig().mapping().containsKey(s)) { + menuKeys.add(mappingConfig.userConfig().mapping().get(s)); + } + }); + } var workspace = workspaceDAO.findByName(workspaceName); if (workspace == null) { @@ -75,7 +87,8 @@ public Response getUserMenu(String workspaceName, @LogExclude UserWorkspaceMenuR criteria.setWorkspaceId(workspace.getId()); var items = menuItemDAO.loadAllMenuItemsByCriteria(criteria); - return Response.ok(mapper.mapTree(workspaceName, items, mapping, new HashSet<>(roles))).build(); + return Response.ok(mapper.mapTree(workspaceName, items, mapping, new HashSet<>(roles), menuKeys)) + .build(); } @ServerExceptionMapper diff --git a/src/main/java/org/tkit/onecx/workspace/rs/user/mappers/UserMenuMapper.java b/src/main/java/org/tkit/onecx/workspace/rs/user/mappers/UserMenuMapper.java index 80986a4..b24da6b 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/user/mappers/UserMenuMapper.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/user/mappers/UserMenuMapper.java @@ -22,13 +22,20 @@ default UserWorkspaceMenuStructureDTO empty(String workspaceName) { } default UserWorkspaceMenuStructureDTO mapTree(String workspaceName, Collection entities, - Map> mapping, Set roles) { + Map> mapping, Set roles, Set mappingKeys) { UserWorkspaceMenuStructureDTO dto = empty(workspaceName); if (entities.isEmpty()) { return dto; } - - var items = entities.stream().filter(m -> m.getParentId() == null).collect(Collectors.toSet()); + Set items; + if (!mappingKeys.isEmpty()) { + items = entities.stream().filter(m -> m.getParentId() == null) + .filter(m -> mappingKeys.contains(m.getKey())) + .collect(Collectors.toSet()); + } else { + items = entities.stream().filter(m -> m.getParentId() == null) + .collect(Collectors.toSet()); + } items = filterMenu(items, mapping, roles); if (items.isEmpty()) { return dto; diff --git a/src/main/java/org/tkit/onecx/workspace/rs/user/services/ClaimService.java b/src/main/java/org/tkit/onecx/workspace/rs/user/services/ClaimService.java index aab1e7e..6358e0c 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/user/services/ClaimService.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/user/services/ClaimService.java @@ -20,7 +20,7 @@ public class ClaimService { @PostConstruct @SuppressWarnings("java:S2696") public void init() { - claimPath = splitClaimPath(config.claimPath()); + claimPath = splitClaimPath(config.token().claimPath()); } public String[] getClaimPath() { diff --git a/src/main/java/org/tkit/onecx/workspace/rs/user/services/MenuMappingConfig.java b/src/main/java/org/tkit/onecx/workspace/rs/user/services/MenuMappingConfig.java new file mode 100644 index 0000000..8b4fb68 --- /dev/null +++ b/src/main/java/org/tkit/onecx/workspace/rs/user/services/MenuMappingConfig.java @@ -0,0 +1,27 @@ +package org.tkit.onecx.workspace.rs.user.services; + +import java.util.Map; + +import io.quarkus.runtime.annotations.StaticInitSafe; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithName; + +@StaticInitSafe +@ConfigMapping(prefix = "onecx.workspace") +public interface MenuMappingConfig { + /** + * + * @return user configs + */ + @WithName("user.menu") + UserConfig userConfig(); + + interface UserConfig { + /** + * + * @return menu mapping keys + */ + @WithName("mapping") + Map mapping(); + } +} diff --git a/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenConfig.java b/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenConfig.java index 379196d..395a032 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenConfig.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenConfig.java @@ -8,25 +8,53 @@ import io.smallrye.config.WithName; @StaticInitSafe -@ConfigMapping(prefix = "onecx.workspace.token") +@ConfigMapping(prefix = "onecx.workspace") public interface TokenConfig { - - @WithName("verified") - @WithDefault("false") - boolean verified(); - - @WithName("issuer.public-key-location.suffix") - @WithDefault("/protocol/openid-connect/certs") - String publicKeyLocationSuffix(); - - @WithName("issuer.public-key-location.enabled") - @WithDefault("false") - boolean publicKeyEnabled(); - - @WithName("claim.separator") - Optional claimSeparator(); - - @WithName("claim.path") - @WithDefault("realm_access/roles") - String claimPath(); + /** + * + * @return token configs + */ + @WithName("token") + Token token(); + + interface Token { + /** + * + * @return verification status + */ + @WithName("verified") + @WithDefault("false") + boolean verified(); + + /** + * + * @return suffix of public key + */ + @WithName("issuer.public-key-location.suffix") + @WithDefault("/protocol/openid-connect/certs") + String publicKeyLocationSuffix(); + + /** + * + * @return status if public key is enabled + */ + @WithName("issuer.public-key-location.enabled") + @WithDefault("false") + boolean publicKeyEnabled(); + + /** + * + * @return separator + */ + @WithName("claim.separator") + Optional claimSeparator(); + + /** + * + * @return claim path + */ + @WithName("claim.path") + @WithDefault("realm_access/roles") + String claimPath(); + } } diff --git a/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenService.java b/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenService.java index ffdef05..a9af0c5 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenService.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/user/services/TokenService.java @@ -36,13 +36,13 @@ public List getTokenRoles(String tokenData) { } var request = new TokenParserRequest(token) - .verify(config.verified()) - .issuerEnabled(config.publicKeyEnabled()) - .issuerSuffix(config.publicKeyLocationSuffix()); + .verify(config.token().verified()) + .issuerEnabled(config.token().publicKeyEnabled()) + .issuerSuffix(config.token().publicKeyLocationSuffix()); var permissionToken = tokenParserService.parseToken(request); var path = claimService.getClaimPath(); - return TokenClaimUtility.findClaimStringList(permissionToken, path, config.claimSeparator().orElse(" ")); + return TokenClaimUtility.findClaimStringList(permissionToken, path, config.token().claimSeparator().orElse(" ")); } catch (Exception ex) { throw new TokenException("Error parsing permission token", ex); diff --git a/src/main/openapi/onecx-user-internal-openapi.yaml b/src/main/openapi/onecx-user-internal-openapi.yaml index 358626c..fb3beff 100644 --- a/src/main/openapi/onecx-user-internal-openapi.yaml +++ b/src/main/openapi/onecx-user-internal-openapi.yaml @@ -49,6 +49,10 @@ components: properties: token: type: string + menuKeys: + type: array + items: + type: string UserWorkspaceMenuStructure: type: object properties: diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index be71001..8e9069a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -19,6 +19,10 @@ onecx.workspace.token.claim.path=realm_access/roles onecx.workspace.token.issuer.public-key-location.enabled=false onecx.workspace.token.issuer.public-key-location.suffix=/protocol/openid-connect/certs +onecx.workspace.user.menu.mapping.main-menu=PORTAL_MAIN_MENU +onecx.workspace.user.menu.mapping.user-profile-menu=USER_PROFILE_MENU +onecx.workspace.user.menu.mapping.footer-menu=PORTAL_FOOTER_MENU + tkit.dataimport.enabled=false tkit.dataimport.configurations.workspace.file=dev-data.import.json tkit.dataimport.configurations.workspace.metadata.operation=CLEAN_INSERT @@ -55,6 +59,8 @@ tkit.rs.context.tenant-id.enabled=true %test.tkit.rs.context.tenant-id.mock.data.org2=tenant-200 %test.tkit.rs.context.tenant-id.mock.data.org3=tenant-300 +%test.onecx.workspace.user.menu.mapping.main-menu=key42 + # TEST-IT (integration tests) quarkus.test.integration-test-profile=test diff --git a/src/test/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalControllerTest.java b/src/test/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalControllerTest.java index d879dd4..f1f7504 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalControllerTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/user/controllers/UserMenuInternalControllerTest.java @@ -161,6 +161,64 @@ void getMenuStructureForUserIdTest() { assertThat(countMenuItems(data.getMenu())).isEqualTo(9); } + @Test + void getMenuStructureForUserIdByMenuKeyTest() { + + var workspaceName = "test03"; + var accessToken = createAccessTokenBearer(USER_BOB); + var idToken = createToken("org1"); + + var data = given() + .when() + .contentType(APPLICATION_JSON) + .header(APM_HEADER_PARAM, idToken) + .body(new UserWorkspaceMenuRequestDTO().token(accessToken).menuKeys(List.of("main-menu", "not-existing"))) + .pathParam("workspaceName", workspaceName) + .post() + .then() + .statusCode(OK.getStatusCode()) + .extract().body().as(UserWorkspaceMenuStructureDTO.class); + + assertThat(data).isNotNull(); + assertThat(data.getWorkspaceName()).isNotNull().isEqualTo(workspaceName); + assertThat(data.getMenu()).isNotNull().isNotEmpty(); + + var output = print(data.getMenu(), ""); + System.out.println(output); + + String tmp = """ + + [1] 4-2 + + [0] 4-2-1 + + [1] 4-2-2 + + [2] 4-2-3 + + [0] 4-2-3-1 + """; + assertThat(output).isEqualTo(tmp); + assertThat(countMenuItems(data.getMenu())).isEqualTo(5); + + // without bearer prefix + accessToken = createAccessToken(USER_BOB); + data = given() + .when() + .contentType(APPLICATION_JSON) + .header(APM_HEADER_PARAM, idToken) + .body(new UserWorkspaceMenuRequestDTO().token(accessToken).menuKeys(List.of("main-menu", "not-existing"))) + .pathParam("workspaceName", workspaceName) + .post() + .then() + .statusCode(OK.getStatusCode()) + .extract().body().as(UserWorkspaceMenuStructureDTO.class); + + assertThat(data).isNotNull(); + assertThat(data.getWorkspaceName()).isNotNull().isEqualTo(workspaceName); + assertThat(data.getMenu()).isNotNull().isNotEmpty(); + + output = print(data.getMenu(), ""); + System.out.println(output); + assertThat(output).isEqualTo(tmp); + assertThat(countMenuItems(data.getMenu())).isEqualTo(5); + } + @Test void getMenuStructureForUserIdOrg2Test() {