From 7d488daaabf7ed2415d430cf50533cd1ebe52323 Mon Sep 17 00:00:00 2001 From: Piaget Bouaka Donfack Date: Tue, 25 Feb 2025 17:54:09 +0100 Subject: [PATCH] [DURACOM-328] File upload not working correctly: problems when trying to delete uploaded file --- .../dspaceFolder/config/item-submission.xml | 258 +++++++++++++++++- .../config/spring/api/access-conditions.xml | 13 +- .../app/rest/submit/step/UploadStep.java | 25 +- .../rest/WorkflowItemRestRepositoryIT.java | 46 ++++ 4 files changed, 320 insertions(+), 22 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml index feb3c7c12b3d..3ceb629a4564 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml @@ -18,7 +18,10 @@ + + + @@ -38,7 +41,7 @@ - + @@ -48,7 +51,7 @@ - + @@ -66,11 +69,26 @@ org.dspace.app.rest.submit.step.DescribeStep submission-form + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + submit.progressbar.describe.steptwo org.dspace.app.rest.submit.step.DescribeStep submission-form + + submit.progressbar.describe.stepthree + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepthree + org.dspace.app.rest.submit.step.DescribeStep + submission-form + submit.progressbar.upload org.dspace.app.rest.submit.step.UploadStep @@ -82,12 +100,17 @@ license submission + + + org.dspace.app.rest.submit.step.ExtractMetadataStep + utils + submission + org.dspace.app.rest.submit.step.DescribeStep submission-form - org.dspace.app.rest.submit.step.DescribeStep submission-form @@ -105,31 +128,61 @@ accessCondition + + submit.progressbar.accessCondition + org.dspace.app.rest.submit.step.AccessConditionStep + accessCondition + + - submit.progressbar.CClicense org.dspace.app.rest.submit.step.CCLicenseStep cclicense - + + + submit.progressbar.detect-duplicate + org.dspace.app.rest.submit.step.DetectPotentialDuplicateStep + detect-duplicate + + + submit.progressbar.ExtractMetadataStep org.dspace.app.rest.submit.step.ExtractMetadataStep extract - + + + submit.progressbar.describe.patent + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.patent_indexing + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.patent_references + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + Sample @@ -137,6 +190,31 @@ sample + + submit.progressbar.describe.publication + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.publication_indexing + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.publication_bibliographic_details + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.publication_references + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.person + org.dspace.app.rest.submit.step.DescribeStep + submission-form + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep @@ -149,6 +227,36 @@ sherpaPolicy + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + + submit.progressbar.CustomUrlStep + org.dspace.app.rest.submit.step.CustomUrlStep + custom-url + + + + submit.progressbar.correction-step + org.dspace.app.rest.submit.step.CorrectionStep + correction + workflow + + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + submit.progressbar.identifiers org.dspace.app.rest.submit.step.ShowIdentifiersStep @@ -182,6 +290,22 @@ submission + + submit.progressbar.describe.green + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.green + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.funding + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + submit.progressbar.duplicates @@ -220,6 +344,7 @@ + @@ -233,6 +358,7 @@ + @@ -242,11 +368,103 @@ + + + + " + + + + + + + + " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -271,11 +489,27 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml index a9af7c66f5e8..1170c4354df9 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/access-conditions.xml @@ -17,7 +17,17 @@ - + + + + + + + + + + + @@ -55,6 +65,7 @@ + diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java index e0a9cb17e01c..44aa75be9a6e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java @@ -11,9 +11,9 @@ import java.io.InputStream; import java.util.List; import java.util.Objects; +import java.util.regex.Pattern; import jakarta.servlet.http.HttpServletRequest; -import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.ErrorRest; @@ -48,6 +48,13 @@ public class UploadStep extends AbstractProcessingStep private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(UploadStep.class); + private static final Pattern UPDATE_METADATA_PATTERN = + Pattern.compile("^/sections/[^/]+/files/[^/]+/metadata/[^/]+(/[^/]+)?$"); + private static final Pattern PRIMARY_FLAG_PATTERN = + Pattern.compile("^/sections/[^/]+/primary$"); + private static final Pattern ACCESS_CONDITION_PATTERN = + Pattern.compile("^/sections/[^/]+/files/[^/]+/accessConditions(/[^/]+)?$"); + @Override public DataUpload getData(SubmissionService submissionService, InProgressSubmission obj, SubmissionStepConfig config) throws Exception { @@ -73,31 +80,31 @@ public void doPatchProcessing(Context context, HttpServletRequest currentRequest String instance = null; if ("remove".equals(op.getOp())) { - if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) { + if (UPDATE_METADATA_PATTERN.matcher(op.getPath()).matches()) { instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY; - } else if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) { + } else if (ACCESS_CONDITION_PATTERN.matcher(op.getPath()).matches()) { instance = stepConf.getType() + "." + UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY; - } else if (op.getPath().contains(PRIMARY_FLAG_ENTRY)) { + } else if (PRIMARY_FLAG_PATTERN.matcher(op.getPath()).matches()) { instance = PRIMARY_FLAG_ENTRY; } else { instance = UPLOAD_STEP_REMOVE_OPERATION_ENTRY; } } else if ("move".equals(op.getOp())) { - if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) { + if (UPDATE_METADATA_PATTERN.matcher(op.getPath()).matches()) { instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY; } else { instance = UPLOAD_STEP_MOVE_OPERATION_ENTRY; } } else { - if (op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) { + if (ACCESS_CONDITION_PATTERN.matcher(op.getPath()).matches()) { instance = stepConf.getType() + "." + UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY; - } else if (op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) { + } else if (UPDATE_METADATA_PATTERN.matcher(op.getPath()).matches()) { instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY; - } else if (op.getPath().contains(PRIMARY_FLAG_ENTRY)) { + } else if (PRIMARY_FLAG_PATTERN.matcher(op.getPath()).matches()) { instance = PRIMARY_FLAG_ENTRY; } } - if (StringUtils.isBlank(instance)) { + if (instance == null) { throw new UnprocessableEntityException("The path " + op.getPath() + " is not supported by the operation " + op.getOp()); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java index a9bbc752f875..1ea62e2a74af 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkflowItemRestRepositoryIT.java @@ -9,6 +9,7 @@ import static com.jayway.jsonpath.JsonPath.read; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -1934,6 +1935,51 @@ public void findOneFullProjectionTest() throws Exception { } + @Test + public void deleteBitstreamTest() + throws Exception { + context.turnOffAuthorisationSystem(); + EPerson submitter = EPersonBuilder.createEPerson(context) + .withEmail("submitter@example.com") + .withPassword(password) + .build(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Collection collection1 = CollectionBuilder.createCollection(context, parentCommunity, + "123456789/collection-test-patch") + .withName("Collection 1") + .build(); + Bitstream bitstream = null; + WorkspaceItem witem = null; + String bitstreamContent = "0123456789"; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, Charset.defaultCharset())) { + context.setCurrentUser(submitter); + witem = WorkspaceItemBuilder.createWorkspaceItem(context, collection1) + .withTitle("Test WorkspaceItem") + .withIssueDate("2019-10-01") + .grantLicense() + .build(); + bitstream = BitstreamBuilder.createBitstream(context, witem.getItem(), is) + .withName("Test bitstream") + .withDescription("This is a bitstream to test range requests") + .withMimeType("text/plain") + .build(); + } + context.restoreAuthSystemState(); + String tokenSubmitter = getAuthToken(submitter.getEmail(), password); + List deleteFile = new ArrayList<>(); + deleteFile.add(new RemoveOperation("/sections/bitstream-metadata-publication/files/0/")); + getClient(tokenSubmitter).perform(patch("/api/submission/workspaceitems/" + witem.getID()) + .content(getPatchContent(deleteFile)) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + // verify that the patch removed bitstream + getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + witem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.sections.bitstream-metadata-publication.files", hasSize(0))); + } + @Test public void whenWorkspaceitemBecomeWorkflowitemWithAccessConditionsTheBitstreamMustBeDownloableTest() throws Exception {