Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native API publish: POST, no 0.1, DOIs #2431 #2461 #3483 #3547 #3550

Merged
merged 1 commit into from
Jan 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ Publishes the dataset whose id is passed. The new dataset version number is dete

POST http://$SERVER/api/datasets/$id/actions/:publish?type=$type&key=$apiKey

.. note:: POST should be used to publish a dataset. GET is supported for backward compatibility but is deprecated and may be removed: https://github.com/IQSS/dataverse/issues/2431

Deletes the draft version of dataset ``$id``. Only the draft version can be deleted::

DELETE http://$SERVER/api/datasets/$id/versions/:draft?key=$apiKey
Expand Down
69 changes: 39 additions & 30 deletions src/main/java/edu/harvard/iq/dataverse/api/Datasets.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
@Path("datasets")
public class Datasets extends AbstractApiBean {

private static final Logger LOGGER = Logger.getLogger(Datasets.class.getName());
private static final Logger logger = Logger.getLogger(Datasets.class.getCanonicalName());

private static final String PERSISTENT_ID_KEY=":persistentId";

Expand Down Expand Up @@ -148,7 +148,7 @@ public Response exportDataset(@QueryParam("persistentId") String persistentId, @
// (the way Access API streams its output).
// -- L.A., 4.5

LOGGER.fine("xml to return: " + xml);
logger.fine("xml to return: " + xml);
String mediaType = MediaType.TEXT_PLAIN;
if (instance.isXMLFormat(exporter)){
mediaType = MediaType.APPLICATION_XML;
Expand Down Expand Up @@ -334,7 +334,7 @@ public Response updateDraftVersion( String jsonBody, @PathParam("id") String id,
return ok( json(managedVersion) );

} catch (JsonParseException ex) {
LOGGER.log(Level.SEVERE, "Semantic error parsing dataset version Json: " + ex.getMessage(), ex);
logger.log(Level.SEVERE, "Semantic error parsing dataset version Json: " + ex.getMessage(), ex);
return error( Response.Status.BAD_REQUEST, "Error parsing dataset version: " + ex.getMessage() );

} catch (WrappedResponse ex) {
Expand All @@ -343,36 +343,45 @@ public Response updateDraftVersion( String jsonBody, @PathParam("id") String id,
}
}

/**
* @deprecated This was shipped as a GET but should have been a POST, see https://github.com/IQSS/dataverse/issues/2431
*/
@GET
@Path("{id}/actions/:publish")
public Response publishDataset( @PathParam("id") String id, @QueryParam("type") String type ) {
@Path("{id}/actions/:publish")
@Deprecated
public Response publishDataseUsingGetDeprecated( @PathParam("id") String id, @QueryParam("type") String type ) {
logger.info("publishDataseUsingGetDeprecated called on id " + id + ". Encourage use of POST rather than GET, which is deprecated.");
return publishDataset(id, type);
}

@POST
@Path("{id}/actions/:publish")
public Response publishDataset(@PathParam("id") String id, @QueryParam("type") String type) {
try {
if ( type == null ) {
return error( Response.Status.BAD_REQUEST, "Missing 'type' parameter (either 'major' or 'minor').");
if (type == null) {
return error(Response.Status.BAD_REQUEST, "Missing 'type' parameter (either 'major' or 'minor').");
}

type = type.toLowerCase();
boolean isMinor;
switch ( type ) {
case "minor": isMinor = true; break;
case "major": isMinor = false; break;
default: return error( Response.Status.BAD_REQUEST, "Illegal 'type' parameter value '" + type + "'. It needs to be either 'major' or 'minor'.");
switch (type) {
case "minor":
isMinor = true;
break;
case "major":
isMinor = false;
break;
default:
return error(Response.Status.BAD_REQUEST, "Illegal 'type' parameter value '" + type + "'. It needs to be either 'major' or 'minor'.");
}
long dsId;
try {
dsId = Long.parseLong(id);
} catch ( NumberFormatException nfe ) {
return error( Response.Status.BAD_REQUEST, "Bad dataset id. Please provide a number.");
}

Dataset ds = datasetService.find(dsId);

return ( ds == null ) ? notFound("Can't find dataset with id '" + id + "'")
: ok( json(execCommand(new PublishDatasetCommand(ds,
createDataverseRequest(findAuthenticatedUserOrDie()),
isMinor))) );

} catch (WrappedResponse ex) {

Dataset ds = findDatasetOrDie(id);

return ok(json(execCommand(new PublishDatasetCommand(ds,
createDataverseRequest(findAuthenticatedUserOrDie()),
isMinor))));

} catch (WrappedResponse ex) {
return ex.getResponse();
}
}
Expand Down Expand Up @@ -420,7 +429,7 @@ public Response getDdi(@QueryParam("id") long id, @QueryParam("persistentId") St
return error(Response.Status.FORBIDDEN, "Not a superuser");
}

LOGGER.fine("looking up " + persistentId);
logger.fine("looking up " + persistentId);
Dataset dataset = datasetService.findByGlobalId(persistentId);
if (dataset == null) {
return error(Response.Status.NOT_FOUND, "A dataset with the persistentId " + persistentId + " could not be found.");
Expand All @@ -439,7 +448,7 @@ public Response getDdi(@QueryParam("id") long id, @QueryParam("persistentId") St
ddiExportService.exportDataset(dataset.getId(), outputStream, null, null);
xml = outputStream.toString();
}
LOGGER.fine("xml to return: " + xml);
logger.fine("xml to return: " + xml);

return Response.ok()
.entity(xml)
Expand Down Expand Up @@ -473,7 +482,7 @@ public Response createAssignment(String userOrGroup, @PathParam("identifier") St
return ok(
json(execCommand(new AssignRoleCommand(assignee, theRole, dataset, createDataverseRequest(findUserOrDie()), privateUrlToken))));
} catch (WrappedResponse ex) {
LOGGER.log(Level.WARNING, "Can''t create assignment: {0}", ex.getMessage());
logger.log(Level.WARNING, "Can''t create assignment: {0}", ex.getMessage());
return ex.getResponse();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public Dataset execute(CommandContext ctxt) throws CommandException {
throw new IllegalCommandException("Latest version of dataset " + theDataset.getIdentifier() + " is already released. Only draft versions can be released.", this);
}

// prevent publishing of 0.1 version
if (minorRelease && theDataset.getVersions().size() == 1 && theDataset.getLatestVersion().isDraft()) {
throw new IllegalCommandException("Cannot publish as minor version. Re-try as major release.", this);
}

if (minorRelease && !theDataset.getLatestVersion().isMinorUpdate()) {
throw new IllegalCommandException("Cannot release as minor version. Re-try as major release.", this);
}
Expand Down
23 changes: 21 additions & 2 deletions src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.util.UUID;
import static javax.ws.rs.core.Response.Status.NO_CONTENT;
import static junit.framework.Assert.assertEquals;
import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;

Expand Down Expand Up @@ -91,11 +90,31 @@ public void testCreatePublishDestroyDataset() {
createDatasetResponse.prettyPrint();
Integer datasetId = JsonPath.from(createDatasetResponse.body().asString()).getInt("data.id");

Response getDatasetJsonBeforePublishing = UtilIT.nativeGet(datasetId, apiToken);
getDatasetJsonBeforePublishing.prettyPrint();
String protocol = JsonPath.from(getDatasetJsonBeforePublishing.getBody().asString()).getString("data.protocol");
String authority = JsonPath.from(getDatasetJsonBeforePublishing.getBody().asString()).getString("data.authority");
String identifier = JsonPath.from(getDatasetJsonBeforePublishing.getBody().asString()).getString("data.identifier");
String datasetPersistentId = protocol + ":" + authority + "/" + identifier;

Response publishDataverse = UtilIT.publishDataverseViaSword(dataverseAlias, apiToken);
assertEquals(200, publishDataverse.getStatusCode());
Response publishDataset = UtilIT.publishDatasetViaNativeApi(datasetId, "major", apiToken);
Response attemptToPublishZeroDotOne = UtilIT.publishDatasetViaNativeApiDeprecated(datasetPersistentId, "minor", apiToken);
attemptToPublishZeroDotOne.prettyPrint();
attemptToPublishZeroDotOne.then().assertThat()
.body("message", equalTo("Cannot publish as minor version. Re-try as major release."))
.statusCode(403);

Response publishDataset = UtilIT.publishDatasetViaNativeApi(datasetPersistentId, "major", apiToken);
assertEquals(200, publishDataset.getStatusCode());

Response getDatasetJsonAfterPublishing = UtilIT.nativeGet(datasetId, apiToken);
getDatasetJsonAfterPublishing.prettyPrint();
getDatasetJsonAfterPublishing.then().assertThat()
.body("data.latestVersion.versionNumber", equalTo(1))
.body("data.latestVersion.versionMinorNumber", equalTo(0))
.statusCode(OK.getStatusCode());

Response deleteDatasetResponse = UtilIT.destroyDataset(datasetId, apiToken);
deleteDatasetResponse.prettyPrint();
assertEquals(200, deleteDatasetResponse.getStatusCode());
Expand Down
4 changes: 0 additions & 4 deletions src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -1165,10 +1165,6 @@ private Response publishDatasetViaNative(long datasetId, String apiToken) {
/**
* This should probably be a POST rather than a GET:
* https://github.com/IQSS/dataverse/issues/2431
*
* Allows version less than v1.0 to be published (i.e. v0.1):
* https://github.com/IQSS/dataverse/issues/2461
*
*/
return given()
.header(keyString, apiToken)
Expand Down
23 changes: 18 additions & 5 deletions src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.path.xml.XmlPath.from;
import java.math.BigDecimal;
import java.util.List;
import javax.json.JsonValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
Expand Down Expand Up @@ -426,13 +424,28 @@ static Response publishDatasetViaSword(String persistentId, String apiToken) {
.post(swordConfiguration.getBaseUrlPathCurrent() + "/edit/study/" + persistentId);
}

static Response publishDatasetViaNativeApi(String persistentId, String majorOrMinor, String apiToken) {
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.urlEncodingEnabled(false)
.post("/api/datasets/:persistentId/actions/:publish?type=" + majorOrMinor + "&persistentId=" + persistentId);
}

static Response publishDatasetViaNativeApiDeprecated(String persistentId, String majorOrMinor, String apiToken) {
/**
* @todo This should be a POST rather than a GET:
* https://github.com/IQSS/dataverse/issues/2431
*/
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.urlEncodingEnabled(false)
.get("/api/datasets/:persistentId/actions/:publish?type=" + majorOrMinor + "&persistentId=" + persistentId);
}

static Response publishDatasetViaNativeApi(Integer datasetId, String majorOrMinor, String apiToken) {
/**
* @todo This should be a POST rather than a GET:
* https://github.com/IQSS/dataverse/issues/2431
*
* @todo Prevent version less than v1.0 to be published (i.e. v0.1):
* https://github.com/IQSS/dataverse/issues/2461
*/
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
Expand Down