diff --git a/doc/release-notes/12260-get-guestbook-with-usage-and-response-counts.md b/doc/release-notes/12260-get-guestbook-with-usage-and-response-counts.md new file mode 100644 index 00000000000..8f2a4e58d24 --- /dev/null +++ b/doc/release-notes/12260-get-guestbook-with-usage-and-response-counts.md @@ -0,0 +1,2 @@ +## API Enhancement +API call to `/api/guestbooks/{dataverseAlias}/list` can now include `"usageCount":#` and `"responseCount":#` in the response by adding the query param "includeStats=true". diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 8fe87ad5e65..d9710dd08d7 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1239,6 +1239,8 @@ 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" +.. note:: By adding the query param "includeStats=true" `usageCount` and `responseCount` values can be added to the response. + Get a Guestbook for a Dataverse Collection ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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..d1a929c8f21 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Guestbooks.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Guestbooks.java @@ -2,6 +2,7 @@ import edu.harvard.iq.dataverse.Dataverse; import edu.harvard.iq.dataverse.Guestbook; +import edu.harvard.iq.dataverse.GuestbookResponseServiceBean; import edu.harvard.iq.dataverse.GuestbookServiceBean; import edu.harvard.iq.dataverse.api.auth.AuthRequired; import edu.harvard.iq.dataverse.authorization.Permission; @@ -38,6 +39,8 @@ public class Guestbooks extends AbstractApiBean { @EJB GuestbookServiceBean guestbookService; + @EJB + GuestbookResponseServiceBean guestbookResponseService; @GET @AuthRequired @@ -57,9 +60,10 @@ 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("includeStats") boolean includeStats) { return response( req -> { Dataverse dataverse = findDataverseOrDie(identifier); + final Long dataverseId = dataverse.getId(); if (!permissionSvc.request(req).on(dataverse).has(Permission.EditDataverse)) { return error(Response.Status.FORBIDDEN, "Not authorized"); } @@ -67,6 +71,10 @@ public Response getGuestbooks(@Context ContainerRequestContext crc, @PathParam(" JsonArrayBuilder guestbookArray = Json.createArrayBuilder(); JsonPrinter jsonPrinter = new JsonPrinter(); for (Guestbook gb : guestbooks) { + if (includeStats) { + gb.setUsageCount(guestbookService.findCountUsages(gb.getId(), dataverseId)); + gb.setResponseCount(guestbookResponseService.findCountByGuestbookId(gb.getId(), dataverseId)); + } guestbookArray.add(jsonPrinter.json(gb)); } return ok(guestbookArray); diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java index e9b5f545663..729596fb3d4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java @@ -423,6 +423,12 @@ public static JsonObjectBuilder json(Guestbook guestbook) { guestbookObject.add("nameRequired", guestbook.isNameRequired()); guestbookObject.add("institutionRequired", guestbook.isInstitutionRequired()); guestbookObject.add("positionRequired", guestbook.isPositionRequired()); + if (guestbook.getUsageCount() != null) { + guestbookObject.add("usageCount", guestbook.getUsageCount()); + } + if (guestbook.getResponseCount() != null) { + guestbookObject.add("responseCount", guestbook.getResponseCount()); + } JsonArrayBuilder customQuestions = Json.createArrayBuilder(); if (guestbook.getCustomQuestions() != null) { for (CustomQuestion cq : guestbook.getCustomQuestions()) { 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..6503a40ef58 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java @@ -3983,6 +3983,7 @@ public void testDownloadFileWithGuestbookResponse() throws IOException, JsonPars .statusCode(BAD_REQUEST.getStatusCode()); String guestbookResponseForGuest = guestbookResponse.replace("\"guestbookResponse\": {", "\"guestbookResponse\": { \"name\":\"My Name\", \"email\":\"myemail@example.com\", \"position\":\"My Position\", \"institution\":\"My Institution\","); + // With GuestbookResponse. Guest user doesn't have the required Name, etc. So we will add those to the Guestbook Response downloadResponse = UtilIT.postDownloadFile(fileId4, guestbookResponseForGuest); downloadResponse.prettyPrint(); @@ -4008,6 +4009,12 @@ public void testDownloadFileWithGuestbookResponse() throws IOException, JsonPars .statusCode(OK.getStatusCode()); signedUrl = UtilIT.getSignedUrlFromResponse(downloadResponse); + // Verify that the Guestbook Response is persisted + Response guestbookResponseResponse = UtilIT.getGuestbookResponses(dataverseAlias, guestbook.getId(), ownerApiToken); + guestbookResponseResponse.then().assertThat() + .statusCode(OK.getStatusCode()); + assertTrue(guestbookResponseResponse.prettyPrint().contains("What color car do you drive,Yellow")); + // Download the file using the signed url signedUrlResponse = get(signedUrl); assertEquals(OK.getStatusCode(), signedUrlResponse.getStatusCode()); @@ -4053,6 +4060,14 @@ public void testDownloadFileWithGuestbookResponse() throws IOException, JsonPars signedUrl = UtilIT.getSignedUrlFromResponse(downloadResponse); signedUrlResponse = get(signedUrl); assertEquals(OK.getStatusCode(), signedUrlResponse.getStatusCode()); + + // Verify that the guestbook has proper stats + Response guestbookListResponse = UtilIT.getGuestbooks(dataverseAlias, ownerApiToken, true); + guestbookListResponse.prettyPrint(); + guestbookListResponse.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data[0].usageCount", is(1)) + .body("data[0].responseCount", is(16)); } @Test 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..6a28b223700 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -612,9 +612,13 @@ static Response getGuestbook(Long guestbookId, String apiToken) { } static Response getGuestbooks(String dataverseAlias, String apiToken) { + return getGuestbooks(dataverseAlias, apiToken, false); + } + static Response getGuestbooks(String dataverseAlias, String apiToken, boolean includeStats) { + String params = "?includeStats=" + includeStats; RequestSpecification requestSpec = given() .header(API_TOKEN_HTTP_HEADER, apiToken); - return requestSpec.get("/api/guestbooks/" + dataverseAlias + "/list" ); + return requestSpec.get("/api/guestbooks/" + dataverseAlias + "/list" + params ); } static Response enableGuestbook(String dataverseAlias, Long guestbookId, String apiToken, String enable) { @@ -1267,7 +1271,9 @@ static Response downloadFileOriginal(Integer fileId, String apiToken) { static Response getDownloadFileUrlWithGuestbookResponse(Integer fileId, String apiToken, String body) { RequestSpecification requestSpecification = given(); - requestSpecification.header(API_TOKEN_HTTP_HEADER, apiToken); + if (apiToken != null) { + requestSpecification.header(API_TOKEN_HTTP_HEADER, apiToken); + } if (body != null) { requestSpecification.body(body); }