Skip to content

Commit

Permalink
[EDGPATRON-133]-Added PUT api for external patron.
Browse files Browse the repository at this point in the history
  • Loading branch information
SinghAdes committed Jun 13, 2024
1 parent da1c828 commit a25c44a
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 4 deletions.
16 changes: 15 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
"users.item.get"
]
},
{
"methods": ["PUT"],
"pathPattern": "/patron/account/by-email/{email}",
"permissionsRequired": ["patron.account.item.put"],
"modulePermissions": [
"users.item.put"
]
},
{
"methods": ["POST"],
"pathPattern": "/patron/account/{accountId}/item/{itemId}/renew",
Expand Down Expand Up @@ -141,6 +149,11 @@
"displayName": "patron - get a list of allowed service points for a hold",
"description": "Get a list of allowed service points for a hold"
},
{
"permissionName": "patron.account.item.put",
"displayName": "update external_patron",
"description": "Update external_patron based on emailId"
},
{
"permissionName": "patron.all",
"displayName": "patron - all permissions",
Expand All @@ -152,7 +165,8 @@
"patron.hold.instance.item.post",
"patron.hold.cancel.item.post",
"patron.hold.allowed-service-points.get",
"patron.account.item.post"
"patron.account.item.post",
"patron.account.item.put"
]
}
],
Expand Down
53 changes: 52 additions & 1 deletion ramls/patron.raml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,58 @@ traits:
body:
text/plain:
example: internal server error, contact administrator

