diff --git a/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java b/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java index 00bfd71c0f..979d842406 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java @@ -310,7 +310,8 @@ public class DescribeStep extends AbstractProcessingStep DCValue[] values = item.getMetadata(inputs[i].getSchema(), inputs[i].getElement(), inputs[i].getQualifier(), Item.ANY); - if (inputs[i].isRequired() && values.length == 0) + if ((inputs[i].isRequired() && values.length == 0) && + inputs[i].isVisible(subInfo.isInWorkflow() ? DCInput.WORKFLOW_SCOPE : DCInput.SUBMISSION_SCOPE)) { // since this field is missing add to list of error fields addErrorField(request, getFieldName(inputs[i])); diff --git a/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java b/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java index d25df53c0c..f6710bdcde 100644 --- a/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java +++ b/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java @@ -86,7 +86,7 @@ public class UsageEvent extends Event { return objText + ":" + action.text(); }catch(Exception e) { - + } return ""; diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java index 24b09d9880..55ec75a7e6 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java @@ -15,12 +15,10 @@ import org.dspace.core.ConfigurationManager; import org.dspace.core.Email; import org.dspace.core.I18nUtil; import org.apache.log4j.Logger; -import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.xmlworkflow.state.Workflow; import org.dspace.xmlworkflow.storedcomponents.CollectionRole; -import javax.mail.MessagingException; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.sql.SQLException; @@ -211,9 +209,13 @@ public class WorkflowUtils extends Util{ /* * Deletes a role group linked to a given role and a collection */ - public static void deleteRoleGroup(Context context, int collectionID, String roleID) throws SQLException { - CollectionRole ass = CollectionRole.find(context,collectionID,roleID); - ass.delete(); + public static void deleteRoleGroup(Context context, Collection collection, String roleID) throws SQLException, IOException, WorkflowConfigurationException { + Workflow workflow = WorkflowFactory.getWorkflow(collection); + Role role = workflow.getRoles().get(roleID); + if(role.getScope() == Role.Scope.COLLECTION){ + CollectionRole ass = CollectionRole.find(context, collection.getID(), roleID); + ass.delete(); + } } @@ -236,6 +238,46 @@ public class WorkflowUtils extends Util{ return result; } + + public static HashMap getCollectionAndRepositoryRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException { + Workflow workflow = WorkflowFactory.getWorkflow(thisCollection); + LinkedHashMap result = new LinkedHashMap(); + if(workflow != null){ + //Make sure we find one + HashMap allRoles = workflow.getRoles(); + //We have retrieved all our roles, not get the ones which can be configured by the collection + for(String roleId : allRoles.keySet()){ + Role role = allRoles.get(roleId); + // We just require the roles which have a scope of collection + if((role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) && !role.isInternal()){ + result.put(roleId, role); + } + } + + } + return result; + } + + + public static HashMap getAllExternalRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException { + Workflow workflow = WorkflowFactory.getWorkflow(thisCollection); + LinkedHashMap result = new LinkedHashMap(); + if(workflow != null){ + //Make sure we find one + HashMap allRoles = workflow.getRoles(); + //We have retrieved all our roles, not get the ones which can be configured by the collection + for(String roleId : allRoles.keySet()){ + Role role = allRoles.get(roleId); + // We just require the roles which have a scope of collection + if(!role.isInternal()){ + result.put(roleId, role); + } + } + + } + return result; + } + public static Group getRoleGroup(Context context, int collectionId, Role role) throws SQLException { if(role.getScope() == Role.Scope.REPOSITORY){ return Group.findByName(context, role.getName()); diff --git a/dspace-jspui/dspace-jspui-webapp/src/main/webapp/submit/upload-file-list.jsp b/dspace-jspui/dspace-jspui-webapp/src/main/webapp/submit/upload-file-list.jsp index 3451e1da9f..0f8ec335e3 100644 --- a/dspace-jspui/dspace-jspui-webapp/src/main/webapp/submit/upload-file-list.jsp +++ b/dspace-jspui/dspace-jspui-webapp/src/main/webapp/submit/upload-file-list.jsp @@ -31,6 +31,7 @@ <%@ page import="org.dspace.content.Bitstream" %> <%@ page import="org.dspace.content.BitstreamFormat" %> <%@ page import="org.dspace.content.Bundle" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> @@ -46,6 +47,7 @@ boolean showChecksums = ((Boolean) request.getAttribute("show.checksums")).booleanValue(); request.setAttribute("LanguageSwitch", "hide"); + boolean allowFileEditing = !subInfo.isInWorkflow() || ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit"); %> @@ -90,7 +92,7 @@ } // Don't display last column ("Remove") in workflow mode - if (!subInfo.isInWorkflow()) + if (allowFileEditing) { // Whether it's an odd or even column depends on whether we're showing checksums String column = (showChecksums ? "Even" : "Odd"); @@ -163,7 +165,7 @@ } // Don't display "remove" button in workflow mode - if (!subInfo.isInWorkflow()) + if (allowFileEditing) { // Whether it's an odd or even column depends on whether we're showing checksums String column = (showChecksums ? "Even" : "Odd"); @@ -188,7 +190,7 @@ <%-- Show information about how to verify correct upload, but not in workflow mode! --%> <% - if (!subInfo.isInWorkflow()) + if (allowFileEditing) { %>

@@ -223,7 +225,7 @@
<% // Don't allow files to be added in workflow mode - if (!subInfo.isInWorkflow()) + if (allowFileEditing) { %>

" />

diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowContainerUtils.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowContainerUtils.java index 2df6333eb0..ee1d737096 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowContainerUtils.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowContainerUtils.java @@ -488,17 +488,23 @@ public class FlowContainerUtils } private static Group getXMLWorkflowRole(Context context, int collectionID, String roleName, Collection collection, Group roleGroup) throws IOException, WorkflowConfigurationException, SQLException, AuthorizeException { - Role role = WorkflowUtils.getCollectionRoles(collection).get(roleName); - if(role.getScope() == Role.Scope.COLLECTION){ + Role role = WorkflowUtils.getCollectionAndRepositoryRoles(collection).get(roleName); + if(role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY){ roleGroup = WorkflowUtils.getRoleGroup(context, collectionID, role); if(roleGroup == null){ AuthorizeManager.authorizeAction(context, collection, Constants.WRITE); roleGroup = Group.create(context); - roleGroup.setName("COLLECTION_" + collection.getID() + "_WORKFLOW_ROLE_" + roleName); + if(role.getScope() == Role.Scope.COLLECTION){ + roleGroup.setName("COLLECTION_" + collection.getID() + "_WORKFLOW_ROLE_" + roleName); + }else{ + roleGroup.setName(role.getName()); + } roleGroup.update(); AuthorizeManager.addPolicy(context, collection, Constants.ADD, roleGroup); - WorkflowUtils.createCollectionWorkflowRole(context, collectionID, roleName, roleGroup); - } + if(role.getScope() == Role.Scope.COLLECTION){ + WorkflowUtils.createCollectionWorkflowRole(context, collectionID, roleName, roleGroup); + } + } } return roleGroup; } @@ -513,8 +519,8 @@ public class FlowContainerUtils * @param groupID The id of the group associated with this role. * @return A process result's object. */ - public static FlowResult processDeleteCollectionRole(Context context, int collectionID, String roleName, int groupID) throws SQLException, UIException, IOException, AuthorizeException - { + public static FlowResult processDeleteCollectionRole(Context context, int collectionID, String roleName, int groupID) throws SQLException, UIException, IOException, AuthorizeException, WorkflowConfigurationException + { FlowResult result = new FlowResult(); Collection collection = Collection.find(context,collectionID); @@ -530,7 +536,7 @@ public class FlowContainerUtils collection.removeSubmitters(); } else{ - WorkflowUtils.deleteRoleGroup(context, collectionID, roleName); + WorkflowUtils.deleteRoleGroup(context, collection, roleName); } // else if (ROLE_WF_STEP1.equals(roleName)) // { diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/collection/AssignCollectionRoles.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/collection/AssignCollectionRoles.java index df3e0beac4..1964773493 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/collection/AssignCollectionRoles.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/collection/AssignCollectionRoles.java @@ -90,6 +90,7 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer private static final Message T_label_default_read = message("xmlui.administrative.collection.AssignCollectionRoles.label_default_read"); private static final Message T_sysadmins_only = message("xmlui.administrative.collection.AssignCollectionRoles.sysadmins_only"); + private static final Message T_sysadmins_only_repository_role = message("xmlui.administrative.collection.AssignCollectionRoles.repository_role"); private static final Message T_not_allowed = message("xmlui.administrative.collection.AssignCollectionRoles.not_allowed"); @@ -116,7 +117,7 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer HashMap roles = null; try { - roles = WorkflowUtils.getCollectionRoles(thisCollection); + roles = WorkflowUtils.getAllExternalRoles(thisCollection); } catch (WorkflowConfigurationException e) { log.error(LogManager.getHeader(context, "error while getting collection roles", "Collection id: " + thisCollection.getID())); } catch (IOException e) { @@ -361,16 +362,35 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer for(String roleId: roles.keySet()){ Role role = roles.get(roleId); - if (role.getScope() == Role.Scope.COLLECTION) { + if (role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) { tableRow = rolesTable.addRow(Row.ROLE_DATA); tableRow.addCell(Cell.ROLE_HEADER).addContent(role.getName()); Group roleGroup = WorkflowUtils.getRoleGroup(context, thisCollection.getID(), role); if (roleGroup != null) { - tableRow.addCell().addXref(baseURL + "&submit_edit_wf_role_" + roleId, roleGroup.getName()); - addAdministratorOnlyButton(tableRow.addCell(), "submit_delete_wf_role_" + roleId, T_delete); + if(role.getScope() == Role.Scope.REPOSITORY){ + if(AuthorizeManager.isAdmin(context)){ + tableRow.addCell().addXref(baseURL + "&submit_edit_wf_role_" + roleId, roleGroup.getName()); + }else{ + Cell cell = tableRow.addCell(); + cell.addContent(roleGroup.getName()); + cell.addHighlight("fade").addContent(T_sysadmins_only_repository_role); + } + }else{ + tableRow.addCell().addXref(baseURL + "&submit_edit_wf_role_" + roleId, roleGroup.getName()); + } + + if (role.getScope() == Role.Scope.COLLECTION) { + addAdministratorOnlyButton(tableRow.addCell(), "submit_delete_wf_role_" + roleId, T_delete); + } else { + tableRow.addCell(); + } } else { tableRow.addCell().addContent(T_no_role); - addAdministratorOnlyButton(tableRow.addCell(), "submit_create_wf_role_" + roleId, T_create); + if (role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) { + addAdministratorOnlyButton(tableRow.addCell(), "submit_create_wf_role_" + roleId, T_create); + } else { + tableRow.addCell(); + } } // help and directions row tableRow = rolesTable.addRow(Row.ROLE_DATA); @@ -379,6 +399,19 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer tableRow.addCell(1,2).addHighlight("fade offset").addContent(role.getDescription()); } + } else { + tableRow = rolesTable.addRow(Row.ROLE_DATA); + tableRow.addCell(Cell.ROLE_HEADER).addContent(role.getName()); + + tableRow.addCell().addContent(T_no_role); + tableRow.addCell(); + + // help and directions row + tableRow = rolesTable.addRow(Row.ROLE_DATA); + tableRow.addCell(); + if (role.getDescription() != null){ + tableRow.addCell(1,2).addHighlight("fade offset").addContent(role.getDescription()); + } } } } diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/AbstractStep.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/AbstractStep.java index 29e4cbbe0a..1f8eefd43e 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/AbstractStep.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/AbstractStep.java @@ -232,7 +232,7 @@ public abstract class AbstractStep extends AbstractDSpaceTransformer HandleUtil.buildHandleTrail(collection,pageMeta,contextPath, true); pageMeta.addTrail().addContent(T_submission_trail); } - else if (submission instanceof WorkflowItem) + else if (submissionInfo != null && submissionInfo.isInWorkflow()) { pageMeta.addMetadata("title").addContent(T_workflow_title); diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadStep.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadStep.java index 88f70810d0..35f123eee6 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadStep.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadStep.java @@ -37,6 +37,7 @@ import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; import org.dspace.workflow.WorkflowItem; import org.xml.sax.SAXException; @@ -166,7 +167,7 @@ public class UploadStep extends AbstractSubmissionStep Item item = submission.getItem(); Collection collection = submission.getCollection(); String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue"; - boolean workflow = submission instanceof WorkflowItem; + boolean disableFileEditing = (submissionInfo.isInWorkflow()) && !ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit"); Bundle[] bundles = item.getBundles("ORIGINAL"); Bitstream[] bitstreams = new Bitstream[0]; if (bundles.length > 0) @@ -182,7 +183,7 @@ public class UploadStep extends AbstractSubmissionStep List upload = null; - if (!workflow) + if (!disableFileEditing) { // Only add the upload capabilities for new item submissions upload = div.addList("submit-upload-new", List.TYPE_FORM); @@ -227,7 +228,7 @@ public class UploadStep extends AbstractSubmissionStep // Part B: // If the user has already uploaded files provide a list for the user. - if (bitstreams.length > 0 || workflow) + if (bitstreams.length > 0 || disableFileEditing) { Table summary = div.addTable("submit-upload-summary",(bitstreams.length * 2) + 2,7); summary.setHead(T_head2); @@ -264,7 +265,7 @@ public class UploadStep extends AbstractSubmissionStep primary.setOptionSelected(String.valueOf(id)); } - if (!workflow) + if (!disableFileEditing) { // Workflow users can not remove files. CheckBox remove = row.addCell().addCheckBox("remove"); @@ -323,7 +324,7 @@ public class UploadStep extends AbstractSubmissionStep checksumCell.addContent(algorithm + ":" + checksum); } - if (!workflow) + if (!disableFileEditing) { // Workflow users can not remove files. Row actionRow = summary.addRow(); diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java index 8683b3f1ed..f1f1429e4b 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java @@ -159,7 +159,8 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); } - public void addPageMeta(PageMeta pageMeta) throws WingException{ + public void addPageMeta(PageMeta pageMeta) throws WingException, AuthorizeException, IOException, SAXException, SQLException { + super.addPageMeta(pageMeta); pageMeta.addMetadata("javascript", "static").addContent("static/js/accessFormUtil.js"); } @@ -186,7 +187,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep Item item = submission.getItem(); Collection collection = submission.getCollection(); String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue"; - boolean workflow = submission instanceof WorkflowItem; + boolean disableFileEditing = (submissionInfo.isInWorkflow()) && !ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit"); Bundle[] bundles = item.getBundles("ORIGINAL"); Bitstream[] bitstreams = new Bitstream[0]; if (bundles.length > 0) @@ -202,7 +203,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep List upload = null; - if (!workflow) + if (!disableFileEditing) { // Only add the upload capabilities for new item submissions upload = div.addList("submit-upload-new", List.TYPE_FORM); @@ -257,7 +258,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep // Part B: // If the user has already uploaded files provide a list for the user. - if (bitstreams.length > 0 || workflow) + if (bitstreams.length > 0 || disableFileEditing) { Table summary = div.addTable("submit-upload-summary",(bitstreams.length * 2) + 2,7); summary.setHead(T_head2); @@ -294,7 +295,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep primary.setOptionSelected(String.valueOf(id)); } - if (!workflow) + if (!disableFileEditing) { // Workflow users can not remove files. CheckBox remove = row.addCell().addCheckBox("remove"); @@ -358,7 +359,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep checksumCell.addContent(algorithm + ":" + checksum); } - if (!workflow) + if (!disableFileEditing) { // Workflow users can not remove files. Row actionRow = summary.addRow(); diff --git a/dspace-xmlui/dspace-xmlui-webapp/src/main/webapp/i18n/messages.xml b/dspace-xmlui/dspace-xmlui-webapp/src/main/webapp/i18n/messages.xml index 753af1eb79..4a0d8fa3f0 100644 --- a/dspace-xmlui/dspace-xmlui-webapp/src/main/webapp/i18n/messages.xml +++ b/dspace-xmlui/dspace-xmlui-webapp/src/main/webapp/i18n/messages.xml @@ -1599,6 +1599,7 @@ Submitters Default read access (system administrators only) +
(Repository level group, system administrators only)
(you are not allowed to configure this) diff --git a/dspace/config/input-forms.dtd b/dspace/config/input-forms.dtd index a32cd2fcba..fa39dd9e3f 100644 --- a/dspace/config/input-forms.dtd +++ b/dspace/config/input-forms.dtd @@ -14,7 +14,7 @@ - + @@ -51,3 +51,5 @@ + + diff --git a/dspace/config/modules/workflow.cfg b/dspace/config/modules/workflow.cfg index 737b930685..65c4bffc74 100644 --- a/dspace/config/modules/workflow.cfg +++ b/dspace/config/modules/workflow.cfg @@ -10,3 +10,7 @@ # xmlworkflow = New (as of 1.8.0) Configurable Reviewer Workflow workflow.framework=originalworkflow #workflow.framework=xmlworkflow + +#Allow the reviewers to add/edit/remove files from the submission +#When changing this property you might want to alert submitters in the license that reviewers can alter their files +reviewer.file-edit=false \ No newline at end of file