diff --git a/doc/release-notes/12323-get-inherited-guestbooks-list-api.md b/doc/release-notes/12323-get-inherited-guestbooks-list-api.md new file mode 100644 index 00000000000..89516d65653 --- /dev/null +++ b/doc/release-notes/12323-get-inherited-guestbooks-list-api.md @@ -0,0 +1,2 @@ +Added 'includeInherited' to query parameters of /api/guestbooks/{ID}/list?includeInherited=true to return the Collection's Guestbooks as well as the Guestbooks of the Collections' hierarchical owners +Also removed the 'EditDataverse' permission requirement to get the list. diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 8fe87ad5e65..4596fd6a6e5 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1223,7 +1223,6 @@ Get a list of Guestbooks for a Dataverse Collection For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide. Get a list of Guestbooks for a Dataverse Collection -You must have "EditDataverse" permission on the Dataverse collection. .. code-block:: bash @@ -1239,6 +1238,12 @@ 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/guestbooks/root/list" +To include the inherited Guestbooks of the Dataverse Collection add the query parameter `includeInherited=true` + +.. code-block:: bash + + curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/guestbooks/root/list?includeInherited=true" + Get a Guestbook for a Dataverse Collection ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/main/java/edu/harvard/iq/dataverse/GuestbookServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/GuestbookServiceBean.java index fc7f361b8b6..4199846efd9 100644 --- a/src/main/java/edu/harvard/iq/dataverse/GuestbookServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/GuestbookServiceBean.java @@ -33,6 +33,17 @@ public List findGuestbooksForGivenDataverse(Dataverse dataverse) { return List.of(); } } + // Get all guestbooks for this collection and it's parent collections + public List findEffectiveGuestbooksForGivenDataverse(Dataverse dataverse) { + List guestbooks = findGuestbooksForGivenDataverse(dataverse); + if (dataverse != null) { + List parentDataverses = dataverse.getOwners(); + for (Dataverse dv : parentDataverses) { + guestbooks.addAll(findGuestbooksForGivenDataverse(dv)); + } + } + return guestbooks; + } public Long findCountUsages(Long guestbookId, Long dataverseId) { String queryString = ""; diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Guestbooks.java b/src/main/java/edu/harvard/iq/dataverse/api/Guestbooks.java index e95d7fd8485..cab58378fc6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Guestbooks.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Guestbooks.java @@ -57,13 +57,12 @@ public Response getGuestbook(@Context ContainerRequestContext crc, @PathParam("i @GET @AuthRequired @Path("{identifier}/list") - public Response getGuestbooks(@Context ContainerRequestContext crc, @PathParam("identifier") String identifier) { + public Response getGuestbooks(@Context ContainerRequestContext crc, @PathParam("identifier") String identifier, @QueryParam("includeInherited") boolean includeInherited) { return response( req -> { Dataverse dataverse = findDataverseOrDie(identifier); - if (!permissionSvc.request(req).on(dataverse).has(Permission.EditDataverse)) { - return error(Response.Status.FORBIDDEN, "Not authorized"); - } - List guestbooks = guestbookService.findGuestbooksForGivenDataverse(dataverse); + List guestbooks = (includeInherited) ? guestbookService.findEffectiveGuestbooksForGivenDataverse(dataverse): + guestbookService.findGuestbooksForGivenDataverse(dataverse); + JsonArrayBuilder guestbookArray = Json.createArrayBuilder(); JsonPrinter jsonPrinter = new JsonPrinter(); for (Guestbook gb : guestbooks) { diff --git a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java index 1e06bd4eed4..3435b6d5bf7 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java @@ -3876,8 +3876,16 @@ public void testDownloadFileWithGuestbookResponse() throws IOException, JsonPars String superusername = UtilIT.getUsernameFromResponse(createUserResponse); UtilIT.makeSuperUser(superusername).then().assertThat().statusCode(200); + // Create Parent Dataverse + String parentDataverseAlias = createDataverseGetAlias(ownerApiToken); + Response publishResponse = UtilIT.publishDataverseViaNativeApi(parentDataverseAlias, ownerApiToken); + assertEquals(200, publishResponse.getStatusCode()); + // Create a Parent Guestbook + Guestbook parentGuestbook = UtilIT.createRandomGuestbook(parentDataverseAlias, null, ownerApiToken); + // Create Dataverse String dataverseAlias = createDataverseGetAlias(ownerApiToken); + UtilIT.moveDataverse(dataverseAlias, parentDataverseAlias, null, ownerApiToken); // Create user with no permission createUserResponse = UtilIT.createRandomUser(); @@ -3912,6 +3920,10 @@ public void testDownloadFileWithGuestbookResponse() throws IOException, JsonPars getGuestbooksResponse = UtilIT.getGuestbooks(dataverseAlias, ownerApiToken); getGuestbooksResponse.then().assertThat().statusCode(200); assertEquals(1, getGuestbooksResponse.getBody().jsonPath().getList("data").size()); + // Get the list of Guestbooks including Parent Guestbook + getGuestbooksResponse = UtilIT.getGuestbooks(dataverseAlias, ownerApiToken, Boolean.TRUE); + getGuestbooksResponse.then().assertThat().statusCode(200); + assertEquals(2, getGuestbooksResponse.getBody().jsonPath().getList("data").size()); // Upload files JsonObjectBuilder json1 = Json.createObjectBuilder().add("description", "my description1").add("directoryLabel", "data/subdir1").add("categories", Json.createArrayBuilder().add("Data")); 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 d70b8f2a235..a33da50d8c5 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -612,8 +612,16 @@ static Response getGuestbook(Long guestbookId, String apiToken) { } static Response getGuestbooks(String dataverseAlias, String apiToken) { - RequestSpecification requestSpec = given() - .header(API_TOKEN_HTTP_HEADER, apiToken); + return getGuestbooks(dataverseAlias, apiToken, null); + } + static Response getGuestbooks(String dataverseAlias, String apiToken, Boolean includeInherited) { + RequestSpecification requestSpec = given(); + if (apiToken != null) { + requestSpec.header(API_TOKEN_HTTP_HEADER, apiToken); + } + if (includeInherited != null) { + requestSpec.queryParam("includeInherited", includeInherited); + } return requestSpec.get("/api/guestbooks/" + dataverseAlias + "/list" ); } @@ -2275,10 +2283,15 @@ static Response rejectFileAccessRequest(String fileIdOrPersistentId, String iden } static Response moveDataverse(String movedDataverseAlias, String targetDataverseAlias, Boolean force, String apiToken) { - Response response = given() - .header(API_TOKEN_HTTP_HEADER, apiToken) - .post("api/dataverses/" + movedDataverseAlias + "/move/" + targetDataverseAlias + "?forceMove=" + force + "&key=" + apiToken); - return response; + RequestSpecification requestSpecification = given(); + if (apiToken != null) { + requestSpecification.header(API_TOKEN_HTTP_HEADER, apiToken); + requestSpecification.queryParam("key", apiToken); + } + if (force != null) { + requestSpecification.queryParam("forceMove", force); + } + return requestSpecification.post("api/dataverses/" + movedDataverseAlias + "/move/" + targetDataverseAlias); } static Response moveDataset(String idOrPersistentIdOfDatasetToMove, String destinationDataverseAlias, String apiToken) { @@ -5545,8 +5558,10 @@ public static Guestbook createRandomGuestbook(String ownerAlias, String persiste gb.getCustomQuestions().get(2).setId(jsonPath.getLong("data.customQuestions[2].id")); // Add the Guestbook to the Dataset - Response setGuestbook = UtilIT.updateDatasetGuestbook(persistentId, guestbookId, apiToken); - setGuestbook.prettyPrint(); + if (persistentId != null) { + Response setGuestbook = UtilIT.updateDatasetGuestbook(persistentId, guestbookId, apiToken); + setGuestbook.prettyPrint(); + } return gb; }