mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 18:46:46 +00:00
feature/Improve error message at function createBerlinGroupConsentJWT
This commit is contained in:
parent
927ba2c3af
commit
5240d47ec7
@ -80,6 +80,7 @@ object BerlinGroupError {
|
||||
case "400" if message.contains("OBP-35001") => "CONSENT_UNKNOWN"
|
||||
case "403" if message.contains("OBP-35001") => "CONSENT_UNKNOWN"
|
||||
|
||||
case "400" if message.contains("OBP-50200") => "RESOURCE_UNKNOWN"
|
||||
case "404" if message.contains("OBP-30076") => "RESOURCE_UNKNOWN"
|
||||
case "404" if message.contains("OBP-40001") => "RESOURCE_UNKNOWN"
|
||||
|
||||
|
||||
@ -739,89 +739,95 @@ object Consent extends MdcLoggable {
|
||||
callContext: Option[CallContext]): Future[Box[String]] = {
|
||||
|
||||
val currentTimeInSeconds = System.currentTimeMillis / 1000
|
||||
val validUntilTimeInSeconds = validUntil match {
|
||||
case Some(date) => date.getTime() / 1000
|
||||
case _ => currentTimeInSeconds
|
||||
}
|
||||
// Write Consent's Auth Context to the DB
|
||||
user map { u =>
|
||||
val validUntilTimeInSeconds = validUntil.map(_.getTime / 1000).getOrElse(currentTimeInSeconds)
|
||||
|
||||
// Write Consent's Auth Context to DB
|
||||
user.foreach { u =>
|
||||
val authContexts = UserAuthContextProvider.userAuthContextProvider.vend.getUserAuthContextsBox(u.userId)
|
||||
.map(_.map(i => BasicUserAuthContext(i.key, i.value)))
|
||||
ConsentAuthContextProvider.consentAuthContextProvider.vend.createOrUpdateConsentAuthContexts(consentId, authContexts.getOrElse(Nil))
|
||||
}
|
||||
|
||||
// 1. Add access
|
||||
|
||||
// Helper to get ConsentView or fail box
|
||||
def getConsentView(ibanOpt: Option[String], viewId: String): Future[Box[ConsentView]] = {
|
||||
val iban = ibanOpt.getOrElse("")
|
||||
Connector.connector.vend.getBankAccountByIban(iban, callContext).map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: $iban ${handleBox(bankAccount._1)}"
|
||||
bankAccount._1 match {
|
||||
case Full(acc) =>
|
||||
Full(ConsentView(
|
||||
bank_id = acc.bankId.value,
|
||||
account_id = acc.accountId.value,
|
||||
view_id = viewId,
|
||||
None
|
||||
))
|
||||
case _ =>
|
||||
ErrorUtil.apiFailureToBox(error, 400)(callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare lists of future boxes
|
||||
val allAccesses = consent.access.accounts.getOrElse(Nil) :::
|
||||
consent.access.balances.getOrElse(Nil) ::: // Balances access implies and Account access as well
|
||||
consent.access.transactions.getOrElse(Nil) // Transactions access implies and Account access as well
|
||||
val accounts: List[Future[ConsentView]] = allAccesses.distinct map { account =>
|
||||
Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.accounts.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: ${account.iban.getOrElse("")} ${handleBox(bankAccount._1)}"
|
||||
ConsentView(
|
||||
bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).openOrThrowException(error),
|
||||
view_id = Constant.SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID,
|
||||
None
|
||||
)
|
||||
consent.access.balances.getOrElse(Nil) :::
|
||||
consent.access.transactions.getOrElse(Nil)
|
||||
|
||||
val accounts: List[Future[Box[ConsentView]]] = allAccesses.distinct.map { account =>
|
||||
getConsentView(account.iban, Constant.SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID)
|
||||
}
|
||||
|
||||
val balances: List[Future[Box[ConsentView]]] = consent.access.balances.getOrElse(Nil).map { account =>
|
||||
getConsentView(account.iban, Constant.SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID)
|
||||
}
|
||||
val transactions: List[Future[Box[ConsentView]]] = consent.access.transactions.getOrElse(Nil).map { account =>
|
||||
getConsentView(account.iban, Constant.SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID)
|
||||
}
|
||||
|
||||
// Collect optional headers
|
||||
val headers = callContext.map(_.requestHeaders).getOrElse(Nil)
|
||||
val tppRedirectUri = headers.find(_.name == RequestHeader.`TPP-Redirect-URI`)
|
||||
val tppNokRedirectUri = headers.find(_.name == RequestHeader.`TPP-Nok-Redirect-URI`)
|
||||
val xRequestId = headers.find(_.name == RequestHeader.`X-Request-ID`)
|
||||
val psuDeviceId = headers.find(_.name == RequestHeader.`PSU-Device-ID`)
|
||||
val psuIpAddress = headers.find(_.name == RequestHeader.`PSU-IP-Address`)
|
||||
val psuGeoLocation = headers.find(_.name == RequestHeader.`PSU-Geo-Location`)
|
||||
|
||||
def sequenceBoxes[A](boxes: List[Box[A]]): Box[List[A]] = {
|
||||
boxes.foldRight(Full(Nil): Box[List[A]]) { (box, acc) =>
|
||||
for {
|
||||
x <- box
|
||||
xs <- acc
|
||||
} yield x :: xs
|
||||
}
|
||||
}
|
||||
val balances: List[Future[ConsentView]] = consent.access.balances.getOrElse(Nil) map { account =>
|
||||
Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.balances.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: ${account.iban.getOrElse("")} ${handleBox(bankAccount._1)}"
|
||||
ConsentView(
|
||||
bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).openOrThrowException(error),
|
||||
view_id = Constant.SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID,
|
||||
None
|
||||
)
|
||||
}
|
||||
}
|
||||
val transactions: List[Future[ConsentView]] = consent.access.transactions.getOrElse(Nil) map { account =>
|
||||
Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.transactions.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: ${account.iban.getOrElse("")} ${handleBox(bankAccount._1)}"
|
||||
ConsentView(
|
||||
bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).openOrThrowException(error),
|
||||
view_id = Constant.SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID,
|
||||
None
|
||||
)
|
||||
}
|
||||
}
|
||||
val tppRedirectUri: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`TPP-Redirect-URI`)
|
||||
val tppNokRedirectUri: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`TPP-Nok-Redirect-URI`)
|
||||
val xRequestId: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`X-Request-ID`)
|
||||
val psuDeviceId: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`PSU-Device-ID`)
|
||||
val psuIpAddress: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`PSU-IP-Address`)
|
||||
val psuGeoLocation: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`PSU-Geo-Location`)
|
||||
Future.sequence(accounts ::: balances ::: transactions) map { views =>
|
||||
|
||||
// Combine and build final JWT
|
||||
Future.sequence(accounts ::: balances ::: transactions).map { listOfBoxes =>
|
||||
sequenceBoxes(listOfBoxes).map { views =>
|
||||
val json = ConsentJWT(
|
||||
createdByUserId = user.map(_.userId).getOrElse(""),
|
||||
sub = APIUtil.generateUUID(),
|
||||
iss = Constant.HostName,
|
||||
aud = consumerId.getOrElse(""),
|
||||
jti = consentId,
|
||||
iat = currentTimeInSeconds,
|
||||
nbf = currentTimeInSeconds,
|
||||
exp = validUntilTimeInSeconds,
|
||||
request_headers = tppRedirectUri.toList :::
|
||||
tppNokRedirectUri.toList :::
|
||||
xRequestId.toList :::
|
||||
psuDeviceId.toList :::
|
||||
psuIpAddress.toList :::
|
||||
psuGeoLocation.toList,
|
||||
name = None,
|
||||
email = None,
|
||||
entitlements = Nil,
|
||||
views = views,
|
||||
access = Some(consent.access)
|
||||
)
|
||||
implicit val formats = CustomJsonFormats.formats
|
||||
val jwtPayloadAsJson = compactRender(Extraction.decompose(json))
|
||||
val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson)
|
||||
Full(CertificateUtil.jwtWithHmacProtection(jwtClaims, secret))
|
||||
createdByUserId = user.map(_.userId).getOrElse(""),
|
||||
sub = APIUtil.generateUUID(),
|
||||
iss = Constant.HostName,
|
||||
aud = consumerId.getOrElse(""),
|
||||
jti = consentId,
|
||||
iat = currentTimeInSeconds,
|
||||
nbf = currentTimeInSeconds,
|
||||
exp = validUntilTimeInSeconds,
|
||||
request_headers = List(
|
||||
tppRedirectUri, tppNokRedirectUri, xRequestId, psuDeviceId, psuIpAddress, psuGeoLocation
|
||||
).flatten,
|
||||
name = None,
|
||||
email = None,
|
||||
entitlements = Nil,
|
||||
views = views,
|
||||
access = Some(consent.access)
|
||||
)
|
||||
implicit val formats = CustomJsonFormats.formats
|
||||
val jwtPayloadAsJson = compactRender(Extraction.decompose(json))
|
||||
val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson)
|
||||
CertificateUtil.jwtWithHmacProtection(jwtClaims, secret)
|
||||
}
|
||||
}
|
||||
}
|
||||
def updateAccountAccessOfBerlinGroupConsentJWT(access: ConsentAccessJson,
|
||||
|
||||
@ -21,13 +21,13 @@ object ErrorUtil {
|
||||
)
|
||||
}
|
||||
|
||||
def apiFailureToBox(errorMessage: String, httpCode: Int)(cc: Option[CallContext]): Box[Nothing] = {
|
||||
def apiFailureToBox[T](errorMessage: String, httpCode: Int)(cc: Option[CallContext]): Box[T] = {
|
||||
val apiFailure = APIFailureNewStyle(
|
||||
failMsg = errorMessage,
|
||||
failCode = httpCode,
|
||||
ccl = cc.map(_.toLight)
|
||||
)
|
||||
val failureBox = Empty ~> apiFailure
|
||||
val failureBox: Box[T] = Empty ~> apiFailure
|
||||
fullBoxOrException(failureBox)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user