From 7bbef89e0afe00fe3d181d13da658e091be3fee1 Mon Sep 17 00:00:00 2001 From: freddyDOTCMS <147462678+freddyDOTCMS@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:18:37 -0600 Subject: [PATCH] #28894 Create Endpoint to calculate Hierarchy (#29142) ### Proposed Changes * Create a new End point to calculate Hierarchy https://github.com/dotCMS/core/pull/29142/files#diff-1677f12a3b6c8909f3436afc7817819af2f46ac5ae6a37bdfab43690ffa24780R289 - Crate Factory and AOI methods too https://github.com/dotCMS/core/pull/29142/files#diff-cc8d6686856cf74ed3cfdbbf782839a205ade11ffa80218a0a1365fe47ac7c17R535 https://github.com/dotCMS/core/pull/29142/files#diff-88379e3d0d9b5a5c54cb2207518bb686c3a9243cf6419ff11377616a7cd88dd2R324 --------- Co-authored-by: Daniel Silva --- .../api/v1/categories/CategoriesResource.java | 103 +- .../api/v1/categories/CategoryInodesForm.java | 41 + .../HierarchyShortCategoriesResponseView.java | 13 + .../categories/business/CategoryAPI.java | 37 + .../categories/business/CategoryAPIImpl.java | 25 +- .../categories/business/CategoryFactory.java | 36 + .../business/CategoryFactoryImpl.java | 105 +- .../model/HierarchyShortCategory.java | 25 + .../categories/business/CategoryAPITest.java | 38 +- .../business/CategoryFactoryTest.java | 58 +- .../postman/Category.postman_collection.json | 906 ++++++++++++++++-- 11 files changed, 1292 insertions(+), 95 deletions(-) create mode 100644 dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java create mode 100644 dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java create mode 100644 dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java index 33b2f33ce41c..ccddc281c05e 100644 --- a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java @@ -31,6 +31,7 @@ import com.dotmarketing.portlets.categories.business.CategoryAPI; import com.dotmarketing.portlets.categories.business.PaginatedCategories; import com.dotmarketing.portlets.categories.model.Category; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; import com.dotmarketing.util.ActivityLogger; import com.dotmarketing.util.Logger; import com.dotmarketing.util.PageMode; @@ -138,7 +139,6 @@ public CategoriesResource(final WebResource webresource, final PaginationUtil pa *
  • per_page: limit of items to return
  • *
  • ordeby: field to order by
  • *
  • direction: asc for upward order and desc for downward order
  • - *
  • showChildrenCount: true for including children categories count and false to exclude it
  • * *

    * Url example: /api/v1/categories?filter=&page=0&per_page=5&ordeby=category_name&direction=ASC&showChildrenCount=true @@ -196,22 +196,30 @@ public final Response getCategories(@Context final HttpServletRequest httpReques /** * Return a list of {@link com.dotmarketing.portlets.categories.model.Category}, entity response - * syntax:. + * Syntax:. + * + * + * { + * contentTypes: array of Category, + * total: total number of Categories + * } + * * - * { contentTypes: array of Category total: total number of Categories } *

    * Url syntax: * api/v1/categories/children?filter=filter-string&page=page-number&per_page=per-page&orderby=order-field-name&direction=order-direction&inode=parentId *

    - * where: * - *

    + * Parameeters: + * + * - filter-string: Return categories whose names contain this pattern. + * - page: The page number to return. + * - per_page: The limit of items to return. + * - orderby: The field to order by. + * - direction: Sorting direction, asc for ascending and desc for descending. + * - showChildrenCount: true to include the count of child categories, false to exclude it. + * - allLevels: A Boolean value. If TRUE, the search will include categories at any level, ignoring the childrenCategories parameter. If showChildrenCount is TRUE, this parameter is ignored. + * *

    * Url example: v1/categories/children?filter=test&page=0&per_page=5&orderby=category_name * @@ -276,6 +284,79 @@ public final Response getChildren(@Context final HttpServletRequest httpRequest, return response; } + /** + * Response with the list of parents for a specific set of {@link Category}. + * + * This ned point receive a list the {@link Category}'s endpoint as follow: + * + * + * { + * "inodes": ["352ca17e238357ce12e9dff10afc8516", "c0ab974897f8d37c98afa4bba74ef9f1"] + * } + * + * + * The output is going to be something like: + * + * + * { + * entity: [ + * { + * "inode": "352ca17e238357ce12e9dff10afc8516", + * "parentList": [ + * { + * 'categoryName': 'Grand Parent Name', + * 'key': 'Grand Parent Key', + * 'inode': 'Grand Parent inode' + * }, + * { + * 'categoryName': 'Parent Name', + * 'key': 'Parent Key', + * 'inode': 'Parent inode' + * } + * ] + * }, + * { + * "inode": "c0ab974897f8d37c98afa4bba74ef9f1", + * "parentList": [ + * { + * 'categoryName': 'Category name value', + * 'key': 'Key value', + * 'inode': 'inode value' + * } + * ] + * } + * ] + * } + * + * + * parentList is the list of parents where the 0 is the more top level parent and the last one is the direct + * parent. + * + * @param httpRequest + * @param httpResponse + * @param form + * @return + * @throws DotDataException + * @throws DotSecurityException + */ + @GET + @Path(("/hierarchy")) + @JSONP + @NoCache + @Produces({MediaType.APPLICATION_JSON}) + public final Response getHierarchy(@Context final HttpServletRequest httpRequest, + @Context final HttpServletResponse httpResponse, + final CategoryInodesForm form) throws DotDataException, DotSecurityException { + + Logger.debug(this, () -> "Getting the List of Parents for the follow categories: " + + form.getInodes().stream().collect(Collectors.joining(","))); + + webResource.init(null, httpRequest, httpResponse, true, null); + + return Response.ok( + new HierarchyShortCategoriesResponseView(categoryAPI.findHierarchy(form.getInodes()))).build(); + } + /** * Lookup operation. Categories can be retrieved by category id or key * @param httpRequest diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java new file mode 100644 index 000000000000..4a71b43d8f71 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java @@ -0,0 +1,41 @@ +package com.dotcms.rest.api.v1.categories; + +import com.dotcms.repackage.javax.validation.constraints.NotNull; +import com.dotcms.rest.api.Validated; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +/** + * Category Input Form + */ +@JsonDeserialize(builder = CategoryInodesForm.Builder.class) +public class CategoryInodesForm extends Validated { + + private List inodes; + + private CategoryInodesForm(final Builder builder) { + + this.inodes = builder.inodes; + } + + public List getInodes() { + return inodes; + } + + public static final class Builder { + + @JsonProperty + private List inodes; + + public void setInodes(List inodes) { + this.inodes = inodes; + } + + public CategoryInodesForm build() { + + return new CategoryInodesForm(this); + } + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java new file mode 100644 index 000000000000..8e418e80b8ae --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java @@ -0,0 +1,13 @@ +package com.dotcms.rest.api.v1.categories; + +import com.dotcms.experiments.model.Experiment; +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; + +import java.util.List; + +public class HierarchyShortCategoriesResponseView extends ResponseEntityView> { + public HierarchyShortCategoriesResponseView(final List categories) { + super(categories); + } +} \ No newline at end of file diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java index 8ff3f200b8da..44b0558d25a5 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java @@ -5,8 +5,11 @@ import com.dotmarketing.exception.DotDataException; import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.categories.model.Category; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; import com.dotmarketing.portlets.contentlet.model.Contentlet; import com.liferay.portal.model.User; + +import java.util.Collection; import java.util.HashMap; import java.util.List; /** @@ -496,4 +499,38 @@ Category findByVariable(final String variable, final User user, */ PaginatedCategories findAll(final CategorySearchCriteria searchCriteria, final User user, boolean respectFrontendRoles) throws DotDataException, DotSecurityException; + + /** + * Find Categories by inodes and calculate its Hierarchy. + * + * For Example if you have the follows categories: + * + * + * | Inode | Name | key |Parent | + * |--------|-------------|-------------|----------------| + * | 1 | Top Category| top | null | + * | 2 | Child | child | Top Category | + * | 3 | Grand Child | grand_child | Child | + * + * And you search by inode 3 then you got: + * + * Inode: 3 + * parentList [ + * { + * 'categoryName':'Top Category', + * 'key': 'top', + * 'inode': '1' + * }, + * { + * 'categoryName':'Child', + * 'key': 'child', + * 'inode': '2' + * } + * ] + * + * @param inodes List of inodes to search + * @return + * @throws DotDataException + */ + List findHierarchy(final Collection inodes) throws DotDataException; } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java index fab12f505b88..2e30d0ff6b44 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java @@ -17,6 +17,7 @@ import com.dotmarketing.exception.DotDataException; import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.categories.model.Category; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; import com.dotmarketing.portlets.contentlet.model.Contentlet; import com.dotmarketing.util.ActivityLogger; import com.dotmarketing.util.InodeUtils; @@ -25,14 +26,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.liferay.portal.model.User; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.UUID; + +import java.util.*; import java.util.stream.Collectors; /** @@ -978,4 +973,18 @@ public PaginatedCategories findAll(final CategorySearchCriteria searchCriteria, return getCategoriesSubList(searchCriteria.offset, searchCriteria.limit, categories, null); } + /** + * Default implementation of {@link CategoryAPI} + * + * @param inodes List of inodes to search + * @return + * + * @throws DotDataException + */ + @CloseDBIfOpened + @Override + public List findHierarchy(final Collection inodes) throws DotDataException { + Logger.debug(this, "Getting parentList for the follow Categories: " + inodes); + return categoryFactory.findHierarchy(inodes); + } } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java index d113529ee09a..332376eef471 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java @@ -1,11 +1,13 @@ package com.dotmarketing.portlets.categories.business; +import java.util.Collection; import java.util.List; import com.dotmarketing.exception.DotDataException; import com.dotmarketing.portlets.categories.model.Category; import com.dotmarketing.portlets.categories.model.HierarchedCategory; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; /** @@ -286,4 +288,38 @@ public abstract class CategoryFactory { * @return List of Category filteredx */ public abstract List findAll(final CategorySearchCriteria searchCriteria) throws DotDataException; + + /** + * Find Categories by inodes and calculate its Hierarchy. + * + * For Example if you have the follows categories: + * + * + * | Inode | Name | key |Parent | + * |--------|-------------|-------------|----------------| + * | 1 | Top Category| top | null | + * | 2 | Child | child | Top Category | + * | 3 | Grand Child | grand_child | Child | + * + * And you search by inode 3 then you got: + * + * Inode: 3 + * parentList [ + * { + * 'categoryName':'Top Category', + * 'key': 'top', + * 'inode': '1' + * }, + * { + * 'categoryName':'Child', + * 'key': 'child', + * 'inode': '2' + * } + * ] + * + * @param inodes List of inodes to search + * @return + * @throws DotDataException + */ + public abstract List findHierarchy(final Collection inodes) throws DotDataException; } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java index 31e8aeb46a1b..d821386218dd 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java @@ -17,24 +17,24 @@ import com.dotmarketing.common.util.SQLUtil; import com.dotmarketing.db.DbConnectionFactory; import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotRuntimeException; import com.dotmarketing.factories.TreeFactory; import com.dotmarketing.portlets.categories.model.Category; import com.dotmarketing.portlets.categories.model.HierarchedCategory; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; import com.dotmarketing.portlets.categories.model.ShortCategory; import com.dotmarketing.util.InodeUtils; import com.dotmarketing.util.Logger; import com.dotmarketing.util.UtilMethods; import com.dotmarketing.util.VelocityUtil; import com.liferay.util.StringPool; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.Serializable; import java.sql.*; -import java.util.ArrayList; +import java.util.*; import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; import java.util.stream.Collectors; /** @@ -633,22 +633,12 @@ private List convertForHierarchedCategories(final List parentList = ((List>) JsonUtil.getObjectFromJson(parentsASJsonArray, List.class)) - .stream() - .map(map -> new ShortCategory.Builder() - .setCategoryName(map.get("categoryName")) - .setKey(map.get("key")) - .setInode(map.get(INODE)) - .build() - ) - .collect(Collectors.toList()); - + final List parentList = getShortCategories(parentsASJsonArray); category.setParentList(parentList.subList(0, parentList.size() - 1)); } categories.add(category); - } catch (IOException e) { + } catch ( Exception e) { Logger.warn(CategoryFactoryImpl.class, e::getMessage); } } @@ -657,6 +647,39 @@ private List convertForHierarchedCategories(final List + * [ + * { + * 'categoryName': 'Category name value', + * 'key': 'Key value', + * 'inode': 'inode value' + * } + * ] + * + * + * + * @param parentsASJsonArray + * @return + */ + private static List getShortCategories(String parentsASJsonArray) { + try { + return ((List>) JsonUtil.getObjectFromJson(parentsASJsonArray, List.class)) + .stream() + .map(map -> new ShortCategory.Builder() + .setCategoryName(map.get("categoryName")) + .setKey(map.get("key")) + .setInode(map.get(INODE)) + .build() + ) + .collect(Collectors.toList()); + } catch (IOException e) { + throw new DotRuntimeException(e); + } + } + private Category convertForCategory(final Map sqlResult) { return convertForCategory(sqlResult, Category.class); } @@ -949,4 +972,54 @@ private void updateCache(List categories) throws DotDataExce } } + /** + * Default implementation of {@link CategoryFactory#findHierarchy(Collection)} + * + * @param inodes list of inodes to search + * @return + * @throws DotDataException + */ + @Override + public List findHierarchy(final Collection inodes) throws DotDataException { + + if (inodes == null || inodes.isEmpty()) { + return Collections.emptyList(); + } + + final String queryTemplate = "WITH RECURSIVE CategoryHierarchy AS ( SELECT " + + "c.inode," + + "c.inode AS root_inode," + + "1 AS level," + + "json_build_object('inode', c.inode, 'categoryName', c.category_name, 'key', c.category_key)::varchar AS path " + + "FROM Category c " + + "WHERE c.inode IN (%s) " + + "UNION ALL " + + "SELECT " + + "c.inode, " + + "ch.root_inode AS root_inode, " + + "ch.level + 1 AS level, " + + "CONCAT(json_build_object('inode', c.inode, 'categoryName', c.category_name, 'key', c.category_key)::varchar, ',', ch.path) AS path " + + "FROM Category c JOIN tree t ON c.inode = t.parent JOIN CategoryHierarchy ch ON t.child = ch.inode " + + ")," + + "MaxLevels AS (SELECT root_inode, MAX(level) AS max_level FROM CategoryHierarchy GROUP BY root_inode) " + + "SELECT " + + "ch.root_inode as inode, " + + "CONCAT('[', path, ']')::jsonb as path " + + "FROM CategoryHierarchy ch JOIN MaxLevels ml ON ch.root_inode = ml.root_inode AND ch.level = ml.max_level;"; + + + final DotConnect dc = new DotConnect() + .setSQL(String.format(queryTemplate, DotConnect.createParametersPlaceholder(inodes.size()))); + + inodes.forEach(dc::addParam); + + return dc.loadObjectResults().stream().map(row -> { + final List parentList = getShortCategories(row.get("path").toString()); + + return new HierarchyShortCategory(row.get(INODE).toString(), parentList.subList(0, parentList.size() - 1)); + }).collect(Collectors.toList()); + } + + + } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java new file mode 100644 index 000000000000..f2c5db0869b3 --- /dev/null +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java @@ -0,0 +1,25 @@ +package com.dotmarketing.portlets.categories.model; + +import java.io.Serializable; +import java.util.List; + +/** + * Represents a HierarchyCategory but just include the parentList and the inode + */ +public class HierarchyShortCategory implements Serializable { + private final String inode; + private final List parentList; + + public HierarchyShortCategory(final String inode, final List parentList) { + this.inode = inode; + this.parentList = parentList; + } + + public String getInode() { + return inode; + } + + public List getParentList() { + return parentList; + } +} diff --git a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java index 8df95b568119..0e9d36b3a2d1 100644 --- a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java +++ b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java @@ -8,8 +8,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import com.dotcms.IntegrationTestBase; import com.dotcms.contenttype.business.ContentTypeAPIImpl; @@ -35,6 +34,7 @@ import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.categories.model.Category; import com.dotmarketing.portlets.categories.model.HierarchedCategory; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; import com.dotmarketing.portlets.contentlet.business.ContentletAPI; import com.dotmarketing.portlets.contentlet.business.HostAPI; import com.dotmarketing.portlets.contentlet.model.Contentlet; @@ -1661,4 +1661,38 @@ public void getAllCategoriesFilteredWithPagination() throws DotDataException, Do assertEquals(4, secondPage.getCategories().size()); assertTrue(list(category6, category7, category8, category9).containsAll(secondPage.getCategories())); } + + /** + * Method to test: {@link CategoryAPIImpl#findAll(CategorySearchCriteria, User, boolean)} + * When: Call the API method + * Should: it should + * - Use the {@link CategoryFactoryImpl#findAll(CategorySearchCriteria)} to search the {@link Category} + * - Use the {@link PermissionAPI#filterCollection(List, int, boolean, User)} method to check permission + */ + @Test + public void findHierarchy() throws DotDataException, DotSecurityException { + final String inode = new RandomString().nextString(); + + final HierarchyShortCategory category1 = mock(HierarchyShortCategory.class); + when(category1.getInode()).thenReturn(inode); + + final HierarchyShortCategory category2 = mock(HierarchyShortCategory.class); + final HierarchyShortCategory category3 = mock(HierarchyShortCategory.class); + + final List categoriesAExpected = list(category2, category3); + + final List inodes = list(category1.getInode()); + final CategoryFactory categoryFactory = mock(); + when(categoryFactory.findHierarchy(inodes)).thenReturn(categoriesAExpected); + + final PermissionAPI permissionAPI = mock(PermissionAPI.class); + + final CategoryAPI categoryAPI = new CategoryAPIImpl(categoryFactory, permissionAPI); + final List hierarchy = categoryAPI.findHierarchy(inodes); + + assertEquals(categoriesAExpected.size(), hierarchy.size()); + assertTrue(categoriesAExpected.containsAll(hierarchy)); + + verify(categoryFactory).findHierarchy(inodes); + } } diff --git a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java index a6c0903f41d0..92b07f52751c 100644 --- a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java +++ b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java @@ -20,14 +20,12 @@ import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.categories.model.Category; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import com.dotmarketing.portlets.categories.model.HierarchedCategory; +import com.dotmarketing.portlets.categories.model.HierarchyShortCategory; import com.dotmarketing.portlets.categories.model.ShortCategory; import com.liferay.util.StringUtil; import com.tngtech.java.junit.dataprovider.DataProvider; @@ -640,4 +638,56 @@ public String transformToSearch(){ return transformToSearch.apply(filter); } } + + /** + * Method to test: {@link com.dotmarketing.portlets.categories.model.HierarchyShortCategory} + * when: Create 4 Category each is a child of the previous one and find for the great grand child and the grand child + * should: Return the great grand child we all the parent list + * @throws DotDataException + */ + @Test + public void findHierarchy() throws DotDataException { + final Category topLevelCategory = new CategoryDataGen().setCategoryName("Top Level Category") + .setKey("top_level") + .setCategoryVelocityVarName("top_level_categoria") + .nextPersisted(); + + final Category childCategory = new CategoryDataGen().setCategoryName("Child Category") + .setKey("child") + .setCategoryVelocityVarName("child_category") + .parent(topLevelCategory) + .nextPersisted(); + + final Category grandChildCategory = new CategoryDataGen().setCategoryName("Grand Child Category") + .setKey("grand_child") + .setCategoryVelocityVarName("grand_child_category") + .parent(childCategory) + .nextPersisted(); + + final Category greatGrandchildCategory = new CategoryDataGen().setCategoryName("Great Grand Child Category") + .setKey("great_grand_child") + .setCategoryVelocityVarName("great_grand_child_category") + .parent(grandChildCategory) + .nextPersisted(); + + final List categories = FactoryLocator.getCategoryFactory() + .findHierarchy(list(grandChildCategory.getInode(), greatGrandchildCategory.getInode())); + + assertEquals(2, categories.size()); + + for (final HierarchyShortCategory category : categories) { + if (grandChildCategory.getInode().equals(category.getInode())) { + assertEquals(2, category.getParentList().size()); + assertEquals("Top Level Category", category.getParentList().get(0).getCategoryName()); + assertEquals("Child Category", category.getParentList().get(1).getCategoryName()); + } else if (greatGrandchildCategory.getInode().equals(category.getInode())) { + assertEquals(3, category.getParentList().size()); + assertEquals("Top Level Category", category.getParentList().get(0).getCategoryName()); + assertEquals("Child Category", category.getParentList().get(1).getCategoryName()); + assertEquals("Grand Child Category", category.getParentList().get(2).getCategoryName()); + } else { + throw new AssertionError("Unexpected Category"); + } + } + } } diff --git a/dotcms-postman/src/main/resources/postman/Category.postman_collection.json b/dotcms-postman/src/main/resources/postman/Category.postman_collection.json index 1b9b85825f59..5b9d409ca5ab 100644 --- a/dotcms-postman/src/main/resources/postman/Category.postman_collection.json +++ b/dotcms-postman/src/main/resources/postman/Category.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "d13b8154-b0c4-46eb-afcd-902105508f76", + "_postman_id": "12554162-5748-4f0b-a315-85639e82d87b", "name": "Category", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "30436704" @@ -2890,7 +2890,7 @@ "method": "GET", "header": [], "url": { - "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&allLevels=true&inode={{topCategoryInode}}", + "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&allLevels=true&inode={{topCategoryInode}}&per_page=7000&direction=ASC", "host": [ "{{serverURL}}" ], @@ -2912,14 +2912,591 @@ { "key": "inode", "value": "{{topCategoryInode}}" + }, + { + "key": "showChildrenCount", + "value": "true", + "disabled": true + }, + { + "key": "per_page", + "value": "7000" + }, + { + "key": "direction", + "value": "ASC" + } + ] + } + }, + "response": [] + }, + { + "name": "Get categories by filter AND looking on the entire tree (Enabled showChildrenCount)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Fetch successfully without errors\", function () {", + " pm.expect(jsonData.errors).to.have.lengthOf(0);", + "});", + "", + "pm.expect(2).to.have.equals(jsonData.entity.length);", + "", + "pm.test('get the right categories', () => { ", + " let data = [];", + "", + " for (let i = 0; i < jsonData.entity.length; i++)", + " { ", + " data.push(jsonData.entity[i]['categoryName']); ", + "", + " if (i === 0) {", + " pm.expect('PostmanTest Child 1').to.have.equals(jsonData.entity[i].categoryName);", + " pm.expect(jsonData.entity[i].parentList).to.be.undefined;", + " } else if (i === 1) {", + " pm.expect('PostmanTest Child 2').to.have.equals(jsonData.entity[i].categoryName);", + " pm.expect(jsonData.entity[i].parentList).to.be.undefined;", + " } ", + " }", + "", + " data.includes(\"PostmanTest Child 1\");", + " data.includes(\"PostmanTest Child 2\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&allLevels=true&inode={{topCategoryInode}}&showChildrenCount=true&per_page=7000&direction=ASC", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories", + "children" + ], + "query": [ + { + "key": "filter", + "value": "PostmanTest" + }, + { + "key": "allLevels", + "value": "true" + }, + { + "key": "inode", + "value": "{{topCategoryInode}}" + }, + { + "key": "showChildrenCount", + "value": "true" + }, + { + "key": "per_page", + "value": "7000" + }, + { + "key": "direction", + "value": "ASC" + } + ] + } + }, + "response": [] + }, + { + "name": "Get categories by filter AND looking just in children", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Fetch successfully without errors\", function () {", + " pm.expect(jsonData.errors).to.have.lengthOf(0);", + "});", + "", + "pm.expect(2).to.have.equals(jsonData.entity.length);", + "", + "pm.test('get the right categories', () => { ", + " let data = [];", + "", + " for (let i = 0; i < jsonData.entity.length; i++)", + " { ", + " data.push(jsonData.entity[i]['categoryName']); ", + " }", + "", + " data.includes(\"PostmanTest Child 1\");", + " data.includes(\"PostmanTest Child 2\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&inode={{topCategoryInode}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories", + "children" + ], + "query": [ + { + "key": "filter", + "value": "PostmanTest" + }, + { + "key": "inode", + "value": "{{topCategoryInode}}" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Getting Category Hierarchy", + "item": [ + { + "name": "Create Top Level category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Top level Category\");", + "});", + "", + "pm.collectionVariables.set(\"topCategoryInodeHierarchy\", jsonData.entity.inode);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key\":\"Hierarchy_TOP_LEVEL\",\n \"categoryName\" : \"Hierarchy Top level Category\",\n \"categoryVelocityVarName\" : \"hierarchy_childrenTopLevel\",\n \"sortOrder\" : 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories" + ] + } + }, + "response": [] + }, + { + "name": "Create First child Category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Child 1\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key\":\"Hierarchy Child 1\",\n \"categoryName\" : \"Hierarchy Child 1\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_ChildTestKey_1\",\n \"parent\" : \"{{topCategoryInodeHierarchy}}\"\n}\n\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories" + ] + } + }, + "response": [] + }, + { + "name": "Create Second child Category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Child 2\");", + "});", + "", + "pm.collectionVariables.set(\"child2CategoryInodeHierarchy\", jsonData.entity.inode);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key\":\"Hierarchy Child 2\",\n \"categoryName\" : \"Hierarchy Child 2\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_ChildTestKey_2\",\n \"parent\" : \"{{topCategoryInodeHierarchy}}\"\n}\n\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories" + ] + } + }, + "response": [] + }, + { + "name": "Create Third child Category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Child 3\");", + "});", + "", + "", + "pm.collectionVariables.set(\"child3CategoryInodeHierarchy\", jsonData.entity.inode);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key\":\"Hierarchy_Child_3\",\n \"categoryName\" : \"Hierarchy Child 3\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_ChildTestKey_3\",\n \"parent\" : \"{{topCategoryInodeHierarchy}}\"\n}\n\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories" + ] + } + }, + "response": [] + }, + { + "name": "Create Grandchild Category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Grandchild 1\");", + "});", + "", + "pm.collectionVariables.set(\"grantChildCategoryInodeHierarchy\", jsonData.entity.inode);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key\":\"Hierarchy ChiGrandchildld 1\",\n \"categoryName\" : \"Hierarchy Grandchild 1\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_GrandcßhildTestKey_1\",\n \"parent\" : \"{{child3CategoryInodeHierarchy}}\"\n}\n\n", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories" ] } }, "response": [] }, { - "name": "Get categories by filter AND looking just in children", + "name": "Create Second Top Level category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key\":\"Hierarchy Second TOP_LEVEL\",\n \"categoryName\" : \"Hierarchy Second Top level Category\",\n \"categoryVelocityVarName\" : \"hierarchy_second_childrenTopLevel\",\n \"sortOrder\" : 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories" + ] + } + }, + "response": [] + }, + { + "name": "Get categories hierarchy", "event": [ { "listen": "test", @@ -2935,6 +3512,9 @@ " pm.expect(jsonData.errors).to.have.lengthOf(0);", "});", "", + "var child2CategoryInodeHierarchy = pm.collectionVariables.get(\"child2CategoryInodeHierarchy\"); ", + "var grantChildCategoryInodeHierarchy = pm.collectionVariables.get(\"grantChildCategoryInodeHierarchy\"); ;", + "", "pm.expect(2).to.have.equals(jsonData.entity.length);", "", "pm.test('get the right categories', () => { ", @@ -2942,11 +3522,122 @@ "", " for (let i = 0; i < jsonData.entity.length; i++)", " { ", - " data.push(jsonData.entity[i]['categoryName']); ", + "", + " if (jsonData.entity[i]['inode'] === child2CategoryInodeHierarchy) {", + " pm.expect(1).to.have.equals(jsonData.entity[i].parentList.length);", + " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);", + " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);", + " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);", + " } else if (jsonData.entity[i]['inode'] === grantChildCategoryInodeHierarchy) {", + " pm.expect(2).to.have.equals(jsonData.entity[i].parentList.length);", + "", + " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);", + " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);", + " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);", + "", + " pm.expect(\"Hierarchy Child 3\").to.have.equals(jsonData.entity[i].parentList[1].categoryName);", + " pm.expect(pm.collectionVariables.get(\"child3CategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[1].inode);", + " pm.expect(\"Hierarchy_Child_3\").to.have.equals(jsonData.entity[i].parentList[1].key);", + " } else {", + " pm.expect(true).to.be.equals(false);", + " } ", + " }", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"inodes\": [\"{{grantChildCategoryInodeHierarchy}}\", \"{{child2CategoryInodeHierarchy}}\"]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories/hierarchy", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories", + "hierarchy" + ] + } + }, + "response": [] + }, + { + "name": "Get categories hierarchy with no valid category", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Fetch successfully without errors\", function () {", + " pm.expect(jsonData.errors).to.have.lengthOf(0);", + "});", + "", + "var child2CategoryInodeHierarchy = pm.collectionVariables.get(\"child2CategoryInodeHierarchy\"); ", + "var grantChildCategoryInodeHierarchy = pm.collectionVariables.get(\"grantChildCategoryInodeHierarchy\"); ;", + "", + "pm.expect(2).to.have.equals(jsonData.entity.length);", + "", + "pm.test('get the right categories', () => { ", + " let data = [];", + "", + " for (let i = 0; i < jsonData.entity.length; i++)", + " { ", + "", + " if (jsonData.entity[i]['inode'] === child2CategoryInodeHierarchy) {", + " pm.expect(1).to.have.equals(jsonData.entity[i].parentList.length);", + " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);", + " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);", + " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);", + " } else if (jsonData.entity[i]['inode'] === grantChildCategoryInodeHierarchy) {", + " pm.expect(2).to.have.equals(jsonData.entity[i].parentList.length);", + "", + " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);", + " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);", + " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);", + "", + " pm.expect(\"Hierarchy Child 3\").to.have.equals(jsonData.entity[i].parentList[1].categoryName);", + " pm.expect(pm.collectionVariables.get(\"child3CategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[1].inode);", + " pm.expect(\"Hierarchy_Child_3\").to.have.equals(jsonData.entity[i].parentList[1].key);", + " } else {", + " pm.expect(true).to.be.equals(false);", + " } ", " }", "", - " data.includes(\"PostmanTest Child 1\");", - " data.includes(\"PostmanTest Child 2\");", "});", "" ], @@ -2955,6 +3646,9 @@ } } ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, "request": { "auth": { "type": "bearer", @@ -2968,8 +3662,17 @@ }, "method": "GET", "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"inodes\": [\"{{grantChildCategoryInodeHierarchy}}\", \"{{child2CategoryInodeHierarchy}}\", \"not_valid_category\"]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { - "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&inode={{topCategoryInode}}", + "raw": "{{serverURL}}/api/v1/categories/hierarchy", "host": [ "{{serverURL}}" ], @@ -2977,17 +3680,72 @@ "api", "v1", "categories", - "children" - ], - "query": [ - { - "key": "filter", - "value": "PostmanTest" - }, + "hierarchy" + ] + } + }, + "response": [] + }, + { + "name": "Get categories hierarchy with empty array of inodes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Fetch successfully without errors\", function () {", + " pm.expect(jsonData.errors).to.have.lengthOf(0);", + "});", + "", + "pm.expect(0).to.have.equals(jsonData.entity.length);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ { - "key": "inode", - "value": "{{topCategoryInode}}" + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"inodes\": []\n}", + "options": { + "raw": { + "language": "json" } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/categories/hierarchy", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "categories", + "hierarchy" ] } }, @@ -3001,44 +3759,7 @@ "type": "text/javascript", "packages": {}, "exec": [ - "if (!pm.environment.get('jwt')) {", - " const serverURL = pm.environment.get('serverURL'); // Get the server URL from the environment variable", - " const apiUrl = `${serverURL}/api/v1/apitoken`; // Construct the full API URL", - "", - " if (!pm.environment.get('jwt')) {", - " const username = 'admin@dotcms.com';", - " const password = 'admin';", - " const basicAuth = btoa(`${username}:${password}`);", - "", - " const requestOptions = {", - " url: apiUrl,", - " method: \"POST\",", - " header: {", - " \"accept\": \"*/*\",", - " \"content-type\": \"application/json\",", - " \"Authorization\": `Basic ${basicAuth}`", - " },", - " body: {", - " mode: \"raw\",", - " raw: JSON.stringify({", - " \"expirationSeconds\": 7200,", - " \"userId\": \"dotcms.org.1\",", - " \"network\": \"0.0.0.0/0\",", - " \"claims\": {\"label\": \"postman-tests\"}", - " })", - " }", - " };", - "", - " pm.sendRequest(requestOptions, function (err, response) {", - " if (err) {", - " console.log(err);", - " } else {", - " const jwt = response.json().entity.jwt;", - " pm.environment.set('jwt', jwt);", - " }", - " });", - " }", - "}" + "" ] } }, @@ -5350,6 +6071,67 @@ "response": [] } ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + " const serverURL = pm.environment.get('serverURL'); // Get the server URL from the environment variable", + " const apiUrl = `${serverURL}/api/v1/apitoken`; // Construct the full API URL", + "", + "// If we are unable to get the JWT we need to generate a new one", + " if (!pm.environment.get('jwt')) {", + " const username = pm.environment.get(\"user\");", + " const password = pm.environment.get(\"password\");", + " const basicAuth = Buffer.from(`${username}:${password}`).toString('base64');", + "", + "", + " const requestOptions = {", + " url: apiUrl,", + " method: \"POST\",", + " header: {", + " \"accept\": \"*/*\",", + " \"content-type\": \"application/json\",", + " \"Authorization\": `Basic ${basicAuth}`", + " },", + " body: {", + " mode: \"raw\",", + " raw: JSON.stringify({", + " \"expirationSeconds\": 7200,", + " \"userId\": \"dotcms.org.1\",", + " \"network\": \"0.0.0.0/0\",", + " \"claims\": {\"label\": \"postman-tests\"}", + " })", + " }", + " };", + "", + "", + " pm.sendRequest(requestOptions, function (err, response) {", + " if (err) {", + " console.log(err);", + " } else {", + " const jwt = response.json().entity.jwt;", + " pm.environment.set('jwt', jwt);", + " console.log(jwt);", + " }", + " });", + " }" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], "variable": [ { "key": "templateIdToEdit", @@ -5402,6 +6184,22 @@ { "key": "child3Inode", "value": "" + }, + { + "key": "topCategoryInodeHierarchy", + "value": "" + }, + { + "key": "child2CategoryInodeHierarchy", + "value": "" + }, + { + "key": "child3CategoryInodeHierarchy", + "value": "" + }, + { + "key": "grantChildCategoryInodeHierarchy", + "value": "" } ] } \ No newline at end of file