From 60b562c3c81b334fd915f26737572e2b3e0796af Mon Sep 17 00:00:00 2001 From: SinghAdes <90304030+SinghAdes@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:27:03 +0530 Subject: [PATCH] [EDGEPATRON-133]-Added PUT endpoint. (#115) * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. * [EDGEPATRON-133]-Added PUT endpoint. --- ramls/edge-patron.raml | 55 ++++++++++++++++++- .../org/folio/edge/patron/MainVerticle.java | 3 + .../org/folio/edge/patron/PatronHandler.java | 15 +++++ .../edge/patron/utils/PatronOkapiClient.java | 31 +++++++++++ .../folio/edge/patron/MainVerticleTest.java | 34 ++++++++++++ .../edge/patron/utils/PatronMockOkapi.java | 22 ++++++++ 6 files changed, 159 insertions(+), 1 deletion(-) diff --git a/ramls/edge-patron.raml b/ramls/edge-patron.raml index a965adb..735ea4e 100644 --- a/ramls/edge-patron.raml +++ b/ramls/edge-patron.raml @@ -122,7 +122,60 @@ types: body: text/plain: example: internal server error, contact administrator - + put: + description: Updates external patron request + queryParameters: + apikey: + description: "API Key" + type: string + body: + application/json: + type: external_patron + example: !include examples/external_patron.json + responses: + 204: + description: | + Returns data for a updated external patron request + body: + application/json: + type: external_patron + example: !include examples/external_patron.json + 400: + description: Bad request + body: + text/plain: + example: unable to process request + 401: + description: Not authorized to perform requested action + body: + text/plain: + example: unable to create request + 404: + description: Item with a given ID not found + body: + text/plain: + example: item not found + 403: + description: Access Denied + body: + text/plain: + example: Access Denied + 409: + description: Conflict + body: + text/plain: + example: Optimistic Locking Conflict + 422: + description: Validation error + body: + text/plain: + example: Validation error + 500: + description: | + Internal server error, e.g. due to misconfiguration + body: + text/plain: + example: internal server error, contact administrator /{id}: displayName: Manage Accounts By Id description: Service endpoints that manage accounts by an existing Id diff --git a/src/main/java/org/folio/edge/patron/MainVerticle.java b/src/main/java/org/folio/edge/patron/MainVerticle.java index 7de4ba9..079a416 100644 --- a/src/main/java/org/folio/edge/patron/MainVerticle.java +++ b/src/main/java/org/folio/edge/patron/MainVerticle.java @@ -60,6 +60,9 @@ public Router defineRoutes() { router.route(HttpMethod.GET, "/patron/account/:patronId/by-email/:emailId") .handler(patronHandler::handleGetExtPatronAccountByEmail); + router.route(HttpMethod.PUT, "/patron/account/:patronId/by-email/:emailId") + .handler(patronHandler::handlePutExtPatronAccountByEmail); + router.route(HttpMethod.POST, "/patron/account/:patronId/item/:itemId/renew") .handler(patronHandler::handleRenew); diff --git a/src/main/java/org/folio/edge/patron/PatronHandler.java b/src/main/java/org/folio/edge/patron/PatronHandler.java index 66d81fb..7b90d73 100644 --- a/src/main/java/org/folio/edge/patron/PatronHandler.java +++ b/src/main/java/org/folio/edge/patron/PatronHandler.java @@ -148,6 +148,21 @@ public void handleGetExtPatronAccountByEmail(RoutingContext ctx) { t -> handleProxyException(ctx, t))); } + public void handlePutExtPatronAccountByEmail(RoutingContext ctx) { + if (ctx.body().asJsonObject() == null) { + badRequest(ctx, MSG_EXTERNAL_NOBODY); + return; + } + final String body = String.valueOf(ctx.body().asJsonObject()); + handleCommon(ctx, + new String[] {PARAM_PATRON_ID, PARAM_EMAIL_ID}, + new String[] {}, + (client, params) -> ((PatronOkapiClient) client).putPatron( + params.get(PARAM_EMAIL_ID), + body, + resp -> handleProxyResponse(ctx, resp), + t -> handleProxyException(ctx, t))); + } public void handlePlaceItemHold(RoutingContext ctx) { if (ctx.body().asJsonObject() == null) { diff --git a/src/main/java/org/folio/edge/patron/utils/PatronOkapiClient.java b/src/main/java/org/folio/edge/patron/utils/PatronOkapiClient.java index e874b0c..2ab6bda 100644 --- a/src/main/java/org/folio/edge/patron/utils/PatronOkapiClient.java +++ b/src/main/java/org/folio/edge/patron/utils/PatronOkapiClient.java @@ -1,6 +1,8 @@ package org.folio.edge.patron.utils; +import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; +import io.vertx.ext.web.client.HttpRequest; import io.vertx.ext.web.client.HttpResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -13,6 +15,7 @@ import org.joda.time.DateTime; import org.joda.time.DateTimeZone; +import static org.folio.edge.core.Constants.X_OKAPI_TOKEN; import static org.folio.edge.patron.Constants.FIELD_CANCELED_DATE; import static org.folio.edge.patron.Constants.FIELD_CANCELLATION_ADDITIONAL_INFO; import static org.folio.edge.patron.Constants.FIELD_CANCELLATION_REASON_ID; @@ -136,6 +139,17 @@ public void postPatron(String requestBody, exceptionHandler); } + public void putPatron(String emailId, String requestBody, + Handler> responseHandler, Handler exceptionHandler) { + put( + String.format("%s/patron/account/by-email/%s", okapiURL, emailId), + tenant, + requestBody, + defaultHeaders, + responseHandler, + exceptionHandler); + } + public void cancelHold(String patronId, String holdId, JsonObject holdCancellationRequest, Handler> responseHandler, Handler exceptionHandler) { getRequest(holdId, @@ -219,4 +233,21 @@ public PatronLookupException(String msg) { } } + public void put(String url, String tenant, String payload, MultiMap headers, Handler> responseHandler, + Handler exceptionHandler) { + logger.debug("put:: Trying to send request to Okapi with url: {}, payload: {}, tenant: {}", url, payload, tenant); + HttpRequest request = client.putAbs(url); + if (headers != null) { + request.headers().setAll(combineHeadersWithDefaults(headers)); + } else { + request.headers().setAll(defaultHeaders); + } + logger.info("PUT '{}' tenant: {} token: {}", () -> url, () -> tenant, () -> request.headers() + .get(X_OKAPI_TOKEN)); + request.timeout(reqTimeout); + request.sendBuffer(Buffer.buffer(payload)) + .onSuccess(responseHandler) + .onFailure(exceptionHandler); + } } + diff --git a/src/test/java/org/folio/edge/patron/MainVerticleTest.java b/src/test/java/org/folio/edge/patron/MainVerticleTest.java index af070bc..b397992 100644 --- a/src/test/java/org/folio/edge/patron/MainVerticleTest.java +++ b/src/test/java/org/folio/edge/patron/MainVerticleTest.java @@ -731,6 +731,40 @@ public void testPostExternalLCPatron(TestContext context) throws Exception { .response(); } + @Test + public void testPutExternalLCPatron(TestContext context) throws Exception { + logger.info("=== Test put external patron ==="); + + Patron patron = PatronMockOkapi.getPatron(); + int expectedStatusCode = 204; + RestAssured + .with() + .body(patron.toJson()) + .contentType(APPLICATION_JSON) + .put( + String.format("/patron/account/%s/by-email/%s?apikey=%s", UUID.randomUUID(), "TestMail", apiKey)) + .then() + .statusCode(expectedStatusCode) + .header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON); + } + + @Test + public void testPutExternalLCPatronWithEmptyBody(TestContext context) { + logger.info("=== Test put external patron ==="); + + int expectedStatusCode = 400; + RestAssured + .with() + .contentType(APPLICATION_JSON) + .put( + String.format("/patron/account/%s/by-email/%s?apikey=%s", UUID.randomUUID(), "TestMail", apiKey)) + .then() + .statusCode(expectedStatusCode) + .header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .extract() + .response(); + } + @Test public void testPlaceInstanceHoldInstanceNotFound(TestContext context) throws Exception { logger.info("=== Test place instance hold w/ instance not found ==="); diff --git a/src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java b/src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java index 580e39d..7fc76b9 100644 --- a/src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java +++ b/src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java @@ -138,6 +138,9 @@ public Router defineRoutes() { router.route(HttpMethod.GET, "/patron/account/by-email/:emailId") .handler(this::getExtPatronAccountHandler); + router.route(HttpMethod.PUT, "/patron/account/by-email/:emailId") + .handler(this::putExtPatronAccountHandler); + router.route(HttpMethod.POST, "/patron/account/:patronId/item/:itemId/renew") .handler(this::renewItemHandler); @@ -249,6 +252,25 @@ public void getExtPatronAccountHandler(RoutingContext ctx) { } } + public void putExtPatronAccountHandler(RoutingContext ctx) { + String token = ctx.request().getHeader(X_OKAPI_TOKEN); + if (token == null || !token.equals(MOCK_TOKEN)) { + ctx.response() + .setStatusCode(403) + .putHeader(HttpHeaders.CONTENT_TYPE, TEXT_PLAIN) + .end("Access requires permission: patron.account.put"); + } else if (ctx.body().isEmpty()) { + ctx.response() + .putHeader(HttpHeaders.CONTENT_TYPE, TEXT_PLAIN) + .end("No Body"); + } else { + ctx.response() + .setStatusCode(204) + .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .end(getPatron().toString()); + } + } + public void renewItemHandler(RoutingContext ctx) { String patronId = ctx.request().getParam(PARAM_PATRON_ID); String itemId = ctx.request().getParam(PARAM_ITEM_ID);