Skip to content

Commit d2bc7b3

Browse files
committed
Fix Publish and Subit for Review when no files are present in Dataset Version
1 parent da0ed77 commit d2bc7b3

11 files changed

Lines changed: 133 additions & 28 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## Bug: Publish and Submit for review must contain files
2+
When `requireFilesToPublishDataset` is set on a Dataverse a Dataset must contain files to be published or submitted for review. This fix make sure the dataset version contains files, and not just the dataset. It also adds this check to the `Submit for Review` functionality.

doc/sphinx-guides/source/api/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ This API changelog is experimental and we would love feedback on its usefulness.
77
:local:
88
:depth: 1
99

10+
v6.11
11+
-----
12+
13+
- The following API will now return ``403`` if the ``requireFilesToPublishDataset`` flag is set and the dataset version contains 0 files.
14+
15+
- **/api/datasets/{Id}/submitForReview**
16+
1017
v6.10
1118
-----
1219
- The following GET APIs will now return ``400`` if a required Guestbook Response is not supplied. A Guestbook Response can be passed to these APIs in the JSON body using a POST call. See the notes under :ref:`basic-file-access` and :ref:`download-by-dataset-by-version` for details.

doc/sphinx-guides/source/api/native-api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ The following attributes are supported:
12781278
* ``description`` Description
12791279
* ``affiliation`` Affiliation
12801280
* ``filePIDsEnabled`` ("true" or "false") Restricted to use by superusers and only when the :ref:`:AllowEnablingFilePIDsPerCollection <:AllowEnablingFilePIDsPerCollection>` setting is true. Enables or disables registration of file-level PIDs in datasets within the collection (overriding the instance-wide setting).
1281-
* ``requireFilesToPublishDataset`` ("true" or "false") Restricted to use by superusers. Defines if Dataset needs files in order to be published. If not set the determination will be made through inheritance by checking the owners of this collection. Publishing by a superusers will not be blocked.
1281+
* ``requireFilesToPublishDataset`` ("true" or "false") Restricted to use by superusers. Defines if Dataset version needs files in order to be published or submitted for review. If not set the determination will be made through inheritance by checking the owners of this collection. Publishing by a superusers will not be blocked.
12821282
* ``allowedDatasetTypes`` Restricted to use by superusers. By default "dataset" is implied. Pass a comma-separated list of dataset types (e.g. "dataset,software"). You cannot unset this attribute so if you want to delete a dataset type, set ``allowedDatasetTypes`` to a dataset type you won't be deleting. See also :ref:`dataset-types`.
12831283

12841284
See also :ref:`update-dataverse-api`.

src/main/java/edu/harvard/iq/dataverse/PermissionsWrapper.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
1313
import edu.harvard.iq.dataverse.engine.command.impl.*;
1414
import java.util.HashMap;
15+
import java.util.List;
1516
import java.util.Map;
1617
import java.util.logging.Logger;
1718
import jakarta.ejb.EJB;
@@ -253,9 +254,34 @@ public boolean canIssueDeleteDatasetCommand(DvObject dvo){
253254

254255
// PUBLISH DATASET
255256
public boolean canIssuePublishDatasetCommand(DvObject dvo){
257+
// Return false if dataset has 0 files and user want to 'publish' or 'submit for review' and 'publish dataset requires files' flag is set
258+
if (dvo.isInstanceofDataset()) {
259+
Dataverse dv =((Dataset)dvo).getOwner();
260+
if (dv != null) {
261+
List<FileMetadata> metadataList = ((Dataset) dvo).getLatestVersion().getFileMetadatas();
262+
if (metadataList.size() == 0 && dv.getEffectiveRequiresFilesToPublishDataset()) {
263+
return false;
264+
}
265+
}
266+
}
256267
return canIssueCommand(dvo, PublishDatasetCommand.class);
257268
}
258-
269+
270+
// SUBMIT DATASET FOR REVIEW
271+
public boolean canIssueSubmitDatasetForReviewCommand(DvObject dvo){
272+
// Return false if dataset has 0 files and user want to 'publish' or 'submit for review' and 'publish dataset requires files' flag is set
273+
if (dvo.isInstanceofDataset()) {
274+
Dataverse dv =((Dataset)dvo).getOwner();
275+
if (dv != null) {
276+
List<FileMetadata> metadataList = ((Dataset) dvo).getLatestVersion().getFileMetadatas();
277+
if (metadataList.size() == 0 && dv.getEffectiveRequiresFilesToPublishDataset()) {
278+
return false;
279+
}
280+
}
281+
}
282+
return canIssueCommand(dvo, SubmitDatasetForReviewCommand.class);
283+
}
284+
259285
// For the dataverse_header fragment (and therefore, most of the pages),
260286
// we need to know if authenticated users can add dataverses and datasets to the
261287
// root collection. For the "Add Data" menu further in the search include fragment

src/main/java/edu/harvard/iq/dataverse/engine/command/impl/AbstractDatasetCommand.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,4 +315,14 @@ protected void registerExternalVocabValuesIfAny(CommandContext ctxt, DatasetVers
315315
}
316316
}
317317
}
318+
319+
// To block Publishing dataset or Submitting dataset for review
320+
protected boolean getEffectiveRequiresFilesToPublishDataset() {
321+
if (getUser().isSuperuser()) {
322+
return false;
323+
} else {
324+
Dataverse dv = getDataset().getOwner();
325+
return dv != null && dv.getEffectiveRequiresFilesToPublishDataset();
326+
}
327+
}
318328
}

src/main/java/edu/harvard/iq/dataverse/engine/command/impl/PublishDatasetCommand.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package edu.harvard.iq.dataverse.engine.command.impl;
22

3-
import edu.harvard.iq.dataverse.Dataset;
4-
import edu.harvard.iq.dataverse.DatasetLock;
5-
import edu.harvard.iq.dataverse.Dataverse;
3+
import edu.harvard.iq.dataverse.*;
64
import edu.harvard.iq.dataverse.authorization.Permission;
75
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
86
import edu.harvard.iq.dataverse.engine.command.CommandContext;
@@ -17,6 +15,7 @@
1715

1816
import jakarta.persistence.OptimisticLockException;
1917

18+
import java.util.List;
2019
import java.util.Optional;
2120
import java.util.logging.Level;
2221
import java.util.logging.Logger;
@@ -233,19 +232,12 @@ private void verifyCommandArguments(CommandContext ctxt) throws IllegalCommandEx
233232
throw new IllegalCommandException("Cannot release as minor version. Re-try as major release.", this);
234233
}
235234

236-
if (getDataset().getFiles().isEmpty() && getEffectiveRequiresFilesToPublishDataset()) {
235+
List<FileMetadata> files = getDataset().getLatestVersion().getFileMetadatas();
236+
if ((files == null || files.isEmpty()) && getEffectiveRequiresFilesToPublishDataset()) {
237237
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dataset.mayNotPublish.FilesRequired"), this);
238238
}
239239
}
240240
}
241-
private boolean getEffectiveRequiresFilesToPublishDataset() {
242-
if (getUser().isSuperuser()) {
243-
return false;
244-
} else {
245-
Dataverse dv = getDataset().getOwner();
246-
return dv != null && dv.getEffectiveRequiresFilesToPublishDataset();
247-
}
248-
}
249241

