From 4ef477819ece95b6f621fce7f091643eeb8b8f14 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:42:48 -0400 Subject: [PATCH 01/15] adding unlink to ui and matching link permissions --- .../edu/harvard/iq/dataverse/DatasetPage.java | 45 +++++++++++ .../iq/dataverse/DataverseServiceBean.java | 14 +++- .../harvard/iq/dataverse/api/Datasets.java | 2 +- .../DeleteDatasetLinkingDataverseCommand.java | 6 +- .../command/impl/MoveDatasetCommand.java | 2 +- .../command/impl/MoveDataverseCommand.java | 2 +- src/main/java/propertyFiles/Bundle.properties | 8 ++ src/main/webapp/dataset.xhtml | 76 +++++++++++++++++++ 8 files changed, 149 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index eae4a9f2977..6d3ffb6c778 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -118,6 +118,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.engine.command.impl.AbstractSubmitToArchiveCommand; import edu.harvard.iq.dataverse.engine.command.impl.CreateNewDatasetCommand; +import edu.harvard.iq.dataverse.engine.command.impl.DeleteDatasetLinkingDataverseCommand; import edu.harvard.iq.dataverse.engine.command.impl.GetLatestPublishedDatasetVersionCommand; import edu.harvard.iq.dataverse.engine.command.impl.RequestRsyncScriptCommand; import edu.harvard.iq.dataverse.engine.command.impl.PublishDatasetResult; @@ -3562,6 +3563,16 @@ public void saveLinkingDataverses(ActionEvent evt) { } alreadyLinkedDataverses = null; //force update to list of linked dataverses } + public void deleteLinkingDataverses(ActionEvent evt) { + + if (deleteLink(selectedDataverseForLinking)) { + JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dataset.message.unlinkSuccess", getSuccessMessageArguments())); + } else { + FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, BundleUtil.getStringFromBundle("dataset.notlinked"), linkingDataverseErrorMessage); + FacesContext.getCurrentInstance().addMessage(null, message); + } + alreadyLinkedDataverses = null; //force update to list of linked dataverses + } private String linkingDataverseErrorMessage = ""; @@ -3596,6 +3607,25 @@ private Boolean saveLink(Dataverse dataverse){ } return retVal; } + private Boolean deleteLink(Dataverse dataverse){ + boolean retVal = true; + linkingDataverse = dataverse; + try { + DatasetLinkingDataverse dsld = dsLinkingService.findDatasetLinkingDataverse(dataset.getId(), linkingDataverse.getId()); + DeleteDatasetLinkingDataverseCommand cmd = new DeleteDatasetLinkingDataverseCommand(dvRequestService.getDataverseRequest(), dataset, dsld, true, true); + commandEngine.submit(cmd); + } catch (CommandException ex) { + String msg = "There was a problem removing the link between this dataset to yours: " + ex; + logger.severe(msg); + msg = BundleUtil.getStringFromBundle("dataset.notlinked.msg") + ex; + /** + * @todo how do we get this message to show up in the GUI? + */ + linkingDataverseErrorMessage = msg; + retVal = false; + } + return retVal; + } private String alreadyLinkedDataverses = null; @@ -3622,6 +3652,14 @@ public List completeLinkingDataverse(String query) { return null; } } + public List completeUnLinkingDataverse(String query) { + dataset = datasetService.find(dataset.getId()); + if (session.getUser().isAuthenticated()) { + return dataverseService.filterDataversesForUnLinking(query, dvRequestService.getDataverseRequest(), dataset); + } else { + return null; + } + } public List completeHostDataverseMenuList(String query) { if (session.getUser().isAuthenticated()) { @@ -5580,12 +5618,19 @@ public void setPrivateUrlJustCreatedToFalse() { public boolean isShowLinkingPopup() { return showLinkingPopup; } + public boolean isShowUnLinkingPopup() { + return showUnLinkingPopup; + } public void setShowLinkingPopup(boolean showLinkingPopup) { this.showLinkingPopup = showLinkingPopup; } + public void setShowUnLinkingPopup(boolean showUnLinkingPopup) { + this.showUnLinkingPopup = showUnLinkingPopup; + } private boolean showLinkingPopup = false; + private boolean showUnLinkingPopup = false; private Boolean anonymizedAccess = null; // diff --git a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java index 10b5d800c21..a1c62659e3e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java @@ -503,7 +503,19 @@ public List filterDataversesForLinking(String query, DataverseRequest return dataverseList; } - + public List filterDataversesForUnLinking(String query, DataverseRequest req, Dataset dataset) { + List alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList(); + List dataverseList = new ArrayList<>(); + if (alreadyLinkeddv_ids != null && !alreadyLinkeddv_ids.isEmpty()) { + alreadyLinkeddv_ids.stream().map((testDVId) -> this.find(testDVId)).forEachOrdered((dataverse) -> { + if (this.permissionService.requestOn(req, dataverse).has(Permission.PublishDataset)) { + dataverseList.add(dataverse); + } + }); + } + return dataverseList; + } + public List filterDataversesForHosting(String pattern, DataverseRequest req) { // Find the dataverses matching the search parameters: diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 4b919c5ed82..5abbcafc47a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -376,7 +376,7 @@ public Response deleteDraftVersion(@Context ContainerRequestContext crc, @PathPa public Response deleteDatasetLinkingDataverse(@Context ContainerRequestContext crc, @PathParam("datasetId") String datasetId, @PathParam("linkedDataverseId") String linkedDataverseId) { boolean index = true; return response(req -> { - execCommand(new DeleteDatasetLinkingDataverseCommand(req, findDatasetOrDie(datasetId), findDatasetLinkingDataverseOrDie(datasetId, linkedDataverseId), index)); + execCommand(new DeleteDatasetLinkingDataverseCommand(req, findDatasetOrDie(datasetId), findDatasetLinkingDataverseOrDie(datasetId, linkedDataverseId), index, false)); return ok("Link from Dataset " + datasetId + " to linked Dataverse " + linkedDataverseId + " deleted"); }, getRequestUser(crc)); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java index f21a2782609..30fffcfc05f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java @@ -31,17 +31,19 @@ public class DeleteDatasetLinkingDataverseCommand extends AbstractCommand + +
+ + #{bundle['dataset.unlinkBtn']} + +
+
@@ -1697,6 +1707,72 @@
+ + +
+

