Skip to content

Commit 5895ecf

Browse files
fix(v4.0.0): CI shard1 test failures (13 tests across 9 suites)
Http4s400.scala — role/URL/shape fixes for migrated endpoints: - deleteBankAttribute: withUserAndBankDelete (204), add canDeleteBankAttribute - deleteCustomerAttribute: correct URL template; add canDeleteCustomerAttributeAtAnyBank - getCustomersByCustomerPhoneNumber: canCreateCustomerAtAnyBank → canGetCustomersAtOneBank - getEntitlementsForBank: add canGetEntitlementsForAnyBank to role list - getCounterpartyByIdForAnyAccount: COUNTERPARTY_ID → COUNTERPARTY_ID_PARAM (400 not 404) - getTransactionRequest: return JSONFactory210 (singular `challenge`) per Lift v4 - getTransactionRequestAttributeById: plural → singular role - getCustomerMessages: add missing canGetCustomerMessages role - createCustomerMessage: migrated POST (Lift handler unreachable via bridge) ErrorResponseConverter.scala — recognise plain `Exception("OBP-XXXXX: ...")` (thrown by fullBoxOrException(Failure)) as 400 to match Lift's errorJsonResponse behaviour. Fixes UserCustomerLinkTest second-delete 500 vs 400. All 113 tests across the originally-failing 9 suites now pass.
1 parent d070005 commit 5895ecf

2 files changed

Lines changed: 46 additions & 18 deletions

