diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 2d77ddd929..99355627c7 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -1147,6 +1147,9 @@ default_auth_context_update_request_key=CUSTOMER_NUMBER # the alias prefix path for BerlinGroupV1.3 (OBP built-in is berlin-group/v1.3), the format must be xxx/yyy, eg: 0.6/v1 #berlin_group_v1_3_alias_path= +# Berlin Group URL version +#berlin_group_version_1_canonical_path=v1.3 + # Show the path inside of Berlin Group error message #berlin_group_error_message_show_path = true diff --git a/obp-api/src/main/scala/code/api/berlin/group/ConstantsBG.scala b/obp-api/src/main/scala/code/api/berlin/group/ConstantsBG.scala index 0058a6fe1c..11bf6659dd 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/ConstantsBG.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/ConstantsBG.scala @@ -1,6 +1,15 @@ package code.api.berlin.group +import code.api.util.APIUtil +import com.openbankproject.commons.util.ApiVersion.berlinGroupV13 +import com.openbankproject.commons.util.ScannedApiVersion +import net.liftweb.common.Full + object ConstantsBG { + val berlinGroupVersion1: ScannedApiVersion = APIUtil.getPropsValue("berlin_group_version_1_canonical_path") match { + case Full(props) => berlinGroupV13.copy(apiShortVersion = props) + case _ => berlinGroupV13 + } object SigningBasketsStatus extends Enumeration { type SigningBasketsStatus = Value // Only the codes 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 b0310910bf..287327ac84 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 @@ -3,6 +3,7 @@ package code.api.builder.AccountInformationServiceAISApi import java.text.SimpleDateFormat import code.api.APIFailureNewStyle import code.api.Constant.{SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID} +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{PostConsentResponseJson, _} import code.api.berlin.group.v1_3.model.{HrefType, LinksAll, ScaStatusResponse} import code.api.berlin.group.v1_3.{BgSpecValidation, JSONFactory_BERLIN_GROUP_1_3, JvalueCaseClass, OBP_BERLIN_GROUP_1_3} @@ -37,7 +38,7 @@ import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future object APIMethods_AccountInformationServiceAISApi extends RestHelper { - val apiVersion = ApiVersion.berlinGroupV13 + val apiVersion = ConstantsBG.berlinGroupVersion1 val resourceDocs = ArrayBuffer[ResourceDoc]() val apiRelations = ArrayBuffer[ApiRelation]() protected implicit def JvalueToSuper(what: JValue): JvalueCaseClass = JvalueCaseClass(what) @@ -784,7 +785,7 @@ This method returns the SCA status of a consent initiation's authorisation sub-r case "consents" :: consentId:: "status" :: Nil JsonGet _ => { cc => for { - (Full(u), callContext) <- authenticatedAccess(cc) + (_, callContext) <- applicationAccess(cc) _ <- passesPsd2Aisp(callContext) consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map { unboxFullOrFail(_, callContext, ConsentNotFound, 403) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala index 0a32939b63..34b0f54f6c 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala @@ -1,5 +1,6 @@ package code.api.builder.CommonServicesApi +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.{JvalueCaseClass, OBP_BERLIN_GROUP_1_3} import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi import code.api.builder.PaymentInitiationServicePISApi.APIMethods_PaymentInitiationServicePISApi @@ -14,7 +15,7 @@ import scala.collection.mutable.ArrayBuffer //TODO maybe we can remove this common services, it just show other apis in this tag. no new ones. object APIMethods_CommonServicesApi extends RestHelper { - val apiVersion = ApiVersion.berlinGroupV13 + val apiVersion = ConstantsBG.berlinGroupVersion1 val resourceDocs = ArrayBuffer[ResourceDoc]() val apiRelations = ArrayBuffer[ApiRelation]() val codeContext = CodeContext(resourceDocs, apiRelations) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala index 94c33db476..7e5108aa7c 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala @@ -1,5 +1,6 @@ package code.api.builder.ConfirmationOfFundsServicePIISApi +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3._ import code.api.berlin.group.v1_3.{JvalueCaseClass, OBP_BERLIN_GROUP_1_3} import code.api.util.APIUtil._ @@ -20,7 +21,7 @@ import scala.collection.immutable.Nil import scala.collection.mutable.ArrayBuffer object APIMethods_ConfirmationOfFundsServicePIISApi extends RestHelper { - val apiVersion = ApiVersion.berlinGroupV13 + val apiVersion = ConstantsBG.berlinGroupVersion1 val resourceDocs = ArrayBuffer[ResourceDoc]() val apiRelations = ArrayBuffer[ApiRelation]() protected implicit def JvalueToSuper(what: JValue): JvalueCaseClass = JvalueCaseClass(what) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala index 5c073c79d2..4204834e1c 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala @@ -1,5 +1,6 @@ package code.api.berlin.group.v1_3 +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.model.TransactionStatus.mapTransactionStatus import code.api.berlin.group.v1_3.model._ import code.api.util.APIUtil._ @@ -513,7 +514,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ TransactionsV13Transactions( booked= transactions.map(transaction => createTransactionJSON(bankAccount, transaction)), pending = transactionRequests.filter(_.status!="COMPLETED").map(transactionRequest => createTransactionFromRequestJSON(bankAccount, transactionRequest)), - _links = TransactionsV13TransactionsLinks(LinkHrefJson(s"/v1.3/accounts/$accountId")) + _links = TransactionsV13TransactionsLinks(LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/accounts/$accountId")) ) ) } @@ -559,7 +560,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ CardTransactionsV13Transactions( booked= transactions.map(t => createCardTransactionJson(t)), pending = Nil, - _links = CardTransactionsLinksV13(LinkHrefJson(s"/v1.3/card-accounts/$accountId")) + _links = CardTransactionsLinksV13(LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/card-accounts/$accountId")) ) ) } @@ -570,7 +571,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ consentId = consent.consentId, consentStatus = consent.status.toLowerCase(), _links = ConsentLinksV13( - startAuthorisation = Some(Href(s"/v1.3/consents/${consent.consentId}/authorisations")) + startAuthorisation = Some(Href(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/authorisations")) ) ) } @@ -589,9 +590,9 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ consentStatus = consent.status.toLowerCase(), _links = ConsentLinksV13( scaRedirect = Some(Href(s"$scaRedirectUrl")), - status = Some(Href(s"/v1.3/consents/${consent.consentId}/status")), + status = Some(Href(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/status")), // TODO Introduce a working link - // scaStatus = Some(Href(s"/v1.3/consents/${consent.consentId}/authorisations/AUTHORISATIONID")), + // scaStatus = Some(Href(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/authorisations/AUTHORISATIONID")), ) ) case Full("redirection_with_dedicated_start_of_authorization") => @@ -601,7 +602,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ consentId = consent.consentId, consentStatus = consent.status.toLowerCase(), _links = ConsentLinksV13( - startAuthorisationWithPsuAuthentication = Some(Href(s"/v1.3/consents/${consent.consentId}/authorisations")) + startAuthorisationWithPsuAuthentication = Some(Href(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/authorisations")) ) ) case Full("decoupled") => @@ -609,7 +610,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ consentId = consent.consentId, consentStatus = consent.status.toLowerCase(), _links = ConsentLinksV13( - startAuthorisationWithPsuIdentification = Some(Href(s"/v1.3/consents/${consent.consentId}/authorisations")) + startAuthorisationWithPsuIdentification = Some(Href(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/authorisations")) ) ) case _ => @@ -620,7 +621,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ def createPutConsentResponseJson(consent: ConsentTrait) : ScaStatusResponse = { ScaStatusResponse( scaStatus = consent.status.toLowerCase(), - _links = Some(LinksAll(scaStatus = Some(HrefType(Some(s"/v1.3/consents/${consent.consentId}/authorisations"))))) + _links = Some(LinksAll(scaStatus = Some(HrefType(Some(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/authorisations"))))) ) } @@ -645,7 +646,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ scaStatus = challenge.scaStatus.map(_.toString).getOrElse("None"), authorisationId = challenge.authenticationMethodId.getOrElse("None"), pushMessage = "started", //TODO Not implement how to fill this. - _links = ScaStatusJsonV13(s"/v1.3/consents/${consent.consentId}/authorisations/${challenge.challengeId}")//TODO, Not sure, what is this for?? + _links = ScaStatusJsonV13(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/consents/${consent.consentId}/authorisations/${challenge.challengeId}")//TODO, Not sure, what is this for?? ) } @@ -698,9 +699,9 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ paymentId = paymentId, _links = InitiatePaymentResponseLinks( scaRedirect = LinkHrefJson(s"$scaRedirectUrl/$paymentId"), - self = LinkHrefJson(s"/v1.3/payments/sepa-credit-transfers/$paymentId"), - status = LinkHrefJson(s"/v1.3/payments/$paymentId/status"), - scaStatus = LinkHrefJson(s"/v1.3/payments/$paymentId/authorisations/${paymentId}") + self = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/$paymentId"), + status = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/$paymentId/status"), + scaStatus = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/$paymentId/authorisations/${paymentId}") ) ) } @@ -709,9 +710,9 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ CancelPaymentResponseJson( "ACTC", _links = CancelPaymentResponseLinks( - self = LinkHrefJson(s"/v1.3/payments/sepa-credit-transfers/$paymentId"), - status = LinkHrefJson(s"/v1.3/payments/sepa-credit-transfers/$paymentId/status"), - startAuthorisation = LinkHrefJson(s"/v1.3/payments/sepa-credit-transfers/cancellation-authorisations/${paymentId}") + self = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/$paymentId"), + status = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/$paymentId/status"), + startAuthorisation = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/cancellation-authorisations/${paymentId}") ) ) } @@ -725,7 +726,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ scaStatus = challenge.scaStatus.map(_.toString).getOrElse(""), authorisationId = challenge.challengeId, psuMessage = "Please check your SMS at a mobile device.", - _links = ScaStatusJsonV13(s"/v1.3/payments/sepa-credit-transfers/${challenge.challengeId}") + _links = ScaStatusJsonV13(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/${challenge.challengeId}") ) } @@ -733,7 +734,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ ScaStatusResponse( scaStatus = challenge.scaStatus.map(_.toString).getOrElse(""), psuMessage = Some("Please check your SMS at a mobile device."), - _links = Some(LinksAll(scaStatus = Some(HrefType(Some(s"/v1.3/payments/sepa-credit-transfers/${challenge.challengeId}")))) + _links = Some(LinksAll(scaStatus = Some(HrefType(Some(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/${challenge.challengeId}")))) ) ) } @@ -745,7 +746,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ ScaStatusResponse( scaStatus = challenge.scaStatus.map(_.toString).getOrElse(""), psuMessage = Some("Please check your SMS at a mobile device."), - _links = Some(LinksAll(scaStatus = Some(HrefType(Some(s"/v1.3/${paymentService}/${paymentProduct}/${paymentId}/cancellation-authorisations/${challenge.challengeId}")))) + _links = Some(LinksAll(scaStatus = Some(HrefType(Some(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/${paymentService}/${paymentProduct}/${paymentId}/cancellation-authorisations/${challenge.challengeId}")))) ) ) } @@ -761,7 +762,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ authorisationId = Some(challenge.challengeId), psuMessage = Some("Please check your SMS at a mobile device."), _links = Some(LinksUpdatePsuAuthentication( - scaStatus = Some(HrefType(Some(s"/v1.3/${paymentService}/${paymentProduct}/${paymentId}/cancellation-authorisations/${challenge.challengeId}")))) + scaStatus = Some(HrefType(Some(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/${paymentService}/${paymentProduct}/${paymentId}/cancellation-authorisations/${challenge.challengeId}")))) ) ) } @@ -772,7 +773,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ scaStatus = challenge.scaStatus.map(_.toString).getOrElse(""), authorisationId = challenge.challengeId, psuMessage = "Please check your SMS at a mobile device.", - _links = ScaStatusJsonV13(s"/v1.3/signing-baskets/${basketId}/authorisations/${challenge.challengeId}") + _links = ScaStatusJsonV13(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/signing-baskets/${basketId}/authorisations/${challenge.challengeId}") ) } @@ -781,9 +782,9 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ basketId = basket.basketId, transactionStatus = basket.status.toLowerCase(), _links = SigningBasketLinksV13( - self = LinkHrefJson(s"/v1.3/signing-baskets/${basket.basketId}"), - status = LinkHrefJson(s"/v1.3/signing-baskets/${basket.basketId}/status"), - startAuthorisation = LinkHrefJson(s"/v1.3/signing-baskets/${basket.basketId}/authorisations") + self = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/signing-baskets/${basket.basketId}"), + status = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/signing-baskets/${basket.basketId}/status"), + startAuthorisation = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/signing-baskets/${basket.basketId}/authorisations") ) ) } diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/OBP_BERLIN_GROUP_1_3.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/OBP_BERLIN_GROUP_1_3.scala index 5a488877fa..0fea84db81 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/OBP_BERLIN_GROUP_1_3.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/OBP_BERLIN_GROUP_1_3.scala @@ -32,6 +32,7 @@ package code.api.berlin.group.v1_3 import code.api.OBPRestHelper +import code.api.berlin.group.ConstantsBG import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi import code.api.builder.CommonServicesApi.APIMethods_CommonServicesApi import code.api.builder.ConfirmationOfFundsServicePIISApi.APIMethods_ConfirmationOfFundsServicePIISApi @@ -40,7 +41,7 @@ import code.api.builder.SigningBasketsApi.APIMethods_SigningBasketsApi import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints} import code.api.util.ScannedApis import code.util.Helper.MdcLoggable -import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion,ApiVersionStatus} +import com.openbankproject.commons.util.{ApiVersion, ApiVersionStatus, ScannedApiVersion} import scala.collection.mutable.ArrayBuffer @@ -52,7 +53,7 @@ This file defines which endpoints from all the versions are available in v1 */ object OBP_BERLIN_GROUP_1_3 extends OBPRestHelper with MdcLoggable with ScannedApis { - override val apiVersion = ApiVersion.berlinGroupV13 + override val apiVersion = ConstantsBG.berlinGroupVersion1 val versionStatus = ApiVersionStatus.DRAFT.toString val endpoints = 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 6472e7b489..9c88b8f307 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 @@ -1,5 +1,6 @@ package code.api.builder.PaymentInitiationServicePISApi +import code.api.berlin.group.ConstantsBG 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.model.TransactionStatus.mapTransactionStatus import code.api.berlin.group.v1_3.model._ @@ -30,7 +31,7 @@ import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future object APIMethods_PaymentInitiationServicePISApi extends RestHelper { - val apiVersion = ApiVersion.berlinGroupV13 + val apiVersion = ConstantsBG.berlinGroupVersion1 val resourceDocs = ArrayBuffer[ResourceDoc]() val apiRelations = ArrayBuffer[ApiRelation]() protected implicit def JvalueToSuper(what: JValue): JvalueCaseClass = JvalueCaseClass(what) 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 905d2d5493..8b1c05891d 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 @@ -28,7 +28,7 @@ import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future object APIMethods_SigningBasketsApi extends RestHelper { - val apiVersion = ApiVersion.berlinGroupV13 + val apiVersion = ConstantsBG.berlinGroupVersion1 val resourceDocs = ArrayBuffer[ResourceDoc]() val apiRelations = ArrayBuffer[ApiRelation]() protected implicit def JvalueToSuper(what: JValue): JvalueCaseClass = JvalueCaseClass(what) 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 3fba160ed5..976a6eb206 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -149,6 +149,8 @@ object RequestHeader { final lazy val `PSD2-CERT` = "PSD2-CERT" final lazy val `If-None-Match` = "If-None-Match" + final lazy val `PSU-Geo-Location` = "PSU-Geo-Location" // Berlin Group + final lazy val `PSU-Device-Name` = "PSU-Device-Name" // Berlin Group final lazy val `PSU-Device-ID` = "PSU-Device-ID" // Berlin Group final lazy val `PSU-IP-Address` = "PSU-IP-Address" // Berlin Group final lazy val `X-Request-ID` = "X-Request-ID" // Berlin Group diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index f4acc2ccce..572472e2d6 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -34,6 +34,7 @@ import code.api.OAuthHandshake._ import code.api.UKOpenBanking.v2_0_0.OBP_UKOpenBanking_200 import code.api.UKOpenBanking.v3_1_0.OBP_UKOpenBanking_310 import code.api._ +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{ErrorMessageBG, ErrorMessagesBG} import code.api.cache.Caching import code.api.dynamic.endpoint.OBPAPIDynamicEndpoint @@ -520,7 +521,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val mirrorByProperties = getPropsValue("mirror_request_headers_to_response", "").split(",").toList.map(_.trim) val mirrorRequestHeadersToResponse: List[String] = - if (callContext.exists(_.url.contains(ApiVersion.berlinGroupV13.urlPrefix))) { + if (callContext.exists(_.url.contains(ConstantsBG.berlinGroupVersion1.urlPrefix))) { // Berlin Group Specification RequestHeader.`X-Request-ID` :: mirrorByProperties } else { @@ -725,7 +726,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } def composeErrorMessage() = { val path = callContextLight.map(_.url).getOrElse("") - if (path.contains(ApiVersion.berlinGroupV13.urlPrefix)) { + if (path.contains(ConstantsBG.berlinGroupVersion1.urlPrefix)) { val path = if(APIUtil.getPropsAsBoolValue("berlin_group_error_message_show_path", defaultValue = true)) callContextLight.map(_.url) diff --git a/obp-api/src/main/scala/code/api/util/BerlinGroupCheck.scala b/obp-api/src/main/scala/code/api/util/BerlinGroupCheck.scala index 0dd184a670..a1061462e2 100644 --- a/obp-api/src/main/scala/code/api/util/BerlinGroupCheck.scala +++ b/obp-api/src/main/scala/code/api/util/BerlinGroupCheck.scala @@ -1,7 +1,9 @@ package code.api.util -import code.api.APIFailureNewStyle +import code.api.berlin.group.ConstantsBG +import code.api.{APIFailureNewStyle, RequestHeader} import code.api.util.APIUtil.{OBPReturnType, fullBoxOrException} +import code.api.util.BerlinGroupSigning.getHeaderValue import code.util.Helper.MdcLoggable import com.openbankproject.commons.model.User import com.openbankproject.commons.util.ApiVersion @@ -27,7 +29,7 @@ object BerlinGroupCheck extends MdcLoggable { private def validateHeaders(verb: String, url: String, reqHeaders: List[HTTPParam], forwardResult: (Box[User], Option[CallContext])): (Box[User], Option[CallContext]) = { val headerMap = reqHeaders.map(h => h.name.toLowerCase -> h).toMap - val missingHeaders = if(url.contains(ApiVersion.berlinGroupV13.urlPrefix) && url.endsWith("/consents")) + val missingHeaders = if(url.contains(ConstantsBG.berlinGroupVersion1.urlPrefix) && url.endsWith("/consents")) (berlinGroupMandatoryHeaders ++ berlinGroupMandatoryHeaderConsent).filterNot(headerMap.contains) else berlinGroupMandatoryHeaders.filterNot(headerMap.contains) @@ -43,8 +45,22 @@ object BerlinGroupCheck extends MdcLoggable { } } + def isTppRequestsWithoutPsuInvolvement(requestHeaders: List[HTTPParam]): Boolean = { + val psuIpAddress = getHeaderValue(RequestHeader.`PSU-IP-Address`, requestHeaders) + val psuDeviceId = getHeaderValue(RequestHeader.`PSU-Device-ID`, requestHeaders) + val psuDeviceNAme = getHeaderValue(RequestHeader.`PSU-Device-Name`, requestHeaders) + if(psuIpAddress == "0.0.0.0" || psuDeviceId == "no-psu-involved" || psuDeviceNAme == "no-psu-involved") { + logger.debug(s"isTppRequestsWithoutPsuInvolvement.psuIpAddress: $psuIpAddress") + logger.debug(s"isTppRequestsWithoutPsuInvolvement.psuDeviceId: $psuDeviceId") + logger.debug(s"isTppRequestsWithoutPsuInvolvement.psuDeviceNAme: $psuDeviceNAme") + true + } else { + false + } + } + def validate(body: Box[String], verb: String, url: String, reqHeaders: List[HTTPParam], forwardResult: (Box[User], Option[CallContext])): OBPReturnType[Box[User]] = { - if(url.contains(ApiVersion.berlinGroupV13.urlPrefix)) { + if(url.contains(ConstantsBG.berlinGroupVersion1.urlPrefix)) { validateHeaders(verb, url, reqHeaders, forwardResult) match { case (user, _) if user.isDefined || user == Empty => // All good. Chain another check // Verify signed request (Berlin Group) 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 83a3ca2255..295d96b330 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -1,5 +1,7 @@ package code.api.util +import code.api.berlin.group.ConstantsBG + import java.text.SimpleDateFormat import java.util.{Date, UUID} import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{ConsentAccessJson, PostConsentJson} @@ -256,7 +258,7 @@ object Consent extends MdcLoggable { case false => Failure(ErrorMessages.ConsentVerificationIssue) } - case Full(c) if c.apiStandard == ApiVersion.berlinGroupV13.apiStandard && // Berlin Group Consent + case Full(c) if c.apiStandard == ConstantsBG.berlinGroupVersion1.apiStandard && // Berlin Group Consent c.status.toLowerCase() != ConsentStatus.valid.toString => Failure(s"${ErrorMessages.ConsentStatusIssue}${ConsentStatus.valid.toString}.") case Full(c) if c.mStatus.toString().toUpperCase() != ConsentStatus.ACCEPTED.toString => @@ -569,9 +571,11 @@ object Consent extends MdcLoggable { logger.debug(s"End of net.liftweb.json.parse(jsonAsString).extract[ConsentJWT].checkConsent.consentBox: $consent") consentBox match { // Check is it Consent-JWT expired case (Full(true)) => // OK - // Update MappedConsent.usesSoFarTodayCounter field - val consentUpdatedBox = Consents.consentProvider.vend.updateBerlinGroupConsent(consentId, currentCounterState + 1) - logger.debug(s"applyBerlinGroupConsentRulesCommon.consentUpdatedBox: $consentUpdatedBox") + if(BerlinGroupCheck.isTppRequestsWithoutPsuInvolvement(callContext.requestHeaders)) { + // Update MappedConsent.usesSoFarTodayCounter field + val consentUpdatedBox = Consents.consentProvider.vend.updateBerlinGroupConsent(consentId, currentCounterState + 1) + logger.debug(s"applyBerlinGroupConsentRulesCommon.consentUpdatedBox: $consentUpdatedBox") + } applyConsentRules(consent, updatedCallContext) case failure@Failure(_, _, _) => // Handled errors Future(failure, Some(updatedCallContext)) @@ -598,7 +602,8 @@ object Consent extends MdcLoggable { Future(Failure("Cannot extract data from: " + consentId), Some(updatedCallContext)) } } else { - Future(Failure(ErrorMessages.TooManyRequests + s" ${RequestHeader.`Consent-ID`}: $consentId"), Some(updatedCallContext)) + val errorMessage = ErrorMessages.TooManyRequests + s" ${RequestHeader.`Consent-ID`}: $consentId" + Future(fullBoxOrException(Empty ~> APIFailureNewStyle(errorMessage, 429, Some(callContext.toLight))), Some(callContext)) } case failure@Failure(_, _, _) => Future(failure, Some(callContext)) @@ -779,6 +784,7 @@ object Consent extends MdcLoggable { val xRequestId: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`X-Request-ID`) val psuDeviceId: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`PSU-Device-ID`) val psuIpAddress: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`PSU-IP-Address`) + val psuGeoLocation: Option[HTTPParam] = callContext.map(_.requestHeaders).getOrElse(Nil).find(_.name == RequestHeader.`PSU-Geo-Location`) Future.sequence(accounts ::: balances ::: transactions) map { views => val json = ConsentJWT( createdByUserId = user.map(_.userId).getOrElse(""), @@ -793,7 +799,8 @@ object Consent extends MdcLoggable { tppNokRedirectUri.toList ::: xRequestId.toList ::: psuDeviceId.toList ::: - psuIpAddress.toList, + psuIpAddress.toList ::: + psuGeoLocation.toList, name = None, email = None, entitlements = Nil, @@ -1048,9 +1055,9 @@ object Consent extends MdcLoggable { def expireAllPreviousValidBerlinGroupConsents(consent: MappedConsent, updateTostatus: ConsentStatus): Boolean = { if(updateTostatus == ConsentStatus.valid && - consent.apiStandard == ApiVersion.berlinGroupV13.apiStandard) { + consent.apiStandard == ConstantsBG.berlinGroupVersion1.apiStandard) { MappedConsent.findAll( // Find all - By(MappedConsent.mApiStandard, ApiVersion.berlinGroupV13.apiStandard), // Berlin Group + By(MappedConsent.mApiStandard, ConstantsBG.berlinGroupVersion1.apiStandard), // Berlin Group By(MappedConsent.mRecurringIndicator, true), // recurring By(MappedConsent.mStatus, ConsentStatus.valid.toString), // and valid consents By(MappedConsent.mUserId, consent.userId), // for the same PSU diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 21ed948e71..937764aa26 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -268,6 +268,7 @@ object ErrorMessages { val OneTimePasswordExpired = "OBP-20211: The One Time Password (OTP) has expired. " val Oauth2IsNotRecognized = "OBP-20214: OAuth2 Access Token is not recognised at this instance." val Oauth2ValidateAccessTokenError = "OBP-20215: There was a problem validating the OAuth2 access token. " + val OneTimePasswordInvalid = "OBP-20216: The One Time Password (OTP) is invalid. " val AuthorizationHeaderAmbiguity = "OBP-20250: Request headers used for authorization are ambiguous. " val MissingMandatoryBerlinGroupHeaders= "OBP-20251: Missing mandatory request headers. " diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index b7bf2973a1..01ea366390 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8081,7 +8081,9 @@ trait APIMethods400 extends MdcLoggable { consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map { i => connectorEmptyResponse(i, callContext) } - _ <- Helper.booleanToFuture(ConsentUserAlreadyAdded, cc=callContext) { consent.userId != null } + _ <- Helper.booleanToFuture(ConsentUserAlreadyAdded, cc = cc.callContext) { + Option(consent.userId).forall(_.isBlank) // checks whether userId is not populated + } consent <- Future(Consents.consentProvider.vend.updateConsentUser(consentId, user)) map { i => connectorEmptyResponse(i, callContext) } 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 a7885cfba2..37c91d5203 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 @@ -1439,7 +1439,7 @@ trait APIMethods510 { nameOf(updateConsentUserIdByConsentId), "PUT", "/management/banks/BANK_ID/consents/CONSENT_ID/created-by-user", - "Update Consent Created by User by CONSENT_ID", + "Update Created by User of Consent by CONSENT_ID", s""" | |This endpoint is used to Update the User bound to a consent. 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 80bc6c3688..05b4bbb1ca 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 @@ -27,6 +27,7 @@ package code.api.v5_1_0 import code.api.Constant +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.ConsentAccessJson import code.api.util.APIUtil.{DateWithDay, DateWithSeconds, gitCommit, stringOrNull} import code.api.util._ @@ -941,8 +942,8 @@ object JSONFactory510 extends CustomJsonFormats { last_action_date = if (c.lastActionDate != null) new SimpleDateFormat(DateWithDay).format(c.lastActionDate) else null, last_usage_date = if (c.usesSoFarTodayCounterUpdatedAt != null) new SimpleDateFormat(DateWithSeconds).format(c.usesSoFarTodayCounterUpdatedAt) else null, jwt_payload = jwtPayload, - frequency_per_day = if(c.apiStandard == ApiVersion.berlinGroupV13.apiStandard) Some(c.frequencyPerDay) else None, - remaining_requests = if(c.apiStandard == ApiVersion.berlinGroupV13.apiStandard) Some(c.frequencyPerDay - c.usesSoFarTodayCounter) else None, + frequency_per_day = if(c.apiStandard == ConstantsBG.berlinGroupVersion1.apiStandard) Some(c.frequencyPerDay) else None, + remaining_requests = if(c.apiStandard == ConstantsBG.berlinGroupVersion1.apiStandard) Some(c.frequencyPerDay - c.usesSoFarTodayCounter) else None, api_standard = c.apiStandard, api_version = c.apiVersion ) diff --git a/obp-api/src/main/scala/code/scheduler/ConsentScheduler.scala b/obp-api/src/main/scala/code/scheduler/ConsentScheduler.scala index a3df0b335b..7d8113a60c 100644 --- a/obp-api/src/main/scala/code/scheduler/ConsentScheduler.scala +++ b/obp-api/src/main/scala/code/scheduler/ConsentScheduler.scala @@ -1,5 +1,6 @@ package code.scheduler +import code.api.berlin.group.ConstantsBG import code.api.util.APIUtil import code.consent.{ConsentStatus, MappedConsent} import code.util.Helper.MdcLoggable @@ -52,7 +53,7 @@ object ConsentScheduler extends MdcLoggable { val outdatedConsents = MappedConsent.findAll( By(MappedConsent.mStatus, ConsentStatus.received.toString), - By(MappedConsent.mApiStandard, ApiVersion.berlinGroupV13.apiStandard), + By(MappedConsent.mApiStandard, ConstantsBG.berlinGroupVersion1.apiStandard), By_<(MappedConsent.updatedAt, SchedulerUtil.someSecondsAgo(seconds)) ) @@ -78,7 +79,7 @@ object ConsentScheduler extends MdcLoggable { val expiredConsents = MappedConsent.findAll( By(MappedConsent.mStatus, ConsentStatus.valid.toString), - By(MappedConsent.mApiStandard, ApiVersion.berlinGroupV13.apiStandard), + By(MappedConsent.mApiStandard, ConstantsBG.berlinGroupVersion1.apiStandard), By_<(MappedConsent.mValidUntil, new Date()) ) diff --git a/obp-api/src/main/scala/code/snippet/BerlinGroupConsent.scala b/obp-api/src/main/scala/code/snippet/BerlinGroupConsent.scala index d27b96636d..00722bba43 100644 --- a/obp-api/src/main/scala/code/snippet/BerlinGroupConsent.scala +++ b/obp-api/src/main/scala/code/snippet/BerlinGroupConsent.scala @@ -393,7 +393,7 @@ class BerlinGroupConsent extends MdcLoggable with RestHelper with APIMethods510 s"$redirectUriValue?CONSENT_ID=${consentId}" ) case _ => - S.error("Cannot bet consent") + S.error(ErrorMessages.ConsentNotFound) } } @@ -411,7 +411,7 @@ class BerlinGroupConsent extends MdcLoggable with RestHelper with APIMethods510 s"/confirm-bg-consent-request-redirect-uri?CONSENT_ID=${consentId}" ) case _ => - S.error("Wrong OTP value") + S.error(ErrorMessages.OneTimePasswordInvalid) } } diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index b9ab1ad229..152cca1210 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -1,6 +1,7 @@ package code.api.ResourceDocs1_4_0 import code.api.ResourceDocs1_4_0.ResourceDocs140.ImplementationsResourceDocs +import code.api.berlin.group.ConstantsBG import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} import code.api.util.APIUtil.OAuth._ @@ -283,7 +284,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.3" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / ConstantsBG.berlinGroupVersion1.apiShortVersion / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -293,7 +294,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "BGv1.3" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / s"BG${ConstantsBG.berlinGroupVersion1.apiShortVersion}" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -540,7 +541,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint2.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.3" / "obp").GET + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / ConstantsBG.berlinGroupVersion1.apiShortVersion / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -550,7 +551,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint2.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "BGv1.3" / "obp").GET + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / s"BG${ConstantsBG.berlinGroupVersion1.apiShortVersion}" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] diff --git a/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala b/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala index a413c86f75..ddf244c088 100644 --- a/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala +++ b/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala @@ -1,7 +1,7 @@ package code.api.berlin.group.v1_3 import code.api.Constant -import code.api.Constant.{SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID} +import code.api.Constant.{SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID} import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3._ import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi import code.api.util.APIUtil @@ -9,10 +9,9 @@ import code.api.util.APIUtil.OAuth._ import code.api.util.ErrorMessages._ import code.api.v4_0_0.PostViewJsonV400 import code.consent.ConsentStatus -import code.model.dataAccess.{BankAccountRouting, MappedBankAccount} +import code.model.dataAccess.BankAccountRouting import code.setup.{APIResponse, DefaultUsers} import com.github.dwickern.macros.NameOf.nameOf -import com.openbankproject.commons.model.{AccountId, BankId, ErrorMessage} import com.openbankproject.commons.model.enums.AccountRoutingScheme import net.liftweb.json.Serialization.write import net.liftweb.mapper.By @@ -103,13 +102,40 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit user1, PostViewJsonV400(view_id = SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID, is_system = true) ) + grantUserAccessToViewViaEndpoint( + bankId, + accountId, + resourceUser1.userId, + user1, + PostViewJsonV400(view_id = SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID, is_system = true) + ) + grantUserAccessToViewViaEndpoint( + bankId, + accountId, + resourceUser1.userId, + user1, + PostViewJsonV400(view_id = SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID, is_system = true) + ) val requestGet = (V1_3_BG / "accounts" / accountId).GET <@ (user1) val response = makeGetRequest(requestGet) Then("We should get a 200 ") response.code should equal(200) - response.body.extract[AccountDetailsJsonV13].account.resourceId should be (accountId) + val jsonResponse = response.body.extract[AccountDetailsJsonV13] + jsonResponse.account.resourceId should be (accountId) + + jsonResponse.account._links.balances match { + case Some(link) => + link.href.contains(berlinGroupVersion1) shouldBe true + case None => // Nothing to check + } + jsonResponse.account._links.transactions match { + case Some(link) => + link.href.contains(berlinGroupVersion1) shouldBe true + case None => // Nothing to check + } + } } @@ -262,8 +288,9 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit Then("We should get a 201 ") response.code should equal(201) - response.body.extract[PostConsentResponseJson].consentId should not be (empty) - response.body.extract[PostConsentResponseJson].consentStatus should be (ConsentStatus.received.toString) + val jsonResponse = response.body.extract[PostConsentResponseJson] + jsonResponse.consentId should not be (empty) + jsonResponse.consentStatus should be (ConsentStatus.received.toString) } } diff --git a/obp-api/src/test/scala/code/api/berlin/group/v1_3/BerlinGroupServerSetupV1_3.scala b/obp-api/src/test/scala/code/api/berlin/group/v1_3/BerlinGroupServerSetupV1_3.scala index 466de7774c..3c55ed5ee2 100644 --- a/obp-api/src/test/scala/code/api/berlin/group/v1_3/BerlinGroupServerSetupV1_3.scala +++ b/obp-api/src/test/scala/code/api/berlin/group/v1_3/BerlinGroupServerSetupV1_3.scala @@ -2,20 +2,21 @@ package code.api.berlin.group.v1_3 import code.api.Constant import code.api.Constant.SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID +import code.api.berlin.group.ConstantsBG import code.api.util.APIUtil.OAuth._ -import code.api.util.APIUtil.OAuth.{Consumer, Token} import code.api.v3_0_0.ViewJsonV300 import code.api.v4_0_0.{PostAccountAccessJsonV400, PostViewJsonV400} import code.setup.ServerSetupWithTestData import code.views.Views -import com.openbankproject.commons.util.ApiVersion import dispatch.Req import net.liftweb.json.Serialization.write import org.scalatest.Tag trait BerlinGroupServerSetupV1_3 extends ServerSetupWithTestData { + + val berlinGroupVersion1: String = ConstantsBG.berlinGroupVersion1.apiShortVersion object BerlinGroupV1_3 extends Tag("BerlinGroup_v1_3") - val V1_3_BG = baseRequest / ApiVersion.berlinGroupV13.urlPrefix / "v1.3" + val V1_3_BG = baseRequest / ConstantsBG.berlinGroupVersion1.urlPrefix / ConstantsBG.berlinGroupVersion1.apiShortVersion def v4_0_0_Request: Req = baseRequest / "obp" / "v4.0.0" override def beforeEach() = { diff --git a/obp-api/src/test/scala/code/util/APIUtilHeavyTest.scala b/obp-api/src/test/scala/code/util/APIUtilHeavyTest.scala index ade584eb3b..722909e798 100644 --- a/obp-api/src/test/scala/code/util/APIUtilHeavyTest.scala +++ b/obp-api/src/test/scala/code/util/APIUtilHeavyTest.scala @@ -30,6 +30,7 @@ package code.util import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.api.UKOpenBanking.v2_0_0.{APIMethods_UKOpenBanking_200, OBP_UKOpenBanking_200} import code.api.UKOpenBanking.v3_1_0.{APIMethods_AccountAccessApi, OBP_UKOpenBanking_310} +import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.OBP_BERLIN_GROUP_1_3 import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi import code.api.util.APIUtil.OBPEndpoint @@ -42,6 +43,8 @@ import code.views.system.ViewDefinition import com.openbankproject.commons.util.ApiVersion class APIUtilHeavyTest extends V400ServerSetup with PropsReset { + + val bgVersion = ConstantsBG.berlinGroupVersion1.apiShortVersion feature("test APIUtil.versionIsAllowed method") { //This mean, we are only disabled the v4.0.0, all other versions should be enabled @@ -101,70 +104,72 @@ class APIUtilHeavyTest extends V400ServerSetup with PropsReset { feature("test APIUtil.getAllowedEndpoints method") { - val obpEndpointsV400: List[OBPEndpoint] = OBPAPI4_0_0.endpointsOf4_0_0.toList - val obpAllResourceDocsV400 = Implementations4_0_0.resourceDocs + scenario(s"Test the APIUtil.getAllowedEndpoints method") { + val obpEndpointsV400: List[OBPEndpoint] = OBPAPI4_0_0.endpointsOf4_0_0.toList + val obpAllResourceDocsV400 = Implementations4_0_0.resourceDocs - val allowedEndpoints: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(obpEndpointsV400, obpAllResourceDocsV400).toList + val allowedEndpoints: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(obpEndpointsV400, obpAllResourceDocsV400).toList - val allowedOperationIds = allowedEndpoints.map(_.operationId) + val allowedOperationIds = allowedEndpoints.map(_.operationId) - allowedOperationIds contains("OBPv4.0.0-getLogoutLink") should be (true) + allowedOperationIds contains("OBPv4.0.0-getLogoutLink") should be (true) - setPropsValues( - "api_disabled_endpoints" -> "[OBPv4.0.0-getLogoutLink,OBPv4.0.0-getMapperDatabaseInfo,OBPv4.0.0-callsLimit,OBPv4.0.0-getBanks,OBPv4.0.0-ibanChecker]", - "api_enabled_endpoints" -> "[]" - ) - val allowedEndpoints2: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(obpEndpointsV400, obpAllResourceDocsV400).toList + setPropsValues( + "api_disabled_endpoints" -> "[OBPv4.0.0-getLogoutLink,OBPv4.0.0-getMapperDatabaseInfo,OBPv4.0.0-callsLimit,OBPv4.0.0-getBanks,OBPv4.0.0-ibanChecker]", + "api_enabled_endpoints" -> "[]" + ) + val allowedEndpoints2: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(obpEndpointsV400, obpAllResourceDocsV400).toList - val allowedOperationIds2 = allowedEndpoints2.map(_.operationId) + val allowedOperationIds2 = allowedEndpoints2.map(_.operationId) - allowedOperationIds2 contains("OBPv4.0.0-getLogoutLink") should be (false) - allowedOperationIds2 contains("OBPv4.0.0-getMapperDatabaseInfo") should be (false) - allowedOperationIds2 contains("OBPv4.0.0-callsLimit") should be (false) + allowedOperationIds2 contains("OBPv4.0.0-getLogoutLink") should be (false) + allowedOperationIds2 contains("OBPv4.0.0-getMapperDatabaseInfo") should be (false) + allowedOperationIds2 contains("OBPv4.0.0-callsLimit") should be (false) - val bgResourceDocsV13 = APIMethods_AccountInformationServiceAISApi.resourceDocs - val bgEndpointsV13 = APIMethods_AccountInformationServiceAISApi.endpoints + val bgResourceDocsV13 = APIMethods_AccountInformationServiceAISApi.resourceDocs + val bgEndpointsV13 = APIMethods_AccountInformationServiceAISApi.endpoints - setPropsValues( - "api_disabled_endpoints" -> "[BGv1.3-createConsent,BGv1.3-deleteConsent]", - "api_enabled_endpoints" -> "[]" - ) - - val allowedEndpoints3: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(bgEndpointsV13, bgResourceDocsV13).toList - val allowedOperationIds3 = allowedEndpoints3.map(_.operationId) - - allowedOperationIds3 contains("BGv1.3-getCardAccountTransactionList") should be (true) - allowedOperationIds3 contains("BGv1.3-createConsent") should be (false) - allowedOperationIds3 contains("BGv1.3-deleteConsent") should be (false) + setPropsValues( + "api_disabled_endpoints" -> s"[BG${bgVersion}-createConsent,BG${bgVersion}-deleteConsent]", + "api_enabled_endpoints" -> "[]" + ) - val ukResourceDocsV31 = APIMethods_AccountAccessApi.resourceDocs - val ukEndpointsV31 = APIMethods_AccountAccessApi.endpoints + val allowedEndpoints3: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(bgEndpointsV13, bgResourceDocsV13).toList + val allowedOperationIds3 = allowedEndpoints3.map(_.operationId) - setPropsValues( - "api_disabled_endpoints" -> "[UKv3.1-createAccountAccessConsents,UKv3.1-deleteConsent]", - "api_enabled_endpoints" -> "[]" - ) + allowedOperationIds3 contains(s"BG${bgVersion}-getCardAccountTransactionList") should be (true) + allowedOperationIds3 contains(s"BG${bgVersion}-createConsent") should be (false) + allowedOperationIds3 contains(s"BG${bgVersion}-deleteConsent") should be (false) - val allowedEndpoints4: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(ukEndpointsV31, ukResourceDocsV31).toList - val allowedOperationIds4 = allowedEndpoints4.map(_.operationId) + val ukResourceDocsV31 = APIMethods_AccountAccessApi.resourceDocs + val ukEndpointsV31 = APIMethods_AccountAccessApi.endpoints - allowedOperationIds4 contains("UKv3.1-getAccountAccessConsentsConsentId") should be (true) - allowedOperationIds4 contains("UKv3.1-createAccountAccessConsents") should be (false) - allowedOperationIds4 contains("UKv3.1-deleteConsent") should be (false) + setPropsValues( + "api_disabled_endpoints" -> "[UKv3.1-createAccountAccessConsents,UKv3.1-deleteConsent]", + "api_enabled_endpoints" -> "[]" + ) - setPropsValues( - "api_disabled_endpoints" -> "[]", - "api_enabled_endpoints" -> "[UKv3.1-createAccountAccessConsents]" - ) + val allowedEndpoints4: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(ukEndpointsV31, ukResourceDocsV31).toList + val allowedOperationIds4 = allowedEndpoints4.map(_.operationId) - val allowedEndpoints5: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(ukEndpointsV31, ukResourceDocsV31).toList - val allowedOperationIds5 = allowedEndpoints5.map(_.operationId) + allowedOperationIds4 contains("UKv3.1-getAccountAccessConsentsConsentId") should be (true) + allowedOperationIds4 contains("UKv3.1-createAccountAccessConsents") should be (false) + allowedOperationIds4 contains("UKv3.1-deleteConsent") should be (false) - allowedOperationIds5.length should be (1) - allowedOperationIds5 contains("UKv3.1-createAccountAccessConsents") should be (true) - allowedOperationIds5 contains("UKv3.1-deleteConsent") should be (false) + setPropsValues( + "api_disabled_endpoints" -> "[]", + "api_enabled_endpoints" -> "[UKv3.1-createAccountAccessConsents]" + ) + + val allowedEndpoints5: List[APIUtil.ResourceDoc] = APIUtil.getAllowedResourceDocs(ukEndpointsV31, ukResourceDocsV31).toList + val allowedOperationIds5 = allowedEndpoints5.map(_.operationId) + + allowedOperationIds5.length should be (1) + allowedOperationIds5 contains("UKv3.1-createAccountAccessConsents") should be (true) + allowedOperationIds5 contains("UKv3.1-deleteConsent") should be (false) + } } feature("test APIUtil.getPermissionPairFromViewDefinition method") {