[Task 69689] added various endpoints for Group management

This commit is contained in:
Raf Ponsaerts
2020-03-17 16:28:30 +01:00
parent ff63e6b464
commit 2f741081d0
15 changed files with 1612 additions and 18 deletions

View File

@@ -17,6 +17,7 @@ import org.dspace.content.WorkspaceItem;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.xmlworkflow.Role;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
/**
@@ -94,5 +95,19 @@ public interface WorkflowService<T extends WorkflowItem> {
public Group getWorkflowRoleGroup(Context context, Collection collection, String roleName, Group roleGroup)
throws SQLException, IOException, WorkflowConfigurationException, AuthorizeException, WorkflowException;
/**
* This method will create the workflowRoleGroup for a collection and the given rolename
* @param context The relevant DSpace context
* @param collection The collection
* @param roleName The rolename
* @return The created Group
* @throws AuthorizeException If something goes wrong
* @throws SQLException If something goes wrong
* @throws IOException If something goes wrong
* @throws WorkflowConfigurationException If something goes wrong
*/
public Group createWorkflowRoleGroup(Context context, Collection collection, String roleName)
throws AuthorizeException, SQLException, IOException, WorkflowConfigurationException;
public List<String> getFlywayMigrationLocations();
}

View File

@@ -53,6 +53,7 @@ import org.dspace.usage.UsageWorkflowEvent;
import org.dspace.workflowbasic.service.BasicWorkflowItemService;
import org.dspace.workflowbasic.service.BasicWorkflowService;
import org.dspace.workflowbasic.service.TaskListItemService;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.springframework.beans.factory.annotation.Autowired;
public class BasicWorkflowServiceImpl implements BasicWorkflowService {
@@ -1216,6 +1217,12 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
return roleGroup;
}
@Override
public Group createWorkflowRoleGroup(Context context, Collection collection, String roleName)
throws AuthorizeException, SQLException, IOException, WorkflowConfigurationException {
return getWorkflowRoleGroup(context, collection, roleName, null);
}
@Override
public List<String> getFlywayMigrationLocations() {
return Collections.emptyList();

View File

@@ -158,22 +158,6 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
Role role = WorkflowUtils.getCollectionAndRepositoryRoles(collection).get(roleName);
if (role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) {
roleGroup = WorkflowUtils.getRoleGroup(context, collection, role);
if (roleGroup == null) {
authorizeService.authorizeAction(context, collection, Constants.WRITE);
roleGroup = groupService.create(context);
if (role.getScope() == Role.Scope.COLLECTION) {
groupService.setName(roleGroup,
"COLLECTION_" + collection.getID().toString()
+ "_WORKFLOW_ROLE_" + roleName);
} else {
groupService.setName(roleGroup, role.getName());
}
groupService.update(context, roleGroup);
authorizeService.addPolicy(context, collection, Constants.ADD, roleGroup);
if (role.getScope() == Role.Scope.COLLECTION) {
WorkflowUtils.createCollectionWorkflowRole(context, collection, roleName, roleGroup);
}
}
}
return roleGroup;
} catch (WorkflowConfigurationException e) {
@@ -181,6 +165,27 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
}
}
public Group createWorkflowRoleGroup(Context context, Collection collection, String roleName)
throws AuthorizeException, SQLException, IOException, WorkflowConfigurationException {
Group roleGroup;
authorizeService.authorizeAction(context, collection, Constants.WRITE);
roleGroup = groupService.create(context);
Role role = WorkflowUtils.getCollectionAndRepositoryRoles(collection).get(roleName);
if (role.getScope() == Role.Scope.COLLECTION) {
groupService.setName(roleGroup,
"COLLECTION_" + collection.getID().toString()
+ "_WORKFLOW_ROLE_" + roleName);
} else {
groupService.setName(roleGroup, role.getName());
}
groupService.update(context, roleGroup);
authorizeService.addPolicy(context, collection, Constants.ADD, roleGroup);
if (role.getScope() == Role.Scope.COLLECTION) {
WorkflowUtils.createCollectionWorkflowRole(context, collection, roleName, roleGroup);
}
return roleGroup;
}
@Override
public List<String> getFlywayMigrationLocations() {
return Collections.singletonList("classpath:org.dspace.storage.rdbms.xmlworkflow");

View File

@@ -130,6 +130,11 @@ public class PoolTaskServiceImpl implements PoolTaskService {
return poolTaskDAO.findByEPerson(context, ePerson);
}
@Override
public List<PoolTask> findByGroup(Context context, Group group) throws SQLException {
return poolTaskDAO.findByGroup(context, group);
}
@Override
public PoolTask create(Context context) throws SQLException, AuthorizeException {
return poolTaskDAO.create(context, new PoolTask());

View File

@@ -14,6 +14,7 @@ import java.util.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.service.DSpaceCRUDService;
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
@@ -41,4 +42,13 @@ public interface PoolTaskService extends DSpaceCRUDService<PoolTask> {
throws SQLException, AuthorizeException;
public List<PoolTask> findByEPerson(Context context, EPerson ePerson) throws SQLException;
/**
* This method will return a list of PoolTask for the given group
* @param context The relevant DSpace context
* @param group The Group to be searched on
* @return The list of PoolTask objects
* @throws SQLException If something goes wrong
*/
public List<PoolTask> findByGroup(Context context, Group group) throws SQLException;
}

View File

@@ -0,0 +1,471 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.model.hateoas.GroupResource;
import org.dspace.app.rest.repository.CollectionRestRepository;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.dspace.workflow.WorkflowService;
import org.dspace.xmlworkflow.WorkflowUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* This RestController will take care of all the calls for a specific collection's admingroup
* This is handled by calling "/api/core/collections/{uuid}/adminGroup" with the correct RequestMethod
*/
@RestController
@RequestMapping("/api/core/collections" + REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID)
public class CollectionGroupRestController {
@Autowired
private CollectionService collectionService;
@Autowired
private CollectionRestRepository collectionRestRepository;
@Autowired
private ConverterService converterService;
@Autowired
private AuthorizeService authorizeService;
@Autowired
private WorkflowService workflowService;
/**
* This method creates and returns an AdminGroup object for the given collection
* This is called by using RequestMethod.POST on the /adminGroup value
* @param uuid The UUID of the collection for which we'll create an adminGroup
* @param response The current response
* @param request The current request
* @return The created AdminGroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
@RequestMapping(method = RequestMethod.POST, value = "/adminGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> postAdminGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to edit the AdminGroup for" +
" collection: " + uuid);
}
if (collection.getAdministrators() != null) {
throw new UnprocessableEntityException("The collection with UUID: " + uuid + " already has " +
"an admin group");
}
GroupRest adminGroup = collectionRestRepository.createAdminGroup(context, request, collection);
context.complete();
GroupResource groupResource = converterService.toResource(adminGroup);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), groupResource);
}
/**
* This method takes care of the deletion of an AdminGroup for the given collection
* This is called by using RequestMethod.DELETE on the /adminGroup value
* @param uuid The UUID of the collection for which we'll delete the AdminGroup
* @param response The current response
* @param request The current request
* @return An empty response if the deletion was successful
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
@RequestMapping(method = RequestMethod.DELETE, value = "/adminGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> deleteAdminGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the AdminGroup for" +
" collection: " + uuid);
}
if (collection.getAdministrators() == null) {
throw new UnprocessableEntityException("The collection with UUID: " + uuid + " doesn't have an admin " +
"group");
}
collectionRestRepository.deleteAdminGroup(context, collection);
context.complete();
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
/**
* This method creates and returns a SubmitterGroup object for the given collection
* This is called by using RequestMethod.POST on the /submittersGroup
* @param uuid The UUID of the collection for which we'll create a submitterGroup
* @param response The current response
* @param request The current request
* @return The created SubmitterGroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
@RequestMapping(method = RequestMethod.POST, value = "/submittersGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> postSubmittersGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to edit the SubmitterGroup for" +
" collection: " + uuid);
}
if (collection.getSubmitters() != null) {
throw new UnprocessableEntityException("The collection with UUID: " + uuid + " already has " +
"a submitter group");
}
GroupRest submitterGroup = collectionRestRepository.createSubmitterGroup(context, request, collection);
context.complete();
GroupResource groupResource = converterService.toResource(submitterGroup);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), groupResource);
}
/**
* This method takes care of the deletion of a SubmitterGroup for the given collection
* This is called by using RequestMethod.DELETE on the default url for this class
* @param uuid The UUID of the collection for which we'll delete the SubmittersGroup
* @param response The current response
* @param request The current request
* @return An empty response if the deletion was successful
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
@RequestMapping(method = RequestMethod.DELETE, value = "/submittersGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> deleteSubmittersGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the SubmitterGroup for" +
" collection: " + uuid);
}
if (collection.getSubmitters() == null) {
throw new UnprocessableEntityException("The collection with UUID: " + uuid + " doesn't have a submitter " +
"group");
}
collectionRestRepository.deleteSubmitterGroup(context, collection);
context.complete();
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
/**
* This method creates and returns a ItemReadGroup object for the given collection
* This is called by using RequestMethod.POST on the /itemReadGroup value
* @param uuid The UUID of the collection for which we'll create a ItemReadGroup
* @param response The current response
* @param request The current request
* @return The created ItemReadGroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
@RequestMapping(method = RequestMethod.POST, value = "/itemReadGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> postItemReadGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to edit the ItemReadGroup for" +
" collection: " + uuid);
}
List<Group> itemGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_ITEM_READ);
if (itemGroups != null && !itemGroups.isEmpty()) {
Group itemReadGroup = itemGroups.get(0);
if (itemReadGroup != null && !StringUtils.equalsIgnoreCase(itemReadGroup.getName(),Group.ANONYMOUS)) {
throw new UnprocessableEntityException("Unable to create a new default read group because either the group already exists or multiple groups are assigned the default privileges.");
}
}
GroupRest itemReadGroup = collectionRestRepository.createItemReadGroup(context, request, collection);
context.complete();
GroupResource groupResource = converterService.toResource(itemReadGroup);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), groupResource);
}
/**
* This method takes care of the deletion of an ItemReadGroup for the given collection
* This is called by using RequestMethod.DELETE on the /itemReadGroup value
* @param uuid The UUID of the collection for which we'll delete the ItemReadGroup
* @param response The current response
* @param request The current request
* @return An empty response if the deletion was successful
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
@RequestMapping(method = RequestMethod.DELETE, value = "/itemReadGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> deleteItemReadGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the ItemReadGroup for" +
" collection: " + uuid);
}
List<Group> itemGroups = authorizeService.getAuthorizedGroups(context, collection, Constants.DEFAULT_ITEM_READ);
if (itemGroups != null && !itemGroups.isEmpty()) {
Group itemReadGroup = itemGroups.get(0);
if (itemReadGroup == null || StringUtils.equalsIgnoreCase(itemReadGroup.getName(), Group.ANONYMOUS)) {
throw new UnprocessableEntityException("Unable to delete the default read group because it's the default");
}
} else {
throw new UnprocessableEntityException("The collection with UUID: " + uuid + " doesn't have " +
"an ItemReadGroup group");
}
collectionRestRepository.deleteItemReadGroup(context, collection);
context.complete();
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
/**
* This method creates and returns a BitstreamReadGroup object for the given collection
* This is called by using RequestMethod.POST on the /bitstreamReadGroup value
* @param uuid The UUID of the collection for which we'll create a BitstreamReadGroup
* @param response The current response
* @param request The current request
* @return The created BitstreamReadGroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
@RequestMapping(method = RequestMethod.POST, value = "/bitstreamReadGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> postBitstreamReadGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to edit the ItemReadGroup for" +
" collection: " + uuid);
}
List<Group> bitstreamGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_BITSTREAM_READ);
if (bitstreamGroups != null && !bitstreamGroups.isEmpty()) {
Group bitstreamGroup = bitstreamGroups.get(0);
if (bitstreamGroup != null && !StringUtils.equalsIgnoreCase(bitstreamGroup.getName(),Group.ANONYMOUS)) {
throw new UnprocessableEntityException("Unable to create a new default read group because either the group already exists or multiple groups are assigned the default privileges.");
}
}
GroupRest bitstreamReadGroup = collectionRestRepository.createBitstreamReadGroup(context, request, collection);
context.complete();
GroupResource groupResource = converterService.toResource(bitstreamReadGroup);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), groupResource);
}
/**
* This method takes care of the deletion of an BitstreamReadGroup for the given collection
* This is called by using RequestMethod.DELETE on the /bitstreamReadGroup value
* @param uuid The UUID of the collection for which we'll delete the bitstreamReadGroup
* @param response The current response
* @param request The current request
* @return An empty response if the deletion was successful
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
@RequestMapping(method = RequestMethod.DELETE, value = "/bitstreamReadGroup")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
public ResponseEntity<ResourceSupport> deleteBitstreamReadGroup(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the BitstreamReadGroup for" +
" collection: " + uuid);
}
List<Group> bitstreamGroups = authorizeService.getAuthorizedGroups(context, collection, Constants.DEFAULT_BITSTREAM_READ);
if (bitstreamGroups != null && !bitstreamGroups.isEmpty()) {
Group bitstreamReadGroup = bitstreamGroups.get(0);
if (bitstreamReadGroup == null || StringUtils.equalsIgnoreCase(bitstreamReadGroup.getName(), Group.ANONYMOUS)) {
throw new UnprocessableEntityException("Unable to delete the default read group because it's the default");
}
} else {
throw new UnprocessableEntityException("The collection with UUID: " + uuid + " doesn't have " +
"an BitstreamReadGroup group");
}
collectionRestRepository.deleteBitstreamReadGroup(context, collection);
context.complete();
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
/**
* This method will retrieve the workflowGroup for a given Collection and workflowRole
* @param uuid The UUID of the collection to retrieve
* @param response The current response
* @param request The current request
* @param workflowRole The given workflowRole
* @return The workflowGroup for the given collection and workflowrole
* @throws Exception If something goes wrong
*/
@RequestMapping(method = RequestMethod.GET, value = "/workflowGroups/{workflowRole}")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'READ')")
public GroupResource getWorkflowGroupForRole(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request, @PathVariable String workflowRole) throws Exception {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
GroupRest groupRest = collectionRestRepository.getWorkflowGroupForRole(context, collection, workflowRole);
return converterService.toResource(groupRest);
}
/**
* This method will create the workflowGroup for a given Collection and workflowRole
* @param uuid The UUID of the collection to retrieve
* @param response The current response
* @param request The current request
* @param workflowRole The given workflowRole
* @return The workflowGroup for the given collection and workflowrole
* @throws Exception If something goes wrong
*/
@RequestMapping(method = RequestMethod.POST, value = "/workflowGroups/{workflowRole}")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'READ')")
public GroupResource postWorkflowGroupForRole(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request, @PathVariable String workflowRole) throws Exception {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
Group group = workflowService.getWorkflowRoleGroup(context, collection, workflowRole, null);
if (group != null) {
throw new UnprocessableEntityException("WorkflowGroup already exists for the role: " + workflowRole +
" in collection with UUID: " + collection.getID());
}
GroupRest groupRest = collectionRestRepository.createWorkflowGroupForRole(context, request, collection, workflowRole);
context.complete();
return converterService.toResource(groupRest);
}
/**
* This method will delete the workflowGroup for a given Collection and workflowRole
* @param uuid The UUID of the collection to retrieve
* @param response The current response
* @param request The current request
* @param workflowRole The given workflowRole
* @return
* @throws Exception If something goes wrong
*/
@RequestMapping(method = RequestMethod.DELETE, value = "/workflowGroups/{workflowRole}")
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'READ')")
public ResponseEntity<ResourceSupport> deleteWorkflowGroupForRole(@PathVariable UUID uuid, HttpServletResponse response,
HttpServletRequest request, @PathVariable String workflowRole) throws Exception {
Context context = ContextUtil.obtainContext(request);
Collection collection = collectionService.find(context, uuid);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + uuid);
}
collectionRestRepository.deleteWorkflowGroupForRole(context, request, collection, workflowRole);
context.complete();
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
}