File tree

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ object ErrorResponseConverter {
3434
implicit val formats: Formats = CustomJsonFormats.formats
3535
private val jsonContentType: `Content-Type` = `Content-Type`(MediaType.application.json)
3636

37+
private val obpErrorCodePrefix = "^OBP-\\d{5}: ".r
38+
3739
private def tryExtractApiFailureFromExceptionMessage(error: Throwable): Option[APIFailureNewStyle] = {
3840
val msg = Option(error.getMessage).getOrElse("").trim
3941
if (msg.startsWith("{") && msg.contains("\"failCode\"") && msg.contains("\"failMsg\"")) {
@@ -45,6 +47,9 @@ object ErrorResponseConverter {
4547
} catch {
4648
case _: Throwable => None
4749
}
50+
} else if (obpErrorCodePrefix.findFirstIn(msg).isDefined) {
51+
// Plain Exception("OBP-XXXXX: ...") thrown by fullBoxOrException(Failure(msg)) — Lift treats these as 400.
52+
Some(APIFailureNewStyle(msg, 400))
4853
} else {
4954
None
5055
}

obp-api/src/main/scala/code/api/v4_0_0/Http4s400.scala

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,7 +2529,7 @@ object Http4s400 {
25292529

25302530
staticResourceDocs += ResourceDoc(
25312531
null, implementedInApiVersion, nameOf(getCounterpartyByIdForAnyAccount), "GET",
2532-
"/management/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID",
2532+
"/management/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID_PARAM",
25332533
"Get Counterparty by Id for any account (Explicit)",
25342534
s"""Get Counterparty by COUNTERPARTY_ID.""".stripMargin,
25352535
EmptyBody, counterpartyWithMetadataJson400,
@@ -2946,10 +2946,7 @@ object Http4s400 {
29462946
for {
29472947
(transactionRequest, _) <- NewStyle.function.getTransactionRequestImpl(
29482948
TransactionRequestId(transactionRequestIdStr), Some(cc))
2949-
(transactionAttributes, _) <- NewStyle.function.getTransactionRequestAttributes(
2950-
account.bankId, TransactionRequestId(transactionRequestIdStr), Some(cc))
2951-
} yield JSONFactory400.createTransactionRequestWithChargeJSON(
2952-
transactionRequest, List.empty, transactionAttributes)
2949+
} yield code.api.v2_1_0.JSONFactory210.createTransactionRequestWithChargeJSON(transactionRequest)
29532950
}
29542951
}
29552952

@@ -3129,7 +3126,7 @@ object Http4s400 {
31293126
EmptyBody, transactionRequestAttributeResponseJson,
31303127
List($AuthenticatedUserIsRequired, $BankNotFound, $BankAccountNotFound, InvalidJsonFormat, UnknownError),
31313128
List(apiTagTransactionRequest, apiTagTransactionRequestAttribute, apiTagAttribute),
3132-
Some(List(canGetTransactionRequestAttributesAtOneBank)),
3129+
Some(List(canGetTransactionRequestAttributeAtOneBank)),
31333130
http4sPartialFunction = Some(getTransactionRequestAttributeById))
31343131

31353132
staticResourceDocs += ResourceDoc(
@@ -3203,7 +3200,7 @@ object Http4s400 {
32033200
postCustomerPhoneNumberJsonV400, customerJsonV310,
32043201
List($AuthenticatedUserIsRequired, $BankNotFound, InvalidJsonFormat, UnknownError),
32053202
List(apiTagCustomer),
3206-
Some(List(canCreateCustomerAtAnyBank)),
3203+
Some(List(canGetCustomersAtOneBank)),
32073204
http4sPartialFunction = Some(getCustomersByCustomerPhoneNumber))
32083205

32093206
staticResourceDocs += ResourceDoc(
@@ -3791,13 +3788,11 @@ object Http4s400 {
37913788
}
37923789

37933790
lazy val deleteBankAttribute: HttpRoutes[IO] = HttpRoutes.of[IO] {
3794-
case req @ DELETE -> `prefixPath` / "banks" / bankIdStr / "attributes" / bankAttributeId =>
3795-
EndpointHelpers.withUser(req) { (user, cc) =>
3791+
case req @ DELETE -> `prefixPath` / "banks" / _ / "attributes" / bankAttributeId =>
3792+
EndpointHelpers.withUserAndBankDelete(req) { (_, _, cc) =>
37963793
for {
3797-
_ <- NewStyle.function.hasEntitlement(bankIdStr, user.userId, canDeleteBankAttribute, Some(cc))
3798-
(_, _) <- NewStyle.function.getBank(BankId(bankIdStr), Some(cc))
3799-
(deleted, _) <- NewStyle.function.deleteBankAttribute(bankAttributeId, Some(cc))
3800-
} yield deleted
3794+
(_, _) <- NewStyle.function.deleteBankAttribute(bankAttributeId, Some(cc))
3795+
} yield ()
38013796
}
38023797
}
38033798

@@ -4055,15 +4050,15 @@ object Http4s400 {
40554050

40564051
staticResourceDocs += ResourceDoc(
40574052
null, implementedInApiVersion, nameOf(deleteCustomerAttribute), "DELETE",
4058-
"/banks/BANK_ID/customers/CUSTOMER_ID/attributes/CUSTOMER_ATTRIBUTE_ID",
4053+
"/banks/BANK_ID/customers/attributes/CUSTOMER_ATTRIBUTE_ID",
40594054
"Delete Customer Attribute",
40604055
s"""Delete Customer Attribute.
40614056
|
40624057
|${userAuthenticationMessage(true)}""".stripMargin,
40634058
EmptyBody, EmptyBody,
40644059
List(UserHasMissingRoles, UnknownError),
40654060
List(apiTagCustomer, apiTagCustomerAttribute, apiTagAttribute),
4066-
Some(List(canDeleteCustomerAttributeAtOneBank)),
4061+
Some(List(canDeleteCustomerAttributeAtOneBank, canDeleteCustomerAttributeAtAnyBank)),
40674062
http4sPartialFunction = Some(deleteCustomerAttribute))
40684063

40694064
staticResourceDocs += ResourceDoc(
@@ -4075,7 +4070,8 @@ object Http4s400 {
40754070
|${userAuthenticationMessage(true)}""".stripMargin,
40764071
EmptyBody, EmptyBody,
40774072
List(UserHasMissingRoles, BankNotFound, UnknownError),
4078-
List(apiTagBank, apiTagBankAttribute, apiTagAttribute), None,
4073+
List(apiTagBank, apiTagBankAttribute, apiTagAttribute),
4074+
Some(List(canDeleteBankAttribute)),
40794075
http4sPartialFunction = Some(deleteBankAttribute))
40804076

40814077
staticResourceDocs += ResourceDoc(
@@ -4329,6 +4325,19 @@ object Http4s400 {
43294325
}
43304326
}
43314327

4328+
lazy val createCustomerMessage: HttpRoutes[IO] = HttpRoutes.of[IO] {
4329+
case req @ POST -> `prefixPath` / "banks" / _ / "customers" / customerId / "messages" =>
4330+
EndpointHelpers.withUserAndBankAndBodyCreated[CreateMessageJsonV400, code.api.v1_2_1.SuccessMessage](req) {
4331+
(_, bank, postedData, cc) =>
4332+
for {
4333+
(customer, _) <- NewStyle.function.getCustomerByCustomerId(customerId, Some(cc))
4334+
(_, _) <- NewStyle.function.createCustomerMessage(
4335+
customer, bank.bankId, postedData.transport, postedData.message,
4336+
postedData.from_department, postedData.from_person, Some(cc))
4337+
} yield successMessage
4338+
}
4339+
}
4340+
43324341
private def initBatch2ResourceDocs(): Unit = {
43334342
staticResourceDocs += ResourceDoc(
43344343
null, implementedInApiVersion, nameOf(getEntitlementsForBank), "GET",
@@ -4338,7 +4347,7 @@ object Http4s400 {
43384347
EmptyBody, entitlementsJsonV400,
43394348
List($AuthenticatedUserIsRequired, BankNotFound, UserHasMissingRoles, UnknownError),
43404349
List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagBank),
4341-
Some(List(canGetEntitlementsForOneBank)),
4350+
Some(List(canGetEntitlementsForOneBank, canGetEntitlementsForAnyBank)),
43424351
http4sPartialFunction = Some(getEntitlementsForBank))
43434352

43444353
staticResourceDocs += ResourceDoc(
@@ -4563,8 +4572,21 @@ object Http4s400 {
45634572
|${userAuthenticationMessage(true)}""".stripMargin,
45644573
EmptyBody, customerMessagesJson,
45654574
List($AuthenticatedUserIsRequired, $BankNotFound, UnknownError),
4566-
List(apiTagMessage, apiTagCustomer), None,
4575+
List(apiTagMessage, apiTagCustomer),
4576+
Some(List(canGetCustomerMessages)),
45674577
http4sPartialFunction = Some(getCustomerMessages))
4578+
4579+
staticResourceDocs += ResourceDoc(
4580+
null, implementedInApiVersion, nameOf(createCustomerMessage), "POST",
4581+
"/banks/BANK_ID/customers/CUSTOMER_ID/messages",
4582+
"Create Customer Message",
4583+
s"""Create a message for the customer specified by CUSTOMER_ID
4584+
|${userAuthenticationMessage(true)}""".stripMargin,
4585+
createMessageJsonV400, successMessage,
4586+
List($AuthenticatedUserIsRequired, $BankNotFound),
4587+
List(apiTagMessage, apiTagCustomer, apiTagPerson),
4588+
Some(List(canCreateCustomerMessage)),
4589+
http4sPartialFunction = Some(createCustomerMessage))
45684590
}
45694591
initBatch2ResourceDocs()
45704592

@@ -4821,6 +4843,7 @@ object Http4s400 {
48214843
.orElse(getUserCustomerLinksByUserId.run(req))
48224844
.orElse(getUserCustomerLinksByCustomerId.run(req))
48234845
.orElse(getCustomerMessages.run(req))
4846+
.orElse(createCustomerMessage.run(req))
48244847
// Batch 3 — DELETEs
48254848
.orElse(deleteTransactionAttributeDefinition.run(req))
48264849
.orElse(deleteCustomerAttributeDefinition.run(req))

0 commit comments

Comments
 (0)