Skip to content

Commit

Permalink
Merge pull request #10689 from IQSS/10583-dataset-unlink-functionalit…
Browse files Browse the repository at this point in the history
…y-same-permission-as-link

adding unlink to ui and matching link permissions
  • Loading branch information
sekmiller authored Aug 27, 2024
2 parents 3da42b4 + ad8cd72 commit 34bfb1b
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +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 [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.
2 changes: 1 addition & 1 deletion doc/sphinx-guides/source/admin/dataverses-datasets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 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

Expand Down
45 changes: 45 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/DatasetPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 = "";

Expand Down Expand Up @@ -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);
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;

Expand All @@ -3622,6 +3652,14 @@ public List<Dataverse> completeLinkingDataverse(String query) {
return null;
}
}
public List<Dataverse> completeUnLinkingDataverse(String query) {
dataset = datasetService.find(dataset.getId());
if (session.getUser().isAuthenticated()) {
return dataverseService.filterDataversesForUnLinking(query, dvRequestService.getDataverseRequest(), dataset);
} else {
return null;
}
}

public List<Dataverse> completeHostDataverseMenuList(String query) {
if (session.getUser().isAuthenticated()) {
Expand Down Expand Up @@ -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;

//
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,19 @@ public List<Dataverse> filterDataversesForLinking(String query, DataverseRequest

return dataverseList;
}

public List<Dataverse> filterDataversesForUnLinking(String query, DataverseRequest req, Dataset dataset) {
List<Object> alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList();
List<Dataverse> 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<Dataverse> filterDataversesForHosting(String pattern, DataverseRequest req) {

// Find the dataverses matching the search parameters:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,22 @@
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 java.util.concurrent.Future;

import org.apache.solr.client.solrj.SolrServerException;

/**
*
* @author sarahferry
*/

@RequiredPermissions( Permission.EditDataset )
@RequiredPermissions( Permission.PublishDataset )
public class DeleteDatasetLinkingDataverseCommand extends AbstractCommand<Dataset>{
private final DatasetLinkingDataverse doomed;
private final Dataset editedDs;
Expand All @@ -41,10 +38,6 @@ public DeleteDatasetLinkingDataverseCommand(DataverseRequest aRequest, Dataset e

@Override
public Dataset execute(CommandContext ctxt) throws CommandException {
if ((!(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);
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ dataverse.link.dataset.none=No linkable dataverses available.
dataverse.link.no.choice=You have one dataverse you can add linked dataverses and datasets in.
dataverse.link.no.linkable=To be able to link a dataverse or dataset, you need to have your own dataverse. Create a dataverse to get started.
dataverse.link.no.linkable.remaining=You have already linked all of your eligible dataverses.
dataverse.unlink.dataset.choose=Enter the name of the dataverse you would like to unlink this dataset from.
dataverse.unlink.dataset.none=No linked dataverses available.
dataverse.savedsearch.link=Link Search
dataverse.savedsearch.searchquery=Search
dataverse.savedsearch.filterQueries=Facets
Expand All @@ -912,6 +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 unlinked from {1}.
dataverse.page.pre=Previous
dataverse.page.next=Next
dataverse.byCategory=Dataverses by Category
Expand Down Expand Up @@ -1423,6 +1426,7 @@ dataset.accessBtn.too.big=The dataset is too large to download. Please select th
dataset.accessBtn.original.too.big=The dataset is too large to download in the original format. Please select the files you need from the files table.
dataset.accessBtn.archival.too.big=The dataset is too large to download in the archival format. Please select the files you need from the files table.
dataset.linkBtn=Link Dataset
dataset.unlinkBtn=Unlink Dataset
dataset.contactBtn=Contact Owner
dataset.shareBtn=Share

Expand Down Expand Up @@ -1530,6 +1534,8 @@ dataset.link.not.to.parent.dataverse=Can't link a dataset to its parent datavers
dataset.link.not.published=Can't link a dataset that has not been published
dataset.link.not.available=Can't link a dataset that has not been published or is not harvested
dataset.link.not.already.linked=Can't link a dataset that has already been linked to this dataverse
dataset.unlink.title=Unlink Dataset
dataset.unlink.delete=Remove Linked Dataset
dataset.email.datasetContactTitle=Contact Dataset Owner
dataset.email.hiddenMessage=
dataset.email.messageSubject=Test Message Subject
Expand Down Expand Up @@ -1611,6 +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 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.
Expand Down Expand Up @@ -2546,6 +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 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.
Expand Down
76 changes: 76 additions & 0 deletions src/main/webapp/dataset.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,16 @@
</p:commandLink>
</div>
<!-- END: LINK -->
<!-- UNLINK -->
<div class="btn-group btn-group-justified" jsf:rendered="#{dataverseSession.user.authenticated and !DatasetPage.workingVersion.deaccessioned and DatasetPage.dataset.released and !empty DatasetPage.dataset.datasetLinkingDataverses}">
<p:commandLink styleClass="btn btn-default btn-access btn-xs btn-block btn-link-dataset"
action="#{DatasetPage.setShowUnLinkingPopup(true)}"
oncomplete="PF('unlinkDatasetForm').show();"
update="@form">
#{bundle['dataset.unlinkBtn']}
</p:commandLink>
</div>
<!-- END: UNLINK -->

<!-- Contact/Share Button Group -->
<div class="btn-group btn-group-justified">
Expand Down Expand Up @@ -1697,6 +1707,72 @@
</div>
</p:dialog>
<p:remoteCommand name="linkDatasetCommand" oncomplete="PF('linkDatasetForm').hide();" update=":messagePanel @([id$=Messages])" actionListener="#{DatasetPage.saveLinkingDataverses}"/>
<p:dialog id="unlinkDatasetForm" styleClass="largePopUp" header="#{bundle['dataset.unlink.title']}" widgetVar="unlinkDatasetForm" modal="true" rendered="#{DatasetPage.showUnLinkingPopup}">
<p:focus for="dataverseUnLinkName"/>
<div class="form-horizontal">
<p class="help-block">
<h:outputFormat value="#{bundle['dataverse.unlink.dataset.choose']}" escape="false">
<o:param>
<p:commandLink value="#{settingsWrapper.supportTeamName}" oncomplete="PF('unlinkDatasetForm').hide();PF('contactForm').show()" update=":contactDialog" actionListener="#{sendFeedbackDialog.initUserInput}">
<f:setPropertyActionListener target="#{sendFeedbackDialog.messageSubject}" value=""/>
<f:setPropertyActionListener target="#{sendFeedbackDialog.recipient}" value="#{null}"/>
<f:setPropertyActionListener target="#{sendFeedbackDialog.userMessage}" value=""/>
<f:setPropertyActionListener target="#{sendFeedbackDialog.userEmail}" value=""/>
</p:commandLink>
</o:param>
</h:outputFormat>
</p>
<div class="form-group">
<label class="col-xs-3 control-label">
<h:outputText value="#{bundle['dataverse.link.yourDataverses']}"/>
</label>
<div class="col-xs-8">
<p:fragment id="unlinkNameContent">
<p:autoComplete id="dataverseUnLinkName"
placeholder="#{bundle['dataverse.link.yourDataverses.inputPlaceholder']}"
emptyMessage="#{bundle['dataverse.unlink.dataset.none']}"
scrollHeight="180" forceSelection="true"
minQueryLength="1" queryDelay="1000"
value="#{DatasetPage.selectedDataverseForLinking}"
multiple="false"
completeMethod="#{DatasetPage.completeUnLinkingDataverse}"
required="#{param['DO_DS_LINK_VALIDATION']}" requiredMessage="#{bundle['dataverse.link.select']}"
styleClass="DropdownPopup" panelStyleClass="DropdownPopupPanel"
var="dataverseLk" itemLabel="#{dataverseLk.displayName}" itemValue="#{dataverseLk}" converter="dataverseConverter">
<p:column>
<h:outputText value="#{dataverseLk.displayName}"/>
</p:column>
<p:column>
<h:outputText value="#{dataverseLk.alias}"/>
</p:column>
<p:ajax process="@this" event="itemSelect" />
<p:ajax process="@this" event="itemUnselect" />
</p:autoComplete>
<p:message for="dataverseUnLinkName"/>
</p:fragment>
</div>
</div>
</div>
<div>
<p:fragment rendered="#{empty DatasetPage.alreadyLinkedDataverses}">
<h:outputLabel value="#{bundle['dataset.linking.popup.not.linked.note']}"/>&#160;
<h:outputText value=""/>
</p:fragment>
</div>
<div class="button-block">
<p:commandButton id="deleteLinkButton" styleClass="btn btn-default"
update="linkNameContent @([id$=Messages])"
oncomplete="if (args &amp;&amp; !args.validationFailed) unlinkDatasetCommand();"
value="#{bundle['dataset.unlink.delete']}">
<f:param name="DO_DS_LINK_VALIDATION" value="true"/>
</p:commandButton>
<button class="btn btn-link" onclick="PF('unlinkDatasetForm').hide();
PF('blockDatasetForm').hide();" type="button">
#{bundle.cancel}
</button>
</div>
</p:dialog>
<p:remoteCommand name="unlinkDatasetCommand" oncomplete="PF('unlinkDatasetForm').hide();" update=":messagePanel @([id$=Messages])" actionListener="#{DatasetPage.deleteLinkingDataverses}"/>
<p:dialog id="computeBatchListPopup" header="#{bundle['dataset.compute.computeBatchListHeader']}" widgetVar="computeBatchListPopup" modal="true">
<div class="text-right">
<!-- Clear link -->
Expand Down
Loading

0 comments on commit 34bfb1b

Please sign in to comment.