Skip to content

Commit

Permalink
Merge pull request #7415 from IQSS/7259-linking
Browse files Browse the repository at this point in the history
prevent double linking of datasets and dataverses #7259
  • Loading branch information
kcondon committed Nov 20, 2020
2 parents e8a2bb1 + 403a966 commit f940279
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 35 deletions.
2 changes: 1 addition & 1 deletion conf/docker-aio/run-test-suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ fi

# Please note the "dataverse.test.baseurl" is set to run for "all-in-one" Docker environment.
# TODO: Rather than hard-coding the list of "IT" classes here, add a profile to pom.xml.
mvn test -Dtest=DataversesIT,DatasetsIT,SwordIT,AdminIT,BuiltinUsersIT,UsersIT,UtilIT,ConfirmEmailIT,FileMetadataIT,FilesIT,SearchIT,InReviewWorkflowIT,HarvestingServerIT,MoveIT,MakeDataCountApiIT,FileTypeDetectionIT,EditDDIIT,ExternalToolsIT,AccessIT,DuplicateFilesIT,DownloadFilesIT -Ddataverse.test.baseurl=$dvurl
mvn test -Dtest=DataversesIT,DatasetsIT,SwordIT,AdminIT,BuiltinUsersIT,UsersIT,UtilIT,ConfirmEmailIT,FileMetadataIT,FilesIT,SearchIT,InReviewWorkflowIT,HarvestingServerIT,MoveIT,MakeDataCountApiIT,FileTypeDetectionIT,EditDDIIT,ExternalToolsIT,AccessIT,DuplicateFilesIT,DownloadFilesIT,LinkIT -Ddataverse.test.baseurl=$dvurl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public DatasetLinkingDataverse execute(CommandContext ctxt) throws CommandExcept
if (linkedDataset.getOwner().getOwners().contains(linkingDataverse)) {
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dataset.link.not.to.parent.dataverse"), this);
}
if (ctxt.dsLinking().alreadyLinked(linkingDataverse, linkedDataset)) {
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dataset.link.not.already.linked"), this);
}

DatasetLinkingDataverse datasetLinkingDataverse = new DatasetLinkingDataverse();
datasetLinkingDataverse.setDataset(linkedDataset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
import edu.harvard.iq.dataverse.engine.command.exception.PermissionException;
import edu.harvard.iq.dataverse.util.BundleUtil;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.concurrent.Future;
Expand Down Expand Up @@ -53,6 +55,9 @@ public DataverseLinkingDataverse execute(CommandContext ctxt) throws CommandExce
if (linkedDataverse.getOwners().contains(linkingDataverse)) {
throw new IllegalCommandException("Can't link a dataverse to its parents", this);
}
if (ctxt.dvLinking().alreadyLinked(linkingDataverse, linkedDataverse)) {
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dataverse.linked.error.alreadyLinked", Arrays.asList(linkedDataverse.getName(), linkingDataverse.getName())), this);
}

DataverseLinkingDataverse dataverseLinkingDataverse = new DataverseLinkingDataverse();
dataverseLinkingDataverse.setDataverse(linkedDataverse);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ dataverse.saved.search.failure=The saved search was not able to be linked.
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.page.pre=Previous
dataverse.page.next=Next
dataverse.byCategory=Dataverses by Category
Expand Down Expand Up @@ -1314,6 +1315,7 @@ 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
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.email.datasetContactTitle=Contact Dataset Owner
dataset.email.hiddenMessage=
dataset.email.messageSubject=Test Message Subject
Expand Down
37 changes: 3 additions & 34 deletions src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -383,40 +383,9 @@ public void testMoveDataverse() {
}

}

@Test
public void testCreateDeleteDataverseLink() {
Response createUser = UtilIT.createRandomUser();

createUser.prettyPrint();
String username = UtilIT.getUsernameFromResponse(createUser);
String apiToken = UtilIT.getApiTokenFromResponse(createUser);

Response superuserResponse = UtilIT.makeSuperUser(username);

Response createDataverseResponse = UtilIT.createRandomDataverse(apiToken);
createDataverseResponse.prettyPrint();
String dataverseAlias = UtilIT.getAliasFromResponse(createDataverseResponse);
Integer dataverseId = UtilIT.getDataverseIdFromResponse(createDataverseResponse);

Response createDataverseResponse2 = UtilIT.createRandomDataverse(apiToken);
createDataverseResponse2.prettyPrint();
String dataverseAlias2 = UtilIT.getAliasFromResponse(createDataverseResponse2);

Response createLinkingDataverseResponse = UtilIT.createDataverseLink(dataverseAlias, dataverseAlias2, apiToken);
createLinkingDataverseResponse.prettyPrint();

createLinkingDataverseResponse.then().assertThat()
.body("data.message", equalTo("Dataverse " + dataverseAlias + " linked successfully to " + dataverseAlias2))
.statusCode(200);

Response deleteLinkingDataverseResponse = UtilIT.deleteDataverseLink(dataverseAlias, dataverseAlias2, apiToken);
deleteLinkingDataverseResponse.prettyPrint();
deleteLinkingDataverseResponse.then().assertThat()
.body("data.message", equalTo("Link from Dataverse " + dataverseAlias + " to linked Dataverse " + dataverseAlias2 + " deleted"))
.statusCode(200);
}


