Skip to content

Commit

Permalink
feat: added role based menu tree
Browse files Browse the repository at this point in the history
  • Loading branch information
JordenReuter committed Dec 3, 2024
1 parent 3f947b0 commit 03ac50f
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ h| Version
| onecx-tenant

| https://onecx.github.io/docs/onecx-quarkus/current/onecx-quarkus/onecx-tenant.html[Link]
| https://github.com/onecx/onecx-quarkus/blob/0.33.0/docs/modules/onecx-quarkus/pages/includes/onecx-tenant.adoc[Link]
| 0.33.0
| https://github.com/onecx/onecx-quarkus/blob/0.34.0/docs/modules/onecx-quarkus/pages/includes/onecx-tenant.adoc[Link]
| 0.34.0

| tkit-quarkus-jpa-tenant

Expand Down Expand Up @@ -144,7 +144,7 @@ h| Version
| https://onecx.github.io/docs/onecx-quarkus/current/onecx-quarkus/onecx-core.html[Link]
|
| 0.33.0
| 0.34.0
| quarkus-container-image-docker
Expand All @@ -157,7 +157,7 @@ h| Version
|
|
| 0.33.0
| 0.34.0
|===
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package org.tkit.onecx.workspace.rs.internal.controllers;

import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toSet;
import static org.jboss.resteasy.reactive.RestResponse.StatusCode.NOT_FOUND;

import java.util.*;
import java.util.stream.Collectors;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
Expand All @@ -15,8 +18,10 @@

import org.jboss.resteasy.reactive.RestResponse;
import org.jboss.resteasy.reactive.server.ServerExceptionMapper;
import org.tkit.onecx.workspace.domain.daos.AssignmentDAO;
import org.tkit.onecx.workspace.domain.daos.MenuItemDAO;
import org.tkit.onecx.workspace.domain.daos.WorkspaceDAO;
import org.tkit.onecx.workspace.domain.models.AssignmentMenu;
import org.tkit.onecx.workspace.domain.models.MenuItem;
import org.tkit.onecx.workspace.domain.services.MenuService;
import org.tkit.onecx.workspace.rs.internal.mappers.InternalExceptionMapper;
Expand All @@ -26,7 +31,9 @@

import gen.org.tkit.onecx.workspace.rs.internal.MenuInternalApi;
import gen.org.tkit.onecx.workspace.rs.internal.model.*;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@LogService
@ApplicationScoped
@Transactional(Transactional.TxType.NOT_SUPPORTED)
Expand All @@ -50,6 +57,9 @@ public class MenuInternalRestController implements MenuInternalApi {
@Inject
MenuService menuService;

@Inject
AssignmentDAO assignmentDAO;

@Override
public Response createMenuItem(CreateMenuItemDTO menuItemDTO) {
var workspace = workspaceDAO.findById(menuItemDTO.getWorkspaceId());
Expand Down Expand Up @@ -107,7 +117,20 @@ public Response getMenuItemById(String menuItemId) {
public Response getMenuStructure(MenuStructureSearchCriteriaDTO menuStructureSearchCriteriaDTO) {
var criteria = mapper.map(menuStructureSearchCriteriaDTO);
var result = dao.loadAllMenuItemsByCriteria(criteria);
return Response.ok(mapper.mapTree(result)).build();
var workspace = workspaceDAO.findById(criteria.getWorkspaceId());
if (menuStructureSearchCriteriaDTO.getRoles().isEmpty()) {
return Response.ok(mapper.mapTree(result)).build();

}

List<AssignmentMenu> assignmentRecords = assignmentDAO
.findAssignmentMenuForWorkspace(menuStructureSearchCriteriaDTO.getWorkspaceId());
Map<String, Set<String>> mapping = assignmentRecords.stream()
.collect(Collectors.groupingBy(AssignmentMenu::menuItemId, mapping(AssignmentMenu::roleName, toSet())));
return Response
.ok(mapper.mapTreeByRoles(workspace, result, mapping, new HashSet<>(menuStructureSearchCriteriaDTO.getRoles())))
.build();

}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package org.tkit.onecx.workspace.rs.internal.mappers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.text.StringSubstitutor;
import org.mapstruct.*;
import org.tkit.onecx.workspace.domain.criteria.MenuItemLoadCriteria;
import org.tkit.onecx.workspace.domain.criteria.MenuItemSearchCriteria;
Expand Down Expand Up @@ -142,4 +141,67 @@ default void updateMenu(MenuItem menuItem, int position, Workspace workspace,
menuItem.setPosition(position);
menuItem.setParent(parent);
}

default MenuItemStructureDTO mapTreeByRoles(Workspace workspace, Collection<MenuItem> menuItems,
Map<String, Set<String>> mapping,
HashSet<String> roles) {
MenuItemStructureDTO dto = new MenuItemStructureDTO();

if (menuItems.isEmpty()) {
return dto;
}
Set<MenuItem> items;

items = filterMenu(new HashSet<>(menuItems), mapping, roles, workspace.getBaseUrl());
if (items.isEmpty()) {
return dto;
}

return dto.menuItems(items.stream().map(this::mapTreeItem).toList());
}

default Set<MenuItem> filterMenu(Set<MenuItem> items, Map<String, Set<String>> mapping, Set<String> roles,
String workspaceUrl) {
Set<MenuItem> tmp = new HashSet<>(items);
final var sub = new StringSubstitutor(System.getenv());
tmp.forEach(rootItem -> {
var mr = mapping.get(rootItem.getId());
if (mr == null || mr.stream().noneMatch(roles::contains)) {
items.remove(rootItem);
} else {
if (rootItem.getChildren() != null && !rootItem.getChildren().isEmpty()) {
filterChildren(rootItem, mapping, roles, workspaceUrl, sub);
} else {
rootItem.setUrl(updateInternalUrl(workspaceUrl, rootItem.getUrl(), rootItem.isExternal(), sub));
}
}
});

return items;
}

default void filterChildren(MenuItem menuItem, Map<String, Set<String>> mapping, Set<String> roles,
String workspaceUrl, StringSubstitutor sub) {
Set<MenuItem> items = new HashSet<>(menuItem.getChildren());
items.forEach(child -> {
var mr = mapping.get(child.getId());
if (mr == null || mr.stream().noneMatch(roles::contains)) {
menuItem.getChildren().remove(child);
} else {
if (child.getChildren() != null && !child.getChildren().isEmpty()) {
filterChildren(child, mapping, roles, workspaceUrl, sub);
} else {
child.setUrl(updateInternalUrl(workspaceUrl, child.getUrl(), child.isExternal(), sub));
}
}
});
}

default String updateInternalUrl(String workspaceUrl, String menuItemUrl, Boolean isExternal, StringSubstitutor sub) {
if (Boolean.TRUE.equals(isExternal)) {
return sub.replace(menuItemUrl);
} else {
return sub.replace(workspaceUrl + menuItemUrl);
}
}
}
4 changes: 4 additions & 0 deletions src/main/openapi/onecx-workspace-internal-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,10 @@ components:
required:
- workspaceId
properties:
roles:
type: array
items:
type: string
workspaceId:
type: string
MenuItemSearchCriteria:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static org.tkit.quarkus.security.test.SecurityTestUtils.getKeycloakClientToken;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

Expand Down Expand Up @@ -290,6 +291,25 @@ void getMenuStructureForWorkspaceIdTest() {
assertThat(countMenuItems(data.getMenuItems())).isEqualTo(13);
}

@Test
void getMenuStructureForWorkspaceIdAndRolesTest() {
var criteria = new MenuStructureSearchCriteriaDTO().workspaceId("11-111").roles(List.of("n3", "n4"));

var data = given()
.auth().oauth2(getKeycloakClientToken("testClient"))
.when()
.contentType(APPLICATION_JSON)
.body(criteria)
.post("/tree")
.then()
.statusCode(OK.getStatusCode())
.extract().body().as(MenuItemStructureDTO.class);

assertThat(data).isNotNull();
assertThat(data.getMenuItems()).hasSize(3);
assertThat(countMenuItems(data.getMenuItems())).isEqualTo(4);
}

private int countMenuItems(Collection<WorkspaceMenuItemDTO> menuItemDTOS) {
int count = 0;
for (WorkspaceMenuItemDTO item : menuItemDTOS) {
Expand Down

0 comments on commit 03ac50f

Please sign in to comment.