Skip to content

Commit

Permalink
EDGPATRON-119 Initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderkurash committed Oct 4, 2023
1 parent a18077a commit 2570ca8
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 2 deletions.
2 changes: 1 addition & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"requires": [
{
"id": "patron",
"version": "4.2 5.0"
"version": "4.2 5.1"
},
{
"id": "circulation",
Expand Down
27 changes: 27 additions & 0 deletions ramls/allowed-service-point.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": ["array", "null"],
"description": "List of allowed pickup service points",
"default": null,
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "UUID string",
"$ref": "raml-util/schemas/uuid.schema"
},
"name": {
"type": "string",
"description": "Service point name"
}
},
"additionalProperties": false,
"required": [
"id",
"name"
]
}
}
15 changes: 15 additions & 0 deletions ramls/allowed-service-points-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Allowed pickup service points grouped by request type",
"type": "object",
"properties": {
"allowedServicePoints": {
"description": "Allowed pickup service point IDs for Page requests",
"type": "array",
"$ref": "allowed-service-point.json"
}
},
"required": [
"allowedServicePoints"
]
}
36 changes: 35 additions & 1 deletion ramls/edge-patron.raml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Patron Services
baseUri: https://github.com/folio-org/mod-patron
protocols: [ HTTPS ]
version: v4.2
version: v4.3

documentation:
- title: Patron Services
Expand All @@ -17,6 +17,7 @@ types:
charge: !include charge.json
money: !include money.json
item: !include item.json
allowedServicePoints: !include allowed-service-points-response.json
hold-cancellation: !include hold-cancellation.json
errors: !include raml-util/schemas/errors.schema

Expand Down Expand Up @@ -270,6 +271,39 @@ types:
body:
text/plain:
example: internal server error, contact administrator
/allowed-service-points:
displayName: Allowed service points
description: Service that provides a list of allowed pickup service points
get:
description: |
Returns a list of pickup service points allowed for a particular patron and instance
queryParameters:
apikey:
description: "API Key"
type: string
body:
application/json:
type: allowedServicePoints
example: !include examples/allowed-service-points-response.json
responses:
200:
description: |
Successfully returns a list of allowed service points
body:
application/json:
type: hold
example: !include examples/allowed-service-points-response.json
422:
description: Validation error
body:
application/json:
type: errors
500:
description: |
Internal server error, e.g. due to misconfiguration
body:
text/plain:
example: internal server error, contact administrator
/hold:
displayName: Hold Management
description: Services that provide hold management
Expand Down
9 changes: 9 additions & 0 deletions ramls/examples/allowed-service-points-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"allowedServicePoints" : [ {
"id" : "3a40852d-49fd-4df2-a1f9-6e2641a6e91f",
"name" : "Circ Desk 1"
}, {
"id" : "c4c90014-c8c9-4ade-8f24-b5e313319f4b",
"name" : "Circ Desk 2"
} ]
}
3 changes: 3 additions & 0 deletions src/main/java/org/folio/edge/patron/MainVerticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ public Router defineRoutes() {
router.route(HttpMethod.POST, "/patron/account/:patronId/instance/:instanceId/hold")
.handler(patronHandler::handlePlaceInstanceHold);

router.route(HttpMethod.GET, "/patron/account/:patronId/instance/:instanceId/" +
"allowed-service-points").handler(patronHandler::handleGetAllowedServicePoints);

router.route(HttpMethod.POST, "/patron/account/:patronId/hold/:holdId/cancel")
.handler(patronHandler::handleCancelHold);

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/folio/edge/patron/PatronHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,17 @@ public void handlePlaceInstanceHold(RoutingContext ctx) {
t -> handleProxyException(ctx, t)));
}

public void handleGetAllowedServicePoints(RoutingContext ctx) {
handleCommon(ctx,
new String[] { PARAM_PATRON_ID, PARAM_INSTANCE_ID },
new String[] {},
(client, params) -> ((PatronOkapiClient) client).getAllowedServicePoints(
params.get(PARAM_PATRON_ID),
params.get(PARAM_INSTANCE_ID),
resp -> handleProxyResponse(ctx, resp),
t -> handleProxyException(ctx, t)));
}