// testCreateDeleteDataverseLink was here but is now in LinkIT

@Test
public void testUpdateDefaultContributorRole() {
Response createUser = UtilIT.createRandomUser();
Expand Down
205 changes: 205 additions & 0 deletions src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package edu.harvard.iq.dataverse.api;

import com.jayway.restassured.RestAssured;
import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.response.Response;
import edu.harvard.iq.dataverse.util.BundleUtil;
import java.util.logging.Logger;
import static javax.ws.rs.core.Response.Status.CREATED;
import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static javax.ws.rs.core.Response.Status.OK;
import static org.hamcrest.CoreMatchers.equalTo;
import org.junit.BeforeClass;
import org.junit.Test;

public class LinkIT {

private static final Logger logger = Logger.getLogger(LinkIT.class.getCanonicalName());

@BeforeClass
public static void setUpClass() {
RestAssured.baseURI = UtilIT.getRestAssuredBaseUri();
}

@Test
public void testLinkedDataset() {

Response createUser = UtilIT.createRandomUser();
createUser.prettyPrint();
createUser.then().assertThat()
.statusCode(OK.getStatusCode());
String username = UtilIT.getUsernameFromResponse(createUser);
String apiToken = UtilIT.getApiTokenFromResponse(createUser);

Response createSuperUser = UtilIT.createRandomUser();
createSuperUser.prettyPrint();
createSuperUser.then().assertThat()
.statusCode(OK.getStatusCode());
String superuserUsername = UtilIT.getUsernameFromResponse(createSuperUser);
String superuserApiToken = UtilIT.getApiTokenFromResponse(createSuperUser);
Response makeSuperuser = UtilIT.makeSuperUser(superuserUsername);
makeSuperuser.prettyPrint();
makeSuperuser.then().assertThat()
.statusCode(OK.getStatusCode());

Response createDataverse1 = UtilIT.createRandomDataverse(apiToken);
createDataverse1.prettyPrint();
createDataverse1.then().assertThat()
.statusCode(CREATED.getStatusCode());
String dataverse1Alias = UtilIT.getAliasFromResponse(createDataverse1);

Response createDataset = UtilIT.createRandomDatasetViaNativeApi(dataverse1Alias, apiToken);
createDataset.prettyPrint();
createDataset.then().assertThat()
.statusCode(CREATED.getStatusCode());

Integer datasetId = UtilIT.getDatasetIdFromResponse(createDataset);
String datasetPid = JsonPath.from(createDataset.asString()).getString("data.persistentId");

Response createDataverse2 = UtilIT.createRandomDataverse(apiToken);
createDataverse2.prettyPrint();
createDataverse2.then().assertThat()
.statusCode(CREATED.getStatusCode());
String dataverse2Alias = UtilIT.getAliasFromResponse(createDataverse2);
Integer dataverse2Id = UtilIT.getDatasetIdFromResponse(createDataverse2);
String dataverse2Name = JsonPath.from(createDataverse2.asString()).getString("data.name");

UtilIT.publishDataverseViaNativeApi(dataverse1Alias, apiToken).then().assertThat()
.statusCode(OK.getStatusCode());

// You can't link an unpublished dataset.
Response tryToLinkUnpublishedDataset = UtilIT.linkDataset(datasetPid, dataverse2Alias, superuserApiToken);
tryToLinkUnpublishedDataset.prettyPrint();
tryToLinkUnpublishedDataset.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo("Can't link a dataset that has not been published or is not harvested"));

UtilIT.publishDatasetViaNativeApi(datasetPid, "major", apiToken).then().assertThat()
.statusCode(OK.getStatusCode());

UtilIT.publishDataverseViaNativeApi(dataverse2Alias, apiToken).then().assertThat()
.statusCode(OK.getStatusCode());

// A dataset cannot be linked to its parent dataverse.
Response tryToLinkToParentDataverse = UtilIT.linkDataset(datasetPid, dataverse1Alias, superuserApiToken);
tryToLinkToParentDataverse.prettyPrint();
tryToLinkToParentDataverse.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo("Can't link a dataset to its dataverse"));

// Link dataset to non-parent dataverse (allowed).
Response linkDataset = UtilIT.linkDataset(datasetPid, dataverse2Alias, superuserApiToken);
linkDataset.prettyPrint();
linkDataset.then().assertThat()
.statusCode(OK.getStatusCode());

// A dataset cannot be linked to the same dataverse again.
Response tryToLinkAgain = UtilIT.linkDataset(datasetPid, dataverse2Alias, superuserApiToken);
tryToLinkAgain.prettyPrint();
tryToLinkAgain.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo("Can't link a dataset that has already been linked to this dataverse"));
}

