From 24df2803f49a89619597bf774398704444c1dd02 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Fri, 8 Jul 2016 10:55:13 -0400 Subject: [PATCH] Private URL: avoid commands so Contributor can delete draft #3200 #3201 --- .../impl/DeleteDatasetVersionCommand.java | 22 ++++++++- .../harvard/iq/dataverse/api/DatasetsIT.java | 45 ++----------------- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetVersionCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetVersionCommand.java index 353766a2994..5ff5b71b836 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetVersionCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDatasetVersionCommand.java @@ -3,7 +3,9 @@ import edu.harvard.iq.dataverse.Dataset; import edu.harvard.iq.dataverse.DatasetVersion; import edu.harvard.iq.dataverse.FileMetadata; +import edu.harvard.iq.dataverse.RoleAssignment; import edu.harvard.iq.dataverse.authorization.Permission; +import edu.harvard.iq.dataverse.authorization.users.PrivateUrlUser; import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand; import edu.harvard.iq.dataverse.engine.command.CommandContext; @@ -13,6 +15,7 @@ import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; import edu.harvard.iq.dataverse.privateurl.PrivateUrl; import java.util.Iterator; +import java.util.List; import java.util.logging.Logger; /** @@ -68,10 +71,25 @@ protected void executeImpl(CommandContext ctxt) throws CommandException { dvIt.remove(); } } - PrivateUrl privateUrl = ctxt.engine().submit(new GetPrivateUrlCommand(getRequest(), doomed)); + /** + * DeleteDatasetDraft, which is required by this command, + * DeleteDatasetVersionCommand is not sufficient for running + * GetPrivateUrlCommand nor DeletePrivateUrlCommand, both of + * which require ManageDatasetPermissions because + * DeletePrivateUrlCommand calls RevokeRoleCommand which + * requires ManageDatasetPermissions when executed on a dataset + * so we make direct calls to the service bean so that a lowly + * Contributor who does NOT have ManageDatasetPermissions can + * still successfully delete a Private URL. + */ + PrivateUrl privateUrl = ctxt.privateUrl().getPrivateUrlFromDatasetId(doomed.getId()); if (privateUrl != null) { logger.fine("Deleting Private URL for dataset id " + doomed.getId()); - ctxt.engine().submit(new DeletePrivateUrlCommand(getRequest(), doomed)); + PrivateUrlUser privateUrlUser = new PrivateUrlUser(doomed.getId()); + List roleAssignments = ctxt.roles().directRoleAssignments(privateUrlUser, doomed); + for (RoleAssignment roleAssignment : roleAssignments) { + ctxt.roles().revoke(roleAssignment); + } } boolean doNormalSolrDocCleanUp = true; ctxt.index().indexDataset(doomed, doNormalSolrDocCleanUp); 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 7b964498526..57114710ca7 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -336,48 +336,9 @@ public void testPrivateUrl() { // A Contributor has DeleteDatasetDraft Response deleteDraftVersionAsContributor = UtilIT.deleteDatasetVersionViaNativeApi(datasetId, ":draft", contributorApiToken); deleteDraftVersionAsContributor.prettyPrint(); - boolean bugs3200and3201haveBeenFixed = false; - if (bugs3200and3201haveBeenFixed) { - deleteDraftVersionAsContributor.then().assertThat() - .statusCode(OK.getStatusCode()); - } else { - /** - * The problem here is that the deletion of the dataset version by - * the contributor only half worked! The version is gone but the - * Private URL was not deleted and reindexing didn't happen. The - * DeleteDatasetVersionCommand exited early. If you allow more - * information to be reported, you will see "status:ERROR" and this - * message: - * - * "User @userbaed3c79 is not permitted to perform requested action. - * Can't execute command - * edu.harvard.iq.dataverse.engine.command.impl.GetPrivateUrlCommand@70d1d3e4, - * because request [DataverseRequest - * user:edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser@69@127.0.0.1] - * is missing permissions [ManageDatasetPermissions] on Object - * Darwin's Finches. granted: [ViewUnpublishedDataset, DownloadFile, - * EditDataset, DeleteDatasetDraft]" - * - * This is fairly awful because you are left with the impression - * that the deletion of the dataset version did not happen - * (UNAUTHORIZED) but it really did! Yikes! - * - * To get the dataset out of its invalid state (indexing cruft left - * behind and a Private URL on a published version), we create a new - * draft. - */ - deleteDraftVersionAsContributor.then().assertThat() - .statusCode(UNAUTHORIZED.getStatusCode()) - .body("message", equalTo("User @" + contributorUsername + " is not permitted to perform requested action.")); - String workaroundTitle = "I am creating a new draft as a workaround while bugs 3200 and 3100 exist. This way the creator can delete it cleanly."; - Response workAroundSoWeCanDeleteDraft = UtilIT.updateDatasetTitleViaSword(dataset1PersistentId, workaroundTitle, apiToken); - workAroundSoWeCanDeleteDraft.prettyPrint(); - assertEquals(OK.getStatusCode(), workAroundSoWeCanDeleteDraft.getStatusCode()); - Response deleteDraftVersionAsCreator = UtilIT.deleteDatasetVersionViaNativeApi(datasetId, ":draft", apiToken); - deleteDraftVersionAsCreator.prettyPrint(); - deleteDraftVersionAsCreator.then().assertThat() - .statusCode(OK.getStatusCode()); - } + deleteDraftVersionAsContributor.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data.message", equalTo("Draft version of dataset " + datasetId + " deleted")); Response privateUrlRoleAssignmentShouldBeGoneAfterDraftDeleted = UtilIT.getRoleAssignmentsOnDataset(datasetId.toString(), null, apiToken); privateUrlRoleAssignmentShouldBeGoneAfterDraftDeleted.prettyPrint();