mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 11:06:49 +00:00
refactor(http4s): consolidate validated entities into CallContext
- Add bank, bankAccount, view, and counterparty fields to CallContext case class - Remove individual Vault keys for User, Bank, BankAccount, View, and Counterparty from Http4sRequestAttributes - Simplify Http4sRequestAttributes to store only CallContext in request attributes - Update ResourceDocMiddleware to enrich CallContext with validated entities instead of storing them separately - Remove ValidatedContext case class as validated entities are now part of CallContext - Streamline request attribute management by centralizing all validated data in a single CallContext object - Improves code maintainability and reduces complexity in the validation chain
This commit is contained in:
parent
baecbc110f
commit
e8999ba54c
@ -55,7 +55,12 @@ case class CallContext(
|
||||
xRateLimitRemaining : Long = -1,
|
||||
xRateLimitReset : Long = -1,
|
||||
paginationOffset : Option[String] = None,
|
||||
paginationLimit : Option[String] = None
|
||||
paginationLimit : Option[String] = None,
|
||||
// Validated entities from ResourceDoc middleware (http4s)
|
||||
bank: Option[Bank] = None,
|
||||
bankAccount: Option[BankAccount] = None,
|
||||
view: Option[View] = None,
|
||||
counterparty: Option[CounterpartyTrait] = None
|
||||
) extends MdcLoggable {
|
||||
override def toString: String = SecureLogging.maskSensitive(
|
||||
s"${this.getClass.getSimpleName}(${this.productIterator.mkString(", ")})"
|
||||
|
||||
@ -24,63 +24,28 @@ import scala.language.higherKinds
|
||||
*
|
||||
* This file contains:
|
||||
* - Http4sCallContextBuilder: Builds shared CallContext from http4s Request[IO]
|
||||
* - Http4sRequestAttributes: Request attribute keys for storing validated objects
|
||||
* - Http4sRequestAttributes: Request attribute key for storing CallContext
|
||||
* - ResourceDocMatcher: Matches http4s requests to ResourceDoc entries
|
||||
* - ResourceDocMiddleware: Validation chain middleware for http4s
|
||||
* - ErrorResponseConverter: Converts OBP errors to http4s Response[IO]
|
||||
*
|
||||
* Validated entities (User, Bank, BankAccount, View, Counterparty) are stored
|
||||
* directly in CallContext fields, making them available throughout the call chain.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Vault keys for storing validated objects in http4s request attributes.
|
||||
* These keys allow middleware to pass validated objects to endpoint handlers.
|
||||
* WIP
|
||||
*/
|
||||
/**
|
||||
* Request attribute keys for storing validated objects in http4s requests.
|
||||
* These keys allow middleware to pass validated objects to endpoint handlers.
|
||||
* Request attribute keys for storing CallContext in http4s requests.
|
||||
*
|
||||
* Note: Uses http4s Vault (org.typelevel.vault.Key) for type-safe request attributes.
|
||||
*/
|
||||
object Http4sRequestAttributes {
|
||||
// Use shared CallContext from code.api.util.ApiSession
|
||||
// CallContext contains all request data and validated entities
|
||||
val callContextKey: Key[CallContext] =
|
||||
Key.newKey[IO, CallContext].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
|
||||
|
||||
val userKey: Key[User] =
|
||||
Key.newKey[IO, User].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
|
||||
|
||||
val bankKey: Key[Bank] =
|
||||
Key.newKey[IO, Bank].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
|
||||
|
||||
val bankAccountKey: Key[BankAccount] =
|
||||
Key.newKey[IO, BankAccount].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
|
||||
|
||||
val viewKey: Key[View] =
|
||||
Key.newKey[IO, View].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
|
||||
|
||||
val counterpartyKey: Key[CounterpartyTrait] =
|
||||
Key.newKey[IO, CounterpartyTrait].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
|
||||
|
||||
/**
|
||||
* Helper methods for accessing validated objects from request attributes
|
||||
* Get CallContext from request attributes.
|
||||
* CallContext contains validated entities: bank, bankAccount, view, counterparty
|
||||
*/
|
||||
def getCallContext(req: Request[IO]): Option[CallContext] =
|
||||
req.attributes.lookup(callContextKey)
|
||||
|
||||
def getUser(req: Request[IO]): Option[User] =
|
||||
req.attributes.lookup(userKey)
|
||||
|
||||
def getBank(req: Request[IO]): Option[Bank] =
|
||||
req.attributes.lookup(bankKey)
|
||||
|
||||
def getBankAccount(req: Request[IO]): Option[BankAccount] =
|
||||
req.attributes.lookup(bankAccountKey)
|
||||
|
||||
def getView(req: Request[IO]): Option[View] =
|
||||
req.attributes.lookup(viewKey)
|
||||
|
||||
def getCounterparty(req: Request[IO]): Option[CounterpartyTrait] =
|
||||
req.attributes.lookup(counterpartyKey)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,16 +296,3 @@ object ResourceDocMatcher {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validated context containing all validated objects from the middleware chain.
|
||||
* This is passed to endpoint handlers after successful validation.
|
||||
*/
|
||||
case class ValidatedContext(
|
||||
user: Option[User],
|
||||
bank: Option[Bank],
|
||||
bankAccount: Option[BankAccount],
|
||||
view: Option[View],
|
||||
counterparty: Option[CounterpartyTrait],
|
||||
callContext: CallContext
|
||||
)
|
||||
|
||||
@ -243,13 +243,16 @@ object ResourceDocMiddleware extends MdcLoggable{
|
||||
counterpartyResult.flatMap {
|
||||
case Left(errorResponse) => IO.pure(errorResponse)
|
||||
case Right((counterpartyOpt, finalCC)) =>
|
||||
// All validations passed - store validated context and invoke route
|
||||
var updatedReq = req.withAttribute(Http4sRequestAttributes.callContextKey, finalCC)
|
||||
boxUser.toOption.foreach { user => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.userKey, user) }
|
||||
bankOpt.foreach { bank => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.bankKey, bank) }
|
||||
accountOpt.foreach { account => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.bankAccountKey, account) }
|
||||
viewOpt.foreach { view => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.viewKey, view) }
|
||||
counterpartyOpt.foreach { counterparty => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.counterpartyKey, counterparty) }
|
||||
// All validations passed - update CallContext with validated entities
|
||||
val enrichedCC = finalCC.copy(
|
||||
bank = bankOpt,
|
||||
bankAccount = accountOpt,
|
||||
view = viewOpt,
|
||||
counterparty = counterpartyOpt
|
||||
)
|
||||
|
||||
// Store enriched CallContext in request attributes
|
||||
val updatedReq = req.withAttribute(Http4sRequestAttributes.callContextKey, enrichedCC)
|
||||
routes.run(updatedReq).getOrElseF(IO.pure(Response[IO](org.http4s.Status.NotFound)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ object Http4s700 {
|
||||
case req @ GET -> `prefixPath` / "cards" =>
|
||||
val response = for {
|
||||
cc <- IO.fromOption(req.attributes.lookup(Http4sRequestAttributes.callContextKey))(new RuntimeException("CallContext not found in request attributes"))
|
||||
user <- IO.fromOption(req.attributes.lookup(Http4sRequestAttributes.userKey))(new RuntimeException("User not found in request attributes"))
|
||||
user <- IO.fromOption(cc.user.toOption)(new RuntimeException("User not found in CallContext"))
|
||||
result <- IO.fromFuture(IO {
|
||||
for {
|
||||
(cards, callContext) <- NewStyle.function.getPhysicalCardsForUser(user, Some(cc))
|
||||
@ -169,8 +169,8 @@ object Http4s700 {
|
||||
case req @ GET -> `prefixPath` / "banks" / bankId / "cards" =>
|
||||
val response = for {
|
||||
cc <- IO.fromOption(req.attributes.lookup(Http4sRequestAttributes.callContextKey))(new RuntimeException("CallContext not found in request attributes"))
|
||||
user <- IO.fromOption(req.attributes.lookup(Http4sRequestAttributes.userKey))(new RuntimeException("User not found in request attributes"))
|
||||
bank <- IO.fromOption(req.attributes.lookup(Http4sRequestAttributes.bankKey))(new RuntimeException("Bank not found in request attributes"))
|
||||
user <- IO.fromOption(cc.user.toOption)(new RuntimeException("User not found in CallContext"))
|
||||
bank <- IO.fromOption(cc.bank)(new RuntimeException("Bank not found in CallContext"))
|
||||
result <- IO.fromFuture(IO {
|
||||
for {
|
||||
httpParams <- NewStyle.function.extractHttpParamsFromUrl(req.uri.renderString)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user