diff --git a/doc/release-notes/12468-prov-fixes.md b/doc/release-notes/12468-prov-fixes.md new file mode 100644 index 00000000000..3235ecb7203 --- /dev/null +++ b/doc/release-notes/12468-prov-fixes.md @@ -0,0 +1,6 @@ +This release resolves two older issues about provenance files and improves the related documentation. + +When uploading a wrong provenance JSON, the user was still able to click on the preview button which caused an exception. +From now on, this button will not be available. Also, the error message about the wrong JSON now includes information about what the error actually is. + +The user guide and the GUI now explicitly state that Dataverse only accepts the PROV-JSON format. diff --git a/doc/sphinx-guides/source/user/dataset-management.rst b/doc/sphinx-guides/source/user/dataset-management.rst index 17eff033882..a50caa69545 100755 --- a/doc/sphinx-guides/source/user/dataset-management.rst +++ b/doc/sphinx-guides/source/user/dataset-management.rst @@ -627,7 +627,7 @@ A **Provenance File** is the preferred way of submitting provenance information Once you upload a provenance file, the Dataverse installation will need some additional information in order to accurately connect it to your data file. Once provenance file upload finishes, an input box labeled "Connect entity" will appear under the file. Provenance files contain a list of "entities", which include your data file as well as any objects associated with it (e.g. a chart, a spellchecker, etc.). You will need to tell the Dataverse installation which entity within the provenance file represents your data file. You may type the name of the entity into the box, or click the arrow next to the box and select the entity from a list of all entities in the provenance file. -For more information on entities and the contents of provenance files, see `the W3C PROV Model Primer `_. +For more information on entities and the contents of provenance files, see `the W3C PROV Model Primer `_. The uploaded file must be in JSON format as described in `the PROV-JSON specification `_. Once you've uploaded your Provenance File and connected the proper entity, you can hit the Preview button to view the raw JSON of the Provenance File. This can help you confirm that you've uploaded the right file. Be sure to double-check it, because the Provenance File will made *permanent* once it's finalized. At that point you will not be able to *replace*, *remove*, or otherwise *edit* the Provenance File. This ensures that the Provenance File maintains a stable, immutable record of the data file's history. This finalization of the Provenance File happens at different points depending on the status of your data file. If this is a brand new data file that has never been published before, then its associated Provenance File will be made permanent once you publish the dataset. If this data file *has* been published in a previous version of your dataset, then its associated Provenance File will be made permanent as soon as you upload the Provenance File and click "Save Changes" on the warning popup. diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Prov.java b/src/main/java/edu/harvard/iq/dataverse/api/Prov.java index 7f81ca20988..77221fd6500 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Prov.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Prov.java @@ -59,8 +59,9 @@ public Response addProvJson(@Context ContainerRequestContext crc, String body, @ return error(FORBIDDEN, BundleUtil.getStringFromBundle("api.prov.error.jsonUpdateNotAllowed")); } - if(!provUtil.isProvValid(body)) { - return error(BAD_REQUEST, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); + var schemaErrorMessages = provUtil.isProvValid(body); + if(!schemaErrorMessages.isEmpty()) { + return error(BAD_REQUEST, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError") + schemaErrorMessages.get()); } /*Add when we actually integrate provCpl*/ diff --git a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java index c2eecb90d9e..09da1bb2dbe 100644 --- a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java +++ b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvInvestigator.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.logging.Logger; import jakarta.json.JsonObject; +import java.util.Optional; import org.everit.json.schema.Schema; import org.everit.json.schema.ValidationException; import org.everit.json.schema.loader.SchemaLoader; @@ -114,18 +115,18 @@ public String getPrettyJsonString(JsonObject jsonObject) { return gson.toJson(je); } - public boolean isProvValid(String jsonInput) { + public Optional isProvValid(String jsonInput) { try { schema.validate(new JSONObject(jsonInput)); // throws a ValidationException if this object is invalid } catch (ValidationException vx) { logger.info("Prov schema error : " + vx); //without classLoader is blows up in actual deployment - return false; + return Optional.of(vx.getAllMessages().toString()); } catch (Exception ex) { logger.info("Prov file error : " + ex); - return false; + return Optional.of(ex.getMessage()); } - return true; + return Optional.empty(); } //Pulled from https://www.w3.org/Submission/2013/SUBM-prov-json-20130424/schema diff --git a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java index a8b28d2d79d..b26bc952464 100644 --- a/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/provenance/ProvPopupFragmentBean.java @@ -95,14 +95,13 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { provJsonState = IOUtils.toString(jsonUploadedTempFile.getInputStream()); - if(!provUtil.isProvValid(provJsonState)) { //if uploaded prov-json does not comply with schema + provUtil.isProvValid(provJsonState).ifPresentOrElse(message -> { //if uploaded prov-json does not comply with schema Logger.getLogger(ProvPopupFragmentBean.class.getName()) .log(Level.INFO, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); + provJsonState = null; removeJsonAndRelatedData(); - JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError")); - } - - else { + JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.invalidSchemaError"), "Reason: " + message); + }, () -> { try { generateProvJsonParsedEntities(); @@ -116,7 +115,7 @@ public void handleFileUpload(FileUploadEvent event) throws IOException { removeJsonAndRelatedData(); JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("file.editProvenanceDialog.noEntitiesError")); } - } + }); } diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 0825816048d..474b51281d0 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2538,9 +2538,9 @@ file.editProvenanceDialog.tip=Provenance is a record of the origin of your data file.editProvenanceDialog.uploadSuccess=Upload complete file.editProvenanceDialog.uploadError=An error occurred during upload and parsing of your provenance file. file.editProvenanceDialog.noEntitiesError=The uploaded provenance file does not contain any entities that can be related to your Data File. -file.editProvenanceDialog.invalidSchemaError=The uploaded provenance file does not comply with the W3C Provenance standard. +file.editProvenanceDialog.invalidSchemaError=The uploaded provenance file does not comply with the PROV-JSON specification. file.editProvenanceDialog.bundleFile=Provenance File -file.editProvenanceDialog.bundleFile.instructions=File must be JSON format and follow the W3C standard. +file.editProvenanceDialog.bundleFile.instructions=File must be in JSON format and follow the PROV-JSON specification. file.editProvenanceDialog.bundleFile.alreadyPublished=This Provenance File has been published and cannot be replaced or removed. file.editProvenanceDialog.bundleEntity=Data File Entity file.editProvenanceDialog.bundleEntity.placeholder=Connect entity... diff --git a/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java b/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java index f59f686a94c..f42b3487983 100644 --- a/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/provenance/ProvInvestigatorTest.java @@ -68,7 +68,7 @@ public void testProvValidator() { " }\n" + "}"; - assertTrue(provUtilBean.isProvValid(validJsonString)); + assertTrue(provUtilBean.isProvValid(validJsonString).isEmpty()); //This string has the "entity" section misnamed to "entitddd" String invalidJsonString = "{\n" + @@ -102,7 +102,7 @@ public void testProvValidator() { " }\n" + "}"; - assertFalse(provUtilBean.isProvValid(invalidJsonString)); + assertFalse(provUtilBean.isProvValid(invalidJsonString).isEmpty()); }