Skip to content

Commit f7e551a

Browse files
feat(v4.0.0): migrate 50 more endpoints to Http4s400 (176/258, 68%)
Batches 9–12 in Http4s400.scala add 42 real `lazy val NAME: HttpRoutes[IO]` handlers ported from Lift, plus 8 ResourceDoc aliases reusing the existing `createTransactionRequest` handler for the transaction-request-type variants (ACCOUNT, ACCOUNT_OTP, SEPA, COUNTERPARTY, REFUND, FREE_FORM, SIMPLE, AGENT_CASH_WITHDRAWAL — already covered by `literalAllCapsSegments` in Http4sSupport). Post-batch fixes: - deleteExplicitCounterparty: COUNTERPARTY_ID → COUNTERPARTY_ID_PARAM in ResourceDoc URL so middleware skips the counterparty lookup (400 vs 404 for missing IDs) - updateBankAttribute: add canUpdateBankAttribute role to ResourceDoc so middleware returns 403 (test expectation) instead of handler's 400 - getFastFirehoseAccountsAtOneBank: read pagination from URL query string via extractHttpParamsFromUrl, not from headers — matching Lift v4 ErrorResponseConverter + ErrorMessages.getCodeByOBPPrefix: - For any thrown Exception with an OBP-XXXXX prefixed message and the default failCode=400, look up the canonical status code in ErrorMessages.errorToCode by OBP prefix. Reproduces Lift's errorJsonResponse behaviour (403 for UserNoPermissionAccessView, UserHasMissingRoles, etc.; 401 for AuthenticatedUserIsRequired). Caller who set failCode explicitly is honored. Skipped 43 endpoints (dynamic/reflection: 31; complex authn: 12) remain on the Lift bridge — they'll be addressed in a follow-up batch. v4 test suite: 491 passed, 1 pre-existing failure (ApiCollectionEndpointTest BGv1.3-getConsentStatus, fails on prior commit too).
1 parent 5895ecf commit f7e551a

3 files changed

Lines changed: 1644 additions & 2 deletions

File tree

obp-api/src/main/scala/code/api/util/ErrorMessages.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,19 @@ object ErrorMessages {
10291029
*/
10301030
def getCode(errorMsg: String): Int = errorToCode.get(errorMsg).getOrElse(400)
10311031

1032+
/**
1033+
* Resolve HTTP status code for an OBP-prefixed error message that may have a
1034+
* runtime suffix appended (e.g. "OBP-20020: User does not have access to the view.
1035+
* Current ViewId is owner"). Extracts the OBP-XXXXX prefix and returns the
1036+
* canonical status code from errorToCode, or 400 if not found.
1037+
*/
1038+
def getCodeByOBPPrefix(errorMsg: String): Int = {
1039+
val prefixOpt = "OBP-\\d{5}".r.findFirstIn(errorMsg)
1040+
prefixOpt.flatMap { prefix =>
1041+
errorToCode.find { case (key, _) => key.startsWith(prefix + ":") }.map(_._2)
1042+
}.getOrElse(400)
1043+
}
1044+
10321045
/****** special error message, start with $, mark as do validation according ResourceDoc errorResponseBodies *****/
10331046
/**
10341047
* validate method: APIUtil.authorizedAccess

obp-api/src/main/scala/code/api/util/http4s/ErrorResponseConverter.scala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,24 @@ object ErrorResponseConverter {
8585
}
8686
}
8787

88+
/**
89+
* Translate a 400 default with an OBP-prefixed message to the canonical status
90+
* Lift assigns (403 for role/view-access codes, 401 for auth codes, etc.) via
91+
* ErrorMessages.getCodeByOBPPrefix. Leaves non-400 failCodes (caller set
92+
* status explicitly) untouched.
93+
*/
94+
private def resolveStatusCode(failCode: Int, failMsg: String): Int =
95+
if (failCode == 400) code.api.util.ErrorMessages.getCodeByOBPPrefix(failMsg)
96+
else failCode
97+
8898
/**
8999
* Convert APIFailureNewStyle to http4s Response.
90100
* Uses failCode as HTTP status and failMsg as error message.
91101
*/
92102
def apiFailureToResponse(failure: APIFailureNewStyle, callContext: CallContext): IO[Response[IO]] = {
93-
val errorJson = OBPErrorResponse(failure.failCode, failure.failMsg)
94-
val status = org.http4s.Status.fromInt(failure.failCode).getOrElse(org.http4s.Status.BadRequest)
103+
val resolvedCode = resolveStatusCode(failure.failCode, failure.failMsg)
104+
val errorJson = OBPErrorResponse(resolvedCode, failure.failMsg)
105+
val status = org.http4s.Status.fromInt(resolvedCode).getOrElse(org.http4s.Status.BadRequest)
95106
IO.pure(
96107
Response[IO](status)
97108
.withEntity(toJsonString(errorJson))

0 commit comments

Comments
 (0)