From 3cfe06231ea0d26151a68c939bedaec2b8c5b406 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Wed, 30 Mar 2022 17:15:30 -0400 Subject: [PATCH 1/8] remove NONE as a license for SWORD, show available licenses #8551 --- .../source/api/sword-atom-entry.xml | 4 +- doc/sphinx-guides/source/api/sword.rst | 4 +- .../api/datadeposit/SwordServiceBean.java | 9 ++- .../edu/harvard/iq/dataverse/api/SwordIT.java | 63 +++++++++++++++++++ .../edu/harvard/iq/dataverse/api/UtilIT.java | 29 ++++++++- 5 files changed, 103 insertions(+), 6 deletions(-) diff --git a/doc/sphinx-guides/source/api/sword-atom-entry.xml b/doc/sphinx-guides/source/api/sword-atom-entry.xml index d47a3dd4f56..8d73653e93e 100755 --- a/doc/sphinx-guides/source/api/sword-atom-entry.xml +++ b/doc/sphinx-guides/source/api/sword-atom-entry.xml @@ -27,8 +27,8 @@ United States Canada - NONE - Downloader will not use the Materials in any way prohibited by applicable laws. + CC0 1.0 + Peets, J., & Stumptown, J. (2013). Roasting at Home. New England Journal of Coffee, 3(1), 22-34. diff --git a/doc/sphinx-guides/source/api/sword.rst b/doc/sphinx-guides/source/api/sword.rst index d853994f073..6c31dca4263 100755 --- a/doc/sphinx-guides/source/api/sword.rst +++ b/doc/sphinx-guides/source/api/sword.rst @@ -80,7 +80,7 @@ New features as of v1.1 - "Contributor" can now be populated and the "Type" (Editor, Funder, Researcher, etc.) can be specified with an XML attribute. For example: ``CaffeineForAll`` -- "License" can now be set with ``dcterms:license`` and the possible values are "CC0" and "NONE". "License" interacts with "Terms of Use" (``dcterms:rights``) in that if you include ``dcterms:rights`` in the XML, the license will be set to "NONE". If you don't include ``dcterms:rights``, the license will default to "CC0". It is invalid to specify "CC0" as a license and also include ``dcterms:rights``; an error will be returned. For backwards compatibility, ``dcterms:rights`` is allowed to be blank (i.e. ````) but blank values will not be persisted to the database and the license will be set to "NONE". +- "License" can now be set with ``dcterms:license`` and the possible values determined by the installation ("CC0 1.0" and "CC BY 4.0" by default). "License" interacts with "Terms of Use" (``dcterms:rights``) in that if you include ``dcterms:rights`` in the XML, the license will be "Custom Dataset Terms". If you don't include ``dcterms:rights``, the default license will be used. It is invalid to specify a license and also include ``dcterms:rights``; an error will be returned. For backwards compatibility, ``dcterms:rights`` is allowed to be blank (i.e. ````) but blank values will not be persisted to the database and the license will be set to "Custom Dataset Terms". - "Contact E-mail" is automatically populated from dataset owner's email. @@ -143,7 +143,7 @@ Dublin Core Terms (DC Terms) Qualified Mapping - Dataverse Project DB Element Cr +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |dcterms:coverage | otherGeographicCoverage | | General information on the geographic coverage of the Dataset. | +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|dcterms:license | license | | Set the license to CC0 (default in a Dataverse installation for new Datasets), otherwise enter "NONE" and fill in the dcterms:rights field. | +|dcterms:license | license | | Set the license. Alternatively, use the dcterms:rights field instead. | +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |dcterms:rights | termsofuse | | If not using CC0, enter any terms of use or restrictions for the Dataset. | +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java index 7e45381d410..7e7f17e58a5 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java @@ -12,6 +12,7 @@ import edu.harvard.iq.dataverse.license.License; import edu.harvard.iq.dataverse.license.LicenseServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -186,7 +187,13 @@ public void setDatasetLicenseAndTermsOfUse(DatasetVersion datasetVersionToMutate setTermsOfUse(datasetVersionToMutate, dcterms, null); } else { License licenseToSet = licenseServiceBean.getByNameOrUri(licenseProvided); - if (licenseToSet == null) throw new SwordError("Couldn't find an active license with: " + licenseProvided); + if (licenseToSet == null) { + List licenses = new ArrayList<>(); + for (License license : licenseServiceBean.listAllActive()) { + licenses.add(license.getName()); + } + throw new SwordError("Couldn't find an active license with: " + licenseProvided + ". Valid licenses: " + licenses); + } terms.setLicense(licenseToSet); setTermsOfUse(datasetVersionToMutate, dcterms, licenseToSet); } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java index ea6709cb915..a77924f6114 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java @@ -5,6 +5,9 @@ import com.jayway.restassured.response.Response; import edu.harvard.iq.dataverse.GlobalId; import edu.harvard.iq.dataverse.api.datadeposit.SwordConfigurationImpl; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; import java.util.List; import java.util.Map; @@ -638,6 +641,66 @@ public void testCreateDatasetPublishDestroy() { } + + @Test + public void testLicenses() { + + Response createUser = UtilIT.createRandomUser(); + String username = UtilIT.getUsernameFromResponse(createUser); + String apiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response createDataverse = UtilIT.createRandomDataverse(apiToken); + createDataverse.prettyPrint(); + createDataverse.then().assertThat() + .statusCode(CREATED.getStatusCode()); + String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse); + + String title = "License to Kill"; + String description = "Spies in 1989"; + String license = "NONE"; + Response failToCreateDataset1 = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, apiToken); + failToCreateDataset1.prettyPrint(); + // As of 5.10 and PR #7920, you cannot pass NONE as a license. + failToCreateDataset1.then().assertThat() + .statusCode(BAD_REQUEST.getStatusCode()); + + String rights = "Call me"; + Response failToCreateDataset2 = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, rights, apiToken); + failToCreateDataset2.prettyPrint(); + // You can't pass both license and rights + failToCreateDataset2.then().assertThat() + .statusCode(BAD_REQUEST.getStatusCode()); + + license = "CC0 1.0"; + Response createDataset = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, apiToken); + createDataset.prettyPrint(); + createDataset.then().assertThat() + .statusCode(CREATED.getStatusCode()); + + } + + @Test + public void testXmlExampleInGuides() throws IOException { + + Response createUser = UtilIT.createRandomUser(); + String username = UtilIT.getUsernameFromResponse(createUser); + String apiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response createDataverse = UtilIT.createRandomDataverse(apiToken); + createDataverse.prettyPrint(); + createDataverse.then().assertThat() + .statusCode(CREATED.getStatusCode()); + String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse); + + File exampleFile = new File("doc/sphinx-guides/source/api/sword-atom-entry.xml"); + String xmlIn = new String(java.nio.file.Files.readAllBytes(Paths.get(exampleFile.getAbsolutePath()))); + Response createDataset = UtilIT.createDatasetViaSwordApiFromXML(dataverseAlias, xmlIn, apiToken); + createDataset.prettyPrint(); + createDataset.then().assertThat() + .statusCode(CREATED.getStatusCode()); + + } + /** * This test requires the root dataverse to have been published already. * diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 23672c45916..7b9b5f3b129 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -436,7 +436,18 @@ static Response createDatasetViaSwordApi(String dataverseToCreateDatasetIn, Stri return createDatasetViaSwordApiFromXML(dataverseToCreateDatasetIn, xmlIn, apiToken); } - private static Response createDatasetViaSwordApiFromXML(String dataverseToCreateDatasetIn, String xmlIn, String apiToken) { + static Response createDatasetViaSwordApi(String dataverseToCreateDatasetIn, String title, String description, String license, String apiToken) { + String nullRights = null; + String xmlIn = getDatasetXml(title, "Lastname, Firstname", description, license, nullRights); + return createDatasetViaSwordApiFromXML(dataverseToCreateDatasetIn, xmlIn, apiToken); + } + + static Response createDatasetViaSwordApi(String dataverseToCreateDatasetIn, String title, String description, String license, String rights, String apiToken) { + String xmlIn = getDatasetXml(title, "Lastname, Firstname", description, license, rights); + return createDatasetViaSwordApiFromXML(dataverseToCreateDatasetIn, xmlIn, apiToken); + } + + public static Response createDatasetViaSwordApiFromXML(String dataverseToCreateDatasetIn, String xmlIn, String apiToken) { Response createDatasetResponse = given() .auth().basic(apiToken, EMPTY_STRING) .body(xmlIn) @@ -534,11 +545,27 @@ static Response loadMetadataBlock(String apiToken, byte[] body) { } static private String getDatasetXml(String title, String author, String description) { + String nullLicense = null; + String nullRights = null; + return getDatasetXml(title, author, description, nullLicense, nullRights); + } + + static private String getDatasetXml(String title, String author, String description, String license, String rights) { + String optionalLicense = ""; + if (license != null) { + optionalLicense = " " + license + "\n"; + } + String optionalRights = ""; + if (rights != null) { + optionalRights = " " + rights + "\n"; + } String xmlIn = "\n" + "\n" + " " + title + "\n" + " " + author + "\n" + " " + description + "\n" + + optionalLicense + + optionalRights + "\n" + ""; return xmlIn; From 66eabc06e30139590ac1aaeecc4faa73f98055f1 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 31 Mar 2022 11:34:13 -0400 Subject: [PATCH 2/8] report error if license is inactive #8551 --- .../harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java index 7e7f17e58a5..0ccd451946e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java @@ -187,7 +187,7 @@ public void setDatasetLicenseAndTermsOfUse(DatasetVersion datasetVersionToMutate setTermsOfUse(datasetVersionToMutate, dcterms, null); } else { License licenseToSet = licenseServiceBean.getByNameOrUri(licenseProvided); - if (licenseToSet == null) { + if (licenseToSet == null || !licenseToSet.isActive()) { List licenses = new ArrayList<>(); for (License license : licenseServiceBean.listAllActive()) { licenses.add(license.getName()); From a97e788562105080c35842b1449454b86d6b6091 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 31 Mar 2022 11:37:00 -0400 Subject: [PATCH 3/8] add assertions on licenses and terms of use #8551 --- .../edu/harvard/iq/dataverse/api/SwordIT.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java index a77924f6114..29173d3bd76 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java @@ -198,6 +198,13 @@ public void testCreateDataverseCreateDatasetUploadFileDownloadFileEditTitle() { String persistentId = UtilIT.getDatasetPersistentIdFromSwordResponse(createDatasetResponse); logger.info("persistent id: " + persistentId); + Response getJson = UtilIT.nativeGetUsingPersistentId(persistentId, apiToken); + getJson.prettyPrint(); + getJson.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data.latestVersion.license.name", equalTo("CC0 1.0")) + .body("data.latestVersion.license.uri", equalTo("http://creativecommons.org/publicdomain/zero/1.0")); + Response atomEntryUnAuth = UtilIT.getSwordAtomEntry(persistentId, apiTokenNoPrivs); atomEntryUnAuth.prettyPrint(); atomEntryUnAuth.then().assertThat() @@ -677,6 +684,47 @@ public void testLicenses() { createDataset.then().assertThat() .statusCode(CREATED.getStatusCode()); + String persistentId = UtilIT.getDatasetPersistentIdFromSwordResponse(createDataset); + + Response getJson = UtilIT.nativeGetUsingPersistentId(persistentId, apiToken); + getJson.prettyPrint(); + getJson.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data.latestVersion.license.name", equalTo("CC0 1.0")) + .body("data.latestVersion.license.uri", equalTo("http://creativecommons.org/publicdomain/zero/1.0")) + .body("data.latestVersion.termsOfUse", equalTo(null)); + } + + @Test + public void testCustomTerms() { + + Response createUser = UtilIT.createRandomUser(); + String username = UtilIT.getUsernameFromResponse(createUser); + String apiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response createDataverse = UtilIT.createRandomDataverse(apiToken); + createDataverse.prettyPrint(); + createDataverse.then().assertThat() + .statusCode(CREATED.getStatusCode()); + String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse); + + String title = "Terms of Endearment"; + String description = "Aurora, etc."; + String license = null; + String rights = "Call me"; + Response createDataset = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, rights, apiToken); + createDataset.prettyPrint(); + createDataset.then().assertThat() + .statusCode(CREATED.getStatusCode()); + + String persistentId = UtilIT.getDatasetPersistentIdFromSwordResponse(createDataset); + + Response getJson = UtilIT.nativeGetUsingPersistentId(persistentId, apiToken); + getJson.prettyPrint(); + getJson.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data.latestVersion.termsOfUse", equalTo("Call me")) + .body("data.latestVersion.license", equalTo(null)); } @Test From b3724f070db3a7d606e63751774127b054fa845f Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 31 Mar 2022 11:37:33 -0400 Subject: [PATCH 4/8] explain NONE is no longer supported, remove CC0 mention #8551 --- doc/sphinx-guides/source/api/sword.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/sword.rst b/doc/sphinx-guides/source/api/sword.rst index 6c31dca4263..106741e4b47 100755 --- a/doc/sphinx-guides/source/api/sword.rst +++ b/doc/sphinx-guides/source/api/sword.rst @@ -65,6 +65,8 @@ Differences in Dataverse Software 4 from DVN 3.x lead to a few minor backward in - The Service Document will show a single API Terms of Use rather than root level and Dataverse collection level Deposit Terms of Use. +- As of Dataverse Software 5.10, ``NONE`` is no longer supported as a license. + New features as of v1.1 ----------------------- @@ -145,7 +147,7 @@ Dublin Core Terms (DC Terms) Qualified Mapping - Dataverse Project DB Element Cr +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |dcterms:license | license | | Set the license. Alternatively, use the dcterms:rights field instead. | +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|dcterms:rights | termsofuse | | If not using CC0, enter any terms of use or restrictions for the Dataset. | +|dcterms:rights | termsofuse | | If not using dcterms:license, enter any terms of use or restrictions for the Dataset. | +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |dcterms:isReferencedBy | publicationCitation | | The publication (journal article, book, other work) that uses this dataset (include citation, permanent identifier (DOI), and permanent URL). | +-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ From 6c6f842954bd3a5dce5c138af0c2a86c43502813 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 31 Mar 2022 11:41:26 -0400 Subject: [PATCH 5/8] add release note #8551 --- doc/release-notes/8551-sword-license.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/release-notes/8551-sword-license.md diff --git a/doc/release-notes/8551-sword-license.md b/doc/release-notes/8551-sword-license.md new file mode 100644 index 00000000000..90b7180ac77 --- /dev/null +++ b/doc/release-notes/8551-sword-license.md @@ -0,0 +1 @@ +As of Dataverse 5.10, "NONE" is no longer supported as a valid license when creating a dataset using the SWORD API. The API Guide has been updated to reflect this. Additionally, if you specify an invalid license, a list of available licenses will be returned in the response. From 7517c78f255b2937c24624330a97394a5db179c2 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Thu, 31 Mar 2022 11:44:55 -0400 Subject: [PATCH 6/8] clarify how to set "Terms of Use" #8551 --- doc/sphinx-guides/source/api/sword.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/sword.rst b/doc/sphinx-guides/source/api/sword.rst index 106741e4b47..d4f56ddb5b4 100755 --- a/doc/sphinx-guides/source/api/sword.rst +++ b/doc/sphinx-guides/source/api/sword.rst @@ -82,7 +82,7 @@ New features as of v1.1 - "Contributor" can now be populated and the "Type" (Editor, Funder, Researcher, etc.) can be specified with an XML attribute. For example: ``CaffeineForAll`` -- "License" can now be set with ``dcterms:license`` and the possible values determined by the installation ("CC0 1.0" and "CC BY 4.0" by default). "License" interacts with "Terms of Use" (``dcterms:rights``) in that if you include ``dcterms:rights`` in the XML, the license will be "Custom Dataset Terms". If you don't include ``dcterms:rights``, the default license will be used. It is invalid to specify a license and also include ``dcterms:rights``; an error will be returned. For backwards compatibility, ``dcterms:rights`` is allowed to be blank (i.e. ````) but blank values will not be persisted to the database and the license will be set to "Custom Dataset Terms". +- "License" can now be set with ``dcterms:license`` and the possible values determined by the installation ("CC0 1.0" and "CC BY 4.0" by default). "License" interacts with "Terms of Use" (``dcterms:rights``) in that if you include ``dcterms:rights`` in the XML and don't include ``dcterms:license``, the license will be "Custom Dataset Terms" and "Terms of Use" will be populated. If you don't include ``dcterms:rights``, the default license will be used. It is invalid to specify a license and also include ``dcterms:rights``; an error will be returned. For backwards compatibility, ``dcterms:rights`` is allowed to be blank (i.e. ````) but blank values will not be persisted to the database and the license will be set to "Custom Dataset Terms". - "Contact E-mail" is automatically populated from dataset owner's email. From 09e1c60334c776def406ee8a7858be2857a6f572 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 5 Apr 2022 12:31:51 -0400 Subject: [PATCH 7/8] remove "A Custom License can be used instead." #8551 --- .../harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java index 0ccd451946e..1468b50fdfb 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java @@ -211,7 +211,7 @@ private void setTermsOfUse(DatasetVersion datasetVersionToMutate, Map 0) { - throw new SwordError("Terms of Use (dcterms:rights) can not be specified in combination with a license. A Custom License can be used instead."); + throw new SwordError("Terms of Use (dcterms:rights) can not be specified in combination with a license."); } } else { if (numRightsProvided != 1) { From 3622427be0a46cf1744102c5e98f6dba4ab70356 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 5 Apr 2022 12:55:28 -0400 Subject: [PATCH 8/8] s/can not/cannot/ #8551 --- .../harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java index 1468b50fdfb..46c38e04153 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java @@ -211,7 +211,7 @@ private void setTermsOfUse(DatasetVersion datasetVersionToMutate, Map 0) { - throw new SwordError("Terms of Use (dcterms:rights) can not be specified in combination with a license."); + throw new SwordError("Terms of Use (dcterms:rights) cannot be specified in combination with a license."); } } else { if (numRightsProvided != 1) {