put:
description: |
Updates external patron request
is: [validate]
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
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/folio/patron/rest/models/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ public void setPrimaryAddress(Boolean primaryAddress) {

@Pattern(regexp = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[1-5][a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
private String addressTypeId;

public String getAddressTypeId() {
return addressTypeId;
}

private Boolean primaryAddress;
}
}
Expand Down
59 changes: 57 additions & 2 deletions src/main/java/org/folio/rest/impl/PatronServicesResourceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void postPatronAccount(ExternalPatron entity, Map<String, String> okapiHe
.thenCompose(userResponse -> handleUserResponse(userResponse, entity, okapiHeaders, userRepository))
.thenAccept(response -> asyncResultHandler.handle(Future.succeededFuture(response)))
.exceptionally(throwable -> {
asyncResultHandler.handle(Future.failedFuture(throwable.getMessage()));
asyncResultHandler.handle(handleError(throwable));
return null;
});
}
Expand All @@ -129,11 +129,57 @@ public void getPatronAccountByEmailByEmailId(String email, Map<String, String> o
getUserByEmail(email, okapiHeaders, userRepository)
.thenAccept(userResponse -> handleGetUserResponse(userResponse, asyncResultHandler))
.exceptionally(throwable -> {
asyncResultHandler.handle(Future.failedFuture(throwable.getMessage()));
asyncResultHandler.handle(handleError(throwable));
return null;
});
}

@Override
public void putPatronAccountByEmailByEmailId(String emailId, ExternalPatron entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
var httpClient = HttpClientFactory.getHttpClient(vertxContext.owner());
final var userRepository = new UserRepository(httpClient);

getUserByEmail(emailId, okapiHeaders, userRepository)
.thenCompose(userResponse -> handleUserUpdateResponse(userResponse, entity, okapiHeaders, userRepository, asyncResultHandler))
.thenAccept(response -> asyncResultHandler.handle(Future.succeededFuture(response)))
.exceptionally(throwable -> {
asyncResultHandler.handle(handleError(throwable));
return null;
});
}
private CompletableFuture<Response> handleUserUpdateResponse(JsonObject userResponse, ExternalPatron entity, Map<String, String> okapiHeaders, UserRepository userRepository, Handler<AsyncResult<Response>> asyncResultHandler) {
int totalRecords = userResponse.getInteger(TOTAL_RECORDS);
if (totalRecords > 1) {
return CompletableFuture.completedFuture(
PutPatronAccountByEmailByEmailIdResponse.respond400WithTextPlain("Multiple users found with the same email")
);
} else if (totalRecords == 1) {
JsonObject userJson = userResponse.getJsonArray(USERS).getJsonObject(0);
String userId = userJson.getString(ID);
String patronGroup = userJson.getString(PATRON_GROUP);

return getRemotePatronGroupId(userRepository, okapiHeaders)
.thenCompose(remotePatronGroupId ->
getAddressTypes(userRepository, okapiHeaders)
.thenCompose(addressTypes -> {
if (Objects.equals(patronGroup, remotePatronGroupId)) {
String homeAddressTypeId = addressTypes.getString(HOME_ADDRESS_TYPE);
String workAddressTypeId = addressTypes.getString(WORK_ADDRESS_TYPE);
return updateUser(userId, entity, okapiHeaders, userRepository, remotePatronGroupId, homeAddressTypeId, workAddressTypeId);
} else {
return CompletableFuture.completedFuture(
PutPatronAccountByEmailByEmailIdResponse.respond500WithTextPlain("Required Patron group not applicable for user")
);
}
})
);
} else {
return CompletableFuture.completedFuture(
PutPatronAccountByEmailByEmailIdResponse.respond404WithTextPlain("user does not exist")
);
}
}

private void handleGetUserResponse(JsonObject userResponse, Handler<AsyncResult<Response>> asyncResultHandler) {
int totalRecords = userResponse.getInteger(TOTAL_RECORDS);

Expand Down Expand Up @@ -235,6 +281,15 @@ private CompletableFuture<Response> createUser(ExternalPatron entity, Map<String
);
}

private CompletableFuture<Response> updateUser(String id, ExternalPatron entity, Map<String, String> okapiHeaders, UserRepository userRepository, String remotePatronGroupId, String homeAddressTypeId, String workAddressTypeId) {
User user = PatronUtils.mapToUser(entity, remotePatronGroupId, homeAddressTypeId, workAddressTypeId);
user.setId(id);
return userRepository.updateUser(id, user, okapiHeaders)
.thenApply(updatedUserJson ->
PutPatronAccountByEmailByEmailIdResponse.respond204WithApplicationJson(entity)
);
}

@Validate
@Override
public void getPatronAccountById(String id, boolean includeLoans,
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/folio/rest/impl/UserRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ public CompletableFuture<JsonObject> createUser(User user, Map<String, String> o
.thenApply(ResponseInterpreter::verifyAndExtractBody);
}

public CompletableFuture<JsonObject> updateUser(String id, User user, Map<String, String> okapiHeaders) {
System.out.println(user.getPersonal().getAddresses().get(0).getAddressTypeId());
JsonObject g = JsonObject.mapFrom(user);
System.out.println(g);
return client.put("/users/"+ id, JsonObject.mapFrom(user), okapiHeaders)
.thenApply(ResponseInterpreter::verifyAndExtractBody);
}

public CompletableFuture<JsonObject> getGroupByGroupName(String groupName, Map<String, String> okapiHeaders) {
Map<String, String> queryParameters = Maps.newLinkedHashMap();
queryParameters.put(QUERY, "(group=="+groupName+")");
Expand Down
71 changes: 71 additions & 0 deletions src/test/java/org/folio/rest/impl/PatronResourceImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ public void setUp(Vertx vertx, VertxTestContext context) {
.setStatusCode(200)
.putHeader("content-type", "application/json")
.end(readMockFile(mockDataFolder + "/user_active.json"));
} else if (req.method()==HttpMethod.PUT && req.path().equals("/users/84970943-c066-4b45-83fd-73e65868a5d4")) {
req.response()
.setStatusCode(204)
.putHeader("content-type", "application/json")
.end(readMockFile(mockDataFolder + "/user_active.json"));
} else if (req.path().equals(String.format("/users/%s", inactiveUserId))) {
req.response()
.setStatusCode(200)
Expand All @@ -197,6 +202,21 @@ public void setUp(Vertx vertx, VertxTestContext context) {
.setStatusCode(200)
.putHeader("content-type", "application/json")
.end(readMockFile(mockDataFolder + "/external_user.json"));
} else if (req.uri().equals("/users?query=%28personal.email%3D%3Dadsfg%29")) {
req.response()
.setStatusCode(200)
.putHeader("content-type", "application/json")
.end(readMockFile(mockDataFolder + "/external_user2.json"));
} else if (req.uri().equals("/users?query=%28personal.email%3D%3Dad%29")) {
req.response()
.setStatusCode(200)
.putHeader("content-type", "application/json")
.end(readMockFile(mockDataFolder + "/external_user6.json"));
} else if (req.uri().equals("/users?query=%28personal.email%3D%3Da%29")) {
req.response()
.setStatusCode(200)
.putHeader("content-type", "application/json")
.end(readMockFile(mockDataFolder + "/external_user.json"));
} else if (req.uri().equals("/users?query=%28personal.email%3D%3Dtst%29")) {
req.response()
.setStatusCode(200)
Expand Down Expand Up @@ -989,6 +1009,57 @@ final void testGetPatronAccountByEmail() {
.extract().response();
}

@Test
final void testUpdatePatronAccountByEmail() {
given()
.log().all()
.header(tenantHeader)
.header(urlHeader)
.header(contentTypeHeader)
.body(readMockFile(mockDataFolder + "/remote_patron2.json"))
.when()
.put(remotePatronAccountPathByEmail + "/adsfg")
.then()
.contentType(JSON)
.statusCode(204)
.extract()
.response();
}

@Test
final void testNotFoundWhenUpdatePatronAccountByEmail() {
given()
.log().all()
.header(tenantHeader)
.header(urlHeader)
.header(contentTypeHeader)
.body(readMockFile(mockDataFolder + "/remote_patron2.json"))
.when()
.put(remotePatronAccountPathByEmail + "/a")
.then()
.contentType(TEXT)
.statusCode(404)
.extract()
.response();
}

@Test
final void testIncorrectPatronWhenUpdatePatronAccountByEmail() {
given()
.log().all()
.header(tenantHeader)
.header(urlHeader)
.header(contentTypeHeader)
.body(readMockFile(mockDataFolder + "/remote_patron2.json"))
.when()
.put(remotePatronAccountPathByEmail + "/ad")
.then()
.contentType(TEXT)
.statusCode(500)
.extract()
.response();
}

@Test
public final void testGetPatronAccountByIdNoListsWhenLimitZero() {
logger.info("Testing for successful patron services account retrieval by id without item lists");
Expand Down
65 changes: 65 additions & 0 deletions src/test/resources/PatronServicesResourceImpl/external_user6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"users": [
{
"id": "84970943-c066-4b45-83fd-73e65868a5d4",
"externalSystemId": "12346-abcde-67890-fhhik",
"active": true,
"type": "patron",
"patronGroup": "3684a786-1111-4268-8ed0-9db82ebca60b",
"departments": [],
"proxyFor": [],
"personal": {
"lastName": "Doe",
"firstName": "Joh",
"middleName": "11",
"preferredFirstName": "J",
"email": "adsfg",
"phone": "555-1234",
"mobilePhone": "555-5678",
"addresses": [
{
"id": "158d16f4-648f-4bc7-b764-ea48251adadd",
"countryId": "USA",
"addressLine1": "123 Main St",
"addressLine2": "Apt 4B",
"city": "Springfield",
"region": "Illinois",
"postalCode": "62704",
"addressTypeId": "93d3d88d-499b-45d0-9bc7-ac73c3a19880",
"primaryAddress": true
},
{
"id": "0a63f1fb-6762-4513-8972-5d519cb8ad76",
"countryId": "USA",
"addressLine1": "456 Elm St",
"addressLine2": "Suite 5A",
"city": "Springfield",
"region": "Illinois",
"postalCode": "62705",
"addressTypeId": "1c4b225f-f669-4e9b-afcd-ebc0e273a34e",
"primaryAddress": false
}
]
},
"enrollmentDate": "2024-05-27T09:15:58.018+00:00",
"expirationDate": "2026-05-26T18:30:00.000+00:00",
"createdDate": "2024-05-27T09:15:58.225+00:00",
"updatedDate": "2024-05-27T09:15:58.225+00:00",
"metadata": {
"createdDate": "2024-05-27T09:15:58.174+00:00",
"createdByUserId": "0b9e36cf-21ef-5251-9c50-507cc4b2b165",
"updatedDate": "2024-05-27T09:15:58.174+00:00",
"updatedByUserId": "0b9e36cf-21ef-5251-9c50-507cc4b2b165"
},
"preferredEmailCommunication": [
"Programs"
]
}
],
"totalRecords": 1,
"resultInfo": {
"totalRecords": 1,
"facets": [],
"diagnostics": []
}
}

0 comments on commit a25c44a

Please sign in to comment.