diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml index 0c4cd9b243..678ecdbbe3 100644 --- a/config/alfresco/public-rest-context.xml +++ b/config/alfresco/public-rest-context.xml @@ -148,6 +148,7 @@ + diff --git a/source/java/org/alfresco/rest/api/Groups.java b/source/java/org/alfresco/rest/api/Groups.java index 509492b465..097f821725 100644 --- a/source/java/org/alfresco/rest/api/Groups.java +++ b/source/java/org/alfresco/rest/api/Groups.java @@ -43,6 +43,7 @@ public interface Groups String PARAM_INCLUDE_PARENT_IDS = "parentIds"; String PARAM_INCLUDE_ZONES = "zones"; String PARAM_IS_ROOT = "isRoot"; + String PARAM_CASCADE = "cascade"; String PARAM_MEMBER_TYPE = "memberType"; String PARAM_MEMBER_TYPE_GROUP = "GROUP"; String PARAM_MEMBER_TYPE_PERSON = "PERSON"; @@ -107,6 +108,18 @@ public interface Groups */ CollectionWithPagingInfo getGroupsByPersonId(String personId, Parameters parameters); + /** + * Delete the given group. + * + * @param groupId + * the group ID + * @param parameters + * the {@link Parameters} object to get the parameters passed + * into the request including: - include param (parentIds, zones) + * @return Updated group + */ + void delete(String groupId, Parameters parameters); + /** * Gets a list of groups. * diff --git a/source/java/org/alfresco/rest/api/groups/GroupsEntityResource.java b/source/java/org/alfresco/rest/api/groups/GroupsEntityResource.java index 8ca41f0278..93cf94052e 100644 --- a/source/java/org/alfresco/rest/api/groups/GroupsEntityResource.java +++ b/source/java/org/alfresco/rest/api/groups/GroupsEntityResource.java @@ -47,8 +47,8 @@ import java.util.List; * @author cturlica */ @EntityResource(name = "groups", title = "Groups") -public class GroupsEntityResource - implements EntityResourceAction.Read, EntityResourceAction.ReadById, EntityResourceAction.Create, EntityResourceAction.Update, InitializingBean +public class GroupsEntityResource implements EntityResourceAction.Read, EntityResourceAction.ReadById, EntityResourceAction.Create, + EntityResourceAction.Update, EntityResourceAction.Delete, InitializingBean { private Groups groups; @@ -94,4 +94,11 @@ public class GroupsEntityResource { return groups.update(groupId, group, parameters); } + + @Override + @WebApiDescription(title = "Delete group", description = "Delete group") + public void delete(String groupId, Parameters parameters) + { + groups.delete(groupId, parameters); + } } \ No newline at end of file diff --git a/source/java/org/alfresco/rest/api/impl/GroupsImpl.java b/source/java/org/alfresco/rest/api/impl/GroupsImpl.java index 17df838d34..fec271aaae 100644 --- a/source/java/org/alfresco/rest/api/impl/GroupsImpl.java +++ b/source/java/org/alfresco/rest/api/impl/GroupsImpl.java @@ -30,6 +30,7 @@ import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; import org.alfresco.repo.security.authority.AuthorityDAO; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authority.AuthorityException; import org.alfresco.repo.security.authority.AuthorityInfo; import org.alfresco.repo.security.authority.UnknownAuthorityException; import org.alfresco.rest.antlr.WhereClauseParser; @@ -138,7 +139,7 @@ public class GroupsImpl implements Groups public Group update(String groupId, Group group, Parameters parameters) { - validateGroupId(groupId); + validateGroupId(groupId, false); validateGroup(group, true); authorityService.setAuthorityDisplayName(groupId, group.getDisplayName()); @@ -525,9 +526,31 @@ public class GroupsImpl implements Groups } } + public void delete(String groupId, Parameters parameters) + { + // Get cascade param - default false (if not provided). + boolean cascade = Boolean.valueOf(parameters.getParameter(PARAM_CASCADE)); + + try + { + authorityService.deleteAuthority(groupId, cascade); + } + catch (AuthorityException ae) + { + if (ae.getMsgId().equals("Trying to modify a fixed authority")) + { + throw new ConstraintViolatedException("Trying to modify a fixed authority"); + } + else + { + throw ae; + } + } + } + public CollectionWithPagingInfo getGroupMembers(String groupId, final Parameters parameters) { - validateGroupId(groupId); + validateGroupId(groupId, false); Paging paging = parameters.getPaging(); @@ -646,14 +669,14 @@ public class GroupsImpl implements Groups return groupMember; } - private void validateGroupId(String groupId) + private void validateGroupId(String groupId, boolean inferPrefix) { if (groupId == null || groupId.isEmpty()) { throw new InvalidArgumentException("groupId is null or empty"); } - if (!groupAuthorityExists(groupId)) + if (!groupAuthorityExists(groupId, inferPrefix)) { throw new EntityNotFoundException(groupId); } @@ -702,14 +725,19 @@ public class GroupsImpl implements Groups } } - private boolean groupAuthorityExists(String shortName) + private boolean groupAuthorityExists(String authorityName) { - return authorityExists(AuthorityType.GROUP, shortName); + return groupAuthorityExists(authorityName, true); } - private boolean authorityExists(AuthorityType authorityType, String shortName) + private boolean groupAuthorityExists(String authorityName, boolean inferPrefix) { - String name = authorityService.getName(authorityType, shortName); + return authorityExists(AuthorityType.GROUP, authorityName, inferPrefix); + } + + private boolean authorityExists(AuthorityType authorityType, String authorityName, boolean inferPrefix) + { + String name = inferPrefix ? authorityService.getName(authorityType, authorityName) : authorityName; return (name != null && authorityService.authorityExists(name)); } diff --git a/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java b/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java index dd20670b85..b59b02dbaa 100644 --- a/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/GroupsTest.java @@ -890,6 +890,22 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest groupsProxy.createGroup(group, null, HttpServletResponse.SC_CREATED); groupsProxy.createGroup(group, null, HttpServletResponse.SC_CONFLICT); } + + // Create subgroup with invalid parent. + { + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + + Map otherParams = new HashMap<>(); + otherParams.put("include", org.alfresco.rest.api.Groups.PARAM_INCLUDE_PARENT_IDS); + + Set subGroupParents = new HashSet<>(); + subGroupParents.add("invalidId"); + + Group subGroup = generateGroup(); + subGroup.setParentIds(subGroupParents); + + groupsProxy.createGroup(subGroup, otherParams, HttpServletResponse.SC_NOT_FOUND); + } } @Test @@ -959,6 +975,70 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest } } + @Test + public void testDeleteGroup() throws Exception + { + final Groups groupsProxy = publicApiClient.groups(); + + Map otherParams = new HashMap<>(); + otherParams.put("include", org.alfresco.rest.api.Groups.PARAM_INCLUDE_PARENT_IDS); + + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + + Group group = groupsProxy.createGroup(generateGroup(), otherParams, HttpServletResponse.SC_CREATED); + + // User without admin rights can't delete a group. + { + setRequestContext(user1); + + groupsProxy.deleteGroup(group.getId(), false, HttpServletResponse.SC_FORBIDDEN); + } + + // Invalid auth. + { + setRequestContext(networkOne.getId(), GUID.generate(), "password"); + groupsProxy.deleteGroup("invalidId", false, HttpServletResponse.SC_UNAUTHORIZED); + } + + // Group id doesn't exist. + { + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + + groupsProxy.deleteGroup("GROUP_invalidId", false, HttpServletResponse.SC_NOT_FOUND); + } + + // Trying to modify a fixed authority. + { + setRequestContext(networkOne.getId(), networkAdmin, DEFAULT_ADMIN_PWD); + + groupsProxy.deleteGroup("admin", false, HttpServletResponse.SC_CONFLICT); + } + + { + Group groupLevel1 = groupsProxy.createGroup(generateGroup(), otherParams, HttpServletResponse.SC_CREATED); + Group groupLevel2 = groupsProxy.createGroup(generateSubGroup(groupLevel1), otherParams, HttpServletResponse.SC_CREATED); + Group groupLevel3 = groupsProxy.createGroup(generateSubGroup(groupLevel2), otherParams, HttpServletResponse.SC_CREATED); + + // Delete the primary root (no cascade) + groupsProxy.deleteGroup(groupLevel1.getId(), false, HttpServletResponse.SC_NO_CONTENT); + groupsProxy.getGroup(groupLevel1.getId(), HttpServletResponse.SC_NOT_FOUND); + + // Check that second level group is now root. + groupLevel2 = groupsProxy.getGroup(groupLevel2.getId(), HttpServletResponse.SC_OK); + assertTrue(groupLevel2.getIsRoot()); + + // Check that third level group wasn't deleted. + groupsProxy.getGroup(groupLevel3.getId(), HttpServletResponse.SC_OK); + + // Delete new root with cascade. + groupsProxy.deleteGroup(groupLevel2.getId(), true, HttpServletResponse.SC_NO_CONTENT); + + // Check that delete with cascade worked. + groupsProxy.getGroup(groupLevel2.getId(), HttpServletResponse.SC_NOT_FOUND); + groupsProxy.getGroup(groupLevel2.getId(), HttpServletResponse.SC_NOT_FOUND); + } + } + private Group generateGroup() { Group group = new Group(); @@ -966,4 +1046,20 @@ public class GroupsTest extends AbstractSingleNetworkSiteTest return group; } + + private Group generateSubGroup(Group parentGroup) + { + + Set subGroupParents = new HashSet<>(); + if (parentGroup.getParentIds() != null && !parentGroup.getParentIds().isEmpty()) + { + subGroupParents.addAll(parentGroup.getParentIds()); + } + subGroupParents.add(parentGroup.getId()); + + Group subGroup = generateGroup(); + subGroup.setParentIds(subGroupParents); + + return subGroup; + } } diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java index 9fa2e1b57b..475adc0d83 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java @@ -2311,6 +2311,16 @@ public class PublicApiClient return parseGroupEntity(response); } + public void deleteGroup(String groupId, boolean cascade, int expectedStatus) throws PublicApiException + { + Map params = null; + if (cascade) + { + params = Collections.singletonMap("cascade", "true"); + } + remove("groups", groupId, null, null, params, "Failed to remove site", expectedStatus); + } + private Group parseGroupEntity(HttpResponse response) { if ((response != null) && (response.getJsonResponse() != null))