diff --git a/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java b/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java index 7f29e6d79e5..03d5dc6b765 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java @@ -11,6 +11,9 @@ import java.util.Map; import org.apache.commons.lang3.BooleanUtils; +import org.dspace.content.InProgressSubmission; +import org.dspace.content.WorkspaceItem; +import org.hibernate.proxy.HibernateProxyHelper; /** * Class representing configuration for a single step within an Item Submission @@ -179,6 +182,45 @@ public String getVisibilityOutside() { return visibilityOutside; } + public boolean isHiddenForInProgressSubmission(InProgressSubmission obj) { + + String scopeToCheck = getScope(obj); + + if (scope == null || scopeToCheck == null) { + return false; + } + + String visibility = getVisibility(); + String visibilityOutside = getVisibilityOutside(); + + if (scope.equalsIgnoreCase(scopeToCheck)) { + return "hidden".equalsIgnoreCase(visibility); + } else { + return visibilityOutside == null || "hidden".equalsIgnoreCase(visibilityOutside); + } + + } + + public boolean isReadOnlyForInProgressSubmission(InProgressSubmission obj) { + + String scopeToCheck = getScope(obj); + + if (scope == null || scopeToCheck == null) { + return false; + } + + String visibility = scope.equalsIgnoreCase(scopeToCheck) ? getVisibility() : getVisibilityOutside(); + return "read-only".equalsIgnoreCase(visibility); + + } + + private String getScope(InProgressSubmission obj) { + if (HibernateProxyHelper.getClassWithoutInitializingProxy(obj).equals(WorkspaceItem.class)) { + return "submission"; + } + return "workflow"; + } + /** * Get the number of this step in the current Submission process config. * Step numbers start with #0 (although step #0 is ALWAYS the special diff --git a/dspace-api/src/main/java/org/dspace/validation/service/impl/ValidationServiceImpl.java b/dspace-api/src/main/java/org/dspace/validation/service/impl/ValidationServiceImpl.java index 10081bb914b..b4c9b4bc4c1 100644 --- a/dspace-api/src/main/java/org/dspace/validation/service/impl/ValidationServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/validation/service/impl/ValidationServiceImpl.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import org.dspace.app.util.SubmissionConfig; @@ -54,23 +55,51 @@ private void setup() throws SubmissionConfigReaderException { @Override public List validate(Context context, InProgressSubmission obj) { + SubmissionConfig submissionConfig = submissionConfigReader.getSubmissionConfigByInProgressSubmission(obj); + List errors = new ArrayList(); - SubmissionConfig submissionConfig = submissionConfigReader.getSubmissionConfigByInProgressSubmission(obj); + errors.addAll(notHiddenStepsValidations(context, obj, submissionConfig)); + errors.addAll(globalValidations(context, obj, submissionConfig)); + + return errors; + + } + + private List notHiddenStepsValidations(Context context, InProgressSubmission obj, + SubmissionConfig submissionConfig) { + + List errors = new ArrayList(); for (SubmissionStepConfig stepConfig : submissionConfig) { + + if (isStepHiddenOrReadOnly(stepConfig, obj)) { + continue; + } + stepValidators.stream() .filter(validation -> validation.getName().equals(stepConfig.getType())) .flatMap(validation -> validation.validate(context, obj, stepConfig).stream()) .forEach(errors::add); + } - globalValidators.stream() + return errors; + + } + + private List globalValidations(Context context, InProgressSubmission obj, + SubmissionConfig submissionConfig) { + + return globalValidators.stream() .flatMap(validator -> validator.validate(context, obj, submissionConfig).stream()) - .forEach(errors::add); + .collect(Collectors.toList()); - return errors; + } + private boolean isStepHiddenOrReadOnly(SubmissionStepConfig stepConfig, InProgressSubmission obj) { + return stepConfig.isHiddenForInProgressSubmission(obj) || stepConfig.isReadOnlyForInProgressSubmission(obj); } + } 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 34acf16fa41..0b7def31ca3 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/item-submission.xml @@ -57,7 +57,6 @@ org.dspace.app.rest.submit.step.CollectionStep collection - submission submit.progressbar.describe.stepone @@ -245,18 +244,46 @@ 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 identifiers + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + workflow + + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + submission + + + + + org.dspace.app.rest.submit.step.CollectionStep + collection + + + + + org.dspace.app.rest.submit.step.CollectionStep + collection + submission + + @@ -320,6 +347,13 @@ + + + + + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/edititem-service.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/edititem-service.xml index 95f341fac20..787bb5ebdd5 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/edititem-service.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/edititem-service.xml @@ -90,6 +90,15 @@ + + + + + ADMIN + + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml index 025561e9237..8ebe20c34f2 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml @@ -1955,7 +1955,7 @@ You can leave out the day and/or month if they aren't applicable. - +
@@ -1996,7 +1996,35 @@ You can leave out the day and/or month if they aren't applicable.
- + +
+ + + dc + title + + false + + onebox + Field required + + +
+ +
+ + + dc + type + + false + + onebox + Field required + + +
+ diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java index 74a3c7264e7..248342e1b19 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java @@ -101,6 +101,10 @@ protected void fillFromModel(T obj, R witem, Projection projection) { for (SubmissionSectionRest sections : def.getPanels()) { SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections); + if (stepConfig.isHiddenForInProgressSubmission(obj)) { + continue; + } + /* * First, load the step processing class (using the current * class loader) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/EditItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/EditItemConverter.java index eb2dedef3e6..24c8761268c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/EditItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/EditItemConverter.java @@ -101,6 +101,10 @@ protected void fillFromModel(EditItem obj, EditItemRest rest, Projection project for (SubmissionSectionRest sections : def.getPanels()) { SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections); + if (stepConfig.isHiddenForInProgressSubmission(obj)) { + continue; + } + /* * First, load the step processing class (using the current * class loader) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java index 350e471f49c..67185f2cdab 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java @@ -25,7 +25,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.io.IOException; import java.io.Serializable; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -64,6 +66,7 @@ import org.dspace.app.rest.projection.DefaultProjection; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.utils.Utils; +import org.dspace.authorize.AuthorizeException; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.EPersonBuilder; @@ -81,8 +84,13 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.services.ConfigurationService; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; +import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; import org.hamcrest.Matcher; import org.hamcrest.Matchers; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -117,6 +125,12 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration @Autowired private ItemConverter itemConverter; + @Autowired + private PoolTaskService poolTaskService; + + @Autowired + private XmlWorkflowItemService xmlWorkflowItemService; + @Autowired private Utils utils; private SiteService siteService; @@ -175,6 +189,14 @@ public void setUp() throws Exception { configurationService.setProperty("webui.user.assumelogin", true); } + @After + public void cleanUp() throws Exception { + context.turnOffAuthorisationSystem(); + poolTaskService.findAll(context).forEach(this::deletePoolTask); + xmlWorkflowItemService.findAll(context).forEach(this::deleteWorkflowItem); + context.restoreAuthSystemState(); + } + @Test /** * This method is not implemented @@ -2824,7 +2846,17 @@ public void verifySpecialGroupForNonAdministrativeUsersTest() throws Exception { .andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()); - getClient(epersonToken).perform(get("/api/submission/workspaceitems/" + workspaceItemIdRef.get())) + AtomicReference workflowItemIdRef = new AtomicReference(); + + getClient(epersonToken).perform(post("/api/workflow/workflowitems") + .content("/api/submission/workspaceitems/" + workspaceItemIdRef.get()) + .contentType(textUriContentType)) + .andExpect(status().isCreated()) + .andDo(result -> workflowItemIdRef.set(read(result.getResponse().getContentAsString(), "$.id"))); + + String tokenAdmin = getAuthToken(admin.getEmail(), password); + + getClient(tokenAdmin).perform(get("/api/workflow/workflowitems/" + workflowItemIdRef.get())) .andExpect(status().isOk()) .andExpect(jsonPath("$.sections.correction.metadata", hasSize(equalTo(3)))) .andExpect(jsonPath("$.sections.correction.empty", is(false))) @@ -2931,5 +2963,20 @@ private String getAuthorizationID(String epersonUuid, String featureName, String + id.toString(); } + private void deletePoolTask(PoolTask poolTask) { + try { + poolTaskService.delete(context, poolTask); + } catch (SQLException | AuthorizeException e) { + throw new RuntimeException(e); + } + } + + private void deleteWorkflowItem(XmlWorkflowItem workflowItem) { + try { + xmlWorkflowItemService.delete(context, workflowItem); + } catch (SQLException | AuthorizeException | IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CorrectionStepIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CorrectionStepIT.java index 05b3db7a4ac..34665592823 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CorrectionStepIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CorrectionStepIT.java @@ -9,9 +9,9 @@ import static com.jayway.jsonpath.JsonPath.read; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; -import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -20,6 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; @@ -40,21 +41,17 @@ import org.dspace.builder.EntityTypeBuilder; import org.dspace.builder.ItemBuilder; import org.dspace.builder.RelationshipTypeBuilder; -import org.dspace.builder.WorkspaceItemBuilder; import org.dspace.content.Collection; import org.dspace.content.EntityType; import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.Relationship; import org.dspace.content.RelationshipType; import org.dspace.content.WorkspaceItem; import org.dspace.content.service.EntityTypeService; -import org.dspace.content.service.ItemService; import org.dspace.content.service.RelationshipService; import org.dspace.content.service.RelationshipTypeService; import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.Constants; -import org.dspace.eperson.EPerson; import org.dspace.services.ConfigurationService; import org.dspace.xmlworkflow.storedcomponents.PoolTask; import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; @@ -68,12 +65,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; -import org.springframework.data.rest.webmvc.RestMediaTypes; /** * Integration tests for {@link CorrectionStep}. * - * @author Giuseppe Digilio (luca.giamminonni at 4science.it) + * @author Giuseppe Digilio (giuseppe.digilio at 4science.it) * */ public class CorrectionStepIT extends AbstractControllerIntegrationTest { @@ -84,9 +80,6 @@ public class CorrectionStepIT extends AbstractControllerIntegrationTest { @Autowired private EntityTypeService entityTypeService; - @Autowired - private ItemService itemService; - @Autowired private PoolTaskService poolTaskService; @@ -138,7 +131,7 @@ public void setup() throws Exception { date = "2020-02-20"; subject = "ExtraEntry"; - title = "Title " + (new Date().getTime()); + title = "Title " + new Date().getTime(); type = "text"; itemToBeCorrected = ItemBuilder.createItem(context, collection) @@ -160,6 +153,7 @@ public void setup() throws Exception { context.restoreAuthSystemState(); } + @Override @After public void destroy() throws Exception { //Clean up the database for the next test @@ -191,14 +185,12 @@ public void destroy() throws Exception { } } - if (workspaceItemIdRef.get() != null) { - WorkspaceItemBuilder.deleteWorkspaceItem(workspaceItemIdRef.get()); - } poolTaskService.findAll(context).forEach(this::deletePoolTask); - super.destroy(); + xmlWorkflowItemService.findAll(context).forEach(this::deleteWorkflowItem); super.destroy(); } + @Test public void checkCorrection() throws Exception { @@ -213,16 +205,15 @@ public void checkCorrection() throws Exception { .andExpect(status().isCreated()) .andDo(result -> workspaceItemIdRef.set(read(result.getResponse().getContentAsString(), "$.id"))); - Integer workspaceItemId = workspaceItemIdRef.get(); - List relationshipList = relationshipService.findByItem(context, itemToBeCorrected); - assert (relationshipList.size() > 0); + assert relationshipList.size() > 0; Item correctedItem = relationshipList.get(0).getLeftItem(); WorkspaceItem newWorkspaceItem = workspaceItemService.findByItem(context,correctedItem); //make a change on the title Map value = new HashMap(); - value.put("value", "New Title"); + final String newTitle = "New Title"; + value.put("value", newTitle); List addGrant = new ArrayList(); addGrant.add(new ReplaceOperation("/sections/traditionalpageone/dc.title/0", value)); String patchBody = getPatchContent(addGrant); @@ -241,9 +232,11 @@ public void checkCorrection() throws Exception { .contentType("application/json-patch+json")) .andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()); + //add an asbtract description - Map addValue = new HashMap(); - addValue.put("value","Description Test"); + Map addValue = new HashMap(); + final String newDescription = "New Description"; + addValue.put("value", newDescription); addGrant = new ArrayList(); addGrant.add(new AddOperation("/sections/traditionalpagetwo/dc.description.abstract", List.of(addValue))); patchBody = getPatchContent(addGrant); @@ -252,17 +245,32 @@ public void checkCorrection() throws Exception { .contentType("application/json-patch+json")) .andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()); - //check if the correction is present + getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + newWorkspaceItem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.sections.correction.metadata").doesNotExist()); + + AtomicReference workflowItemIdRef = new AtomicReference(); + + getClient(tokenSubmitter).perform(post("/api/workflow/workflowitems") + .content("/api/submission/workspaceitems/" + newWorkspaceItem.getID()) + .contentType(textUriContentType)) + .andExpect(status().isCreated()) + .andDo(result -> workflowItemIdRef.set(read(result.getResponse().getContentAsString(), "$.id"))); + + String tokenAdmin = getAuthToken(admin.getEmail(), password); + + //check if the correction is present + final String extraEntry = "ExtraEntry"; + getClient(tokenAdmin).perform(get("/api/workflow/workflowitems/" + workflowItemIdRef.get())) //The status has to be 200 OK .andExpect(status().isOk()) //The array of browse index should have a size equals to 4 .andExpect(jsonPath("$.sections.correction.metadata", hasSize(equalTo(3)))) .andExpect(jsonPath("$.sections.correction.empty", is(false))) - .andExpect(jsonPath("$.sections.correction.metadata", - containsInAnyOrder(matchMetadataCorrection("New Title"), - matchMetadataCorrection("Description Test"), - matchMetadataCorrection("ExtraEntry")))); + .andExpect(jsonPath("$.sections.correction.metadata",hasItem(matchMetadataCorrection(newTitle)))) + .andExpect(jsonPath("$.sections.correction.metadata",hasItem(matchMetadataCorrection(newDescription)))) + .andExpect(jsonPath("$.sections.correction.metadata",hasItem(matchMetadataCorrection(extraEntry)))); } @@ -279,14 +287,23 @@ public void checkEmptyCorrection() throws Exception { .andExpect(status().isCreated()) .andDo(result -> workspaceItemIdRef.set(read(result.getResponse().getContentAsString(), "$.id"))); - Integer workspaceItemId = workspaceItemIdRef.get(); List relationshipList = relationshipService.findByItem(context, itemToBeCorrected); - assert (relationshipList.size() > 0); + assert relationshipList.size() > 0; Item correctedItem = relationshipList.get(0).getLeftItem(); WorkspaceItem newWorkspaceItem = workspaceItemService.findByItem(context, correctedItem); + AtomicReference workflowItemIdRef = new AtomicReference(); + + getClient(tokenSubmitter).perform(post("/api/workflow/workflowitems") + .content("/api/submission/workspaceitems/" + newWorkspaceItem.getID()) + .contentType(textUriContentType)) + .andExpect(status().isCreated()) + .andDo(result -> workflowItemIdRef.set(read(result.getResponse().getContentAsString(), "$.id"))); + + String tokenAdmin = getAuthToken(admin.getEmail(), password); + //check if the correction section is empty on relation item - getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/" + newWorkspaceItem.getID())) + getClient(tokenAdmin).perform(get("/api/workflow/workflowitems/" + workflowItemIdRef.get())) //The status has to be 200 OK .andExpect(status().isOk()) //The array of browse index should have a size greater or equals to 1 @@ -295,72 +312,10 @@ public void checkEmptyCorrection() throws Exception { } - private static Matcher matchMetadataCorrection(String value) { + private static Matcher matchMetadataCorrection(String value) { return Matchers.anyOf( - // Check workspaceitem properties - hasJsonPath("$.newValues[0]", is(value)), - hasJsonPath("$.oldValues[0]", is(value))); - } - - private void claimTaskAndCheckResponse(String authToken, Integer poolTaskId) throws SQLException, Exception { - getClient(authToken).perform(post("/api/workflow/claimedtasks") - .contentType(RestMediaTypes.TEXT_URI_LIST) - .content("/api/workflow/pooltasks/" + poolTaskId)) - .andExpect(status().isCreated()) - .andExpect(jsonPath("$", Matchers.allOf(hasJsonPath("$.type", is("claimedtask"))))); - } - - private XmlWorkflowItem setSubmission(EPerson user, String title, String date) - throws Exception { - - context.setCurrentUser(user); - - AtomicReference idRef = new AtomicReference(); - String tokenSubmitter = getAuthToken(user.getEmail(), password); - // create empty workSpaceItem - getClient(tokenSubmitter).perform(post("/api/submission/workspaceitems") - .param("owningCollection", collection.getID().toString()) - .contentType(org.springframework.http.MediaType.APPLICATION_JSON)) - .andExpect(status().isCreated()) - .andDo((result -> idRef - .set(read(result.getResponse().getContentAsString(), "$.id")))); - - WorkspaceItem witem = workspaceItemService.find(context, idRef.get()); - Item item = witem.getItem(); - - // add metadata - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "title", null, null, title); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "date", "issued", null, date); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "subject", null, null, "ExtraEntry"); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "type", null, null, "text"); - // accept license - List addGrant = new ArrayList(); - addGrant.add(new AddOperation("/sections/license/granted", true)); - String patchBody = getPatchContent(addGrant); - getClient(tokenSubmitter).perform(patch("/api/submission/workspaceitems/" + witem.getID()) - .content(patchBody) - .contentType("application/json-patch+json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.errors").doesNotExist()) - .andExpect(jsonPath("$.sections.license.granted", - is(true))) - .andExpect(jsonPath("$.sections.license.acceptanceDate").isNotEmpty()) - .andExpect(jsonPath("$.sections.license.url").isNotEmpty()); - - //deposit workSpaceItem, so it become workFlowItem - getClient(tokenSubmitter).perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems") - .content("/api/submission/workspaceitems/" + witem.getID()) - .contentType(textUriContentType)) - .andExpect(status().isCreated()) - .andDo((result -> idRef - .set(read(result.getResponse().getContentAsString(), "$.id")))); - - XmlWorkflowItem xmlWorkFlowItem = xmlWorkflowItemService.find(context, idRef.get()); - return xmlWorkFlowItem; + hasJsonPath("$.newValues[0]", equalTo(value)), + hasJsonPath("$.oldValues[0]", equalTo(value))); } private void deletePoolTask(PoolTask poolTask) { @@ -371,5 +326,12 @@ private void deletePoolTask(PoolTask poolTask) { } } + private void deleteWorkflowItem(XmlWorkflowItem workflowItem) { + try { + xmlWorkflowItemService.delete(context, workflowItem); + } catch (SQLException | AuthorizeException | IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EditItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EditItemRestRepositoryIT.java index b2cc8e5ea7c..7a511f662fc 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EditItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EditItemRestRepositoryIT.java @@ -15,6 +15,7 @@ import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -1906,6 +1907,50 @@ public void testEditItemModeConfigurationWithEntityTypeAndSubmission() throws Ex } + @Test + public void testEditWithHiddenSections() throws Exception { + context.turnOffAuthorisationSystem(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Collection collection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Collection 1") + .withEntityType("Publication") + .build(); + Item item = ItemBuilder.createItem(context, collection) + .withTitle("Item") + .build(); + context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) + .perform(get("/api/core/edititems/" + item.getID() + ":MODE-TEST-HIDDEN")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.sections.test-outside-workflow-hidden").exists()) + .andExpect(jsonPath("$.sections.test-outside-submission-hidden").doesNotExist()) + .andExpect(jsonPath("$.sections.test-never-hidden").exists()) + .andExpect(jsonPath("$.sections.test-always-hidden").doesNotExist()); + } + + @Test + public void testValidationWithHiddenSteps() throws Exception { + context.turnOffAuthorisationSystem(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Collection collection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Collection 1") + .withEntityType("Publication") + .build(); + Item item = ItemBuilder.createItem(context, collection) + .build(); + context.restoreAuthSystemState(); + getClient(getAuthToken(admin.getEmail(), password)) + .perform(get("/api/core/edititems/" + item.getID() + ":MODE-TEST-HIDDEN")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors", hasSize(1))) + .andExpect(jsonPath("$.errors[0].message", is("error.validation.required"))) + .andExpect(jsonPath("$.errors[0].paths", contains("/sections/test-outside-workflow-hidden/dc.title"))); + } + private Bitstream getBitstream(Item item, String name) throws SQLException { return bitstreamService.getBitstreamByName(item, "ORIGINAL", name); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java index d3a830a5eb5..a0343d67e93 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionDefinitionsControllerIT.java @@ -310,7 +310,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "0")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("patent"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("test-hidden"))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -322,10 +322,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=15"), Matchers.containsString("size=1")))) + Matchers.containsString("page=16"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(16))) - .andExpect(jsonPath("$.page.totalPages", is(16))) + .andExpect(jsonPath("$.page.totalElements", is(17))) + .andExpect(jsonPath("$.page.totalPages", is(17))) .andExpect(jsonPath("$.page.number", is(0))); getClient(tokenAdmin).perform(get("/api/config/submissiondefinitions") @@ -333,7 +333,7 @@ public void findAllPaginationTest() throws Exception { .param("page", "1")) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) - .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("accessConditionNotDiscoverable"))) + .andExpect(jsonPath("$._embedded.submissiondefinitions[0].id", is("patent"))) .andExpect(jsonPath("$._links.first.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), Matchers.containsString("page=0"), Matchers.containsString("size=1")))) @@ -348,10 +348,10 @@ public void findAllPaginationTest() throws Exception { Matchers.containsString("page=1"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$._links.last.href", Matchers.allOf( Matchers.containsString("/api/config/submissiondefinitions?"), - Matchers.containsString("page=15"), Matchers.containsString("size=1")))) + Matchers.containsString("page=16"), Matchers.containsString("size=1")))) .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(16))) - .andExpect(jsonPath("$.page.totalPages", is(16))) + .andExpect(jsonPath("$.page.totalElements", is(17))) + .andExpect(jsonPath("$.page.totalPages", is(17))) .andExpect(jsonPath("$.page.number", is(1))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java index 43f80037b16..9236e7c4ce2 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java @@ -51,8 +51,8 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe @Autowired private ChoiceAuthorityService cas; - private final static int PAGE_TOTAL_ELEMENTS = 31; - private final static int PAGE_TOTAL_PAGES = 16; + private final static int PAGE_TOTAL_ELEMENTS = 33; + private final static int PAGE_TOTAL_PAGES = 17; @Test public void findAll() throws Exception { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionSectionsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionSectionsControllerIT.java index 8ff9ff19217..5fd5ba9fba5 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionSectionsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionSectionsControllerIT.java @@ -68,8 +68,7 @@ public void testFindOne() throws Exception { getClient(token).perform(get("/api/config/submissionsections/collection")) .andExpect(status().isOk()) - .andExpect(jsonPath("$", matches("collection", true, "collection", - of("submission", "hidden", "workflow", "hidden", "edit", "hidden")))); + .andExpect(jsonPath("$", matches("collection", true, "collection"))); getClient(token).perform(get("/api/config/submissionsections/traditionalpageone")) .andExpect(status().isOk()) 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 1f26477910a..026a8d95654 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 @@ -69,6 +69,7 @@ import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.services.ConfigurationService; +import org.dspace.workflow.WorkflowItem; import org.dspace.xmlworkflow.factory.XmlWorkflowFactory; import org.dspace.xmlworkflow.state.Step; import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; @@ -2646,4 +2647,64 @@ public void whenWorkspaceitemBecomeWorkflowitemWithAccessConditionsTheItemMustBe WorkflowItemBuilder.deleteWorkflowItem(idRef.get()); } } + + @Test + public void testWorkflowWithHiddenSections() throws Exception { + + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Collection 1") + .withSubmissionDefinition("test-hidden") + .withWorkflowGroup(1, eperson) + .build(); + + WorkflowItem workflowItem = WorkflowItemBuilder.createWorkflowItem(context, collection) + .withTitle("Workflow Item") + .build(); + + context.restoreAuthSystemState(); + + getClient(getAuthToken(admin.getEmail(), password)) + .perform(get("/api/workflow/workflowitems/" + workflowItem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.sections.test-outside-workflow-hidden").exists()) + .andExpect(jsonPath("$.sections.test-outside-submission-hidden").doesNotExist()) + .andExpect(jsonPath("$.sections.test-never-hidden").exists()) + .andExpect(jsonPath("$.sections.test-always-hidden").doesNotExist()); + + } + + @Test + public void testValidationWithHiddenSteps() throws Exception { + + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Collection 1") + .withSubmissionDefinition("test-hidden") + .withWorkflowGroup(1, eperson) + .build(); + + WorkflowItem workflowItem = WorkflowItemBuilder.createWorkflowItem(context, collection) + .build(); + + context.restoreAuthSystemState(); + + getClient(getAuthToken(admin.getEmail(), password)) + .perform(get("/api/workflow/workflowitems/" + workflowItem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors", hasSize(1))) + .andExpect(jsonPath("$.errors[0].message", is("error.validation.required"))) + .andExpect(jsonPath("$.errors[0].paths", contains("/sections/test-outside-workflow-hidden/dc.title"))); + } + } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java index cc7dd26e1d6..c7725805687 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java @@ -9849,6 +9849,64 @@ public void supervisionOrdersEndpointTest() throws Exception { )); } + @Test + public void testSubmissionWithHiddenSections() throws Exception { + + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Collection 1") + .withSubmissionDefinition("test-hidden") + .build(); + + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection) + .withTitle("Workspace Item") + .withIssueDate("2023-01-01") + .withType("Type") + .build(); + + context.restoreAuthSystemState(); + + getClient(getAuthToken(admin.getEmail(), password)) + .perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.sections.test-outside-workflow-hidden").doesNotExist()) + .andExpect(jsonPath("$.sections.test-outside-submission-hidden").exists()) + .andExpect(jsonPath("$.sections.test-never-hidden").exists()) + .andExpect(jsonPath("$.sections.test-always-hidden").doesNotExist()); + } + + @Test + public void testValidationWithHiddenSteps() throws Exception { + + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Collection 1") + .withSubmissionDefinition("test-hidden") + .build(); + + WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection) + .build(); + + context.restoreAuthSystemState(); + + getClient(getAuthToken(admin.getEmail(), password)) + .perform(get("/api/submission/workspaceitems/" + workspaceItem.getID())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors", hasSize(1))) + .andExpect(jsonPath("$.errors[0].message", is("error.validation.required"))) + .andExpect(jsonPath("$.errors[0].paths", contains("/sections/test-outside-submission-hidden/dc.type"))); + } + @Test public void patchBySupervisorTest() throws Exception { context.turnOffAuthorisationSystem(); diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index 6c33b1023a2..b3e2f504c9b 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -59,7 +59,6 @@ submit.progressbar.collection org.dspace.app.rest.submit.step.CollectionStep collection - submission submit.progressbar.upload