From cf387bd561effe9c8ecb1c89ba5fbcd4b9e87917 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 18 Jul 2024 21:03:21 +0200 Subject: [PATCH 01/30] bugfix/added the missing fields for obp consent creation --- obp-api/src/main/scala/code/consent/MappedConsent.scala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/obp-api/src/main/scala/code/consent/MappedConsent.scala b/obp-api/src/main/scala/code/consent/MappedConsent.scala index 37734773da..56f463ff1c 100644 --- a/obp-api/src/main/scala/code/consent/MappedConsent.scala +++ b/obp-api/src/main/scala/code/consent/MappedConsent.scala @@ -7,6 +7,7 @@ import code.consent.ConsentStatus.ConsentStatus import code.model.Consumer import code.util.MappedUUID import com.openbankproject.commons.model.User +import com.openbankproject.commons.util.ApiStandards import net.liftweb.common.{Box, Empty, Failure, Full} import net.liftweb.mapper.{MappedString, _} import net.liftweb.util.Helpers.{now, tryo} @@ -74,6 +75,12 @@ object MappedConsentProvider extends ConsentProvider { .mChallenge(challengeAnswerHashed) .mSalt(salt) .mStatus(ConsentStatus.INITIATED.toString) + .mRecurringIndicator(true) + .mFrequencyPerDay(100) + .mUsesSoFarTodayCounter(0) + .mUsesSoFarTodayCounterUpdatedAt(new Date()) + .mLastActionDate(now) //maybe not right, but for the create we use the `now`, we need to update it later. + .mApiStandard(ApiStandards.obp.toString) .saveMe() } } From 9ebe0e3c7be5e8695b941b50bb3e647d37bdb0f4 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Mon, 22 Jul 2024 08:53:31 +0200 Subject: [PATCH 02/30] bugfix/added vrp logic to create consent --- .../SwaggerDefinitionsJSON.scala | 4 + .../scala/code/api/v5_0_0/APIMethods500.scala | 162 +++++++++++++++++- .../code/api/v5_0_0/JSONFactory5.0.0.scala | 1 + 3 files changed, 159 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 894194da38..3375379fc8 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -5218,6 +5218,10 @@ object SwaggerDefinitionsJSON { consent_request_id = Some(consentRequestIdExample.value) ) + val createConsentByRequestIdJson = CreateConsentByRequestIdJson( + source_view_id = Some(viewIdExample.copy(value="_VRP-9d429899-24f5-42c8-8565-943ffa6a7945").value) + ) + val postConsentRequestJsonV500 = PostConsentRequestJsonV500( everything = false, bank_id = None, diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index ac57b988a5..16e98b8e49 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -15,7 +15,7 @@ import code.api.v2_1_0.JSONFactory210 import code.api.v3_0_0.JSONFactory300 import code.api.v3_1_0._ import code.api.v4_0_0.JSONFactory400.createCustomersMinimalJson -import code.api.v4_0_0.{JSONFactory400, OBPAPI4_0_0, PutProductJsonV400} +import code.api.v4_0_0.{JSONFactory400, OBPAPI4_0_0, PostCounterpartyJson400, PutProductJsonV400} import code.api.v5_0_0.JSONFactory500.{createPhysicalCardJson, createViewJsonV500, createViewsIdsJsonV500, createViewsJsonV500} import code.bankconnectors.Connector import code.consent.{ConsentRequest, ConsentRequests, Consents} @@ -44,11 +44,13 @@ import java.util.concurrent.ThreadLocalRandom import code.accountattribute.AccountAttributeX import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.api.util.FutureUtil.EndpointContext -import code.api.v5_1_0.PostConsentRequestJsonV510 +import code.api.v5_1_0.{CreateCustomViewJson, PostConsentRequestJsonV510, PostCounterpartyLimitV510} import code.consumer.Consumers +import code.metadata.counterparties.MappedCounterparty import code.util.Helper.booleanToFuture import code.views.system.{AccountAccess, ViewDefinition} +import java.util.UUID import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future @@ -790,7 +792,7 @@ trait APIMethods500 { |Please note that the Consent cannot elevate the privileges logged in user already have. | |""", - EmptyBody, + createConsentByRequestIdJson, consentJsonV500, List( UserNotLoggedIn, @@ -818,7 +820,7 @@ trait APIMethods500 { |Please note that the Consent cannot elevate the privileges logged in user already have. | |""", - EmptyBody, + createConsentByRequestIdJson, consentJsonV500, List( UserNotLoggedIn, @@ -849,7 +851,7 @@ trait APIMethods500 { |Please note that the Consent cannot elevate the privileges logged in user already have. | |""", - EmptyBody, + createConsentByRequestIdJson, consentJsonV500, List( UserNotLoggedIn, @@ -874,7 +876,7 @@ trait APIMethods500 { lazy val createConsentByConsentRequestId : OBPEndpoint = { - case "consumer" :: "consent-requests":: consentRequestId :: scaMethod :: "consents" :: Nil JsonPost _ -> _ => { + case "consumer" :: "consent-requests":: consentRequestId :: scaMethod :: "consents" :: Nil JsonPost jsonBody -> _ => { def sendEmailNotification(callContext: Option[CallContext], consentRequestJson: PostConsentRequestJsonV500, challengeText: String) = { for { failMsg <- Future { @@ -929,16 +931,160 @@ trait APIMethods500 { } consentRequestJson <- if(createdConsentRequest.payload.contains("to_account")) { - val failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentBodyCommonJson " + val failMsg = s"$InvalidJsonFormat The vrp consent request json body should be the $PostConsentRequestJsonV510 " NewStyle.function.tryons(failMsg, 400, callContext) { json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostConsentRequestJsonV510] }.map(_.toPostConsentRequestJsonV500) } else{ - val failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentBodyCommonJson " + val failMsg = s"$InvalidJsonFormat The consent request Json body should be the $PostConsentRequestJsonV500 " NewStyle.function.tryons(failMsg, 400, callContext) { json.parse(createdConsentRequest.payload).extract[PostConsentRequestJsonV500] } } + + _ <- if (createdConsentRequest.payload.contains("to_account")) { + val postConsentRequestJsonV510 = json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostConsentRequestJsonV510] + val fromBankIdAccountId = BankIdAccountId(BankId(postConsentRequestJsonV510.from_account.bank_routing.address), AccountId(postConsentRequestJsonV510.from_account.account_routing.address)) + + val vrpViewId = "_VRP-" + UUID.randomUUID.toString + val targetPermissions = List(//may need getTransactionRequest .. so far only this payments. + "can_add_transaction_request_to_own_account", + "can_add_transaction_request_to_any_account", + "can_add_transaction_request_to_beneficiary" + ) //TODO,here need to be checked later. + + val targetCreateCustomViewJson = CreateCustomViewJson( + name = vrpViewId, + description = vrpViewId, + metadata_view = vrpViewId, + is_public = false, + which_alias_to_use = vrpViewId, + hide_metadata_if_alias_used = true, + allowed_permissions = targetPermissions + + val failMsg = s"$InvalidJsonFormat The vrp consent request json body should be the $PostConsentRequestJsonV510 " + + for { + requestJsonViewIdOption <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.parse(createdConsentRequest.payload) + .extractOpt[CreateConsentByRequestIdJson] + .map(_.source_view_id) + .flatten + .filterNot(_.isEmpty) // if view_id = "",then return NONE. + } + //the json body view_id is an option field, if it is NONE, we need to find all the permissions the user have, + sourceViewId = requestJsonViewIdOption.getOrElse(APIUtil.getPropsValue("defaultBank.view_id", "owner"))//get all the views the user has, + //1st: create the Custom View for the from account. + (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(fromBankIdAccountId.bankId, fromBankIdAccountId.accountId, callContext) + view <- NewStyle.function.checkViewAccessAndReturnView(ViewId(sourceViewId), fromBankIdAccountId, Some(user), callContext) + + permissionsFromSource = APIUtil.getViewPermissions(view.asInstanceOf[ViewDefinition]) + permissionsFromTarget = targetCreateCustomViewJson.allowed_permissions + + _ <- Helper.booleanToFuture(failMsg = SourceViewHasLessPermission + s"Current source view permissions ($permissionsFromSource), target view permissions ($permissionsFromTarget)", cc = callContext) { + permissionsFromTarget.toSet.subsetOf(permissionsFromSource) + } + failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(nameOf(view.canUpdateCustomView))}` permission on VIEW_ID(${sourceViewId})" + _ <- Helper.booleanToFuture(failMsg, cc = callContext) { + view.canCreateCustomView + } + (view, callContext) <- NewStyle.function.createCustomView(fromBankIdAccountId, targetCreateCustomViewJson.toCreateViewJson, callContext) + + //2st: Create a new counterparty on that view (_VRP-9d429899-24f5-42c8-8565-943ffa6a7945) + postJson = PostCounterpartyJson400( + name = "", //TODO, this need to be a unique. + description = "", + currency = postConsentRequestJsonV510.to_account.limit.currency, + other_account_routing_scheme = postConsentRequestJsonV510.to_account.account_routing.scheme, + other_account_routing_address = postConsentRequestJsonV510.to_account.account_routing.scheme, + other_account_secondary_routing_scheme = "", + other_account_secondary_routing_address = "", + other_bank_routing_scheme = postConsentRequestJsonV510.to_account.account_routing.scheme, + other_bank_routing_address = postConsentRequestJsonV510.to_account.account_routing.scheme, + other_branch_routing_scheme = postConsentRequestJsonV510.to_account.account_routing.scheme, + other_branch_routing_address = postConsentRequestJsonV510.to_account.account_routing.scheme, + is_beneficiary = true, + bespoke = Nil + ) + _ <- Helper.booleanToFuture(s"$InvalidValueLength. The maximum length of `description` field is ${MappedCounterparty.mDescription.maxLen}", cc = callContext) { + postJson.description.length <= 36 + } + + + (counterparty, callContext) <- Connector.connector.vend.checkCounterpartyExists(postJson.name, fromBankIdAccountId.bankId.value, fromBankIdAccountId.accountId.value, view.viewId.value, callContext) + + _ <- Helper.booleanToFuture(CounterpartyAlreadyExists.replace("value for BANK_ID or ACCOUNT_ID or VIEW_ID or NAME.", + s"COUNTERPARTY_NAME(${postJson.name}) for the BANK_ID(${fromBankIdAccountId.bankId.value}) and ACCOUNT_ID(${fromBankIdAccountId.accountId.value}) and VIEW_ID($sourceViewId)"), cc = callContext) { + counterparty.isEmpty + } + + _ <- Helper.booleanToFuture(s"$InvalidISOCurrencyCode Current input is: '${postJson.currency}'", cc = callContext) { + isValidCurrencyISOCode(postJson.currency) + } + + (counterparty, callContext) <- NewStyle.function.createCounterparty( + name = postJson.name, + description = postJson.description, + currency = postJson.currency, + createdByUserId = user.userId, + thisBankId = fromBankIdAccountId.bankId.value, + thisAccountId = fromBankIdAccountId.accountId.value, + thisViewId = sourceViewId, + otherAccountRoutingScheme = postJson.other_account_routing_scheme, + otherAccountRoutingAddress = postJson.other_account_routing_address, + otherAccountSecondaryRoutingScheme = postJson.other_account_secondary_routing_scheme, + otherAccountSecondaryRoutingAddress = postJson.other_account_secondary_routing_address, + otherBankRoutingScheme = postJson.other_bank_routing_scheme, + otherBankRoutingAddress = postJson.other_bank_routing_address, + otherBranchRoutingScheme = postJson.other_branch_routing_scheme, + otherBranchRoutingAddress = postJson.other_branch_routing_address, + isBeneficiary = postJson.is_beneficiary, + bespoke = postJson.bespoke.map(bespoke => CounterpartyBespoke(bespoke.key, bespoke.value)), + callContext + ) + + + postCounterpartyLimitV510 = PostCounterpartyLimitV510( + currency = postConsentRequestJsonV510.to_account.limit.currency, + max_single_amount = postConsentRequestJsonV510.to_account.limit.max_single_amount, + max_monthly_amount = postConsentRequestJsonV510.to_account.limit.max_monthly_amount, + max_number_of_monthly_transactions = postConsentRequestJsonV510.to_account.limit.max_number_of_monthly_transactions, + max_yearly_amount = postConsentRequestJsonV510.to_account.limit.max_yearly_amount, + max_number_of_yearly_transactions = postConsentRequestJsonV510.to_account.limit.max_number_of_yearly_transactions + ) + //3rd: create the counterparty limit + (counterpartyLimitBox, callContext) <- Connector.connector.vend.getCounterpartyLimit( + fromBankIdAccountId.bankId.value, + fromBankIdAccountId.accountId.value, + sourceViewId, + counterparty.counterpartyId, + cc.callContext + ) + failMsg = s"$CounterpartyLimitAlreadyExists Current BANK_ID(${fromBankIdAccountId.bankId.value}), ACCOUNT_ID(${fromBankIdAccountId.accountId.value}), VIEW_ID($sourceViewId),COUNTERPARTY_ID(${counterparty.counterpartyId})" + _ <- Helper.booleanToFuture(failMsg, cc = callContext) { + counterpartyLimitBox.isEmpty + } + (counterpartyLimit, callContext) <- NewStyle.function.createOrUpdateCounterpartyLimit( + bankId = counterparty.thisBankId, + accountId = counterparty.thisAccountId, + viewId = counterparty.thisViewId, + counterpartyId = counterparty.counterpartyId, + postCounterpartyLimitV510.currency, + postCounterpartyLimitV510.max_single_amount, + postCounterpartyLimitV510.max_monthly_amount, + postCounterpartyLimitV510.max_number_of_monthly_transactions, + postCounterpartyLimitV510.max_yearly_amount, + postCounterpartyLimitV510.max_number_of_yearly_transactions, + cc.callContext + ) + + } yield { + (view,counterparty,counterpartyLimit) + } + }else{ + Future.successful(true) + } + maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty="consents.max_time_to_live", defaultValue=3600) _ <- Helper.booleanToFuture(s"$ConsentMaxTTL ($maxTimeToLive)", cc=callContext){ consentRequestJson.time_to_live match { diff --git a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala index b424dc291b..2932b1ac1a 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala @@ -235,6 +235,7 @@ case class PostConsentRequestJsonV500( ) case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String]) +case class CreateConsentByRequestIdJson(source_view_id: Option[String]) case class CreatePhysicalCardJsonV500( card_number: String, From f60d7a8fd9b2a085103268fd215652197df5c887 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 22 Jul 2024 10:40:37 +0200 Subject: [PATCH 03/30] test/fixed the failed test --- .../scala/code/api/v1_4_0/JSONFactory1_4_0_LightTest.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0_LightTest.scala b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0_LightTest.scala index c49419e9ea..5ae2e0b554 100644 --- a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0_LightTest.scala +++ b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0_LightTest.scala @@ -104,11 +104,12 @@ class JSONFactory1_4_0_LightTest extends FeatureSpec listFields.toString contains ("private final java.util.Date code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassDate, ") shouldBe (true) listFields.toString contains ("private final scala.collection.immutable.List code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassTwo$1.strings2, ") shouldBe (true) listFields.toString contains ("private int java.lang.String.hash, private final java.lang.String code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassOne$1.string1, ") shouldBe (true) - listFields.toString contains ("private static final long java.lang.String.serialVersionUID, private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassTwo$1.$outer, ") shouldBe (true) + listFields.toString contains ("private static final long java.lang.String.serialVersionUID,") shouldBe (true) + listFields.toString contains ("private final code.api.v1_4_0.JSONFactory1_4_0_LightTest code.api.v1_4_0.JSONFactory1_4_0_LightTest$ClassTwo$1.$outer, ") shouldBe (true) listFields.toString contains ("private final scala.Option code.api.v1_4_0.JSONFactory1_4_0_LightTest$ComplexNestedClass$1.complexNestedClassOptionNoneIn") shouldBe (true) // println(listFields) } - + } From 4c6f3bb025a0a044133690ddc1555c1e920c03e0 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 23 Jul 2024 00:33:33 +0200 Subject: [PATCH 04/30] bugfix/added vrp logic to create consent -step2 --- .../SwaggerDefinitionsJSON.scala | 5 +- .../scala/code/api/util/ErrorMessages.scala | 1 + .../scala/code/api/v5_0_0/APIMethods500.scala | 47 ++++++++----------- .../code/api/v5_0_0/JSONFactory5.0.0.scala | 1 - .../code/api/v5_1_0/JSONFactory5.1.0.scala | 1 + 5 files changed, 22 insertions(+), 33 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 3375379fc8..0effd4e3c7 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -5218,10 +5218,6 @@ object SwaggerDefinitionsJSON { consent_request_id = Some(consentRequestIdExample.value) ) - val createConsentByRequestIdJson = CreateConsentByRequestIdJson( - source_view_id = Some(viewIdExample.copy(value="_VRP-9d429899-24f5-42c8-8565-943ffa6a7945").value) - ) - val postConsentRequestJsonV500 = PostConsentRequestJsonV500( everything = false, bank_id = None, @@ -5473,6 +5469,7 @@ object SwaggerDefinitionsJSON { ) val consentRequestToAccountJson = ConsentRequestToAccountJson ( + counterparty_name = counterpartyNameExample.value, bank_routing = bankRoutingJsonV121, account_routing = accountRoutingJsonV121, branch_routing = branchRoutingJsonV141, diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 21733fe8ad..23239c74f6 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -507,6 +507,7 @@ object ErrorMessages { val CounterpartyLimitAlreadyExists = "OBP-30264: Counterparty limit already exists. Please specify a different value for BANK_ID, ACCOUNT_ID, VIEW_ID or COUNTERPARTY_ID." val DeleteCounterpartyLimitError = "OBP-30265: Could not delete the counterparty limit." val CustomViewAlreadyExistsError = "OBP-30266: The custom view is already exists." + val UserDoesNotHavePermission = "OBP-30267: The user does not have the permission:" val TaxResidenceNotFound = "OBP-30300: Tax Residence not found by TAX_RESIDENCE_ID. " val CustomerAddressNotFound = "OBP-30310: Customer's Address not found by CUSTOMER_ADDRESS_ID. " diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 16e98b8e49..d82d415bb0 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -792,7 +792,7 @@ trait APIMethods500 { |Please note that the Consent cannot elevate the privileges logged in user already have. | |""", - createConsentByRequestIdJson, + EmptyBody, consentJsonV500, List( UserNotLoggedIn, @@ -820,7 +820,7 @@ trait APIMethods500 { |Please note that the Consent cannot elevate the privileges logged in user already have. | |""", - createConsentByRequestIdJson, + EmptyBody, consentJsonV500, List( UserNotLoggedIn, @@ -851,7 +851,7 @@ trait APIMethods500 { |Please note that the Consent cannot elevate the privileges logged in user already have. | |""", - createConsentByRequestIdJson, + EmptyBody, consentJsonV500, List( UserNotLoggedIn, @@ -876,7 +876,7 @@ trait APIMethods500 { lazy val createConsentByConsentRequestId : OBPEndpoint = { - case "consumer" :: "consent-requests":: consentRequestId :: scaMethod :: "consents" :: Nil JsonPost jsonBody -> _ => { + case "consumer" :: "consent-requests":: consentRequestId :: scaMethod :: "consents" :: Nil JsonPost _ -> _ => { def sendEmailNotification(callContext: Option[CallContext], consentRequestJson: PostConsentRequestJsonV500, challengeText: String) = { for { failMsg <- Future { @@ -961,39 +961,30 @@ trait APIMethods500 { which_alias_to_use = vrpViewId, hide_metadata_if_alias_used = true, allowed_permissions = targetPermissions - - val failMsg = s"$InvalidJsonFormat The vrp consent request json body should be the $PostConsentRequestJsonV510 " + ) for { - requestJsonViewIdOption <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.parse(createdConsentRequest.payload) - .extractOpt[CreateConsentByRequestIdJson] - .map(_.source_view_id) - .flatten - .filterNot(_.isEmpty) // if view_id = "",then return NONE. - } - //the json body view_id is an option field, if it is NONE, we need to find all the permissions the user have, - sourceViewId = requestJsonViewIdOption.getOrElse(APIUtil.getPropsValue("defaultBank.view_id", "owner"))//get all the views the user has, //1st: create the Custom View for the from account. (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(fromBankIdAccountId.bankId, fromBankIdAccountId.accountId, callContext) - view <- NewStyle.function.checkViewAccessAndReturnView(ViewId(sourceViewId), fromBankIdAccountId, Some(user), callContext) + //we do not need sourceViewId so far, we need to get all the view access for the login user, and + + permission <- NewStyle.function.permission(fromAccount.bankId, fromAccount.accountId, user, callContext) - permissionsFromSource = APIUtil.getViewPermissions(view.asInstanceOf[ViewDefinition]) + permissionsFromSource = permission.views.map(view =>APIUtil.getViewPermissions(view.asInstanceOf[ViewDefinition]).toList).flatten.toSet permissionsFromTarget = targetCreateCustomViewJson.allowed_permissions - _ <- Helper.booleanToFuture(failMsg = SourceViewHasLessPermission + s"Current source view permissions ($permissionsFromSource), target view permissions ($permissionsFromTarget)", cc = callContext) { - permissionsFromTarget.toSet.subsetOf(permissionsFromSource) - } - failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(nameOf(view.canUpdateCustomView))}` permission on VIEW_ID(${sourceViewId})" + userMissingPermissions = permissionsFromTarget.toSet diff permissionsFromSource + + failMsg = s"${ErrorMessages.UserDoesNotHavePermission} ${userMissingPermissions.toString}" _ <- Helper.booleanToFuture(failMsg, cc = callContext) { - view.canCreateCustomView + userMissingPermissions.isEmpty } (view, callContext) <- NewStyle.function.createCustomView(fromBankIdAccountId, targetCreateCustomViewJson.toCreateViewJson, callContext) //2st: Create a new counterparty on that view (_VRP-9d429899-24f5-42c8-8565-943ffa6a7945) postJson = PostCounterpartyJson400( - name = "", //TODO, this need to be a unique. - description = "", + name = postConsentRequestJsonV510.to_account.counterparty_name, + description = postConsentRequestJsonV510.to_account.counterparty_name, currency = postConsentRequestJsonV510.to_account.limit.currency, other_account_routing_scheme = postConsentRequestJsonV510.to_account.account_routing.scheme, other_account_routing_address = postConsentRequestJsonV510.to_account.account_routing.scheme, @@ -1014,7 +1005,7 @@ trait APIMethods500 { (counterparty, callContext) <- Connector.connector.vend.checkCounterpartyExists(postJson.name, fromBankIdAccountId.bankId.value, fromBankIdAccountId.accountId.value, view.viewId.value, callContext) _ <- Helper.booleanToFuture(CounterpartyAlreadyExists.replace("value for BANK_ID or ACCOUNT_ID or VIEW_ID or NAME.", - s"COUNTERPARTY_NAME(${postJson.name}) for the BANK_ID(${fromBankIdAccountId.bankId.value}) and ACCOUNT_ID(${fromBankIdAccountId.accountId.value}) and VIEW_ID($sourceViewId)"), cc = callContext) { + s"COUNTERPARTY_NAME(${postJson.name}) for the BANK_ID(${fromBankIdAccountId.bankId.value}) and ACCOUNT_ID(${fromBankIdAccountId.accountId.value}) and VIEW_ID($vrpViewId)"), cc = callContext) { counterparty.isEmpty } @@ -1029,7 +1020,7 @@ trait APIMethods500 { createdByUserId = user.userId, thisBankId = fromBankIdAccountId.bankId.value, thisAccountId = fromBankIdAccountId.accountId.value, - thisViewId = sourceViewId, + thisViewId = vrpViewId, otherAccountRoutingScheme = postJson.other_account_routing_scheme, otherAccountRoutingAddress = postJson.other_account_routing_address, otherAccountSecondaryRoutingScheme = postJson.other_account_secondary_routing_scheme, @@ -1056,11 +1047,11 @@ trait APIMethods500 { (counterpartyLimitBox, callContext) <- Connector.connector.vend.getCounterpartyLimit( fromBankIdAccountId.bankId.value, fromBankIdAccountId.accountId.value, - sourceViewId, + vrpViewId, counterparty.counterpartyId, cc.callContext ) - failMsg = s"$CounterpartyLimitAlreadyExists Current BANK_ID(${fromBankIdAccountId.bankId.value}), ACCOUNT_ID(${fromBankIdAccountId.accountId.value}), VIEW_ID($sourceViewId),COUNTERPARTY_ID(${counterparty.counterpartyId})" + failMsg = s"$CounterpartyLimitAlreadyExists Current BANK_ID(${fromBankIdAccountId.bankId.value}), ACCOUNT_ID(${fromBankIdAccountId.accountId.value}), VIEW_ID($vrpViewId),COUNTERPARTY_ID(${counterparty.counterpartyId})" _ <- Helper.booleanToFuture(failMsg, cc = callContext) { counterpartyLimitBox.isEmpty } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala index 2932b1ac1a..b424dc291b 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala @@ -235,7 +235,6 @@ case class PostConsentRequestJsonV500( ) case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String]) -case class CreateConsentByRequestIdJson(source_view_id: Option[String]) case class CreatePhysicalCardJsonV500( card_number: String, diff --git a/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala b/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala index e9a12640b2..54debc1d28 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala @@ -393,6 +393,7 @@ case class ConsentRequestFromAccountJson( ) case class ConsentRequestToAccountJson( + counterparty_name: String, bank_routing: BankRoutingJsonV121, account_routing: AccountRoutingJsonV121, branch_routing: BranchRoutingJsonV141, From 2fb010186acecd53d8a4baa11fa1d58fbece47a7 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Tue, 23 Jul 2024 13:07:20 +0200 Subject: [PATCH 05/30] refactor/added log for createBerlinGroupConsentJWT --- obp-api/src/main/scala/code/api/util/ConsentUtil.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala index d1f2ceed1d..fac407a1cc 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -683,6 +683,7 @@ object Consent extends MdcLoggable { // 1. Add access val accounts: List[Future[ConsentView]] = consent.access.accounts.getOrElse(Nil) map { account => Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), None) map { bankAccount => + logger.debug(s"createBerlinGroupConsentJWT.accounts.bankAccount: $bankAccount") ConsentView( bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""), account_id = bankAccount._1.map(_.accountId.value).getOrElse(""), @@ -692,6 +693,7 @@ object Consent extends MdcLoggable { } val balances: List[Future[ConsentView]] = consent.access.balances.getOrElse(Nil) map { account => Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), None) map { bankAccount => + logger.debug(s"createBerlinGroupConsentJWT.balances.bankAccount: $bankAccount") ConsentView( bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""), account_id = bankAccount._1.map(_.accountId.value).getOrElse(""), @@ -701,6 +703,7 @@ object Consent extends MdcLoggable { } val transactions: List[Future[ConsentView]] = consent.access.transactions.getOrElse(Nil) map { account => Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), None) map { bankAccount => + logger.debug(s"createBerlinGroupConsentJWT.transactions.bankAccount: $bankAccount") ConsentView( bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""), account_id = bankAccount._1.map(_.accountId.value).getOrElse(""), From 461f16c5225406d79af7b5510c50b844f0416287 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 24 Jul 2024 10:24:52 +0200 Subject: [PATCH 06/30] bugfix/added the callContext to createBerlinGroupConsentJWT method --- .../group/v1_3/AccountInformationServiceAISApi.scala | 3 ++- obp-api/src/main/scala/code/api/util/ConsentUtil.scala | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala index 17e79ea189..223ea3afa4 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala @@ -186,7 +186,8 @@ As a last option, an ASPSP might in addition accept a command with access rights createdConsent.secret, createdConsent.consentId, callContext.flatMap(_.consumer).map(_.consumerId.get), - Some(validUntil) + Some(validUntil), + callContext ) _ <- Future(Consents.consentProvider.vend.setJsonWebToken(createdConsent.consentId, consentJWT)) map { i => connectorEmptyResponse(i, callContext) diff --git a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala index fac407a1cc..1b8781fe0c 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -666,7 +666,8 @@ object Consent extends MdcLoggable { secret: String, consentId: String, consumerId: Option[String], - validUntil: Option[Date]): Future[String] = { + validUntil: Option[Date], + callContext: Option[CallContext]): Future[String] = { val currentTimeInSeconds = System.currentTimeMillis / 1000 val validUntilTimeInSeconds = validUntil match { @@ -682,7 +683,7 @@ object Consent extends MdcLoggable { // 1. Add access val accounts: List[Future[ConsentView]] = consent.access.accounts.getOrElse(Nil) map { account => - Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), None) map { bankAccount => + Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount => logger.debug(s"createBerlinGroupConsentJWT.accounts.bankAccount: $bankAccount") ConsentView( bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""), @@ -692,7 +693,7 @@ object Consent extends MdcLoggable { } } val balances: List[Future[ConsentView]] = consent.access.balances.getOrElse(Nil) map { account => - Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), None) map { bankAccount => + Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount => logger.debug(s"createBerlinGroupConsentJWT.balances.bankAccount: $bankAccount") ConsentView( bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""), @@ -702,7 +703,7 @@ object Consent extends MdcLoggable { } } val transactions: List[Future[ConsentView]] = consent.access.transactions.getOrElse(Nil) map { account => - Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), None) map { bankAccount => + Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount => logger.debug(s"createBerlinGroupConsentJWT.transactions.bankAccount: $bankAccount") ConsentView( bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""), From 00fac70873e4eb84e46f1eaaefa98819cb738d5f Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 25 Jul 2024 09:21:09 +0200 Subject: [PATCH 07/30] feature/VRP add the tests --- .../scala/code/api/v5_0_0/APIMethods500.scala | 6 +++--- .../api/v5_1_0/VRPConsentRequestTest.scala | 20 ++++++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index d82d415bb0..470d6ff754 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -945,12 +945,12 @@ trait APIMethods500 { _ <- if (createdConsentRequest.payload.contains("to_account")) { val postConsentRequestJsonV510 = json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostConsentRequestJsonV510] val fromBankIdAccountId = BankIdAccountId(BankId(postConsentRequestJsonV510.from_account.bank_routing.address), AccountId(postConsentRequestJsonV510.from_account.account_routing.address)) - - val vrpViewId = "_VRP-" + UUID.randomUUID.toString + + val vrpViewId = s"_VRP-${UUID.randomUUID.toString}".dropRight(5)// to make sure the length of the viewId is 36. val targetPermissions = List(//may need getTransactionRequest .. so far only this payments. "can_add_transaction_request_to_own_account", "can_add_transaction_request_to_any_account", - "can_add_transaction_request_to_beneficiary" +// "can_add_transaction_request_to_beneficiary" ) //TODO,here need to be checked later. val targetCreateCustomViewJson = CreateCustomViewJson( diff --git a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala index 7cdc044a57..d225bf9b29 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala @@ -26,10 +26,12 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_1_0 import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{accountRoutingJsonV121, bankRoutingJsonV121, branchRoutingJsonV141, postCounterpartyLimitV510} import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole._ import code.api.util.Consent import code.api.util.ErrorMessages._ +import code.api.util.ExampleValue.counterpartyNameExample import code.api.v3_1_0.PostConsentChallengeJsonV310 import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 import code.api.v4_0_0.UsersJsonV400 @@ -75,7 +77,23 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ def createConsentByConsentRequestIdImplicit(requestId:String) = (v5_1_0_Request / "consumer"/ "consent-requests"/requestId/"IMPLICIT"/"consents").POST<@(user1) def getConsentByRequestIdUrl(requestId:String) = (v5_1_0_Request / "consumer"/ "consent-requests"/requestId/"consents").GET<@(user1) - lazy val postConsentRequestJson = SwaggerDefinitionsJSON.postConsentRequestJsonV510 + val fromAccountJson = ConsentRequestFromAccountJson ( + bank_routing = bankRoutingJsonV121.copy(address = testBankId1.value), + account_routing = accountRoutingJsonV121.copy(address = testAccountId0.value), + branch_routing = branchRoutingJsonV141 + ) + + val toAccountJson = ConsentRequestToAccountJson ( + counterparty_name = counterpartyNameExample.value, + bank_routing = bankRoutingJsonV121.copy(address = testBankId1.value), + account_routing = accountRoutingJsonV121.copy(address = testAccountId1.value), + branch_routing = branchRoutingJsonV141, + limit = postCounterpartyLimitV510 + ) + lazy val postConsentRequestJson = SwaggerDefinitionsJSON.postConsentRequestJsonV510.copy( + from_account=fromAccountJson, + to_account=toAccountJson + ) feature("Create/Get Consent Request v5.1.0") { From 7394a5950b8fe453d5c90c8b392745bfc147b6ee Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Jul 2024 13:24:33 +0200 Subject: [PATCH 08/30] feature/VRP added new view permission can_add_transaction_request_to_beneficiary --- .../main/scala/code/api/v5_0_0/APIMethods500.scala | 6 ++---- .../main/scala/code/views/system/ViewDefinition.scala | 11 +++++++++-- .../com/openbankproject/commons/model/ViewModel.scala | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 470d6ff754..512a90aac7 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -948,10 +948,8 @@ trait APIMethods500 { val vrpViewId = s"_VRP-${UUID.randomUUID.toString}".dropRight(5)// to make sure the length of the viewId is 36. val targetPermissions = List(//may need getTransactionRequest .. so far only this payments. - "can_add_transaction_request_to_own_account", - "can_add_transaction_request_to_any_account", -// "can_add_transaction_request_to_beneficiary" - ) //TODO,here need to be checked later. + "can_add_transaction_request_to_beneficiary" + ) val targetCreateCustomViewJson = CreateCustomViewJson( name = vrpViewId, diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 287f716ff9..08d997b440 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -298,9 +298,15 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many } //internal transfer between my own accounts + + @deprecated("we added new field `canAddTransactionRequestToBeneficiary_`","25-07-2024") object canAddTransactionRequestToOwnAccount_ extends MappedBoolean(this){ override def defaultValue = false } + + object canAddTransactionRequestToBeneficiary_ extends MappedBoolean(this){ + override def defaultValue = false + } // transfer to any account object canAddTransactionRequestToAnyAccount_ extends MappedBoolean(this){ @@ -438,7 +444,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canAddWhereTag_(actions.exists(_ == "can_add_where_tag")) canSeeWhereTag_(actions.exists(_ == "can_see_where_tag")) canDeleteWhereTag_(actions.exists(_ == "can_delete_where_tag")) - canAddTransactionRequestToOwnAccount_(actions.exists(_ == "can_add_transaction_request_to_own_account")) //added following two for payments + canAddTransactionRequestToBeneficiary_(actions.exists(_ == "can_add_transaction_request_to_beneficiary")) canAddTransactionRequestToAnyAccount_(actions.exists(_ == "can_add_transaction_request_to_any_account")) canSeeBankAccountCreditLimit_(actions.exists(_ == "can_see_bank_account_credit_limit")) canCreateDirectDebit_(actions.exists(_ == "can_create_direct_debit")) @@ -585,8 +591,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canSeeWhereTag : Boolean = canSeeWhereTag_.get def canDeleteWhereTag : Boolean = canDeleteWhereTag_.get - def canAddTransactionRequestToOwnAccount: Boolean = canAddTransactionRequestToOwnAccount_.get //added following two for payments + def canAddTransactionRequestToOwnAccount: Boolean = false //we do not need this field, set this to false. def canAddTransactionRequestToAnyAccount: Boolean = canAddTransactionRequestToAnyAccount_.get + def canAddTransactionRequestToBeneficiary: Boolean = canSeeBankAccountCreditLimit_.get def canSeeBankAccountCreditLimit: Boolean = canSeeBankAccountCreditLimit_.get def canCreateDirectDebit: Boolean = canCreateDirectDebit_.get diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 4cf6b06fbb..a4b0fcf9f2 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -421,6 +421,7 @@ trait View { def canAddTransactionRequestToOwnAccount: Boolean //added following two for payments def canAddTransactionRequestToAnyAccount: Boolean + def canAddTransactionRequestToBeneficiary: Boolean def canSeeBankAccountCreditLimit: Boolean From d84a59629217aa701092f452330f655b4e34da36 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Jul 2024 15:14:40 +0200 Subject: [PATCH 09/30] feature/VRP added account access to the user --- .../main/scala/code/api/v5_0_0/APIMethods500.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 512a90aac7..7177557acd 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -977,7 +977,9 @@ trait APIMethods500 { _ <- Helper.booleanToFuture(failMsg, cc = callContext) { userMissingPermissions.isEmpty } - (view, callContext) <- NewStyle.function.createCustomView(fromBankIdAccountId, targetCreateCustomViewJson.toCreateViewJson, callContext) + (vrpView, callContext) <- NewStyle.function.createCustomView(fromBankIdAccountId, targetCreateCustomViewJson.toCreateViewJson, callContext) + + _ <-NewStyle.function.grantAccessToCustomView(vrpView, user, callContext) //2st: Create a new counterparty on that view (_VRP-9d429899-24f5-42c8-8565-943ffa6a7945) postJson = PostCounterpartyJson400( @@ -1000,7 +1002,7 @@ trait APIMethods500 { } - (counterparty, callContext) <- Connector.connector.vend.checkCounterpartyExists(postJson.name, fromBankIdAccountId.bankId.value, fromBankIdAccountId.accountId.value, view.viewId.value, callContext) + (counterparty, callContext) <- Connector.connector.vend.checkCounterpartyExists(postJson.name, fromBankIdAccountId.bankId.value, fromBankIdAccountId.accountId.value, vrpView.viewId.value, callContext) _ <- Helper.booleanToFuture(CounterpartyAlreadyExists.replace("value for BANK_ID or ACCOUNT_ID or VIEW_ID or NAME.", s"COUNTERPARTY_NAME(${postJson.name}) for the BANK_ID(${fromBankIdAccountId.bankId.value}) and ACCOUNT_ID(${fromBankIdAccountId.accountId.value}) and VIEW_ID($vrpViewId)"), cc = callContext) { @@ -1010,7 +1012,7 @@ trait APIMethods500 { _ <- Helper.booleanToFuture(s"$InvalidISOCurrencyCode Current input is: '${postJson.currency}'", cc = callContext) { isValidCurrencyISOCode(postJson.currency) } - + (counterparty, callContext) <- NewStyle.function.createCounterparty( name = postJson.name, description = postJson.description, @@ -1066,9 +1068,9 @@ trait APIMethods500 { postCounterpartyLimitV510.max_number_of_yearly_transactions, cc.callContext ) - + } yield { - (view,counterparty,counterpartyLimit) + (vrpView,counterparty,counterpartyLimit) } }else{ Future.successful(true) From 67eafacff993ed68f71040b2914c3b59bf26160f Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Jul 2024 15:27:17 +0200 Subject: [PATCH 10/30] feature/VRP added views to consent --- .../scala/code/api/v5_0_0/APIMethods500.scala | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 7177557acd..145b8d660e 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -942,7 +942,7 @@ trait APIMethods500 { } } - _ <- if (createdConsentRequest.payload.contains("to_account")) { + bankIdAccountIdViewId <- if (createdConsentRequest.payload.contains("to_account")) { val postConsentRequestJsonV510 = json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostConsentRequestJsonV510] val fromBankIdAccountId = BankIdAccountId(BankId(postConsentRequestJsonV510.from_account.bank_routing.address), AccountId(postConsentRequestJsonV510.from_account.account_routing.address)) @@ -1070,10 +1070,10 @@ trait APIMethods500 { ) } yield { - (vrpView,counterparty,counterpartyLimit) + BankIdAccountIdViewId(fromAccount.bankId, fromAccount.accountId, vrpView.viewId) } }else{ - Future.successful(true) + Future.successful(BankIdAccountIdViewId(BankId(""), AccountId(""), ViewId(""))) } maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty="consents.max_time_to_live", defaultValue=3600) @@ -1100,17 +1100,25 @@ trait APIMethods500 { ) ) } - postConsentViewJsons <- Future.sequence( - consentRequestJson.account_access.map( - access => - NewStyle.function.getBankAccountByRouting(None,access.account_routing.scheme, access.account_routing.address, cc.callContext) - .map(result =>PostConsentViewJsonV310( - result._1.bankId.value, - result._1.accountId.value, - access.view_id - )) + postConsentViewJsons <- if(createdConsentRequest.payload.contains("to_account")) { + Future.successful(List(PostConsentViewJsonV310( + bankIdAccountIdViewId.bankId.value, + bankIdAccountIdViewId.accountId.value, + bankIdAccountIdViewId.viewId.value + ))) + }else{ + Future.sequence( + consentRequestJson.account_access.map( + access => + NewStyle.function.getBankAccountByRouting(None,access.account_routing.scheme, access.account_routing.address, cc.callContext) + .map(result =>PostConsentViewJsonV310( + result._1.bankId.value, + result._1.accountId.value, + access.view_id + )) ) ) + } (_, assignedViews) <- Future(Views.views.vend.privateViewsUserCanAccess(user)) _ <- Helper.booleanToFuture(ViewsAllowedInConsent, cc=callContext){ From a5ebcb53a0311347ebd30d885ed3e7a84b50b570 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Jul 2024 09:15:34 +0200 Subject: [PATCH 11/30] feature/VRP add new permission `canAddTransactionRequestToBeneficiary_` --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 6 ++++-- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 3 ++- .../code/api/util/migration/MigrationOfViewDefinition.scala | 1 + .../src/main/scala/code/model/dataAccess/MappedView.scala | 5 +++++ obp-api/src/main/scala/code/views/MapperViews.scala | 4 ++++ .../setup/TestConnectorSetupWithStandardPermissions.scala | 1 + 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 74f57dfa9e..2f16c2c2d0 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -3649,11 +3649,13 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ lazy val canAddTransactionRequestToAnyAccount = view.map(_.canAddTransactionRequestToAnyAccount).getOrElse(false) + lazy val canAddTransactionRequestToBeneficiary = view.map(_.canAddTransactionRequestToBeneficiary).getOrElse(false) //1st check the admin level role/entitlement `canCreateAnyTransactionRequest` if (hasCanCreateAnyTransactionRequestRole) { Full(true) - //2rd: check if the user have the view access and the view has the `canAddTransactionRequestToAnyAccount` permission - } else if (canAddTransactionRequestToAnyAccount) { + } else if (canAddTransactionRequestToAnyAccount) { //2rd: check if the user have the view access and the view has the `canAddTransactionRequestToAnyAccount` permission + Full(true) + } else if (canAddTransactionRequestToBeneficiary) { //3erd: check if the user have the view access and the view has the `canAddTransactionRequestToBeneficiary` permission Full(true) } else { Empty diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 23239c74f6..4ae821124a 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -600,7 +600,8 @@ object ErrorMessages { "because the login user doesn't have access to the view of the from account " + "or the consumer doesn't have the access to the view of the from account " + s"or the login user does not have the `${CanCreateAnyTransactionRequest.toString()}` role " + - s"or the view does not have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName).dropRight(1)}." + s"or the view does not have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName).dropRight(1)}." + + s"or the view does not have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToBeneficiary_.dbColumnName).dropRight(1)}." val InvalidTransactionRequestCurrency = "OBP-40003: Transaction Request Currency must be the same as From Account Currency." val InvalidTransactionRequestId = "OBP-40004: Transaction Request Id not found." val InsufficientAuthorisationToCreateTransactionType = "OBP-40005: Insufficient authorisation to Create Transaction Type offered by the bank. The Request could not be created because you don't have access to CanCreateTransactionType." diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinition.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinition.scala index 6771437630..a91c6d9970 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinition.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinition.scala @@ -115,6 +115,7 @@ object TableViewDefinition { .canSeeOtherAccountRoutingAddress_(view.canSeeOtherAccountRoutingAddress) .canAddTransactionRequestToOwnAccount_(view.canAddTransactionRequestToOwnAccount) .canAddTransactionRequestToAnyAccount_(view.canAddTransactionRequestToAnyAccount) + .canAddTransactionRequestToBeneficiary_(view.canAddTransactionRequestToBeneficiary) .save } val isSuccessful = insertedRows.forall(_ == true) diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index c5c3c156b8..abaf09f344 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -442,6 +442,9 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canAddTransactionRequestToAnyAccount_ extends MappedBoolean(this){ override def defaultValue = false } + object canAddTransactionRequestToBeneficiary_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeBankAccountCreditLimit_ extends MappedBoolean(this){ override def defaultValue = false } @@ -589,6 +592,8 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with override def canGrantAccessToCustomViews: Boolean = canGrantAccessToCustomViews_.get override def canRevokeAccessToCustomViews: Boolean = canRevokeAccessToCustomViews_.get + + override def canAddTransactionRequestToBeneficiary: Boolean = canAddTransactionRequestToBeneficiary_.get } object ViewImpl extends ViewImpl with LongKeyedMetaMapper[ViewImpl]{ diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 37e97d0e9c..aedb244391 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -905,6 +905,7 @@ object MapperViews extends Views with MdcLoggable { .canSeeOtherAccountRoutingAddress_(true) .canAddTransactionRequestToOwnAccount_(true) //added following two for payments .canAddTransactionRequestToAnyAccount_(true) + .canAddTransactionRequestToBeneficiary_(true) .canSeeAvailableViewsForBankAccount_(false) .canSeeTransactionRequests_(false) .canSeeTransactionRequestTypes_(false) @@ -933,6 +934,7 @@ object MapperViews extends Views with MdcLoggable { entity .canSeeTransactionDescription_(false) .canAddTransactionRequestToAnyAccount_(false) + .canAddTransactionRequestToBeneficiary_(false) case SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID => entity .canRevokeAccessToCustomViews_(true) @@ -1040,6 +1042,8 @@ object MapperViews extends Views with MdcLoggable { canSeeOtherAccountRoutingAddress_(true). canAddTransactionRequestToOwnAccount_(false). //added following two for payments canAddTransactionRequestToAnyAccount_(false). + canAddTransactionRequestToBeneficiary_(false). + canAddTransactionRequestToBeneficiary_(false). canSeeTransactionRequests_(false). canSeeTransactionRequestTypes_(false). canUpdateBankAccountLabel_(false). diff --git a/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala b/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala index dcc67510b9..511ec4b149 100644 --- a/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala +++ b/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala @@ -130,6 +130,7 @@ trait TestConnectorSetupWithStandardPermissions extends TestConnectorSetup { canSeeOtherAccountRoutingAddress_(true). canAddTransactionRequestToOwnAccount_(false). //added following two for payments canAddTransactionRequestToAnyAccount_(false). + canAddTransactionRequestToBeneficiary_(false). canSeeBankAccountCreditLimit_(true). saveMe } From c2465d6d287e59754ae51619cbec7cc80a96f5a1 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 26 Jul 2024 10:47:09 +0200 Subject: [PATCH 12/30] feature/VRP set the canAddTransactionRequestToBeneficiary_ for owner view in Migration --- .../code/api/util/migration/Migration.scala | 8 ++++ ...anAddTransactionRequestToBeneficiary.scala | 47 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionCanAddTransactionRequestToBeneficiary.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 03c6f24c11..6309a8be44 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -101,6 +101,7 @@ object Migration extends MdcLoggable { alterMappedCustomerAttribute(startedBeforeSchemifier) dropMappedBadLoginAttemptIndex() alterMetricColumnUrlLength() + populateViewDefinitionCanAddTransactionRequestToBeneficiary() } private def dummyScript(): Boolean = { @@ -128,6 +129,13 @@ object Migration extends MdcLoggable { runOnce(name) { TableViewDefinition.populate(name) } + } + + private def populateViewDefinitionCanAddTransactionRequestToBeneficiary(): Boolean = { + val name = nameOf(populateViewDefinitionCanAddTransactionRequestToBeneficiary) + runOnce(name) { + MigrationOfViewDefinitionCanAddTransactionRequestToBeneficiary.populateTheField(name) + } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionCanAddTransactionRequestToBeneficiary.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionCanAddTransactionRequestToBeneficiary.scala new file mode 100644 index 0000000000..32fec4883d --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionCanAddTransactionRequestToBeneficiary.scala @@ -0,0 +1,47 @@ +package code.api.util.migration + +import code.api.Constant.SYSTEM_OWNER_VIEW_ID + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.model.Consumer +import code.views.system.ViewDefinition + +object MigrationOfViewDefinitionCanAddTransactionRequestToBeneficiary { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def populateTheField(name: String): Boolean = { + DbFunction.tableExists(ViewDefinition) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val view = ViewDefinition.findSystemView(SYSTEM_OWNER_VIEW_ID).map(_.canAddTransactionRequestToBeneficiary_(true).saveMe()) + + + val endDate = System.currentTimeMillis() + val comment: String = + s"""set $SYSTEM_OWNER_VIEW_ID.canAddTransactionRequestToBeneficiary_ to {true}""".stripMargin + val value = view.map(_.canAddTransactionRequestToBeneficiary_.get).getOrElse(false) + isSuccessful = value + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${Consumer._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } +} From 9d590ccde4839eb62d2d05a96193c358ffc29f31 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 26 Jul 2024 12:48:43 +0200 Subject: [PATCH 13/30] bugfix/tweaked the view permission for canGetCounterparty --- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index aa29368675..acb97e0d9d 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8390,8 +8390,8 @@ trait APIMethods400 extends MdcLoggable { cc => implicit val ec = EndpointContext(Some(cc)) for { (user @Full(u), _, account, view, callContext) <- SS.userBankAccountView - _ <- Helper.booleanToFuture(failMsg = s"${NoViewPermission}can_add_counterparty", 403, cc=callContext) { - view.canAddCounterparty == true + _ <- Helper.booleanToFuture(failMsg = s"${NoViewPermission}can_get_counterparty", 403, cc=callContext) { + view.canGetCounterparty == true } (counterparties, callContext) <- NewStyle.function.getCounterparties(bankId,accountId,viewId, callContext) //Here we need create the metadata for all the explicit counterparties. maybe show them in json response. From 65c4f64517c4ee5b9b13dcf70e3ca411aac4f10a Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Jul 2024 13:53:43 +0200 Subject: [PATCH 14/30] feature/VRP add consent_type to obp internal --- .../scala/code/api/v5_1_0/APIMethods510.scala | 23 +++++++++++-------- .../commons/model/enums/Enumerations.scala | 5 ++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 5ce86b3f39..af13fbacae 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -49,7 +49,8 @@ import com.openbankproject.commons.model._ import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} import net.liftweb.common.Full import net.liftweb.http.rest.RestHelper -import net.liftweb.json.{Extraction, compactRender, parse, prettyRender} +import net.liftweb.json +import net.liftweb.json.{Extraction, JObject, compactRender, parse, prettyRender} import net.liftweb.mapper.By import net.liftweb.util.{Helpers, StringHelpers} import net.liftweb.util.Helpers.tryo @@ -57,7 +58,7 @@ import net.liftweb.util.Helpers.tryo import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future - +import com.openbankproject.commons.model.enums.ConsentType trait APIMethods510 { self: RestHelper => @@ -2796,25 +2797,29 @@ trait APIMethods510 { ) lazy val createVRPConsentRequest : OBPEndpoint = { - case "consumer" :: "vrp-consent-requests" :: Nil JsonPost json -> _ => { + case "consumer" :: "vrp-consent-requests" :: Nil JsonPost postJson -> _ => { cc => implicit val ec = EndpointContext(Some(cc)) for { (_, callContext) <- applicationAccess(cc) _ <- passesPsd2Aisp(callContext) - failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentRequestJsonV510 " - consentRequestJson: PostConsentRequestJsonV510 <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.extract[PostConsentRequestJsonV510] + failMsg = s"$InvalidJsonFormat The Json body should be the $PostVRPConsentRequestJsonV510 " + consentRequestJson: PostVRPConsentRequestJsonV510 <- NewStyle.function.tryons(failMsg, 400, callContext) { + postJson.extract[PostVRPConsentRequestJsonV510] } - maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty="consents.max_time_to_live", defaultValue=3600) - _ <- Helper.booleanToFuture(s"$ConsentMaxTTL ($maxTimeToLive)", cc=callContext){ + maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty = "consents.max_time_to_live", defaultValue = 3600) + _ <- Helper.booleanToFuture(s"$ConsentMaxTTL ($maxTimeToLive)", cc = callContext) { consentRequestJson.time_to_live match { case Some(ttl) => ttl <= maxTimeToLive case _ => true } } + + // we need to add the consent_type internally, the user does not need to know it. + consentType = json.parse(s"""{"consent_type": "${ConsentType.VRP}"}""") + createdConsentRequest <- Future(ConsentRequests.consentRequestProvider.vend.createConsentRequest( callContext.flatMap(_.consumer), - Some(compactRender(json)) + Some(compactRender(postJson merge consentType)) )) map { i => connectorEmptyResponse(i, callContext) } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/enums/Enumerations.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/enums/Enumerations.scala index b23ae9b95c..38a604467b 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/enums/Enumerations.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/enums/Enumerations.scala @@ -218,6 +218,11 @@ object AttributeType extends OBPEnumeration[AttributeType]{ object DATE_WITH_DAY extends Value } +sealed trait ConsentType extends EnumValue +object ConsentType extends OBPEnumeration[ConsentType]{ + object VRP extends Value +} + sealed trait AttributeCategory extends EnumValue object AttributeCategory extends OBPEnumeration[AttributeCategory]{ object Bank extends Value From d7cca297aebd8d3ce34aaec86c44014e86c0f099 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Jul 2024 14:36:11 +0200 Subject: [PATCH 15/30] refactor/typo --- .../code/metadata/counterparties/MapperCounterparties.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala b/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala index f6eff475e8..b3bb9b5f82 100644 --- a/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala +++ b/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala @@ -211,7 +211,7 @@ object MapperCounterparties extends Counterparties with MdcLoggable { ): Box[CounterpartyTrait] = { val mappedCounterparty = MappedCounterparty.create - .mCounterPartyId(APIUtil.createExplicitCounterpartyId) //We create the Counterparty_Id here, it means, it will be create in each connnector. + .mCounterPartyId(APIUtil.createExplicitCounterpartyId) //We create the Counterparty_Id here, it means, it will be create in each connector. .mName(name) .mCreatedByUserId(createdByUserId) .mThisBankId(thisBankId) From 7929273180b89b306cbf1e054d1d2ac099249e0f Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Jul 2024 15:12:39 +0200 Subject: [PATCH 16/30] feature/VRP add helperInfo object --- .../SwaggerDefinitionsJSON.scala | 2 +- .../scala/code/api/v5_0_0/APIMethods500.scala | 39 +++++++++++-------- .../code/api/v5_0_0/JSONFactory5.0.0.scala | 9 ++++- .../scala/code/api/v5_1_0/APIMethods510.scala | 2 +- .../code/api/v5_1_0/JSONFactory5.1.0.scala | 22 ++++++++--- .../api/v5_1_0/VRPConsentRequestTest.scala | 26 ++++++++----- 6 files changed, 65 insertions(+), 35 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 0effd4e3c7..680e052e36 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -5476,7 +5476,7 @@ object SwaggerDefinitionsJSON { limit = postCounterpartyLimitV510 ) - val postConsentRequestJsonV510 = PostConsentRequestJsonV510( + val postVRPConsentRequestJsonV510 = PostVRPConsentRequestJsonV510( from_account = consentRequestFromAccountJson, to_account = consentRequestToAccountJson, email = Some(emailExample.value), diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 145b8d660e..aaa1b9122e 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -44,7 +44,7 @@ import java.util.concurrent.ThreadLocalRandom import code.accountattribute.AccountAttributeX import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.api.util.FutureUtil.EndpointContext -import code.api.v5_1_0.{CreateCustomViewJson, PostConsentRequestJsonV510, PostCounterpartyLimitV510} +import code.api.v5_1_0.{CreateCustomViewJson, PostVRPConsentRequestJsonV510, PostCounterpartyLimitV510} import code.consumer.Consumers import code.metadata.counterparties.MappedCounterparty import code.util.Helper.booleanToFuture @@ -929,21 +929,22 @@ trait APIMethods500 { _ <- Helper.booleanToFuture(ConsentAllowedScaMethods, cc=callContext){ List(StrongCustomerAuthentication.SMS.toString(), StrongCustomerAuthentication.EMAIL.toString(), StrongCustomerAuthentication.IMPLICIT.toString()).exists(_ == scaMethod) } - consentRequestJson <- + (consentRequestJson, isVRPConsentRequest) <- if(createdConsentRequest.payload.contains("to_account")) { - val failMsg = s"$InvalidJsonFormat The vrp consent request json body should be the $PostConsentRequestJsonV510 " + val failMsg = s"$InvalidJsonFormat The vrp consent request json body should be the $PostVRPConsentRequestJsonV510 " NewStyle.function.tryons(failMsg, 400, callContext) { - json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostConsentRequestJsonV510] - }.map(_.toPostConsentRequestJsonV500) + json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostVRPConsentRequestJsonInternalV510] + }.map(postVRPConsentRequest => (postVRPConsentRequest.toPostConsentRequestJsonV500, true)) } else{ val failMsg = s"$InvalidJsonFormat The consent request Json body should be the $PostConsentRequestJsonV500 " NewStyle.function.tryons(failMsg, 400, callContext) { json.parse(createdConsentRequest.payload).extract[PostConsentRequestJsonV500] - } + }.map(postVRPConsentRequest => (postVRPConsentRequest, false)) } - - bankIdAccountIdViewId <- if (createdConsentRequest.payload.contains("to_account")) { - val postConsentRequestJsonV510 = json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostConsentRequestJsonV510] + + //Here are all the VRP consent request + (bankId, accountId, viewId, counterpartyId) <- if (isVRPConsentRequest) { + val postConsentRequestJsonV510 = json.parse(createdConsentRequest.payload).extract[code.api.v5_1_0.PostVRPConsentRequestJsonV510] val fromBankIdAccountId = BankIdAccountId(BankId(postConsentRequestJsonV510.from_account.bank_routing.address), AccountId(postConsentRequestJsonV510.from_account.account_routing.address)) val vrpViewId = s"_VRP-${UUID.randomUUID.toString}".dropRight(5)// to make sure the length of the viewId is 36. @@ -1070,10 +1071,10 @@ trait APIMethods500 { ) } yield { - BankIdAccountIdViewId(fromAccount.bankId, fromAccount.accountId, vrpView.viewId) + (fromAccount.bankId, fromAccount.accountId, vrpView.viewId, CounterpartyId(counterparty.counterpartyId)) } }else{ - Future.successful(BankIdAccountIdViewId(BankId(""), AccountId(""), ViewId(""))) + Future.successful(BankId(""), AccountId(""), ViewId(""),CounterpartyId("")) } maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty="consents.max_time_to_live", defaultValue=3600) @@ -1101,10 +1102,10 @@ trait APIMethods500 { ) } postConsentViewJsons <- if(createdConsentRequest.payload.contains("to_account")) { - Future.successful(List(PostConsentViewJsonV310( - bankIdAccountIdViewId.bankId.value, - bankIdAccountIdViewId.accountId.value, - bankIdAccountIdViewId.viewId.value + Future.successful(List(PostConsentViewJsonV310( + bankId.value, + accountId.value, + viewId.value ))) }else{ Future.sequence( @@ -1203,7 +1204,13 @@ trait APIMethods500 { case _ =>Future{"Success"} } } yield { - (ConsentJsonV500(createdConsent.consentId, consentJWT, createdConsent.status, Some(createdConsent.consentRequestId)), HttpCode.`201`(callContext)) + (ConsentJsonV500( + createdConsent.consentId, + consentJWT, + createdConsent.status, + Some(createdConsent.consentRequestId), + if (isVRPConsentRequest) Some(HelperInfoJson(bankId.value, accountId.value, viewId.value, counterpartyId.value)) else None + ), HttpCode.`201`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala index b424dc291b..e52db51d49 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala @@ -233,8 +233,15 @@ case class PostConsentRequestJsonV500( valid_from: Option[Date], time_to_live: Option[Long] ) +case class HelperInfoJson( + bank_id:String, + account_id:String, + view_id:String, + counterparty_id:String +) + -case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String]) +case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String], helper_info:Option[HelperInfoJson] = None) case class CreatePhysicalCardJsonV500( card_number: String, diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index af13fbacae..ab1aa17571 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -2783,7 +2783,7 @@ trait APIMethods510 { |Authorization: Bearer eXtneO-THbQtn3zvK_kQtXXfvOZyZFdBCItlPDbR2Bk.dOWqtXCtFX-tqGTVR0YrIjvAolPIVg7GZ-jz83y6nA0 | |""".stripMargin, - postConsentRequestJsonV510, + postVRPConsentRequestJsonV510, vrpConsentRequestResponseJson, List( InvalidJsonFormat, diff --git a/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala b/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala index 54debc1d28..428be9ab19 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala @@ -35,7 +35,7 @@ import code.api.v2_1_0.ResourceUserJSON import code.api.v3_0_0.JSONFactory300.{createLocationJson, createMetaJson, transformToAddressFromV300} import code.api.v3_0_0.{AccountIdJson, AccountsIdsJsonV300, AddressJsonV300, OpeningTimesV300, ViewJsonV300} import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400, PostViewJsonV400} -import code.api.v5_0_0.{PostConsentRequestJsonV500} +import code.api.v5_0_0.PostConsentRequestJsonV500 import code.atmattribute.AtmAttribute import code.atms.Atms.Atm import code.users.{UserAttribute, Users} @@ -47,6 +47,7 @@ import java.util.Date import code.consent.MappedConsent import code.metrics.APIMetric import code.model.Consumer +import com.openbankproject.commons.model.enums.ConsentType import net.liftweb.common.{Box, Full} import net.liftweb.json import net.liftweb.json.{JString, JValue, parse, parseOpt} @@ -400,14 +401,14 @@ case class ConsentRequestToAccountJson( limit: PostCounterpartyLimitV510 ) -case class PostConsentRequestJsonV510( - from_account:ConsentRequestFromAccountJson, - to_account:ConsentRequestToAccountJson, +case class PostVRPConsentRequestJsonInternalV510( + consent_type: String, + from_account: ConsentRequestFromAccountJson, + to_account: ConsentRequestToAccountJson, email: Option[String], phone_number: Option[String], valid_from: Option[Date], - time_to_live: Option[Long] -){ + time_to_live: Option[Long]) { def toPostConsentRequestJsonV500 = { PostConsentRequestJsonV500( everything = false, @@ -423,6 +424,15 @@ case class PostConsentRequestJsonV510( } } +case class PostVRPConsentRequestJsonV510( + from_account:ConsentRequestFromAccountJson, + to_account:ConsentRequestToAccountJson, + email: Option[String], + phone_number: Option[String], + valid_from: Option[Date], + time_to_live: Option[Long] +) + object JSONFactory510 extends CustomJsonFormats { def createViewJson(view: View): CustomViewJsonV510 = { diff --git a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala index d225bf9b29..961f39fba9 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala @@ -27,6 +27,7 @@ package code.api.v5_1_0 import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{accountRoutingJsonV121, bankRoutingJsonV121, branchRoutingJsonV141, postCounterpartyLimitV510} +import code.api.v5_0_0.ConsentJsonV500 import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole._ import code.api.util.Consent @@ -90,16 +91,16 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ branch_routing = branchRoutingJsonV141, limit = postCounterpartyLimitV510 ) - lazy val postConsentRequestJson = SwaggerDefinitionsJSON.postConsentRequestJsonV510.copy( + lazy val postVRPConsentRequestJson = SwaggerDefinitionsJSON.postVRPConsentRequestJsonV510.copy( from_account=fromAccountJson, to_account=toAccountJson ) - - + + feature("Create/Get Consent Request v5.1.0") { scenario("We will call the Create endpoint without a user credentials", ApiEndpoint1, VersionOfApi) { When("We make a request v5.1.0") - val response510 = makePostRequest(createVRPConsentRequestWithoutLoginUrl, write(postConsentRequestJson)) + val response510 = makePostRequest(createVRPConsentRequestWithoutLoginUrl, write(postVRPConsentRequestJson)) Then("We should get a 401") response510.code should equal(401) response510.body.extract[ErrorMessage].message should equal (ApplicationNotIdentified) @@ -107,7 +108,7 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ scenario("We will call the Create, Get and Delete endpoints with user credentials ", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, VersionOfApi) { When(s"We try $ApiEndpoint1 v5.1.0") - val createConsentResponse = makePostRequest(createVRPConsentRequestUrl, write(postConsentRequestJson)) + val createConsentResponse = makePostRequest(createVRPConsentRequestUrl, write(postVRPConsentRequestJson)) Then("We should get a 201") createConsentResponse.code should equal(201) val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] @@ -126,8 +127,10 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ val createConsentByRequestResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) Then("We should get a 200") createConsentByRequestResponse.code should equal(201) - val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV510].consent_id - val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV510].jwt + val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id + val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV500].jwt + val helperInfo = createConsentByRequestResponse.body.extract[ConsentJsonV500].helper_info + helperInfo.isDefined should equal(true) setPropsValues("consumer_validation_method_for_consent"->"NONE") val requestWhichFails = (v5_1_0_Request / "users").GET @@ -159,7 +162,7 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ scenario("We will call the Create (IMPLICIT), Get and Delete endpoints with user credentials ", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, ApiEndpoint6, VersionOfApi) { When(s"We try $ApiEndpoint1 v5.1.0") - val createConsentResponse = makePostRequest(createVRPConsentRequestUrl, write(postConsentRequestJson)) + val createConsentResponse = makePostRequest(createVRPConsentRequestUrl, write(postVRPConsentRequestJson)) Then("We should get a 201") createConsentResponse.code should equal(201) val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] @@ -178,8 +181,11 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ val createConsentByRequestResponse = makePostRequest(createConsentByConsentRequestIdImplicit(consentRequestId), write("")) Then("We should get a 200") createConsentByRequestResponse.code should equal(201) - val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV510].consent_id - val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV510].jwt + val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id + val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV500].jwt + val helperInfo = createConsentByRequestResponse.body.extract[ConsentJsonV500].helper_info + helperInfo.isDefined should equal(true) + setPropsValues("consumer_validation_method_for_consent"->"NONE") val requestWhichFails = (v5_1_0_Request / "users").GET From 4e67fdb899581ffb208244c5275b6ca9b9e51f47 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 26 Jul 2024 15:28:15 +0200 Subject: [PATCH 17/30] refactor/typo --- .../main/scala/code/api/v2_2_0/APIMethods220.scala | 12 ++++++------ .../scala/code/api/v2_2_0/JSONFactory2.2.0.scala | 2 +- .../src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala | 4 ++-- .../src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala | 4 ++-- .../src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala | 4 ++-- .../main/scala/code/api/v4_0_0/APIMethods400.scala | 12 ++++++------ obp-api/src/main/scala/code/model/BankingData.scala | 10 +++++----- obp-api/src/main/scala/code/model/User.scala | 4 ++-- .../scala/code/api/v4_0_0/CounterpartyTest.scala | 4 ++-- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 7d5c5a7200..2ea62793f7 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -335,9 +335,9 @@ trait APIMethods220 { } resourceDocs += ResourceDoc( - getExplictCounterpartiesForAccount, + getExplicitCounterpartiesForAccount, implementedInApiVersion, - "getExplictCounterpartiesForAccount", + "getExplicitCounterpartiesForAccount", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties", "Get Counterparties (Explicit)", @@ -357,7 +357,7 @@ trait APIMethods220 { ), List(apiTagCounterparty, apiTagPSD2PIS, apiTagAccount, apiTagPsd2)) - lazy val getExplictCounterpartiesForAccount : OBPEndpoint = { + lazy val getExplicitCounterpartiesForAccount : OBPEndpoint = { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "counterparties" :: Nil JsonGet req => { cc => implicit val ec = EndpointContext(Some(cc)) for { @@ -391,9 +391,9 @@ trait APIMethods220 { resourceDocs += ResourceDoc( - getExplictCounterpartyById, + getExplicitCounterpartyById, implementedInApiVersion, - "getExplictCounterpartyById", + "getExplicitCounterpartyById", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID", "Get Counterparty by Counterparty Id (Explicit)", @@ -407,7 +407,7 @@ trait APIMethods220 { List(apiTagCounterparty, apiTagPSD2PIS, apiTagCounterpartyMetaData, apiTagPsd2) ) - lazy val getExplictCounterpartyById : OBPEndpoint = { + lazy val getExplicitCounterpartyById : OBPEndpoint = { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "counterparties" :: CounterpartyId(counterpartyId) :: Nil JsonGet req => { cc => implicit val ec = EndpointContext(Some(cc)) for { diff --git a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala index 15eb4e55cb..89ede907ad 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala @@ -185,7 +185,7 @@ case class CounterpartyJsonV220( ) case class CounterpartyMetadataJson( - public_alias : String, // Only have this value when we create explict counterparty + public_alias : String, // Only have this value when we create explicit counterparty more_info : String, url : String, image_url : String, diff --git a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala index 3e3d015c63..d618322c20 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala @@ -178,8 +178,8 @@ object OBPAPI2_2_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w Implementations2_2_0.createViewForBankAccount :: Implementations2_2_0.updateViewForBankAccount :: Implementations2_2_0.getCurrentFxRate :: - Implementations2_2_0.getExplictCounterpartiesForAccount :: - Implementations2_2_0.getExplictCounterpartyById :: + Implementations2_2_0.getExplicitCounterpartiesForAccount :: + Implementations2_2_0.getExplicitCounterpartyById :: Implementations2_2_0.getMessageDocs :: Implementations2_2_0.createBank :: Implementations2_2_0.createAccount :: diff --git a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala index 89678b1961..fad91faae6 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala @@ -209,8 +209,8 @@ object OBPAPI3_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints from 2.1.0 val endpointsOf2_2_0 = Implementations2_2_0.getCurrentFxRate :: Implementations2_2_0.createFx :: - Implementations2_2_0.getExplictCounterpartiesForAccount :: - Implementations2_2_0.getExplictCounterpartyById :: + Implementations2_2_0.getExplicitCounterpartiesForAccount :: + Implementations2_2_0.getExplicitCounterpartyById :: Implementations2_2_0.getMessageDocs :: Implementations2_2_0.createBank :: Implementations2_2_0.createAccount :: diff --git a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala index 9881be60bd..b581773be2 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala @@ -209,8 +209,8 @@ object OBPAPI3_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints from 2.1.0 val endpointsOf2_2_0 = Implementations2_2_0.getCurrentFxRate :: Implementations2_2_0.createFx :: - Implementations2_2_0.getExplictCounterpartiesForAccount :: - Implementations2_2_0.getExplictCounterpartyById :: + Implementations2_2_0.getExplicitCounterpartiesForAccount :: + Implementations2_2_0.getExplicitCounterpartyById :: Implementations2_2_0.getMessageDocs :: Implementations2_2_0.createBank :: // Implementations2_2_0.createAccount :: diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index acb97e0d9d..56f25e11a9 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8363,9 +8363,9 @@ trait APIMethods400 extends MdcLoggable { } staticResourceDocs += ResourceDoc( - getExplictCounterpartiesForAccount, + getExplicitCounterpartiesForAccount, implementedInApiVersion, - "getExplictCounterpartiesForAccount", + "getExplicitCounterpartiesForAccount", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties", "Get Counterparties (Explicit)", @@ -8385,7 +8385,7 @@ trait APIMethods400 extends MdcLoggable { ), List(apiTagCounterparty, apiTagPSD2PIS, apiTagPsd2, apiTagAccount)) - lazy val getExplictCounterpartiesForAccount : OBPEndpoint = { + lazy val getExplicitCounterpartiesForAccount : OBPEndpoint = { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "counterparties" :: Nil JsonGet req => { cc => implicit val ec = EndpointContext(Some(cc)) for { @@ -8466,9 +8466,9 @@ trait APIMethods400 extends MdcLoggable { } staticResourceDocs += ResourceDoc( - getExplictCounterpartyById, + getExplicitCounterpartyById, implementedInApiVersion, - "getExplictCounterpartyById", + "getExplicitCounterpartyById", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID", "Get Counterparty by Id (Explicit)", @@ -8482,7 +8482,7 @@ trait APIMethods400 extends MdcLoggable { List(apiTagCounterparty, apiTagPSD2PIS, apiTagPsd2, apiTagCounterpartyMetaData) ) - lazy val getExplictCounterpartyById : OBPEndpoint = { + lazy val getExplicitCounterpartyById : OBPEndpoint = { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "counterparties" :: CounterpartyId(counterpartyId) :: Nil JsonGet req => { cc => implicit val ec = EndpointContext(Some(cc)) for { diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index 086d1692cb..b8381fae4a 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -388,11 +388,11 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable final def moderatedOtherBankAccounts(view : View, bankIdAccountId: BankIdAccountId, user : Box[User], callContext: Option[CallContext]) : Box[List[ModeratedOtherBankAccount]] = if(APIUtil.hasAccountAccess(view, bankIdAccountId, user, callContext)){ val implicitModeratedOtherBankAccounts = Connector.connector.vend.getCounterpartiesFromTransaction(bankId, accountId).openOrThrowException(attemptedToOpenAnEmptyBox).map(oAcc => view.moderateOtherAccount(oAcc)).flatten - val explictCounterpartiesBox = Connector.connector.vend.getCounterpartiesLegacy(view.bankId, view.accountId, view.viewId) - explictCounterpartiesBox match { + val explicitCounterpartiesBox = Connector.connector.vend.getCounterpartiesLegacy(view.bankId, view.accountId, view.viewId) + explicitCounterpartiesBox match { case Full((counterparties, callContext))=> { - val explictModeratedOtherBankAccounts: List[ModeratedOtherBankAccount] = counterparties.flatMap(BankAccountX.toInternalCounterparty).flatMap(counterparty=>view.moderateOtherAccount(counterparty)) - Full(explictModeratedOtherBankAccounts ++ implicitModeratedOtherBankAccounts) + val explicitModeratedOtherBankAccounts: List[ModeratedOtherBankAccount] = counterparties.flatMap(BankAccountX.toInternalCounterparty).flatMap(counterparty=>view.moderateOtherAccount(counterparty)) + Full(explicitModeratedOtherBankAccounts ++ implicitModeratedOtherBankAccounts) } case _ => Full(implicitModeratedOtherBankAccounts) } @@ -409,7 +409,7 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable final def moderatedOtherBankAccount(counterpartyID : String, view : View, bankIdAccountId: BankIdAccountId, user : Box[User], callContext: Option[CallContext]) : Box[ModeratedOtherBankAccount] = if(APIUtil.hasAccountAccess(view, bankIdAccountId, user, callContext)) Connector.connector.vend.getCounterpartyByCounterpartyIdLegacy(CounterpartyId(counterpartyID), None).map(_._1).flatMap(BankAccountX.toInternalCounterparty).flatMap(view.moderateOtherAccount) match { - //First check the explict counterparty + //First check the explicit counterparty case Full(moderatedOtherBankAccount) => Full(moderatedOtherBankAccount) //Than we checked the implict counterparty. case _ => Connector.connector.vend.getCounterpartyFromTransaction(bankId, accountId, counterpartyID).flatMap(oAcc => view.moderateOtherAccount(oAcc)) diff --git a/obp-api/src/main/scala/code/model/User.scala b/obp-api/src/main/scala/code/model/User.scala index 891cc1f839..bc8d2906a4 100644 --- a/obp-api/src/main/scala/code/model/User.scala +++ b/obp-api/src/main/scala/code/model/User.scala @@ -66,7 +66,7 @@ case class UserExtended(val user: User) extends MdcLoggable { val consumerAccountAccess = { //If we find the AccountAccess by consumerId, this mean the accountAccess already assigned to some consumers - val explictConsumerHasAccountAccess = if(consumerId.isDefined){ + val explicitConsumerHasAccountAccess = if(consumerId.isDefined){ AccountAccess.find( By(AccountAccess.bank_id, bankIdAccountId.bankId.value), By(AccountAccess.account_id, bankIdAccountId.accountId.value), @@ -77,7 +77,7 @@ case class UserExtended(val user: User) extends MdcLoggable { false } - if(explictConsumerHasAccountAccess) { + if(explicitConsumerHasAccountAccess) { true }else{ //If we can not find accountAccess by consumerId, then we will find AccountAccess by default "ALL_CONSUMERS" , this mean the accountAccess can be used for all consumers diff --git a/obp-api/src/test/scala/code/api/v4_0_0/CounterpartyTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/CounterpartyTest.scala index 75007ee992..016bce8f2f 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/CounterpartyTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/CounterpartyTest.scala @@ -32,9 +32,9 @@ class CounterpartyTest extends V400ServerSetup { object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.createExplicitCounterparty)) - object ApiEndpoint6 extends Tag(nameOf(Implementations4_0_0.getExplictCounterpartyById)) + object ApiEndpoint6 extends Tag(nameOf(Implementations4_0_0.getExplicitCounterpartyById)) object ApiEndpoint7 extends Tag(nameOf(Implementations4_0_0.deleteExplicitCounterparty)) - object ApiEndpoint8 extends Tag(nameOf(Implementations4_0_0.getExplictCounterpartiesForAccount)) + object ApiEndpoint8 extends Tag(nameOf(Implementations4_0_0.getExplicitCounterpartiesForAccount)) feature(s" test manage counterparties endpoints.") { From c5ae53c2406703e1fcaa470ee8275f6a137b0c86 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 26 Jul 2024 16:46:03 +0200 Subject: [PATCH 18/30] refactor/tweaked error message --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 4 ++-- obp-api/src/main/scala/code/views/system/ViewDefinition.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 4ae821124a..d57a556cc3 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -600,8 +600,8 @@ object ErrorMessages { "because the login user doesn't have access to the view of the from account " + "or the consumer doesn't have the access to the view of the from account " + s"or the login user does not have the `${CanCreateAnyTransactionRequest.toString()}` role " + - s"or the view does not have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName).dropRight(1)}." + - s"or the view does not have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToBeneficiary_.dbColumnName).dropRight(1)}." + s"or the view does not have the permission can_add_transaction_request_to_any_account " + + s"or the view does not have the permission can_add_transaction_request_to_beneficiary." val InvalidTransactionRequestCurrency = "OBP-40003: Transaction Request Currency must be the same as From Account Currency." val InvalidTransactionRequestId = "OBP-40004: Transaction Request Id not found." val InsufficientAuthorisationToCreateTransactionType = "OBP-40005: Insufficient authorisation to Create Transaction Type offered by the bank. The Request could not be created because you don't have access to CanCreateTransactionType." diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 08d997b440..879d3127ce 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -593,7 +593,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canAddTransactionRequestToOwnAccount: Boolean = false //we do not need this field, set this to false. def canAddTransactionRequestToAnyAccount: Boolean = canAddTransactionRequestToAnyAccount_.get - def canAddTransactionRequestToBeneficiary: Boolean = canSeeBankAccountCreditLimit_.get + def canAddTransactionRequestToBeneficiary: Boolean = canAddTransactionRequestToBeneficiary_.get def canSeeBankAccountCreditLimit: Boolean = canSeeBankAccountCreditLimit_.get def canCreateDirectDebit: Boolean = canCreateDirectDebit_.get From 4b45608a3dec766b95259e44b9c5c8b095c2515d Mon Sep 17 00:00:00 2001 From: Hongwei Date: Mon, 29 Jul 2024 11:32:16 +0200 Subject: [PATCH 19/30] refactor/tweaked createConsentByConsentRequestId endpoint response body --- .../scala/code/api/v5_0_0/APIMethods500.scala | 2 +- .../scala/code/api/v5_0_0/JSONFactory5.0.0.scala | 8 ++++++-- .../code/api/v5_1_0/VRPConsentRequestTest.scala | 16 +++++++++++----- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index aaa1b9122e..5b34388171 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -1209,7 +1209,7 @@ trait APIMethods500 { consentJWT, createdConsent.status, Some(createdConsent.consentRequestId), - if (isVRPConsentRequest) Some(HelperInfoJson(bankId.value, accountId.value, viewId.value, counterpartyId.value)) else None + if (isVRPConsentRequest) Some(ConsentAccountAccessJson(bankId.value, accountId.value, viewId.value, HelperInfoJson(List(counterpartyId.value)))) else None ), HttpCode.`201`(callContext)) } } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala index e52db51d49..8ca40ad23b 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/JSONFactory5.0.0.scala @@ -234,14 +234,18 @@ case class PostConsentRequestJsonV500( time_to_live: Option[Long] ) case class HelperInfoJson( + counterparty_id:List[String] +) + +case class ConsentAccountAccessJson( bank_id:String, account_id:String, view_id:String, - counterparty_id:String + helper_info: HelperInfoJson ) -case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String], helper_info:Option[HelperInfoJson] = None) +case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String], account_access:Option[ConsentAccountAccessJson] = None) case class CreatePhysicalCardJsonV500( card_number: String, diff --git a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala index 961f39fba9..50122feca0 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala @@ -129,9 +129,12 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ createConsentByRequestResponse.code should equal(201) val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV500].jwt - val helperInfo = createConsentByRequestResponse.body.extract[ConsentJsonV500].helper_info - helperInfo.isDefined should equal(true) - + val accountAccess = createConsentByRequestResponse.body.extract[ConsentJsonV500].account_access + accountAccess.isDefined should equal(true) + accountAccess.get.bank_id should equal(fromAccountJson.bank_routing.address) + accountAccess.get.account_id should equal(fromAccountJson.account_routing.address) + accountAccess.get.view_id contains("_VRP-") shouldBe( true) + setPropsValues("consumer_validation_method_for_consent"->"NONE") val requestWhichFails = (v5_1_0_Request / "users").GET val responseWhichFails = makeGetRequest(requestWhichFails, List((s"Consent-JWT", consentJwt))) @@ -183,8 +186,11 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ createConsentByRequestResponse.code should equal(201) val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV500].jwt - val helperInfo = createConsentByRequestResponse.body.extract[ConsentJsonV500].helper_info - helperInfo.isDefined should equal(true) + val accountAccess = createConsentByRequestResponse.body.extract[ConsentJsonV500].account_access + accountAccess.isDefined should equal(true) + accountAccess.get.bank_id should equal(fromAccountJson.bank_routing.address) + accountAccess.get.account_id should equal(fromAccountJson.account_routing.address) + accountAccess.get.view_id contains("_VRP-") shouldBe( true) setPropsValues("consumer_validation_method_for_consent"->"NONE") From 65142f5d98377964ede797284207d98b3488fdad Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 29 Jul 2024 14:23:13 +0200 Subject: [PATCH 20/30] feature/VRP fixed the failed test --- .../src/test/resources/frozen_type_meta_data | Bin 141259 -> 141564 bytes .../api/v5_1_0/VRPConsentRequestTest.scala | 4 ++-- .../scala/code/util/FrozenClassTest.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/test/resources/frozen_type_meta_data b/obp-api/src/test/resources/frozen_type_meta_data index 3f67994246f72756bb6dbc9ecb50d66836d0d0fd..a1a4db202b3ac6500cf58ac785e287327153492d 100644 GIT binary patch delta 1815 zcmZuyYitx%6ux&Y+p@c~ZoAvv?snQPg_Z?e+e%-64_c^zG?aIs(9LA_whZjfY-jG4 zRuIY~hA0uuF|3L)L5v!r2pIzj{xD!-q7V$>henML@YVPO5@TZ2SkIkV9#Q_BJ$uf% z-}%nD=iIsYS;^m5N={`x@Ml|{i>!z0_6H-Jc!n77GxStW;hcEy{DB)a4e(EGqfgkn zb%@I7}|xQ%2rOMBB-Oo&Gv_3pfWto=YSQgX@9i2)UkBuOs->cPD=39YCX+NM_p$! z164O#7x4@yao9UA2wF#=4D;Q^+61Ys#YIM7RonDEoYbRh$!IpMDk>J1(>OD-vcXkm z_UOhUMG>Z9vYV6(5fB1Pbt}3ys19Mj3N&SHJ14go7TUu}^xoKGU1Q5q0_joAUtTEd zPU&J@!YJVf-}Llrwb$27(}Q(Lmk2Ng{-%V zNyE{~$2=k|E5tC|sFZBb{SXfI(G#GCX3~B*9Ez0*zbu3z#1Z%=^mx&6PQqeJ=qQwV zTj&|+^6s;bZ-Oh{r){ktm~Vlt4Ol0AhaJj0p{Mjq+o)KbWfiVA0XdGXG1!Q{orzh+ zh6y9iM8IZmk9W78PBVK-g-?Tb{jreH_Hj}s8Z8?sF#%n8v(|NgDJ>FCm@NMsUhb%K z(I9-#v5p=Bf2Uk6V~6Eb>WMK0yNiqAq?;oSdP)*|5yqq7nIBpIDvqUd zY7Lip&c2h^ap@deFH5O*i!_JNUEp@)J^^Goz9kx0d76pDCS>MEp(ol*6EGURRQxO_ zHCPS2)+)i)>T`4x)JuD9K2O3M(qei6CZub4E0=0!cm?8SyakNU%YV@TJW#t9cc&Qt zi!N{y8DjZKPQ!4#cB7541?uZI&_mYFx`VX%Q#*h|Rtnk9i&n$*E=mtuYQ0A33)UAi zo}nJVy+pi4=`^gIS#2F`XrNSv_ZlbR>Z}EV0gX9p<1pxo$BM}=K`aFa;tS~!I3Mq| z(VwzvXK$u-!rC<_;|#)XYhvz3N8JM(68q`z)>nyHl#WAD(+^aGiKgu(Su9Vi1q>uA z!Dx=sVe7f(OH|sAqmg21##v$8x@A+5Q%n$=4F?|j$V$yCrSvT@TQe@|hik39uqIp= zc2(Gy;oDI}2x$~N#WO+s;Q4TzehlZrP4p`K8qQaKEqvb!@x2hcIGH7`<#eP1tg1eG z9f~3e_m9H$6LduS=?!=>GUy){22BW@N(tXgI2oygnkqLmMx!oT4g;PRw<}>9q#oX( zQ8?{cF;zrQqGhgad2{|Yy20`<`1$?X8bwdBgq&3qBdy7%WK&`(OJ|v}OdHgfo4S@C zU^Ft#w?Z{}{~B(n+RzqAu6o3pcaxrjilya}vq*)d#~*x8#5vIb*XDflZ?p=e3m%_$ zs|}k}5f@@RBslboH*~Lr;)On+37lPif-Y>&wAwA4!pVKxcHpPS?NAVl~b&<0a~7~pGgDw;>3=1p2a;lx#VB2 CdtrnC delta 1698 zcmZuydu&r>6#q_BpliEFyLEOe>st1}4b0pSy735mu$d{-0YhUT#Ov*4l(qMkd%wb# z7*I3@y+!OldccbZoJVEafqjIeP=DU&tK}7qI6i3J&GB(`V6yM(MK@tZ-X`Xu77K> z6mI%BXd3a1DzUlzl@cjD_cRuMRKB2~>M?XHlhRCkvV0E|NikJ5^tFj$+#WcG6P}R0 zzS8H2NKvesnj*D=OFEm{Mq@-{YfYEl$L!_B}F;AC^RCm!}SfR5*VQA~U4-E6&^;WT>vk2<=W9~TWLtlKDxFNIi5$y&*#_}!`zm-F=XR|1jk98c z;eZr1L~eFpKUCtej;KQ%#|zWvKotgRzMl4_6k$pa)AMRD-QvWe@L?Fnqv02^uXYKH z;Evjh^n5*1kLTSD&LCaQrd6oGgOQ;r?EN;DMmOSZcN6Z6u7nfz#ppJG435-AVWYjP zt{dPR`@4D_;H15{@l|l1lA;OA=G58OW;Os!VrA3qx*6oPca$GP4MJ_BnQ6t835`o! z=p-y}UPSHsK%Nq==$$@Tn$Sn6x}m$78O_lt;F4l`t}s7&rs7-8^Wij}ZXWR6Yuh{H z(Ku^0z?=3t&e0E3G4N6_>TOPy2<4XKK4zr`r>4`{Ci=q^QWdDa>1sVyQ}8%g=nTE)z1TrD*Qx zJrTByK3{>m9(k|&fB6~f9_x?WbLRR0e#hQc{CMvZde9{vg7v5-PtI}xh(>?9jt5WDf` zP;$#T7JtYussCi2i*cSdloF3WKBlgaip=D6muY|Jbpu*Fp|A%^jsF02jTog3PTj!j z9Qij%f"NONE") val requestWhichFails = (v5_1_0_Request / "users").GET @@ -190,7 +190,7 @@ class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ accountAccess.isDefined should equal(true) accountAccess.get.bank_id should equal(fromAccountJson.bank_routing.address) accountAccess.get.account_id should equal(fromAccountJson.account_routing.address) - accountAccess.get.view_id contains("_VRP-") shouldBe( true) + accountAccess.get.view_id contains("_vrp-") shouldBe( true) setPropsValues("consumer_validation_method_for_consent"->"NONE") diff --git a/obp-api/src/test/scala/code/util/FrozenClassTest.scala b/obp-api/src/test/scala/code/util/FrozenClassTest.scala index a529ff9360..a7a7a5b7fd 100644 --- a/obp-api/src/test/scala/code/util/FrozenClassTest.scala +++ b/obp-api/src/test/scala/code/util/FrozenClassTest.scala @@ -53,7 +53,7 @@ class FrozenClassTest extends ServerSetup { } yield { s"$version increased apis: $increasedApis" } - increasedApis should equal(Nil) + increasedApis should equal(Nil) } } From a625fc95cb13b681cd93debf77eaf469706f912b Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 30 Jul 2024 15:05:38 +0200 Subject: [PATCH 21/30] feature/added consenter and outboundAdapterConsenterInfo --- .../MessageDocsSwaggerDefinitions.scala | 33 +++++++++++++++++- .../main/scala/code/api/util/ApiSession.scala | 1 + .../scala/code/api/util/ConsentUtil.scala | 3 +- .../StoredProcedureConnector_vDec2019.scala | 10 +++--- .../RestConnector_vMar2019_frozen_meta_data | Bin 114769 -> 114868 bytes .../commons/model/CommonModel.scala | 1 + 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/MessageDocsSwaggerDefinitions.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/MessageDocsSwaggerDefinitions.scala index 6fbd7001e4..57f2e9c60c 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/MessageDocsSwaggerDefinitions.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/MessageDocsSwaggerDefinitions.scala @@ -79,13 +79,44 @@ object MessageDocsSwaggerDefinitions emailAddress = emailExample.value, name = usernameExample.value ))))))) + + val outboundAdapterConsenterInfo = OutboundAdapterAuthInfo( + userId = Some(userIdExample.value), + username = Some(usernameExample.value), + linkedCustomers = Some(List(BasicLinkedCustomer(customerIdExample.value,customerNumberExample.value,legalNameExample.value))), + userAuthContext = Some(List(BasicUserAuthContext(keyExample.value,valueExample.value))), //be set by obp from some endpoints. + authViews = Some(List(AuthView( + view = ViewBasic( + id = viewIdExample.value, + name = viewNameExample.value, + description = viewDescriptionExample.value, + ), + account = AccountBasic( + id = accountIdExample.value, + accountRoutings =List(AccountRouting( + scheme = accountRoutingSchemeExample.value, + address = accountRoutingAddressExample.value + )), + customerOwners = List(InternalBasicCustomer( + bankId = bankIdExample.value, + customerId = customerIdExample.value, + customerNumber = customerNumberExample.value, + legalName = legalNameExample.value, + dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + )), + userOwners = List(InternalBasicUser( + userId = userIdExample.value, + emailAddress = emailExample.value, + name = usernameExample.value + ))))))) val outboundAdapterCallContext = OutboundAdapterCallContext( correlationIdExample.value, Some(sessionIdExample.value), Some(consumerIdExample.value), generalContext = Some(List(BasicGeneralContext(keyExample.value,valueExample.value))), - Some(outboundAdapterAuthInfo) + Some(outboundAdapterAuthInfo), + Some(outboundAdapterConsenterInfo) ) val inboundAdapterCallContext = InboundAdapterCallContext( diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala index 2dd1c53783..b8f250fdc4 100644 --- a/obp-api/src/main/scala/code/api/util/ApiSession.scala +++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala @@ -30,6 +30,7 @@ case class CallContext( dauthResponseHeader: Option[String] = None, spelling: Option[String] = None, user: Box[User] = Empty, + consenter: Box[User] = Empty, consumer: Box[Consumer] = Empty, ipAddress: String = "", resourceDocument: Option[ResourceDoc] = None, diff --git a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala index 1b8781fe0c..010e06947f 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -507,7 +507,8 @@ object Consent extends MdcLoggable { case Full(storedConsent) => // Set Consumer into Call Context val consumer = getCurrentConsumerViaMtls(callContext) - val updatedCallContext = callContext.copy(consumer = consumer) + val user = Users.users.vend.getUserByUserId(storedConsent.userId) + val updatedCallContext = callContext.copy(consumer = consumer).copy(consenter = user) // This function MUST be called only once per call. I.e. it's date dependent val (canBeUsed, currentCounterState) = checkFrequencyPerDay(storedConsent) if(canBeUsed) { diff --git a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala index 72e5c1b98c..0eacbb069c 100644 --- a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala @@ -75,7 +75,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { val connectorName = "stored_procedure_vDec2019" //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2024-07-06T09:03:12Z +// ---------- created on 2024-07-30T13:47:52Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -444,7 +444,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { exampleOutboundMessage = ( OutBoundValidateChallengeAnswerV2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, challengeId=challengeIdExample.value, - suppliedAnswer="string", + suppliedAnswer=suppliedAnswerExample.value, suppliedAnswerType=com.openbankproject.commons.model.enums.SuppliedAnswerType.example) ), exampleInboundMessage = ( @@ -557,7 +557,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { transactionRequestId=Some(transactionRequestIdExample.value), consentId=Some(consentIdExample.value), challengeId=challengeIdExample.value, - suppliedAnswer="string", + suppliedAnswer=suppliedAnswerExample.value, suppliedAnswerType=com.openbankproject.commons.model.enums.SuppliedAnswerType.example) ), exampleInboundMessage = ( @@ -6737,8 +6737,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2024-07-06T09:03:12Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2024-07-30T13:47:52Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data index 58c888c9b584b7451f36312615a919e17f9a5c38..a18469eb1adb5af07e61ce54ca96f9d982b9b3c1 100644 GIT binary patch delta 61 zcmccEz`muCeM8wvMz+c2C$}reEt<(KBAIHn{Pl%y6p=jRot<^dU=d1?72433jO QmTOKvAj7{|`IO!_03HAt+5i9m delta 20 ccmdne$bPYbeM8wvM%KyYC%12&cuM&j0AtSzI{*Lx diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala index 3b869c13b9..b66518b83f 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala @@ -886,6 +886,7 @@ case class OutboundAdapterCallContext( consumerId: Option[String] = None, generalContext: Option[List[BasicGeneralContext]]= None, outboundAdapterAuthInfo: Option[OutboundAdapterAuthInfo] = None, + outboundAdapterConsenterInfo: Option[OutboundAdapterAuthInfo] = None, //Here consentInfo object structure is the same as AuthInfo. so share the same class ) case class BasicGeneralContext( From 305099854a010f03f6e969f105865b76a774cd31 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 31 Jul 2024 14:32:37 +0200 Subject: [PATCH 22/30] refactor/typo --- obp-api/src/main/scala/code/bankconnectors/Connector.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 1e68c3ed21..a4c3ebdc5d 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -521,7 +521,7 @@ trait Connector extends MdcLoggable { * If it is Mapped connector: * OBP will return all the accounts from accountHolder * @param username username of the user. - * @param callContext inside, should contains the proper values for CBS to identify a bank Customer + * @param callContext inside, should contain the proper values for CBS to identify a bank Customer * @return all the accounts, get from Main Frame. */ def getBankAccountsForUser(provider: String, username:String, callContext: Option[CallContext]) : Future[Box[(List[InboundAccount], Option[CallContext])]] = Future{ From 5dd05a61fd5a120507af5abc6d87a6f814478a6e Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 31 Jul 2024 14:32:54 +0200 Subject: [PATCH 23/30] feature/added outboundAdapterConsenterInfo --- obp-api/src/main/scala/code/api/util/ApiSession.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala index b8f250fdc4..e4aa24e911 100644 --- a/obp-api/src/main/scala/code/api/util/ApiSession.scala +++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala @@ -97,7 +97,14 @@ case class CallContext( username = username, linkedCustomers = likedCustomersBasic, userAuthContext = basicUserAuthContexts, - if (authViews.isEmpty) None else Some(authViews))) + if (authViews.isEmpty) None else Some(authViews))), + outboundAdapterConsenterInfo = + if (this.consenter.isDefined){ + Some(OutboundAdapterAuthInfo( + username = this.consenter.toOption.map(_.name)))//TODO, here we may added more field to the consenter, at the moment only username is useful + }else{ + None + } ) }}.openOr(OutboundAdapterCallContext( //For anonymousAccess endpoints, there are no user info this.correlationId, From c904a815fd184aa2832fb945d0c935d06b12fe97 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 31 Jul 2024 15:03:06 +0200 Subject: [PATCH 24/30] refactor/added log for consenter --- obp-api/src/main/scala/code/api/util/ConsentUtil.scala | 1 + .../storedprocedure/StoredProcedureConnector_vDec2019.scala | 2 ++ 2 files changed, 3 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala index 010e06947f..5894dad479 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -508,6 +508,7 @@ object Consent extends MdcLoggable { // Set Consumer into Call Context val consumer = getCurrentConsumerViaMtls(callContext) val user = Users.users.vend.getUserByUserId(storedConsent.userId) + logger.debug(s"applyBerlinGroupConsentRulesCommon.storedConsent.user : $user") val updatedCallContext = callContext.copy(consumer = consumer).copy(consenter = user) // This function MUST be called only once per call. I.e. it's date dependent val (canBeUsed, currentCounterState) = checkFrequencyPerDay(storedConsent) diff --git a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala index 0eacbb069c..b9d7ba4f46 100644 --- a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala @@ -1304,7 +1304,9 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { override def checkBankAccountExists(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { import com.openbankproject.commons.dto.{InBoundCheckBankAccountExists => InBound, OutBoundCheckBankAccountExists => OutBound} + logger.debug(s"StoredProcedureConnector_vDec2019.checkBankAccountExists.callContext : $callContext") val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) + logger.debug(s"StoredProcedureConnector_vDec2019.checkBankAccountExists.req : $req") val response: Future[Box[InBound]] = sendRequest[InBound]("obp_check_bank_account_exists", req, callContext) response.map(convertToTuple[BankAccountCommons](callContext)) } From 53274430868093b7a524b9913d1811d9df4d951a Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 31 Jul 2024 15:37:52 +0200 Subject: [PATCH 25/30] bugfix/added callContext to applyConsentRules method --- obp-api/src/main/scala/code/api/util/ConsentUtil.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala index 5894dad479..73e20cfd4a 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -451,7 +451,7 @@ object Consent extends MdcLoggable { private def applyBerlinGroupConsentRulesCommon(consentId: String, callContext: CallContext): Future[(Box[User], Option[CallContext])] = { implicit val dateFormats = CustomJsonFormats.formats - def applyConsentRules(consent: ConsentJWT): Future[(Box[User], Option[CallContext])] = { + def applyConsentRules(consent: ConsentJWT, callContext: CallContext): Future[(Box[User], Option[CallContext])] = { val cc = callContext // 1. Get or Create a User getOrCreateUser(consent.sub, consent.iss, Some(consent.toConsent().consentId), None, None) map { @@ -526,7 +526,7 @@ object Consent extends MdcLoggable { // Update MappedConsent.usesSoFarTodayCounter field val consentUpdatedBox = Consents.consentProvider.vend.updateBerlinGroupConsent(consentId, currentCounterState + 1) logger.debug(s"applyBerlinGroupConsentRulesCommon.consentUpdatedBox: $consentUpdatedBox") - applyConsentRules(consent) + applyConsentRules(consent, updatedCallContext) case failure@Failure(_, _, _) => // Handled errors Future(failure, Some(updatedCallContext)) case _ => // Unexpected errors From f3e7a16326999712558c2e9decf8d125858c7421 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 2 Aug 2024 16:50:30 +0200 Subject: [PATCH 26/30] bugfix/tweaked BGv1.3 view error messages --- .../api/berlin/group/v1_3/AccountInformationServiceAISApi.scala | 2 +- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala index 223ea3afa4..c6f57b897b 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala @@ -75,7 +75,7 @@ object APIMethods_AccountInformationServiceAISApi extends RestHelper { Future { Helper.booleanToBox(u.hasViewAccess(BankIdAccountId(account.bankId, account.accountId), viewId, callContext)) } map { - unboxFullOrFail(_, callContext, NoViewReadAccountsBerlinGroup + " userId : " + u.userId + ". account : " + account.accountId, 403) + unboxFullOrFail(_, callContext, s"$NoViewReadAccountsBerlinGroup ${viewId.value} userId : ${u.userId}. account : ${account.accountId}", 403) } } diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index d57a556cc3..56149a0053 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -211,7 +211,7 @@ object ErrorMessages { val UserNotFoundByUserId = "OBP-20057: User not found by userId." val ConsumerIsDisabled = "OBP-20058: Consumer is disabled." val CouldNotGetUserLockStatus = "OBP-20059: Could not get the lock status of the user." - val NoViewReadAccountsBerlinGroup = s"OBP-20060: User does not have access to the view $SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID." + val NoViewReadAccountsBerlinGroup = s"OBP-20060: User does not have access to the view:" val FrequencyPerDayError = "OBP-20062: Frequency per day must be greater than 0." val FrequencyPerDayMustBeOneError = "OBP-20063: Frequency per day must be equal to 1 in case of one-off access." From 78c7f3d53251fcabdffabc372973a8da4509ebaf Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 5 Aug 2024 21:58:33 +0200 Subject: [PATCH 27/30] refactor/typo --- .../api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala | 2 +- .../scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala index ed282eaf44..6149cb8301 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala @@ -933,7 +933,7 @@ This applies in the following scenarios: None, callContext ) - //NOTE: in OBP it support multiple challenges, but in Berlin Group it has only one challenge. The following guard is to make sure it return the 1st challenge properly. + //NOTE: in OBP it support multiple challenges, but in Berlin Group it has only one challenge. The following guard is to make sure it returns the 1st challenge properly. challenge <- NewStyle.function.tryons(InvalidConnectorResponseForCreateChallenge, 400, callContext) { challenges.head } diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala index 337484981d..50464a1809 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala @@ -111,7 +111,7 @@ The resource identifications of these transactions are contained in the payload jsonPost.extract[PostSigningBasketJsonV13] } _ <- booleanToFuture(failMsg, cc = callContext) { - // One of them MUST be defined. Otherwise post json is treated as empty one. + // One of them MUST be defined. Otherwise, post json is treated as empty one. !(jsonPost.extract[PostSigningBasketJsonV13].paymentIds.isEmpty && jsonPost.extract[PostSigningBasketJsonV13].consentIds.isEmpty) } From 25b163a295ac8389dd8f99550a7be12e3efd647b Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 6 Aug 2024 12:44:58 +0200 Subject: [PATCH 28/30] refactor/tweaked the challenge logic for authorisationId --- .../group/v1_3/AccountInformationServiceAISApi.scala | 7 ++----- .../berlin/group/v1_3/PaymentInitiationServicePISApi.scala | 5 +++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala index 223ea3afa4..e78ec64676 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala @@ -1256,15 +1256,12 @@ Maybe in a later version the access path will change. updateJson <- NewStyle.function.tryons(failMsg, 400, callContext) { jsonPut.extract[TransactionAuthorisation] } - (challenges, callContext) <- NewStyle.function.getChallengesByConsentId(consentId, callContext) - _ <- NewStyle.function.tryons(s"$AuthorisationNotFound Current AUTHORISATION_ID($authorisationId)", 400, callContext) { - challenges.filter(_.challengeId == authorisationId).size == 1 - } + (_, callContext) <- NewStyle.function.getChallenge(authorisationId, callContext) (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC4( ChallengeType.BERLIN_GROUP_CONSENT_CHALLENGE, None, Some(consentId), - challenges.filter(_.challengeId == authorisationId).head.challengeId, + authorisationId, updateJson.scaAuthenticationData, SuppliedAnswerType.PLAIN_TEXT_VALUE, callContext diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala index ed282eaf44..c4d9e05d64 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala @@ -1447,7 +1447,7 @@ There are the following request types on this access path: ) lazy val updatePaymentPsuDataTransactionAuthorisation : OBPEndpoint = { - case paymentService :: paymentProduct :: paymentId:: "authorisations" :: authorisationid :: Nil JsonPut json -> _ if checkTransactionAuthorisation(json) => { + case paymentService :: paymentProduct :: paymentId:: "authorisations" :: authorisationId :: Nil JsonPut json -> _ if checkTransactionAuthorisation(json) => { cc => for { (Full(u), callContext) <- authenticatedAccess(cc) @@ -1469,11 +1469,12 @@ There are the following request types on this access path: _ <- Helper.booleanToFuture(failMsg= CannotUpdatePSUData, cc=callContext) { existingTransactionRequest.status == TransactionRequestStatus.INITIATED.toString } + (_, callContext) <- NewStyle.function.getChallenge(authorisationId, callContext) (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC4( ChallengeType.BERLIN_GROUP_PAYMENT_CHALLENGE, Some(paymentId), None, - authorisationid, + authorisationId, transactionAuthorisationJson.scaAuthenticationData, SuppliedAnswerType.PLAIN_TEXT_VALUE, callContext From ef2e13e9e555cba67beacb9312a4df8d574b6a50 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 6 Aug 2024 17:35:12 +0200 Subject: [PATCH 29/30] bugfix/fixed the SigningBasket paymentIds and consentIds mapping --- .../code/api/util/newstyle/SigningBasketNewStyle.scala | 2 +- .../code/signingbaskets/MappedSigningBasketProvider.scala | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/newstyle/SigningBasketNewStyle.scala b/obp-api/src/main/scala/code/api/util/newstyle/SigningBasketNewStyle.scala index d0ce26305e..624f908239 100644 --- a/obp-api/src/main/scala/code/api/util/newstyle/SigningBasketNewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/newstyle/SigningBasketNewStyle.scala @@ -23,7 +23,7 @@ object SigningBasketNewStyle { basket.flatMap(_.payments.map(_.forall(i => Connector.connector.vend.getTransactionRequestImpl(TransactionRequestId(i), callContext).isDefined))) if (existAll.getOrElse(false)) { Some(true) - } else { // Fail due to unexisting payment + } else { // Fail due to nonexistent payment val paymentIds = basket.flatMap(_.payments).getOrElse(Nil).mkString(",") unboxFullOrFail(Empty, callContext, s"$InvalidConnectorResponse Some of paymentIds [${paymentIds}] are invalid") } diff --git a/obp-api/src/main/scala/code/signingbaskets/MappedSigningBasketProvider.scala b/obp-api/src/main/scala/code/signingbaskets/MappedSigningBasketProvider.scala index eb2ab958c5..b39568d052 100644 --- a/obp-api/src/main/scala/code/signingbaskets/MappedSigningBasketProvider.scala +++ b/obp-api/src/main/scala/code/signingbaskets/MappedSigningBasketProvider.scala @@ -14,11 +14,11 @@ object MappedSigningBasketProvider extends SigningBasketProvider { override def getSigningBasketByBasketId(entityId: String): Box[SigningBasketContent] = { val basket: Box[MappedSigningBasket] = MappedSigningBasket.find(By(MappedSigningBasket.BasketId, entityId)) - val payments = MappedSigningBasketPayment.findAll(By(MappedSigningBasketPayment.BasketId, entityId)).map(_.basketId) match { + val payments = MappedSigningBasketPayment.findAll(By(MappedSigningBasketPayment.BasketId, entityId)).map(_.paymentId) match { case Nil => None case head :: tail => Some(head :: tail) } - val consents = MappedSigningBasketConsent.findAll(By(MappedSigningBasketConsent.BasketId, entityId)).map(_.basketId) match { + val consents = MappedSigningBasketConsent.findAll(By(MappedSigningBasketConsent.BasketId, entityId)).map(_.consentId) match { case Nil => None case head :: tail => Some(head :: tail) } @@ -26,11 +26,11 @@ object MappedSigningBasketProvider extends SigningBasketProvider { } override def saveSigningBasketStatus(entityId: String, status: String): Box[SigningBasketContent] = { val basket: Box[MappedSigningBasket] = MappedSigningBasket.find(By(MappedSigningBasket.BasketId, entityId)).map(_.Status(status).saveMe) - val payments = MappedSigningBasketPayment.findAll(By(MappedSigningBasketPayment.BasketId, entityId)).map(_.basketId) match { + val payments = MappedSigningBasketPayment.findAll(By(MappedSigningBasketPayment.BasketId, entityId)).map(_.paymentId) match { case Nil => None case head :: tail => Some(head :: tail) } - val consents = MappedSigningBasketConsent.findAll(By(MappedSigningBasketConsent.BasketId, entityId)).map(_.basketId) match { + val consents = MappedSigningBasketConsent.findAll(By(MappedSigningBasketConsent.BasketId, entityId)).map(_.consentId) match { case Nil => None case head :: tail => Some(head :: tail) } From 43bb59e9927b4949b65c506b623c5b8e41677d5d Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 7 Aug 2024 13:17:18 +0200 Subject: [PATCH 30/30] feature/added new method getChallengesByBasketId to StoredProcedureConnector_vDec2019 --- .../bankconnectors/ConnectorBuilderUtil.scala | 1 + .../StoredProcedureConnector_vDec2019.scala | 46 +++++++++++++++++-- .../commons/dto/JsonsTransfer.scala | 3 ++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala index 4bf6e97bdd..937fa0e9c3 100644 --- a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala +++ b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala @@ -359,6 +359,7 @@ object ConnectorBuilderUtil { "createDirectDebit", "deleteCustomerAttribute", "getPhysicalCardsForUser", + "getChallengesByBasketId", // The follow methods's parameter or return type are special "getCurrentFxRate", diff --git a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala index b9d7ba4f46..e0954ea6e9 100644 --- a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala @@ -75,7 +75,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { val connectorName = "stored_procedure_vDec2019" //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2024-07-30T13:47:52Z +// ---------- created on 2024-08-07T12:43:02Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -706,6 +706,44 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[List[ChallengeCommons]](callContext)) } + messageDocs += getChallengesByBasketIdDoc + def getChallengesByBasketIdDoc = MessageDoc( + process = "obp.getChallengesByBasketId", + messageFormat = messageFormat, + description = "Get Challenges By Basket Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallengesByBasketId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + basketId=basketIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallengesByBasketId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + basketId=Some(basketIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string"), + attemptCounter=123))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallengesByBasketId(basketId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundGetChallengesByBasketId => InBound, OutBoundGetChallengesByBasketId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, basketId) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_get_challenges_by_basket_id", req, callContext) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + messageDocs += getChallengeDoc def getChallengeDoc = MessageDoc( process = "obp.getChallenge", @@ -1304,9 +1342,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { override def checkBankAccountExists(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { import com.openbankproject.commons.dto.{InBoundCheckBankAccountExists => InBound, OutBoundCheckBankAccountExists => OutBound} - logger.debug(s"StoredProcedureConnector_vDec2019.checkBankAccountExists.callContext : $callContext") val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) - logger.debug(s"StoredProcedureConnector_vDec2019.checkBankAccountExists.req : $req") val response: Future[Box[InBound]] = sendRequest[InBound]("obp_check_bank_account_exists", req, callContext) response.map(convertToTuple[BankAccountCommons](callContext)) } @@ -6739,8 +6775,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2024-07-30T13:47:52Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2024-08-07T12:43:02Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala index d80578a5d6..916be6c834 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala @@ -1431,6 +1431,9 @@ case class InBoundGetChallengesByTransactionRequestId(inboundAdapterCallContext: case class OutBoundGetChallengesByConsentId(outboundAdapterCallContext: OutboundAdapterCallContext, consentId: String) extends TopicTrait case class InBoundGetChallengesByConsentId(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[ChallengeCommons]) extends InBoundTrait[List[ChallengeCommons]] +case class OutBoundGetChallengesByBasketId(outboundAdapterCallContext: OutboundAdapterCallContext, basketId: String) extends TopicTrait +case class InBoundGetChallengesByBasketId(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[ChallengeCommons]) extends InBoundTrait[List[ChallengeCommons]] + case class OutBoundGetCounterpartyByIbanAndBankAccountId(outboundAdapterCallContext: OutboundAdapterCallContext, iban: String, bankId: BankId, accountId: AccountId) extends TopicTrait case class InBoundGetCounterpartyByIbanAndBankAccountId(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: CounterpartyTraitCommons) extends InBoundTrait[CounterpartyTraitCommons]