diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionController.java index 775a08e496c3..6f91bf7c17f5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionController.java @@ -24,7 +24,10 @@ import org.dspace.app.rest.model.WorkspaceItemRest; import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.AuthorizeService; +import org.dspace.authorize.service.ResourcePolicyService; +import org.dspace.content.Collection; import org.dspace.content.WorkspaceItem; import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.Constants; @@ -32,6 +35,8 @@ import org.dspace.core.Email; import org.dspace.core.I18nUtil; import org.dspace.eperson.EPerson; +import org.dspace.eperson.Group; +import org.dspace.eperson.service.GroupService; import org.dspace.services.ConfigurationService; import org.dspace.web.ContextUtil; import org.springframework.beans.factory.annotation.Autowired; @@ -68,6 +73,12 @@ public class SubmissionController { @Autowired AuthorizeService authorizeService; + @Autowired + GroupService groupService; + + @Autowired + ResourcePolicyService resourcePolicyService; + @Lazy @Autowired protected ConverterService converter; @@ -145,12 +156,6 @@ public WorkspaceItemRest setOwner(@RequestParam(name = "shareToken") String shar // Check the wsi does exist validateWorkspaceItem(wsi, null, shareToken); - if (!authorizeService.authorizeActionBoolean(context, wsi.getItem(), Constants.READ)) { - String errorMessage = "The current user does not have rights to view the WorkflowItem"; - log.error(errorMessage); - throw new AccessDeniedException(errorMessage); - } - // Set the owner of the workspace item to the current user EPerson currentUser = context.getCurrentUser(); // If the current user is null, throw an exception @@ -160,6 +165,25 @@ public WorkspaceItemRest setOwner(@RequestParam(name = "shareToken") String shar throw new DSpaceBadRequestException(errorMessage); } + Collection collection = wsi.getCollection(); + Group submittersGroup = collection.getSubmitters(); + boolean isSubmitterGroupMember = submittersGroup != null && + groupService.isMember(context, currentUser, submittersGroup); + boolean canRead = authorizeService.authorizeActionBoolean(context, wsi.getItem(), Constants.READ); + if (!canRead && !isSubmitterGroupMember) { + String errorMessage = "The current user does not have rights to view or claim the WorkspaceItem"; + log.error(errorMessage); + throw new AccessDeniedException(errorMessage); + } + + List resourcePolicies = resourcePolicyService.find(context, + wsi.getItem(), ResourcePolicy.TYPE_SUBMISSION); + // Set submitter + for (ResourcePolicy resourcePolicy: resourcePolicies) { + resourcePolicy.setEPerson(currentUser); + resourcePolicyService.update(context, resourcePolicy); + } + wsi.getItem().setSubmitter(currentUser); workspaceItemService.update(context, wsi); WorkspaceItemRest wsiRest = converter.toRest(wsi, utils.obtainProjection()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java index 2bafd26516aa..a9c7b5ecd568 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java @@ -70,6 +70,8 @@ import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.EPersonServiceImpl; +import org.dspace.eperson.Group; +import org.dspace.eperson.service.GroupService; import org.dspace.event.Event; import org.dspace.importer.external.datamodel.ImportRecord; import org.dspace.importer.external.exception.FileMultipleOccurencesException; @@ -150,6 +152,9 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository findByShareToken(@Parameter(value = SHARE_TOKEN, log.error(errorMessage); throw new DSpaceBadRequestException(errorMessage); } - if (!authorizeService.authorizeActionBoolean(context, witems.get(0).getItem(), Constants.READ)) { + // One token can be used to share only one item + Collection collection = witems.get(0).getCollection(); + Group submittersGroup = collection.getSubmitters(); + boolean isSubmitterGroupMember = submittersGroup != null && + groupService.isMember(context, context.getCurrentUser(), submittersGroup); + boolean canRead = authorizeService.authorizeActionBoolean(context, witems.get(0).getItem(), Constants.READ); + if (!canRead && !isSubmitterGroupMember) { String errorMessage = "The current user does not have rights to view the WorkflowItem"; log.error(errorMessage); throw new AccessDeniedException(errorMessage); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionControllerIT.java index 957f275220e1..ff7be5916a8c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionControllerIT.java @@ -23,12 +23,15 @@ import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; +import org.dspace.builder.GroupBuilder; import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.WorkspaceItem; import org.dspace.content.service.WorkspaceItemService; import org.dspace.eperson.EPerson; +import org.dspace.eperson.Group; import org.dspace.eperson.service.EPersonService; +import org.dspace.eperson.service.GroupService; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -45,6 +48,8 @@ public class SubmissionControllerIT extends AbstractControllerIntegrationTest { private WorkspaceItemService workspaceItemService; @Autowired private EPersonService ePersonService; + @Autowired + private GroupService groupService; WorkspaceItem wsi; @@ -113,4 +118,70 @@ public void generateShareTokenAndSetOwnerTest() throws Exception { assertThat(updatedWsi.getSubmitter().getEmail(), is(adminUser.getEmail())); assertThat(updatedWsi.getSubmitter().getEmail(), not(SUBMITTER_EMAIL)); } + + @Test + public void generateShareTokenAndSetOwnerTo3rdPersonTest() throws Exception { + context.turnOffAuthorisationSystem(); + EPerson submitter2 = EPersonBuilder.createEPerson(context) + .withEmail("user@test.edu") + .withPassword(password) + .build(); + Group group = GroupBuilder.createCollectionSubmitterGroup(context, wsi.getCollection()) + .withName("Test Submitters Group").build(); + groupService.addMember(context, group, submitter2); + context.restoreAuthSystemState(); + + EPerson currentUser = context.getCurrentUser(); + + String adminToken = getAuthToken(admin.getEmail(), password); + getClient(adminToken).perform(get("/api/submission/share") + .param("workspaceitemid", wsi.getID().toString()) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.shareLink", is(notNullValue()))); + + // Check that the share token was set on the WorkspaceItem and persisted into the database + WorkspaceItem updatedWsi = workspaceItemService.find(context, wsi.getID()); + assertThat(wsi.getID(), is(updatedWsi.getID())); + assertThat(updatedWsi.getSubmitter().getEmail(), is(SUBMITTER_EMAIL)); + assertThat(updatedWsi.getSubmitter().getEmail(), not(currentUser.getEmail())); + + EPerson adminUser = ePersonService.findByEmail(context, admin.getEmail()); + context.setCurrentUser(adminUser); + // Set workspace item owner to the current user + getClient(adminToken).perform(get("/api/submission/setOwner") + .param("shareToken", updatedWsi.getShareToken()) + .param("workspaceitemid", updatedWsi.getID().toString()) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + + // Check that the owner of the WorkspaceItem was set to the current user + // Check the wsi was persisted into the database + updatedWsi = workspaceItemService.find(context, wsi.getID()); + assertThat(updatedWsi.getSubmitter().getEmail(), is(adminUser.getEmail())); + assertThat(updatedWsi.getSubmitter().getEmail(), not(SUBMITTER_EMAIL)); + + getClient(adminToken).perform(get("/api/submission/share") + .param("workspaceitemid", wsi.getID().toString()) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.shareLink", is(notNullValue()))); + + updatedWsi = workspaceItemService.find(context, wsi.getID()); + + context.setCurrentUser(submitter2); + String userToken = getAuthToken(submitter2.getEmail(), password); + // Set workspace item owner to the 3rd person + getClient(userToken).perform(get("/api/submission/setOwner") + .param("shareToken", updatedWsi.getShareToken()) + .param("workspaceitemid", updatedWsi.getID().toString()) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + + // Check that the owner of the WorkspaceItem was set to the current user + // Check the wsi was persisted into the database + updatedWsi = workspaceItemService.find(context, wsi.getID()); + assertThat(updatedWsi.getSubmitter().getEmail(), is(submitter2.getEmail())); + assertThat(updatedWsi.getSubmitter().getEmail(), not(adminUser.getEmail())); + } }