250242
@Override
251243
public boolean onSuccess(CommandContext ctxt, Object r) {

src/main/java/edu/harvard/iq/dataverse/engine/command/impl/SubmitDatasetForReviewCommand.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
package edu.harvard.iq.dataverse.engine.command.impl;
22

3-
import edu.harvard.iq.dataverse.Dataset;
4-
import edu.harvard.iq.dataverse.DatasetLock;
5-
import edu.harvard.iq.dataverse.DatasetVersionUser;
6-
import edu.harvard.iq.dataverse.UserNotification;
3+
import edu.harvard.iq.dataverse.*;
74
import edu.harvard.iq.dataverse.authorization.Permission;
85
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
9-
import edu.harvard.iq.dataverse.batch.util.LoggingUtil;
10-
import edu.harvard.iq.dataverse.engine.command.AbstractCommand;
116
import edu.harvard.iq.dataverse.engine.command.CommandContext;
127
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
138
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
149
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
1510
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
1611
import edu.harvard.iq.dataverse.util.BundleUtil;
17-
import java.io.IOException;
1812
import java.sql.Timestamp;
1913
import java.util.Date;
2014
import java.util.List;
21-
import java.util.concurrent.Future;
22-
import org.apache.solr.client.solrj.SolrServerException;
2315

2416
@RequiredPermissions(Permission.EditDataset)
2517
public class SubmitDatasetForReviewCommand extends AbstractDatasetCommand<Dataset> {
@@ -41,6 +33,11 @@ public Dataset execute(CommandContext ctxt) throws CommandException {
4133
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dataset.submit.failure.inReview"), this);
4234
}
4335

36+
List<FileMetadata> files = getDataset().getLatestVersion().getFileMetadatas();
37+
if ((files == null || files.isEmpty()) && getEffectiveRequiresFilesToPublishDataset()) {
38+
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dataset.mayNotSubmitForReview.FilesRequired"), this);
39+
}
40+
4441
//SEK 9-1 Add Lock before saving dataset
4542
DatasetLock inReviewLock = new DatasetLock(DatasetLock.Reason.InReview, getRequest().getAuthenticatedUser());
4643
ctxt.engine().submit(new AddLockCommand(getRequest(), getDataset(), inReviewLock));

src/main/java/propertyFiles/Bundle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,7 @@ dataset.mayNotPublish.both= This dataset cannot be published until {0} is publis
16361636
dataset.mayNotPublish.twoGenerations= This dataset cannot be published until {0} and {1} are published.
16371637
dataset.mayNotBePublished.both.button=Yes, Publish Both
16381638
dataset.mayNotPublish.FilesRequired=Published datasets should contain at least one data file.
1639+
dataset.mayNotSubmitForReview.FilesRequired=The dataset must contain at least one data file in order to be submitted for review.
16391640
dataset.viewVersion.unpublished=View Unpublished Version
16401641
dataset.viewVersion.published=View Published Version
16411642
dataset.link.title=Link Dataset

src/main/webapp/dataset.xhtml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
<ui:param name="canUpdateDataset" value="#{DatasetPage.canUpdateDataset()}"/>
2828
<ui:param name="canDownloadFiles" value="#{DatasetPage.canDownloadFiles()}"/>
2929
<ui:param name="canIssuePublishDatasetCommand" value="#{permissionsWrapper.canIssuePublishDatasetCommand(DatasetPage.dataset)}"/>
30-
<ui:param name="showPublishLink" value="#{version == DatasetPage.dataset.latestVersion
30+
<ui:param name="canIssueSubmitDatasetForReviewCommand" value="#{permissionsWrapper.canIssueSubmitDatasetForReviewCommand(DatasetPage.dataset)}"/>
31+
<ui:param name="showPublishLink" value="#{version == DatasetPage.dataset.latestVersion
3132
and DatasetPage.dataset.latestVersion.versionState=='DRAFT'
3233
and canIssuePublishDatasetCommand}"/>
3334
<ui:param name="versionHasTabular" value="#{DatasetPage.versionHasTabular}"/>
@@ -56,7 +57,8 @@
5657
and !DatasetPage.datasetLockedInWorkflow
5758
and DatasetPage.dataset.latestVersion.versionState=='DRAFT'
5859
and canUpdateDataset
59-
and !canIssuePublishDatasetCommand}"/>
60+
and !canIssuePublishDatasetCommand
61+
and canIssueSubmitDatasetForReviewCommand}"/>
6062
<ui:param name="showReturnToAuthorLink" value="#{DatasetPage.dataset.latestVersion.versionState=='DRAFT' and latestVersionInReview
6163
and canIssuePublishDatasetCommand}"/>
6264
<ui:param name="showAccessDatasetButtonGroup" value="#{(canDownloadFiles or versionHasGlobus)
@@ -358,7 +360,7 @@
358360
<!-- END: DOWNLOAD/ACCESS DATASET -->
359361

