ACS-4030: Delete category endpoint (#1618)

* ACS-4030: Delete category endpoint implementation and tests
This commit is contained in:
George Evangelopoulos
2022-12-14 16:00:59 +00:00
committed by GitHub
parent 28114338c8
commit 88b6a8e5b3
6 changed files with 262 additions and 2 deletions

View File

@@ -32,7 +32,6 @@ 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
@@ -42,4 +41,7 @@ public interface Categories
List<Category> createSubcategories(String parentCategoryId, List<Category> categories, Parameters parameters);
CollectionWithPagingInfo<Category> getCategoryChildren(String parentCategoryId, Parameters params);
void deleteCategoryById(String id, Parameters params);
}

View File

@@ -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<Category>
public class CategoriesEntityResource implements EntityResourceAction.ReadById<Category>,
EntityResourceAction.Delete
{
private final Categories categories;
@@ -58,4 +59,12 @@ public class CategoriesEntityResource implements EntityResourceAction.ReadById<C
{
return categories.getCategoryById(id, parameters);
}
@WebApiDescription(title = "Delete category",
description = "Delete a category given its node id",
successStatus = HttpServletResponse.SC_NO_CONTENT)
@Override
public void delete(String id, Parameters parameters) {
categories.deleteCategoryById(id, parameters);
}
}

View File

@@ -58,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;
@@ -114,6 +115,23 @@ public class CategoriesImpl implements Categories
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}

View File

@@ -230,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()
{