From 96efb7a5ce08b0962b174c2e279b22a6cde51007 Mon Sep 17 00:00:00 2001 From: gurleenkaurbp Date: Mon, 23 Dec 2024 14:46:31 +0530 Subject: [PATCH 1/5] [EDGPATRON-161] - Extend get API for /patron/registration-status with {externalSystemId} --- ramls/edge-patron.raml | 6 ++- .../org/folio/edge/patron/PatronHandler.java | 18 +++++--- .../edge/patron/utils/PatronOkapiClient.java | 6 +-- .../folio/edge/patron/MainVerticleTest.java | 42 +++++++++++++++++-- .../edge/patron/utils/PatronMockOkapi.java | 33 ++++++++------- src/test/resources/user_active.json | 2 +- 6 files changed, 76 insertions(+), 31 deletions(-) diff --git a/ramls/edge-patron.raml b/ramls/edge-patron.raml index 4dcc99d..b7185db 100644 --- a/ramls/edge-patron.raml +++ b/ramls/edge-patron.raml @@ -1036,7 +1036,7 @@ types: example: internal server error, contact administrator /registration-status: get: - description: Get the patron details by email ID + description: Get the patron details by email ID or externalSystemId queryParameters: apikey: description: "API Key" @@ -1044,7 +1044,9 @@ types: emailId: description: The email ID of the patron. type: string - required: true + externalSystemId: + description: The external system ID of the patron. + type: string responses: 200: description: patron information retrieved successfully diff --git a/src/main/java/org/folio/edge/patron/PatronHandler.java b/src/main/java/org/folio/edge/patron/PatronHandler.java index 26631ea..d2494c6 100644 --- a/src/main/java/org/folio/edge/patron/PatronHandler.java +++ b/src/main/java/org/folio/edge/patron/PatronHandler.java @@ -308,24 +308,32 @@ public void handleSecureGetAllowedServicePointsForItem(RoutingContext ctx) { public void handleGetPatronRegistrationStatus(RoutingContext ctx) { logger.debug("handleGetPatronRegistrationStatus:: Fetching patron registration"); + String emailId = ctx.request().getParam(PARAM_EMAIL_ID); - if(StringUtils.isNullOrEmpty(emailId)) { - logger.warn("handleGetPatronRegistrationStatus:: Missing or empty emailId"); + String externalSystemId = ctx.request().getParam(PARAM_EXTERNAL_SYSTEM_ID); + + if (StringUtils.isNullOrEmpty(emailId) && StringUtils.isNullOrEmpty(externalSystemId)) { + logger.warn("handleGetPatronRegistrationStatus:: Missing or empty emailId and externalSystemId"); ctx.response() .setStatusCode(400) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) - .end(getErrorMsg("EMAIL_NOT_PROVIDED", "emailId is missing in the request")); + .end(getErrorMsg("IDENTIFIERS_NOT_PROVIDED", "Either emailId or externalSystemId must be provided in the request")); return; } + super.handleCommon(ctx, new String[]{}, new String[]{}, (client, params) -> { String alternateTenantId = ctx.request().getParam("alternateTenantId", client.tenant); final PatronOkapiClient patronClient = new PatronOkapiClient(client, alternateTenantId); - patronClient.getPatronRegistrationStatus(emailId, + + patronClient.getPatronRegistrationStatus( + emailId != null ? emailId : externalSystemId, resp -> handleRegistrationStatusResponse(ctx, resp), - t -> handleProxyException(ctx, t)); + t -> handleProxyException(ctx, t) + ); }); } + @Override protected void invalidApiKey(RoutingContext ctx, String msg) { accessDenied(ctx, msg); 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 fef94e3..028cf8d 100644 --- a/src/main/java/org/folio/edge/patron/utils/PatronOkapiClient.java +++ b/src/main/java/org/folio/edge/patron/utils/PatronOkapiClient.java @@ -251,11 +251,11 @@ public void placeInstanceHold(String patronId, String instanceId, String request exceptionHandler); } - public void getPatronRegistrationStatus(String emailId, - Handler> responseHandler, Handler exceptionHandler) { + public void getPatronRegistrationStatus(String identifier, + Handler> responseHandler, Handler exceptionHandler) { get(format("%s/patron/registration-status/%s", okapiURL, - emailId), tenant, null, responseHandler, exceptionHandler); + identifier), tenant, null, responseHandler, exceptionHandler); } private Hold createCancellationHoldRequest(JsonObject cancellationRequest, JsonObject baseRequest, String patronId) { diff --git a/src/test/java/org/folio/edge/patron/MainVerticleTest.java b/src/test/java/org/folio/edge/patron/MainVerticleTest.java index 1346c32..c2d8334 100644 --- a/src/test/java/org/folio/edge/patron/MainVerticleTest.java +++ b/src/test/java/org/folio/edge/patron/MainVerticleTest.java @@ -393,8 +393,8 @@ public void testGetPatronRegistrationStatusWithoutEmail(TestContext context) { .response(); var jsonResponse = new JsonObject(response.body().asString()); - assertEquals("EMAIL_NOT_PROVIDED", jsonResponse.getString("code")); - assertEquals("emailId is missing in the request", jsonResponse.getString("errorMessage")); + assertEquals("IDENTIFIERS_NOT_PROVIDED", jsonResponse.getString("code")); + assertEquals("Either emailId or externalSystemId must be provided in the request", jsonResponse.getString("errorMessage")); response = RestAssured .get(String.format("/patron/registration-status?emailId=%s&apikey=%s", "", apiKey)) @@ -405,8 +405,8 @@ public void testGetPatronRegistrationStatusWithoutEmail(TestContext context) { .response(); jsonResponse = new JsonObject(response.body().asString()); - assertEquals("EMAIL_NOT_PROVIDED", jsonResponse.getString("code")); - assertEquals("emailId is missing in the request", jsonResponse.getString("errorMessage")); + assertEquals("IDENTIFIERS_NOT_PROVIDED", jsonResponse.getString("code")); + assertEquals("Either emailId or externalSystemId must be provided in the request", jsonResponse.getString("errorMessage")); } @Test @@ -426,6 +426,23 @@ public void testGetPatronRegistrationStatusWithActiveEmail(TestContext context) assertEquals(expected, actual); } + @Test + public void testGetPatronRegistrationStatusWithExternalSystemId(TestContext context) { + + final var response = RestAssured + .get(String.format("/patron/registration-status?externalSystemId=%s&apikey=%s", "9eb67301-6f6e-468f-9b1a-6134dc39a699", apiKey)) + .then() + .statusCode(200) + .header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .extract() + .response(); + + var expected = new JsonObject(readMockFile( + "/user_active.json")); + var actual = new JsonObject(response.body().asString()); + assertEquals(expected, actual); + } + @Test public void testGetPatronRegistrationStatusWithInvalidEmail() { @@ -442,6 +459,23 @@ public void testGetPatronRegistrationStatusWithInvalidEmail() { assertEquals("User does not exist", jsonResponse.getString("errorMessage")); } + @Test + public void testGetPatronRegistrationStatusWithInvalidExternalSystemId() { + + final var response = RestAssured + .get(String.format("/patron/registration-status?externalSystemId=%s&apikey=%s", "9eb67301-6f6e-468f-9b1a-6134dc39a700", apiKey)) + .then() + .statusCode(404) + .header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .extract() + .response(); + + var jsonResponse = new JsonObject(response.body().asString()); + assertEquals("USER_NOT_FOUND", jsonResponse.getString("code")); + assertEquals("User does not exist", jsonResponse.getString("errorMessage")); + } + + @Test public void testGetPatronRegistrationStatusWithMultipleUserEmail() { 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 b4004f8..d3943ff 100644 --- a/src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java +++ b/src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java @@ -5,18 +5,7 @@ import static org.folio.edge.core.Constants.DAY_IN_MILLIS; import static org.folio.edge.core.Constants.TEXT_PLAIN; import static org.folio.edge.core.Constants.X_OKAPI_TOKEN; -import static org.folio.edge.patron.Constants.PARAM_EMAIL_ID; -import static org.folio.edge.patron.Constants.PARAM_HOLD_ID; -import static org.folio.edge.patron.Constants.PARAM_INCLUDE_CHARGES; -import static org.folio.edge.patron.Constants.PARAM_INCLUDE_HOLDS; -import static org.folio.edge.patron.Constants.PARAM_INCLUDE_LOANS; -import static org.folio.edge.patron.Constants.PARAM_INSTANCE_ID; -import static org.folio.edge.patron.Constants.PARAM_ITEM_ID; -import static org.folio.edge.patron.Constants.PARAM_LIMIT; -import static org.folio.edge.patron.Constants.PARAM_OFFSET; -import static org.folio.edge.patron.Constants.PARAM_PATRON_ID; -import static org.folio.edge.patron.Constants.PARAM_REQUEST_ID; -import static org.folio.edge.patron.Constants.PARAM_SORT_BY; +import static org.folio.edge.patron.Constants.*; import com.fasterxml.jackson.core.JsonProcessingException; import io.vertx.core.http.HttpHeaders; @@ -277,22 +266,34 @@ public void getRegistrationStatusHandler(RoutingContext ctx) { .setStatusCode(403) .putHeader(HttpHeaders.CONTENT_TYPE, TEXT_PLAIN) .end("Access requires permission: patron.account.get"); - } else if(emailId.equals("active@folio.com")) { + } else if(emailId!=null && emailId.equals("active@folio.com")) { ctx.response() .setStatusCode(200) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) .end(readMockFile("/user_active.json")); - } else if(emailId.equals("multipleuser@folio.com")) { + } else if(emailId!=null && emailId.equals("9eb67301-6f6e-468f-9b1a-6134dc39a699")) { + ctx.response() + .setStatusCode(200) + .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .end(readMockFile("/user_active.json")); + } else if(emailId!=null && emailId.equals("multipleuser@folio.com")) { ctx.response() .setStatusCode(400) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) .end(readMockFile("/multiple_user_error.json")); - } else if(emailId.equals("usernotfound@folio.com")) { + } else if(emailId!=null && emailId.equals("usernotfound@folio.com")) { + ctx.response() + .setStatusCode(404) + .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .end(readMockFile("/user_not_found_error.json")); + } + else if(emailId!=null && emailId.equals("9eb67301-6f6e-468f-9b1a-6134dc39a700")) { ctx.response() .setStatusCode(404) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) .end(readMockFile("/user_not_found_error.json")); - } else if(emailId.equals("invalid@folio.com")) { + } + else if(emailId!=null && emailId.equals("invalid@folio.com")) { ctx.response() .setStatusCode(404) .putHeader(HttpHeaders.CONTENT_TYPE, TEXT_PLAIN) diff --git a/src/test/resources/user_active.json b/src/test/resources/user_active.json index cc3e1ae..753e657 100644 --- a/src/test/resources/user_active.json +++ b/src/test/resources/user_active.json @@ -1,6 +1,6 @@ { "id": "cacc29d8-cade-4312-a5f2-4eeac55d8697", - "externalSystemId": "active@folio.com", + "externalSystemId": "9eb67301-6f6e-468f-9b1a-6134dc39a699", "active": true, "type": "patron", "patronGroup": "63f8065f-df84-4e76-a36b-3ba32dbdc9e5", From 6805054fa59d960d64a2d0c3c6f611e52140e7d0 Mon Sep 17 00:00:00 2001 From: gurleenkaurbp Date: Mon, 23 Dec 2024 14:56:02 +0530 Subject: [PATCH 2/5] [EDGPATRON-161] - Extend get API for /patron/registration-status with {externalSystemId} --- ramls/edge-patron.raml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ramls/edge-patron.raml b/ramls/edge-patron.raml index b7185db..f08bbc5 100644 --- a/ramls/edge-patron.raml +++ b/ramls/edge-patron.raml @@ -1045,8 +1045,9 @@ types: description: The email ID of the patron. type: string externalSystemId: - description: The external system ID of the patron. + description: The UUID of a staging user type: string + pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$ responses: 200: description: patron information retrieved successfully From e86aaa3f57b1ac711f05ca0f470e889beaec5f6a Mon Sep 17 00:00:00 2001 From: gurleenkaurbp Date: Fri, 27 Dec 2024 19:07:05 +0530 Subject: [PATCH 3/5] [EDGPATRON-161] - Extend get API for /patron/registration-status with {externalSystemId} --- ramls/schemas/user_error_400.schema | 7 +++-- .../org/folio/edge/patron/PatronHandler.java | 20 +++++++++++--- .../folio/edge/patron/MainVerticleTest.java | 26 ++++++++++++++++--- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/ramls/schemas/user_error_400.schema b/ramls/schemas/user_error_400.schema index 55f2f61..51646aa 100644 --- a/ramls/schemas/user_error_400.schema +++ b/ramls/schemas/user_error_400.schema @@ -9,7 +9,8 @@ "description": "Error code", "examples": [ "MULTIPLE_USER_WITH_EMAIL", - "EMAIL_NOT_PROVIDED" + "EMAIL_NOT_PROVIDED", + "INVALID_IDENTIFIERS" ] }, "errorMessage": { @@ -17,7 +18,9 @@ "description": "Error code description", "examples": [ "Multiple users found with the same email", - "emailId is missing in the request" + "emailId is missing in the request", + "Either emailId or externalSystemId must be provided in the request.", + Provide either emailId or externalSystemId, not both. ] } }, diff --git a/src/main/java/org/folio/edge/patron/PatronHandler.java b/src/main/java/org/folio/edge/patron/PatronHandler.java index d2494c6..aa338a6 100644 --- a/src/main/java/org/folio/edge/patron/PatronHandler.java +++ b/src/main/java/org/folio/edge/patron/PatronHandler.java @@ -312,12 +312,13 @@ public void handleGetPatronRegistrationStatus(RoutingContext ctx) { String emailId = ctx.request().getParam(PARAM_EMAIL_ID); String externalSystemId = ctx.request().getParam(PARAM_EXTERNAL_SYSTEM_ID); - if (StringUtils.isNullOrEmpty(emailId) && StringUtils.isNullOrEmpty(externalSystemId)) { - logger.warn("handleGetPatronRegistrationStatus:: Missing or empty emailId and externalSystemId"); + String validationError = validateIdentifiers(emailId, externalSystemId); + if (validationError != null) { + logger.warn("handleGetPatronRegistrationStatus:: " + validationError); ctx.response() .setStatusCode(400) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) - .end(getErrorMsg("IDENTIFIERS_NOT_PROVIDED", "Either emailId or externalSystemId must be provided in the request")); + .end(getErrorMsg("INVALID_IDENTIFIERS", validationError)); return; } @@ -333,6 +334,19 @@ public void handleGetPatronRegistrationStatus(RoutingContext ctx) { }); } + private String validateIdentifiers(String emailId, String externalSystemId) { + if (StringUtils.isNullOrEmpty(emailId) && StringUtils.isNullOrEmpty(externalSystemId)) { + return "Either emailId or externalSystemId must be provided in the request."; + } + + if (!StringUtils.isNullOrEmpty(emailId) && !StringUtils.isNullOrEmpty(externalSystemId)) { + return "Provide either emailId or externalSystemId, not both."; + } + + return null; + } + + @Override protected void invalidApiKey(RoutingContext ctx, String msg) { diff --git a/src/test/java/org/folio/edge/patron/MainVerticleTest.java b/src/test/java/org/folio/edge/patron/MainVerticleTest.java index c2d8334..0d39e9c 100644 --- a/src/test/java/org/folio/edge/patron/MainVerticleTest.java +++ b/src/test/java/org/folio/edge/patron/MainVerticleTest.java @@ -393,8 +393,8 @@ public void testGetPatronRegistrationStatusWithoutEmail(TestContext context) { .response(); var jsonResponse = new JsonObject(response.body().asString()); - assertEquals("IDENTIFIERS_NOT_PROVIDED", jsonResponse.getString("code")); - assertEquals("Either emailId or externalSystemId must be provided in the request", jsonResponse.getString("errorMessage")); + assertEquals("INVALID_IDENTIFIERS", jsonResponse.getString("code")); + assertEquals("Either emailId or externalSystemId must be provided in the request.", jsonResponse.getString("errorMessage")); response = RestAssured .get(String.format("/patron/registration-status?emailId=%s&apikey=%s", "", apiKey)) @@ -405,10 +405,28 @@ public void testGetPatronRegistrationStatusWithoutEmail(TestContext context) { .response(); jsonResponse = new JsonObject(response.body().asString()); - assertEquals("IDENTIFIERS_NOT_PROVIDED", jsonResponse.getString("code")); - assertEquals("Either emailId or externalSystemId must be provided in the request", jsonResponse.getString("errorMessage")); + assertEquals("INVALID_IDENTIFIERS", jsonResponse.getString("code")); + assertEquals("Either emailId or externalSystemId must be provided in the request.", jsonResponse.getString("errorMessage")); } + @Test + public void testGetPatronRegistrationStatusWithEmailAndESID(TestContext context) { + + var response = RestAssured + .get(String.format("/patron/registration-status?emailId=%s&externalSystemId=%s&apikey=%s", "abc@abc.com", "9eb67301-6f6e-468f-9b1a-6134dc39a670", apiKey)) + .then() + .statusCode(400) + .header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + .extract() + .response(); + + var jsonResponse = new JsonObject(response.body().asString()); + assertEquals("INVALID_IDENTIFIERS", jsonResponse.getString("code")); + assertEquals("Provide either emailId or externalSystemId, not both.", jsonResponse.getString("errorMessage")); + + } + + @Test public void testGetPatronRegistrationStatusWithActiveEmail(TestContext context) { From b37bcade630781a27f8824bc10d10c34d84efe9c Mon Sep 17 00:00:00 2001 From: gurleenkaurbp Date: Fri, 27 Dec 2024 19:15:19 +0530 Subject: [PATCH 4/5] [EDGPATRON-161] - Extend get API for /patron/registration-status with {externalSystemId} --- ramls/schemas/user_error_400.schema | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ramls/schemas/user_error_400.schema b/ramls/schemas/user_error_400.schema index 51646aa..972195a 100644 --- a/ramls/schemas/user_error_400.schema +++ b/ramls/schemas/user_error_400.schema @@ -20,7 +20,7 @@ "Multiple users found with the same email", "emailId is missing in the request", "Either emailId or externalSystemId must be provided in the request.", - Provide either emailId or externalSystemId, not both. + "Provide either emailId or externalSystemId, not both." ] } }, From f1be11eb75276a4abe28fcd528a8790b8a29bc52 Mon Sep 17 00:00:00 2001 From: gurleenkaurbp Date: Fri, 27 Dec 2024 19:30:48 +0530 Subject: [PATCH 5/5] [EDGPATRON-161] - Extend get API for /patron/registration-status with {externalSystemId} --- src/main/java/org/folio/edge/patron/PatronHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/folio/edge/patron/PatronHandler.java b/src/main/java/org/folio/edge/patron/PatronHandler.java index 608ab66..2440512 100644 --- a/src/main/java/org/folio/edge/patron/PatronHandler.java +++ b/src/main/java/org/folio/edge/patron/PatronHandler.java @@ -314,7 +314,6 @@ public void handleGetPatronRegistrationStatus(RoutingContext ctx) { String validationError = validateIdentifiers(emailId, externalSystemId); if (validationError != null) { - logger.warn("handleGetPatronRegistrationStatus:: " + validationError); ctx.response() .setStatusCode(400) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON)