mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 11:06:49 +00:00
Merge remote-tracking branch 'UPSTREAM/develop' into develop
This commit is contained in:
commit
8c422752e2
@ -248,7 +248,7 @@ recurringIndicator:
|
||||
(Full(user), callContext) <- authenticatedAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
_ <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound)
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound, 403)
|
||||
}
|
||||
_ <- Future(Consents.consentProvider.vend.revokeBerlinGroupConsent(consentId)) map {
|
||||
i => connectorEmptyResponse(i, callContext)
|
||||
@ -752,7 +752,7 @@ This method returns the SCA status of a consent initiation's authorisation sub-r
|
||||
(_, callContext) <- authenticatedAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
_ <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
unboxFullOrFail(_, callContext, s"$ConsentNotFound ($consentId)")
|
||||
unboxFullOrFail(_, callContext, s"$ConsentNotFound ($consentId)", 403)
|
||||
}
|
||||
(challenges, callContext) <- NewStyle.function.getChallengesByConsentId(consentId, callContext)
|
||||
} yield {
|
||||
@ -787,7 +787,7 @@ This method returns the SCA status of a consent initiation's authorisation sub-r
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound)
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound, 403)
|
||||
}
|
||||
} yield {
|
||||
val status = consent.status
|
||||
@ -1134,7 +1134,7 @@ using the extended forms as indicated above.
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound)
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound, 403)
|
||||
}
|
||||
(challenges, callContext) <- NewStyle.function.createChallengesC2(
|
||||
List(u.userId),
|
||||
@ -1297,7 +1297,7 @@ Maybe in a later version the access path will change.
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
_ <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound)
|
||||
unboxFullOrFail(_, callContext, ConsentNotFound, 403)
|
||||
}
|
||||
failMsg = s"$InvalidJsonFormat The Json body should be the $TransactionAuthorisation "
|
||||
updateJson <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
|
||||
@ -62,7 +62,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
case class CoreAccountJsonV13(
|
||||
resourceId: String,
|
||||
iban: String,
|
||||
bban: String,
|
||||
bban: Option[String],
|
||||
currency: String,
|
||||
name: String,
|
||||
product: String,
|
||||
@ -137,6 +137,10 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
iban: String,
|
||||
currency : Option[String] = None,
|
||||
)
|
||||
case class FromAccountJson(
|
||||
iban: String,
|
||||
currency : Option[String] = None,
|
||||
)
|
||||
case class TransactionJsonV13(
|
||||
transactionId: String,
|
||||
creditorName: String,
|
||||
@ -190,7 +194,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
)
|
||||
|
||||
case class TransactionsJsonV13(
|
||||
account:FromAccount,
|
||||
account: FromAccountJson,
|
||||
transactions:TransactionsV13Transactions,
|
||||
)
|
||||
|
||||
@ -259,7 +263,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
recurringIndicator: Boolean,
|
||||
validUntil: String,
|
||||
frequencyPerDay: Int,
|
||||
combinedServiceIndicator: Boolean,
|
||||
combinedServiceIndicator: Option[Boolean],
|
||||
lastActionDate: String,
|
||||
consentStatus: String
|
||||
)
|
||||
@ -332,12 +336,12 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
CoreAccountJsonV13(
|
||||
resourceId = x.accountId.value,
|
||||
iban = iBan,
|
||||
bban = bBan,
|
||||
bban = None,
|
||||
currency = x.currency,
|
||||
name = x.name,
|
||||
cashAccountType = x.accountType,
|
||||
product = x.accountType,
|
||||
balances = accountBalances,
|
||||
balances = if(canReadBalances) accountBalances else None,
|
||||
_links = CoreAccountLinksJsonV13(
|
||||
balances = if(canReadBalances) Some(balanceRef) else None,
|
||||
transactions = if(canReadTransactions) Some(transactionRef) else None,
|
||||
@ -363,7 +367,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
CoreAccountJsonV13(
|
||||
resourceId = x.accountId.value,
|
||||
iban = iBan,
|
||||
bban = bBan,
|
||||
bban = None,
|
||||
currency = x.currency,
|
||||
name = x.name,
|
||||
cashAccountType = x.accountType,
|
||||
@ -440,14 +444,17 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
))
|
||||
}
|
||||
|
||||
def createTransactionJSON(bankAccount: BankAccount, transaction : ModeratedTransaction, creditorAccount: CreditorAccountJson) : TransactionJsonV13 = {
|
||||
val bookingDate = transaction.startDate.getOrElse(null)
|
||||
val valueDate = transaction.finishDate.getOrElse(null)
|
||||
def createTransactionJSON(bankAccount: BankAccount, transaction : ModeratedTransaction) : TransactionJsonV13 = {
|
||||
val bookingDate = transaction.startDate.orNull
|
||||
val valueDate = transaction.finishDate.orNull
|
||||
val creditorName = bankAccount.label
|
||||
TransactionJsonV13(
|
||||
transactionId = transaction.id.value,
|
||||
creditorName = creditorName,
|
||||
creditorAccount = creditorAccount,
|
||||
creditorAccount = CreditorAccountJson(
|
||||
transaction.otherBankAccount.map(_.iban.orNull).orNull,
|
||||
transaction.currency
|
||||
),
|
||||
transactionAmount = AmountOfMoneyV13(APIUtil.stringOptionOrNull(transaction.currency), transaction.amount.get.toString().trim.stripPrefix("-")),
|
||||
bookingDate = BgSpecValidation.formatToISODate(bookingDate) ,
|
||||
valueDate = BgSpecValidation.formatToISODate(valueDate),
|
||||
@ -476,16 +483,19 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
}
|
||||
|
||||
|
||||
def createTransactionFromRequestJSON(bankAccount: BankAccount, transactionRequest : TransactionRequest, creditorAccount: CreditorAccountJson) : TransactionJsonV13 = {
|
||||
def createTransactionFromRequestJSON(bankAccount: BankAccount, tr : TransactionRequest) : TransactionJsonV13 = {
|
||||
val creditorName = bankAccount.accountHolder
|
||||
val remittanceInformationUnstructured = stringOrNull(transactionRequest.body.description)
|
||||
val remittanceInformationUnstructured = stringOrNull(tr.body.description)
|
||||
TransactionJsonV13(
|
||||
transactionId = transactionRequest.id.value,
|
||||
transactionId = tr.id.value,
|
||||
creditorName = creditorName,
|
||||
creditorAccount = creditorAccount,
|
||||
transactionAmount = AmountOfMoneyV13(transactionRequest.charge.value.currency, transactionRequest.charge.value.amount.trim.stripPrefix("-")),
|
||||
bookingDate = BgSpecValidation.formatToISODate(transactionRequest.start_date),
|
||||
valueDate = BgSpecValidation.formatToISODate(transactionRequest.end_date),
|
||||
creditorAccount = CreditorAccountJson(
|
||||
if (tr.other_account_routing_scheme == "IBAN") tr.other_account_routing_address else "",
|
||||
Some(tr.body.value.currency)
|
||||
),
|
||||
transactionAmount = AmountOfMoneyV13(tr.charge.value.currency, tr.charge.value.amount.trim.stripPrefix("-")),
|
||||
bookingDate = BgSpecValidation.formatToISODate(tr.start_date),
|
||||
valueDate = BgSpecValidation.formatToISODate(tr.end_date),
|
||||
remittanceInformationUnstructured = remittanceInformationUnstructured
|
||||
)
|
||||
}
|
||||
@ -494,17 +504,15 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
val accountId = bankAccount.accountId.value
|
||||
val (iban: String, bban: String) = getIbanAndBban(bankAccount)
|
||||
|
||||
val creditorAccount = CreditorAccountJson(
|
||||
val account = FromAccountJson(
|
||||
iban = iban,
|
||||
currency = Some(bankAccount.currency)
|
||||
)
|
||||
TransactionsJsonV13(
|
||||
FromAccount(
|
||||
iban = iban,
|
||||
),
|
||||
account,
|
||||
TransactionsV13Transactions(
|
||||
booked= transactions.map(transaction => createTransactionJSON(bankAccount, transaction, creditorAccount)),
|
||||
pending = transactionRequests.filter(_.status!="COMPLETED").map(transactionRequest => createTransactionFromRequestJSON(bankAccount, transactionRequest, creditorAccount)),
|
||||
booked= transactions.map(transaction => createTransactionJSON(bankAccount, transaction)),
|
||||
pending = transactionRequests.filter(_.status!="COMPLETED").map(transactionRequest => createTransactionFromRequestJSON(bankAccount, transactionRequest)),
|
||||
_links = TransactionsV13TransactionsLinks(LinkHrefJson(s"/v1.3/accounts/$accountId"))
|
||||
)
|
||||
)
|
||||
@ -626,7 +634,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
|
||||
recurringIndicator = createdConsent.recurringIndicator,
|
||||
validUntil = if(createdConsent.validUntil == null) null else new SimpleDateFormat(DateWithDay).format(createdConsent.validUntil),
|
||||
frequencyPerDay = createdConsent.frequencyPerDay,
|
||||
combinedServiceIndicator= createdConsent.combinedServiceIndicator,
|
||||
combinedServiceIndicator = None,
|
||||
lastActionDate = if(createdConsent.lastActionDate == null) null else new SimpleDateFormat(DateWithDay).format(createdConsent.lastActionDate),
|
||||
consentStatus = createdConsent.status.toLowerCase()
|
||||
)
|
||||
|
||||
@ -260,7 +260,7 @@ This method returns the SCA status of a signing basket's authorisation sub-resou
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
_ <- passesPsd2Pisp(callContext)
|
||||
_ <- Future(SigningBasketX.signingBasketProvider.vend.getSigningBasketByBasketId(basketId)) map {
|
||||
unboxFullOrFail(_, callContext, s"$ConsentNotFound ($basketId)")
|
||||
unboxFullOrFail(_, callContext, s"$ConsentNotFound ($basketId)", 403)
|
||||
}
|
||||
(challenges, callContext) <- NewStyle.function.getChallengesByBasketId(basketId, callContext)
|
||||
} yield {
|
||||
|
||||
@ -149,6 +149,8 @@ object RequestHeader {
|
||||
final lazy val `PSD2-CERT` = "PSD2-CERT"
|
||||
final lazy val `If-None-Match` = "If-None-Match"
|
||||
|
||||
final lazy val `PSU-Device-ID` = "PSU-Device-ID" // Berlin Group
|
||||
final lazy val `PSU-IP-Address` = "PSU-IP-Address" // Berlin Group
|
||||
final lazy val `X-Request-ID` = "X-Request-ID" // Berlin Group
|
||||
final lazy val `TPP-Redirect-URI` = "TPP-Redirect-URI" // Berlin Group
|
||||
final lazy val `TPP-Nok-Redirect-URI` = "TPP-Nok-Redirect-URI" // Redirect URI in case of an error.
|
||||
|
||||
@ -3001,12 +3001,12 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
val res =
|
||||
if (authHeadersWithEmptyValues.nonEmpty) { // Check Authorization Headers Empty Values
|
||||
val message = ErrorMessages.EmptyRequestHeaders + s"Header names: ${authHeadersWithEmptyValues.mkString(", ")}"
|
||||
Future { (fullBoxOrException(Empty ~> APIFailureNewStyle(message, 400, Some(cc.toLight))), None) }
|
||||
Future { (fullBoxOrException(Empty ~> APIFailureNewStyle(message, 400, Some(cc.toLight))), Some(cc)) }
|
||||
} else if (authHeadersWithEmptyNames.nonEmpty) { // Check Authorization Headers Empty Names
|
||||
val message = ErrorMessages.EmptyRequestHeaders + s"Header values: ${authHeadersWithEmptyNames.mkString(", ")}"
|
||||
Future { (fullBoxOrException(Empty ~> APIFailureNewStyle(message, 400, Some(cc.toLight))), None) }
|
||||
Future { (fullBoxOrException(Empty ~> APIFailureNewStyle(message, 400, Some(cc.toLight))), Some(cc)) }
|
||||
} else if (authHeaders.size > 1) { // Check Authorization Headers ambiguity
|
||||
Future { (Failure(ErrorMessages.AuthorizationHeaderAmbiguity + s"${authHeaders}"), None) }
|
||||
Future { (Failure(ErrorMessages.AuthorizationHeaderAmbiguity + s"${authHeaders}"), Some(cc)) }
|
||||
} else if (APIUtil.`hasConsent-ID`(reqHeaders)) { // Berlin Group's Consent
|
||||
Consent.applyBerlinGroupRules(APIUtil.`getConsent-ID`(reqHeaders), cc.copy(consumer = consumerByCertificate))
|
||||
} else if (APIUtil.hasConsentJWT(reqHeaders)) { // Open Bank Project's Consent
|
||||
|
||||
@ -69,8 +69,6 @@ object BerlinGroupError {
|
||||
case "401" if message.contains("OBP-35018") => "CONSENT_INVALID"
|
||||
case "401" if message.contains("OBP-35005") => "CONSENT_INVALID"
|
||||
|
||||
case "403" if message.contains("OBP-35001") => "CONSENT_UNKNOWN"
|
||||
|
||||
case "401" if message.contains("OBP-20300") => "CERTIFICATE_BLOCKED"
|
||||
case "401" if message.contains("OBP-20312") => "CERTIFICATE_INVALID"
|
||||
case "401" if message.contains("OBP-20300") => "CERTIFICATE_INVALID"
|
||||
@ -80,6 +78,7 @@ object BerlinGroupError {
|
||||
|
||||
case "400" if message.contains("OBP-35018") => "CONSENT_UNKNOWN"
|
||||
case "400" if message.contains("OBP-35001") => "CONSENT_UNKNOWN"
|
||||
case "403" if message.contains("OBP-35001") => "CONSENT_UNKNOWN"
|
||||
|
||||
case "404" if message.contains("OBP-30076") => "RESOURCE_UNKNOWN"
|
||||
|
||||
|
||||
@ -160,14 +160,15 @@ object BerlinGroupSigning extends MdcLoggable {
|
||||
val certificate = getCertificateFromTppSignatureCertificate(requestHeaders)
|
||||
X509.validateCertificate(certificate) match {
|
||||
case Full(true) => // PEM certificate is ok
|
||||
val digest = generateDigest(body.getOrElse(""))
|
||||
if(digest == getHeaderValue(RequestHeader.Digest, requestHeaders)) { // Verifying the Hash in the Digest Field
|
||||
val generatedDigest = generateDigest(body.getOrElse(""))
|
||||
val requestHeaderDigest = getHeaderValue(RequestHeader.Digest, requestHeaders)
|
||||
if(generatedDigest == requestHeaderDigest) { // Verifying the Hash in the Digest Field
|
||||
val signatureHeaderValue = getHeaderValue(RequestHeader.Signature, requestHeaders)
|
||||
val signature = parseSignatureHeader(signatureHeaderValue).getOrElse("signature", "NONE")
|
||||
val headersToSign = parseSignatureHeader(signatureHeaderValue).getOrElse("headers", "").split(" ").toList
|
||||
val headers = headersToSign.map(h =>
|
||||
if (h.toLowerCase() == RequestHeader.Digest.toLowerCase()) {
|
||||
s"$h: $digest"
|
||||
s"$h: $generatedDigest"
|
||||
} else {
|
||||
s"$h: ${getHeaderValue(h, requestHeaders)}"
|
||||
}
|
||||
@ -183,6 +184,8 @@ object BerlinGroupSigning extends MdcLoggable {
|
||||
case (false, _) => (Failure(ErrorMessages.X509PublicKeyCannotVerify), forwardResult._2)
|
||||
}
|
||||
} else { // The two DIGEST hashes do NOT match, the integrity of the request body is NOT confirmed.
|
||||
logger.debug(s"Generated digest: $generatedDigest")
|
||||
logger.debug(s"Request header digest: $requestHeaderDigest")
|
||||
(Failure(ErrorMessages.X509PublicKeyCannotVerify), forwardResult._2)
|
||||
}
|
||||
case Failure(msg, t, c) => (Failure(msg, t, c), forwardResult._2) // PEM certificate is not valid
|
||||
|
||||
@ -3,19 +3,22 @@ package code.api.util
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.{Date, UUID}
|
||||
import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{ConsentAccessJson, PostConsentJson}
|
||||
import code.api.util.APIUtil.fullBoxOrException
|
||||
import code.api.util.ApiRole.{canCreateEntitlementAtAnyBank, canCreateEntitlementAtOneBank}
|
||||
import code.api.util.BerlinGroupSigning.getHeaderValue
|
||||
import code.api.util.ErrorMessages.{CouldNotAssignAccountAccess, InvalidConnectorResponse, NoViewReadAccountsBerlinGroup}
|
||||
import code.api.v3_1_0.{PostConsentBodyCommonJson, PostConsentEntitlementJsonV310, PostConsentViewJsonV310}
|
||||
import code.api.v5_0_0.HelperInfoJson
|
||||
import code.api.{APIFailure, Constant, RequestHeader}
|
||||
import code.api.{APIFailure, APIFailureNewStyle, Constant, RequestHeader}
|
||||
import code.bankconnectors.Connector
|
||||
import code.consent
|
||||
import code.consent.ConsentStatus.ConsentStatus
|
||||
import code.consent.{ConsentStatus, Consents, MappedConsent}
|
||||
import code.consumer.Consumers
|
||||
import code.context.{ConsentAuthContextProvider, UserAuthContextProvider}
|
||||
import code.entitlement.Entitlement
|
||||
import code.model.Consumer
|
||||
import code.scheduler.ConsentScheduler.logger
|
||||
import code.users.Users
|
||||
import code.util.Helper.MdcLoggable
|
||||
import code.util.HydraUtil
|
||||
@ -600,7 +603,8 @@ object Consent extends MdcLoggable {
|
||||
case failure@Failure(_, _, _) =>
|
||||
Future(failure, Some(callContext))
|
||||
case _ =>
|
||||
Future(Failure(ErrorMessages.ConsentNotFound + s" ($consentId)"), Some(callContext))
|
||||
val errorMessage = ErrorMessages.ConsentNotFound + s" ($consentId)"
|
||||
Future(fullBoxOrException(Empty ~> APIFailureNewStyle(errorMessage, 400, Some(callContext.toLight))), Some(callContext))
|
||||
}
|
||||
}
|
||||
def applyBerlinGroupRules(consentId: Option[String], callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
@ -772,6 +776,9 @@ object Consent extends MdcLoggable {
|
||||
}
|
||||
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`)
|
||||
Future.sequence(accounts ::: balances ::: transactions) map { views =>
|
||||
val json = ConsentJWT(
|
||||
createdByUserId = user.map(_.userId).getOrElse(""),
|
||||
@ -782,7 +789,11 @@ object Consent extends MdcLoggable {
|
||||
iat = currentTimeInSeconds,
|
||||
nbf = currentTimeInSeconds,
|
||||
exp = validUntilTimeInSeconds,
|
||||
request_headers = tppRedirectUri.toList ::: tppNokRedirectUri.toList,
|
||||
request_headers = tppRedirectUri.toList :::
|
||||
tppNokRedirectUri.toList :::
|
||||
xRequestId.toList :::
|
||||
psuDeviceId.toList :::
|
||||
psuIpAddress.toList,
|
||||
name = None,
|
||||
email = None,
|
||||
entitlements = Nil,
|
||||
@ -855,19 +866,18 @@ object Consent extends MdcLoggable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def updateUserIdOfBerlinGroupConsentJWT(createdByUserId: String,
|
||||
consent: MappedConsent,
|
||||
callContext: Option[CallContext]): Future[Box[String]] = {
|
||||
callContext: Option[CallContext]): Box[String] = {
|
||||
implicit val dateFormats = CustomJsonFormats.formats
|
||||
val payloadToUpdate: Box[ConsentJWT] = JwtUtil.getSignedPayloadAsJson(consent.jsonWebToken) // Payload as JSON string
|
||||
.map(net.liftweb.json.parse(_).extract[ConsentJWT]) // Extract case class
|
||||
|
||||
Future {
|
||||
val updatedPayload = payloadToUpdate.map(i => i.copy(createdByUserId = createdByUserId)) // Update only the field "createdByUserId"
|
||||
val jwtPayloadAsJson = compactRender(Extraction.decompose(updatedPayload))
|
||||
val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson)
|
||||
Full(CertificateUtil.jwtWithHmacProtection(jwtClaims, consent.secret))
|
||||
}
|
||||
val updatedPayload = payloadToUpdate.map(i => i.copy(createdByUserId = createdByUserId)) // Update only the field "createdByUserId"
|
||||
val jwtPayloadAsJson = compactRender(Extraction.decompose(updatedPayload))
|
||||
val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson)
|
||||
Full(CertificateUtil.jwtWithHmacProtection(jwtClaims, consent.secret))
|
||||
}
|
||||
|
||||
def createUKConsentJWT(
|
||||
@ -1036,6 +1046,26 @@ object Consent extends MdcLoggable {
|
||||
consentsOfBank
|
||||
}
|
||||
|
||||
def expireAllPreviousValidBerlinGroupConsents(consent: MappedConsent, updateTostatus: ConsentStatus): Boolean = {
|
||||
if(updateTostatus == ConsentStatus.valid &&
|
||||
consent.apiStandard == ApiVersion.berlinGroupV13.apiStandard) {
|
||||
MappedConsent.findAll( // Find all
|
||||
By(MappedConsent.mApiStandard, ApiVersion.berlinGroupV13.apiStandard), // Berlin Group
|
||||
By(MappedConsent.mRecurringIndicator, true), // recurring
|
||||
By(MappedConsent.mStatus, ConsentStatus.valid.toString), // and valid consents
|
||||
By(MappedConsent.mUserId, consent.userId), // for the same PSU
|
||||
By(MappedConsent.mConsumerId, consent.consumerId), // from the same TPP
|
||||
).filterNot(_.consentId == consent.consentId) // Exclude current consent
|
||||
.map{ c => // Set to expired
|
||||
val changedStatus = c.mStatus(ConsentStatus.expired.toString).mLastActionDate(new Date()).save
|
||||
if(changedStatus) logger.warn(s"|---> Changed status to ${ConsentStatus.expired.toString} for consent ID: ${c.id}")
|
||||
changedStatus
|
||||
}.forall(_ == true)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Example Usage
|
||||
val box1: Box[String] = Full("Hello, World!")
|
||||
|
||||
@ -2,6 +2,7 @@ package code.api.util
|
||||
|
||||
import java.math.BigInteger
|
||||
import net.liftweb.common.Box
|
||||
import org.iban4j.IbanUtil
|
||||
|
||||
object HashUtil {
|
||||
def Sha256Hash(in: String): String = {
|
||||
@ -25,5 +26,8 @@ object HashUtil {
|
||||
val hashedText = Sha256Hash(plainText)
|
||||
println("Password: " + plainText)
|
||||
println("Hashed password: " + hashedText)
|
||||
println("BBAN: " + IbanUtil.getBban("AT483200000012345864"))
|
||||
println("Bank code: " + IbanUtil.getBankCode("AT483200000012345864"))
|
||||
println("Country code: " + IbanUtil.getCountryCode("AT483200000012345864"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1493,11 +1493,11 @@ trait APIMethods510 {
|
||||
consent <- Future(Consents.consentProvider.vend.updateConsentUser(consentId, user)) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
consentJWT <- Consent.updateUserIdOfBerlinGroupConsentJWT(
|
||||
consentJWT <- Future(Consent.updateUserIdOfBerlinGroupConsentJWT(
|
||||
consentJson.user_id,
|
||||
consent,
|
||||
cc.callContext
|
||||
) map {
|
||||
)) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
updatedConsent <- Future(Consents.consentProvider.vend.setJsonWebToken(consent.consentId, consentJWT)) map {
|
||||
|
||||
@ -30,6 +30,7 @@ object MappedConsentProvider extends ConsentProvider {
|
||||
override def updateConsentStatus(consentId: String, status: ConsentStatus): Box[MappedConsent] = {
|
||||
MappedConsent.find(By(MappedConsent.mConsentId, consentId)) match {
|
||||
case Full(consent) =>
|
||||
Consent.expireAllPreviousValidBerlinGroupConsents(consent, status)
|
||||
tryo(consent
|
||||
.mStatus(status.toString)
|
||||
.mLastActionDate(now) //maybe not right, but for the create we use the `now`, we need to update it later.
|
||||
|
||||
@ -110,7 +110,7 @@ class BerlinGroupConsent extends MdcLoggable with RestHelper with APIMethods510
|
||||
for {
|
||||
// Fetch the consent by ID
|
||||
consent: MappedConsent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
APIUtil.unboxFullOrFail(_, None, s"$ConsentNotFound ($consentId)", 404)
|
||||
APIUtil.unboxFullOrFail(_, None, s"$ConsentNotFound ($consentId)", 400)
|
||||
}
|
||||
// Update the consent JWT with new access details
|
||||
consentJWT <- Consent.updateAccountAccessOfBerlinGroupConsentJWT(
|
||||
@ -385,10 +385,17 @@ class BerlinGroupConsent extends MdcLoggable with RestHelper with APIMethods510
|
||||
*/
|
||||
private def denyConsentRequestProcess() = {
|
||||
val consentId = ObpS.param("CONSENT_ID") openOr ("")
|
||||
Consents.consentProvider.vend.updateConsentStatus(consentId, ConsentStatus.rejected)
|
||||
S.redirectTo(
|
||||
s"$redirectUriValue?CONSENT_ID=${consentId}"
|
||||
)
|
||||
Consents.consentProvider.vend.getConsentByConsentId(consentId) match {
|
||||
case Full(consent) if otpValue.is == consent.challenge =>
|
||||
updateConsentUser(consent)
|
||||
Consents.consentProvider.vend.updateConsentStatus(consentId, ConsentStatus.rejected)
|
||||
S.redirectTo(
|
||||
s"$redirectUriValue?CONSENT_ID=${consentId}"
|
||||
)
|
||||
case _ =>
|
||||
S.error("Cannot bet consent")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -398,6 +405,7 @@ class BerlinGroupConsent extends MdcLoggable with RestHelper with APIMethods510
|
||||
val consentId = ObpS.param("CONSENT_ID") openOr ("")
|
||||
Consents.consentProvider.vend.getConsentByConsentId(consentId) match {
|
||||
case Full(consent) if otpValue.is == consent.challenge =>
|
||||
updateConsentUser(consent)
|
||||
Consents.consentProvider.vend.updateConsentStatus(consentId, ConsentStatus.valid)
|
||||
S.redirectTo(
|
||||
s"/confirm-bg-consent-request-redirect-uri?CONSENT_ID=${consentId}"
|
||||
@ -407,6 +415,13 @@ class BerlinGroupConsent extends MdcLoggable with RestHelper with APIMethods510
|
||||
}
|
||||
}
|
||||
|
||||
private def updateConsentUser(consent: MappedConsent): Box[MappedConsent] = {
|
||||
val loggedInUser = AuthUser.currentUser.flatMap(_.user.foreign).openOrThrowException(ErrorMessages.UserNotLoggedIn)
|
||||
Consents.consentProvider.vend.updateConsentUser(consent.consentId, loggedInUser)
|
||||
val jwt = Consent.updateUserIdOfBerlinGroupConsentJWT(loggedInUser.userId, consent, None).openOrThrowException(ErrorMessages.InvalidConnectorResponse)
|
||||
Consents.consentProvider.vend.setJsonWebToken(consent.consentId, jwt)
|
||||
}
|
||||
|
||||
private def getTppRedirectUri() = {
|
||||
val consentId = ObpS.param("CONSENT_ID") openOr ("")
|
||||
s"$redirectUriValue?CONSENT_ID=${consentId}"
|
||||
|
||||
@ -484,7 +484,7 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit
|
||||
scenario("Authentication User, only mocked data, just test succeed", BerlinGroupV1_3, updateConsentsPsuDataTransactionAuthorisation) {
|
||||
val requestStartConsentAuthorisation = (V1_3_BG / "consents"/"consentId" /"authorisations"/ "AUTHORISATIONID" ).PUT <@ (user1)
|
||||
val responseStartConsentAuthorisation = makePutRequest(requestStartConsentAuthorisation, """{"scaAuthenticationData":""}""")
|
||||
responseStartConsentAuthorisation.code should be (400)
|
||||
responseStartConsentAuthorisation.code should be (403)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user