From ba9b90e743a77aad735aeaf438c966fc6e437d84 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 5 Feb 2020 16:44:41 -0500 Subject: [PATCH 01/17] #6290 add DS Role api and tests --- .../harvard/iq/dataverse/api/Datasets.java | 36 +++++++--- .../harvard/iq/dataverse/api/DatasetsIT.java | 69 +++++++++++++++++++ .../edu/harvard/iq/dataverse/api/UtilIT.java | 11 ++- 3 files changed, 104 insertions(+), 12 deletions(-) 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 7fa85473d1a..ec02834fd04 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -77,6 +77,7 @@ import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import edu.harvard.iq.dataverse.S3PackageImporter; import static edu.harvard.iq.dataverse.api.AbstractApiBean.error; +import edu.harvard.iq.dataverse.api.dto.RoleAssignmentDTO; import edu.harvard.iq.dataverse.batch.util.LoggingUtil; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.UnforcedCommandException; @@ -135,6 +136,7 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import javax.ws.rs.core.UriInfo; import org.apache.solr.client.solrj.SolrServerException; @@ -1082,24 +1084,38 @@ public Response getLinks(@PathParam("id") String idSupplied ) { } /** - * @todo Make this real. Currently only used for API testing. Copied from - * the equivalent API endpoint for dataverses and simplified with values - * hard coded. + * Add a given assignment to a given user or group + * @param ra role assignment DTO + * @param id dataset id + * @param apiKey */ @POST @Path("{identifier}/assignments") - public Response createAssignment(String userOrGroup, @PathParam("identifier") String id, @QueryParam("key") String apiKey) { - boolean apiTestingOnly = true; - if (apiTestingOnly) { - return error(Response.Status.FORBIDDEN, "This is only for API tests."); - } + public Response createAssignment(RoleAssignmentDTO ra, @PathParam("identifier") String id, @QueryParam("key") String apiKey) { try { Dataset dataset = findDatasetOrDie(id); - RoleAssignee assignee = findAssignee(userOrGroup); + + RoleAssignee assignee = findAssignee(ra.getAssignee()); if (assignee == null) { return error(Response.Status.BAD_REQUEST, "Assignee not found"); + } + + DataverseRole theRole; + Dataverse dv = dataset.getOwner(); + theRole = null; + while ((theRole == null) && (dv != null)) { + for (DataverseRole aRole : rolesSvc.availableRoles(dv.getId())) { + if (aRole.getAlias().equals(ra.getRole())) { + theRole = aRole; + break; + } + } + dv = dv.getOwner(); } - DataverseRole theRole = rolesSvc.findBuiltinRoleByAlias("admin"); + if (theRole == null) { + return error(Status.BAD_REQUEST, "Can't find role named '" + ra.getRole() + "' in dataverse " + dataset.getOwner()); + } + String privateUrlToken = null; return ok( json(execCommand(new AssignRoleCommand(assignee, theRole, dataset, createDataverseRequest(findUserOrDie()), privateUrlToken)))); 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 666f006ce3e..69712914b63 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -32,6 +32,7 @@ import static com.jayway.restassured.path.json.JsonPath.with; import com.jayway.restassured.path.xml.XmlPath; import static edu.harvard.iq.dataverse.api.UtilIT.equalToCI; +import static edu.harvard.iq.dataverse.authorization.AuthenticationResponse.Status.ERROR; import edu.harvard.iq.dataverse.authorization.groups.impl.builtin.AuthenticatedUsers; import edu.harvard.iq.dataverse.util.SystemConfig; import java.io.IOException; @@ -46,6 +47,7 @@ import org.junit.AfterClass; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.matchers.JUnitMatchers.containsString; public class DatasetsIT { @@ -1101,6 +1103,73 @@ public void testPrivateUrl() { * @todo Should the Search API work with the Private URL token? */ } + + @Test + public void testAddRoles(){ + + Response createUser = UtilIT.createRandomUser(); + createUser.prettyPrint(); + String username = UtilIT.getUsernameFromResponse(createUser); + String apiToken = UtilIT.getApiTokenFromResponse(createUser); + + Response createDataverseResponse = UtilIT.createRandomDataverse(apiToken); + createDataverseResponse.prettyPrint(); + String dataverseAlias = UtilIT.getAliasFromResponse(createDataverseResponse); + + Response createDatasetResponse = UtilIT.createRandomDatasetViaNativeApi(dataverseAlias, apiToken); + createDatasetResponse.prettyPrint(); + Integer datasetId = UtilIT.getDatasetIdFromResponse(createDatasetResponse); + + Response datasetAsJson = UtilIT.nativeGet(datasetId, apiToken); + datasetAsJson.then().assertThat() + .statusCode(OK.getStatusCode()); + + String identifier = JsonPath.from(datasetAsJson.getBody().asString()).getString("data.identifier"); + assertEquals(10, identifier.length()); + + String protocol1 = JsonPath.from(datasetAsJson.getBody().asString()).getString("data.protocol"); + String authority1 = JsonPath.from(datasetAsJson.getBody().asString()).getString("data.authority"); + String identifier1 = JsonPath.from(datasetAsJson.getBody().asString()).getString("data.identifier"); + String datasetPersistentId = protocol1 + ":" + authority1 + "/" + identifier1; + + + + // Create another random user: + + Response createRandomUser = UtilIT.createRandomUser(); + createRandomUser.prettyPrint(); + String randomUsername = UtilIT.getUsernameFromResponse(createRandomUser); + String randomUserApiToken = UtilIT.getApiTokenFromResponse(createRandomUser); + + + //Give that random user permission + //(String definitionPoint, String role, String roleAssignee, String apiToken) + + Response giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, apiToken); + giveRandoPermission.prettyPrint(); + assertEquals(200, giveRandoPermission.getStatusCode()); + + giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "designatedHitter", "@" + randomUsername, apiToken); + giveRandoPermission.prettyPrint(); + giveRandoPermission.then().assertThat() + .contentType(ContentType.JSON) + .body("message", containsString("Can't find role named 'designatedHitter' in dataverse ")) + .statusCode(400); + assertEquals(400, giveRandoPermission.getStatusCode()); + + Response deleteDatasetResponse = UtilIT.deleteDatasetViaNativeApi(datasetId, apiToken); + deleteDatasetResponse.prettyPrint(); + assertEquals(200, deleteDatasetResponse.getStatusCode()); + + Response deleteDataverseResponse = UtilIT.deleteDataverse(dataverseAlias, apiToken); + deleteDataverseResponse.prettyPrint(); + assertEquals(200, deleteDataverseResponse.getStatusCode()); + + Response deleteUserResponse = UtilIT.deleteUser(username); + deleteUserResponse.prettyPrint(); + assertEquals(200, deleteUserResponse.getStatusCode()); + + } @Test public void testFileChecksum() { diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index ed7de84de8d..0bb03194ecf 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1587,10 +1587,17 @@ static Response getRoleAssignmentsOnDataset(String datasetId, String persistentI } static Response grantRoleOnDataset(String definitionPoint, String role, String roleAssignee, String apiToken) { + + JsonObjectBuilder roleBuilder = Json.createObjectBuilder(); + roleBuilder.add("assignee", roleAssignee); + roleBuilder.add("role", role); + + JsonObject roleObject = roleBuilder.build(); logger.info("Granting role on dataset \"" + definitionPoint + "\": " + role); return given() - .body("@" + roleAssignee) - .post("api/datasets/" + definitionPoint + "/assignments?key=" + apiToken); + .body(roleObject.toString()) + .contentType(ContentType.JSON) + .post("api/datasets/:persistentId/assignments?key=" + apiToken + "&persistentId=" + definitionPoint); } static Response revokeRole(String definitionPoint, long doomed, String apiToken) { From dac1ad19f76bbb083e1f9668f2e20abf86009336 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 6 Feb 2020 11:11:49 -0500 Subject: [PATCH 02/17] #6290 cannot add role without permission --- src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 69712914b63..bfda75a465a 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -1144,8 +1144,12 @@ public void testAddRoles(){ //Give that random user permission //(String definitionPoint, String role, String roleAssignee, String apiToken) + //Can't give yourself permission + Response giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, randomUserApiToken); + giveRandoPermission.prettyPrint(); + assertEquals(401, giveRandoPermission.getStatusCode()); - Response giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, apiToken); + giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "fileDownloader", "@" + randomUsername, apiToken); giveRandoPermission.prettyPrint(); assertEquals(200, giveRandoPermission.getStatusCode()); From ba7f66c10555cc0e03fc9052f470e5dde4a5a026 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 6 Feb 2020 15:50:02 -0500 Subject: [PATCH 03/17] #6290 Add doc to dataset role api --- doc/sphinx-guides/source/api/native-api.rst | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 541a1fbf273..45ced8545a0 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -952,6 +952,34 @@ List Role Assignments for a Dataset List all the role assignments at the given dataset:: GET http://$SERVER/api/datasets/$id/assignments?key=$apiKey + +.. _assign-role-on-a-dataverse-api: + +Assign a New Role on a Dataset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Assigns a new role, based on the POSTed JSON: + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=xxxxxx + + curl -H X-Dataverse-key:$API_TOKEN -X POST $SERVER_URL/api/datasets/$ID/assignments --upload-file role.json + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST https://demo.dataverse.org/api/datasets/xxxxxx/assignments --upload-file role.json + +POSTed JSON example (the content of ``role.json`` file):: + + { + "assignee": "@uma", + "role": "curator" + } Create a Private URL for a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 039bd5e199ff50b4426a249bf60cf8b465e8742f Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 10 Feb 2020 14:18:09 -0500 Subject: [PATCH 04/17] #6920 add revoke role api for datasets --- .../harvard/iq/dataverse/api/Datasets.java | 22 +++++++++++++++++++ .../harvard/iq/dataverse/api/DatasetsIT.java | 13 +++++++++++ .../edu/harvard/iq/dataverse/api/UtilIT.java | 7 ++++++ 3 files changed, 42 insertions(+) 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 d581676a55e..d3f4f3d54b4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -16,10 +16,12 @@ import edu.harvard.iq.dataverse.DataverseRequestServiceBean; import edu.harvard.iq.dataverse.DataverseServiceBean; import edu.harvard.iq.dataverse.DataverseSession; +import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.EjbDataverseEngine; import edu.harvard.iq.dataverse.MetadataBlock; import edu.harvard.iq.dataverse.MetadataBlockServiceBean; import edu.harvard.iq.dataverse.PermissionServiceBean; +import edu.harvard.iq.dataverse.RoleAssignment; import edu.harvard.iq.dataverse.UserNotification; import edu.harvard.iq.dataverse.UserNotificationServiceBean; import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean; @@ -82,6 +84,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.UnforcedCommandException; import edu.harvard.iq.dataverse.engine.command.impl.GetDatasetStorageSizeCommand; +import edu.harvard.iq.dataverse.engine.command.impl.RevokeRoleCommand; import edu.harvard.iq.dataverse.engine.command.impl.UpdateDvObjectPIDMetadataCommand; import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitations; import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitationsServiceBean; @@ -1126,6 +1129,25 @@ public Response createAssignment(RoleAssignmentDTO ra, @PathParam("identifier") return ex.getResponse(); } } + + @DELETE + @Path("{identifier}/assignments/{id}") + public Response deleteAssignment(@PathParam("id") long assignmentId, @PathParam("identifier") String dsId) { + RoleAssignment ra = em.find(RoleAssignment.class, assignmentId); + if (ra != null) { + try { + findDatasetOrDie(dsId); + execCommand(new RevokeRoleCommand(ra, createDataverseRequest(findUserOrDie()))); + return ok("Role " + ra.getRole().getName() + + " revoked for assignee " + ra.getAssigneeIdentifier() + + " in " + ra.getDefinitionPoint().accept(DvObject.NamePrinter)); + } catch (WrappedResponse ex) { + return ex.getResponse(); + } + } else { + return error(Status.NOT_FOUND, "Role assignment " + assignmentId + " not found"); + } + } @GET @Path("{identifier}/assignments") 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 bfda75a465a..b19e6ab6584 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -1153,6 +1153,8 @@ public void testAddRoles(){ giveRandoPermission.prettyPrint(); assertEquals(200, giveRandoPermission.getStatusCode()); + String idToDelete = JsonPath.from(giveRandoPermission.getBody().asString()).getString("data.id"); + giveRandoPermission = UtilIT.grantRoleOnDataset(datasetPersistentId, "designatedHitter", "@" + randomUsername, apiToken); giveRandoPermission.prettyPrint(); giveRandoPermission.then().assertThat() @@ -1161,6 +1163,17 @@ public void testAddRoles(){ .statusCode(400); assertEquals(400, giveRandoPermission.getStatusCode()); + //Try to delete Role with Id saved above + //Fails for lack of perms + Response deleteGrantedAccess = UtilIT.revokeRoleOnDataset(datasetPersistentId, new Long(idToDelete), randomUserApiToken); + deleteGrantedAccess.prettyPrint(); + assertEquals(401, deleteGrantedAccess.getStatusCode()); + + //Should be able to delete with proper apiToken + deleteGrantedAccess = UtilIT.revokeRoleOnDataset(datasetPersistentId, new Long(idToDelete), apiToken); + deleteGrantedAccess.prettyPrint(); + assertEquals(200, deleteGrantedAccess.getStatusCode()); + Response deleteDatasetResponse = UtilIT.deleteDatasetViaNativeApi(datasetId, apiToken); deleteDatasetResponse.prettyPrint(); assertEquals(200, deleteDatasetResponse.getStatusCode()); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index d44f63fc6dc..c609b400f7e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1606,6 +1606,13 @@ static Response revokeRole(String definitionPoint, long doomed, String apiToken) .delete("api/dataverses/" + definitionPoint + "/assignments/" + doomed); } + static Response revokeRoleOnDataset(String definitionPoint, long doomed, String apiToken) { + + return given() + .header(API_TOKEN_HTTP_HEADER, apiToken) + .delete("api/datasets/:persistentId/assignments/" + doomed + "?persistentId=" + definitionPoint); + } + static Response revokeFileAccess(String definitionPoint, String doomed, String apiToken) { return given() .header(API_TOKEN_HTTP_HEADER, apiToken) From 9eb308ad82a2de3fd4bbd8d16e2c9fe47325b15a Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 10 Feb 2020 16:01:14 -0500 Subject: [PATCH 05/17] #6290 bundle-ize api messages --- .../edu/harvard/iq/dataverse/api/Datasets.java | 17 ++++++++++------- src/main/java/propertyFiles/Bundle.properties | 6 +++++- .../harvard/iq/dataverse/api/DatasetsIT.java | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) 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 d3f4f3d54b4..bf54b9bd696 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Datasets.java @@ -1102,7 +1102,7 @@ public Response createAssignment(RoleAssignmentDTO ra, @PathParam("identifier") RoleAssignee assignee = findAssignee(ra.getAssignee()); if (assignee == null) { - return error(Response.Status.BAD_REQUEST, "Assignee not found"); + return error(Response.Status.BAD_REQUEST, BundleUtil.getStringFromBundle("datasets.api.grant.role.assignee.not.found.error")); } DataverseRole theRole; @@ -1118,16 +1118,19 @@ public Response createAssignment(RoleAssignmentDTO ra, @PathParam("identifier") dv = dv.getOwner(); } if (theRole == null) { - return error(Status.BAD_REQUEST, "Can't find role named '" + ra.getRole() + "' in dataverse " + dataset.getOwner()); + List args = Arrays.asList(ra.getRole(), dataset.getOwner().getDisplayName()); + return error(Status.BAD_REQUEST, BundleUtil.getStringFromBundle("datasets.api.grant.role.not.found.error", args)); } String privateUrlToken = null; 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()); + List args = Arrays.asList(ex.getMessage()); + logger.log(Level.WARNING, BundleUtil.getStringFromBundle("datasets.api.grant.role.cant.create.assignment.error", args)); return ex.getResponse(); } + } @DELETE @@ -1138,14 +1141,14 @@ public Response deleteAssignment(@PathParam("id") long assignmentId, @PathParam( try { findDatasetOrDie(dsId); execCommand(new RevokeRoleCommand(ra, createDataverseRequest(findUserOrDie()))); - return ok("Role " + ra.getRole().getName() - + " revoked for assignee " + ra.getAssigneeIdentifier() - + " in " + ra.getDefinitionPoint().accept(DvObject.NamePrinter)); + List args = Arrays.asList(ra.getRole().getName(), ra.getAssigneeIdentifier(), ra.getDefinitionPoint().accept(DvObject.NamePrinter)); + return ok(BundleUtil.getStringFromBundle("datasets.api.revoke.role.success", args)); } catch (WrappedResponse ex) { return ex.getResponse(); } } else { - return error(Status.NOT_FOUND, "Role assignment " + assignmentId + " not found"); + List args = Arrays.asList(Long.toString(assignmentId)); + return error(Status.NOT_FOUND, BundleUtil.getStringFromBundle("datasets.api.revoke.role.not.found.error", args)); } } diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 04b19bb59ee..1d54a749d9a 100755 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -2229,7 +2229,11 @@ datasets.api.listing.error=Fatal error trying to list the contents of the datase datasets.api.datasize.storage=Total size of the files stored in this dataset: {0} bytes datasets.api.datasize.download=Total size of the files available for download in this version of the dataset: {0} bytes datasets.api.datasize.ioerror=Fatal IO error while trying to determine the total size of the files stored in the dataset. Please report this error to the Dataverse administrator. - +datasets.api.grant.role.not.found.error=Cannot find role named ''{0}'' in dataverse {1} +datasets.api.grant.role.cant.create.assignment.error=Cannot create assignment: {0} +datasets.api.grant.role.assignee.not.found.error=Assignee not found +datasets.api.revoke.role.not.found.error="Role assignment {0} not found" +datasets.api.revoke.role.success=Role {0} revoked for assignee {1} in {2} #Dataverses.java dataverses.api.update.default.contributor.role.failure.role.not.found=Role {0} not found. 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 b19e6ab6584..51d3a214d5d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -1159,7 +1159,7 @@ public void testAddRoles(){ giveRandoPermission.prettyPrint(); giveRandoPermission.then().assertThat() .contentType(ContentType.JSON) - .body("message", containsString("Can't find role named 'designatedHitter' in dataverse ")) + .body("message", containsString("Cannot find role named 'designatedHitter' in dataverse ")) .statusCode(400); assertEquals(400, giveRandoPermission.getStatusCode()); From f341af23adf611ef08b01a94b061cedd07521e4e Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 10 Feb 2020 17:15:46 -0500 Subject: [PATCH 06/17] #6290 Add doc for revoke role on Dataset --- doc/sphinx-guides/source/api/native-api.rst | 25 ++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 45ced8545a0..b7cfa8db4ab 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -979,7 +979,30 @@ POSTed JSON example (the content of ``role.json`` file):: { "assignee": "@uma", "role": "curator" - } + } + +.. _revoke-role-on-a-dataset-api: + +Delete Role Assignment from a Dataset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Delete the assignment whose id is ``$id``: + +.. code-block:: bash + + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=2347 + export ASSIGNMENT_ID=6 + + curl -H X-Dataverse-key:$API_TOKEN -X DELETE $SERVER_URL/api/dataverses/$ID/assignments/$ASSIGNMENT_ID + +The fully expanded example above (without environment variables) looks like this: + +.. code-block:: bash + + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X DELETE https://demo.dataverse.org/api/datasets/2347/assignments/6 + Create a Private URL for a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From fed7f86ca2c0d59fcbc9eae44c7024de76b02260 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Mon, 10 Feb 2020 17:17:35 -0500 Subject: [PATCH 07/17] #6290 fix doc typo --- doc/sphinx-guides/source/api/native-api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index b7cfa8db4ab..8517f33ab7b 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -995,7 +995,7 @@ Delete the assignment whose id is ``$id``: export ID=2347 export ASSIGNMENT_ID=6 - curl -H X-Dataverse-key:$API_TOKEN -X DELETE $SERVER_URL/api/dataverses/$ID/assignments/$ASSIGNMENT_ID + curl -H X-Dataverse-key:$API_TOKEN -X DELETE $SERVER_URL/api/datasets/$ID/assignments/$ASSIGNMENT_ID The fully expanded example above (without environment variables) looks like this: From 71e3e036dbc043619f40d8c0e7ecbff614738a38 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 11 Feb 2020 09:59:16 -0500 Subject: [PATCH 08/17] #6290 fix list dataset roles after merge conflict --- doc/sphinx-guides/source/api/native-api.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 40373cc181d..325a4d7db96 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1018,13 +1018,19 @@ The fully expanded example above (without environment variables) looks like this curl -H "X-Dataverse-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE https://demo.dataverse.org/api/datasets/24/citationdate -List Role Assignments for a Dataset -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +List Role Assignments in a Dataset +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ List all the role assignments at the given dataset: +export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +export SERVER_URL=https://demo.dataverse.org +export ID=2347 + +curl -H X-Dataverse-key:$API_TOKEN $SERVER_URL/api/datasets/$ID/assignments +The fully expanded example above (without environment variables) looks like this: - GET http://$SERVER/api/datasets/$id/assignments?key=$apiKey +curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/datasets/2347/assignments .. _assign-role-on-a-dataverse-api: From a064189b23917095a0c5e10bd641ff415bc50bd6 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 11 Feb 2020 10:02:09 -0500 Subject: [PATCH 09/17] #6290 add code block tags --- doc/sphinx-guides/source/api/native-api.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 325a4d7db96..29d44bf055a 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1022,14 +1022,18 @@ List Role Assignments in a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ List all the role assignments at the given dataset: +.. code-block:: bash export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx export SERVER_URL=https://demo.dataverse.org export ID=2347 curl -H X-Dataverse-key:$API_TOKEN $SERVER_URL/api/datasets/$ID/assignments + The fully expanded example above (without environment variables) looks like this: +.. code-block:: bash + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/datasets/2347/assignments .. _assign-role-on-a-dataverse-api: From d1dafdcbc509f16e9317e183fe91970c88dae260 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 11 Feb 2020 10:04:49 -0500 Subject: [PATCH 10/17] reformat --- doc/sphinx-guides/source/api/native-api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 29d44bf055a..2a227baa881 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1022,6 +1022,7 @@ List Role Assignments in a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ List all the role assignments at the given dataset: + .. code-block:: bash export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx From 4e3de66da0c87290b90a129b1848fb6cf4ed1a84 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 11 Feb 2020 10:08:58 -0500 Subject: [PATCH 11/17] once again --- doc/sphinx-guides/source/api/native-api.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 2a227baa881..ce911937afa 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1018,6 +1018,8 @@ The fully expanded example above (without environment variables) looks like this curl -H "X-Dataverse-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X DELETE https://demo.dataverse.org/api/datasets/24/citationdate +.. _list-roles-on-a-dataset-api: + List Role Assignments in a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1037,7 +1039,7 @@ The fully expanded example above (without environment variables) looks like this curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/datasets/2347/assignments -.. _assign-role-on-a-dataverse-api: +.. _assign-role-on-a-dataset-api: Assign a New Role on a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 9a1ff014e9b4da99db35941d392c5c32e8a92228 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 11 Feb 2020 10:12:11 -0500 Subject: [PATCH 12/17] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index ce911937afa..95153040bbc 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1023,22 +1023,22 @@ The fully expanded example above (without environment variables) looks like this List Role Assignments in a Dataset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -List all the role assignments at the given dataset: +Lists all role assignments on a given dataset: .. code-block:: bash -export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -export SERVER_URL=https://demo.dataverse.org -export ID=2347 + export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + export SERVER_URL=https://demo.dataverse.org + export ID=2347 -curl -H X-Dataverse-key:$API_TOKEN $SERVER_URL/api/datasets/$ID/assignments + curl -H X-Dataverse-key:$API_TOKEN -X GET $SERVER_URL/api/datasets/$ID/assignments The fully expanded example above (without environment variables) looks like this: .. code-block:: bash -curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/datasets/2347/assignments - + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X GET https://demo.dataverse.org/api/datasets/2347/assignments + .. _assign-role-on-a-dataset-api: Assign a New Role on a Dataset @@ -1050,7 +1050,7 @@ Assigns a new role, based on the POSTed JSON: export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx export SERVER_URL=https://demo.dataverse.org - export ID=xxxxxx + export ID=2347 curl -H X-Dataverse-key:$API_TOKEN -X POST $SERVER_URL/api/datasets/$ID/assignments --upload-file role.json @@ -1058,7 +1058,7 @@ The fully expanded example above (without environment variables) looks like this .. code-block:: bash - curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST https://demo.dataverse.org/api/datasets/xxxxxx/assignments --upload-file role.json + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST https://demo.dataverse.org/api/datasets/2347/assignments --upload-file role.json POSTed JSON example (the content of ``role.json`` file):: From 0a7d066e34521566cc0308f259c1b0f70df8d60e Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Tue, 11 Feb 2020 10:13:28 -0500 Subject: [PATCH 13/17] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 95153040bbc..ecc6371ebf3 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1031,13 +1031,13 @@ Lists all role assignments on a given dataset: export SERVER_URL=https://demo.dataverse.org export ID=2347 - curl -H X-Dataverse-key:$API_TOKEN -X GET $SERVER_URL/api/datasets/$ID/assignments + curl -H X-Dataverse-key:$API_TOKEN -X $SERVER_URL/api/datasets/$ID/assignments The fully expanded example above (without environment variables) looks like this: .. code-block:: bash - curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X GET https://demo.dataverse.org/api/datasets/2347/assignments + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X https://demo.dataverse.org/api/datasets/2347/assignments .. _assign-role-on-a-dataset-api: From 60988887c50f76081d24672fd396aea087419aee Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 12 Feb 2020 15:29:12 -0500 Subject: [PATCH 14/17] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index ecc6371ebf3..8181cacb720 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1031,13 +1031,13 @@ Lists all role assignments on a given dataset: export SERVER_URL=https://demo.dataverse.org export ID=2347 - curl -H X-Dataverse-key:$API_TOKEN -X $SERVER_URL/api/datasets/$ID/assignments + curl -H X-Dataverse-key:$API_TOKEN $SERVER_URL/api/datasets/$ID/assignments The fully expanded example above (without environment variables) looks like this: .. code-block:: bash - curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X https://demo.dataverse.org/api/datasets/2347/assignments + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/datasets/2347/assignments .. _assign-role-on-a-dataset-api: From 7288f919adcf4d8b287628bf568c623d3413d4ad Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Wed, 12 Feb 2020 17:14:56 -0500 Subject: [PATCH 15/17] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 8181cacb720..9b149b53a6f 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1052,13 +1052,13 @@ Assigns a new role, based on the POSTed JSON: export SERVER_URL=https://demo.dataverse.org export ID=2347 - curl -H X-Dataverse-key:$API_TOKEN -X POST $SERVER_URL/api/datasets/$ID/assignments --upload-file role.json + curl -H X-Dataverse-key:$API_TOKEN -X POST -H "Content-Type: application/json" $SERVER_URL/api/datasets/$ID/assignments --upload-file role.json The fully expanded example above (without environment variables) looks like this: .. code-block:: bash - curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST https://demo.dataverse.org/api/datasets/2347/assignments --upload-file role.json + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST -H "Content-Type: application/json" https://demo.dataverse.org/api/datasets/2347/assignments --upload-file role.json POSTed JSON example (the content of ``role.json`` file):: From 9e311549b4f43efdbf376dbce262af155486f637 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 13 Feb 2020 10:07:42 -0500 Subject: [PATCH 16/17] #6290 get role assignments at DV level for DS --- .../dataverse/engine/command/impl/ListRoleAssignments.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ListRoleAssignments.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ListRoleAssignments.java index ed438bc3815..1858ba377ab 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ListRoleAssignments.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/ListRoleAssignments.java @@ -8,6 +8,7 @@ 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 java.util.ArrayList; import java.util.List; /** @@ -25,6 +26,12 @@ public ListRoleAssignments(DataverseRequest aRequest, DvObject aDefinitionPoint) @Override public List execute(CommandContext ctxt) throws CommandException { + if(definitionPoint.isInstanceofDataset()){ + List retVal = new ArrayList(); + retVal.addAll(ctxt.permissions().assignmentsOn(definitionPoint)); + retVal.addAll(ctxt.permissions().assignmentsOn(definitionPoint.getOwner())); + return retVal; + } return ctxt.permissions().assignmentsOn(definitionPoint); } From b7b3645e70411c60526527df5920cb2708d78802 Mon Sep 17 00:00:00 2001 From: Stephen Kraffmiller Date: Thu, 13 Feb 2020 10:43:35 -0500 Subject: [PATCH 17/17] Update native-api.rst --- doc/sphinx-guides/source/api/native-api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 7d90a80612d..4a1653b9a9c 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -315,13 +315,13 @@ Assigns a new role, based on the POSTed JSON: export SERVER_URL=https://demo.dataverse.org export ID=root - curl -H X-Dataverse-key:$API_TOKEN -X POST $SERVER_URL/api/dataverses/$ID/assignments --upload-file role.json + curl -H X-Dataverse-key:$API_TOKEN -X POST -H "Content-Type: application/json" $SERVER_URL/api/dataverses/$ID/assignments --upload-file role.json The fully expanded example above (without environment variables) looks like this: .. code-block:: bash - curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST https://demo.dataverse.org/api/dataverses/root/assignments --upload-file role.json + curl -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -X POST -H "Content-Type: application/json" https://demo.dataverse.org/api/dataverses/root/assignments --upload-file role.json POSTed JSON example (the content of ``role.json`` file)::