@Test
public void testCreateDeleteDataverseLink() {
Response createUser = UtilIT.createRandomUser();

createUser.prettyPrint();
String username = UtilIT.getUsernameFromResponse(createUser);
String apiToken = UtilIT.getApiTokenFromResponse(createUser);

Response superuserResponse = UtilIT.makeSuperUser(username);

Response createDataverseResponse = UtilIT.createRandomDataverse(apiToken);
createDataverseResponse.prettyPrint();
String dataverseAlias = UtilIT.getAliasFromResponse(createDataverseResponse);
Integer dataverseId = UtilIT.getDataverseIdFromResponse(createDataverseResponse);

Response createDataverseResponse2 = UtilIT.createRandomDataverse(apiToken);
createDataverseResponse2.prettyPrint();
String dataverseAlias2 = UtilIT.getAliasFromResponse(createDataverseResponse2);

Response createLinkingDataverseResponse = UtilIT.createDataverseLink(dataverseAlias, dataverseAlias2, apiToken);
createLinkingDataverseResponse.prettyPrint();
createLinkingDataverseResponse.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.message", equalTo("Dataverse " + dataverseAlias + " linked successfully to " + dataverseAlias2));

Response tryLinkingAgain = UtilIT.createDataverseLink(dataverseAlias, dataverseAlias2, apiToken);
tryLinkingAgain.prettyPrint();
tryLinkingAgain.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo(dataverseAlias + " has already been linked to " + dataverseAlias2 + "."));

Response deleteLinkingDataverseResponse = UtilIT.deleteDataverseLink(dataverseAlias, dataverseAlias2, apiToken);
deleteLinkingDataverseResponse.prettyPrint();
deleteLinkingDataverseResponse.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.message", equalTo("Link from Dataverse " + dataverseAlias + " to linked Dataverse " + dataverseAlias2 + " deleted"));
}

@Test
public void testDeepLinks() {
Response createUser = UtilIT.createRandomUser();

createUser.prettyPrint();
String username = UtilIT.getUsernameFromResponse(createUser);
String apiToken = UtilIT.getApiTokenFromResponse(createUser);

Response superuserResponse = UtilIT.makeSuperUser(username);

Response createLevel1a = UtilIT.createSubDataverse(UtilIT.getRandomDvAlias() + "-level1a", null, apiToken, ":root");
createLevel1a.prettyPrint();
String level1a = UtilIT.getAliasFromResponse(createLevel1a);

Response createLevel1b = UtilIT.createSubDataverse(UtilIT.getRandomDvAlias() + "-level1b", null, apiToken, ":root");
createLevel1b.prettyPrint();
String level1b = UtilIT.getAliasFromResponse(createLevel1b);

Response linkLevel1toLevel1 = UtilIT.createDataverseLink(level1a, level1b, apiToken);
linkLevel1toLevel1.prettyPrint();
linkLevel1toLevel1.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.message", equalTo("Dataverse " + level1a + " linked successfully to " + level1b));

Response searchLevel1toLevel1 = UtilIT.search("*", apiToken, "&subtree=" + level1b);
searchLevel1toLevel1.prettyPrint();
searchLevel1toLevel1.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.total_count", equalTo(1))
.body("data.items[0].name", equalTo(level1a));

/**
* Remove this early return when you are ready to work on
* https://github.com/IQSS/dataverse/issues/7430 about strange linking
* behavior.
*/
if (true) {
return;
}

Response createLevel2a = UtilIT.createSubDataverse(UtilIT.getRandomDvAlias() + "-level2a", null, apiToken, level1a);
createLevel2a.prettyPrint();
String level2a = UtilIT.getAliasFromResponse(createLevel2a);

Response createLevel2b = UtilIT.createSubDataverse(UtilIT.getRandomDvAlias() + "-level2b", null, apiToken, level1b);
createLevel2b.prettyPrint();
String level2b = UtilIT.getAliasFromResponse(createLevel2b);

Response linkLevel2toLevel2 = UtilIT.createDataverseLink(level2a, level2b, apiToken);
linkLevel2toLevel2.prettyPrint();
linkLevel2toLevel2.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.message", equalTo("Dataverse " + level2a + " linked successfully to " + level2b));

Response searchLevel2toLevel2 = UtilIT.search("*", apiToken, "&subtree=" + level2b);
searchLevel2toLevel2.prettyPrint();
searchLevel2toLevel2.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.total_count", equalTo(1))
.body("data.items[0].name", equalTo(level2a));

}

}

0 comments on commit f940279

Please sign in to comment.