@Override
protected void invalidApiKey(RoutingContext ctx, String msg) {
accessDenied(ctx, msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ public void cancelHold(String patronId, String holdId, JsonObject holdCancellati
);
}

public void getAllowedServicePoints(String patronId, String instanceId,
Handler<HttpResponse<Buffer>> responseHandler, Handler<Throwable> exceptionHandler) {

get(String.format("%s/patron/account/%s/instance/%s/allowed-service-points", okapiURL,
patronId, instanceId), tenant, null, responseHandler, exceptionHandler);
}

public void getRequest(String holdId, Handler<HttpResponse<Buffer>> responseHandler,
Handler<Throwable> exceptionHandler) {

Expand Down
43 changes: 43 additions & 0 deletions src/test/java/org/folio/edge/patron/MainVerticleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
import static org.folio.edge.patron.utils.PatronMockOkapi.holdCancellationHoldId;
import static org.folio.edge.patron.utils.PatronMockOkapi.holdReqId_notFound;
import static org.folio.edge.patron.utils.PatronMockOkapi.holdReqTs;
import static org.folio.edge.patron.utils.PatronMockOkapi.instanceId_notFound;
import static org.folio.edge.patron.utils.PatronMockOkapi.invalidHoldCancellationdHoldId;
import static org.folio.edge.patron.utils.PatronMockOkapi.limit_param;
import static org.folio.edge.patron.utils.PatronMockOkapi.malformedHoldCancellationHoldId;
import static org.folio.edge.patron.utils.PatronMockOkapi.nonUUIDHoldCanceledByPatronId;
import static org.folio.edge.patron.utils.PatronMockOkapi.offset_param;
import static org.folio.edge.patron.utils.PatronMockOkapi.readMockFile;
import static org.folio.edge.patron.utils.PatronMockOkapi.wrongIntegerParamMessage;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -64,6 +66,7 @@

import io.vertx.core.DeploymentOptions;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;

Expand Down Expand Up @@ -1049,6 +1052,46 @@ public void testPlaceItemHoldRequestNoBody(TestContext context) throws Exception
.body("errorMessage", is(MSG_HOLD_NOBODY));
}

@Test
public void testAllowedServicePointsSuccess(TestContext context) throws Exception {
logger.info("=== Test successful allowed service points request ===");

final Response resp = RestAssured
.with()
.get(String.format("/patron/account/%s/instance/%s/allowed-service-points?apikey=%s",
patronId, instanceId, apiKey))
.then()
.statusCode(200)
.header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON)
.extract()
.response();

JsonObject expected = new JsonObject(readMockFile(
"/allowed_sp_mod_patron_expected_response.json"));
JsonObject actual = new JsonObject(resp.body().asString());
assertEquals(expected, actual);
}

@Test
public void testAllowedServicePointsError(TestContext context) throws Exception {
logger.info("=== Test validation error during allowed service points request ===");

final Response resp = RestAssured
.with()
.get(String.format("/patron/account/%s/instance/%s/allowed-service-points?apikey=%s",
patronId, instanceId_notFound, apiKey))
.then()
.statusCode(422)
.header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON)
.extract()
.response();

JsonObject expected = new JsonObject(readMockFile(
"/allowed_sp_error_edge_patron.json"));
JsonObject actual = new JsonObject(resp.body().asString());
assertEquals(expected, actual);
}

@Test
public void testCancelHoldSuccess(TestContext context) throws Exception {
logger.info("=== Test cancel hold success ===");
Expand Down
26 changes: 26 additions & 0 deletions src/test/java/org/folio/edge/patron/utils/PatronMockOkapi.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ public Router defineRoutes() {
router.route(HttpMethod.POST, "/patron/account/:patronId/instance/:instanceId/hold")
.handler(this::placeInstanceHoldHandler);

router.route(HttpMethod.GET,
"/patron/account/:patronId/instance/:instanceId/allowed-service-points")
.handler(this::getAllowedServicePoints);

router.route(HttpMethod.POST, "/patron/account/:patronId/hold/:holdId/cancel")
.handler(this::cancelHoldHandler);

Expand Down Expand Up @@ -431,6 +435,28 @@ public void placeInstanceHoldHandler(RoutingContext ctx) {
}
}

public void getAllowedServicePoints(RoutingContext ctx) {
String instanceId = ctx.request().getParam(PARAM_INSTANCE_ID);
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.instance.hold.post");
} else if (instanceId.equals(instanceId_notFound)) {
ctx.response()
.setStatusCode(422)
.putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON)
.end(readMockFile("/allowed_sp_error_mod_patron.json"));
} else {
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON)
.end(readMockFile("/allowed_sp_mod_patron_expected_response.json"));
}
}

public static String getPatronJson(String extPatronId) {
JsonArray users = new JsonArray();
logger.info(extPatronId_notFound);
Expand Down
4 changes: 4 additions & 0 deletions src/test/resources/allowed_sp_error_edge_patron.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"code": 422,
"errorMessage": "Instance with ID d5a2f197-23d9-4153-9d79-da7a9f2d4a0d was not found"
}
8 changes: 8 additions & 0 deletions src/test/resources/allowed_sp_error_mod_patron.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"errors": [
{
"message": "Instance with ID d5a2f197-23d9-4153-9d79-da7a9f2d4a0d was not found",
"parameters": []
}
]
}
12 changes: 12 additions & 0 deletions src/test/resources/allowed_sp_mod_patron_expected_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"allowedServicePoints" : [ {
"id" : "3a40852d-49fd-4df2-a1f9-6e2641a6e91f",
"name" : "Circ Desk 1"
}, {
"id" : "c4c90014-c8c9-4ade-8f24-b5e313319f4b",
"name" : "Circ Desk 2"
}, {
"id" : "7c5abc9f-f3d7-4856-b8d7-6712462ca007",
"name" : "Online"
} ]
}

0 comments on commit 2570ca8

Please sign in to comment.