From ef959a9791a771b0412428894cea8310e4e09c5a Mon Sep 17 00:00:00 2001 From: Andrej Petras Date: Wed, 7 Feb 2024 20:46:53 +0100 Subject: [PATCH] fix: update modification count for rest-api (#20) * fix: update modification count for rest-api * feat: update jpa model, fix rest api * fix: sonar issues * fix: sonar issues * fix: sonar issues * fix: sonar issues --- .../workspace/domain/daos/MenuItemDAO.java | 20 ++- .../workspace/domain/daos/ProductDAO.java | 8 +- .../workspace/domain/models/MenuItem.java | 4 +- .../workspace/domain/models/Product.java | 1 + .../workspace/domain/models/Workspace.java | 2 +- .../ProductsExternalV1RestController.java | 2 +- .../rs/external/v1/log/WorkspaceLogParam.java | 23 ++++ .../MenuInternalRestController.java | 121 +++++------------ .../ProductInternalRestController.java | 4 +- .../WorkspaceInternalRestController.java | 2 +- .../rs/internal/log/MenuItemLogParam.java | 30 +++-- .../rs/internal/log/ProductLogParam.java | 14 +- .../rs/internal/log/WorkspaceLogParam.java | 19 ++- .../rs/internal/mappers/MenuItemMapper.java | 7 +- .../rs/internal/services/MenuItemService.java | 103 +++++++++++++++ .../internal/services/WorkspaceService.java | 4 - .../onecx-workspace-internal-openapi.yaml | 66 ++++++++-- .../openapi/onecx-workspace-v1-openapi.yaml | 2 +- src/main/resources/application.properties | 11 +- .../domain/daos/MenuItemDAOTest.java | 2 + .../workspace/domain/daos/ProductDAOTest.java | 4 +- .../MenuInternalRestControllerTenantTest.java | 26 ++-- .../MenuInternalRestControllerTest.java | 124 ++++++++++++------ .../ProductRestControllerTenantTest.java | 8 +- .../ProductRestControllerTest.java | 44 +++++-- .../WorkspaceInternalRestControllerTest.java | 2 +- ...TkitPortalRestControllerExceptionTest.java | 3 - src/test/resources/data/testdata-internal.xml | 6 +- 28 files changed, 427 insertions(+), 235 deletions(-) create mode 100644 src/main/java/org/tkit/onecx/workspace/rs/external/v1/log/WorkspaceLogParam.java create mode 100644 src/main/java/org/tkit/onecx/workspace/rs/internal/services/MenuItemService.java diff --git a/src/main/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAO.java b/src/main/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAO.java index e5c1ac3..2425613 100644 --- a/src/main/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAO.java +++ b/src/main/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAO.java @@ -1,6 +1,7 @@ package org.tkit.onecx.workspace.domain.daos; import static jakarta.persistence.criteria.JoinType.LEFT; +import static org.tkit.onecx.workspace.domain.models.MenuItem.MENU_ITEM_LOAD_ALL; import static org.tkit.onecx.workspace.domain.models.MenuItem.MENU_ITEM_WORKSPACE_AND_TRANSLATIONS; import java.util.List; @@ -180,15 +181,32 @@ public MenuItem findById(Object id) throws DAOException { } } + public MenuItem loadById(Object id) throws DAOException { + try { + var cb = this.getEntityManager().getCriteriaBuilder(); + var cq = cb.createQuery(MenuItem.class); + var root = cq.from(MenuItem.class); + cq.where(cb.equal(root.get(TraceableEntity_.ID), id)); + return this.getEntityManager().createQuery(cq) + .setHint(HINT_LOAD_GRAPH, + this.getEntityManager().getEntityGraph(MENU_ITEM_LOAD_ALL)) + .getSingleResult(); + } catch (NoResultException nre) { + return null; + } catch (Exception e) { + throw new DAOException(MenuItemDAO.ErrorKeys.LOAD_ENTITY_BY_ID_FAILED, e, entityName, id); + } + } + public enum ErrorKeys { FIND_ENTITY_BY_ID_FAILED, + LOAD_ENTITY_BY_ID_FAILED, ERROR_UPDATE_MENU_ITEMS, ERROR_LOAD_ALL_MENU_ITEMS_BY_WORKSPACE_ID, ERROR_DELETE_ALL_MENU_ITEMS_BY_WORKSPACE_ID, ERROR_LOAD_ALL_MENU_ITEMS_BY_WORKSPACE_NAME, - ERROR_LOAD_ALL_MENU_ITEM_BY_KEY, ERROR_DELETE_ALL_MENU_ITEMS_BY_WORKSPACE_NAME_AND_APP_ID, } diff --git a/src/main/java/org/tkit/onecx/workspace/domain/daos/ProductDAO.java b/src/main/java/org/tkit/onecx/workspace/domain/daos/ProductDAO.java index fb0d5a2..080601d 100644 --- a/src/main/java/org/tkit/onecx/workspace/domain/daos/ProductDAO.java +++ b/src/main/java/org/tkit/onecx/workspace/domain/daos/ProductDAO.java @@ -59,18 +59,18 @@ public void deleteProductByWorkspaceId(String workspaceId) { delete(products); } - @Override - public Product findById(Object id) throws DAOException { + public Product loadById(Object id) throws DAOException { try { var cb = this.getEntityManager().getCriteriaBuilder(); var cq = cb.createQuery(Product.class); var root = cq.from(Product.class); + root.fetch(Product_.WORKSPACE); cq.where(cb.equal(root.get(TraceableEntity_.ID), id)); return this.getEntityManager().createQuery(cq).getSingleResult(); } catch (NoResultException nre) { return null; } catch (Exception e) { - throw this.handleConstraint(e, ProductDAO.ErrorKeys.FIND_ENTITY_BY_ID_FAILED); + throw this.handleConstraint(e, ProductDAO.ErrorKeys.LOAD_ENTITY_BY_ID_FAILED); } } @@ -88,7 +88,7 @@ public Stream findByName(String name) throws DAOException { public enum ErrorKeys { - FIND_ENTITY_BY_ID_FAILED, + LOAD_ENTITY_BY_ID_FAILED, ERROR_DELETE_PRODUCT_ID, diff --git a/src/main/java/org/tkit/onecx/workspace/domain/models/MenuItem.java b/src/main/java/org/tkit/onecx/workspace/domain/models/MenuItem.java index 2ddaf1d..ff0dd58 100644 --- a/src/main/java/org/tkit/onecx/workspace/domain/models/MenuItem.java +++ b/src/main/java/org/tkit/onecx/workspace/domain/models/MenuItem.java @@ -32,12 +32,14 @@ @NamedEntityGraph(name = MenuItem.MENU_ITEM_WORKSPACE_AND_TRANSLATIONS, attributeNodes = { @NamedAttributeNode("i18n"), @NamedAttributeNode("workspace") }) @NamedEntityGraph(name = "MenuItem.loadById", includeAllAttributes = true, attributeNodes = { @NamedAttributeNode("i18n"), - @NamedAttributeNode("children") }) + @NamedAttributeNode("children"), @NamedAttributeNode("workspace") }) @SuppressWarnings("squid:S2160") public class MenuItem extends TraceableEntity { public static final String MENU_ITEM_WORKSPACE_AND_TRANSLATIONS = "MenuItem.workspaceAndTranslations"; + public static final String MENU_ITEM_LOAD_ALL = "MenuItem.loadById"; + @TenantId @Column(name = "TENANT_ID") private String tenantId; diff --git a/src/main/java/org/tkit/onecx/workspace/domain/models/Product.java b/src/main/java/org/tkit/onecx/workspace/domain/models/Product.java index 986257b..2c736d1 100644 --- a/src/main/java/org/tkit/onecx/workspace/domain/models/Product.java +++ b/src/main/java/org/tkit/onecx/workspace/domain/models/Product.java @@ -19,6 +19,7 @@ @Table(name = "PRODUCT", uniqueConstraints = { @UniqueConstraint(name = "PRODUCT_NAME_WORKSPACE_GUID", columnNames = { "PRODUCT_NAME", "WORKSPACE_GUID", "TENANT_ID" }) }) +@NamedEntityGraph(name = "Product.loadById", includeAllAttributes = true, attributeNodes = { @NamedAttributeNode("workspace") }) @SuppressWarnings("squid:S2160") public class Product extends TraceableEntity { diff --git a/src/main/java/org/tkit/onecx/workspace/domain/models/Workspace.java b/src/main/java/org/tkit/onecx/workspace/domain/models/Workspace.java index 72d1aa5..8c5df24 100644 --- a/src/main/java/org/tkit/onecx/workspace/domain/models/Workspace.java +++ b/src/main/java/org/tkit/onecx/workspace/domain/models/Workspace.java @@ -79,7 +79,7 @@ public class Workspace extends TraceableEntity { @Column(name = "LOGO_URL") private String logoUrl; - @OneToMany(mappedBy = "workspace") + @OneToMany(mappedBy = "workspace", fetch = LAZY) private List products; } diff --git a/src/main/java/org/tkit/onecx/workspace/rs/external/v1/controllers/ProductsExternalV1RestController.java b/src/main/java/org/tkit/onecx/workspace/rs/external/v1/controllers/ProductsExternalV1RestController.java index 21f670a..905dd87 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/external/v1/controllers/ProductsExternalV1RestController.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/external/v1/controllers/ProductsExternalV1RestController.java @@ -22,7 +22,7 @@ class ProductsExternalV1RestController implements ProductExternalV1Api { ProductDAO productDAO; @Override - public Response getProductsForWorkspaceId(String id) { + public Response getProducts(String id) { var result = productDAO.getProductsForWorkspaceId(id); return Response.ok(mapper.map(result)).build(); } diff --git a/src/main/java/org/tkit/onecx/workspace/rs/external/v1/log/WorkspaceLogParam.java b/src/main/java/org/tkit/onecx/workspace/rs/external/v1/log/WorkspaceLogParam.java new file mode 100644 index 0000000..6eaf71f --- /dev/null +++ b/src/main/java/org/tkit/onecx/workspace/rs/external/v1/log/WorkspaceLogParam.java @@ -0,0 +1,23 @@ +package org.tkit.onecx.workspace.rs.external.v1.log; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; + +import org.tkit.quarkus.log.cdi.LogParam; + +import gen.org.tkit.onecx.workspace.rs.external.v1.model.WorkspaceSearchCriteriaDTOV1; + +@ApplicationScoped +public class WorkspaceLogParam implements LogParam { + + @Override + public List getClasses() { + return List.of( + item(10, WorkspaceSearchCriteriaDTOV1.class, x -> { + WorkspaceSearchCriteriaDTOV1 d = (WorkspaceSearchCriteriaDTOV1) x; + return WorkspaceSearchCriteriaDTOV1.class.getSimpleName() + "[" + d.getPageNumber() + "," + d.getPageSize() + + "]"; + })); + } +} diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestController.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestController.java index f125e1b..160a109 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestController.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestController.java @@ -3,7 +3,6 @@ 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; @@ -21,6 +20,7 @@ import org.tkit.onecx.workspace.domain.models.MenuItem; import org.tkit.onecx.workspace.rs.internal.mappers.InternalExceptionMapper; import org.tkit.onecx.workspace.rs.internal.mappers.MenuItemMapper; +import org.tkit.onecx.workspace.rs.internal.services.MenuItemService; import org.tkit.quarkus.jpa.exceptions.ConstraintException; import org.tkit.quarkus.log.cdi.LogService; @@ -47,6 +47,9 @@ public class MenuInternalRestController implements MenuInternalApi { @Inject WorkspaceDAO workspaceDAO; + @Inject + MenuItemService menuItemService; + @Override @Transactional public Response createMenuItemForWorkspace(String id, CreateMenuItemDTO menuItemDTO) { @@ -122,67 +125,69 @@ public Response getMenuStructureForWorkspaceId(String id) { } @Override - @Transactional - public Response patchMenuItems(String id, List menuItemDTO) { - // create map of - Map tmp = menuItemDTO.stream() - .collect(Collectors.toMap(MenuItemDTO::getId, x -> x)); - + public Response patchMenuItems(String id, UpdateMenuItemsRequestDTO updateMenuItemsRequestDTO) { + // list of IDs + List ids = new ArrayList<>(updateMenuItemsRequestDTO.getItems().keySet()); + if (ids.isEmpty()) { + return Response.status(NOT_FOUND).build(); + } // load menu items - var items = dao.findByIds(Arrays.asList(tmp.keySet().toArray())).toList(); + var items = dao.findByIds(ids).toList(); if (items.isEmpty()) { return Response.status(NOT_FOUND).build(); } - if (items.size() != tmp.size()) { + if (items.size() != ids.size()) { return Response.status(NOT_FOUND).entity("Menu Items specified in request body do not exist in db").build(); } - for (MenuItem item : items) { - MenuItemDTO dto = tmp.get(item.getId()); - - // update parent - updateParent(item, dto); - - mapper.update(dto, item); + List toUpdate = new ArrayList<>(); + for (Map.Entry entry : updateMenuItemsRequestDTO.getItems().entrySet()) { + var menuItem = update(entry.getKey(), entry.getValue()); + toUpdate.add(menuItem); } - var result = dao.update(items); + var result = dao.update(toUpdate); return Response.ok(mapper.map(result)).build(); } @Override - @Transactional - public Response updateMenuItem(String id, String menuItemId, MenuItemDTO menuItemDTO) { - var menuItem = dao.findById(menuItemId); + public Response updateMenuItem(String id, String menuItemId, UpdateMenuItemRequestDTO menuItemDTO) { + var menuItem = update(menuItemId, menuItemDTO); if (menuItem == null) { return Response.status(NOT_FOUND).build(); } - - // update parent - updateParent(menuItem, menuItemDTO); - - mapper.update(menuItemDTO, menuItem); - menuItem = dao.update(menuItem); - return Response.ok(mapper.map(menuItem)).build(); } + private MenuItem update(String menuItemId, UpdateMenuItemRequestDTO menuItemDTO) { + var result = menuItemService.updateMenuItem(menuItemId, menuItemDTO.getParentItemId()); + if (result == null) { + return null; + } + var menuItem = result.getMenuItem(); + mapper.update(menuItemDTO, menuItem); + if (result.isParentChange()) { + menuItem.setParent(result.getParent()); + } + return menuItem; + } + @Override @Transactional - public Response uploadMenuStructureForWorkspaceId(String id, WorkspaceMenuItemStructrueDTO menuItemStructrueDTO) { + public Response uploadMenuStructureForWorkspaceId(String id, WorkspaceMenuItemStructureDTO menuItemStructureDTO) { var workspace = workspaceDAO.findById(id); if (workspace == null) { throw new ConstraintException("Given workspace does not exist", MenuItemErrorKeys.WORKSPACE_DOES_NOT_EXIST, null); } - if (menuItemStructrueDTO.getMenuItems() == null || menuItemStructrueDTO.getMenuItems().isEmpty()) { + if (menuItemStructureDTO.getMenuItems() == null || menuItemStructureDTO.getMenuItems().isEmpty()) { throw new ConstraintException("menuItems cannot be null", MenuItemErrorKeys.MENU_ITEMS_NULL, null); } List items = new LinkedList<>(); - mapper.recursiveMappingTreeStructure(menuItemStructrueDTO.getMenuItems(), workspace, null, items); + mapper.recursiveMappingTreeStructure(menuItemStructureDTO.getMenuItems(), workspace, null, items); dao.deleteAllMenuItemsByWorkspaceId(id); dao.create(items); @@ -191,57 +196,6 @@ public Response uploadMenuStructureForWorkspaceId(String id, WorkspaceMenuItemSt } - private void updateParent(MenuItem menuItem, MenuItemDTO dto) { - - if (dto.getParentItemId() == null) { - menuItem.setParent(null); - return; - } - - // check parent change - if (menuItem.getParent() != null && dto.getParentItemId().equals(menuItem.getParent().getId())) { - return; - } - - // checking if request parent id is the same as current id - if (dto.getParentItemId().equals(menuItem.getId())) { - throw new ConstraintException("Menu Item " + menuItem.getId() + " id and parentItem id are the same", - MenuItemErrorKeys.PARENT_MENU_SAME_AS_MENU_ITEM, null); - } - - // checking if parent exists - var parent = dao.findById(dto.getParentItemId()); - if (parent == null) { - throw new ConstraintException("Parent menu item " + dto.getParentItemId() + " does not exists", - MenuItemErrorKeys.PARENT_MENU_DOES_NOT_EXIST, null); - } else { - // checking if parent exists in the same portal - if (!parent.getWorkspace().getId().equals(menuItem.getWorkspace().getId())) { - throw new ConstraintException("Parent menu item is assigned to different portal", - MenuItemErrorKeys.PARENT_ASSIGNED_TO_DIFFERENT_PORTAL, null); - } - - // check for cycle - Set children = new HashSet<>(); - children(menuItem, children); - if (children.contains(parent.getId())) { - throw new ConstraintException( - "One of the items try to set one of its children to the new parent. Cycle dependency can not be created in tree structure", - MenuItemErrorKeys.CYCLE_DEPENDENCY, null); - } - } - - // set new parent - menuItem.setParent(parent); - } - - private void children(MenuItem menuItem, Set result) { - menuItem.getChildren().forEach(c -> { - result.add(c.getId()); - children(c, result); - }); - } - @ServerExceptionMapper public RestResponse exception(ConstraintException ex) { return exceptionMapper.exception(ex); @@ -261,14 +215,9 @@ enum MenuItemErrorKeys { WORKSPACE_DOES_NOT_EXIST, PARENT_MENU_DOES_NOT_EXIST, - PARENT_MENU_SAME_AS_MENU_ITEM, WORKSPACE_DIFFERENT, MENU_ITEMS_NULL, - PARENT_ASSIGNED_TO_DIFFERENT_PORTAL, - - CYCLE_DEPENDENCY - } } diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductInternalRestController.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductInternalRestController.java index bcb0886..5388e32 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductInternalRestController.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductInternalRestController.java @@ -78,13 +78,11 @@ public Response getProductsForWorkspaceId(String id) { } @Override - @Transactional public Response updateProductById(String id, String productId, UpdateProductRequestDTO updateProductRequestDTO) { - var product = dao.findById(productId); + var product = dao.loadById(productId); if (product == null) { return Response.status(NOT_FOUND).build(); } - mapper.update(updateProductRequestDTO, product); product = dao.update(product); return Response.ok(mapper.map(product)).build(); diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestController.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestController.java index 3b89529..71cbfd1 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestController.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestController.java @@ -85,7 +85,7 @@ public Response getWorkspace(String id) { } @Override - public Response getWorkspaceByName(String name) { + public Response findWorkspaceByName(String name) { var item = dao.findByWorkspaceName(name); if (item == null) { return Response.status(Response.Status.NOT_FOUND).build(); diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/log/MenuItemLogParam.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/log/MenuItemLogParam.java index f3b797e..994ab57 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/log/MenuItemLogParam.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/log/MenuItemLogParam.java @@ -6,9 +6,7 @@ import org.tkit.quarkus.log.cdi.LogParam; -import gen.org.tkit.onecx.workspace.rs.internal.model.CreateMenuItemDTO; -import gen.org.tkit.onecx.workspace.rs.internal.model.MenuItemDTO; -import gen.org.tkit.onecx.workspace.rs.internal.model.WorkspaceMenuItemStructrueDTO; +import gen.org.tkit.onecx.workspace.rs.internal.model.*; @ApplicationScoped public class MenuItemLogParam implements LogParam { @@ -16,18 +14,24 @@ public class MenuItemLogParam implements LogParam { @Override public List getClasses() { return List.of( - this.item(10, MenuItemDTO.class, - x -> "MenuItem[ key: " + ((MenuItemDTO) x).getKey() - + ", workspaceName: " + ((MenuItemDTO) x).getWorkspaceName() + " ]"), + this.item(10, UpdateMenuItemsRequestDTO.class, + x -> { + var items = ((UpdateMenuItemsRequestDTO) x).getItems(); + return UpdateMenuItemsRequestDTO.class.getSimpleName() + "[" + + (items != null ? items.size() : "null") + "]"; + }), + this.item(10, UpdateMenuItemRequestDTO.class, + x -> UpdateMenuItemRequestDTO.class.getSimpleName() + "[" + ((UpdateMenuItemRequestDTO) x).getKey() + + "," + ((UpdateMenuItemRequestDTO) x).getWorkspaceName() + "]"), this.item(10, CreateMenuItemDTO.class, - x -> "CreateMenuItemDTO[ key: " + ((CreateMenuItemDTO) x).getKey() - + ", url: " + ((CreateMenuItemDTO) x).getUrl() + " ]"), - this.item(10, WorkspaceMenuItemStructrueDTO.class, - x -> "WorkspaceMenuItemStructrueDTO[ menu items size: " - + (((WorkspaceMenuItemStructrueDTO) x).getMenuItems() != null - ? ((WorkspaceMenuItemStructrueDTO) x).getMenuItems().size() + x -> CreateMenuItemDTO.class.getSimpleName() + "[" + ((CreateMenuItemDTO) x).getKey() + + "," + ((CreateMenuItemDTO) x).getUrl() + "]"), + this.item(10, WorkspaceMenuItemStructureDTO.class, + x -> WorkspaceMenuItemStructureDTO.class.getSimpleName() + "[" + + (((WorkspaceMenuItemStructureDTO) x).getMenuItems() != null + ? ((WorkspaceMenuItemStructureDTO) x).getMenuItems().size() : "null") - + " ]") + + "]") ); diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/log/ProductLogParam.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/log/ProductLogParam.java index 1b83e49..640ff2e 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/log/ProductLogParam.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/log/ProductLogParam.java @@ -16,19 +16,19 @@ public class ProductLogParam implements LogParam { public List getClasses() { return List.of( this.item(10, CreateProductRequestDTO.class, - x -> "CreateProductRequestDTO[ name: " + ((CreateProductRequestDTO) x).getProductName() - + ", baseUrl: " + ((CreateProductRequestDTO) x).getBaseUrl() - + ", mfe list size: " + x -> CreateProductRequestDTO.class.getSimpleName() + "[" + + ((CreateProductRequestDTO) x).getProductName() + + "," + ((CreateProductRequestDTO) x).getBaseUrl() + "," + (((CreateProductRequestDTO) x).getMicrofrontends() != null ? ((CreateProductRequestDTO) x).getMicrofrontends().size() : "null") - + " ]"), + + "]"), this.item(10, UpdateProductRequestDTO.class, - x -> "UpdateProductRequestDTO[ baseUrl: " + ((UpdateProductRequestDTO) x).getBaseUrl() - + ", mfe list size: " + x -> UpdateProductRequestDTO.class.getSimpleName() + "[" + ((UpdateProductRequestDTO) x).getBaseUrl() + + "," + (((UpdateProductRequestDTO) x).getMicrofrontends() != null ? ((UpdateProductRequestDTO) x).getMicrofrontends().size() : "null") - + " ]")); + + "]")); } } diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/log/WorkspaceLogParam.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/log/WorkspaceLogParam.java index 80d2a6f..f3edf68 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/log/WorkspaceLogParam.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/log/WorkspaceLogParam.java @@ -15,16 +15,15 @@ public class WorkspaceLogParam implements LogParam { public List getClasses() { return List.of( this.item(10, CreateWorkspaceRequestDTO.class, - x -> "CreateWorkspaceRequestDTO[ name: " + ((CreateWorkspaceRequestDTO) x).getName() - + ", baseUrl: " + ((CreateWorkspaceRequestDTO) x).getBaseUrl() - + ", company name: " + ((CreateWorkspaceRequestDTO) x).getCompanyName() - + " ]"), + x -> CreateWorkspaceRequestDTO.class.getSimpleName() + "[" + ((CreateWorkspaceRequestDTO) x).getName() + + "]"), this.item(10, UpdateWorkspaceRequestDTO.class, - x -> "UpdateWorkspaceRequestDTO[ name: " + ((UpdateWorkspaceRequestDTO) x).getName() - + ", baseUrl: " + ((UpdateWorkspaceRequestDTO) x).getBaseUrl() - + ", company name: " + ((UpdateWorkspaceRequestDTO) x).getCompanyName() - + " ]") - - ); + x -> UpdateWorkspaceRequestDTO.class.getSimpleName() + "[" + ((UpdateWorkspaceRequestDTO) x).getName() + + "]"), + item(10, WorkspaceSearchCriteriaDTO.class, x -> { + WorkspaceSearchCriteriaDTO d = (WorkspaceSearchCriteriaDTO) x; + return WorkspaceSearchCriteriaDTO.class.getSimpleName() + "[" + d.getPageNumber() + "," + d.getPageSize() + + "]"; + })); } } diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/mappers/MenuItemMapper.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/mappers/MenuItemMapper.java index 731d76f..ac05aab 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/mappers/MenuItemMapper.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/mappers/MenuItemMapper.java @@ -38,7 +38,6 @@ public abstract class MenuItemMapper { @Mapping(target = "workspace", ignore = true) @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) @Mapping(target = "id", ignore = true) - //@Mapping(target = "modificationCount", ignore = true, defaultValue = "0") @Mapping(target = "workspaceName", ignore = true) @Mapping(target = "creationDate", ignore = true) @Mapping(target = "creationUser", ignore = true) @@ -50,7 +49,7 @@ public abstract class MenuItemMapper { @Mapping(target = "parent", ignore = true) @Mapping(target = "children", ignore = true) @Mapping(target = "tenantId", ignore = true) - public abstract void update(MenuItemDTO menuItemDetailsDto, @MappingTarget MenuItem entity); + public abstract void update(UpdateMenuItemRequestDTO menuItemDetailsDto, @MappingTarget MenuItem entity); public abstract List mapList(List items); @@ -72,8 +71,8 @@ public String mapListToString(List list) { return String.join(",", list); } - public WorkspaceMenuItemStructrueDTO mapTree(Collection entities) { - WorkspaceMenuItemStructrueDTO dto = new WorkspaceMenuItemStructrueDTO(); + public WorkspaceMenuItemStructureDTO mapTree(Collection entities) { + WorkspaceMenuItemStructureDTO dto = new WorkspaceMenuItemStructureDTO(); if (entities.isEmpty()) { dto.setMenuItems(new ArrayList<>()); return dto; diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/services/MenuItemService.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/services/MenuItemService.java new file mode 100644 index 0000000..f499c5f --- /dev/null +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/services/MenuItemService.java @@ -0,0 +1,103 @@ +package org.tkit.onecx.workspace.rs.internal.services; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +import org.tkit.onecx.workspace.domain.daos.MenuItemDAO; +import org.tkit.onecx.workspace.domain.models.MenuItem; +import org.tkit.quarkus.jpa.exceptions.ConstraintException; + +import lombok.Getter; + +@ApplicationScoped +public class MenuItemService { + + @Inject + MenuItemDAO dao; + + @Transactional(Transactional.TxType.REQUIRES_NEW) + public UpdateResult updateMenuItem(String menuItemId, String newParentItemId) { + var menuItem = dao.loadById(menuItemId); + if (menuItem == null) { + return null; + } + + if (newParentItemId == null) { + return UpdateResult.of(menuItem, null, true); + } + + // check parent change + if (menuItem.getParent() != null && newParentItemId.equals(menuItem.getParent().getId())) { + return UpdateResult.of(menuItem, null, false); + } + + // checking if request parent id is the same as current id + if (newParentItemId.equals(menuItem.getId())) { + throw new ConstraintException("Menu Item " + menuItem.getId() + " id and parentItem id are the same", + MenuItemErrorKeys.PARENT_MENU_SAME_AS_MENU_ITEM, null); + } + + // checking if parent exists + var parent = dao.findById(newParentItemId); + if (parent == null) { + throw new ConstraintException("Parent menu item " + newParentItemId + " does not exists", + MenuItemErrorKeys.PARENT_MENU_DOES_NOT_EXIST, null); + } else { + // checking if parent exists in the same portal + if (!parent.getWorkspace().getId().equals(menuItem.getWorkspace().getId())) { + throw new ConstraintException("Parent menu item is assigned to different portal", + MenuItemErrorKeys.PARENT_ASSIGNED_TO_DIFFERENT_PORTAL, null); + } + + // check for cycle + Set children = new HashSet<>(); + children(menuItem, children); + if (children.contains(parent.getId())) { + throw new ConstraintException( + "One of the items try to set one of its children to the new parent. Cycle dependency can not be created in tree structure", + MenuItemErrorKeys.CYCLE_DEPENDENCY, null); + } + } + + // set new parent + return UpdateResult.of(menuItem, parent, true); + } + + @Getter + public static class UpdateResult { + private MenuItem menuItem; + private MenuItem parent; + private boolean parentChange; + + public static UpdateResult of(MenuItem menuItem, MenuItem parent, boolean parentChange) { + var r = new UpdateResult(); + r.menuItem = menuItem; + r.parent = parent; + r.parentChange = parentChange; + return r; + } + + } + + private void children(MenuItem menuItem, Set result) { + menuItem.getChildren().forEach(c -> { + result.add(c.getId()); + children(c, result); + }); + } + + public enum MenuItemErrorKeys { + PARENT_MENU_DOES_NOT_EXIST, + + PARENT_MENU_SAME_AS_MENU_ITEM, + + PARENT_ASSIGNED_TO_DIFFERENT_PORTAL, + + CYCLE_DEPENDENCY; + + } +} diff --git a/src/main/java/org/tkit/onecx/workspace/rs/internal/services/WorkspaceService.java b/src/main/java/org/tkit/onecx/workspace/rs/internal/services/WorkspaceService.java index 6bcd3ca..ed35b7a 100644 --- a/src/main/java/org/tkit/onecx/workspace/rs/internal/services/WorkspaceService.java +++ b/src/main/java/org/tkit/onecx/workspace/rs/internal/services/WorkspaceService.java @@ -5,7 +5,6 @@ import jakarta.transaction.Transactional; import org.tkit.onecx.workspace.domain.daos.MenuItemDAO; -import org.tkit.onecx.workspace.domain.daos.ProductDAO; import org.tkit.onecx.workspace.domain.daos.WorkspaceDAO; import org.tkit.onecx.workspace.domain.models.Workspace; @@ -14,9 +13,6 @@ public class WorkspaceService { @Inject WorkspaceDAO workspaceDAO; - @Inject - ProductDAO productDAO; - @Inject MenuItemDAO menuItemDAO; diff --git a/src/main/openapi/onecx-workspace-internal-openapi.yaml b/src/main/openapi/onecx-workspace-internal-openapi.yaml index bc5ccf9..cf88711 100644 --- a/src/main/openapi/onecx-workspace-internal-openapi.yaml +++ b/src/main/openapi/onecx-workspace-internal-openapi.yaml @@ -128,7 +128,7 @@ paths: tags: - workspaceInternal description: Return workspace by name - operationId: getWorkspaceByName + operationId: findWorkspaceByName parameters: - $ref: '#/components/parameters/name' responses: @@ -169,10 +169,7 @@ paths: content: application/json: schema: - type: array - minItems: 1 - items: - $ref: '#/components/schemas/MenuItem' + $ref: '#/components/schemas/UpdateMenuItemsRequest' responses: "200": description: OK @@ -252,7 +249,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/WorkspaceMenuItemStructrue' + $ref: '#/components/schemas/WorkspaceMenuItemStructure' "404": description: Not found /internal/workspaces/{id}/menuItems/tree/upload: @@ -268,7 +265,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/WorkspaceMenuItemStructrue' + $ref: '#/components/schemas/WorkspaceMenuItemStructure' responses: "201": description: New workspace created @@ -326,7 +323,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/MenuItem' + $ref: '#/components/schemas/UpdateMenuItemRequest' responses: "200": description: OK @@ -660,7 +657,7 @@ components: type: string url: type: string - WorkspaceMenuItemStructrue: + WorkspaceMenuItemStructure: type: object properties: menuItems: @@ -718,6 +715,57 @@ components: type: array items: $ref: '#/components/schemas/WorkspaceMenuItem' + UpdateMenuItemsRequest: + type: object + required: + - items + properties: + items: + $ref: '#/components/schemas/UpdateMenuItemsRequestData' + UpdateMenuItemsRequestData: + type: object + nullable: false + additionalProperties: + $ref: '#/components/schemas/UpdateMenuItemRequest' + UpdateMenuItemRequest: + type: object + required: + - modificationCount + properties: + modificationCount: + format: int32 + type: integer + key: + type: string + name: + type: string + description: + type: string + url: + type: string + workspaceName: + type: string + applicationId: + type: string + disabled: + type: boolean + position: + format: int32 + type: integer + permission: + type: string + badge: + type: string + scope: + $ref: '#/components/schemas/Scope' + workspaceExit: + type: boolean + parentItemId: + type: string + i18n: + type: object + additionalProperties: + type: string MenuItem: type: object required: diff --git a/src/main/openapi/onecx-workspace-v1-openapi.yaml b/src/main/openapi/onecx-workspace-v1-openapi.yaml index c571bf5..0227f81 100644 --- a/src/main/openapi/onecx-workspace-v1-openapi.yaml +++ b/src/main/openapi/onecx-workspace-v1-openapi.yaml @@ -77,7 +77,7 @@ paths: tags: - productExternal description: Find all products belonging to a workspace - operationId: getProductsForWorkspaceId + operationId: getProducts parameters: - $ref: '#/components/parameters/id' responses: diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2144b16..da501db 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -46,16 +46,7 @@ tkit.rs.context.tenant-id.enabled=true %test.tkit.rs.context.tenant-id.mock.data.org3=tenant-300 # TEST-IT (integration tests) -quarkus.test.integration-test-profile=test-it -%test-it.tkit.log.json.enabled=false -%test-it.tkit.jpa.tenant.default=tenant-100 -%test-it.tkit.rs.context.tenant-id.mock.enabled=true -%test-it.tkit.rs.context.tenant-id.mock.default-tenant=tenant-100 -%test-it.tkit.rs.context.tenant-id.mock.claim-org-id=orgId -%test-it.tkit.rs.context.tenant-id.mock.data.org1=tenant-100 -%test-it.tkit.rs.context.tenant-id.mock.data.org2=tenant-200 -%test-it.tkit.rs.context.tenant-id.mock.data.org3=tenant-300 - +quarkus.test.integration-test-profile=test # PROD %prod.quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://postgresdb:5432/onecx-workspace?sslmode=disable} diff --git a/src/test/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAOTest.java b/src/test/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAOTest.java index 1c42ba9..791e86e 100644 --- a/src/test/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAOTest.java +++ b/src/test/java/org/tkit/onecx/workspace/domain/daos/MenuItemDAOTest.java @@ -41,6 +41,8 @@ void methodExceptionTests() { MenuItemDAO.ErrorKeys.ERROR_LOAD_ALL_MENU_ITEMS_BY_WORKSPACE_NAME); methodExceptionTests(() -> dao.findById(null), MenuItemDAO.ErrorKeys.FIND_ENTITY_BY_ID_FAILED); + methodExceptionTests(() -> dao.loadById(null), + MenuItemDAO.ErrorKeys.LOAD_ENTITY_BY_ID_FAILED); } void methodExceptionTests(Executable fn, Enum key) { diff --git a/src/test/java/org/tkit/onecx/workspace/domain/daos/ProductDAOTest.java b/src/test/java/org/tkit/onecx/workspace/domain/daos/ProductDAOTest.java index 0842c88..7d9b8a5 100644 --- a/src/test/java/org/tkit/onecx/workspace/domain/daos/ProductDAOTest.java +++ b/src/test/java/org/tkit/onecx/workspace/domain/daos/ProductDAOTest.java @@ -30,8 +30,8 @@ void beforeAll() { void methodExceptionTests() { methodExceptionTests(() -> dao.getProductsForWorkspaceId(null), ProductDAO.ErrorKeys.ERROR_FIND_PRODUCTS_BY_WORKSPACE_ID); - methodExceptionTests(() -> dao.findById(null), - ProductDAO.ErrorKeys.FIND_ENTITY_BY_ID_FAILED); + methodExceptionTests(() -> dao.loadById(null), + ProductDAO.ErrorKeys.LOAD_ENTITY_BY_ID_FAILED); methodExceptionTests(() -> dao.deleteProduct(null), ProductDAO.ErrorKeys.ERROR_DELETE_PRODUCT_ID); methodExceptionTests(() -> dao.findByName(null), diff --git a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTenantTest.java b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTenantTest.java index 721225c..52fcb9a 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTenantTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTenantTest.java @@ -228,7 +228,7 @@ void getMenuStructureForWorkspaceIdTest() { .get("/tree") .then() .statusCode(OK.getStatusCode()) - .extract().body().as(WorkspaceMenuItemStructrueDTO.class); + .extract().body().as(WorkspaceMenuItemStructureDTO.class); assertThat(data).isNotNull(); assertThat(data.getMenuItems()).isEmpty(); @@ -240,7 +240,7 @@ void getMenuStructureForWorkspaceIdTest() { .get("/tree") .then() .statusCode(OK.getStatusCode()) - .extract().body().as(WorkspaceMenuItemStructrueDTO.class); + .extract().body().as(WorkspaceMenuItemStructureDTO.class); assertThat(data).isNotNull(); assertThat(data.getMenuItems()).hasSize(5); @@ -264,7 +264,7 @@ void bulkPatchMenuItemsEmptyListTest() { given() .when() .contentType(APPLICATION_JSON) - .body(List.of()) + .body(new UpdateMenuItemsRequestDTO()) .pathParam("id", "11-222") .header(APM_HEADER_PARAM, createToken("org3")) .patch() @@ -274,23 +274,25 @@ void bulkPatchMenuItemsEmptyListTest() { @Test void patchMenuItemsTest() { - var menuItemDetailsDTO = new MenuItemDTO(); - menuItemDetailsDTO.setId("44-1"); + var menuItemDetailsDTO = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO.setName("Test menu 44-1"); menuItemDetailsDTO.setDisabled(false); menuItemDetailsDTO.setModificationCount(0); - var menuItemDetailsDTO1 = new MenuItemDTO(); - menuItemDetailsDTO1.setId("44-2"); + var menuItemDetailsDTO1 = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO1.setParentItemId("44-5"); menuItemDetailsDTO1.setName("Test menu 44-2"); menuItemDetailsDTO1.setDisabled(false); menuItemDetailsDTO1.setModificationCount(0); + var request = new UpdateMenuItemsRequestDTO(); + request.putItemsItem("44-1", menuItemDetailsDTO); + request.putItemsItem("44-2", menuItemDetailsDTO1); + given() .when() .contentType(APPLICATION_JSON) - .body(List.of(menuItemDetailsDTO, menuItemDetailsDTO1)) + .body(request) .pathParam("id", "11-222") .header(APM_HEADER_PARAM, createToken("org3")) .patch() @@ -299,7 +301,7 @@ void patchMenuItemsTest() { var updatedData = given() .when() .contentType(APPLICATION_JSON) - .body(List.of(menuItemDetailsDTO, menuItemDetailsDTO1)) + .body(request) .pathParam("id", "11-222") .header(APM_HEADER_PARAM, createToken("org1")) .patch() @@ -324,7 +326,7 @@ void patchMenuItemsTest() { @Test void updateMenuItemTest() { - var request = new MenuItemDTO(); + var request = new UpdateMenuItemRequestDTO(); request.setKey("Test menu"); request.setDescription("New test menu description"); request.setDisabled(false); @@ -380,7 +382,7 @@ void updateMenuItemTest() { @Test void uploadMenuStructureTest() { - var menuStructureListDTO = new WorkspaceMenuItemStructrueDTO(); + var menuStructureListDTO = new WorkspaceMenuItemStructureDTO(); var menuItemStructureDTO = new WorkspaceMenuItemDTO(); menuItemStructureDTO.setKey("Test menu"); @@ -439,7 +441,7 @@ void uploadMenuStructureTest() { .get("/tree") .then() .statusCode(OK.getStatusCode()) - .extract().body().as(WorkspaceMenuItemStructrueDTO.class); + .extract().body().as(WorkspaceMenuItemStructureDTO.class); assertThat(data).isNotNull(); assertThat(data.getMenuItems()).hasSize(1); diff --git a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTest.java b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTest.java index 3eb7b24..625e03a 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/MenuInternalRestControllerTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.tkit.onecx.workspace.rs.internal.services.MenuItemService; import org.tkit.onecx.workspace.test.AbstractTest; import org.tkit.quarkus.test.WithDBData; @@ -205,7 +206,7 @@ void getMenuStructureForWorkspaceIdTest() { .get("/tree") .then() .statusCode(OK.getStatusCode()) - .extract().body().as(WorkspaceMenuItemStructrueDTO.class); + .extract().body().as(WorkspaceMenuItemStructureDTO.class); assertThat(data).isNotNull(); assertThat(data.getMenuItems()).hasSize(5); @@ -231,7 +232,7 @@ void getMenuStructureForPortalIdDoesNotExistsTest() { .pathParam("id", "does-not-exists") .get("/tree") .then().statusCode(OK.getStatusCode()) - .extract().body().as(WorkspaceMenuItemStructrueDTO.class); + .extract().body().as(WorkspaceMenuItemStructureDTO.class); assertThat(data).isNotNull(); assertThat(data.getMenuItems()).isEmpty(); @@ -253,7 +254,16 @@ void bulkPatchMenuItemsEmptyListTest() { given() .when() .contentType(APPLICATION_JSON) - .body(List.of()) + .body(new UpdateMenuItemsRequestDTO().items(null)) + .pathParam("id", "11-222") + .patch() + .then() + .statusCode(BAD_REQUEST.getStatusCode()); + + given() + .when() + .contentType(APPLICATION_JSON) + .body(new UpdateMenuItemsRequestDTO()) .pathParam("id", "11-222") .patch() .then() @@ -262,23 +272,25 @@ void bulkPatchMenuItemsEmptyListTest() { @Test void patchMenuItemsTest() { - var menuItemDetailsDTO = new MenuItemDTO(); - menuItemDetailsDTO.setId("44-1"); + var menuItemDetailsDTO = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO.setName("Test menu 44-1"); menuItemDetailsDTO.setDisabled(false); menuItemDetailsDTO.setModificationCount(0); - var menuItemDetailsDTO1 = new MenuItemDTO(); - menuItemDetailsDTO1.setId("44-2"); + var menuItemDetailsDTO1 = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO1.setParentItemId("44-5"); menuItemDetailsDTO1.setName("Test menu 44-2"); menuItemDetailsDTO1.setDisabled(false); menuItemDetailsDTO1.setModificationCount(0); + var request = new UpdateMenuItemsRequestDTO(); + request.putItemsItem("44-1", menuItemDetailsDTO); + request.putItemsItem("44-2", menuItemDetailsDTO1); + var updatedData = given() .when() .contentType(APPLICATION_JSON) - .body(List.of(menuItemDetailsDTO, menuItemDetailsDTO1)) + .body(request) .pathParam("id", "11-222") .patch() .then().statusCode(OK.getStatusCode()) @@ -303,23 +315,25 @@ void patchMenuItemsTest() { @Test void bulkPatchMenuItemsNewMenuItemTest() { - var menuItemDetailsDTO = new MenuItemDTO(); - menuItemDetailsDTO.setId("44-1"); + var menuItemDetailsDTO = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO.setName("Test menu 44-1"); menuItemDetailsDTO.setDisabled(false); menuItemDetailsDTO.setModificationCount(0); - var menuItemDetailsDTO1 = new MenuItemDTO(); - menuItemDetailsDTO1.setId("does-not-exists"); + var menuItemDetailsDTO1 = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO1.setParentItemId("44-5"); menuItemDetailsDTO1.setName("Test menu 44-2"); menuItemDetailsDTO1.setDisabled(false); menuItemDetailsDTO1.setModificationCount(0); + var request = new UpdateMenuItemsRequestDTO(); + request.putItemsItem("44-1", menuItemDetailsDTO); + request.putItemsItem("does-not-exists", menuItemDetailsDTO); + given() .when() .contentType(APPLICATION_JSON) - .body(List.of(menuItemDetailsDTO, menuItemDetailsDTO1)) + .body(request) .pathParam("id", "11-222") .patch() .then().statusCode(NOT_FOUND.getStatusCode()); @@ -328,25 +342,27 @@ void bulkPatchMenuItemsNewMenuItemTest() { @Test void bulkPatchMenuItemsParentToParentTest() { - var menuItemDetailsDTO1 = new MenuItemDTO(); - menuItemDetailsDTO1.setId("44-5"); + var menuItemDetailsDTO1 = new UpdateMenuItemRequestDTO(); menuItemDetailsDTO1.setParentItemId("44-5"); menuItemDetailsDTO1.setName("Test menu 44-2"); menuItemDetailsDTO1.setDisabled(false); + var request = new UpdateMenuItemsRequestDTO(); + request.putItemsItem("44-5", menuItemDetailsDTO1); + given() .when() .contentType(APPLICATION_JSON) - .body(List.of(menuItemDetailsDTO1)) + .body(request) .pathParam("id", "11-222") .patch() .then().statusCode(BAD_REQUEST.getStatusCode()); } @Test - void patchMenuItemDoesNotUpdateParentTest() { + void updateMenuItemDoesNotUpdateParentTest() { - var request = new MenuItemDTO(); + var request = new UpdateMenuItemRequestDTO(); request.setKey("Test menu"); request.setDisabled(false); request.setParentItemId("44-2"); @@ -369,9 +385,9 @@ void patchMenuItemDoesNotUpdateParentTest() { } @Test - void patchMenuItemParentSetChildAsParentTest() { + void updateMenuItemParentSetChildAsParentTest() { - var request = new MenuItemDTO(); + var request = new UpdateMenuItemRequestDTO(); request.setKey("Test menu"); request.setDisabled(false); request.setParentItemId("44-6"); @@ -389,7 +405,31 @@ void patchMenuItemParentSetChildAsParentTest() { .extract().as(ProblemDetailResponseDTO.class); assertThat(error).isNotNull(); - assertThat(error.getErrorCode()).isEqualTo("CYCLE_DEPENDENCY"); + assertThat(error.getErrorCode()).isEqualTo(MenuItemService.MenuItemErrorKeys.CYCLE_DEPENDENCY.name()); + } + + @Test + void updateMenuItemParentSetToMenuItemTest() { + + var request = new UpdateMenuItemRequestDTO(); + request.setKey("Test menu"); + request.setDisabled(false); + request.setParentItemId("44-2"); + request.setModificationCount(0); + + // update menu item + var error = given() + .when() + .contentType(APPLICATION_JSON) + .body(request) + .pathParam("id", "11-222") + .pathParam("menuItemId", "44-2") + .put("{menuItemId}") + .then().statusCode(BAD_REQUEST.getStatusCode()) + .extract().as(ProblemDetailResponseDTO.class); + + assertThat(error).isNotNull(); + assertThat(error.getErrorCode()).isEqualTo(MenuItemService.MenuItemErrorKeys.PARENT_MENU_SAME_AS_MENU_ITEM.name()); } static Stream inputParams() { @@ -402,11 +442,12 @@ static Stream inputParams() { @ParameterizedTest @MethodSource("inputParams") - void patchMenuItemErrors(String portalId, String menuItemId, String parentItemId) { - var request = new MenuItemDTO(); + void updateMenuItemErrors(String portalId, String menuItemId, String parentItemId) { + var request = new UpdateMenuItemRequestDTO(); request.setKey("Test menu"); request.setDisabled(false); request.setParentItemId(parentItemId); + request.setModificationCount(0); // update menu item given() @@ -421,7 +462,7 @@ void patchMenuItemErrors(String portalId, String menuItemId, String parentItemId @Test void updateMenuItemTest() { - var request = new MenuItemDTO(); + var request = new UpdateMenuItemRequestDTO(); request.setKey("Test menu"); request.setDescription("New test menu description"); request.setDisabled(false); @@ -446,15 +487,16 @@ void updateMenuItemTest() { assertThat(updatedData.getWorkspaceName()).isEqualTo("test02"); //Update second time and expect a BAD REQUEST because of wrong modificationCount - // given() - // .when() - // .contentType(APPLICATION_JSON) - // .body(updatedData) - // .pathParam("id", "11-222") - // .pathParam("menuItemId", "44-6") - // .put("{menuItemId}") - // .then() - // .statusCode(BAD_REQUEST.getStatusCode()); + request.setModificationCount(-1); + given() + .when() + .contentType(APPLICATION_JSON) + .body(request) + .pathParam("id", "11-222") + .pathParam("menuItemId", "44-6") + .put("{menuItemId}") + .then() + .statusCode(BAD_REQUEST.getStatusCode()); var dto = given().when() .contentType(APPLICATION_JSON) @@ -466,15 +508,15 @@ void updateMenuItemTest() { .extract().as(MenuItemDTO.class); assertThat(dto).isNotNull(); - assertThat(updatedData.getKey()).isEqualTo(request.getKey()); + assertThat(updatedData.getKey()).isEqualTo(dto.getKey()); assertThat(updatedData.getWorkspaceName()).isEqualTo("test02"); - assertThat(updatedData.getDescription()).isEqualTo(request.getDescription()); + assertThat(updatedData.getDescription()).isEqualTo(dto.getDescription()); assertThat(dto.getName()).isEqualTo("Portal Child 1"); } @Test void updateMenuItemNotExistsTest() { - var request = new MenuItemDTO(); + var request = new UpdateMenuItemRequestDTO(); request.setKey("Test menu"); request.setDescription("New test menu description"); request.setDisabled(false); @@ -505,7 +547,7 @@ void uploadMenuStructureNoBodyTest() { @Test void uploadMenuStructureNoMenuItemsTest() { - var menuStructureListDTO = new WorkspaceMenuItemStructrueDTO(); + var menuStructureListDTO = new WorkspaceMenuItemStructureDTO(); menuStructureListDTO.setMenuItems(null); var error = given() @@ -520,7 +562,7 @@ void uploadMenuStructureNoMenuItemsTest() { assertThat(error).isNotNull(); assertThat(error.getErrorCode()).isEqualTo("MENU_ITEMS_NULL"); - menuStructureListDTO = new WorkspaceMenuItemStructrueDTO(); + menuStructureListDTO = new WorkspaceMenuItemStructureDTO(); menuStructureListDTO.setMenuItems(new ArrayList<>()); error = given() @@ -539,7 +581,7 @@ void uploadMenuStructureNoMenuItemsTest() { @Test void uploadMenuStructurePortalDoesNotExistsTest() { - var menuStructureListDTO = new WorkspaceMenuItemStructrueDTO(); + var menuStructureListDTO = new WorkspaceMenuItemStructureDTO(); var menuItemStructureDTO = new WorkspaceMenuItemDTO(); menuItemStructureDTO.setKey("Test menu"); @@ -565,7 +607,7 @@ void uploadMenuStructurePortalDoesNotExistsTest() { @Test void uploadMenuStructureTest() { - var menuStructureListDTO = new WorkspaceMenuItemStructrueDTO(); + var menuStructureListDTO = new WorkspaceMenuItemStructureDTO(); var menuItemStructureDTO = new WorkspaceMenuItemDTO(); menuItemStructureDTO.setKey("Test menu"); @@ -607,7 +649,7 @@ void uploadMenuStructureTest() { .get("/tree") .then() .statusCode(OK.getStatusCode()) - .extract().body().as(WorkspaceMenuItemStructrueDTO.class); + .extract().body().as(WorkspaceMenuItemStructureDTO.class); assertThat(data).isNotNull(); assertThat(data.getMenuItems()).hasSize(1); diff --git a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTenantTest.java b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTenantTest.java index 724f843..292efc4 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTenantTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTenantTest.java @@ -188,7 +188,7 @@ void getProductsForWorkspaceIdTest() { void updateProductByIdTest() { var request = new UpdateProductRequestDTO(); request.setBaseUrl("/onecx-core"); - request.setModificationCount(0); + request.setModificationCount(10); // not sending request var error = given() @@ -206,11 +206,11 @@ void updateProductByIdTest() { // not existing product given() .when() - .body(request) .contentType(APPLICATION_JSON) .pathParam("id", "11-111") .pathParam("productId", "1234") .header(APM_HEADER_PARAM, createToken("org2")) + .body(request) .put("{productId}") .then() .statusCode(NOT_FOUND.getStatusCode()); @@ -295,10 +295,10 @@ void updateProductByIdTest() { assertThat(filteredProduct.get().getMicrofrontends().get(0).getBasePath()) .isEqualTo(request.getMicrofrontends().get(0).getBasePath()); - request.setMicrofrontends(new ArrayList<>()); + dto.setMicrofrontends(new ArrayList<>()); dto = given() .when() - .body(request) + .body(dto) .contentType(APPLICATION_JSON) .pathParam("id", "11-111") .pathParam("productId", "1234") diff --git a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTest.java b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTest.java index 67427a3..2300875 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/ProductRestControllerTest.java @@ -186,6 +186,7 @@ void updateProductByIdTest() { var product = productDTOList.get(0); request.setBaseUrl("/mho-test"); + request.setModificationCount(product.getModificationCount()); request.setMicrofrontends(new ArrayList<>()); for (var mf : product.getMicrofrontends()) { var updateDto = new UpdateMicrofrontendDTO(); @@ -222,14 +223,14 @@ void updateProductByIdTest() { assertThat(response).isNotNull().isNotEmpty().hasSize(2); var filteredProduct = response.stream().filter(x -> x.getProductName().equals(product.getProductName())).findFirst(); - assertThat(filteredProduct.get().getMicrofrontends()).isNotEmpty(); + assertThat(filteredProduct).isPresent(); assertThat(filteredProduct.get().getMicrofrontends().get(0).getBasePath()) .isEqualTo(request.getMicrofrontends().get(0).getBasePath()); - request.setMicrofrontends(new ArrayList<>()); + dto.setMicrofrontends(new ArrayList<>()); dto = given() .when() - .body(request) + .body(dto) .contentType(APPLICATION_JSON) .pathParam("id", "11-111") .pathParam("productId", "1234") @@ -243,15 +244,32 @@ void updateProductByIdTest() { assertThat(dto.getBaseUrl()).isEqualTo(request.getBaseUrl()); //second time should fail because of wrong modificationCount - // request.setModificationCount(-1); - // given() - // .when() - // .body(request) - // .contentType(APPLICATION_JSON) - // .pathParam("id", "11-111") - // .pathParam("productId", "1234") - // .put("{productId}") - // .then() - // .statusCode(BAD_REQUEST.getStatusCode()); + request.setModificationCount(-1); + given() + .when() + .body(request) + .contentType(APPLICATION_JSON) + .pathParam("id", "11-111") + .pathParam("productId", "1234") + .put("{productId}") + .then() + .statusCode(BAD_REQUEST.getStatusCode()); + } + + @Test + void modificationCountTest() { + + var update = new UpdateProductRequestDTO(); + update.setBaseUrl("1234"); + update.setModificationCount(-1); + + given() + .when() + .body(update) + .contentType(APPLICATION_JSON) + .pathParam("id", "11-111") + .put("1234") + .then() + .statusCode(BAD_REQUEST.getStatusCode()); } } diff --git a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestControllerTest.java b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestControllerTest.java index 68c5195..86a066b 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestControllerTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/internal/controllers/WorkspaceInternalRestControllerTest.java @@ -286,7 +286,7 @@ void updateWorkspaceTest() { } @Test - void optlockTest() { + void modificationCountTest() { var updatedResponse = given().when() .contentType(APPLICATION_JSON) .pathParam("id", "11-222") diff --git a/src/test/java/org/tkit/onecx/workspace/rs/legacy/controllers/TkitPortalRestControllerExceptionTest.java b/src/test/java/org/tkit/onecx/workspace/rs/legacy/controllers/TkitPortalRestControllerExceptionTest.java index 75b3477..f08c116 100644 --- a/src/test/java/org/tkit/onecx/workspace/rs/legacy/controllers/TkitPortalRestControllerExceptionTest.java +++ b/src/test/java/org/tkit/onecx/workspace/rs/legacy/controllers/TkitPortalRestControllerExceptionTest.java @@ -55,7 +55,4 @@ void getMenuStructureForNoPortalNameTest() { assertThat(exception.getErrorCode()).isEqualTo(ERROR_TEST.name()); } - public enum ErrorKey { - ERROR_TEST; - } } diff --git a/src/test/resources/data/testdata-internal.xml b/src/test/resources/data/testdata-internal.xml index 115a82d..a709556 100644 --- a/src/test/resources/data/testdata-internal.xml +++ b/src/test/resources/data/testdata-internal.xml @@ -26,7 +26,7 @@ - + @@ -47,8 +47,8 @@ - - + +