Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d0a387c
Merge branch 'develop' into 4410-dataset-linking
sekmiller Aug 28, 2018
2dbab88
#4410 Dataset linking prelim check in
sekmiller Aug 29, 2018
255f837
Merge branch 'develop' into 4410-dataset-linking
sekmiller Aug 29, 2018
60faa1c
#4410 Add permissions remove debug code
sekmiller Aug 30, 2018
7bb8b99
#4410 filter used links fix messaging
sekmiller Aug 30, 2018
660d5f6
Merge branch 'develop' into 4410-dataset-linking
sekmiller Aug 30, 2018
d7e0288
#4410 Remove unused code
sekmiller Aug 31, 2018
9517c64
Added back link dataset msg's to popup, cleaned up layout. [ref #4410]
mheppler Aug 31, 2018
8c4d1ca
#4410 remove more unused code
sekmiller Aug 31, 2018
f689c44
Merge branch 'develop' into 4410-dataset-linking
sekmiller Aug 31, 2018
bda5a58
#4410 file code delete
sekmiller Aug 31, 2018
2f99f60
#4410 fix error messages
sekmiller Aug 31, 2018
0e42fbb
#4410 return prompt for dataverse name
sekmiller Aug 31, 2018
7047ab7
#4410 Fix none selected error; support multiple link success message
sekmiller Sep 6, 2018
ae31a4d
#4410 code cleanup add msgs to bundle
sekmiller Sep 7, 2018
701f673
Merge branch 'develop' into 4410-dataset-linking
sekmiller Sep 7, 2018
c7ce08b
#4410 limit linking to one dv at a time modify perms
sekmiller Sep 7, 2018
ee08a43
Merge branch 'develop' into 4410-dataset-linking
sekmiller Sep 7, 2018
13abdb6
#4410 add "alias" to dv linking selector
sekmiller Sep 7, 2018
d00d57b
Merge branch 'develop' into 4410-dataset-linking
sekmiller Sep 7, 2018
190fd65
#4410 Add Dataverse to Applies to for publish Dataset perm
sekmiller Sep 10, 2018
6e464ec
#4410 post support email to linking success message
sekmiller Sep 17, 2018
e844401
Merge branch 'develop' into 4410-dataset-linking
sekmiller Sep 17, 2018
5cf37a3
Linking API doc revisions [#4410]
dlmurphy Sep 17, 2018
1479e9d
Revert Dataverse Linking doc change [#4410]
dlmurphy Sep 17, 2018
baa12d8
Dataset Linking User Guide [4410]
dlmurphy Sep 17, 2018
d2482eb
Added configurable support team name and text link to contact popup t…
mheppler Sep 20, 2018
6ad831a
#4410 force query input to lower case to match NamedQuery
sekmiller Sep 20, 2018
e74a366
#4410 prevent linking to unpublished ds via api
sekmiller Sep 20, 2018
cd1fb3a
Merge branch 'develop' into 4410-dataset-linking
sekmiller Sep 21, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -41,7 +41,7 @@ Moves a dataset whose id is passed to a dataverse whose alias is passed. If the
Link a Dataset
^^^^^^^^^^^^^^

Creates a link between a dataset and a dataverse (see the Linked Dataverses + Linked Datasets section of the :doc:`/user/dataverse-management` guide for more information). Only accessible to superusers. ::
Creates a link between a dataset and a dataverse (see the Linked Dataverses + Linked Datasets section of the :doc:`/user/dataverse-management` guide for more information). ::

curl -H "X-Dataverse-key: $API_TOKEN" -X PUT http://$SERVER/api/datasets/$linked-dataset-id/link/$linking-dataverse-alias

Expand Down
7 changes: 7 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,13 @@ In the example below, the curator has saved the JSON file as :download:`reason-f

The review process can sometimes resemble a tennis match, with the authors submitting and resubmitting the dataset over and over until the curators are satisfied. Each time the curators send a "reason for return" via API, that reason is persisted into the database, stored at the dataset version level.

Link a Dataset
~~~~~~~~~~~~~~

Creates a link between a dataset and a dataverse (see the Linked Dataverses + Linked Datasets section of the :doc:`/user/dataverse-management` guide for more information). ::

curl -H "X-Dataverse-key: $API_TOKEN" -X PUT http://$SERVER/api/datasets/$linked-dataset-id/link/$linking-dataverse-alias

Dataset Locks
~~~~~~~~~~~~~

Expand Down
22 changes: 17 additions & 5 deletions doc/sphinx-guides/source/user/dataverse-management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,26 @@ Click on Featured Dataverses and a pop up will appear. Select which sub datavers

Note: Featured Dataverses can only be used with published dataverses.

Linked Dataverses + Linked Datasets
======================================================
Dataset Linking
===============

Dataset linking allows a dataverse owner to "link" their dataverse to a dataset that exists outside of that dataverse, so it appears in the dataverse’s list of contents without actually *being* in that dataverse. You can link other users' datasets to your dataverse, but that does not transfer editing or other special permissions to you. The linked dataset will still be under the original user's control.

For example, researchers working on a collaborative study across institutions can each link their own individual institutional dataverses to the one collaborative dataset, making it easier for interested parties from each institution to find the study.

In order to link a dataset, you will need your account to have the "Add Dataset" permission on the Dataverse that is doing the linking. If you created the dataverse then you should have this permission already, but if not then you will need to ask the admin of that dataverse to assign that permission to your account. You do not need any special permissions on the dataset being linked.

Currently, the ability to link a dataverse to another dataverse or a dataset to a dataverse is a super user only feature.
To link a dataset to your dataverse, you must navigate to that dataset and click the white "Link" button in the upper-right corner of the dataset page. This will open up a window where you can type in the name of the dataverse that you would like to link the dataset to. Select your dataverse and click the save button. This will establish the link, and the dataset will now appear under your dataverse.

There is currently no way to remove established links in the UI. If you need to remove a link between a dataverse and a dataset, please contact the support team for the Dataverse installation you are using.


Dataverse Linking
======================================================

If you link a dataset to your dataverse, that means that the dataset will appear in the list of datasets contained within your dataverse. Linking another dataverse to your dataverse works the same way. You can link other users' dataverses and datasets to your dataverse, but that does not transfer editing or other special permissions to you. The linked dataverse or dataset will still be under the original user's control.
Similarly to dataset linking, dataverse linking allows a dataverse owner to "link" their dataverse to another dataverse, so the dataverse being linked will appear in the linking dataverse's list of contents without actually *being* in that dataverse. Currently, the ability to link a dataverse to another dataverse is a superuser only feature.

If you need to have a dataverse or dataset linked to your dataverse, please contact the support team for the Dataverse installation you are using.
If you need to have a dataverse linked to your dataverse, please contact the support team for the Dataverse installation you are using.

Publish Your Dataverse
=================================================================
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -684,11 +684,16 @@ dataverse.contact=Email Dataverse Contact
dataset.link=Link Dataset
dataverse.link=Link Dataverse
dataverse.link.btn.tip=Link to Your Dataverse
dataverse.link.yourDataverses=Your {0, choice, 1#Dataverse|2#Dataverses}
dataverse.link.yourDataverses=Your Dataverse
dataverse.link.yourDataverses.inputPlaceholder=Enter Dataverse Name
dataverse.link.save=Save Linked Dataverse
dataset.link.save=Save Linked Dataset
dataset.link.not.to.owner=Can't link a dataset to its dataverse
dataset.link.not.to.parent.dataverse=Can't link a dataset to its parent dataverses
dataset.link.not.published=Can't link a dataset that has not been published
dataverse.link.dataverse.choose=Choose which of your dataverses you would like to link this dataverse to.
dataverse.link.dataset.choose=Choose which of your dataverses you would like to link this dataset to.
dataverse.link.dataset.choose=Enter the name of the dataverse you would like to link this dataset to. If you need to remove this link in the future, please contact {0}.
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. Click on the Add Data button on the homepage to get started.
dataverse.link.no.linkable.remaining=You have already linked all of your eligible dataverses.
Expand Down Expand Up @@ -1909,6 +1914,7 @@ dataverse.edit.msg=Edit Dataverse
dataverse.edit.detailmsg= - Edit your dataverse and click Save. Asterisks indicate required fields.
dataverse.feature.update=The featured dataverses for this dataverse have been updated.
dataverse.link.select=You must select a linking dataverse.
dataset.noSelectedDataverse.header=Select Dataverse(s)
dataverse.link.user=Only authenticated users can link a dataverse.
dataverse.link.error=Unable to link {0} to {1}. An internal error occurred.
dataverse.search.user=Only authenticated users can save a search.
Expand Down
129 changes: 70 additions & 59 deletions src/main/java/edu/harvard/iq/dataverse/DatasetPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
import edu.harvard.iq.dataverse.externaltools.ExternalToolServiceBean;
import edu.harvard.iq.dataverse.export.SchemaDotOrgExporter;
import java.util.Collections;
import javax.faces.component.UIInput;

import javax.faces.event.AjaxBehaviorEvent;
import javax.servlet.ServletOutputStream;
Expand Down Expand Up @@ -238,7 +239,6 @@ public enum DisplayMode {

private boolean stateChanged = false;

private List<Dataverse> dataversesForLinking = new ArrayList<>();
private Long linkingDataverseId;
private List<SelectItem> linkingDVSelectItems;
private Dataverse linkingDataverse;
Expand Down Expand Up @@ -738,59 +738,14 @@ public void setLinkingDataverseId(Long linkingDataverseId) {
this.linkingDataverseId = linkingDataverseId;
}

public List<Dataverse> getDataversesForLinking() {
return dataversesForLinking;
}

public void setDataversesForLinking(List<Dataverse> dataversesForLinking) {
this.dataversesForLinking = dataversesForLinking;
}

public void updateReleasedVersions(){

setReleasedVersionTabList(resetReleasedVersionTabList());

}

public void updateLinkableDataverses() {
dataversesForLinking = new ArrayList<>();
linkingDVSelectItems = new ArrayList<>();

//Since this is a super user we are getting all dataverses
dataversesForLinking = dataverseService.findAll();
if (dataversesForLinking.isEmpty()) {
setNoDVsAtAll(true);
return;
}

dataversesForLinking.remove(dataset.getOwner());
Dataverse testDV = dataset.getOwner();
while(testDV.getOwner() != null){
dataversesForLinking.remove(testDV.getOwner());
testDV = testDV.getOwner();
}

for (Dataverse removeLinked : dsLinkingService.findLinkingDataverses(dataset.getId())) {
dataversesForLinking.remove(removeLinked);
}
for (Dataverse removeLinked : dvLinkingService.findLinkingDataverses(dataset.getOwner().getId())) {
dataversesForLinking.remove(removeLinked);
}

if (dataversesForLinking.isEmpty()) {
setNoDVsRemaining(true);
return;
}

for (Dataverse selectDV : dataversesForLinking) {
linkingDVSelectItems.add(new SelectItem(selectDV.getId(), selectDV.getDisplayName()));
}

if (!dataversesForLinking.isEmpty() && dataversesForLinking.size() == 1 && dataversesForLinking.get(0) != null) {
linkingDataverse = dataversesForLinking.get(0);
linkingDataverseId = linkingDataverse.getId();
}
}

public void updateSelectedLinkingDV(ValueChangeEvent event) {
linkingDataverseId = (Long) event.getNewValue();
Expand Down Expand Up @@ -2128,6 +2083,16 @@ public void setSelectedFiles(List<FileMetadata> selectedFiles) {
this.selectedFiles = selectedFiles;
}

private Dataverse selectedDataverseForLinking;

public Dataverse getSelectedDataverseForLinking() {
return selectedDataverseForLinking;
}

public void setSelectedDataverseForLinking(Dataverse sdvfl) {
this.selectedDataverseForLinking = sdvfl;
}

private List<FileMetadata> selectedRestrictedFiles; // = new ArrayList<>();

public List<FileMetadata> getSelectedRestrictedFiles() {
Expand Down Expand Up @@ -2294,37 +2259,83 @@ public void updateFileCounts(){

private List<String> getSuccessMessageArguments() {
List<String> arguments = new ArrayList<>();
String dataverseString = "";
arguments.add(StringEscapeUtils.escapeHtml(dataset.getDisplayName()));
String linkString = "<a href=\"/dataverse/" + linkingDataverse.getAlias() + "\">" + StringEscapeUtils.escapeHtml(linkingDataverse.getDisplayName()) + "</a>";
arguments.add(linkString);
dataverseString += " <a href=\"/dataverse/" + selectedDataverseForLinking.getAlias() + "\">" + StringEscapeUtils.escapeHtml(selectedDataverseForLinking.getDisplayName()) + "</a>";
arguments.add(dataverseString);
return arguments;
}

public String saveLinkedDataset() {
if (linkingDataverseId == null) {
JsfHelper.addFlashMessage(BundleUtil.getStringFromBundle("dataverse.link.select"));
return "";

public void saveLinkingDataverses() {

if (selectedDataverseForLinking == null) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "", BundleUtil.getStringFromBundle("dataverse.link.select"));
FacesContext.getCurrentInstance().addMessage(null, message);
return;
}

if(saveLink(selectedDataverseForLinking)){
JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dataset.message.linkSuccess", getSuccessMessageArguments()));
} else{
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, BundleUtil.getStringFromBundle("dataset.notlinked"), linkingDataverseErrorMessage);
FacesContext.getCurrentInstance().addMessage(null, message);
}
linkingDataverse = dataverseService.find(linkingDataverseId);
}

private String linkingDataverseErrorMessage = "";


public String getLinkingDataverseErrorMessage() {
return linkingDataverseErrorMessage;
}

public void setLinkingDataverseErrorMessage(String linkingDataverseErrorMessage) {
this.linkingDataverseErrorMessage = linkingDataverseErrorMessage;
}

UIInput selectedLinkingDataverseMenu;

public UIInput getSelectedDataverseMenu() {
return selectedLinkingDataverseMenu;
}

public void setSelectedDataverseMenu(UIInput selectedDataverseMenu) {
this.selectedLinkingDataverseMenu = selectedDataverseMenu;
}


private Boolean saveLink(Dataverse dataverse){
boolean retVal = true;
if (readOnly) {
// Pass a "real", non-readonly dataset the the LinkDatasetCommand:
dataset = datasetService.find(dataset.getId());
}
LinkDatasetCommand cmd = new LinkDatasetCommand(dvRequestService.getDataverseRequest(), linkingDataverse, dataset);
LinkDatasetCommand cmd = new LinkDatasetCommand(dvRequestService.getDataverseRequest(), dataverse, dataset);
linkingDataverse = dataverse;
try {
commandEngine.submit(cmd);
JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dataset.message.linkSuccess", getSuccessMessageArguments()));
commandEngine.submit(cmd);
} catch (CommandException ex) {
String msg = "There was a problem linking 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?
*/
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, BundleUtil.getStringFromBundle("dataset.notlinked"), msg);
FacesContext.getCurrentInstance().addMessage(null, message);
linkingDataverseErrorMessage = msg;
retVal = false;
}
return retVal;
}


public List<Dataverse> completeLinkingDataverse(String query) {
dataset = datasetService.find(dataset.getId());
if (session.getUser().isAuthenticated()) {
return dataverseService.filterDataversesForLinking(query, dvRequestService.getDataverseRequest(), dataset);
} else {
return null;
}
return returnToLatestVersion();
}

List<FileMetadata> previouslyRestrictedFiles = null;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/Dataverse.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
@NamedQuery(name = "Dataverse.findRoot", query = "SELECT d FROM Dataverse d where d.owner.id=null"),
@NamedQuery(name = "Dataverse.findByAlias", query="SELECT dv FROM Dataverse dv WHERE LOWER(dv.alias)=:alias"),
@NamedQuery(name = "Dataverse.filterByAlias", query="SELECT dv FROM Dataverse dv WHERE LOWER(dv.alias) LIKE :alias order by dv.alias"),
@NamedQuery(name = "Dataverse.filterByAliasNameAffiliation", query="SELECT dv FROM Dataverse dv WHERE (LOWER(dv.alias) LIKE :alias) OR (LOWER(dv.name) LIKE :name) OR (LOWER(dv.affiliation) LIKE :affiliation) order by dv.alias")
@NamedQuery(name = "Dataverse.filterByAliasNameAffiliation", query="SELECT dv FROM Dataverse dv WHERE (LOWER(dv.alias) LIKE :alias) OR (LOWER(dv.name) LIKE :name) OR (LOWER(dv.affiliation) LIKE :affiliation) order by dv.alias"),
@NamedQuery(name = "Dataverse.filterByName", query="SELECT dv FROM Dataverse dv WHERE LOWER(dv.name) LIKE :name order by dv.alias")
})
@Entity
@Table(indexes = {@Index(columnList="defaultcontributorrole_id")
Expand Down
38 changes: 36 additions & 2 deletions src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
*/
package edu.harvard.iq.dataverse;

import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.search.IndexServiceBean;
import edu.harvard.iq.dataverse.search.SolrSearchResult;
import edu.harvard.iq.dataverse.util.SystemConfig;
Expand Down Expand Up @@ -49,13 +52,16 @@ public class DataverseServiceBean implements java.io.Serializable {

@EJB
DatasetServiceBean datasetService;

@EJB
DataverseLinkingServiceBean dataverseLinkingService;

@EJB
DatasetLinkingServiceBean datasetLinkingService;

@EJB
PermissionServiceBean permissionService;

@EJB
SystemConfig systemConfig;

Expand Down Expand Up @@ -179,7 +185,7 @@ public Dataverse findByAlias(String anAlias) {
return null;
}
}
public boolean hasData( Dataverse dv ) {
TypedQuery<Long> amountQry = em.createNamedQuery("Dataverse.ownedObjectsById", Long.class)
.setParameter("id", dv.getId());
Expand Down Expand Up @@ -441,6 +447,34 @@ public List<Dataverse> filterByAliasQuery(String filterQuery) {
return ret;
}

public List<Dataverse> filterDataversesForLinking(String query, DataverseRequest req, Dataset dataset) {

List<Dataverse> dataverseList = new ArrayList<>();

List<Dataverse> results = em.createNamedQuery("Dataverse.filterByName", Dataverse.class)
.setParameter("name", "%" + query.toLowerCase() + "%")
.getResultList();

List<Object> alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList();
List<Dataverse> remove = new ArrayList<>();

if (alreadyLinkeddv_ids != null && !alreadyLinkeddv_ids.isEmpty()) {
alreadyLinkeddv_ids.stream().map((testDVId) -> this.find(testDVId)).forEachOrdered((removeIt) -> {
remove.add(removeIt);
});
}

for (Dataverse res : results) {
if (!remove.contains(res)) {
if (this.permissionService.requestOn(req, res).has(Permission.PublishDataset)) {
dataverseList.add(res);
}
}
}

return dataverseList;
}

/**
* Used to identify and properly display Harvested objects on the dataverse page.
*
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/SettingsWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ public String getSupportTeamName() {
InternetAddress systemAddress = MailUtil.parseSystemAddress(systemEmail);
return BrandingUtil.getSupportTeamName(systemAddress, dataverseService.findRootDataverse().getName());
}

public String getSupportTeamEmail() {
String systemEmail = getValueForKey(SettingsServiceBean.Key.SystemEmail);
InternetAddress systemAddress = MailUtil.parseSystemAddress(systemEmail);
return BrandingUtil.getSupportTeamEmailAddress(systemAddress) != null ? BrandingUtil.getSupportTeamEmailAddress(systemAddress) : BrandingUtil.getSupportTeamName(systemAddress, dataverseService.findRootDataverse().getName());
}

public boolean isRootDataverseThemeDisabled() {
return isTrueForKey(Key.DisableRootDataverseTheme, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public enum Permission implements java.io.Serializable {
ManageDataversePermissions(BundleUtil.getStringFromBundle("permission.managePermissionsDataverse"), true, Dataverse.class),
ManageDatasetPermissions(BundleUtil.getStringFromBundle("permission.managePermissionsDataset"), true, Dataset.class),
PublishDataverse(BundleUtil.getStringFromBundle("permission.publishDataverse"), true, Dataverse.class),
PublishDataset(BundleUtil.getStringFromBundle("permission.publishDataset"), true, Dataset.class),
PublishDataset(BundleUtil.getStringFromBundle("permission.publishDataset"), true, Dataset.class, Dataverse.class),
// Delete
DeleteDataverse(BundleUtil.getStringFromBundle("permission.deleteDataverse"), true, Dataverse.class),
DeleteDatasetDraft(BundleUtil.getStringFromBundle("permission.deleteDataset"), true, Dataset.class);
Expand Down
Loading