Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Fix manual patron blocks not reflected in SIP2 Patron Status Response (24) ([SIP2-310](https://folio-org.atlassian.net/browse/SIP2-310))
* Use GitHub Workflows for Maven ([SIP2-307](https://folio-org.atlassian.net/browse/SIP2-307))
* Fix misleading log messages when token refresh fails and recovery login is used([SIP2-316](https://folio-org.atlassian.net/browse/SIP2-316))
* Fix doPinCheck failing when FOLIO returns 200 without Content-Type header([SIP2-309](https://folio-org.atlassian.net/browse/SIP2-309))

---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ public Future<Boolean> doPinCheck(IRequestData requestData) {
log.debug(sessionData, "Doing pin verification at {}", requestData::getPath);
return initHttpRequest(POST, requestData)
.flatMap(request -> request.sendJsonObject(requestData.getBody()))
.expecting(getHttpRequestExpectations(sessionData, SC_SUCCESS))
.expecting(SC_SUCCESS.wrappingFailure(
(head, err) -> getHttpRequestError(sessionData, head, err)))
.map(Boolean.TRUE)
.onFailure(e -> log.error(sessionData, "Pin check failed", e));
}
Expand Down
78 changes: 78 additions & 0 deletions src/test/java/org/folio/edge/sip2/api/PatronInformationIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,84 @@ void getPatronInformationWithPasswordVerificationRequired_validPassword() throws
));
}

@Test
@WiremockStubs({
"/wiremock/stubs/mod-settings/200-get-locale.json",
"/wiremock/stubs/mod-settings/200-get-settings(pin-validation).json",
"/wiremock/stubs/mod-login/201-post-acs-login.json",
"/wiremock/stubs/mod-users/200-get-user-by-patron-identifier.json",
"/wiremock/stubs/mod-users/200-post-patron-pin.json",
"/wiremock/stubs/mod-users-bl/200-get-user-by-id.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-open-loans.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-open-loans-by-due-date.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-requests-hold.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-requests-recall.json",
"/wiremock/stubs/mod-fee-fines/200-get-accounts.json",
"/wiremock/stubs/mod-fee-fines/200-get-manualblocks.json",
"/wiremock/stubs/mod-fee-fines/200-get-feefines-empty.json",
})
void getPatronInformation_positive_pinVerificationEnabled() throws Throwable {
executeInSession(
successLoginExchange(),
sip2Exchange(
PatronInformationCommand.builder()
.patronIdentifier(PATRON_BARCODE)
.languageCode(LanguageMapper.ENGLISH)
.summary(HOLD_ITEMS)
.patronPassword("132456")
.build(),
sip2Result -> {
assertSuccessfulExchange(sip2Result);

var respMsg = sip2Result.getResponseMessage();
assertThat(respMsg).startsWith("64");

var patronInfo = parseResponse(respMsg);
assertThat(patronInfo.getValidPatron()).isTrue();
assertThat(patronInfo.getValidPatronPassword()).isTrue();
}
));
}

@Test
@WiremockStubs({
"/wiremock/stubs/mod-settings/200-get-locale.json",
"/wiremock/stubs/mod-settings/200-get-settings(pin-validation).json",
"/wiremock/stubs/mod-login/201-post-acs-login.json",
"/wiremock/stubs/mod-users/200-get-user-by-patron-identifier.json",
"/wiremock/stubs/mod-users/422-post-patron-pin.json",
"/wiremock/stubs/mod-users-bl/200-get-user-by-id.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-open-loans.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-open-loans-by-due-date.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-requests-hold.json",
"/wiremock/stubs/mod-circulation/200-get-circulation-requests-recall.json",
"/wiremock/stubs/mod-fee-fines/200-get-accounts.json",
"/wiremock/stubs/mod-fee-fines/200-get-manualblocks.json",
"/wiremock/stubs/mod-fee-fines/200-get-feefines-empty.json",
})
void getPatronInformation_negative_pinVerificationEnabledWithInvalidPin() throws Throwable {
executeInSession(
successLoginExchange(),
sip2Exchange(
PatronInformationCommand.builder()
.patronIdentifier(PATRON_BARCODE)
.languageCode(LanguageMapper.ENGLISH)
.summary(HOLD_ITEMS)
.patronPassword("132456")
.build(),
sip2Result -> {
assertSuccessfulExchange(sip2Result);

var respMsg = sip2Result.getResponseMessage();
assertThat(respMsg).startsWith("64");

var patronInfo = parseResponse(respMsg);
assertThat(patronInfo.getValidPatron()).isTrue();
assertThat(patronInfo.getValidPatronPassword()).isFalse();
}
));
}

private static PatronInformationResponse parseResponse(String respMsg) {
return new PatronInformationResponseParser(delimiter, TIMEZONE).parse(respMsg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientResponse;
import io.vertx.core.http.HttpMethod;
Expand Down Expand Up @@ -228,6 +229,48 @@ void doPinCheck_positive(VertxTestContext testContext) {
}));
}

@Test
void doPinCheck_positive_missingContentTypeHeader(VertxTestContext testContext) {
var requestData = testRequestDataWithBody("/patron-pin/verify",
new JsonObject().put("pin", "1234"));
var httpResponse = httpResponseNoBody(200, "OK");

prepareRequestMocks(POST, requestData);
when(jsonRequest.sendJsonObject(any())).thenReturn(succeededFuture(httpResponse));
when(loginRepository.getSessionAccessToken(any(SessionData.class)))
.thenReturn(succeededFuture(ACCESS_TOKEN));

var resultFuture = provider.doPinCheck(requestData);

resultFuture.onComplete(testContext.succeeding(result -> {
assertTrue(result);
testContext.completeNow();
}));
}

@Test
void doPinCheck_realHttp_200WithoutContentType(Vertx vertx, VertxTestContext testContext) {
var realClient = WebClient.create(vertx);
var requestData = testRequestDataWithBody("/patron-pin/verify",
new JsonObject().put("id", "user-id").put("pin", "1234"));
when(loginRepository.getSessionAccessToken(any(SessionData.class)))
.thenReturn(succeededFuture(ACCESS_TOKEN));

vertx.createHttpServer()
.requestHandler(req -> req.response().setStatusCode(200).end())
.listen(0)
.compose(server -> {
var realProvider = new FolioResourceProvider(
loginRepository, "http://localhost:" + server.actualPort(), realClient);
return realProvider.doPinCheck(requestData)
.compose(result -> server.close().map(result));
})
.onComplete(testContext.succeeding(result -> {
assertTrue(result);
testContext.completeNow();
}));
}

@Test
void doPinCheck_negative_accessTokenMissing(VertxTestContext testContext) {
var requestData = testRequestDataWithBody("/pin-verify", new JsonObject());
Expand Down Expand Up @@ -306,6 +349,11 @@ private static HttpResponse<JsonObject> httpResponse(
headers, caseInsensitiveMultiMap(), emptyList(), body, emptyList());
}

private static HttpResponse<JsonObject> httpResponseNoBody(int statusCode, String statusMessage) {
return new HttpResponseImpl<>(HTTP_1_1, statusCode, statusMessage,
httpHeaders(), caseInsensitiveMultiMap(), emptyList(), null, emptyList());
}

private static class TestRequestData implements IRequestData {
private final String path;
private final JsonObject body;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
},
"response": {
"status": 200,
"body": "",
"headers": {
"Content-Type": "application/json"
}
"body": ""
Comment thread
pfilippov-epam marked this conversation as resolved.
}
}
Loading