View File

@@ -30,7 +30,23 @@ import com.fasterxml.jackson.annotation.JsonProperty;
@LinkRest(
name = CollectionRest.PARENT_COMMUNITY,
method = "getParentCommunity"
)
),
@LinkRest(
name = CollectionRest.ADMIN_GROUP,
method = "getAdminGroup"
),
@LinkRest(
name = CollectionRest.SUBMITTERS_GROUP,
method = "getSubmittersGroup"
),
@LinkRest(
name = CollectionRest.ITEM_READ_GROUP,
method = "getItemReadGroup"
),
@LinkRest(
name = CollectionRest.BITSTREAM_READ_GROUP,
method = "getBitstreamReadGroup"
),
})
public class CollectionRest extends DSpaceObjectRest {
public static final String NAME = "collection";
@@ -42,6 +58,11 @@ public class CollectionRest extends DSpaceObjectRest {
public static final String LOGO = "logo";
public static final String MAPPED_ITEMS = "mappedItems";
public static final String PARENT_COMMUNITY = "parentCommunity";
public static final String ADMIN_GROUP = "adminGroup";
public static final String SUBMITTERS_GROUP = "submittersGroup";
public static final String ITEM_READ_GROUP = "itemReadGroup";
public static final String BITSTREAM_READ_GROUP = "bitstreamReadGroup";
@Override
public String getCategory() {

View File

@@ -0,0 +1,83 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* Link repository for "admingroup" subresource of an individual collection.
*
*/
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME + "." + CollectionRest.ADMIN_GROUP)
public class CollectionAdminGroupLinkRepository extends AbstractDSpaceRestRepository implements LinkRestRepository {
@Autowired
private CollectionService collectionService;
@Autowired
private AuthorizeService authorizeService;
/**
* This method is responsible for retrieving the AdminGroup of a Collection
* @param request The current request
* @param collectionId The id of the collection that we'll retrieve the admingroup for
* @param optionalPageable The pageable if applicable
* @param projection The current Projection
* @return The admingroup of the given collection
*/
@PreAuthorize("hasPermission(#collectionId, 'COLLECTION', 'READ')")
public GroupRest getAdminGroup(@Nullable HttpServletRequest request,
UUID collectionId,
@Nullable Pageable optionalPageable,
Projection projection) {
try {
Context context = obtainContext();
Collection collection = collectionService.find(context, collectionId);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + collectionId);
}
Group administrators = collection.getAdministrators();
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the AdminGroup for" +
" collection: " + collectionId);
}
if (administrators == null) {
return null;
}
if (!authorizeService.authorizeActionBoolean(context, administrators, Constants.READ)) {
throw new AccessDeniedException("The current user doesn't have sufficient rights to access the admin" +
"group of collection with id: " + collectionId);
}
return converter.toRest(administrators, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,88 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* Link repository for "BitstreamReadGroup" subresource of an individual collection.
*
*/
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME + "." + CollectionRest.BITSTREAM_READ_GROUP)
public class CollectionBitstreamReadGroupLinkRepository extends AbstractDSpaceRestRepository
implements LinkRestRepository {
@Autowired
private CollectionService collectionService;
@Autowired
private AuthorizeService authorizeService;
/**
* This method is responsible for retrieving the BitstreamReadGroup of a Collection
* @param request The current request
* @param collectionId The id of the collection that we'll retrieve the BitstreamReadGroup for
* @param optionalPageable The pageable if applicable
* @param projection The current Projection
* @return The BitstreamReadGroup of the given collection
*/
@PreAuthorize("hasPermission(#collectionId, 'COLLECTION', 'READ')")
public GroupRest getBitstreamReadGroup(@Nullable HttpServletRequest request,
UUID collectionId,
@Nullable Pageable optionalPageable,
Projection projection) {
try {
Context context = obtainContext();
Collection collection = collectionService.find(context, collectionId);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + collectionId);
}
List<Group> bitstreamGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_BITSTREAM_READ);
Group bitstreamReadGroup = bitstreamGroups.get(0);
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException(
"The current user was not allowed to retrieve the bitstreamReadGroup for" +
" collection: " + collectionId);
}
if (bitstreamReadGroup == null) {
return null;
}
if (!authorizeService.authorizeActionBoolean(context, bitstreamReadGroup, Constants.READ)) {
throw new AccessDeniedException(
"The current user doesn't have sufficient rights to access the bitstreamReadGroup" +
"group of collection with id: " + collectionId);
}
return converter.toRest(bitstreamReadGroup, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,89 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* Link repository for "ItemReadGroup" subresource of an individual collection.
*
*/
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME + "." + CollectionRest.ITEM_READ_GROUP)
public class CollectionItemReadGroupLinkRepository extends AbstractDSpaceRestRepository implements LinkRestRepository {
@Autowired
private CollectionService collectionService;
@Autowired
private AuthorizeService authorizeService;
/**
* This method is responsible for retrieving the ItemReadGroup of a Collection
* @param request The current request
* @param collectionId The id of the collection that we'll retrieve the ItemReadGroup for
* @param optionalPageable The pageable if applicable
* @param projection The current Projection
* @return The ItemReadGroup of the given collection
*/
@PreAuthorize("hasPermission(#collectionId, 'COLLECTION', 'READ')")
public GroupRest getItemReadGroup(@Nullable HttpServletRequest request,
UUID collectionId,
@Nullable Pageable optionalPageable,
Projection projection) {
try {
Context context = obtainContext();
Collection collection = collectionService.find(context, collectionId);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + collectionId);
}
List<Group> itemGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_ITEM_READ);
if (itemGroups == null || itemGroups.isEmpty()) {
return null;
}
Group itemReadGroup = itemGroups.get(0);
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the itemReadGroup for" +
" collection: " + collectionId);
}
if (itemReadGroup == null) {
return null;
}
if (!authorizeService.authorizeActionBoolean(context, itemReadGroup, Constants.READ)) {
throw new AccessDeniedException(
"The current user doesn't have sufficient rights to access the itemReadGroup" +
"group of collection with id: " + collectionId);
}
return converter.toRest(itemReadGroup, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -10,12 +10,15 @@ package org.dspace.app.rest.repository;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.SortedMap;
import java.util.UUID;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
@@ -24,11 +27,15 @@ import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.CommunityRest;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.model.MetadataRest;
import org.dspace.app.rest.model.MetadataValueRest;
import org.dspace.app.rest.model.TemplateItemRest;
import org.dspace.app.rest.model.patch.Patch;
import org.dspace.app.rest.model.wrapper.TemplateItem;
import org.dspace.app.rest.utils.CollectionRestEqualityUtils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Bitstream;
import org.dspace.content.Collection;
import org.dspace.content.Community;
@@ -39,6 +46,16 @@ import org.dspace.content.service.CommunityService;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.RequestService;
import org.dspace.workflow.WorkflowException;
import org.dspace.workflow.WorkflowService;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.dspace.xmlworkflow.WorkflowUtils;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.service.CollectionRoleService;
import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@@ -56,6 +73,8 @@ import org.springframework.web.multipart.MultipartFile;
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME)
public class CollectionRestRepository extends DSpaceObjectRestRepository<Collection, CollectionRest> {
public static Logger log = org.apache.logging.log4j.LogManager.getLogger(CollectionRestRepository.class);
@Autowired
CommunityService communityService;
@@ -71,6 +90,21 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
@Autowired
private ItemService itemService;
@Autowired
private GroupService groupService;
@Autowired
private AuthorizeService authorizeService;
@Autowired
private WorkflowService workflowService;
@Autowired
private PoolTaskService poolTaskService;
@Autowired
private CollectionRoleService collectionRoleService;
public CollectionRestRepository(CollectionService dsoService) {
super(dsoService);
}
@@ -300,4 +334,264 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
throw new UnprocessableEntityException("The item with id " + item.getID() + " is not a template item");
}
}
/**
* This method will create an AdminGroup for the given Collection with the given Information through JSON
* @param context The current context
* @param request The current request
* @param collection The collection for which we'll create an admingroup
* @return The created AdminGroup's REST object
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
public GroupRest createAdminGroup(Context context, HttpServletRequest request, Collection collection)
throws SQLException, AuthorizeException {
Group group = cs.createAdministrators(context, collection);
return populateGroupInformation(context, request, group);
}
/**
* This method will delete the AdminGroup for the given Collection
* @param context The current context
* @param collection The community for which we'll delete the admingroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
public void deleteAdminGroup(Context context, Collection collection)
throws SQLException, AuthorizeException, IOException {
Group adminGroup = collection.getAdministrators();
cs.removeAdministrators(context, collection);
groupService.delete(context, adminGroup);
}
/**
* This method will create a SubmitterGroup for the given Collection with the given Information through JSON
* @param context The current context
* @param request The current request
* @param collection The collection for which we'll create a submittergroup
* @return The created SubmitterGroup's REST object
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
public GroupRest createSubmitterGroup(Context context, HttpServletRequest request, Collection collection)
throws SQLException, AuthorizeException {
Group group = cs.createSubmitters(context, collection);
return populateGroupInformation(context, request, group);
}
/**
* This method will delete the SubmitterGroup for the given Collection
* @param context The current context
* @param collection The community for which we'll delete the submittergroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
public void deleteSubmitterGroup(Context context, Collection collection)
throws SQLException, AuthorizeException, IOException {
Group submitters = collection.getSubmitters();
cs.removeSubmitters(context, collection);
groupService.delete(context, submitters);
}
/**
* This method will create an ItemReadGroup for the given Collection with the given Information through JSON
* @param context The current context
* @param request The current request
* @param collection The collection for which we'll create an ItemReadGroup
* @return The created ItemReadGroup's REST object
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
public GroupRest createItemReadGroup(Context context, HttpServletRequest request, Collection collection)
throws SQLException, AuthorizeException {
Group role = groupService.create(context);
groupService.setName(role, "COLLECTION_" + collection.getID().toString() + "_ITEM_DEFAULT_READ");
// Remove existing privileges from the anonymous group.
authorizeService.removePoliciesActionFilter(context, collection, Constants.DEFAULT_ITEM_READ);
// Grant our new role the default privileges.
authorizeService.addPolicy(context, collection, Constants.DEFAULT_ITEM_READ, role);
// Commit the changes
groupService.update(context, role);
return populateGroupInformation(context, request, role);
}
/**
* This method will delete the ItemReadGroup for the given Collection
* @param context The current context
* @param collection The community for which we'll delete the ItemReadGroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
public void deleteItemReadGroup(Context context, Collection collection)
throws SQLException, AuthorizeException, IOException {
List<Group> itemGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_ITEM_READ);
Group itemReadGroup = itemGroups.get(0);
groupService.delete(context, itemReadGroup);
authorizeService.addPolicy(context, collection, Constants.DEFAULT_ITEM_READ,
groupService.findByName(context, Group.ANONYMOUS));
}
/**
* This method will create an BitstreamReadGroup for the given Collection with the given Information through JSON
* @param context The current context
* @param request The current request
* @param collection The collection for which we'll create an BitstreamReadGroup
* @return The created BitstreamReadGroup's REST object
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
*/
public GroupRest createBitstreamReadGroup(Context context, HttpServletRequest request, Collection collection)
throws SQLException, AuthorizeException {
Group role = groupService.create(context);
groupService.setName(role, "COLLECTION_" + collection.getID().toString() + "_BITSTREAM_DEFAULT_READ");
// Remove existing privileges from the anonymous group.
authorizeService.removePoliciesActionFilter(context, collection, Constants.DEFAULT_BITSTREAM_READ);
// Grant our new role the default privileges.
authorizeService.addPolicy(context, collection, Constants.DEFAULT_BITSTREAM_READ, role);
// Commit the changes
groupService.update(context, role);
return populateGroupInformation(context, request, role);
}
/**
* This method will delete the BitstreamReadGroup for the given Collection
* @param context The current context
* @param collection The community for which we'll delete the BitstreamReadGroup
* @throws SQLException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws IOException If something goes wrong
*/
public void deleteBitstreamReadGroup(Context context, Collection collection)
throws SQLException, AuthorizeException, IOException {
List<Group> itemGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_BITSTREAM_READ);
Group itemReadGroup = itemGroups.get(0);
groupService.delete(context, itemReadGroup);
authorizeService.addPolicy(context, collection, Constants.DEFAULT_BITSTREAM_READ,
groupService.findByName(context, Group.ANONYMOUS));
}
private GroupRest populateGroupInformation(Context context, HttpServletRequest request, Group group)
throws SQLException, AuthorizeException {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
try {
ServletInputStream input = request.getInputStream();
groupRest = mapper.readValue(input, GroupRest.class);
if (groupRest.isPermanent() || StringUtils.isNotBlank(groupRest.getName())) {
throw new UnprocessableEntityException("The given GroupRest object has to be non-permanent and can't" +
" contain a name");
}
MetadataRest metadata = groupRest.getMetadata();
SortedMap<String, List<MetadataValueRest>> map = metadata.getMap();
if (map != null) {
List<MetadataValueRest> dcTitleMetadata = map.get("dc.title");
if (dcTitleMetadata != null) {
if (!dcTitleMetadata.isEmpty()) {
throw new UnprocessableEntityException("The given GroupRest can't contain a dc.title mdv");
}
}
}
metadataConverter.setMetadata(context, group, metadata);
} catch (IOException e1) {
throw new UnprocessableEntityException("Error parsing request body.", e1);
}
return converter.toRest(group, utils.obtainProjection());
}
/**
* This method will retrieve the GroupRest object for the workflowGroup for the given Collection and workflowRole
* @param context The relevant DSpace context
* @param collection The given collection
* @param workflowRole The given workflowRole
* @return The GroupRest for the WorkflowGroup for the given Collection and workflowRole
* @throws SQLException If something goes wrong
* @throws IOException If something goes wrong
* @throws WorkflowConfigurationException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws WorkflowException If something goes wrong
*/
public GroupRest getWorkflowGroupForRole(Context context, Collection collection, String workflowRole)
throws SQLException, IOException, WorkflowConfigurationException, AuthorizeException, WorkflowException {
if (WorkflowUtils.getCollectionAndRepositoryRoles(collection).get(workflowRole) == null) {
throw new ResourceNotFoundException("Couldn't find role for: " + workflowRole +
" in the collection with UUID: " + collection.getID());
}
Group group = workflowService.getWorkflowRoleGroup(context, collection, workflowRole, null);
if (group == null) {
throw new ResourceNotFoundException("The requested Group was not found");
}
return converter.toRest(group, utils.obtainProjection());
}
/**
* This method will create the WorkflowGroup for the given Collection and workflowRole
* @param context The relevant DSpace context
* @param request The current request
* @param collection The given collection
* @param workflowRole The given workflowRole
* @return The created WorkflowGroup for the given Collection and workflowRole
* @throws SQLException If something goes wrong
* @throws WorkflowConfigurationException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws WorkflowException If something goes wrong
* @throws IOException If something goes wrong
*/
public GroupRest createWorkflowGroupForRole(Context context, HttpServletRequest request, Collection collection, String workflowRole)
throws SQLException, WorkflowConfigurationException, AuthorizeException, WorkflowException, IOException {
Group group = workflowService.createWorkflowRoleGroup(context, collection, workflowRole);
populateGroupInformation(context, request, group);
return converter.toRest(group, utils.obtainProjection());
}
/**
* This method will delete the WorkflowGroup for a given Collection and workflowRole
* @param context The relevant DSpace context
* @param request The current DSpace request
* @param collection The given Collection
* @param workflowRole The given WorkflowRole
* @throws SQLException If something goes wrong
* @throws WorkflowConfigurationException If something goes wrong
* @throws AuthorizeException If something goes wrong
* @throws WorkflowException If something goes wrong
* @throws IOException If something goes wrong
*/
public void deleteWorkflowGroupForRole(Context context, HttpServletRequest request, Collection collection, String workflowRole)
throws SQLException, WorkflowConfigurationException, AuthorizeException, WorkflowException, IOException {
Group group = workflowService.getWorkflowRoleGroup(context, collection, workflowRole, null);
if (!poolTaskService.findByGroup(context, group).isEmpty()) {
throw new UnprocessableEntityException("The Group that was attempted to be deleted still has Pooltasks open");
}
if (group == null) {
throw new ResourceNotFoundException("The requested Group was not found");
}
List<CollectionRole> collectionRoles = collectionRoleService.findByGroup(context, group);
if (!collectionRoles.isEmpty()) {
collectionRoles.stream().forEach(collectionRole -> {
try {
collectionRoleService.delete(context, collectionRole);
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
});
}
groupService.delete(context, group);
}
}