360362
<!-- PUBLISH DATASET -->
361-
<div class="btn-group btn-group-justified" jsf:rendered="#{showPublishLink or showSubmitForReviewLink}">
363+
<div class="btn-group btn-group-justified" jsf:rendered="#{showSubmitForReviewLink or showReturnToAuthorLink or showPublishLink or latestVersionInReview}">
362364
<div class="btn-group">
363365
<!-- Publish BTN -->
364366
<h:outputLink value="#" disabled="#{DatasetPage.lockedFromPublishing or !DatasetPage.hasValidTermsOfAccess or !valid}">
@@ -372,7 +374,7 @@
372374
<f:passThroughAttribute name="aria-haspopup" value="true"/>
373375
<f:passThroughAttribute name="aria-expanded" value="false"/>
374376
</c:if>
375-
#{showPublishLink ? bundle['dataset.publishBtn'] : (latestVersionInReview ? bundle['dataset.disabledSubmittedBtn'] : bundle['dataset.submitBtn'])} <span jsf:rendered="#{(showSubmitForReviewLink or showReturnToAuthorLink) and showPublishLink}" class="caret"></span>
377+
#{showPublishLink ? bundle['dataset.publishBtn'] : (latestVersionInReview ? bundle['dataset.disabledSubmittedBtn'] : bundle['dataset.submitBtn'])} <span jsf:rendered="#{(showSubmitForReviewLink or showReturnToAuthorLink or showPublishLink or latestVersionInReview)}" class="caret"></span>
376378
</h:outputLink>
377379
<!-- Publish BTN DROPDOWN-MENU OPTIONS -->
378380
<ul class="dropdown-menu pull-right text-left">

src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6868,10 +6868,22 @@ public void testRequireFilesToPublishDatasets() {
68686868
String pathToFile = "src/main/webapp/resources/images/dataverseproject.png";
68696869
Response uploadResponse = UtilIT.uploadFileViaNative(String.valueOf(id), pathToFile, apiToken);
68706870
uploadResponse.then().assertThat().statusCode(OK.getStatusCode());
6871+
Integer fileId = UtilIT.getDataFileIdFromResponse(uploadResponse);
68716872

68726873
publishDatasetResponse = UtilIT.publishDatasetViaNativeApi(String.valueOf(id), "major", apiToken);
68736874
publishDatasetResponse.prettyPrint();
68746875
publishDatasetResponse.then().assertThat().statusCode(OK.getStatusCode());
6876+
6877+
// Remove the file and try to publish again. Dataset still has a file but the new version has none
6878+
Response deleteResponse = UtilIT.deleteFileInDataset(fileId, apiToken);
6879+
deleteResponse.prettyPrint();
6880+
deleteResponse.then().assertThat().statusCode(OK.getStatusCode());
6881+
6882+
publishDatasetResponse = UtilIT.publishDatasetViaNativeApi(String.valueOf(id), "major", apiToken);
6883+
publishDatasetResponse.prettyPrint();
6884+
publishDatasetResponse.then().assertThat()
6885+
.statusCode(FORBIDDEN.getStatusCode())
6886+
.body("message", containsString( BundleUtil.getStringFromBundle("dataset.mayNotPublish.FilesRequired")));
68756887
}
68766888

68776889
@Test

0 commit comments

Comments
 (0)