From 9e93fc72d7c7d4880188ab76e5a8346849c1906d Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 5 Jul 2024 13:39:37 +0200 Subject: [PATCH 1/9] refactor/tweaked the constant variable names --- .../src/main/scala/code/api/constant/constant.scala | 9 ++++++--- .../MigrationOfViewDefinitionPermissions.scala | 10 +++++----- obp-api/src/main/scala/code/views/MapperViews.scala | 12 ++++-------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/obp-api/src/main/scala/code/api/constant/constant.scala b/obp-api/src/main/scala/code/api/constant/constant.scala index 69ac481743..f18b76a2c0 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -61,8 +61,8 @@ object Constant extends MdcLoggable { final val SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID = "ReadBalancesBerlinGroup" final val SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID = "ReadTransactionsBerlinGroup" - //TODO, this need to be double check - final val ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT = + //This is used for the canRevokeAccessToViews_ and canGrantAccessToViews_ fields of SYSTEM_OWNER_VIEW_ID or SYSTEM_STANDARD_VIEW_ID. + final val DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS = SYSTEM_OWNER_VIEW_ID:: SYSTEM_AUDITOR_VIEW_ID:: SYSTEM_ACCOUNTANT_VIEW_ID:: @@ -80,7 +80,10 @@ object Constant extends MdcLoggable { SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID:: SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID :: Nil - final val ALL_SYSTEM_VIEWS_CREATED_FROM_CBS = + //We allow CBS side to generate views by getBankAccountsForUser.viewsToGenerate filed. + // viewsToGenerate can be any views, and OBP will check the following list, to make sure only allowed views are generated + // If some views are not allowed, obp just log it, do not throw exceptions. + final val VIEWS_GENERATED_FROM_CBS_WHITE_LIST = SYSTEM_OWNER_VIEW_ID:: SYSTEM_ACCOUNTANT_VIEW_ID:: SYSTEM_AUDITOR_VIEW_ID:: diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index dd98763de1..0c2fac0cec 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -1,6 +1,6 @@ package code.api.util.migration -import code.api.Constant.{ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT, SYSTEM_OWNER_VIEW_ID, SYSTEM_STANDARD_VIEW_ID} +import code.api.Constant.{DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS, SYSTEM_OWNER_VIEW_ID, SYSTEM_STANDARD_VIEW_ID} import code.api.util.APIUtil import code.api.util.migration.Migration.{DbFunction, saveLog} import code.views.system.ViewDefinition @@ -31,8 +31,8 @@ object MigrationOfViewDefinitionPermissions { .canUpdateCustomView_(false) .canGrantAccessToCustomViews_(false) .canRevokeAccessToCustomViews_(false) - .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) - .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .canGrantAccessToViews_(DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS.mkString(",")) + .canRevokeAccessToViews_(DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS.mkString(",")) .save ) @@ -54,8 +54,8 @@ object MigrationOfViewDefinitionPermissions { .canUpdateCustomView_(false) .canGrantAccessToCustomViews_(false) .canRevokeAccessToCustomViews_(false) - .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) - .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .canGrantAccessToViews_(DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS.mkString(",")) + .canRevokeAccessToViews_(DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS.mkString(",")) .save ) diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 41144c9c57..37e97d0e9c 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -619,14 +619,10 @@ object MapperViews extends Views with MdcLoggable { def getOrCreateSystemViewFromCbs(viewId: String): Box[View] = { logger.debug(s"-->getOrCreateSystemViewFromCbs--- start--${viewId} ") - val ownerView = SYSTEM_OWNER_VIEW_ID.equals(viewId.toLowerCase) - - val theView = if (ownerView) { - getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID) - } else if (ALL_SYSTEM_VIEWS_CREATED_FROM_CBS.contains(viewId)) { + val theView = if (VIEWS_GENERATED_FROM_CBS_WHITE_LIST.contains(viewId)) { getOrCreateSystemView(viewId) } else { - val errorMessage = ViewIdNotSupported + code.api.Constant.ALL_SYSTEM_VIEWS_CREATED_FROM_CBS.mkString(", ") + s"Your input viewId is :$viewId" + val errorMessage = ViewIdNotSupported + code.api.Constant.VIEWS_GENERATED_FROM_CBS_WHITE_LIST.mkString(", ") + s"Your input viewId is :$viewId" logger.error(errorMessage) Failure(errorMessage) } @@ -931,8 +927,8 @@ object MapperViews extends Views with MdcLoggable { .canUpdateBankAccountLabel_(true) .canSeeViewsWithPermissionsForOneUser_(true) .canSeeViewsWithPermissionsForAllUsers_(true) - .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) - .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .canGrantAccessToViews_(DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS.mkString(",")) + .canRevokeAccessToViews_(DEFAULT_CAN_GRANT_AND_REVOKE_ACCESS_TO_VIEWS.mkString(",")) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) From 0faa6c5f34f663a203a7bc3b5d3ee51dd24c288a Mon Sep 17 00:00:00 2001 From: Hongwei Date: Sat, 6 Jul 2024 08:49:32 +0200 Subject: [PATCH 2/9] refactor/added new methods validateChallengeAnswerC4 and validateChallengeAnswerC5 --- .../AccountInformationServiceAISApi.scala | 5 ++-- .../v1_3/PaymentInitiationServicePISApi.scala | 12 ++++---- .../berlin/group/v1_3/SigningBasketsApi.scala | 5 ++-- .../main/scala/code/api/util/NewStyle.scala | 24 ++++++++------- .../scala/code/bankconnectors/Connector.scala | 26 ++++++++++++++-- .../bankconnectors/LocalMappedConnector.scala | 30 +++++++++++++++++++ 6 files changed, 80 insertions(+), 22 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 b2fe2b1f2c..17e79ea189 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 @@ -23,7 +23,7 @@ import code.views.Views import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.model._ -import com.openbankproject.commons.model.enums.{ChallengeType, StrongCustomerAuthentication, StrongCustomerAuthenticationStatus} +import com.openbankproject.commons.model.enums.{ChallengeType, StrongCustomerAuthentication, StrongCustomerAuthenticationStatus, SuppliedAnswerType} import com.openbankproject.commons.util.ApiVersion import net.liftweb.common.{Empty, Full} import net.liftweb.http.js.JE.JsRaw @@ -1259,12 +1259,13 @@ Maybe in a later version the access path will change. _ <- NewStyle.function.tryons(s"$AuthorisationNotFound Current AUTHORISATION_ID($authorisationId)", 400, callContext) { challenges.filter(_.challengeId == authorisationId).size == 1 } - (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC2( + (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC4( ChallengeType.BERLIN_GROUP_CONSENT_CHALLENGE, None, Some(consentId), challenges.filter(_.challengeId == authorisationId).head.challengeId, updateJson.scaAuthenticationData, + SuppliedAnswerType.PLAIN_TEXT_VALUE, callContext ) consent <- challenge.scaStatus match { 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 bce50fbdb1..ed282eaf44 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 @@ -2,9 +2,7 @@ package code.api.builder.PaymentInitiationServicePISApi import code.api.Constant import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.sepaCreditTransfersBerlinGroupV13 -import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{CancelPaymentResponseJson, - CancelPaymentResponseLinks, LinkHrefJson, UpdatePaymentPsuDataJson, checkUpdatePsuAuthentication,checkAuthorisationConfirmation, - checkTransactionAuthorisation, checkSelectPsuAuthenticationMethod, createCancellationTransactionRequestJson} +import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{CancelPaymentResponseJson, CancelPaymentResponseLinks, LinkHrefJson, UpdatePaymentPsuDataJson, checkAuthorisationConfirmation, checkSelectPsuAuthenticationMethod, checkTransactionAuthorisation, checkUpdatePsuAuthentication, createCancellationTransactionRequestJson} import code.api.berlin.group.v1_3.{JSONFactory_BERLIN_GROUP_1_3, JvalueCaseClass, OBP_BERLIN_GROUP_1_3} import code.api.util.APIUtil._ import code.api.util.ApiTag._ @@ -24,7 +22,7 @@ import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.model._ import com.openbankproject.commons.model.enums.ChallengeType.BERLIN_GROUP_PAYMENT_CHALLENGE import com.openbankproject.commons.model.enums.TransactionRequestStatus._ -import com.openbankproject.commons.model.enums.{ChallengeType, StrongCustomerAuthenticationStatus, TransactionRequestStatus} +import com.openbankproject.commons.model.enums.{ChallengeType, StrongCustomerAuthenticationStatus, SuppliedAnswerType, TransactionRequestStatus} import com.openbankproject.commons.util.ApiVersion import net.liftweb import net.liftweb.common.Box.tryo @@ -1227,12 +1225,13 @@ There are the following request types on this access path: existingTransactionRequest.status == TransactionRequestStatus.COMPLETED.toString } (_, callContext) <- NewStyle.function.getTransactionRequestImpl(TransactionRequestId(paymentId), callContext) - (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC2( + (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC4( ChallengeType.BERLIN_GROUP_PAYMENT_CHALLENGE, Some(paymentId), None, authorisationId, transactionAuthorisation.scaAuthenticationData, + SuppliedAnswerType.PLAIN_TEXT_VALUE, callContext ) @@ -1470,12 +1469,13 @@ There are the following request types on this access path: _ <- Helper.booleanToFuture(failMsg= CannotUpdatePSUData, cc=callContext) { existingTransactionRequest.status == TransactionRequestStatus.INITIATED.toString } - (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC2( + (challenge, callContext) <- NewStyle.function.validateChallengeAnswerC4( ChallengeType.BERLIN_GROUP_PAYMENT_CHALLENGE, Some(paymentId), None, authorisationid, transactionAuthorisationJson.scaAuthenticationData, + SuppliedAnswerType.PLAIN_TEXT_VALUE, callContext ) 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 312fc7de8b..337484981d 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 @@ -15,7 +15,7 @@ import code.util.Helper.booleanToFuture import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.model.enums.TransactionRequestStatus.{COMPLETED, REJECTED} -import com.openbankproject.commons.model.enums.{ChallengeType, StrongCustomerAuthenticationStatus} +import com.openbankproject.commons.model.enums.{ChallengeType, StrongCustomerAuthenticationStatus,SuppliedAnswerType} import com.openbankproject.commons.model.{ChallengeTrait, TransactionRequestId} import com.openbankproject.commons.util.ApiVersion import net.liftweb.common.{Box, Empty, Full} @@ -476,13 +476,14 @@ There are the following request types on this access path: } _ <- SigningBasketNewStyle.checkSigningBasketPayments(basketId, callContext) // Validate a challenge answer and get an error if any - (boxedChallenge: Box[ChallengeTrait], callContext) <- NewStyle.function.validateChallengeAnswerC3( + (boxedChallenge: Box[ChallengeTrait], callContext) <- NewStyle.function.validateChallengeAnswerC5( ChallengeType.BERLIN_GROUP_SIGNING_BASKETS_CHALLENGE, None, None, Some(basketId), authorisationId, updateBasketPsuDataJson.scaAuthenticationData, + SuppliedAnswerType.PLAIN_TEXT_VALUE, callContext ) // Get the challenge after validation diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 8932ccb83d..a6b4a7f2d0 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1330,13 +1330,14 @@ object NewStyle extends MdcLoggable{ (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponse() "), i._2) } - //At moment this method is used for Berlin Group Payments - def validateChallengeAnswerC2( + //At moment this method is used for Berlin Group Payments and Consents + def validateChallengeAnswerC4( challengeType: ChallengeType.Value, transactionRequestId: Option[String], consentId: Option[String], - challengeId: String, - hashOfSuppliedAnswer: String, + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext] ): OBPReturnType[ChallengeTrait] = { if(challengeType == ChallengeType.BERLIN_GROUP_PAYMENT_CHALLENGE && transactionRequestId.isEmpty ){ @@ -1344,11 +1345,12 @@ object NewStyle extends MdcLoggable{ }else if(challengeType == ChallengeType.BERLIN_GROUP_CONSENT_CHALLENGE && consentId.isEmpty ){ Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_CONSENT_CHALLENGE challengeType: consentId($consentId) ")} }else{ - Connector.connector.vend.validateChallengeAnswerC2( + Connector.connector.vend.validateChallengeAnswerC4( transactionRequestId: Option[String], consentId: Option[String], challengeId: String, - hashOfSuppliedAnswer: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext] ) map { i => (unboxFullOrFail(i._1, callContext, s"${ @@ -1361,13 +1363,14 @@ object NewStyle extends MdcLoggable{ } //At moment this method is used for Berlin Group SigningBasketsApi.scala - def validateChallengeAnswerC3( + def validateChallengeAnswerC5( challengeType: ChallengeType.Value, transactionRequestId: Option[String], consentId: Option[String], basketId: Option[String], challengeId: String, - hashOfSuppliedAnswer: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext] ): OBPReturnType[Box[ChallengeTrait]] = { if(challengeType == ChallengeType.BERLIN_GROUP_PAYMENT_CHALLENGE && transactionRequestId.isEmpty ){ @@ -1377,12 +1380,13 @@ object NewStyle extends MdcLoggable{ } else if(challengeType == ChallengeType.BERLIN_GROUP_SIGNING_BASKETS_CHALLENGE && basketId.isEmpty ){ Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_CONSENT_CHALLENGE challengeType: basketId($basketId) ")} } else { - Connector.connector.vend.validateChallengeAnswerC3( + Connector.connector.vend.validateChallengeAnswerC5( transactionRequestId: Option[String], consentId: Option[String], basketId: Option[String], challengeId: String, - hashOfSuppliedAnswer: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext] ) } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index a63916fe2c..0cf4f48d2c 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -437,10 +437,10 @@ trait Connector extends MdcLoggable { authenticationMethodId: Option[String], callContext: Option[CallContext]) : OBPReturnType[Box[List[ChallengeTrait]]]= Future{(Failure(setUnimplementedError), callContext)} - // Validates an answer for a challenge and returns if the answer is correct or not @deprecated("Please use @validateChallengeAnswerV2 instead ","01.07.2024") def validateChallengeAnswer(challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = Future{(Full(true), callContext)} + // Validates an answer for a challenge and returns if the answer is correct or not def validateChallengeAnswerV2(challengeId: String, suppliedAnswer: String, suppliedAnswerType:SuppliedAnswerType.Value, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = Future{(Full(true), callContext)} def allChallengesSuccessfullyAnswered( @@ -449,7 +449,8 @@ trait Connector extends MdcLoggable { transReqId: TransactionRequestId, callContext: Option[CallContext] ): OBPReturnType[Box[Boolean]]= Future{(Full(true), callContext)} - + + @deprecated("Please use @validateChallengeAnswerC4 instead ","04.07.2024") def validateChallengeAnswerC2( transactionRequestId: Option[String], consentId: Option[String], @@ -457,6 +458,8 @@ trait Connector extends MdcLoggable { hashOfSuppliedAnswer: String, callContext: Option[CallContext] ): OBPReturnType[Box[ChallengeTrait]] = Future{(Failure(setUnimplementedError), callContext)} + + @deprecated("Please use @validateChallengeAnswerC5 instead ","04.07.2024") def validateChallengeAnswerC3( transactionRequestId: Option[String], consentId: Option[String], @@ -465,6 +468,25 @@ trait Connector extends MdcLoggable { hashOfSuppliedAnswer: String, callContext: Option[CallContext] ): OBPReturnType[Box[ChallengeTrait]] = Future{(Failure(setUnimplementedError), callContext)} + + def validateChallengeAnswerC4( + transactionRequestId: Option[String], + consentId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, + callContext: Option[CallContext] + ): OBPReturnType[Box[ChallengeTrait]] = Future{(Failure(setUnimplementedError), callContext)} + + def validateChallengeAnswerC5( + transactionRequestId: Option[String], + consentId: Option[String], + basketId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, + callContext: Option[CallContext] + ): OBPReturnType[Box[ChallengeTrait]] = Future{(Failure(setUnimplementedError), callContext)} def getChallengesByTransactionRequestId(transactionRequestId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = Future{(Failure(setUnimplementedError), callContext)} diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 128c26d595..9488f6bca3 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -474,6 +474,36 @@ object LocalMappedConnector extends Connector with MdcLoggable { (Challenges.ChallengeProvider.vend.validateChallenge(challengeId, hashOfSuppliedAnswer, userId), callContext) } } + + + override def validateChallengeAnswerC4( + transactionRequestId: Option[String], + consentId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, + callContext: Option[CallContext] + ) = Future { + Future { + val userId = callContext.map(_.user.map(_.userId).openOrThrowException(s"$UserNotLoggedIn Can not find the userId here.")) + (Challenges.ChallengeProvider.vend.validateChallenge(challengeId, suppliedAnswer, userId), callContext) + } + } + + override def validateChallengeAnswerC5( + transactionRequestId: Option[String], + consentId: Option[String], + basketId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType.Value, + callContext: Option[CallContext] + ) = Future { + Future { + val userId = callContext.map(_.user.map(_.userId).openOrThrowException(s"$UserNotLoggedIn Can not find the userId here.")) + (Challenges.ChallengeProvider.vend.validateChallenge(challengeId, suppliedAnswer, userId), callContext) + } + } override def getChallengesByTransactionRequestId(transactionRequestId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = Future {(Challenges.ChallengeProvider.vend.getChallengesByTransactionRequestId(transactionRequestId), callContext)} From a2809f1ed1fb2684b89f25a90a887264d8b76ab2 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Sat, 6 Jul 2024 09:05:47 +0200 Subject: [PATCH 3/9] test/added new methods validateChallengeAnswerC4 and validateChallengeAnswerC5 for StoredProcedureConnector_vDec2019 --- .../bankconnectors/ConnectorBuilderUtil.scala | 2 + .../StoredProcedureConnector_vDec2019.scala | 91 ++++++++++++++++++- .../commons/dto/JsonsTransfer.scala | 31 +++++++ 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala index 95d7d4ed9f..4bf6e97bdd 100644 --- a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala +++ b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala @@ -373,6 +373,8 @@ object ConnectorBuilderUtil { "validateAndCheckIbanNumber", "validateChallengeAnswerC2", "validateChallengeAnswerC3", + "validateChallengeAnswerC4", + "validateChallengeAnswerC5", "validateChallengeAnswerV2", "getCounterpartyByIbanAndBankAccountId", ).distinct 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 b5468c3e7b..f66ac6469b 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-01T13:40:08Z +// ---------- created on 2024-07-06T09:03:12Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -545,6 +545,91 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[ChallengeCommons](callContext)) } + messageDocs += validateChallengeAnswerC4Doc + def validateChallengeAnswerC4Doc = MessageDoc( + process = "obp.validateChallengeAnswerC4", + messageFormat = messageFormat, + description = "Validate Challenge Answer C4", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateChallengeAnswerC4(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=Some(transactionRequestIdExample.value), + consentId=Some(consentIdExample.value), + challengeId=challengeIdExample.value, + suppliedAnswer="string", + suppliedAnswerType=com.openbankproject.commons.model.enums.SuppliedAnswerType.example) + ), + exampleInboundMessage = ( + InBoundValidateChallengeAnswerC4(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= 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 validateChallengeAnswerC4(transactionRequestId: Option[String], consentId: Option[String], challengeId: String, suppliedAnswer: String, suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswerC4 => InBound, OutBoundValidateChallengeAnswerC4 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId, consentId, challengeId, suppliedAnswer, suppliedAnswerType) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_validate_challenge_answer_c4", req, callContext) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + + messageDocs += validateChallengeAnswerC5Doc + def validateChallengeAnswerC5Doc = MessageDoc( + process = "obp.validateChallengeAnswerC5", + messageFormat = messageFormat, + description = "Validate Challenge Answer C5", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateChallengeAnswerC5(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=Some(transactionRequestIdExample.value), + consentId=Some(consentIdExample.value), + basketId=Some(basketIdExample.value), + challengeId=challengeIdExample.value, + hashOfSuppliedAnswer=hashOfSuppliedAnswerExample.value, + suppliedAnswerType=com.openbankproject.commons.model.enums.SuppliedAnswerType.example) + ), + exampleInboundMessage = ( + InBoundValidateChallengeAnswerC5(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= 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 validateChallengeAnswerC5(transactionRequestId: Option[String], consentId: Option[String], basketId: Option[String], challengeId: String, suppliedAnswer: String, suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswerC5 => InBound, OutBoundValidateChallengeAnswerC5 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId, consentId, basketId, challengeId, suppliedAnswer, suppliedAnswerType) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_validate_challenge_answer_c5", req, callContext) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + messageDocs += getChallengesByTransactionRequestIdDoc def getChallengesByTransactionRequestIdDoc = MessageDoc( process = "obp.getChallengesByTransactionRequestId", @@ -6652,8 +6737,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2024-07-01T13:40:08Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2024-07-06T09:03:12Z +//---------------- 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 bb1b3f63fa..d80578a5d6 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 @@ -1381,6 +1381,37 @@ case class OutBoundValidateChallengeAnswerC3( hashOfSuppliedAnswer: String ) extends TopicTrait +case class OutBoundValidateChallengeAnswerC4( + outboundAdapterCallContext: OutboundAdapterCallContext, + transactionRequestId: Option[String], + consentId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType +) extends TopicTrait + +case class OutBoundValidateChallengeAnswerC5( + outboundAdapterCallContext: OutboundAdapterCallContext, + transactionRequestId: Option[String], + consentId: Option[String], + basketId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType, +) extends TopicTrait + +case class InBoundValidateChallengeAnswerC4( + inboundAdapterCallContext: InboundAdapterCallContext, + status: Status, + data: ChallengeCommons +) extends InBoundTrait[ChallengeCommons] + +case class InBoundValidateChallengeAnswerC5( + inboundAdapterCallContext: InboundAdapterCallContext, + status: Status, + data: ChallengeCommons +) extends InBoundTrait[ChallengeCommons] + case class InBoundValidateChallengeAnswerC2(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: ChallengeCommons) extends InBoundTrait[ChallengeCommons] case class InBoundValidateChallengeAnswerC3(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: ChallengeCommons) extends InBoundTrait[ChallengeCommons] From 9e0bdf0213e3ee74cec2255e4533bab80ada9652 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Sat, 6 Jul 2024 09:05:47 +0200 Subject: [PATCH 4/9] test/added new methods validateChallengeAnswerC4 and validateChallengeAnswerC5 for StoredProcedureConnector_vDec2019 --- .../scala/code/api/util/ExampleValue.scala | 3 + .../bankconnectors/ConnectorBuilderUtil.scala | 2 + .../StoredProcedureConnector_vDec2019.scala | 91 ++++++++++++++++++- .../commons/dto/JsonsTransfer.scala | 31 +++++++ 4 files changed, 124 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index e931599cf1..b96aeb5541 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -241,6 +241,9 @@ object ExampleValue { lazy val hashOfSuppliedAnswerExample = ConnectorField(HashUtil.Sha256Hash("123"), s"Sha256 hash value of the ChallengeAnswer.challengeId") glossaryItems += makeGlossaryItem("ChallengeAnswer.hashOfSuppliedAnswer", hashOfSuppliedAnswerExample) + + lazy val suppliedAnswerExample = ConnectorField("123456", s"The value of the ChallengeAnswer.challengeId") + glossaryItems += makeGlossaryItem("ChallengeAnswer.suppliedAnswerExample", suppliedAnswerExample) lazy val gitCommitExample = ConnectorField("59623811dd8a41f6ffe67be46954eee11913dc28", "Identifies the code running on the OBP-API (Connector) or Adapter.") diff --git a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala index 95d7d4ed9f..4bf6e97bdd 100644 --- a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala +++ b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala @@ -373,6 +373,8 @@ object ConnectorBuilderUtil { "validateAndCheckIbanNumber", "validateChallengeAnswerC2", "validateChallengeAnswerC3", + "validateChallengeAnswerC4", + "validateChallengeAnswerC5", "validateChallengeAnswerV2", "getCounterpartyByIbanAndBankAccountId", ).distinct 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 b5468c3e7b..0454246b55 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-01T13:40:08Z +// ---------- created on 2024-07-06T09:03:12Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -545,6 +545,91 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[ChallengeCommons](callContext)) } + messageDocs += validateChallengeAnswerC4Doc + def validateChallengeAnswerC4Doc = MessageDoc( + process = "obp.validateChallengeAnswerC4", + messageFormat = messageFormat, + description = "Validate Challenge Answer C4", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateChallengeAnswerC4(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=Some(transactionRequestIdExample.value), + consentId=Some(consentIdExample.value), + challengeId=challengeIdExample.value, + suppliedAnswer=suppliedAnswerExample.value, + suppliedAnswerType=com.openbankproject.commons.model.enums.SuppliedAnswerType.example) + ), + exampleInboundMessage = ( + InBoundValidateChallengeAnswerC4(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= 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 validateChallengeAnswerC4(transactionRequestId: Option[String], consentId: Option[String], challengeId: String, suppliedAnswer: String, suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswerC4 => InBound, OutBoundValidateChallengeAnswerC4 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId, consentId, challengeId, suppliedAnswer, suppliedAnswerType) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_validate_challenge_answer_c4", req, callContext) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + + messageDocs += validateChallengeAnswerC5Doc + def validateChallengeAnswerC5Doc = MessageDoc( + process = "obp.validateChallengeAnswerC5", + messageFormat = messageFormat, + description = "Validate Challenge Answer C5", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateChallengeAnswerC5(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=Some(transactionRequestIdExample.value), + consentId=Some(consentIdExample.value), + basketId=Some(basketIdExample.value), + challengeId=challengeIdExample.value, + suppliedAnswer=suppliedAnswerExample.value, + suppliedAnswerType=com.openbankproject.commons.model.enums.SuppliedAnswerType.example) + ), + exampleInboundMessage = ( + InBoundValidateChallengeAnswerC5(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= 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 validateChallengeAnswerC5(transactionRequestId: Option[String], consentId: Option[String], basketId: Option[String], challengeId: String, suppliedAnswer: String, suppliedAnswerType: SuppliedAnswerType.Value, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswerC5 => InBound, OutBoundValidateChallengeAnswerC5 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId, consentId, basketId, challengeId, suppliedAnswer, suppliedAnswerType) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_validate_challenge_answer_c5", req, callContext) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + messageDocs += getChallengesByTransactionRequestIdDoc def getChallengesByTransactionRequestIdDoc = MessageDoc( process = "obp.getChallengesByTransactionRequestId", @@ -6652,8 +6737,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2024-07-01T13:40:08Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2024-07-06T09:03:12Z +//---------------- 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 bb1b3f63fa..d80578a5d6 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 @@ -1381,6 +1381,37 @@ case class OutBoundValidateChallengeAnswerC3( hashOfSuppliedAnswer: String ) extends TopicTrait +case class OutBoundValidateChallengeAnswerC4( + outboundAdapterCallContext: OutboundAdapterCallContext, + transactionRequestId: Option[String], + consentId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType +) extends TopicTrait + +case class OutBoundValidateChallengeAnswerC5( + outboundAdapterCallContext: OutboundAdapterCallContext, + transactionRequestId: Option[String], + consentId: Option[String], + basketId: Option[String], + challengeId: String, + suppliedAnswer: String, + suppliedAnswerType: SuppliedAnswerType, +) extends TopicTrait + +case class InBoundValidateChallengeAnswerC4( + inboundAdapterCallContext: InboundAdapterCallContext, + status: Status, + data: ChallengeCommons +) extends InBoundTrait[ChallengeCommons] + +case class InBoundValidateChallengeAnswerC5( + inboundAdapterCallContext: InboundAdapterCallContext, + status: Status, + data: ChallengeCommons +) extends InBoundTrait[ChallengeCommons] + case class InBoundValidateChallengeAnswerC2(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: ChallengeCommons) extends InBoundTrait[ChallengeCommons] case class InBoundValidateChallengeAnswerC3(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: ChallengeCommons) extends InBoundTrait[ChallengeCommons] From 108d7d2dc1408e725020baa36ea066e90856f635 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 10 Jul 2024 11:17:56 +0200 Subject: [PATCH 5/9] refactor/added more debug log for code.api.util.JwtUtil.getSignedPayloadAsJson method --- .../main/scala/code/api/util/ConsentUtil.scala | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 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 e78704fe30..12d9350307 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -500,9 +500,18 @@ object Consent extends MdcLoggable { Future(Failure(ErrorMessages.ConsentCheckExpiredIssue), Some(updatedCallContext)) } } catch { // Possible exceptions - case e: ParseException => Future(Failure("ParseException: " + e.getMessage), Some(updatedCallContext)) - case e: MappingException => Future(Failure("MappingException: " + e.getMessage), Some(updatedCallContext)) - case e: Exception => Future(Failure("parsing failed: " + e.getMessage), Some(updatedCallContext)) + case e: ParseException => { + logger.debug(s"code.api.util.JwtUtil.getSignedPayloadAsJson.ParseException: $e") + Future(Failure("ParseException: " + e.getMessage), Some(updatedCallContext)) + } + case e: MappingException => { + logger.debug(s"code.api.util.JwtUtil.getSignedPayloadAsJson.MappingException: $e") + Future(Failure("MappingException: " + e.getMessage), Some(updatedCallContext)) + } + case e: Throwable => { + logger.debug(s"code.api.util.JwtUtil.getSignedPayloadAsJson.Throwable: $e") + Future(Failure("parsing failed: " + e.getMessage), Some(updatedCallContext)) + } } case failure@Failure(_, _, _) => Future(failure, Some(updatedCallContext)) From 6024b8f81cce35b0027d3526480780ecfd41f585 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 11 Jul 2024 17:28:20 +0200 Subject: [PATCH 6/9] refactor/OBPv510 added new endpoint createVPRConsentRequest --- .../SwaggerDefinitionsJSON.scala | 35 +++++++-- .../scala/code/api/util/ExampleValue.scala | 46 ++++++++++++ .../scala/code/api/v5_0_0/APIMethods500.scala | 18 +++-- .../scala/code/api/v5_1_0/APIMethods510.scala | 71 ++++++++++++++++++- .../code/api/v5_1_0/JSONFactory5.1.0.scala | 39 +++++++++- .../api/v5_1_0/CounterpartyLimitTest.scala | 1 + 6 files changed, 197 insertions(+), 13 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 6a1c916465..d8e6e36f13 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 @@ -1529,7 +1529,7 @@ object SwaggerDefinitionsJSON { from_person = "String" ) - val branchRoutingJSON = BranchRoutingJsonV141( + val branchRoutingJsonV141 = BranchRoutingJsonV141( scheme = "BranchNumber", address = "678" ) @@ -1542,7 +1542,7 @@ object SwaggerDefinitionsJSON { lobby = lobbyJson, drive_up = driveUpJson, meta = metaJson, - branch_routing = branchRoutingJSON + branch_routing = branchRoutingJsonV141 ) @@ -3229,7 +3229,7 @@ object SwaggerDefinitionsJSON { meta = metaJson, lobby = lobbyJson, drive_up = driveUpJson, - branch_routing = branchRoutingJSON + branch_routing = branchRoutingJsonV141 ) @@ -3820,7 +3820,7 @@ object SwaggerDefinitionsJSON { account_id =accountIdExample.value , account_type ="330", account_routings = List(accountRoutingJsonV121), - branch_routings = List(branchRoutingJSON) + branch_routings = List(branchRoutingJsonV141) ) val checkbookOrdersJson = CheckbookOrdersJson( @@ -5205,6 +5205,12 @@ object SwaggerDefinitionsJSON { consumer_id = consumerIdExample.value ) + val vrpConsentRequestResponseJson = ConsentRequestResponseJson( + consent_request_id = consentRequestIdExample.value, + payload = json.parse(vrpConsentRequestPayloadExample.value), + consumer_id = consumerIdExample.value + ) + val consentJsonV500 = ConsentJsonV500( consent_id = "9d429899-24f5-42c8-8565-943ffa6a7945", jwt = "eyJhbGciOiJIUzI1NiJ9.eyJlbnRpdGxlbWVudHMiOltdLCJjcmVhdGVkQnlVc2VySWQiOiJhYjY1MzlhOS1iMTA1LTQ0ODktYTg4My0wYWQ4ZDZjNjE2NTciLCJzdWIiOiIyMWUxYzhjYy1mOTE4LTRlYWMtYjhlMy01ZTVlZWM2YjNiNGIiLCJhdWQiOiJlanpuazUwNWQxMzJyeW9tbmhieDFxbXRvaHVyYnNiYjBraWphanNrIiwibmJmIjoxNTUzNTU0ODk5LCJpc3MiOiJodHRwczpcL1wvd3d3Lm9wZW5iYW5rcHJvamVjdC5jb20iLCJleHAiOjE1NTM1NTg0OTksImlhdCI6MTU1MzU1NDg5OSwianRpIjoiMDlmODhkNWYtZWNlNi00Mzk4LThlOTktNjYxMWZhMWNkYmQ1Iiwidmlld3MiOlt7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAxIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifSx7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAyIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifV19.8cc7cBEf2NyQvJoukBCmDLT7LXYcuzTcSYLqSpbxLp4", @@ -5226,6 +5232,26 @@ object SwaggerDefinitionsJSON { valid_from = Some(new Date()), time_to_live = Some(3600) ) + + val consentRequestFromAccountJson = ConsentRequestFromAccountJson ( + bank_routing = bankRoutingJsonV121, + account_routing = accountRoutingJsonV121, + branch_routing = branchRoutingJsonV141 + ) + + val consentRequestToAccountJson = ConsentRequestToAccountJson ( + bank_routing = bankRoutingJsonV121, + account_routing = accountRoutingJsonV121, + branch_routing = branchRoutingJsonV141, + limit = postCounterpartyLimitV510 + ) + + val postConsentRequestJsonV510 = PostConsentRequestJsonV510( + from_account = consentRequestFromAccountJson, + to_account = consentRequestToAccountJson, + valid_from = Some(new Date()), + time_to_live = Some(3600) + ) val createPhysicalCardJsonV500 = CreatePhysicalCardJsonV500( card_number = bankCardNumberExample.value, @@ -5428,6 +5454,7 @@ object SwaggerDefinitionsJSON { ) val postCounterpartyLimitV510 = PostCounterpartyLimitV510( + currency = currencyExample.value, max_single_amount = maxSingleAmountExample.value.toInt, max_monthly_amount = maxMonthlyAmountExample.value.toInt, max_number_of_monthly_transactions = maxNumberOfMonthlyTransactionsExample.value.toInt, diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index b96aeb5541..c081095678 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -1519,7 +1519,53 @@ object ExampleValue { "The whole create consent request json body." ) + lazy val vrpConsentRequestPayloadExample = ConnectorField( + s"""{ + | "from_account": { + | "bank_routing": { + | "scheme": "BIC", + | "address": "ABCDED" + | }, + | "account_routing": { + | "scheme": "AccountNumber", + | "address": "4930396" + | }, + | "branch_routing": { + | "scheme": "", + | "address": "" + | } + | }, + | "to_account": { + | "bank_routing": { + | "scheme": "BIC", + | "address": "DDFFFF" + | }, + | "account_routing": { + | "scheme": "AccountNumber", + | "address": "123567" + | }, + | "branch_routing": { + | "scheme": "", + | "address": "" + | }, + | "limit": { + | "currency": "EUR", + | "max_single_amount": 1000, + | "max_monthly_amount": 10000, + | "max_number_of_monthly_transactions": 10, + | "max_yearly_amount": 12000, + | "max_number_of_yearly_transactions": 100 + | } + | }, + | "valid_from": "2024-07-10T09:22:06Z", + | "time_to_live": 3600 + |} + |""".stripMargin, + "The whole create consent request json body." + ) + glossaryItems += makeGlossaryItem("payload", consentRequestPayloadExample) + glossaryItems += makeGlossaryItem("vrp_consent_request.payload", vrpConsentRequestPayloadExample) lazy val consentRequestIdExample = ConnectorField ( "8ca8a7e4-6d02-40e3-a129-0b2bf89de9f0", 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 7f55f50101..ac57b988a5 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 @@ -1,7 +1,6 @@ package code.api.v5_0_0 import java.util.concurrent.ThreadLocalRandom - import code.accountattribute.AccountAttributeX import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ @@ -45,6 +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.PostConsentRequestJsonV510 import code.consumer.Consumers import code.util.Helper.booleanToFuture import code.views.system.{AccountAccess, ViewDefinition} @@ -927,10 +927,18 @@ trait APIMethods500 { _ <- Helper.booleanToFuture(ConsentAllowedScaMethods, cc=callContext){ List(StrongCustomerAuthentication.SMS.toString(), StrongCustomerAuthentication.EMAIL.toString(), StrongCustomerAuthentication.IMPLICIT.toString()).exists(_ == scaMethod) } - failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentBodyCommonJson " - consentRequestJson <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.parse(createdConsentRequest.payload).extract[PostConsentRequestJsonV500] - } + consentRequestJson <- + if(createdConsentRequest.payload.contains("to_account")) { + val failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentBodyCommonJson " + 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 " + NewStyle.function.tryons(failMsg, 400, callContext) { + json.parse(createdConsentRequest.payload).extract[PostConsentRequestJsonV500] + } + } 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_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 721fe5a14a..d211bb9344 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 @@ -21,14 +21,15 @@ import code.api.v2_1_0.{ConsumerRedirectUrlJSON, JSONFactory210} import code.api.v2_2_0.JSONFactory220 import code.api.v3_0_0.JSONFactory300 import code.api.v3_0_0.JSONFactory300.createAggregateMetricJson -import code.api.v3_1_0.ConsentJsonV310 +import code.api.v3_1_0.{ConsentJsonV310, PostConsentBodyCommonJson} import code.api.v3_1_0.JSONFactory310.createBadLoginStatusJson import code.api.v4_0_0.JSONFactory400.{createAccountBalancesJson, createBalancesJson, createNewCoreBankAccountJson} import code.api.v4_0_0.{JSONFactory400, PostAccountAccessJsonV400, PostApiCollectionJson400, RevokedJsonV400} +import code.api.v5_0_0.{JSONFactory500, PostConsentRequestJsonV500} import code.api.v5_1_0.JSONFactory510.{createRegulatedEntitiesJson, createRegulatedEntityJson} import code.atmattribute.AtmAttribute import code.bankconnectors.Connector -import code.consent.Consents +import code.consent.{ConsentRequests, Consents} import code.loginattempts.LoginAttempt import code.metrics.APIMetrics import code.model.{AppType, BankAccountX} @@ -2718,7 +2719,71 @@ trait APIMethods510 { } } } - + + + + staticResourceDocs += ResourceDoc( + createVPRConsentRequest, + implementedInApiVersion, + nameOf(createVPRConsentRequest), + "POST", + "/consumer/vrp-consent-requests", + "Create VPR Consent Request", + s""" + |Client Authentication (mandatory) + | + |It is used when applications request an access token to access their own resources, not on behalf of a user. + | + |The client needs to authenticate themselves for this request. + |In case of public client we use client_id and private kew to obtain access token, otherwise we use client_id and client_secret. + |The obtained access token is used in the HTTP Bearer auth header of our request. + | + |Example: + |Authorization: Bearer eXtneO-THbQtn3zvK_kQtXXfvOZyZFdBCItlPDbR2Bk.dOWqtXCtFX-tqGTVR0YrIjvAolPIVg7GZ-jz83y6nA0 + | + |""".stripMargin, + postConsentRequestJsonV510, + vrpConsentRequestResponseJson, + List( + InvalidJsonFormat, + ConsentMaxTTL, + X509CannotGetCertificate, + X509GeneralError, + InvalidConnectorResponse, + UnknownError + ), + apiTagConsent :: apiTagPSD2AIS :: apiTagPsd2 :: Nil + ) + + lazy val createVPRConsentRequest : OBPEndpoint = { + case "consumer" :: "vrp-consent-requests" :: Nil JsonPost json -> _ => { + 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] + } + 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 + } + } + createdConsentRequest <- Future(ConsentRequests.consentRequestProvider.vend.createConsentRequest( + callContext.flatMap(_.consumer), + Some(compactRender(json)) + )) map { + i => connectorEmptyResponse(i, callContext) + } + } yield { + (JSONFactory500.createConsentRequestResponseJson(createdConsentRequest), HttpCode.`201`(callContext)) + } + } + } + } } 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 a7c047658f..f7f83d5870 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 @@ -29,16 +29,18 @@ package code.api.v5_1_0 import code.api.Constant import code.api.util.{APIUtil, ConsentJWT, CustomJsonFormats, JwtUtil, Role} import code.api.util.APIUtil.{gitCommit, stringOrNull} +import code.api.v1_2_1.BankRoutingJsonV121 import code.api.v1_4_0.JSONFactory1_4_0.{LocationJsonV140, MetaJsonV140, transformToLocationFromV140, transformToMetaFromV140} 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.atmattribute.AtmAttribute import code.atms.Atms.Atm import code.users.{UserAttribute, Users} import code.views.system.{AccountAccess, ViewDefinition} -import com.openbankproject.commons.model.{Address, AtmId, AtmT, BankId, BankIdAccountId, CreateViewJson, Customer, Location, Meta, RegulatedEntityTrait, UpdateViewJSON, View} +import com.openbankproject.commons.model.{AccountRoutingJsonV121, Address, AtmId, AtmT, BankId, BankIdAccountId, BranchRoutingJsonV141, CreateViewJson, Customer, Location, Meta, RegulatedEntityTrait, UpdateViewJSON, View} import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} import java.util.Date @@ -161,6 +163,7 @@ case class PostAtmJsonV510 ( ) case class PostCounterpartyLimitV510( + currency: String, max_single_amount: Int, max_monthly_amount: Int, max_number_of_monthly_transactions: Int, @@ -382,6 +385,40 @@ case class CustomViewJsonV510( allowed_permissions: List[String] ) +case class ConsentRequestFromAccountJson( + bank_routing: BankRoutingJsonV121, + account_routing: AccountRoutingJsonV121, + branch_routing: BranchRoutingJsonV141 +) + +case class ConsentRequestToAccountJson( + bank_routing: BankRoutingJsonV121, + account_routing: AccountRoutingJsonV121, + branch_routing: BranchRoutingJsonV141, + limit: PostCounterpartyLimitV510 +) + +case class PostConsentRequestJsonV510( + from_account:ConsentRequestFromAccountJson, + to_account:ConsentRequestToAccountJson, + valid_from: Option[Date], + time_to_live: Option[Long] +){ + def toPostConsentRequestJsonV500 = { + PostConsentRequestJsonV500( + everything = false, + bank_id = Some(from_account.bank_routing.address), + account_access = Nil, + entitlements = None, + consumer_id = None, + email = None, + phone_number = None, + valid_from = valid_from, + time_to_live = time_to_live + ) + } +} + object JSONFactory510 extends CustomJsonFormats { def createViewJson(view: View): CustomViewJsonV510 = { diff --git a/obp-api/src/test/scala/code/api/v5_1_0/CounterpartyLimitTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/CounterpartyLimitTest.scala index 3e9516539d..9a3685aa9b 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/CounterpartyLimitTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/CounterpartyLimitTest.scala @@ -30,6 +30,7 @@ class CounterpartyLimitTest extends V510ServerSetup { val ownerView = SYSTEM_OWNER_VIEW_ID val postCounterpartyLimitV510 = code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.postCounterpartyLimitV510 val putCounterpartyLimitV510 = PostCounterpartyLimitV510( + currency = "EUR", max_single_amount = 1, max_monthly_amount = 2, max_number_of_monthly_transactions = 3, From 60ffae09f2d549dda7157f8d0cceed32be29586a Mon Sep 17 00:00:00 2001 From: Hongwei Date: Thu, 11 Jul 2024 22:23:00 +0200 Subject: [PATCH 7/9] test/uncomment the test case of ConsentRequestTest --- .../code/api/v5_0_0/ConsentRequestTest.scala | 232 +++++++++--------- 1 file changed, 116 insertions(+), 116 deletions(-) diff --git a/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala index 61ed28f991..d8dc980014 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala @@ -70,7 +70,7 @@ class ConsentRequestTest extends V500ServerSetupAsync with PropsReset{ account_routing = AccountRoutingJsonV121( scheme = "AccountId", address = testAccountId1.value), Constant.SYSTEM_OWNER_VIEW_ID)) - lazy val postConsentRequestJsonV310 = SwaggerDefinitionsJSON.postConsentRequestJsonV500 + lazy val postConsentRequestJson = SwaggerDefinitionsJSON.postConsentRequestJsonV500 .copy(entitlements=Some(entitlements)) .copy(consumer_id=None) .copy(account_access=accountAccess) @@ -83,91 +83,91 @@ class ConsentRequestTest extends V500ServerSetupAsync with PropsReset{ def getConsentByRequestIdUrl(requestId:String) = (v5_0_0_Request / "consumer"/ "consent-requests"/requestId/"consents").GET<@(user1) feature("Create/Get Consent Request v5.0.0") { -// scenario("We will call the Create endpoint without a user credentials", ApiEndpoint1, VersionOfApi) { -// When("We make a request v5.0.0") -// val response500 = makePostRequest(createConsentRequestWithoutLoginUrl, write(postConsentRequestJsonV310)) -// Then("We should get a 401") -// response500.code should equal(401) -// response500.body.extract[ErrorMessage].message should equal (ApplicationNotIdentified) -// } -// -// 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.0.0") -// val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postConsentRequestJsonV310)) -// Then("We should get a 201") -// createConsentResponse.code should equal(201) -// val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] -// val consentRequestId = createConsentRequestResponseJson.consent_request_id -// -// When("We try to make the GET request v5.0.0") -// val successGetRes = makeGetRequest(getConsentRequestUrl(consentRequestId)) -// Then("We should get a 200") -// successGetRes.code should equal(200) -// val getConsentRequestResponseJson = successGetRes.body.extract[ConsentRequestResponseJson] -// getConsentRequestResponseJson.payload should not be("") -// -// When("We try to make the GET request v5.0.0") -// Then("We grant the role and test it again") -// Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) -// val createConsentByRequestResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) -// Then("We should get a 200") -// createConsentByRequestResponse.code should equal(201) -// val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id -// val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV500].jwt -// -// setPropsValues("consumer_validation_method_for_consent"->"NONE") -// val requestWhichFails = (v5_0_0_Request / "users").GET -// val responseWhichFails = makeGetRequest(requestWhichFails, List((s"Consent-JWT", consentJwt))) -// Then("We get successful response") -// responseWhichFails.code should equal(401) -// -// -// val answerConsentChallengeRequest = (v5_0_0_Request / "banks" / testBankId1.value / "consents" / consentId / "challenge").POST <@ (user1) -// val challenge = Consent.challengeAnswerAtTestEnvironment -// val post = PostConsentChallengeJsonV310(answer = challenge) -// val answerConsentChallengeResponse = makePostRequest(answerConsentChallengeRequest, write(post)) -// Then("We should get a 201") -// answerConsentChallengeResponse.code should equal(201) -// -// When("We try to make the GET request v5.0.0") -// val getConsentByRequestResponse = makeGetRequest(getConsentByRequestIdUrl(consentRequestId)) -// Then("We should get a 200") -// getConsentByRequestResponse.code should equal(200) -// val getConsentByRequestResponseJson = getConsentByRequestResponse.body.extract[ConsentJsonV500] -// getConsentByRequestResponseJson.consent_request_id.head should be(consentRequestId) -// getConsentByRequestResponseJson.status should be(ConsentStatus.ACCEPTED.toString) -// -// -// val requestGetUsers = (v5_0_0_Request / "users").GET -// -// // Test Request Header "Consent-JWT:SOME_VALUE" -// val consentRequestHeader = (s"Consent-JWT", getConsentByRequestResponseJson.jwt) -// val responseGetUsers = makeGetRequest(requestGetUsers, List(consentRequestHeader)) -// Then("We get successful response") -// responseGetUsers.code should equal(200) -// val users = responseGetUsers.body.extract[UsersJsonV400].users -// users.size should be > 0 -// -// // Test Request Header "Consent-Id:SOME_VALUE" -// val consentIdRequestHeader = (s"Consent-Id", getConsentByRequestResponseJson.consent_id) -// val responseGetUsersSecond = makeGetRequest(requestGetUsers, List(consentIdRequestHeader)) -// Then("We get successful response") -// responseGetUsersSecond.code should equal(200) -// val usersSecond = responseGetUsersSecond.body.extract[UsersJsonV400].users -// usersSecond.size should be > 0 -// users.size should equal(usersSecond.size) -// -// // Test Request Header "Consent-JWT:INVALID_JWT_VALUE" -// val wrongRequestHeader = (s"Consent-JWT", "INVALID_JWT_VALUE") -// val responseGetUsersWrong = makeGetRequest(requestGetUsers, List(wrongRequestHeader)) -// Then("We get successful response") -// responseGetUsersWrong.code should equal(401) -// responseGetUsersWrong.body.extract[ErrorMessage].message contains (ConsentHeaderValueInvalid) should be (true) -// } + scenario("We will call the Create endpoint without a user credentials", ApiEndpoint1, VersionOfApi) { + When("We make a request v5.0.0") + val response500 = makePostRequest(createConsentRequestWithoutLoginUrl, write(postConsentRequestJson)) + Then("We should get a 401") + response500.code should equal(401) + response500.body.extract[ErrorMessage].message should equal (ApplicationNotIdentified) + } + + 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.0.0") + val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postConsentRequestJson)) + Then("We should get a 201") + createConsentResponse.code should equal(201) + val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] + val consentRequestId = createConsentRequestResponseJson.consent_request_id + + When("We try to make the GET request v5.0.0") + val successGetRes = makeGetRequest(getConsentRequestUrl(consentRequestId)) + Then("We should get a 200") + successGetRes.code should equal(200) + val getConsentRequestResponseJson = successGetRes.body.extract[ConsentRequestResponseJson] + getConsentRequestResponseJson.payload should not be("") + + When("We try to make the GET request v5.0.0") + Then("We grant the role and test it again") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) + val createConsentByRequestResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) + Then("We should get a 200") + createConsentByRequestResponse.code should equal(201) + val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id + val consentJwt = createConsentByRequestResponse.body.extract[ConsentJsonV500].jwt + + setPropsValues("consumer_validation_method_for_consent"->"NONE") + val requestWhichFails = (v5_0_0_Request / "users").GET + val responseWhichFails = makeGetRequest(requestWhichFails, List((s"Consent-JWT", consentJwt))) + Then("We get successful response") + responseWhichFails.code should equal(401) + + + val answerConsentChallengeRequest = (v5_0_0_Request / "banks" / testBankId1.value / "consents" / consentId / "challenge").POST <@ (user1) + val challenge = Consent.challengeAnswerAtTestEnvironment + val post = PostConsentChallengeJsonV310(answer = challenge) + val answerConsentChallengeResponse = makePostRequest(answerConsentChallengeRequest, write(post)) + Then("We should get a 201") + answerConsentChallengeResponse.code should equal(201) + + When("We try to make the GET request v5.0.0") + val getConsentByRequestResponse = makeGetRequest(getConsentByRequestIdUrl(consentRequestId)) + Then("We should get a 200") + getConsentByRequestResponse.code should equal(200) + val getConsentByRequestResponseJson = getConsentByRequestResponse.body.extract[ConsentJsonV500] + getConsentByRequestResponseJson.consent_request_id.head should be(consentRequestId) + getConsentByRequestResponseJson.status should be(ConsentStatus.ACCEPTED.toString) + + + val requestGetUsers = (v5_0_0_Request / "users").GET + + // Test Request Header "Consent-JWT:SOME_VALUE" + val consentRequestHeader = (s"Consent-JWT", getConsentByRequestResponseJson.jwt) + val responseGetUsers = makeGetRequest(requestGetUsers, List(consentRequestHeader)) + Then("We get successful response") + responseGetUsers.code should equal(200) + val users = responseGetUsers.body.extract[UsersJsonV400].users + users.size should be > 0 + + // Test Request Header "Consent-Id:SOME_VALUE" + val consentIdRequestHeader = (s"Consent-Id", getConsentByRequestResponseJson.consent_id) + val responseGetUsersSecond = makeGetRequest(requestGetUsers, List(consentIdRequestHeader)) + Then("We get successful response") + responseGetUsersSecond.code should equal(200) + val usersSecond = responseGetUsersSecond.body.extract[UsersJsonV400].users + usersSecond.size should be > 0 + users.size should equal(usersSecond.size) + + // Test Request Header "Consent-JWT:INVALID_JWT_VALUE" + val wrongRequestHeader = (s"Consent-JWT", "INVALID_JWT_VALUE") + val responseGetUsersWrong = makeGetRequest(requestGetUsers, List(wrongRequestHeader)) + Then("We get successful response") + responseGetUsersWrong.code should equal(401) + responseGetUsersWrong.body.extract[ErrorMessage].message contains (ConsentHeaderValueInvalid) should be (true) + } 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.0.0") - val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postConsentRequestJsonV310)) + val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postConsentRequestJson)) Then("We should get a 201") createConsentResponse.code should equal(201) val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] @@ -239,39 +239,39 @@ class ConsentRequestTest extends V500ServerSetupAsync with PropsReset{ responseGetUsersWrong.body.extract[ErrorMessage].message contains (ConsentHeaderValueInvalid) should be (true) } -// scenario(s"Check the forbidden roles ${CanCreateEntitlementAtAnyBank.toString()}", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, VersionOfApi) { -// When(s"We try $ApiEndpoint1 v5.0.0") -// val postJsonForbiddenEntitlementAtAnyBank = postConsentRequestJsonV310.copy(entitlements = Some(forbiddenEntitlementAnyBank)) -// val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postJsonForbiddenEntitlementAtAnyBank)) -// Then("We should get a 201") -// createConsentResponse.code should equal(201) -// val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] -// val consentRequestId = createConsentRequestResponseJson.consent_request_id -// -// // Role CanCreateEntitlementAtAnyBank MUST be forbidden -// val forbiddenRoleResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) -// Then("We should get a 400") -// forbiddenRoleResponse.code should equal(400) -// forbiddenRoleResponse.code should equal(400) -// forbiddenRoleResponse.body.extract[ErrorMessage].message should equal (RolesForbiddenInConsent) -// } -// -// scenario(s"Check the forbidden roles ${CanCreateEntitlementAtOneBank.toString()}", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, VersionOfApi) { -// When(s"We try $ApiEndpoint1 v5.0.0") -// val postJsonForbiddenEntitlementAtOneBank = postConsentRequestJsonV310.copy(entitlements = Some(forbiddenEntitlementOneBank)) -// val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postJsonForbiddenEntitlementAtOneBank)) -// Then("We should get a 201") -// createConsentResponse.code should equal(201) -// val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] -// val consentRequestId = createConsentRequestResponseJson.consent_request_id -// -// // Role CanCreateEntitlementAtOneBank MUST be forbidden -// val forbiddenRoleResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) -// Then("We should get a 400") -// forbiddenRoleResponse.code should equal(400) -// forbiddenRoleResponse.code should equal(400) -// forbiddenRoleResponse.body.extract[ErrorMessage].message should equal (RolesForbiddenInConsent) -// } + scenario(s"Check the forbidden roles ${CanCreateEntitlementAtAnyBank.toString()}", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, VersionOfApi) { + When(s"We try $ApiEndpoint1 v5.0.0") + val postJsonForbiddenEntitlementAtAnyBank = postConsentRequestJson.copy(entitlements = Some(forbiddenEntitlementAnyBank)) + val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postJsonForbiddenEntitlementAtAnyBank)) + Then("We should get a 201") + createConsentResponse.code should equal(201) + val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] + val consentRequestId = createConsentRequestResponseJson.consent_request_id + + // Role CanCreateEntitlementAtAnyBank MUST be forbidden + val forbiddenRoleResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) + Then("We should get a 400") + forbiddenRoleResponse.code should equal(400) + forbiddenRoleResponse.code should equal(400) + forbiddenRoleResponse.body.extract[ErrorMessage].message should equal (RolesForbiddenInConsent) + } + + scenario(s"Check the forbidden roles ${CanCreateEntitlementAtOneBank.toString()}", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, VersionOfApi) { + When(s"We try $ApiEndpoint1 v5.0.0") + val postJsonForbiddenEntitlementAtOneBank = postConsentRequestJson.copy(entitlements = Some(forbiddenEntitlementOneBank)) + val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postJsonForbiddenEntitlementAtOneBank)) + Then("We should get a 201") + createConsentResponse.code should equal(201) + val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] + val consentRequestId = createConsentRequestResponseJson.consent_request_id + + // Role CanCreateEntitlementAtOneBank MUST be forbidden + val forbiddenRoleResponse = makePostRequest(createConsentByConsentRequestIdEmail(consentRequestId), write("")) + Then("We should get a 400") + forbiddenRoleResponse.code should equal(400) + forbiddenRoleResponse.code should equal(400) + forbiddenRoleResponse.body.extract[ErrorMessage].message should equal (RolesForbiddenInConsent) + } } From d9f0bce9a8916830650089cb1aae3d6eec9942b0 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 12 Jul 2024 10:31:56 +0200 Subject: [PATCH 8/9] feature/OBPv510 added new endpoint createVRPConsentRequest --- .../SwaggerDefinitionsJSON.scala | 2 + .../scala/code/api/v5_1_0/APIMethods510.scala | 8 +- .../code/api/v5_1_0/JSONFactory5.1.0.scala | 6 +- .../code/api/v5_0_0/ConsentRequestTest.scala | 3 +- .../api/v5_1_0/VRPConsentRequestTest.scala | 192 ++++++++++++++++++ 5 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala 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 d8e6e36f13..8ecf9d02d3 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 @@ -5249,6 +5249,8 @@ object SwaggerDefinitionsJSON { val postConsentRequestJsonV510 = PostConsentRequestJsonV510( from_account = consentRequestFromAccountJson, to_account = consentRequestToAccountJson, + email = Some(emailExample.value), + phone_number = Some(mobileNumberExample.value), valid_from = Some(new Date()), time_to_live = Some(3600) ) 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 d211bb9344..d06efd1aa8 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 @@ -2723,12 +2723,12 @@ trait APIMethods510 { staticResourceDocs += ResourceDoc( - createVPRConsentRequest, + createVRPConsentRequest, implementedInApiVersion, - nameOf(createVPRConsentRequest), + nameOf(createVRPConsentRequest), "POST", "/consumer/vrp-consent-requests", - "Create VPR Consent Request", + "Create VRP Consent Request", s""" |Client Authentication (mandatory) | @@ -2755,7 +2755,7 @@ trait APIMethods510 { apiTagConsent :: apiTagPSD2AIS :: apiTagPsd2 :: Nil ) - lazy val createVPRConsentRequest : OBPEndpoint = { + lazy val createVRPConsentRequest : OBPEndpoint = { case "consumer" :: "vrp-consent-requests" :: Nil JsonPost json -> _ => { cc => implicit val ec = EndpointContext(Some(cc)) for { 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 f7f83d5870..1cc11b3868 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 @@ -401,6 +401,8 @@ case class ConsentRequestToAccountJson( case class PostConsentRequestJsonV510( from_account:ConsentRequestFromAccountJson, to_account:ConsentRequestToAccountJson, + email: Option[String], + phone_number: Option[String], valid_from: Option[Date], time_to_live: Option[Long] ){ @@ -411,8 +413,8 @@ case class PostConsentRequestJsonV510( account_access = Nil, entitlements = None, consumer_id = None, - email = None, - phone_number = None, + email = email, + phone_number = phone_number, valid_from = valid_from, time_to_live = time_to_live ) diff --git a/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala index d8dc980014..af98a24033 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala @@ -118,8 +118,9 @@ class ConsentRequestTest extends V500ServerSetupAsync with PropsReset{ setPropsValues("consumer_validation_method_for_consent"->"NONE") val requestWhichFails = (v5_0_0_Request / "users").GET val responseWhichFails = makeGetRequest(requestWhichFails, List((s"Consent-JWT", consentJwt))) - Then("We get successful response") + Then("We get 401 error") responseWhichFails.code should equal(401) + responseWhichFails.body.toString contains(ConsentStatusIssue) shouldBe(true) val answerConsentChallengeRequest = (v5_0_0_Request / "banks" / testBankId1.value / "consents" / consentId / "challenge").POST <@ (user1) 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 new file mode 100644 index 0000000000..7cdc044a57 --- /dev/null +++ b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala @@ -0,0 +1,192 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH +Osloerstrasse 16/17 +Berlin 13359, Germany + +This product includes software developed at +TESOBE (http://www.tesobe.com/) + */ +package code.api.v5_1_0 + +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole._ +import code.api.util.Consent +import code.api.util.ErrorMessages._ +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 +import code.api.v5_0_0.ConsentRequestResponseJson +import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0 +import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 +import code.consent.ConsentStatus +import code.entitlement.Entitlement +import code.setup.PropsReset +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.model.ErrorMessage +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write +import org.scalatest.Tag + +import scala.language.postfixOps + +class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ + + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.createVRPConsentRequest)) + + object ApiEndpoint2 extends Tag(nameOf(Implementations5_0_0.getConsentByConsentRequestId)) + object ApiEndpoint3 extends Tag(nameOf(Implementations5_0_0.createConsentByConsentRequestId)) + object ApiEndpoint4 extends Tag(nameOf(Implementations5_0_0.getConsentByConsentRequestId)) + object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.getUsers)) + object ApiEndpoint6 extends Tag(nameOf(Implementations5_0_0.getConsentRequest)) + + + + + val createVRPConsentRequestWithoutLoginUrl = (v5_1_0_Request / "consumer" / "vrp-consent-requests") + val createVRPConsentRequestUrl = (v5_1_0_Request / "consumer"/ "vrp-consent-requests").POST<@(user1) + def getConsentRequestUrl(requestId:String) = (v5_1_0_Request / "consumer"/ "consent-requests"/requestId).GET<@(user1) + def createConsentByConsentRequestIdEmail(requestId:String) = (v5_1_0_Request / "consumer"/ "consent-requests"/requestId/"EMAIL"/"consents").POST<@(user1) + 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 + + + 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)) + Then("We should get a 401") + response510.code should equal(401) + response510.body.extract[ErrorMessage].message should equal (ApplicationNotIdentified) + } + + 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)) + Then("We should get a 201") + createConsentResponse.code should equal(201) + val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] + val consentRequestId = createConsentRequestResponseJson.consent_request_id + + When("We try to make the GET request v5.1.0") + val successGetRes = makeGetRequest(getConsentRequestUrl(consentRequestId)) + Then("We should get a 200") + successGetRes.code should equal(200) + val getConsentRequestResponseJson = successGetRes.body.extract[ConsentRequestResponseJson] + getConsentRequestResponseJson.payload should not be("") + + When("We try to make the GET request v5.1.0") + Then("We grant the role and test it again") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) + 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 + + setPropsValues("consumer_validation_method_for_consent"->"NONE") + val requestWhichFails = (v5_1_0_Request / "users").GET + val responseWhichFails = makeGetRequest(requestWhichFails, List((s"Consent-JWT", consentJwt))) + Then("We get 401 error") + responseWhichFails.code should equal(401) + responseWhichFails.body.toString contains(ConsentStatusIssue) shouldBe(true) + + + val answerConsentChallengeRequest = (v5_1_0_Request / "banks" / testBankId1.value / "consents" / consentId / "challenge").POST <@ (user1) + val challenge = Consent.challengeAnswerAtTestEnvironment + val post = PostConsentChallengeJsonV310(answer = challenge) + val answerConsentChallengeResponse = makePostRequest(answerConsentChallengeRequest, write(post)) + Then("We should get a 201") + answerConsentChallengeResponse.code should equal(201) + + When("We try to make the GET request v5.1.0") + val getConsentByRequestResponse = makeGetRequest(getConsentByRequestIdUrl(consentRequestId)) + Then("We should get a 200") + getConsentByRequestResponse.code should equal(200) + val getConsentByRequestResponseJson = getConsentByRequestResponse.body.extract[ConsentJsonV510] + getConsentByRequestResponseJson.consent_request_id.head should be(consentRequestId) + getConsentByRequestResponseJson.status should be(ConsentStatus.ACCEPTED.toString) + + + val requestGetUsers = (v5_1_0_Request / "users").GET + + } + + 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)) + Then("We should get a 201") + createConsentResponse.code should equal(201) + val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson] + val consentRequestId = createConsentRequestResponseJson.consent_request_id + + When("We try to make the GET request v5.1.0") + val successGetRes = makeGetRequest(getConsentRequestUrl(consentRequestId)) + Then("We should get a 200") + successGetRes.code should equal(200) + val getConsentRequestResponseJson = successGetRes.body.extract[ConsentRequestResponseJson] + getConsentRequestResponseJson.payload should not be("") + + When("We try to make the GET request v5.1.0") + Then("We grant the role and test it again") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) + 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 + + setPropsValues("consumer_validation_method_for_consent"->"NONE") + val requestWhichFails = (v5_1_0_Request / "users").GET + val responseWhichFails = makeGetRequest(requestWhichFails, List((s"Consent-JWT", consentJwt))) + Then("We get successful response") + responseWhichFails.code should equal(401) + + + val answerConsentChallengeRequest = (v5_1_0_Request / "banks" / testBankId1.value / "consents" / consentId / "challenge").POST <@ (user1) + val challenge = Consent.challengeAnswerAtTestEnvironment + val post = PostConsentChallengeJsonV310(answer = challenge) + val answerConsentChallengeResponse = makePostRequest(answerConsentChallengeRequest, write(post)) + Then("We should get a 201") + answerConsentChallengeResponse.code should equal(201) + + When("We try to make the GET request v5.1.0") + val getConsentByRequestResponse = makeGetRequest(getConsentByRequestIdUrl(consentRequestId)) + Then("We should get a 200") + getConsentByRequestResponse.code should equal(200) + val getConsentByRequestResponseJson = getConsentByRequestResponse.body.extract[ConsentJsonV510] + getConsentByRequestResponseJson.consent_request_id.head should be(consentRequestId) + getConsentByRequestResponseJson.status should be(ConsentStatus.ACCEPTED.toString) + } + + + } + +} From ec2c10e79da461baddf7827a07e8404028ef9314 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 12 Jul 2024 10:50:32 +0200 Subject: [PATCH 9/9] refactor/OBPv510 added currency to CounterpartyLimit Model --- .../api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 1 + obp-api/src/main/scala/code/api/util/NewStyle.scala | 2 ++ obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala | 2 ++ .../src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala | 1 + obp-api/src/main/scala/code/bankconnectors/Connector.scala | 1 + .../scala/code/bankconnectors/LocalMappedConnector.scala | 2 ++ .../scala/code/counterpartylimit/CounterpartyLimit.scala | 2 ++ .../code/counterpartylimit/MappedCounterpartyLimit.scala | 7 +++++++ 8 files changed, 18 insertions(+) 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 8ecf9d02d3..11242f92b3 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 @@ -5470,6 +5470,7 @@ object SwaggerDefinitionsJSON { account_id = accountIdExample.value, view_id = viewIdExample.value, counterparty_id = counterpartyIdExample.value, + currency = currencyExample.value, max_single_amount = maxSingleAmountExample.value.toInt, max_monthly_amount = maxMonthlyAmountExample.value.toInt, max_number_of_monthly_transactions = maxNumberOfMonthlyTransactionsExample.value.toInt, diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index a6b4a7f2d0..d4cb55eeb9 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -4068,6 +4068,7 @@ object NewStyle extends MdcLoggable{ accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, @@ -4080,6 +4081,7 @@ object NewStyle extends MdcLoggable{ accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, 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 d06efd1aa8..eb7034597d 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 @@ -2351,6 +2351,7 @@ trait APIMethods510 { accountId.value, viewId.value, counterpartyId.value, + postCounterpartyLimitV510.currency, postCounterpartyLimitV510.max_single_amount, postCounterpartyLimitV510.max_monthly_amount, postCounterpartyLimitV510.max_number_of_monthly_transactions, @@ -2398,6 +2399,7 @@ trait APIMethods510 { accountId.value, viewId.value, counterpartyId.value, + postCounterpartyLimitV510.currency, postCounterpartyLimitV510.max_single_amount, postCounterpartyLimitV510.max_monthly_amount, postCounterpartyLimitV510.max_number_of_monthly_transactions, 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 1cc11b3868..e9a12640b2 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 @@ -177,6 +177,7 @@ case class CounterpartyLimitV510( account_id: String, view_id: String, counterparty_id: String, + currency: String, max_single_amount: Int, max_monthly_amount: Int, max_number_of_monthly_transactions: Int, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 0cf4f48d2c..1e68c3ed21 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -2693,6 +2693,7 @@ trait Connector extends MdcLoggable { accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 9488f6bca3..b6ea170f10 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -5947,6 +5947,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, @@ -5957,6 +5958,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, diff --git a/obp-api/src/main/scala/code/counterpartylimit/CounterpartyLimit.scala b/obp-api/src/main/scala/code/counterpartylimit/CounterpartyLimit.scala index 92bc5f5591..753034f62a 100644 --- a/obp-api/src/main/scala/code/counterpartylimit/CounterpartyLimit.scala +++ b/obp-api/src/main/scala/code/counterpartylimit/CounterpartyLimit.scala @@ -34,6 +34,7 @@ trait CounterpartyLimitProviderTrait { accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, @@ -48,6 +49,7 @@ trait CounterpartyLimitTrait extends JsonAble{ def viewId: String def counterpartyId: String + def currency: String def maxSingleAmount: Int def maxMonthlyAmount: Int def maxNumberOfMonthlyTransactions: Int diff --git a/obp-api/src/main/scala/code/counterpartylimit/MappedCounterpartyLimit.scala b/obp-api/src/main/scala/code/counterpartylimit/MappedCounterpartyLimit.scala index a919f3c96c..5552f99bbd 100644 --- a/obp-api/src/main/scala/code/counterpartylimit/MappedCounterpartyLimit.scala +++ b/obp-api/src/main/scala/code/counterpartylimit/MappedCounterpartyLimit.scala @@ -46,6 +46,7 @@ object MappedCounterpartyLimitProvider extends CounterpartyLimitProviderTrait { accountId: String, viewId: String, counterpartyId: String, + currency: String, maxSingleAmount: Int, maxMonthlyAmount: Int, maxNumberOfMonthlyTransactions: Int, @@ -58,6 +59,7 @@ object MappedCounterpartyLimitProvider extends CounterpartyLimitProviderTrait { counterpartyLimit.AccountId(accountId) counterpartyLimit.ViewId(viewId) counterpartyLimit.CounterpartyId(counterpartyId) + counterpartyLimit.Currency(currency) counterpartyLimit.MaxSingleAmount(maxSingleAmount) counterpartyLimit.MaxMonthlyAmount(maxMonthlyAmount) counterpartyLimit.MaxNumberOfMonthlyTransactions(maxNumberOfMonthlyTransactions) @@ -100,6 +102,9 @@ class CounterpartyLimit extends CounterpartyLimitTrait with LongKeyedMapper[Coun override def dbNotNull_? = true } + object Currency extends MappedString(this, 255){ + override def dbNotNull_? = true + } object MaxSingleAmount extends MappedInt(this) { override def defaultValue = -1 @@ -123,6 +128,7 @@ class CounterpartyLimit extends CounterpartyLimitTrait with LongKeyedMapper[Coun def accountId: String = AccountId.get def viewId: String = ViewId.get def counterpartyId: String = CounterpartyId.get + def currency: String = Currency.get def maxSingleAmount: Int = MaxSingleAmount.get def maxMonthlyAmount: Int = MaxMonthlyAmount.get @@ -136,6 +142,7 @@ class CounterpartyLimit extends CounterpartyLimitTrait with LongKeyedMapper[Coun ("account_id",accountId) ~ ("view_id",viewId) ~ ("counterparty_id",counterpartyId) ~ + ("currency",currency) ~ ("max_single_amount", maxSingleAmount) ~ ("max_monthly_amount", maxMonthlyAmount) ~ ("max_number_of_monthly_transactions", maxNumberOfMonthlyTransactions) ~