View File

@@ -0,0 +1,83 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* Link repository for "submittergroup" subresource of an individual collection.
*
*/
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME + "." + CollectionRest.SUBMITTERS_GROUP)
public class CollectionSubmitterGroupLinkRepository extends AbstractDSpaceRestRepository implements LinkRestRepository {
@Autowired
private CollectionService collectionService;
@Autowired
private AuthorizeService authorizeService;
/**
* This method is responsible for retrieving the Submittergroup of a Collection
* @param request The current request
* @param collectionId The id of the collection that we'll retrieve the submitterGroup for
* @param optionalPageable The pageable if applicable
* @param projection The current Projection
* @return The submitterGroup of the given collection
*/
@PreAuthorize("hasPermission(#collectionId, 'COLLECTION', 'READ')")
public GroupRest getSubmittersGroup(@Nullable HttpServletRequest request,
UUID collectionId,
@Nullable Pageable optionalPageable,
Projection projection) {
try {
Context context = obtainContext();
Collection collection = collectionService.find(context, collectionId);
if (collection == null) {
throw new ResourceNotFoundException("No such collection: " + collectionId);
}
Group submitters = collection.getSubmitters();
if (!authorizeService.isAdmin(context) && !authorizeService.authorizeActionBoolean(context, collection,
Constants.ADMIN, true)) {
throw new AccessDeniedException("The current user was not allowed to retrieve the submitterGroup for" +
" collection: " + collectionId);
}
if (submitters == null) {
return null;
}
if (!authorizeService.authorizeActionBoolean(context, submitters, Constants.READ)) {
throw new AccessDeniedException("The current user doesn't have sufficient rights to access the submitter" +
"group of collection with id: " + collectionId);
}
return converter.toRest(submitters, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,415 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static com.jayway.jsonpath.JsonPath.read;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.builder.CollectionBuilder;
import org.dspace.app.rest.builder.CommunityBuilder;
import org.dspace.app.rest.matcher.GroupMatcher;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.model.MetadataRest;
import org.dspace.app.rest.model.MetadataValueRest;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class CollectionGroupRestControllerIT extends AbstractControllerIntegrationTest {
@Autowired
private CollectionService collectionService;
@Autowired
private GroupService groupService;
@Autowired
private AuthorizeService authorizeService;
Collection collection;
@Before
public void setup() {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context).withName("test").build();
collection = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build();
}
@Test
public void getCollectionAdminGroupTest() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", GroupMatcher.matchGroupEntry(adminGroup.getID(), adminGroup.getName())));
}
@Test
public void getCollectionAdminGroupTestParentCommunityAdmin() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", GroupMatcher.matchGroupEntry(adminGroup.getID(), adminGroup.getName())));
}
@Test
public void getCollectionAdminGroupTestCollectionAdmin() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", GroupMatcher.matchGroupEntry(adminGroup.getID(), adminGroup.getName())));
}
@Test
public void getCollectionAdminGroupUnAuthorizedTest() throws Exception {
collectionService.createAdministrators(context, collection);
getClient().perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isUnauthorized());
}
@Test
public void getCollectionAdminGroupForbiddenTest() throws Exception {
collectionService.createAdministrators(context, collection);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isForbidden());
}
@Test
public void getCollectionAdminGroupNoContentTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
}
@Test
public void getCollectionAdminGroupWrongCollectionUuidResourceNotFoundTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + UUID.randomUUID() + "/adminGroup"))
.andExpect(status().isNotFound());
}
@Test
public void postCollectionAdminGroupCreateAdminGroupSuccess() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isCreated())
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID()))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", GroupMatcher.matchGroupEntry(adminGroup.getID(), adminGroup.getName())));
}
@Test
public void postCollectionAdminGroupCreateAdminGroupDcTitleUnprocessable() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
metadataRest.put("dc.title", new MetadataValueRest("testTitle"));
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isUnprocessableEntity());
}
@Test
public void postCollectionAdminGroupCreateAdminGroupSuccessParentCommunityAdmin() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isCreated())
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID()))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", GroupMatcher.matchGroupEntry(adminGroup.getID(), adminGroup.getName())));
}
@Test
public void postCollectionAdminGroupCreateAdminGroupSuccessCollectionAdmin() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isCreated())
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID()))
.andExpect(status().isOk())
.andExpect(
jsonPath("$", GroupMatcher.matchGroupEntry(adminGroup.getID(), adminGroup.getName())));
}
@Test
public void postCollectionAdminGroupCreateAdminGroupUnAuthorized() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
getClient().perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isUnauthorized());
}
@Test
public void postCollectionAdminGroupCreateAdminGroupForbidden() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isForbidden());
}
@Test
public void postCollectionAdminGroupCreateAdminGroupNotFound() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + UUID.randomUUID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isNotFound());
}
@Test
public void postCollectionAdminGroupCreateAdminGroupUnProcessableName() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
groupRest.setName("Fail");
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isUnprocessableEntity());
}
@Test
public void postCollectionAdminGroupCreateAdminGroupUnProcessablePermanent() throws Exception {
ObjectMapper mapper = new ObjectMapper();
GroupRest groupRest = new GroupRest();
groupRest.setPermanent(true);
MetadataRest metadataRest = new MetadataRest();
metadataRest.put("dc.description", new MetadataValueRest("testingDescription"));
metadataRest.put("dc.subject", new MetadataValueRest("testSubject"));
groupRest.setMetadata(metadataRest);
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/adminGroup")
.content(mapper.writeValueAsBytes(groupRest))
.contentType(contentType))
.andExpect(status().isUnprocessableEntity());
}
@Test
public void deleteCollectionAdminGroupTest() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
}
// This is currently not supported in DSpace API
@Ignore
@Test
public void deleteCollectionAdminGroupTestParentCommunityAdmin() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
}
// This is currently not supported in DSpace API
@Ignore
@Test
public void deleteCollectionAdminGroupTestCollectionAdmin() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, collection, Constants.ADMIN, eperson);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isNoContent());
}
@Test
public void deleteCollectionAdminGroupUnAuthorizedTest() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
getClient().perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isUnauthorized());
}
@Test
public void deleteCollectionAdminGroupForbiddenTest() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(delete("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isForbidden());
}
@Test
public void deleteCollectionAdminGroupNotFoundTest() throws Exception {
Group adminGroup = collectionService.createAdministrators(context, collection);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(delete("/api/core/collections/" + UUID.randomUUID() + "/adminGroup"))
.andExpect(status().isNotFound());
}
}

View File

@@ -155,6 +155,12 @@ public class CollectionBuilder extends AbstractDSpaceObjectBuilder<Collection> {
@Override
public void cleanup() throws Exception {
context.turnOffAuthorisationSystem();
if (collection.getAdministrators() != null) {
Group adminGroup = collection.getAdministrators();
collectionService.removeAdministrators(context, collection);
groupService.delete(context, adminGroup);
}
deleteWorkflowGroups(collection);
delete(collection);
}

View File

@@ -84,7 +84,9 @@ public class CollectionMatcher {
"logo",
"mappedItems",
"parentCommunity",
"self"
"self",
"adminGroup"
);
}