+ + + + + + + + + + +

+
+ +
+ + + + + + + + + + + + + +
+
+
+
+ +   + + +
+
+ + + + +
+
+
From 4dbb048b93b74094bc44fc1b45e7dae42d0eb6fd Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:47:23 -0400 Subject: [PATCH 02/15] add release notes --- ...583-dataset-unlink-functionality-same-permission-as-link.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md diff --git a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md new file mode 100644 index 00000000000..dff77aebf68 --- /dev/null +++ b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md @@ -0,0 +1,3 @@ +New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a Dataverse that was priovously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. +The unlink can still be accomplished by a superuser/Admin using the pre-existing api +`curl -s -H "X-Dataverse-key:$API_TOKEN" -X DELETE http://localhost:8080/api/datasets/$datsetId/deleteLink/$dataverseAlias` From 57bb5830ef4183bedd667cb3153f747dfbaa4dcb Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:00:23 -0400 Subject: [PATCH 03/15] Update doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md Co-authored-by: Philip Durbin --- ...0583-dataset-unlink-functionality-same-permission-as-link.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md index dff77aebf68..afb3d51a388 100644 --- a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md +++ b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md @@ -1,3 +1,3 @@ -New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a Dataverse that was priovously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. +New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a Dataverse that was previously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. The unlink can still be accomplished by a superuser/Admin using the pre-existing api `curl -s -H "X-Dataverse-key:$API_TOKEN" -X DELETE http://localhost:8080/api/datasets/$datsetId/deleteLink/$dataverseAlias` From 9bf7d6cea56df0cac7f3d73ee0d0de01797f1ad9 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:01:59 -0400 Subject: [PATCH 04/15] Update doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md Co-authored-by: Philip Durbin --- ...583-dataset-unlink-functionality-same-permission-as-link.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md index afb3d51a388..84af4a6ccad 100644 --- a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md +++ b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md @@ -1,3 +1,2 @@ New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a Dataverse that was previously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. -The unlink can still be accomplished by a superuser/Admin using the pre-existing api -`curl -s -H "X-Dataverse-key:$API_TOKEN" -X DELETE http://localhost:8080/api/datasets/$datsetId/deleteLink/$dataverseAlias` +The unlink can still be accomplished by a superuser/Admin using the [pre-existing API](https://guides.dataverse.org/en/6.3/admin/dataverses-datasets.html#unlink-a-dataset). From be7dafa6d139f5d3c40c3b5fa2490641d1e16a18 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:02:19 -0400 Subject: [PATCH 05/15] Update src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java Co-authored-by: Philip Durbin --- .../java/edu/harvard/iq/dataverse/DataverseServiceBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java index a1c62659e3e..be6fb0dcc98 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java @@ -504,7 +504,7 @@ public List filterDataversesForLinking(String query, DataverseRequest return dataverseList; } public List filterDataversesForUnLinking(String query, DataverseRequest req, Dataset dataset) { - List alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList(); + List alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList(); List dataverseList = new ArrayList<>(); if (alreadyLinkeddv_ids != null && !alreadyLinkeddv_ids.isEmpty()) { alreadyLinkeddv_ids.stream().map((testDVId) -> this.find(testDVId)).forEachOrdered((dataverse) -> { From 44f1fe582eaf1e6490ea4f3f8013e63f28da438a Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:02:32 -0400 Subject: [PATCH 06/15] Update src/main/java/propertyFiles/Bundle.properties Co-authored-by: Philip Durbin --- src/main/java/propertyFiles/Bundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index d2e4226f77e..853f5f68e69 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -914,7 +914,7 @@ dataverse.linked.success= {0} has been successfully linked to {1}. dataverse.linked.success.wait= {0} has been successfully linked to {1}. Please wait for its contents to appear. dataverse.linked.internalerror={0} has been successfully linked to {1} but contents will not appear until an internal error has been fixed. dataverse.linked.error.alreadyLinked={0} has already been linked to {1}. -dataverse.unlinked.success= {0} has been successfully un-linked from {1}. +dataverse.unlinked.success= {0} has been successfully unlinked from {1}. dataverse.page.pre=Previous dataverse.page.next=Next dataverse.byCategory=Dataverses by Category From 1e1063e1525eb43751a999b148009a1c9350f0de Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:02:42 -0400 Subject: [PATCH 07/15] Update src/main/java/propertyFiles/Bundle.properties Co-authored-by: Philip Durbin --- src/main/java/propertyFiles/Bundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 853f5f68e69..ea50f37cf23 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -1617,7 +1617,7 @@ dataset.message.createSuccess=This dataset has been created. dataset.message.createSuccess.failedToSaveFiles=Partial Success: The dataset has been created. But the file(s) could not be saved. Please try uploading the file(s) again. dataset.message.createSuccess.partialSuccessSavingFiles=Partial Success: The dataset has been created. But only {0} out of {1} files have been saved. Please try uploading the missing file(s) again. dataset.message.linkSuccess= {0} has been successfully linked to {1}. -dataset.message.unlinkSuccess= {0} has been successfully un-linked from {1}. +dataset.message.unlinkSuccess= {0} has been successfully unlinked from {1}. dataset.message.metadataSuccess=The metadata for this dataset have been updated. dataset.message.termsSuccess=The terms for this dataset have been updated. dataset.message.filesSuccess=One or more files have been updated. From 5b031bf6a74b1aa6c3c7d6d6fa58fc0e7525b25e Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:02:59 -0400 Subject: [PATCH 08/15] Update src/main/webapp/dataset.xhtml Co-authored-by: Philip Durbin --- src/main/webapp/dataset.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataset.xhtml b/src/main/webapp/dataset.xhtml index cff4c43325a..03577b9571a 100644 --- a/src/main/webapp/dataset.xhtml +++ b/src/main/webapp/dataset.xhtml @@ -1755,7 +1755,7 @@
-   +  
From 64053b8f95dce4716a0c3acd8b5d155941698d0d Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:12:33 -0400 Subject: [PATCH 09/15] change preAuthorized to hasPermission --- .../impl/DeleteDatasetLinkingDataverseCommand.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java index 30fffcfc05f..c7fc108054a 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java @@ -18,7 +18,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import java.io.IOException; import java.util.Collections; -import java.util.concurrent.Future; + import org.apache.solr.client.solrj.SolrServerException; /** @@ -31,19 +31,19 @@ public class DeleteDatasetLinkingDataverseCommand extends AbstractCommand Date: Fri, 2 Aug 2024 10:16:55 -0400 Subject: [PATCH 10/15] fix unlink note --- src/main/java/propertyFiles/Bundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index ea50f37cf23..9ae0be17c57 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2553,7 +2553,7 @@ dataset.registered.msg=Your dataset is now registered. dataset.notlinked=DatasetNotLinked dataset.notlinked.msg=There was a problem linking this dataset to yours: dataset.linking.popop.already.linked.note=Note: This dataset is already linked to the following dataverse(s): -dataset.linking.popup.not.linked.note=Note: This dataset is not linked to the following dataverse(s): +dataset.linking.popup.not.linked.note=Note: This dataset is not linked to any of your accessible dataverses datasetversion.archive.success=Archival copy of Version successfully submitted datasetversion.archive.failure=Error in submitting an archival copy datasetversion.update.failure=Dataset Version Update failed. Changes are still in the DRAFT version. From 874ae0b32abb97e2f1f411679ccec05950f0ec70 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:24:44 -0400 Subject: [PATCH 11/15] remove hasPermission paramerter and change delete link to require PublishDataset permissions --- ...k-functionality-same-permission-as-link.md | 2 +- .../source/admin/dataverses-datasets.rst | 2 +- .../edu/harvard/iq/dataverse/DatasetPage.java | 2 +- .../harvard/iq/dataverse/api/Datasets.java | 2 +- .../DeleteDatasetLinkingDataverseCommand.java | 13 +----- .../command/impl/MoveDatasetCommand.java | 2 +- .../command/impl/MoveDataverseCommand.java | 2 +- .../harvard/iq/dataverse/api/DatasetsIT.java | 42 +++++++++++++++++-- 8 files changed, 46 insertions(+), 21 deletions(-) diff --git a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md index 84af4a6ccad..37900252980 100644 --- a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md +++ b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md @@ -1,2 +1,2 @@ New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a Dataverse that was previously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. -The unlink can still be accomplished by a superuser/Admin using the [pre-existing API](https://guides.dataverse.org/en/6.3/admin/dataverses-datasets.html#unlink-a-dataset). +The unlink can still be accomplished by a superuser/Admin or a User with Publish Dataset permissions using the [pre-existing API](https://guides.dataverse.org/en/6.3/admin/dataverses-datasets.html#unlink-a-dataset). diff --git a/doc/sphinx-guides/source/admin/dataverses-datasets.rst b/doc/sphinx-guides/source/admin/dataverses-datasets.rst index 37494c57fa1..14fd6c89e70 100644 --- a/doc/sphinx-guides/source/admin/dataverses-datasets.rst +++ b/doc/sphinx-guides/source/admin/dataverses-datasets.rst @@ -147,7 +147,7 @@ It returns a list in the following format: Unlink a Dataset ^^^^^^^^^^^^^^^^ -Removes a link between a dataset and a Dataverse collection. Only accessible to superusers. :: +Removes a link between a dataset and a Dataverse collection. Accessible to superusers or Users with Publish Dataset permissions (as of Dataverse 6.4). :: curl -H "X-Dataverse-key: $API_TOKEN" -X DELETE http://$SERVER/api/datasets/$linked-dataset-id/deleteLink/$linking-dataverse-alias diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java index 6d3ffb6c778..8522f2733c7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetPage.java @@ -3612,7 +3612,7 @@ private Boolean deleteLink(Dataverse dataverse){ linkingDataverse = dataverse; try { DatasetLinkingDataverse dsld = dsLinkingService.findDatasetLinkingDataverse(dataset.getId(), linkingDataverse.getId()); - DeleteDatasetLinkingDataverseCommand cmd = new DeleteDatasetLinkingDataverseCommand(dvRequestService.getDataverseRequest(), dataset, dsld, true, true); + DeleteDatasetLinkingDataverseCommand cmd = new DeleteDatasetLinkingDataverseCommand(dvRequestService.getDataverseRequest(), dataset, dsld, true); commandEngine.submit(cmd); } catch (CommandException ex) { String msg = "There was a problem removing the link between this dataset to yours: " + ex; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java index 5abbcafc47a..4b919c5ed82 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -376,7 +376,7 @@ public Response deleteDraftVersion(@Context ContainerRequestContext crc, @PathPa public Response deleteDatasetLinkingDataverse(@Context ContainerRequestContext crc, @PathParam("datasetId") String datasetId, @PathParam("linkedDataverseId") String linkedDataverseId) { boolean index = true; return response(req -> { - execCommand(new DeleteDatasetLinkingDataverseCommand(req, findDatasetOrDie(datasetId), findDatasetLinkingDataverseOrDie(datasetId, linkedDataverseId), index, false)); + execCommand(new DeleteDatasetLinkingDataverseCommand(req, findDatasetOrDie(datasetId), findDatasetLinkingDataverseOrDie(datasetId, linkedDataverseId), index)); return ok("Link from Dataset " + datasetId + " to linked Dataverse " + linkedDataverseId + " deleted"); }, getRequestUser(crc)); } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java index c7fc108054a..7f5672c0cd7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetLinkingDataverseCommand.java @@ -8,16 +8,13 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetLinkingDataverse; import edu.harvard.iq.dataverse.authorization.Permission; -import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.batch.util.LoggingUtil; import edu.harvard.iq.dataverse.engine.command.AbstractCommand; import edu.harvard.iq.dataverse.engine.command.CommandContext; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; -import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import java.io.IOException; -import java.util.Collections; import org.apache.solr.client.solrj.SolrServerException; @@ -26,27 +23,21 @@ * @author sarahferry */ -@RequiredPermissions( Permission.EditDataset ) +@RequiredPermissions( Permission.PublishDataset ) public class DeleteDatasetLinkingDataverseCommand extends AbstractCommand{ private final DatasetLinkingDataverse doomed; private final Dataset editedDs; private final boolean index; - private final boolean hasPermission; - public DeleteDatasetLinkingDataverseCommand(DataverseRequest aRequest, Dataset editedDs , DatasetLinkingDataverse doomed, boolean index, boolean hasPermission) { + public DeleteDatasetLinkingDataverseCommand(DataverseRequest aRequest, Dataset editedDs , DatasetLinkingDataverse doomed, boolean index) { super(aRequest, editedDs); this.editedDs = editedDs; this.doomed = doomed; this.index = index; - this.hasPermission = hasPermission; } @Override public Dataset execute(CommandContext ctxt) throws CommandException { - if (!hasPermission && (!(getUser() instanceof AuthenticatedUser) || !getUser().isSuperuser())) { - throw new PermissionException("Delete dataset linking dataverse can only be called by superusers.", - this, Collections.singleton(Permission.EditDataset), editedDs); - } Dataset merged = ctxt.em().merge(editedDs); DatasetLinkingDataverse doomedAndMerged = ctxt.em().merge(doomed); ctxt.em().remove(doomedAndMerged); diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDatasetCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDatasetCommand.java index eee012b48f8..94bcfa2f5b7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDatasetCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDatasetCommand.java @@ -119,7 +119,7 @@ public void executeImpl(CommandContext ctxt) throws CommandException { break; } boolean index = false; - ctxt.engine().submit(new DeleteDatasetLinkingDataverseCommand(getRequest(), dsld.getDataset(), dsld, index, false)); + ctxt.engine().submit(new DeleteDatasetLinkingDataverseCommand(getRequest(), dsld.getDataset(), dsld, index)); moved.getDatasetLinkingDataverses().remove(dsld); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDataverseCommand.java index 7f49c4d06f1..ea38f5a7af7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDataverseCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/MoveDataverseCommand.java @@ -259,7 +259,7 @@ public void executeImpl(CommandContext ctxt) throws CommandException { break; } boolean index = false; - ctxt.engine().submit(new DeleteDatasetLinkingDataverseCommand(getRequest(), dsld.getDataset(), dsld, index, false)); + ctxt.engine().submit(new DeleteDatasetLinkingDataverseCommand(getRequest(), dsld.getDataset(), dsld, index)); (dsld.getDataset()).getDatasetLinkingDataverses().remove(dsld); } } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java index cb9481d3491..ae380b61e55 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -2411,6 +2411,7 @@ public void testCreateDeleteDatasetLink() { Response createDatasetResponse = UtilIT.createRandomDatasetViaNativeApi(dataverseAlias, apiToken); createDatasetResponse.prettyPrint(); Integer datasetId = UtilIT.getDatasetIdFromResponse(createDatasetResponse); + String datasetPersistentId = UtilIT.getDatasetPersistentIdFromResponse(createDatasetResponse); // This should fail, because we are attempting to link the dataset // to its own dataverse: @@ -2445,11 +2446,44 @@ public void testCreateDeleteDatasetLink() { createLinkingDatasetResponse.then().assertThat() .body("data.message", equalTo("Dataset " + datasetId +" linked successfully to " + dataverseAlias)) .statusCode(200); - - // And now test deleting it: - Response deleteLinkingDatasetResponse = UtilIT.deleteDatasetLink(datasetId.longValue(), dataverseAlias, apiToken); + + // Create a new user that doesn't have permission to delete the link + Response createUser2 = UtilIT.createRandomUser(); + createUser2.prettyPrint(); + String username2 = UtilIT.getUsernameFromResponse(createUser2); + String apiToken2 = UtilIT.getApiTokenFromResponse(createUser2); + // Try to delete the link without PublishDataset permissions + Response deleteLinkingDatasetResponse = UtilIT.deleteDatasetLink(datasetId.longValue(), dataverseAlias, apiToken2); deleteLinkingDatasetResponse.prettyPrint(); - + deleteLinkingDatasetResponse.then().assertThat() + .body("message", equalTo("User @" + username2 + " is not permitted to perform requested action.")) + .statusCode(UNAUTHORIZED.getStatusCode()); + + // Add the Curator role to this user to show that they can delete the link later. (Timing issues if you try to delete right after giving permission) + Response givePermissionResponse = UtilIT.grantRoleOnDataset(datasetPersistentId, "curator", "@" + username2, apiToken); + givePermissionResponse.prettyPrint(); + givePermissionResponse.then().assertThat() + .statusCode(200); + + // And now test deleting it as superuser: + deleteLinkingDatasetResponse = UtilIT.deleteDatasetLink(datasetId.longValue(), dataverseAlias, apiToken); + deleteLinkingDatasetResponse.prettyPrint(); + + deleteLinkingDatasetResponse.then().assertThat() + .body("data.message", equalTo("Link from Dataset " + datasetId + " to linked Dataverse " + dataverseAlias + " deleted")) + .statusCode(200); + + // And re-link the dataset to this new dataverse: + createLinkingDatasetResponse = UtilIT.createDatasetLink(datasetId.longValue(), dataverseAlias, apiToken); + createLinkingDatasetResponse.prettyPrint(); + createLinkingDatasetResponse.then().assertThat() + .body("data.message", equalTo("Dataset " + datasetId +" linked successfully to " + dataverseAlias)) + .statusCode(200); + + // And now test deleting it as user2 with new role as curator (Publish permissions): + deleteLinkingDatasetResponse = UtilIT.deleteDatasetLink(datasetId.longValue(), dataverseAlias, apiToken2); + deleteLinkingDatasetResponse.prettyPrint(); + deleteLinkingDatasetResponse.then().assertThat() .body("data.message", equalTo("Link from Dataset " + datasetId + " to linked Dataverse " + dataverseAlias + " deleted")) .statusCode(200); From fae99e4be459c29145abeaebb781d52cde3845a1 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:05:59 -0400 Subject: [PATCH 12/15] Update doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md Co-authored-by: Philip Durbin --- ...0583-dataset-unlink-functionality-same-permission-as-link.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md index 37900252980..5baa5e96936 100644 --- a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md +++ b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md @@ -1,2 +1,2 @@ -New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a Dataverse that was previously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. +New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a collection that was previously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. The unlink can still be accomplished by a superuser/Admin or a User with Publish Dataset permissions using the [pre-existing API](https://guides.dataverse.org/en/6.3/admin/dataverses-datasets.html#unlink-a-dataset). From b9514c3a686941d528a63c9fd25ad0335cb71ba0 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:20:45 -0400 Subject: [PATCH 13/15] Update doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md Co-authored-by: Philip Durbin --- ...0583-dataset-unlink-functionality-same-permission-as-link.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md index 5baa5e96936..f97bd252db3 100644 --- a/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md +++ b/doc/release-notes/10583-dataset-unlink-functionality-same-permission-as-link.md @@ -1,2 +1,2 @@ New "Unlink Dataset" button has been added to the Dataset Page to allow a user to unlink a dataset from a collection that was previously linked with the "Link Dataset" button. The user must possess the same permissions needed to unlink the Dataset as they would to link the Dataset. -The unlink can still be accomplished by a superuser/Admin or a User with Publish Dataset permissions using the [pre-existing API](https://guides.dataverse.org/en/6.3/admin/dataverses-datasets.html#unlink-a-dataset). +The [existing API](https://guides.dataverse.org/en/6.3/admin/dataverses-datasets.html#unlink-a-dataset) for unlinking datasets has been updated to no longer require superuser access. The "Publish Dataset" permission is now enough. From 5d82a802ea7622cf4d801bc1ec504fee0aa8c5c8 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:21:55 -0400 Subject: [PATCH 14/15] Update doc/sphinx-guides/source/admin/dataverses-datasets.rst Co-authored-by: Philip Durbin --- doc/sphinx-guides/source/admin/dataverses-datasets.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/admin/dataverses-datasets.rst b/doc/sphinx-guides/source/admin/dataverses-datasets.rst index 14fd6c89e70..c6f15968f00 100644 --- a/doc/sphinx-guides/source/admin/dataverses-datasets.rst +++ b/doc/sphinx-guides/source/admin/dataverses-datasets.rst @@ -147,7 +147,7 @@ It returns a list in the following format: Unlink a Dataset ^^^^^^^^^^^^^^^^ -Removes a link between a dataset and a Dataverse collection. Accessible to superusers or Users with Publish Dataset permissions (as of Dataverse 6.4). :: +Removes a link between a dataset and a Dataverse collection. Accessible to users with Publish Dataset permissions. :: curl -H "X-Dataverse-key: $API_TOKEN" -X DELETE http://$SERVER/api/datasets/$linked-dataset-id/deleteLink/$linking-dataverse-alias From ad8cd72bc21b739b313c00fb50f2483fa51f1b4c Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:16:45 -0400 Subject: [PATCH 15/15] only show unlink if dataset can be unlinked --- src/main/webapp/dataset.xhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/dataset.xhtml b/src/main/webapp/dataset.xhtml index 03577b9571a..4cece74b67a 100644 --- a/src/main/webapp/dataset.xhtml +++ b/src/main/webapp/dataset.xhtml @@ -523,7 +523,7 @@ -
+