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))