diff --git a/amps/ags/pom.xml b/amps/ags/pom.xml
index 368fdadb2a..7ea46aa1b7 100644
--- a/amps/ags/pom.xml
+++ b/amps/ags/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-amps
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/ags/rm-automation/pom.xml b/amps/ags/rm-automation/pom.xml
index 83f4b18ca1..b60e5ec611 100644
--- a/amps/ags/rm-automation/pom.xml
+++ b/amps/ags/rm-automation/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-community-parent
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml b/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
index 92d6cb86a9..e0f6bf31e4 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-automation-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/ags/rm-community/pom.xml b/amps/ags/rm-community/pom.xml
index a149001911..4743beb7e7 100644
--- a/amps/ags/rm-community/pom.xml
+++ b/amps/ags/rm-community/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-community-parent
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/ags/rm-community/rm-community-repo/.env b/amps/ags/rm-community/rm-community-repo/.env
index fc37bc79cc..9c612ce1fb 100644
--- a/amps/ags/rm-community/rm-community-repo/.env
+++ b/amps/ags/rm-community/rm-community-repo/.env
@@ -1,3 +1,3 @@
-SOLR6_TAG=2.0.6-A4
+SOLR6_TAG=2.0.6
POSTGRES_TAG=14.4
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
diff --git a/amps/ags/rm-community/rm-community-repo/pom.xml b/amps/ags/rm-community/rm-community-repo/pom.xml
index 0a07aa28ee..8e85cc0f94 100644
--- a/amps/ags/rm-community/rm-community-repo/pom.xml
+++ b/amps/ags/rm-community/rm-community-repo/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-governance-services-community-repo-parent
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml b/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml
index dae56a6e0b..ce5a6d46bd 100644
--- a/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml
+++ b/amps/ags/rm-community/rm-community-rest-api-explorer/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-governance-services-community-repo-parent
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/pom.xml b/amps/pom.xml
index d4dbb3a5fd..a9d1866061 100644
--- a/amps/pom.xml
+++ b/amps/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/amps/share-services/pom.xml b/amps/share-services/pom.xml
index ed0697c0b4..90d7cf5448 100644
--- a/amps/share-services/pom.xml
+++ b/amps/share-services/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-community-repo-amps
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/core/pom.xml b/core/pom.xml
index f95335b303..4d48e8b4e3 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/data-model/pom.xml b/data-model/pom.xml
index dcae4f74c3..9ca95416cc 100644
--- a/data-model/pom.xml
+++ b/data-model/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/mmt/pom.xml b/mmt/pom.xml
index c84563075c..f075a4c335 100644
--- a/mmt/pom.xml
+++ b/mmt/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/distribution/pom.xml b/packaging/distribution/pom.xml
index 24937dadcc..51e2ecc6d3 100644
--- a/packaging/distribution/pom.xml
+++ b/packaging/distribution/pom.xml
@@ -9,6 +9,6 @@
org.alfresco
alfresco-community-repo-packaging
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/docker-alfresco/pom.xml b/packaging/docker-alfresco/pom.xml
index 70dc62b2ae..37c25ae4d7 100644
--- a/packaging/docker-alfresco/pom.xml
+++ b/packaging/docker-alfresco/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-packaging
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/pom.xml b/packaging/pom.xml
index a6f54d86f8..59ec7e5d0e 100644
--- a/packaging/pom.xml
+++ b/packaging/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/environment/.env b/packaging/tests/environment/.env
index fc37bc79cc..9c612ce1fb 100644
--- a/packaging/tests/environment/.env
+++ b/packaging/tests/environment/.env
@@ -1,3 +1,3 @@
-SOLR6_TAG=2.0.6-A4
+SOLR6_TAG=2.0.6
POSTGRES_TAG=14.4
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
diff --git a/packaging/tests/pom.xml b/packaging/tests/pom.xml
index ef43555ad2..9a596006c7 100644
--- a/packaging/tests/pom.xml
+++ b/packaging/tests/pom.xml
@@ -6,7 +6,7 @@
org.alfresco
alfresco-community-repo-packaging
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/scripts/output_tests_run.sh b/packaging/tests/scripts/output_tests_run.sh
index ca1c9355c4..cd7c630cbf 100755
--- a/packaging/tests/scripts/output_tests_run.sh
+++ b/packaging/tests/scripts/output_tests_run.sh
@@ -4,4 +4,4 @@ TAS_DIRECTORY=$1
cd ${TAS_DIRECTORY}
-cat target/reports/alfresco-tas.log | grep "*** STARTING"
+cat target/reports/alfresco-tas.log | grep -a "*** STARTING"
diff --git a/packaging/tests/tas-cmis/pom.xml b/packaging/tests/tas-cmis/pom.xml
index 11b8729383..6eeacfc3e9 100644
--- a/packaging/tests/tas-cmis/pom.xml
+++ b/packaging/tests/tas-cmis/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-tests
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/tas-email/pom.xml b/packaging/tests/tas-email/pom.xml
index 312f92e976..6bea3a195a 100644
--- a/packaging/tests/tas-email/pom.xml
+++ b/packaging/tests/tas-email/pom.xml
@@ -9,7 +9,7 @@
org.alfresco
alfresco-community-repo-tests
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/tas-integration/pom.xml b/packaging/tests/tas-integration/pom.xml
index a5b26852cb..3580670ea2 100644
--- a/packaging/tests/tas-integration/pom.xml
+++ b/packaging/tests/tas-integration/pom.xml
@@ -9,7 +9,7 @@
org.alfresco
alfresco-community-repo-tests
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/tas-restapi/pom.xml b/packaging/tests/tas-restapi/pom.xml
index 258f4aa6fb..149a190861 100644
--- a/packaging/tests/tas-restapi/pom.xml
+++ b/packaging/tests/tas-restapi/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-community-repo-tests
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/tas-restapi/src/main/java/org/alfresco/rest/requests/Categories.java b/packaging/tests/tas-restapi/src/main/java/org/alfresco/rest/requests/Categories.java
index e5a3843201..33697d5a65 100644
--- a/packaging/tests/tas-restapi/src/main/java/org/alfresco/rest/requests/Categories.java
+++ b/packaging/tests/tas-restapi/src/main/java/org/alfresco/rest/requests/Categories.java
@@ -33,7 +33,6 @@ import org.alfresco.rest.core.RestRequest;
import org.alfresco.rest.core.RestWrapper;
import org.alfresco.rest.model.RestCategoryModel;
import org.alfresco.rest.model.RestCategoryModelsCollection;
-import org.alfresco.rest.model.RestRuleModelsCollection;
import org.springframework.http.HttpMethod;
public class Categories extends ModelRequest
@@ -75,9 +74,34 @@ public class Categories extends ModelRequest
* @param restCategoryModel The categories to create.
* @return Created category with additional data populated by the repository.
*/
- public RestCategoryModel createSingleCategory(RestCategoryModel restCategoryModel) {
- RestRequest request = RestRequest.requestWithBody(HttpMethod.POST, restCategoryModel.toJson(), "categories/{categoryId}/subcategories", category.getId());
+ public RestCategoryModel createSingleCategory(RestCategoryModel restCategoryModel)
+ {
+ RestRequest request = RestRequest
+ .requestWithBody(HttpMethod.POST, restCategoryModel.toJson(), "categories/{categoryId}/subcategories", category.getId());
return restWrapper.processModel(RestCategoryModel.class, request);
}
+ /**
+ * Get parent category children.
+ *
+ * @return The list of child categories.
+ */
+ public RestCategoryModelsCollection getCategoryChildren()
+ {
+ RestRequest request = RestRequest.simpleRequest(HttpMethod.GET, "categories/{categoryId}/subcategories", category.getId());
+ return restWrapper.processModels(RestCategoryModelsCollection.class, request);
+ }
+
+ /**
+ * Delete category.
+ *
+ * - DELETE /categories/{categoryId}
+ */
+ public void deleteCategory()
+ {
+ RestRequest request = RestRequest.
+ simpleRequest(HttpMethod.DELETE, "/categories/{categoryId}", category.getId());
+ restWrapper.processEmptyModel(request);
+ }
+
}
diff --git a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/CreateCategoriesTests.java b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/CreateCategoriesTests.java
index 74200018f0..68e199dcf9 100644
--- a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/CreateCategoriesTests.java
+++ b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/CreateCategoriesTests.java
@@ -260,7 +260,7 @@ public class CreateCategoriesTests extends RestTest
restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Node id does not refer to a valid category");
}
- private List getCategoriesToCreate(final int count)
+ static List getCategoriesToCreate(final int count)
{
return IntStream.range(0, count)
.mapToObj(i -> {
diff --git a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/DeleteCategoriesTests.java b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/DeleteCategoriesTests.java
new file mode 100644
index 0000000000..e0b11e582c
--- /dev/null
+++ b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/DeleteCategoriesTests.java
@@ -0,0 +1,133 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.categories;
+
+import org.alfresco.rest.RestTest;
+import org.alfresco.rest.model.RestCategoryModel;
+import org.alfresco.utility.data.RandomData;
+import org.alfresco.utility.model.FolderModel;
+import org.alfresco.utility.model.SiteModel;
+import org.alfresco.utility.model.TestGroup;
+import org.alfresco.utility.model.UserModel;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+import static org.springframework.http.HttpStatus.CREATED;
+import static org.springframework.http.HttpStatus.FORBIDDEN;
+import static org.springframework.http.HttpStatus.NOT_FOUND;
+import static org.springframework.http.HttpStatus.NO_CONTENT;
+
+public class DeleteCategoriesTests extends RestTest {
+
+ private UserModel user;
+
+
+ @BeforeClass(alwaysRun = true)
+ public void dataPreparation() throws Exception
+ {
+ STEP("Create a user");
+ user = dataUser.createRandomTestUser();
+ }
+
+ /**
+ * Check we can delete a category.
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testDeleteCategory()
+ {
+ STEP("Create a category and send a request to delete it.");
+ RestCategoryModel aCategory = createCategory();
+ restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI().usingCategory(aCategory).deleteCategory();
+ restClient.assertStatusCodeIs(NO_CONTENT);
+
+ STEP("Ensure that the category has been deleted by sending a GET request and receiving 404.");
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(aCategory).getCategory();
+ restClient.assertStatusCodeIs(NOT_FOUND);
+ }
+
+ /**
+ * Check we get an error when trying to delete a category as a non-admin user.
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testDeleteCategoryAsRegularUser_andFail()
+ {
+ RestCategoryModel aCategory = createCategory();
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(aCategory).deleteCategory();
+ restClient.assertStatusCodeIs(FORBIDDEN).assertLastError().containsSummary("Current user does not have permission to delete a category");
+ }
+
+ /**
+ * Check we receive 404 error when trying to delete a category with a non-existent node id.
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testDeleteNonExistentCategory()
+ {
+ STEP("Get category with non-existent id");
+ final RestCategoryModel rootCategory = new RestCategoryModel();
+ final String id = "non-existing-dummy-id";
+ rootCategory.setId(id);
+
+ STEP("Attempt to delete category with non-existent id and receive 404");
+ restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI().usingCategory(rootCategory).deleteCategory();
+ restClient.assertStatusCodeIs(NOT_FOUND);
+ }
+
+ /**
+ * Attempt to delete a category when providing a node id that doesn't belong to a category
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testDeleteCategory_givenNonCategoryNodeId()
+ {
+ STEP("Create a site and a folder inside it");
+ final SiteModel site = dataSite.usingUser(user).createPublicRandomSite();
+ final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
+ String id = folder.getNodeRef();
+
+ STEP("Create a category, set its id to the folder id and attempt to delete it");
+ final RestCategoryModel aCategory = new RestCategoryModel();
+ aCategory.setId(id);
+ restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI().usingCategory(aCategory).deleteCategory();
+ restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Node id does not refer to a valid category");
+ }
+
+ public RestCategoryModel createCategory()
+ {
+ final RestCategoryModel rootCategory = new RestCategoryModel();
+ rootCategory.setId("-root-");
+ final RestCategoryModel aCategory = new RestCategoryModel();
+ aCategory.setName(RandomData.getRandomName("Category"));
+ final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
+ .withCoreAPI()
+ .usingCategory(rootCategory)
+ .createSingleCategory(aCategory);
+ restClient.assertStatusCodeIs(CREATED);
+
+ return createdCategory;
+ }
+}
diff --git a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/GetCategoriesTests.java b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/GetCategoriesTests.java
index d02312442b..a8d2da0340 100644
--- a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/GetCategoriesTests.java
+++ b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/categories/GetCategoriesTests.java
@@ -28,11 +28,20 @@ package org.alfresco.rest.categories;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
+import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import org.alfresco.rest.RestTest;
+import org.alfresco.rest.core.RestResponse;
import org.alfresco.rest.model.RestCategoryModel;
+import org.alfresco.rest.model.RestCategoryModelsCollection;
+import org.alfresco.utility.data.RandomData;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
@@ -42,6 +51,10 @@ import org.testng.annotations.Test;
public class GetCategoriesTests extends RestTest
{
+ private static final List DEFAULT_ROOT_CATEGORIES = List.of("Software Document Classification", "Languages", "Regions", "Tags");
+ private static final String ROOT = "-root-";
+ private static final String NON_EXISTING_CATEGORY_ID = "non-existing-category-id";
+
private UserModel user;
@BeforeClass(alwaysRun = true)
@@ -57,11 +70,29 @@ public class GetCategoriesTests extends RestTest
@Test(groups = {TestGroup.REST_API})
public void testGetCategoryById()
{
- STEP("Get category with -root- as id (which does not exist)");
+ STEP("Create a category under root category (as admin)");
final RestCategoryModel rootCategory = new RestCategoryModel();
- rootCategory.setId("-root-");
- restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategory();
- restClient.assertStatusCodeIs(NOT_FOUND);
+ rootCategory.setId(ROOT);
+ final RestCategoryModel aCategory = new RestCategoryModel();
+ aCategory.setName(RandomData.getRandomName("Category"));
+ final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
+ .withCoreAPI()
+ .usingCategory(rootCategory)
+ .createSingleCategory(aCategory);
+ restClient.assertStatusCodeIs(CREATED);
+
+ createdCategory.assertThat()
+ .field("name").is(aCategory.getName());
+ createdCategory.assertThat()
+ .field("parentId").is(rootCategory.getId());
+ createdCategory.assertThat()
+ .field("hasChildren").is(false);
+
+ STEP("Get the created category (as regular user)");
+ final RestCategoryModel categoryFromGet =
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(createdCategory).getCategory();
+ restClient.assertStatusCodeIs(OK);
+ categoryFromGet.assertThat().isEqualTo(createdCategory);
}
/**
@@ -70,15 +101,15 @@ public class GetCategoriesTests extends RestTest
@Test(groups = {TestGroup.REST_API})
public void testGetCategoryByIdProvidingRootAsId()
{
- STEP("Get category with -root- as id (which does not exist)");
+ STEP("Get category with -root- as id");
final RestCategoryModel rootCategory = new RestCategoryModel();
- rootCategory.setId("-root-");
+ rootCategory.setId(ROOT);
restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategory();
- restClient.assertStatusCodeIs(NOT_FOUND);
+ restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Node id does not refer to a valid category");
}
/**
- * Check we get an error when passing as category id
+ * Check we get an error when passing folder node id as category id
*/
@Test(groups = {TestGroup.REST_API})
public void testGetCategoryByIdProvidingFolderAsId()
@@ -91,7 +122,101 @@ public class GetCategoriesTests extends RestTest
final RestCategoryModel rootCategory = new RestCategoryModel();
rootCategory.setId(folder.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategory();
- restClient.assertStatusCodeIs(BAD_REQUEST);
+ restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Node id does not refer to a valid category");
}
+ /**
+ * Check we get an error when passing non existing as category id
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testGetCategoryByIdProvidingNonExistingId()
+ {
+ STEP("Get category with id which does not exist");
+ final RestCategoryModel rootCategory = new RestCategoryModel();
+ final String id = NON_EXISTING_CATEGORY_ID;
+ rootCategory.setId(id);
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategory();
+ restClient.assertStatusCodeIs(NOT_FOUND).assertLastError().containsSummary(id);
+ }
+
+ /**
+ * Check we can get children category of a root category
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testGetCategoryChildren()
+ {
+ STEP("Get category children with -root- as parent id");
+ final RestCategoryModel rootCategory = new RestCategoryModel();
+ rootCategory.setId(ROOT);
+ RestCategoryModelsCollection childCategoriesList =
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategoryChildren();
+ restClient.assertStatusCodeIs(OK);
+
+ childCategoriesList.assertThat().entriesListIsNotEmpty();
+ assertTrue(childCategoriesList.getEntries().stream()
+ .map(RestCategoryModel::onModel)
+ .map(RestCategoryModel::getName)
+ .collect(Collectors.toList())
+ .containsAll(DEFAULT_ROOT_CATEGORIES));
+ STEP("Create a new category under root and make sure it is returned as one of root's children");
+ final RestCategoryModel aCategory = new RestCategoryModel();
+ aCategory.setName((RandomData.getRandomName("newCategoryUnderRoot")));
+ final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
+ .withCoreAPI()
+ .usingCategory(rootCategory)
+ .createSingleCategory(aCategory);
+ restClient.assertStatusCodeIs(CREATED);
+
+ childCategoriesList = restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategoryChildren();
+ restClient.assertStatusCodeIs(OK);
+ assertTrue(childCategoriesList.getEntries().stream()
+ .map(RestCategoryModel::onModel)
+ .map(RestCategoryModel::getId)
+ .collect(Collectors.toList())
+ .contains(createdCategory.getId()));
+
+ STEP("Create 2 more categories under newCategoryUnderRoot and make sure they are returned as children");
+ final int categoriesCount = 2;
+ final List categoriesToCreate = CreateCategoriesTests.getCategoriesToCreate(categoriesCount);
+ final RestCategoryModelsCollection createdSubCategories = restClient.authenticateUser(dataUser.getAdminUser())
+ .withCoreAPI()
+ .usingCategory(createdCategory)
+ .createCategoriesList(categoriesToCreate);
+ restClient.assertStatusCodeIs(CREATED);
+ childCategoriesList = restClient.authenticateUser(user).withCoreAPI().usingCategory(rootCategory).getCategoryChildren();
+ restClient.assertStatusCodeIs(OK);
+ childCategoriesList.getEntries().containsAll(createdSubCategories.getEntries());
+ }
+
+ /**
+ * Check we get an error when passing folder node id as parent category id when getting children.
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testGetCategoryChildrenProvidingFolderAsId()
+ {
+ STEP("Create a site and a folder inside it");
+ final SiteModel site = dataSite.usingUser(user).createPublicRandomSite();
+ final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
+
+ STEP("Get category children with folder id passed as parent id");
+ final RestCategoryModel parentCategory = new RestCategoryModel();
+ parentCategory.setId(folder.getNodeRef());
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(parentCategory).getCategoryChildren();
+ restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Node id does not refer to a valid category");
+ }
+
+ /**
+ * Check we get an error when passing a non-existent node id as parent category id when getting children.
+ */
+ @Test(groups = {TestGroup.REST_API})
+ public void testGetCategoryChildrenProvidingNonExistingParent()
+ {
+
+ STEP("Get category with folder id passed as id");
+ final RestCategoryModel parentCategory = new RestCategoryModel();
+ final String parentId = NON_EXISTING_CATEGORY_ID;
+ parentCategory.setId(parentId);
+ restClient.authenticateUser(user).withCoreAPI().usingCategory(parentCategory).getCategoryChildren();
+ restClient.assertStatusCodeIs(NOT_FOUND).assertLastError().containsSummary(parentId);
+ }
}
diff --git a/packaging/tests/tas-webdav/pom.xml b/packaging/tests/tas-webdav/pom.xml
index 21614ddd38..c6510867a2 100644
--- a/packaging/tests/tas-webdav/pom.xml
+++ b/packaging/tests/tas-webdav/pom.xml
@@ -9,7 +9,7 @@
org.alfresco
alfresco-community-repo-tests
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/packaging/tests/tas-webdav/src/test/java/org/alfresco/webdav/WebDavTest.java b/packaging/tests/tas-webdav/src/test/java/org/alfresco/webdav/WebDavTest.java
index f75eed0f92..ca71c0ab91 100644
--- a/packaging/tests/tas-webdav/src/test/java/org/alfresco/webdav/WebDavTest.java
+++ b/packaging/tests/tas-webdav/src/test/java/org/alfresco/webdav/WebDavTest.java
@@ -1,17 +1,25 @@
package org.alfresco.webdav;
+import java.lang.reflect.Method;
+
import org.alfresco.utility.data.DataContent;
import org.alfresco.utility.data.DataSite;
import org.alfresco.utility.data.DataUser;
+import org.alfresco.utility.LogFactory;
import org.alfresco.utility.network.ServerHealth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.slf4j.Logger;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
@ContextConfiguration("classpath:alfresco-webdav-context.xml")
public abstract class WebDavTest extends AbstractTestNGSpringContextTests
{
+ private static final Logger LOG = LogFactory.getLogger();
+
@Autowired
protected DataSite dataSite;
@@ -36,4 +44,16 @@ public abstract class WebDavTest extends AbstractTestNGSpringContextTests
// The webdav protocol is enabled by default.
//webDavProtocol.assertThat().protocolIsEnabled();
}
-}
+
+ @BeforeMethod(alwaysRun=true)
+ public void showStartTestInfo(Method method)
+ {
+ LOG.info(String.format("*** STARTING Test: [%s] ***", method.getName()));
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void showEndTestInfo(Method method)
+ {
+ LOG.info(String.format("*** ENDING Test: [%s] ***", method.getName()));
+ }
+}
\ No newline at end of file
diff --git a/packaging/war/pom.xml b/packaging/war/pom.xml
index 0cae073a7c..1c8075a60c 100644
--- a/packaging/war/pom.xml
+++ b/packaging/war/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo-packaging
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index e7e4878733..9e6845e241 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
pom
Alfresco Community Repo Parent
diff --git a/remote-api/pom.xml b/remote-api/pom.xml
index 38a8d8cffb..0c485a45a4 100644
--- a/remote-api/pom.xml
+++ b/remote-api/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT
diff --git a/remote-api/src/main/java/org/alfresco/rest/api/Categories.java b/remote-api/src/main/java/org/alfresco/rest/api/Categories.java
index 6c18d06fd2..a3babc5905 100644
--- a/remote-api/src/main/java/org/alfresco/rest/api/Categories.java
+++ b/remote-api/src/main/java/org/alfresco/rest/api/Categories.java
@@ -29,9 +29,9 @@ package org.alfresco.rest.api;
import java.util.List;
import org.alfresco.rest.api.model.Category;
+import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
-import org.alfresco.service.cmr.repository.NodeRef;
@Experimental
public interface Categories
@@ -39,4 +39,9 @@ public interface Categories
Category getCategoryById(String id, Parameters params);
List createSubcategories(String parentCategoryId, List categories, Parameters parameters);
+
+ CollectionWithPagingInfo getCategoryChildren(String parentCategoryId, Parameters params);
+
+ void deleteCategoryById(String id, Parameters params);
+
}
diff --git a/remote-api/src/main/java/org/alfresco/rest/api/categories/CategoriesEntityResource.java b/remote-api/src/main/java/org/alfresco/rest/api/categories/CategoriesEntityResource.java
index 3bde251ca0..df8483958f 100644
--- a/remote-api/src/main/java/org/alfresco/rest/api/categories/CategoriesEntityResource.java
+++ b/remote-api/src/main/java/org/alfresco/rest/api/categories/CategoriesEntityResource.java
@@ -41,7 +41,8 @@ import org.alfresco.rest.framework.resource.parameters.Parameters;
* @author mpichura
*/
@EntityResource(name = "categories", title = "Categories")
-public class CategoriesEntityResource implements EntityResourceAction.ReadById
+public class CategoriesEntityResource implements EntityResourceAction.ReadById,
+ EntityResourceAction.Delete
{
private final Categories categories;
@@ -58,4 +59,12 @@ public class CategoriesEntityResource implements EntityResourceAction.ReadById
+public class SubcategoriesRelation implements RelationshipResourceAction.Create, RelationshipResourceAction.Read
{
private final Categories categories;
@@ -56,4 +57,13 @@ public class SubcategoriesRelation implements RelationshipResourceAction.Create<
{
return categories.createSubcategories(parentCategoryId, categoryList, parameters);
}
+
+ @WebApiDescription(title = "List category direct children",
+ description = "Lists direct children of a parent category",
+ successStatus = HttpServletResponse.SC_OK)
+ @Override
+ public CollectionWithPagingInfo readAll(String parentCategoryId, Parameters params)
+ {
+ return categories.getCategoryChildren(parentCategoryId, params);
+ }
}
diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/CategoriesImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/CategoriesImpl.java
index 8db2796b16..f00cede7a9 100644
--- a/remote-api/src/main/java/org/alfresco/rest/api/impl/CategoriesImpl.java
+++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/CategoriesImpl.java
@@ -39,6 +39,8 @@ import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
+import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
+import org.alfresco.rest.framework.resource.parameters.ListPage;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -56,6 +58,7 @@ public class CategoriesImpl implements Categories
{
static final String NOT_A_VALID_CATEGORY = "Node id does not refer to a valid category";
static final String NO_PERMISSION_TO_CREATE_A_CATEGORY = "Current user does not have permission to create a category";
+ static final String NO_PERMISSION_TO_DELETE_A_CATEGORY = "Current user does not have permission to delete a category";
private static final String NOT_NULL_OR_EMPTY = "Category name must not be null or empty";
private final AuthorityService authorityService;
@@ -74,8 +77,8 @@ public class CategoriesImpl implements Categories
@Override
public Category getCategoryById(final String id, final Parameters params)
{
- final NodeRef nodeRef = nodes.validateNode(id);
- if (isNotACategory(nodeRef) || isRootCategory(nodeRef))
+ final NodeRef nodeRef = getCategoryNodeRef(id);
+ if (isRootCategory(nodeRef))
{
throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{id});
}
@@ -90,14 +93,7 @@ public class CategoriesImpl implements Categories
{
throw new PermissionDeniedException(NO_PERMISSION_TO_CREATE_A_CATEGORY);
}
- final NodeRef parentNodeRef = PATH_ROOT.equals(parentCategoryId) ?
- categoryService.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE)
- .orElseThrow(() -> new EntityNotFoundException(parentCategoryId)) :
- nodes.validateNode(parentCategoryId);
- if (isNotACategory(parentNodeRef))
- {
- throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{parentCategoryId});
- }
+ final NodeRef parentNodeRef = getCategoryNodeRef(parentCategoryId);
final List categoryNodeRefs = categories.stream()
.map(c -> createCategoryNodeRef(parentNodeRef, c))
.collect(Collectors.toList());
@@ -106,6 +102,66 @@ public class CategoriesImpl implements Categories
.collect(Collectors.toList());
}
+ @Override
+ public CollectionWithPagingInfo getCategoryChildren(String parentCategoryId, Parameters params)
+ {
+ final NodeRef parentNodeRef = getCategoryNodeRef(parentCategoryId);
+ final List childCategoriesAssocs = nodeService.getChildAssocs(parentNodeRef).stream()
+ .filter(ca -> ContentModel.ASSOC_SUBCATEGORIES.equals(ca.getTypeQName()))
+ .collect(Collectors.toList());
+ final List categories = childCategoriesAssocs.stream()
+ .map(c -> mapToCategory(c.getChildRef()))
+ .collect(Collectors.toList());
+ return ListPage.of(categories, params.getPaging());
+ }
+
+ @Override
+ public void deleteCategoryById(String id, Parameters params)
+ {
+ if (!authorityService.hasAdminAuthority())
+ {
+ throw new PermissionDeniedException(NO_PERMISSION_TO_DELETE_A_CATEGORY);
+ }
+
+ final NodeRef nodeRef = nodes.validateNode(id);
+ if (isNotACategory(nodeRef) || isRootCategory(nodeRef))
+ {
+ throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{id});
+ }
+
+ nodeService.deleteNode(nodeRef);
+ }
+
+ /**
+ * This method gets category NodeRef for a given category id.
+ * If '-root-' is passed as category id, then it's retrieved as a call to {@link org.alfresco.service.cmr.search.CategoryService#getRootCategoryNodeRef}
+ * In all other cases it's retrieved as a node of a category type {@link #validateCategoryNode(String)}
+ * @param nodeId category node id
+ * @return NodRef of category node
+ */
+ private NodeRef getCategoryNodeRef(String nodeId)
+ {
+ return PATH_ROOT.equals(nodeId) ?
+ categoryService.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE)
+ .orElseThrow(() -> new EntityNotFoundException(nodeId)) :
+ validateCategoryNode(nodeId);
+ }
+
+ /**
+ * Validates if the node exists and is a category.
+ * @param nodeId (presumably) category node id
+ * @return category NodeRef
+ */
+ private NodeRef validateCategoryNode(String nodeId)
+ {
+ final NodeRef nodeRef = nodes.validateNode(nodeId);
+ if (isNotACategory(nodeRef))
+ {
+ throw new InvalidArgumentException(NOT_A_VALID_CATEGORY, new String[]{nodeId});
+ }
+ return nodeRef;
+ }
+
private NodeRef createCategoryNodeRef(NodeRef parentNodeRef, Category c)
{
if (StringUtils.isEmpty(c.getName())) {
diff --git a/remote-api/src/test/java/org/alfresco/rest/api/categories/SubcategoriesRelationTest.java b/remote-api/src/test/java/org/alfresco/rest/api/categories/SubcategoriesRelationTest.java
new file mode 100644
index 0000000000..7b1948f7d2
--- /dev/null
+++ b/remote-api/src/test/java/org/alfresco/rest/api/categories/SubcategoriesRelationTest.java
@@ -0,0 +1,105 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.api.categories;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.then;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.alfresco.rest.api.Categories;
+import org.alfresco.rest.api.model.Category;
+import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
+import org.alfresco.rest.framework.resource.parameters.Paging;
+import org.alfresco.rest.framework.resource.parameters.Parameters;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SubcategoriesRelationTest
+{
+ private static final String PARENT_CATEGORY_ID = "parent-category-node-id";
+ private static final String CATEGORY_ID = "category-node-id";
+ private static final String CATEGORY_NAME = "categoryName";
+ private static final String SUBCATEGORY_NAME_PREFIX = "childCategoryName";
+
+ @Mock
+ private Categories categoriesMock;
+ @Mock
+ private Parameters parametersMock;
+
+ @InjectMocks
+ private SubcategoriesRelation objectUnderTest;
+
+ @Test
+ public void testCreateSubcategory()
+ {
+ final Category categoryToCreate = Category.builder().name(CATEGORY_NAME).create();
+ final Category category = Category.builder().name(CATEGORY_NAME).parentId(PARENT_CATEGORY_ID).hasChildren(false).id(CATEGORY_ID).create();
+ final List categoriesToCreate = List.of(categoryToCreate);
+ given(categoriesMock.createSubcategories(PARENT_CATEGORY_ID, categoriesToCreate, parametersMock)).willReturn(List.of(category));
+
+ //when
+ List categories = objectUnderTest.create(PARENT_CATEGORY_ID, categoriesToCreate, parametersMock);
+
+ then(categoriesMock).should().createSubcategories(PARENT_CATEGORY_ID, categoriesToCreate, parametersMock);
+ then(categoriesMock).shouldHaveNoMoreInteractions();
+ assertEquals(List.of(category), categories);
+ }
+
+ @Test
+ public void testGetCategoryChildren() {
+ final CollectionWithPagingInfo categoryChildren = getCategories(3);
+ given(categoriesMock.getCategoryChildren(PARENT_CATEGORY_ID, parametersMock)).willReturn(categoryChildren);
+
+ //when
+ final CollectionWithPagingInfo returnedChildren = objectUnderTest.readAll(PARENT_CATEGORY_ID, parametersMock);
+
+ then(categoriesMock).should().getCategoryChildren(PARENT_CATEGORY_ID, parametersMock);
+ then(categoriesMock).shouldHaveNoMoreInteractions();
+ assertEquals(categoryChildren, returnedChildren);
+ }
+
+ private CollectionWithPagingInfo getCategories(final int count)
+ {
+ return CollectionWithPagingInfo.asPaged(Paging.DEFAULT,
+ IntStream.range(0, count)
+ .mapToObj(i -> Category.builder().name(SUBCATEGORY_NAME_PREFIX + "-" + i)
+ .parentId(PARENT_CATEGORY_ID)
+ .hasChildren(false)
+ .id(CATEGORY_ID + "-" + i)
+ .create())
+ .collect(Collectors.toList())
+ );
+ }
+}
diff --git a/remote-api/src/test/java/org/alfresco/rest/api/impl/CategoriesImplTest.java b/remote-api/src/test/java/org/alfresco/rest/api/impl/CategoriesImplTest.java
index 7787e19812..f4e5dd6f62 100644
--- a/remote-api/src/test/java/org/alfresco/rest/api/impl/CategoriesImplTest.java
+++ b/remote-api/src/test/java/org/alfresco/rest/api/impl/CategoriesImplTest.java
@@ -31,10 +31,15 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import org.alfresco.model.ContentModel;
import org.alfresco.rest.api.Nodes;
@@ -43,6 +48,7 @@ import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
+import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -224,6 +230,92 @@ public class CategoriesImplTest
then(authorityServiceMock).shouldHaveNoInteractions();
}
+ @Test
+ public void testDeleteCategoryById_asAdmin()
+ {
+ given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
+ final NodeRef categoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID);
+ given(nodesMock.validateNode(CATEGORY_ID)).willReturn(categoryNodeRef);
+ given(nodesMock.isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
+ final Node categoryNode = new Node();
+ categoryNode.setName(CATEGORY_NAME);
+ categoryNode.setNodeId(CATEGORY_ID);
+ final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
+ categoryNode.setParentId(parentNodeRef);
+
+ //when
+ objectUnderTest.deleteCategoryById(CATEGORY_ID, parametersMock);
+
+ then(authorityServiceMock).should().hasAdminAuthority();
+ then(authorityServiceMock).shouldHaveNoMoreInteractions();
+ then(nodesMock).should().validateNode(CATEGORY_ID);
+
+ then(nodesMock).should().isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false);
+ then(nodesMock).shouldHaveNoMoreInteractions();
+
+ then(nodeServiceMock).should().getParentAssocs(categoryNodeRef);
+ then(nodeServiceMock).should().deleteNode(categoryNodeRef);
+ then(nodeServiceMock).shouldHaveNoMoreInteractions();
+ }
+
+ @Test
+ public void testDeleteCategoryById_asNonAdminUser()
+ {
+ given(authorityServiceMock.hasAdminAuthority()).willReturn(false);
+
+ //when
+ assertThrows(PermissionDeniedException.class, () -> objectUnderTest.deleteCategoryById(CATEGORY_ID, parametersMock));
+
+ then(authorityServiceMock).should().hasAdminAuthority();
+ then(authorityServiceMock).shouldHaveNoMoreInteractions();
+
+ then(nodesMock).shouldHaveNoInteractions();
+ then(nodeServiceMock).shouldHaveNoInteractions();
+ }
+
+ @Test
+ public void testDeleteCategoryById_nonCategoryId()
+ {
+ given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
+ final NodeRef categoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID);
+ given(nodesMock.validateNode(CATEGORY_ID)).willReturn(categoryNodeRef);
+ given(nodesMock.isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(false);
+
+ //when
+ assertThrows(InvalidArgumentException.class, () -> objectUnderTest.deleteCategoryById(CATEGORY_ID, parametersMock));
+
+ then(authorityServiceMock).should().hasAdminAuthority();
+ then(authorityServiceMock).shouldHaveNoMoreInteractions();
+
+ then(nodesMock).should().validateNode(CATEGORY_ID);
+ then(nodesMock).should().isSubClass(categoryNodeRef, ContentModel.TYPE_CATEGORY, false);
+ then(nodesMock).shouldHaveNoMoreInteractions();
+ }
+
+ @Test
+ public void testDeleteCategoryById_rootCategory()
+ {
+ given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
+ final NodeRef categoryRootNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CAT_ROOT_NODE_ID);
+ given(nodesMock.validateNode(CAT_ROOT_NODE_ID)).willReturn(categoryRootNodeRef);
+ given(nodesMock.isSubClass(categoryRootNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
+ given(categoryChildAssociationRefMock.getQName()).willReturn(ContentModel.ASPECT_GEN_CLASSIFIABLE);
+ given(nodeServiceMock.getParentAssocs(categoryRootNodeRef)).willReturn(List.of(categoryChildAssociationRefMock));
+
+ //when
+ assertThrows(InvalidArgumentException.class, () -> objectUnderTest.deleteCategoryById(CAT_ROOT_NODE_ID, parametersMock));
+
+ then(authorityServiceMock).should().hasAdminAuthority();
+ then(authorityServiceMock).shouldHaveNoMoreInteractions();
+
+ then(nodesMock).should().validateNode(CAT_ROOT_NODE_ID);
+ then(nodesMock).should().isSubClass(categoryRootNodeRef, ContentModel.TYPE_CATEGORY, false);
+ then(nodesMock).shouldHaveNoMoreInteractions();
+
+ then(nodeServiceMock).should().getParentAssocs(categoryRootNodeRef);
+ then(nodeServiceMock).shouldHaveNoMoreInteractions();
+ }
+
@Test
public void testCreateCategoryUnderRoot()
{
@@ -231,7 +323,6 @@ public class CategoriesImplTest
final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PATH_ROOT);
given(categoryServiceMock.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE))
.willReturn(Optional.of(parentCategoryNodeRef));
- given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
final NodeRef categoryNodeRef = prepareCategoryNodeRef();
given(categoryServiceMock.createCategory(parentCategoryNodeRef, CATEGORY_NAME)).willReturn(categoryNodeRef);
given(nodesMock.getNode(CATEGORY_ID)).willReturn(prepareCategoryNode());
@@ -246,7 +337,6 @@ public class CategoriesImplTest
then(authorityServiceMock).should().hasAdminAuthority();
then(authorityServiceMock).shouldHaveNoMoreInteractions();
- then(nodesMock).should().isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false);
then(nodesMock).should().getNode(CATEGORY_ID);
then(nodesMock).shouldHaveNoMoreInteractions();
then(nodeServiceMock).should().getPrimaryParent(categoryNodeRef);
@@ -366,12 +456,151 @@ public class CategoriesImplTest
then(categoryServiceMock).shouldHaveNoInteractions();
}
+ @Test
+ public void testGetRootCategoryChildren()
+ {
+ final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PATH_ROOT);
+ given(categoryServiceMock.getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE))
+ .willReturn(Optional.of(parentCategoryNodeRef));
+ final int childrenCount = 3;
+ final List childAssociationRefMocks = prepareChildAssocMocks(childrenCount, parentCategoryNodeRef);
+ given(nodeServiceMock.getChildAssocs(parentCategoryNodeRef)).willReturn(childAssociationRefMocks);
+ childAssociationRefMocks.forEach(this::prepareCategoryNodeMocks);
+
+ //when
+ final CollectionWithPagingInfo categoryChildren = objectUnderTest.getCategoryChildren(PATH_ROOT, parametersMock);
+
+ then(categoryServiceMock).should().getRootCategoryNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
+ then(categoryServiceMock).shouldHaveNoMoreInteractions();
+ then(nodeServiceMock).should().getChildAssocs(parentCategoryNodeRef);
+ childAssociationRefMocks.forEach(ca -> {
+ then(nodesMock).should().getNode(ca.getChildRef().getId());
+ then(nodeServiceMock).should()
+ .getChildAssocs(ca.getChildRef(), RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
+ then(nodeServiceMock).should().getPrimaryParent(ca.getChildRef());
+ });
+ then(nodeServiceMock).should(times(childrenCount)).getParentAssocs(parentCategoryNodeRef);
+
+ then(nodesMock).shouldHaveNoMoreInteractions();
+ then(nodeServiceMock).shouldHaveNoMoreInteractions();
+
+ then(authorityServiceMock).shouldHaveNoInteractions();
+
+ assertEquals(childAssociationRefMocks.size(), categoryChildren.getTotalItems().intValue());
+ final List categoryChildrenList = new ArrayList<>(categoryChildren.getCollection());
+ assertEquals(childAssociationRefMocks.size(), categoryChildrenList.size());
+ IntStream.range(0, childrenCount).forEach(i -> doCategoryAssertions(categoryChildrenList.get(i), i, PATH_ROOT));
+ }
+
+ @Test
+ public void testGetCategoryChildren()
+ {
+ final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
+ given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
+ given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
+ final int childrenCount = 3;
+ final List childAssociationRefMocks = prepareChildAssocMocks(childrenCount, parentCategoryNodeRef);
+ given(nodeServiceMock.getChildAssocs(parentCategoryNodeRef)).willReturn(childAssociationRefMocks);
+ childAssociationRefMocks.forEach(this::prepareCategoryNodeMocks);
+
+ //when
+ final CollectionWithPagingInfo categoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
+
+ then(nodesMock).should().validateNode(PARENT_ID);
+ then(nodesMock).should().isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false);
+ then(nodeServiceMock).should().getChildAssocs(parentCategoryNodeRef);
+ childAssociationRefMocks.forEach(ca -> {
+ then(nodesMock).should().getNode(ca.getChildRef().getId());
+ then(nodeServiceMock).should()
+ .getChildAssocs(ca.getChildRef(), RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
+ then(nodeServiceMock).should().getPrimaryParent(ca.getChildRef());
+ });
+ then(nodeServiceMock).should(times(childrenCount)).getParentAssocs(parentCategoryNodeRef);
+
+ then(nodesMock).shouldHaveNoMoreInteractions();
+ then(nodeServiceMock).shouldHaveNoMoreInteractions();
+
+ then(authorityServiceMock).shouldHaveNoInteractions();
+ then(categoryServiceMock).shouldHaveNoInteractions();
+
+ assertEquals(childAssociationRefMocks.size(), categoryChildren.getTotalItems().intValue());
+ final List categoryChildrenList = new ArrayList<>(categoryChildren.getCollection());
+ assertEquals(childAssociationRefMocks.size(), categoryChildrenList.size());
+ IntStream.range(0, childrenCount).forEach(i -> doCategoryAssertions(categoryChildrenList.get(i), i, PARENT_ID));
+ }
+
+ @Test
+ public void testGetCategoryChildren_noChildren()
+ {
+ final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
+ given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
+ given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
+
+ given(nodeServiceMock.getChildAssocs(parentCategoryNodeRef)).willReturn(Collections.emptyList());
+
+
+ //when
+ final CollectionWithPagingInfo categoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
+
+ then(nodesMock).should().validateNode(PARENT_ID);
+ then(nodesMock).should().isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false);
+ then(nodesMock).shouldHaveNoMoreInteractions();
+ then(nodeServiceMock).should().getChildAssocs(parentCategoryNodeRef);
+ then(nodeServiceMock).shouldHaveNoMoreInteractions();
+
+ then(authorityServiceMock).shouldHaveNoInteractions();
+ then(categoryServiceMock).shouldHaveNoInteractions();
+
+ assertEquals(0, categoryChildren.getTotalItems().intValue());
+ }
+
+ @Test
+ public void testGetCategoryChildren_wrongParentNodeType()
+ {
+ final NodeRef parentCategoryNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
+ given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
+ given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(false);
+
+ //when
+ assertThrows(InvalidArgumentException.class, () -> objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock));
+
+ then(nodesMock).should().validateNode(PARENT_ID);
+ then(nodesMock).should().isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false);
+ then(nodesMock).shouldHaveNoMoreInteractions();
+
+ then(nodeServiceMock).shouldHaveNoInteractions();
+ then(categoryServiceMock).shouldHaveNoInteractions();
+ then(authorityServiceMock).shouldHaveNoInteractions();
+ }
+
+ @Test
+ public void testGetCategoryChildren_nonExistingParentNode()
+ {
+ given(nodesMock.validateNode(PARENT_ID)).willThrow(EntityNotFoundException.class);
+
+ //when
+ assertThrows(EntityNotFoundException.class, () -> objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock));
+
+
+ then(nodesMock).should().validateNode(PARENT_ID);
+ then(nodesMock).shouldHaveNoMoreInteractions();
+
+ then(nodeServiceMock).shouldHaveNoInteractions();
+ then(categoryServiceMock).shouldHaveNoInteractions();
+ then(authorityServiceMock).shouldHaveNoInteractions();
+ }
+
private Node prepareCategoryNode()
{
- final Node categoryNode = new Node();
- categoryNode.setName(CATEGORY_NAME);
- categoryNode.setNodeId(CATEGORY_ID);
final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_ID);
+ return prepareCategoryNode(CATEGORY_NAME, CATEGORY_ID, parentNodeRef);
+ }
+
+ private Node prepareCategoryNode(final String name, final String id, final NodeRef parentNodeRef)
+ {
+ final Node categoryNode = new Node();
+ categoryNode.setName(name);
+ categoryNode.setNodeId(id);
categoryNode.setParentId(parentNodeRef);
return categoryNode;
}
@@ -387,4 +616,40 @@ public class CategoriesImplTest
.name(CATEGORY_NAME)
.create());
}
+
+ private List prepareChildAssocMocks(final int count, NodeRef parentCategoryNodeRef)
+ {
+ return IntStream.range(0, count).mapToObj(i -> {
+ ChildAssociationRef dummyChildAssocMock = mock(ChildAssociationRef.class);
+ given(dummyChildAssocMock.getTypeQName()).willReturn(ContentModel.ASSOC_SUBCATEGORIES);
+ given(dummyChildAssocMock.getChildRef())
+ .willReturn(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, CATEGORY_ID + "-" + i));
+ given(dummyChildAssocMock.getParentRef()).willReturn(parentCategoryNodeRef);
+ return dummyChildAssocMock;
+ })
+ .collect(Collectors.toList());
+ }
+
+ private void prepareCategoryNodeMocks(ChildAssociationRef childAssociationRef)
+ {
+ final NodeRef childRef = childAssociationRef.getChildRef();
+ final String id = childRef.getId();
+ final String name = id.replace(CATEGORY_ID, CATEGORY_NAME);
+ final NodeRef parentRef = childAssociationRef.getParentRef();
+ given(nodesMock.getNode(id)).willReturn(prepareCategoryNode(name, id, parentRef));
+ final ChildAssociationRef parentAssoc = new ChildAssociationRef(null, parentRef, null, childRef);
+ given(nodeServiceMock.getPrimaryParent(childRef)).willReturn(parentAssoc);
+ given(nodeServiceMock.getParentAssocs(parentRef)).willReturn(List.of(parentAssoc));
+ }
+
+ private void doCategoryAssertions(final Category category, final int index, final String parentId)
+ {
+ final Category expectedCategory = Category.builder()
+ .id(CATEGORY_ID + "-" + index)
+ .name(CATEGORY_NAME + "-" + index)
+ .parentId(parentId)
+ .hasChildren(false)
+ .create();
+ assertEquals(expectedCategory, category);
+ }
}
diff --git a/repository/pom.xml b/repository/pom.xml
index 0b74a64168..3b22b8a836 100644
--- a/repository/pom.xml
+++ b/repository/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-community-repo
- 20.41-SNAPSHOT
+ 20.45-SNAPSHOT