mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 17:17:09 +00:00
Merge pull request #1383 from hongwei1/develop
added the new endpoint --getBankAccountsBalances, added tests for swagger
This commit is contained in:
commit
ad119f52dc
@ -360,6 +360,17 @@
|
||||
<artifactId>client</artifactId>
|
||||
<version>4.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger.parser.v3</groupId>
|
||||
<artifactId>swagger-parser</artifactId>
|
||||
<version>2.0.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.9.8</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
### Base configuration
|
||||
|
||||
## Which data connector to use, if config star as connector, should make sure other connector config appropriate and works
|
||||
## Which data connector to use, if config `star` as connector, please also check `starConnector_supported_types`
|
||||
connector=mapped
|
||||
#connector=mongodb
|
||||
#connector=kafka
|
||||
@ -17,6 +17,9 @@ connector=mapped
|
||||
#connector=star
|
||||
#connector=...
|
||||
|
||||
## if connector = star, then need to set which connectors will be used. For now, obp support rest, akka, kafka. If you set kafka, then you need to start the kafka server.
|
||||
#starConnector_supported_types=rest,akka,kafka
|
||||
|
||||
## whether export LocalMappedConnector methods as endpoints, it is just for develop, default is false
|
||||
#connector.export.LocalMappedConnector=false
|
||||
|
||||
@ -32,9 +35,9 @@ connector=mapped
|
||||
#connector.cache.ttl.seconds.getCounterpartiesFromTransaction=10
|
||||
#connector.cache.ttl.seconds.APIMethods121.getTransactions=10
|
||||
|
||||
## MethodRouting cache time-to-live in seconds, caching defaults to 30 seconds
|
||||
## MethodRouting cache time-to-live in seconds
|
||||
#methodRouting.cache.ttl.seconds=30
|
||||
## webui props cache time-to-live in seconds, caching defaults to 20 seconds
|
||||
## webui props cache time-to-live in seconds
|
||||
#webui.props.cache.ttl.seconds=20
|
||||
|
||||
## enable logging all the database queries in log file
|
||||
|
||||
@ -220,7 +220,7 @@ class Boot extends MdcLoggable {
|
||||
|
||||
// ensure our relational database's tables are created/fit the schema
|
||||
val connector = APIUtil.getPropsValue("connector").openOrThrowException("no connector set")
|
||||
if(connector != "mongodb" || connector == "star")
|
||||
if(connector != "mongodb")
|
||||
schemifyAll()
|
||||
|
||||
// This sets up MongoDB config (for the mongodb connector)
|
||||
@ -242,9 +242,11 @@ class Boot extends MdcLoggable {
|
||||
|
||||
val actorSystem = ObpActorSystem.startLocalActorSystem()
|
||||
connector match {
|
||||
case ("akka_vDec2018"| "star") =>
|
||||
case "akka_vDec2018" =>
|
||||
// Start Actor system of Akka connector
|
||||
ObpActorSystem.startNorthSideAkkaConnectorActorSystem()
|
||||
case "star" if (APIUtil.getPropsValue("starConnector_supported_types","").split(",").contains("akka")) =>
|
||||
ObpActorSystem.startNorthSideAkkaConnectorActorSystem()
|
||||
case _ => // Do nothing
|
||||
}
|
||||
|
||||
@ -336,7 +338,7 @@ class Boot extends MdcLoggable {
|
||||
|
||||
WebhookHelperActors.startLocalWebhookHelperWorkers(actorSystem)
|
||||
|
||||
if (connector.startsWith("kafka") || connector == "star") {
|
||||
if (connector.startsWith("kafka") || (connector == "star" && APIUtil.getPropsValue("starConnector_supported_types","").split(",").contains("kafka"))) {
|
||||
logger.info(s"KafkaHelperActors.startLocalKafkaHelperWorkers( ${actorSystem} ) starting")
|
||||
KafkaHelperActors.startLocalKafkaHelperWorkers(actorSystem)
|
||||
// Start North Side Consumer if it's not already started
|
||||
|
||||
@ -257,15 +257,15 @@ object APIBuilderModel
|
||||
|
||||
def overwriteApiCode(apiSource: Source, jsonFactorySource:Source =jsonFactorySource) = {
|
||||
//APIMethods_APIBuilder.scala
|
||||
overwriteCurrentFile(apiSource,"src/main/scala/code/api/builder/APIMethods_APIBuilder.scala")
|
||||
overwriteCurrentFile(apiSource,"obp-api/src/main/scala/code/api/builder/APIMethods_APIBuilder.scala")
|
||||
|
||||
//JsonFactory_APIBuilder.scala
|
||||
overwriteCurrentFile(jsonFactorySource, "src/main/scala/code/api/builder/JsonFactory_APIBuilder.scala")
|
||||
overwriteCurrentFile(jsonFactorySource, "obp-api/src/main/scala/code/api/builder/JsonFactory_APIBuilder.scala")
|
||||
|
||||
println("Congratulations! You make the new APIs. Please restart OBP-API server!")
|
||||
}
|
||||
|
||||
val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("src/main/scala/code/api/APIBuilder/APIModelSource.json")
|
||||
val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("obp-api/src/main/scala/code/api/APIBuilder/APIModelSource.json")
|
||||
|
||||
//"/templates"
|
||||
val apiUrl= getApiUrl(jsonJValueFromFile)
|
||||
|
||||
@ -36,7 +36,7 @@ object APIBuilder
|
||||
{
|
||||
def main(args: Array[String]): Unit = overwriteApiCode(apiSource,jsonFactorySource)
|
||||
|
||||
val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("src/main/scala/code/api/APIBuilder/apiResourceDoc/apisResource.json")
|
||||
val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("obp-api/src/main/scala/code/api/APIBuilder/apiResourceDoc/apisResource.json")
|
||||
|
||||
val resourceDocsJObject= jsonJValueFromFile.\("resource_docs").children.asInstanceOf[List[JObject]]
|
||||
|
||||
@ -210,7 +210,7 @@ object APIBuilder
|
||||
cc => {
|
||||
for {
|
||||
u <- $getMultipleAuthenticationStatement
|
||||
jsonStringFromFile = scala.io.Source.fromFile("src/main/scala/code/api/APIBuilder/apisResource.json").mkString
|
||||
jsonStringFromFile = scala.io.Source.fromFile("obp-api/src/main/scala/code/api/APIBuilder/apisResource.json").mkString
|
||||
jsonJValueFromFile = json.parse(jsonStringFromFile)
|
||||
resourceDocsJObject= jsonJValueFromFile.\("resource_docs").children.asInstanceOf[List[JObject]]
|
||||
getMethodJValue = resourceDocsJObject.filter(jObject => jObject.\("request_verb") == JString("GET")&& !jObject.\("request_url").asInstanceOf[JString].values.contains("_ID")).head
|
||||
@ -380,7 +380,7 @@ trait APIMethods_APIBuilder
|
||||
|
||||
val ImplementationsBuilderAPI = new Object()
|
||||
{
|
||||
val apiVersion: ApiVersion = ApiVersion.apiBuilder
|
||||
val apiVersion = ApiVersion.apiBuilder
|
||||
val resourceDocs = ArrayBuffer[ResourceDoc]()
|
||||
val apiRelations = ArrayBuffer[ApiRelation]()
|
||||
val codeContext = CodeContext(resourceDocs, apiRelations)
|
||||
|
||||
@ -35,7 +35,7 @@ import scala.meta._
|
||||
|
||||
object APIBuilderSwagger {
|
||||
def main(args: Array[String]): Unit = overwriteApiCode(apiSource,jsonFactorySource)
|
||||
val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("src/main/scala/code/api/APIBuilder/swagger/swaggerResource.json")
|
||||
val jsonJValueFromFile: JValue = APIUtil.getJValueFromFile("obp-api/src/main/scala/code/api/APIBuilder/swagger/swaggerResource.json")
|
||||
|
||||
val getSingleApiResponseBody: JValue = jsonJValueFromFile \\("foo")\"foo"\"value"
|
||||
//"template"
|
||||
@ -328,7 +328,7 @@ trait APIMethods_APIBuilder
|
||||
|
||||
val ImplementationsBuilderAPI = new Object()
|
||||
{
|
||||
val apiVersion: ApiVersion = ApiVersion.apiBuilder
|
||||
val apiVersion = ApiVersion.apiBuilder
|
||||
val resourceDocs = ArrayBuffer[ResourceDoc]()
|
||||
val apiRelations = ArrayBuffer[ApiRelation]()
|
||||
val codeContext = CodeContext(resourceDocs, apiRelations)
|
||||
|
||||
@ -5,7 +5,7 @@ import java.util.Date
|
||||
import code.api.Constant
|
||||
import code.api.UKOpenBanking.v2_0_0.JSONFactory_UKOpenBanking_200
|
||||
import code.api.UKOpenBanking.v2_0_0.JSONFactory_UKOpenBanking_200.{Account, AccountBalancesUKV200, AccountInner, AccountList, Accounts, BalanceJsonUKV200, BalanceUKOpenBankingJson, BankTransactionCodeJson, CreditLineJson, DataJsonUKV200, Links, MetaBisJson, MetaInnerJson, TransactionCodeJson, TransactionInnerJson, TransactionsInnerJson, TransactionsJsonUKV200}
|
||||
import code.api.berlin.group.v1.JSONFactory_BERLIN_GROUP_1.{AccountBalance, AccountBalances, AmountOfMoneyV1, ClosingBookedBody, ExpectedBody, TransactionJsonV1, TransactionsJsonV1, ViewAccount}
|
||||
import code.api.berlin.group.v1.JSONFactory_BERLIN_GROUP_1.{AccountBalanceV1, AccountBalances, AmountOfMoneyV1, Balances, ClosingBookedBody, CoreAccountJsonV1, CoreAccountsJsonV1, ExpectedBody, TransactionJsonV1, Transactions, TransactionsJsonV1, ViewAccount}
|
||||
import code.api.util.APIUtil.{defaultJValue, _}
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.util.{ApiTrigger, ExampleValue}
|
||||
@ -15,6 +15,8 @@ import code.api.v3_0_0.JSONFactory300.createBranchJsonV300
|
||||
import code.api.v3_0_0.custom.JSONFactoryCustom300
|
||||
import code.api.v3_0_0.{LobbyJsonV330, _}
|
||||
import code.api.v3_1_0.{BadLoginStatusJson, ContactDetailsJson, InviteeJson, ObpApiLoopbackJson, PhysicalCardWithAttributesJsonV310, PutUpdateCustomerEmailJsonV310, _}
|
||||
import code.api.v3_0_0.{EmptyElasticSearch, LobbyJsonV330, NewModeratedCoreAccountJsonV300, _}
|
||||
import code.api.v3_1_0.{AccountBalanceV310, AccountsBalancesV310Json, BadLoginStatusJson, ContactDetailsJson, InviteeJson, ObpApiLoopbackJson, PhysicalCardWithAttributesJsonV310, PutUpdateCustomerEmailJsonV310, _}
|
||||
import code.branches.Branches.{Branch, DriveUpString, LobbyString}
|
||||
import code.sandbox.SandboxData
|
||||
import code.transactionrequests.TransactionRequests.TransactionRequestTypes._
|
||||
@ -25,6 +27,8 @@ import com.openbankproject.commons.model
|
||||
import com.openbankproject.commons.model.PinResetReason.{FORGOT, GOOD_SECURITY_PRACTICE}
|
||||
import com.openbankproject.commons.model.{ViewBasic, _}
|
||||
import com.openbankproject.commons.util.ReflectUtils
|
||||
import com.openbankproject.commons.model.{AccountBalance, GeoTag, ViewBasic, _}
|
||||
import net.liftweb.json
|
||||
|
||||
import scala.collection.immutable.List
|
||||
|
||||
@ -2651,13 +2655,13 @@ object SwaggerDefinitionsJSON {
|
||||
lastActionDateTime = DateWithDayExampleObject
|
||||
)
|
||||
|
||||
val accountBalance = AccountBalance(
|
||||
val accountBalanceV1 = AccountBalanceV1(
|
||||
closingBooked = closingBookedBody,
|
||||
expected = expectedBody
|
||||
)
|
||||
|
||||
val accountBalances = AccountBalances(
|
||||
`balances` = List(accountBalance)
|
||||
`balances` = List(accountBalanceV1)
|
||||
)
|
||||
|
||||
val transactionJsonV1 = TransactionJsonV1(
|
||||
@ -3414,7 +3418,21 @@ object SwaggerDefinitionsJSON {
|
||||
val elasticSearchQuery = ElasticSearchQuery(emptyElasticSearch)
|
||||
|
||||
val elasticSearchJsonV300 = ElasticSearchJsonV300(elasticSearchQuery)
|
||||
|
||||
val accountBalanceV310 = AccountBalanceV310(
|
||||
id = accountIdExample.value,
|
||||
label = labelExample.value,
|
||||
bank_id = bankIdExample.value,
|
||||
account_routings = List(accountRouting),
|
||||
balance = amountOfMoney
|
||||
)
|
||||
|
||||
val accountBalancesV310Json = AccountsBalancesV310Json(
|
||||
accounts = List(accountBalanceV310),
|
||||
overall_balance = amountOfMoney,
|
||||
overall_balance_date = DateWithMsExampleObject
|
||||
)
|
||||
|
||||
//The common error or success format.
|
||||
//Just some helper format to use in Json
|
||||
case class NoSupportYet()
|
||||
|
||||
@ -209,8 +209,8 @@ The TPP sends a request to the ASPSP for retrieving the list of the PSU payment
|
||||
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
|
||||
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u, bankId)
|
||||
|
||||
Full(accounts) <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts,callContext)}
|
||||
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
|
||||
} yield {
|
||||
(createTransactionListJSON(accounts), callContext)
|
||||
|
||||
@ -57,9 +57,9 @@ object APIMethods_UKOpenBanking_200 extends RestHelper{
|
||||
for {
|
||||
(Full(u), callContext) <- authorizedAccess(cc)
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u)
|
||||
accounts <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
} yield {
|
||||
(JSONFactory_UKOpenBanking_200.createAccountsListJSON(accounts.getOrElse(Nil)), callContext)
|
||||
(JSONFactory_UKOpenBanking_200.createAccountsListJSON(accounts), callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,9 +144,9 @@ object APIMethods_UKOpenBanking_200 extends RestHelper{
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u) map {
|
||||
_.filter(_.accountId.value == accountId.value)
|
||||
}
|
||||
accounts <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
} yield {
|
||||
(JSONFactory_UKOpenBanking_200.createAccountJSON(accounts.getOrElse(Nil)), callContext)
|
||||
(JSONFactory_UKOpenBanking_200.createAccountJSON(accounts), callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,10 +229,10 @@ object APIMethods_UKOpenBanking_200 extends RestHelper{
|
||||
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u)
|
||||
|
||||
accounts <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
|
||||
} yield {
|
||||
(JSONFactory_UKOpenBanking_200.createBalancesJSON(accounts.getOrElse(Nil)), callContext)
|
||||
(JSONFactory_UKOpenBanking_200.createBalancesJSON(accounts), callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package code.api.UKOpenBanking.v3_1_0
|
||||
|
||||
import code.api.berlin.group.v1_3.JvalueCaseClass
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ApiTag
|
||||
import code.api.util.{ApiTag, NewStyle}
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.bankconnectors.Connector
|
||||
@ -110,9 +110,9 @@ object APIMethods_AccountsApi extends RestHelper {
|
||||
for {
|
||||
(Full(u), callContext) <- authorizedAccess(cc)
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u)
|
||||
accounts <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
} yield {
|
||||
(JSONFactory_UKOpenBanking_310.createAccountsListJSON(accounts.getOrElse(Nil)), callContext)
|
||||
(JSONFactory_UKOpenBanking_310.createAccountsListJSON(accounts), callContext)
|
||||
}
|
||||
|
||||
}
|
||||
@ -202,9 +202,9 @@ object APIMethods_AccountsApi extends RestHelper {
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u) map {
|
||||
_.filter(_.accountId.value == accountId.value)
|
||||
}
|
||||
accounts <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
} yield {
|
||||
(JSONFactory_UKOpenBanking_310.createAccountJSON(accounts.getOrElse(Nil)), callContext)
|
||||
(JSONFactory_UKOpenBanking_310.createAccountJSON(accounts), callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,10 +222,10 @@ object APIMethods_BalancesApi extends RestHelper {
|
||||
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u)
|
||||
|
||||
accounts <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
|
||||
} yield {
|
||||
(JSONFactory_UKOpenBanking_310.createBalancesJSON(accounts.getOrElse(Nil)), callContext)
|
||||
(JSONFactory_UKOpenBanking_310.createBalancesJSON(accounts), callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1022,7 +1022,7 @@ object APIMethods_TransactionsApi extends RestHelper {
|
||||
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u)
|
||||
|
||||
Full(accounts) <- Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
|
||||
transactionAndTransactionRequestTuple = for{
|
||||
bankAccount <- accounts
|
||||
|
||||
@ -44,11 +44,11 @@ object JSONFactory_BERLIN_GROUP_1 extends CustomJsonFormats {
|
||||
amount : AmountOfMoneyV1,
|
||||
lastActionDateTime: Date
|
||||
)
|
||||
case class AccountBalance(
|
||||
case class AccountBalanceV1(
|
||||
closingBooked: ClosingBookedBody,
|
||||
expected: ExpectedBody
|
||||
)
|
||||
case class AccountBalances(`balances`: List[AccountBalance])
|
||||
case class AccountBalances(`balances`: List[AccountBalanceV1])
|
||||
|
||||
case class TransactionsJsonV1(
|
||||
transactions_booked: List[TransactionJsonV1],
|
||||
@ -93,7 +93,7 @@ object JSONFactory_BERLIN_GROUP_1 extends CustomJsonFormats {
|
||||
val sumOfAll = (BigDecimal(moderatedAccount.balance) + sumOfAllUncompletedTransactionrequests).toString()
|
||||
|
||||
AccountBalances(
|
||||
AccountBalance(
|
||||
AccountBalanceV1(
|
||||
closingBooked = ClosingBookedBody(
|
||||
amount = AmountOfMoneyV1(currency = moderatedAccount.currency.getOrElse(""), content = moderatedAccount.balance),
|
||||
date = APIUtil.DateWithDayFormat.format(latestCompletedEndDate)
|
||||
|
||||
@ -270,10 +270,10 @@ of the PSU at this ASPSP.
|
||||
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u, bankId)
|
||||
|
||||
Full((coreAccounts)) <- {Connector.connector.vend.getBankAccounts(availablePrivateAccounts, callContext)}
|
||||
(accounts, callContext)<- NewStyle.function.getBankAccounts(availablePrivateAccounts, callContext)
|
||||
|
||||
} yield {
|
||||
(JSONFactory_BERLIN_GROUP_1_3.createAccountListJson(coreAccounts, u), callContext)
|
||||
(JSONFactory_BERLIN_GROUP_1_3.createAccountListJson(accounts, u), callContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
package code.api.builder
|
||||
import java.util.UUID
|
||||
|
||||
import code.api.builder.JsonFactory_APIBuilder._
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.{ApiVersion, CustomJsonFormats}
|
||||
import code.api.util.ApiVersion
|
||||
import code.api.util.ErrorMessages._
|
||||
import net.liftweb.common.Full
|
||||
import net.liftweb.http.rest.RestHelper
|
||||
@ -13,7 +12,6 @@ import net.liftweb.json.Extraction._
|
||||
import net.liftweb.json._
|
||||
import net.liftweb.mapper.By
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
import scala.collection.immutable.Nil
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
trait APIMethods_APIBuilder { self: RestHelper =>
|
||||
@ -22,10 +20,10 @@ trait APIMethods_APIBuilder { self: RestHelper =>
|
||||
val resourceDocs = ArrayBuffer[ResourceDoc]()
|
||||
val apiRelations = ArrayBuffer[ApiRelation]()
|
||||
val codeContext = CodeContext(resourceDocs, apiRelations)
|
||||
implicit val formats = CustomJsonFormats.formats
|
||||
val TemplateNotFound = "OBP-31001: Template not found. Please specify a valid value for TEMPLATE_ID."
|
||||
def endpointsOfBuilderAPI = getTemplates :: getTemplate :: createTemplate :: deleteTemplate :: Nil
|
||||
resourceDocs += ResourceDoc(getTemplates, apiVersion, "getTemplates", "GET", "/templates", "Get Templates", "Return All Templates", emptyObjectJson, templatesJson, List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
implicit val formats = code.api.util.CustomJsonFormats.formats
|
||||
val TemplatesNotFound = "OBP-31001: Templates not found. Please specify a valid value for TEMPLATES_ID."
|
||||
def endpointsOfBuilderAPI = getTemplates :: createTemplate :: getTemplate :: deleteTemplate :: Nil
|
||||
resourceDocs += ResourceDoc(getTemplates, apiVersion, "getTemplates", "GET", "/templates", "Get Templates", "Return All my templates. Authentication is Mandatory.", emptyObjectJson, templatesJson, List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
lazy val getTemplates: OBPEndpoint = {
|
||||
case ("templates" :: Nil) JsonGet req =>
|
||||
cc => {
|
||||
@ -34,16 +32,7 @@ trait APIMethods_APIBuilder { self: RestHelper =>
|
||||
}
|
||||
}
|
||||
}
|
||||
resourceDocs += ResourceDoc(getTemplate, apiVersion, "getTemplate", "GET", "/templates/TEMPLATE_ID", "Get Template", "Return One Template By Id", emptyObjectJson, templateJson, List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
lazy val getTemplate: OBPEndpoint = {
|
||||
case ("templates" :: templateId :: Nil) JsonGet _ =>
|
||||
cc => {
|
||||
for (u <- cc.user ?~ UserNotLoggedIn; template <- APIBuilder_Connector.getTemplateById(templateId) ?~! TemplateNotFound; templateJson = JsonFactory_APIBuilder.createTemplate(template); jsonObject: JValue = decompose(templateJson)) yield {
|
||||
successJsonResponse(jsonObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
resourceDocs += ResourceDoc(createTemplate, apiVersion, "createTemplate", "POST", "/templates", "Create Template", "Create One Template", createTemplateJson, templateJson, List(UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
resourceDocs += ResourceDoc(createTemplate, apiVersion, "createTemplate", "POST", "/templates", "Create Template", "Create template. Authentication is Mandatory.", createTemplateJson, templateJson, List(UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
lazy val createTemplate: OBPEndpoint = {
|
||||
case ("templates" :: Nil) JsonPost json -> _ =>
|
||||
cc => {
|
||||
@ -52,15 +41,20 @@ trait APIMethods_APIBuilder { self: RestHelper =>
|
||||
}
|
||||
}
|
||||
}
|
||||
resourceDocs += ResourceDoc(deleteTemplate, apiVersion, "deleteTemplate", "DELETE", "/templates/TEMPLATE_ID", "Delete Template", "Delete One Template", emptyObjectJson, emptyObjectJson.copy("true"), List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
resourceDocs += ResourceDoc(getTemplate, apiVersion, "getTemplate", "GET", "/templates/{template_id}", "Get Template", "Return one template. Authentication is Mandatory.", emptyObjectJson, templateJson, List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
lazy val getTemplate: OBPEndpoint = {
|
||||
case ("templates" :: templateId :: Nil) JsonGet _ =>
|
||||
cc => {
|
||||
for (u <- cc.user ?~ UserNotLoggedIn; template <- APIBuilder_Connector.getTemplateById(templateId) ?~! TemplatesNotFound; templateJson = JsonFactory_APIBuilder.createTemplate(template); jsonObject: JValue = decompose(templateJson)) yield {
|
||||
successJsonResponse(jsonObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
resourceDocs += ResourceDoc(deleteTemplate, apiVersion, "deleteTemplate", "DELETE", "/templates/{template_id}", "Delete Template", "Delete template. Authentication is Mandatory.", emptyObjectJson, emptyObjectJson.copy("true"), List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), apiTagApiBuilder :: Nil)
|
||||
lazy val deleteTemplate: OBPEndpoint = {
|
||||
case ("templates" :: templateId :: Nil) JsonDelete _ =>
|
||||
cc => {
|
||||
for (
|
||||
u <- cc.user ?~ UserNotLoggedIn;
|
||||
template <- APIBuilder_Connector.getTemplateById(templateId) ?~! TemplateNotFound;
|
||||
deleted <- APIBuilder_Connector.deleteTemplate(templateId)
|
||||
) yield {
|
||||
for (u <- cc.user ?~ UserNotLoggedIn; template <- APIBuilder_Connector.getTemplateById(templateId) ?~! TemplatesNotFound; deleted <- APIBuilder_Connector.deleteTemplate(templateId)) yield {
|
||||
if (deleted) noContentJsonResponse else errorJsonResponse("Delete not completed")
|
||||
}
|
||||
}
|
||||
@ -68,25 +62,25 @@ trait APIMethods_APIBuilder { self: RestHelper =>
|
||||
}
|
||||
}
|
||||
object APIBuilder_Connector {
|
||||
val allAPIBuilderModels = List(MappedTemplate_4824100653501473508)
|
||||
def createTemplate(createTemplateJson: CreateTemplateJson) = Full(MappedTemplate_4824100653501473508.create.mTemplateId(generateUUID()).mAuthor(createTemplateJson.author).mPages(createTemplateJson.pages).mPoints(createTemplateJson.points).saveMe())
|
||||
def getTemplates() = Full(MappedTemplate_4824100653501473508.findAll())
|
||||
def getTemplateById(templateId: String) = MappedTemplate_4824100653501473508.find(By(MappedTemplate_4824100653501473508.mTemplateId, templateId))
|
||||
def deleteTemplate(templateId: String) = MappedTemplate_4824100653501473508.find(By(MappedTemplate_4824100653501473508.mTemplateId, templateId)).map(_.delete_!)
|
||||
val allAPIBuilderModels = List(MappedTemplates_430794570390706560)
|
||||
def createTemplate(createTemplateJson: CreateTemplateJson) = Full(MappedTemplates_430794570390706560.create.mTemplateId(UUID.randomUUID().toString).mAuthor(createTemplateJson.author).mPages(createTemplateJson.pages).mPoints(createTemplateJson.points).saveMe())
|
||||
def getTemplates() = Full(MappedTemplates_430794570390706560.findAll())
|
||||
def getTemplateById(templateId: String) = MappedTemplates_430794570390706560.find(By(MappedTemplates_430794570390706560.mTemplateId, templateId))
|
||||
def deleteTemplate(templateId: String) = MappedTemplates_430794570390706560.find(By(MappedTemplates_430794570390706560.mTemplateId, templateId)).map(_.delete_!)
|
||||
}
|
||||
import net.liftweb.mapper._
|
||||
class MappedTemplate_4824100653501473508 extends Template with LongKeyedMapper[MappedTemplate_4824100653501473508] with IdPK {
|
||||
class MappedTemplates_430794570390706560 extends Template with LongKeyedMapper[MappedTemplates_430794570390706560] with IdPK {
|
||||
object mAuthor extends MappedString(this, 100)
|
||||
override def author: String = mAuthor.get
|
||||
object mPages extends MappedInt(this)
|
||||
override def pages: Int = mPages.get
|
||||
object mPoints extends MappedDouble(this)
|
||||
override def points: Double = mPoints.get
|
||||
def getSingleton = MappedTemplate_4824100653501473508
|
||||
def getSingleton = MappedTemplates_430794570390706560
|
||||
object mTemplateId extends MappedString(this, 100)
|
||||
override def templateId: String = mTemplateId.get
|
||||
}
|
||||
object MappedTemplate_4824100653501473508 extends MappedTemplate_4824100653501473508 with LongKeyedMetaMapper[MappedTemplate_4824100653501473508]
|
||||
object MappedTemplates_430794570390706560 extends MappedTemplates_430794570390706560 with LongKeyedMetaMapper[MappedTemplates_430794570390706560]
|
||||
trait Template { `_` =>
|
||||
def author: String
|
||||
def pages: Int
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package code.api.builder
|
||||
import code.api.util.APIUtil
|
||||
case class TemplateJson(id: String = """11231231312""", author: String = """Chinua Achebe""", pages: Int = 209, points: Double = 1.3)
|
||||
case class CreateTemplateJson(author: String = """Chinua Achebe""", pages: Int = 209, points: Double = 1.3)
|
||||
case class TemplateJson(template_id: String = """11231231312""", author: String = """Chinua Achebe""", pages: Int = 209, points: Double = 1.3)
|
||||
object JsonFactory_APIBuilder {
|
||||
val templateJson = TemplateJson()
|
||||
val templatesJson = List(templateJson)
|
||||
|
||||
@ -2496,6 +2496,18 @@ Returns a string showed to the developer
|
||||
def createBasicUserAuthContextJson(userAuthContexts : List[UserAuthContext]) : List[BasicUserAuthContext] = {
|
||||
userAuthContexts.map(createBasicUserAuthContext)
|
||||
}
|
||||
|
||||
def createBasicUserAuthContextJsonFromCallContext(callContext : CallContext) : List[BasicGeneralContext] = {
|
||||
val requestHeaders: List[HTTPParam] = callContext.requestHeaders
|
||||
|
||||
//Only these Pass-Through headers can be propagated to Adapter side.
|
||||
val passThroughHeaders: List[HTTPParam] = requestHeaders
|
||||
.filter(requestHeader => requestHeader.name.startsWith("Pass-Through"))
|
||||
|
||||
passThroughHeaders.map(header => BasicGeneralContext(
|
||||
key = header.name,
|
||||
value = if (header.values.isEmpty) "" else header.values.head))
|
||||
}
|
||||
|
||||
def createAuthInfoCustomerJson(customer : Customer) : InternalBasicCustomer = {
|
||||
InternalBasicCustomer(
|
||||
|
||||
@ -57,8 +57,10 @@ case class CallContext(
|
||||
views <- tryo(permission.views)
|
||||
linkedCustomers <- tryo(CustomerX.customerProvider.vend.getCustomersByUserId(user.userId))
|
||||
likedCustomersBasic = if (linkedCustomers.isEmpty) None else Some(createInternalLinkedBasicCustomersJson(linkedCustomers))
|
||||
userAuthContexts<- UserAuthContextProvider.userAuthContextProvider.vend.getUserAuthContextsBox(user.userId)
|
||||
basicUserAuthContexts = if (userAuthContexts.isEmpty) None else Some(createBasicUserAuthContextJson(userAuthContexts))
|
||||
userAuthContexts<- UserAuthContextProvider.userAuthContextProvider.vend.getUserAuthContextsBox(user.userId)
|
||||
basicUserAuthContextsFromDatabase = if (userAuthContexts.isEmpty) None else Some(createBasicUserAuthContextJson(userAuthContexts))
|
||||
generalContextFromPassThroughHeaders = createBasicUserAuthContextJsonFromCallContext(this)
|
||||
basicUserAuthContexts = Some(basicUserAuthContextsFromDatabase.getOrElse(List.empty[BasicUserAuthContext]))
|
||||
authViews<- tryo(
|
||||
for{
|
||||
view <- views
|
||||
@ -79,7 +81,7 @@ case class CallContext(
|
||||
correlationId = this.correlationId,
|
||||
sessionId = this.sessionId,
|
||||
consumerId = Some(consumerId),
|
||||
generalContext = None,
|
||||
generalContext = Some(generalContextFromPassThroughHeaders),
|
||||
outboundAdapterAuthInfo = Some(OutboundAdapterAuthInfo(
|
||||
userId = currentResourceUserId,
|
||||
username = username,
|
||||
|
||||
@ -204,6 +204,7 @@ object NewStyle {
|
||||
(nameOf(Implementations3_1_0.createAccount), ApiVersion.v3_1_0.toString),
|
||||
(nameOf(Implementations3_1_0.saveHistoricalTransaction), ApiVersion.v3_1_0.toString),
|
||||
(nameOf(Implementations3_1_0.getPrivateAccountByIdFull), ApiVersion.v3_1_0.toString),
|
||||
(nameOf(Implementations3_1_0.getBankAccountsBalances), ApiVersion.v3_1_0.toString),
|
||||
(nameOf(Implementations4_0_0.getBanks), ApiVersion.v4_0_0.toString)
|
||||
)
|
||||
|
||||
@ -286,12 +287,27 @@ object NewStyle {
|
||||
connectorEmptyResponse(_, callContext)
|
||||
}
|
||||
}
|
||||
|
||||
def getBalances(callContext: Option[CallContext]) : OBPReturnType[List[Bank]] = {
|
||||
Connector.connector.vend.getBanks(callContext: Option[CallContext]) map {
|
||||
connectorEmptyResponse(_, callContext)
|
||||
}
|
||||
}
|
||||
def getBankAccount(bankId : BankId, accountId : AccountId, callContext: Option[CallContext]): OBPReturnType[BankAccount] = {
|
||||
Connector.connector.vend.getBankAccount(bankId, accountId, callContext) map { i =>
|
||||
(unboxFullOrFail(i._1, callContext,s"$BankAccountNotFound Current BankId is $bankId and Current AccountId is $accountId", 400 ), i._2)
|
||||
}
|
||||
}
|
||||
def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[List[BankAccount]] = {
|
||||
Connector.connector.vend.getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) map { i =>
|
||||
(unboxFullOrFail(i._1, callContext,s"$InvalidConnectorResponseForGetBankAccounts", 400 ), i._2)
|
||||
}
|
||||
}
|
||||
|
||||
def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[AccountsBalances] = {
|
||||
Connector.connector.vend.getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) map { i =>
|
||||
(unboxFullOrFail(i._1, callContext,s"$InvalidConnectorResponseForGetBankAccounts", 400 ), i._2)
|
||||
}
|
||||
}
|
||||
|
||||
def getBankAccountByIban(iban : String, callContext: Option[CallContext]) : OBPReturnType[BankAccount] = {
|
||||
Connector.connector.vend.getBankAccountByIban(iban : String, callContext: Option[CallContext]) map { i =>
|
||||
@ -1507,7 +1523,7 @@ object NewStyle {
|
||||
}
|
||||
}
|
||||
|
||||
private[this] val methodRoutingTTL = APIUtil.getPropsValue(s"methodRouting.cache.ttl.seconds", "30").toInt // default 30 seconds
|
||||
private[this] val methodRoutingTTL = APIUtil.getPropsValue(s"methodRouting.cache.ttl.seconds", "0").toInt
|
||||
|
||||
def getMethodRoutings(methodName: Option[String], isBankIdExactMatch: Option[Boolean] = None, bankIdPattern: Option[String] = None): List[MethodRoutingT] = {
|
||||
import scala.concurrent.duration._
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
package code.api.v3_1_0
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.{Date, UUID}
|
||||
import java.util.UUID
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import code.accountholders.AccountHolders
|
||||
import code.api.{APIFailureNewStyle, ChargePolicy}
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
|
||||
import code.api.ResourceDocs1_4_0.{MessageDocsSwaggerDefinitions, SwaggerDefinitionsJSON, SwaggerJSONFactory}
|
||||
import code.api.util.APIUtil._
|
||||
@ -16,16 +14,13 @@ import code.api.util.ExampleValue._
|
||||
import code.api.util.NewStyle.HttpCode
|
||||
import code.api.util._
|
||||
import code.api.v1_2_1.{JSONFactory, RateLimiting}
|
||||
import code.api.v1_3_0.{JSONFactory1_3_0, PostPhysicalCardJSON}
|
||||
import code.api.v1_4_0.JSONFactory1_4_0.TransactionRequestAccountJsonV140
|
||||
import code.api.v2_0_0.CreateMeetingJson
|
||||
import code.api.v2_1_0._
|
||||
import code.api.v2_2_0.{CreateAccountJSONV220, JSONFactory220}
|
||||
import code.api.v3_0_0.JSONFactory300
|
||||
import code.api.v3_0_0.JSONFactory300.{createAdapterInfoJson, createCoreBankAccountJSON}
|
||||
import code.api.v3_0_0.JSONFactory300.{createAdapterInfoJson}
|
||||
import code.api.v3_1_0.JSONFactory310._
|
||||
import code.bankconnectors.Connector
|
||||
import code.bankconnectors.akka.AkkaConnector_vDec2018
|
||||
import code.bankconnectors.rest.RestConnector_vMar2019
|
||||
import code.consent.{ConsentStatus, Consents}
|
||||
import code.consumer.Consumers
|
||||
@ -33,31 +28,29 @@ import code.context.{UserAuthContextUpdateProvider, UserAuthContextUpdateStatus}
|
||||
import code.entitlement.Entitlement
|
||||
import code.kafka.KafkaHelper
|
||||
import code.loginattempts.LoginAttempt
|
||||
import code.methodrouting.MethodRoutingCommons
|
||||
import code.methodrouting.{MethodRoutingCommons, MethodRoutingParam}
|
||||
import code.metrics.APIMetrics
|
||||
import code.model._
|
||||
import code.model.dataAccess.{AuthUser, BankAccountCreation}
|
||||
import code.transactionrequests.TransactionRequests.TransactionRequestTypes
|
||||
import code.transactionrequests.TransactionRequests.TransactionRequestTypes.{COUNTERPARTY, FREE_FORM, SANDBOX_TAN, SEPA}
|
||||
import com.openbankproject.commons.model.Product
|
||||
import code.users.Users
|
||||
import code.util.Helper
|
||||
import code.views.Views
|
||||
import code.webhook.AccountWebhook
|
||||
import code.webuiprops.{MappedWebUiPropsProvider, WebUiPropsCommons, WebUiPropsProvider}
|
||||
import code.webuiprops.{MappedWebUiPropsProvider, WebUiPropsCommons}
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.nexmo.client.NexmoClient
|
||||
import com.nexmo.client.sms.messages.TextMessage
|
||||
import com.openbankproject.commons.model.{CreditLimit, _}
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full}
|
||||
import net.liftweb.common.{Box, Empty, Full}
|
||||
import net.liftweb.http.provider.HTTPParam
|
||||
import net.liftweb.http.rest.RestHelper
|
||||
import net.liftweb.json.Serialization.write
|
||||
|
||||
import net.liftweb.json._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To}
|
||||
import net.liftweb.util.{Helpers, Mailer, Props}
|
||||
import org.apache.commons.lang3.Validate
|
||||
import net.liftweb.util.{Helpers, Mailer}
|
||||
import org.apache.commons.lang3.{StringUtils, Validate}
|
||||
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
@ -3930,7 +3923,7 @@ trait APIMethods310 {
|
||||
emptyObjectJson,
|
||||
ListResult(
|
||||
"method_routings",
|
||||
(List(MethodRoutingCommons("getBanks", "rest_vMar2019", false, Some("some_bank_.*"), Some("method-routing-id"))))
|
||||
(List(MethodRoutingCommons("getBanks", "rest_vMar2019", false, Some("some_bank_.*"), Some(List(MethodRoutingParam("url", "http://mydomain.com/xxx"))), Some("method-routing-id"))))
|
||||
)
|
||||
,
|
||||
List(
|
||||
@ -3976,12 +3969,17 @@ trait APIMethods310 {
|
||||
|* connector_name is required String value
|
||||
|* is_bank_id_exact_match is required boolean value, if bank_id_pattern is exact bank_id value, this value is true; if bank_id_pattern is null or a regex, this value is false
|
||||
|* bank_id_pattern is optional String value, it can be null, a exact bank_id or a regex
|
||||
|* parameters is optional array of key value pairs. You can set some paremeters for this method
|
||||
|
|
||||
|note: if bank_id_pattern is regex, special characters need to do escape, for example:
|
||||
|bank_id_pattern = "some\\-id_pattern_\\d+"
|
||||
|note:
|
||||
|
|
||||
|* if bank_id_pattern is regex, special characters need to do escape, for example: bank_id_pattern = "some\\-id_pattern_\\d+"
|
||||
|""",
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_.*")),
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_.*"), Some("this-method-routing-Id")),
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_.*"), Some(List(MethodRoutingParam("url", "http://mydomain.com/xxx")))),
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_.*"),
|
||||
Some(List(MethodRoutingParam("url", "http://mydomain.com/xxx"))),
|
||||
Some("this-method-routing-Id")
|
||||
),
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
@ -4036,13 +4034,13 @@ trait APIMethods310 {
|
||||
|* connector_name is required String value
|
||||
|* is_bank_id_exact_match is required boolean value, if bank_id_pattern is exact bank_id value, this value is true; if bank_id_pattern is null or a regex, this value is false
|
||||
|* bank_id_pattern is optional String value, it can be null, a exact bank_id or a regex
|
||||
|* parameters is optional array of key value pairs. You can set some paremeters for this method
|
||||
|note:
|
||||
|
|
||||
|note: if bank_id_pattern is regex, special characters need to do escape, for example:
|
||||
|bank_id_pattern = "some\\-id_pattern_\\d+"
|
||||
|
|
||||
|* if bank_id_pattern is regex, special characters need to do escape, for example: bank_id_pattern = "some\\-id_pattern_\\d+"
|
||||
|""",
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", true, Some("some_bankId"), None),
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", true, Some("some_bankId"), None),
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", true, Some("some_bankId"), Some(List(MethodRoutingParam("url", "http://mydomain.com/xxx")))),
|
||||
MethodRoutingCommons("getBank", "rest_vMar2019", true, Some("some_bankId"),Some(List(MethodRoutingParam("url", "http://mydomain.com/xxx"))), Some("this-method-routing-Id")),
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
@ -4061,21 +4059,21 @@ trait APIMethods310 {
|
||||
_ <- NewStyle.function.hasEntitlement("", u.userId, canUpdateMethodRouting, callContext)
|
||||
|
||||
failMsg = s"$InvalidJsonFormat The Json body should be the ${classOf[MethodRoutingCommons]} "
|
||||
postedData <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
putData <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
json.extract[MethodRoutingCommons].copy(methodRoutingId = Some(methodRoutingId))
|
||||
}
|
||||
|
||||
(_, _) <- NewStyle.function.getMethodRoutingById(methodRoutingId, callContext)
|
||||
|
||||
invalidRegexMsg = s"$InvalidBankIdRegex The bankIdPattern is invalid regex, bankIdPatten: ${postedData.bankIdPattern.orNull} "
|
||||
invalidRegexMsg = s"$InvalidBankIdRegex The bankIdPattern is invalid regex, bankIdPatten: ${putData.bankIdPattern.orNull} "
|
||||
_ <- NewStyle.function.tryons(invalidRegexMsg, 400, callContext) {
|
||||
// if do fuzzy match and bankIdPattern not empty, do check the regex is valid
|
||||
if(!postedData.isBankIdExactMatch && postedData.bankIdPattern.isDefined) {
|
||||
Pattern.compile(postedData.bankIdPattern.get)
|
||||
if(!putData.isBankIdExactMatch && putData.bankIdPattern.isDefined) {
|
||||
Pattern.compile(putData.bankIdPattern.get)
|
||||
}
|
||||
}
|
||||
|
||||
Full(methodRouting) <- NewStyle.function.createOrUpdateMethodRouting(postedData)
|
||||
Full(methodRouting) <- NewStyle.function.createOrUpdateMethodRouting(putData)
|
||||
} yield {
|
||||
val commonsData: MethodRoutingCommons = methodRouting
|
||||
(commonsData, HttpCode.`200`(callContext))
|
||||
@ -5450,6 +5448,35 @@ trait APIMethods310 {
|
||||
}
|
||||
}
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
getBankAccountsBalances,
|
||||
implementedInApiVersion,
|
||||
nameOf(getBankAccountsBalances),
|
||||
"GET",
|
||||
"/banks/BANK_ID/balances",
|
||||
"Get Accounts Balances",
|
||||
"""Get the Balances for the Accounts of the current User at one bank.""",
|
||||
emptyObjectJson,
|
||||
accountBalancesV310Json,
|
||||
List(UnknownError),
|
||||
Catalogs(Core, PSD2, OBWG),
|
||||
apiTagAccount :: apiTagPSD2AIS :: apiTagNewStyle :: Nil
|
||||
)
|
||||
|
||||
lazy val getBankAccountsBalances : OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "balances" :: Nil JsonGet _ => {
|
||||
cc =>
|
||||
for {
|
||||
(Full(u), callContext) <- authorizedAccess(cc)
|
||||
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
|
||||
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u, bankId)
|
||||
(accountsBalances, callContext)<- NewStyle.function.getBankAccountsBalances(availablePrivateAccounts, callContext)
|
||||
} yield{
|
||||
(createBalancesJson(accountsBalances), HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ import code.api.util.APIUtil.{stringOptionOrNull, stringOrNull}
|
||||
import code.api.util.RateLimitPeriod.LimitCallPeriod
|
||||
import code.api.util.{APIUtil, RateLimitPeriod}
|
||||
import code.api.v1_2_1.JSONFactory.{createAmountOfMoneyJSON, createOwnersJSON}
|
||||
import code.api.v1_2_1.{RateLimiting, UserJSONV121, ViewJSONV121}
|
||||
import code.api.v1_2_1.{BankJSON, RateLimiting, UserJSONV121, ViewJSONV121}
|
||||
import code.api.v1_3_0.JSONFactory1_3_0._
|
||||
import code.api.v1_3_0.{PinResetJSON, ReplacementJSON}
|
||||
import code.api.v1_4_0.JSONFactory1_4_0.{CustomerFaceImageJson, MetaJsonV140, TransactionRequestAccountJsonV140}
|
||||
@ -42,7 +42,7 @@ import code.api.v2_0_0.{MeetingKeysJson, MeetingPresentJson}
|
||||
import code.api.v2_1_0.JSONFactory210.createLicenseJson
|
||||
import code.api.v2_1_0.{CustomerCreditRatingJSON, ResourceUserJSON}
|
||||
import code.api.v2_2_0._
|
||||
import code.api.v3_0_0.AccountRuleJsonV300
|
||||
import code.api.v3_0_0.{AccountRuleJsonV300, ViewBasicV300}
|
||||
import code.api.v3_0_0.JSONFactory300.{createAccountRoutingsJSON, createAccountRulesJSON}
|
||||
import code.consent.MappedConsent
|
||||
import code.context.UserAuthContextUpdate
|
||||
@ -701,6 +701,24 @@ case class PostHistoricalTransactionResponseJson(
|
||||
charge_policy: String
|
||||
)
|
||||
|
||||
case class AccountsBalancesV310Json(
|
||||
accounts:List[AccountBalanceV310],
|
||||
overall_balance: AmountOfMoney,
|
||||
overall_balance_date: Date
|
||||
)
|
||||
case class AccountBalanceV310(
|
||||
id: String,
|
||||
label: String,
|
||||
bank_id: String,
|
||||
account_routings: List[AccountRouting],
|
||||
balance: AmountOfMoney
|
||||
)
|
||||
|
||||
case class AccountBalancesJson(
|
||||
accounts: List[AccountBalanceV310],
|
||||
overall_balance: AmountOfMoney,
|
||||
overall_balance_date: Date
|
||||
)
|
||||
|
||||
object JSONFactory310{
|
||||
def createCheckbookOrdersJson(checkbookOrders: CheckbookOrdersJson): CheckbookOrdersJson =
|
||||
@ -1309,5 +1327,19 @@ object JSONFactory310{
|
||||
)
|
||||
}
|
||||
|
||||
def createBalancesJson(accountsBalances: AccountsBalances) = {
|
||||
AccountsBalancesV310Json(
|
||||
accounts = accountsBalances.accounts.map(account => AccountBalanceV310(
|
||||
account.id,
|
||||
account.label,
|
||||
account.bankId,
|
||||
account.accountRoutings,
|
||||
account.balance)
|
||||
),
|
||||
overall_balance = accountsBalances.overallBalance,
|
||||
overall_balance_date = accountsBalances.overallBalanceDate
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -376,6 +376,7 @@ object OBPAPI3_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations3_1_0.getWebUiProps ::
|
||||
Implementations3_1_0.createWebUiProps ::
|
||||
Implementations3_1_0.deleteWebUiProps ::
|
||||
Implementations3_1_0.getBankAccountsBalances ::
|
||||
Nil
|
||||
|
||||
val allResourceDocs = Implementations3_1_0.resourceDocs ++
|
||||
|
||||
@ -377,6 +377,7 @@ object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations3_1_0.getWebUiProps ::
|
||||
Implementations3_1_0.createWebUiProps ::
|
||||
Implementations3_1_0.deleteWebUiProps ::
|
||||
Implementations3_1_0.getBankAccountsBalances ::
|
||||
Nil
|
||||
|
||||
|
||||
|
||||
@ -273,7 +273,9 @@ trait Connector extends MdcLoggable with CustomJsonFormats{
|
||||
def getBankAccountByIban(iban : String, callContext: Option[CallContext]) : OBPReturnType[Box[BankAccount]]= Future{(Failure(setUnimplementedError),callContext)}
|
||||
def getBankAccountByRouting(scheme : String, address : String, callContext: Option[CallContext]) : Box[(BankAccount, Option[CallContext])]= Failure(setUnimplementedError)
|
||||
|
||||
def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : Future[Box[List[BankAccount]]]= Future{Failure(setUnimplementedError)}
|
||||
def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : OBPReturnType[Box[List[BankAccount]]]= Future{(Failure(setUnimplementedError), callContext)}
|
||||
|
||||
def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : OBPReturnType[Box[AccountsBalances]]= Future{(Failure(setUnimplementedError), callContext)}
|
||||
|
||||
def getCoreBankAccountsLegacy(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : Box[(List[CoreAccount], Option[CallContext])] =
|
||||
Failure(setUnimplementedError)
|
||||
|
||||
@ -5,7 +5,7 @@ import code.api.util.APIUtil.{OBPEndpoint, _}
|
||||
import code.api.util.NewStyle.HttpCode
|
||||
import code.api.util.{APIUtil, CallContext, OBPQueryParam}
|
||||
import code.api.v3_1_0.OBPAPI3_1_0.oauthServe
|
||||
import com.openbankproject.commons.model.{AccountId, BankId, BankIdAccountId, InboundAdapterCallContext}
|
||||
import com.openbankproject.commons.model._
|
||||
import com.openbankproject.commons.util.ReflectUtils
|
||||
import com.openbankproject.commons.util.ReflectUtils.{getType, toValueObject}
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full}
|
||||
@ -55,7 +55,7 @@ object ConnectorEndpoints extends RestHelper{
|
||||
inboundAdapterCallContextValue = InboundAdapterCallContext(cc.correlationId)
|
||||
} yield {
|
||||
// NOTE: if any filed type is BigDecimal, it is can't be serialized by lift json
|
||||
val json = Map((inboundAdapterCallContextKey, inboundAdapterCallContextValue),("data", toValueObject(data)))
|
||||
val json = Map((inboundAdapterCallContextKey, inboundAdapterCallContextValue),("status", Status("",List(InboundStatusMessage("","","","")))),("data", toValueObject(data)))
|
||||
(json, HttpCode.`200`(cc))
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import code.api.cache.Caching
|
||||
import code.api.util.APIUtil.{OBPReturnType, isValidCurrencyISOCode, saveConnectorMetric, stringOrNull}
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util._
|
||||
import code.api.v3_1_0.AccountBalanceV310
|
||||
import code.atms.Atms.Atm
|
||||
import code.atms.MappedAtm
|
||||
import code.bankconnectors.vJune2017.InboundAccountJune2017
|
||||
@ -437,19 +438,61 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
).map(bankAccount => (bankAccount, callContext))
|
||||
}
|
||||
|
||||
override def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : Future[Box[List[BankAccount]]] = {
|
||||
override def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) = {
|
||||
Future {
|
||||
Full(
|
||||
(Full(
|
||||
bankIdAccountIds.map(
|
||||
bankIdAccountId =>
|
||||
getBankAccount(
|
||||
bankIdAccountId.bankId,
|
||||
bankIdAccountId.accountId
|
||||
).openOrThrowException(s"${ErrorMessages.BankAccountNotFound} current BANK_ID(${bankIdAccountId.bankId}) and ACCOUNT_ID(${bankIdAccountId.accountId})"))
|
||||
)
|
||||
),callContext)
|
||||
}
|
||||
}
|
||||
|
||||
override def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) =
|
||||
Future {
|
||||
val accountsBalances = for{
|
||||
bankIdAccountId <- bankIdAccountIds
|
||||
bankAccount <- getBankAccount(bankIdAccountId.bankId, bankIdAccountId.accountId) ?~! s"${ErrorMessages.BankAccountNotFound} current BANK_ID(${bankIdAccountId.bankId}) and ACCOUNT_ID(${bankIdAccountId.accountId})"
|
||||
accountBalance = AccountBalance(
|
||||
id = bankAccount.accountId.value,
|
||||
label = bankAccount.label,
|
||||
bankId = bankAccount.bankId.value,
|
||||
accountRoutings = bankAccount.accountRoutings.map(accountRounting => AccountRouting(accountRounting.scheme, accountRounting.address)),
|
||||
balance = AmountOfMoney(bankAccount.currency, bankAccount.balance.toString())
|
||||
)
|
||||
} yield {
|
||||
(accountBalance)
|
||||
}
|
||||
|
||||
val allCurrencies = accountsBalances.map(_.balance.currency)
|
||||
val mostCommonCurrency = if (allCurrencies.isEmpty) "EUR" else allCurrencies.groupBy(identity).mapValues(_.size).maxBy(_._2)._1
|
||||
|
||||
val allCommonCurrencyBalances = for {
|
||||
accountBalance <- accountsBalances
|
||||
requestAccountCurrency = accountBalance.balance.currency
|
||||
requestAccountAmount = BigDecimal(accountBalance.balance.amount)
|
||||
//From change from requestAccount Currency to mostCommon Currency
|
||||
rate <- fx.exchangeRate(requestAccountCurrency, mostCommonCurrency)
|
||||
requestChangedCurrencyAmount = fx.convert(requestAccountAmount, Some(rate))
|
||||
}yield {
|
||||
requestChangedCurrencyAmount
|
||||
}
|
||||
|
||||
val overallBalance = allCommonCurrencyBalances.sum
|
||||
|
||||
(Full(AccountsBalances(
|
||||
accounts = accountsBalances,
|
||||
overallBalance = AmountOfMoney(
|
||||
mostCommonCurrency,
|
||||
overallBalance.toString
|
||||
),
|
||||
overallBalanceDate = now
|
||||
)), callContext)
|
||||
}
|
||||
|
||||
override def checkBankAccountExistsLegacy(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]) = {
|
||||
getBankAccountLegacy(bankId: BankId, accountId: AccountId, callContext)
|
||||
}
|
||||
|
||||
@ -17,24 +17,22 @@ import code.api.util.CodeGenerateUtils.createDocExample
|
||||
|
||||
object RestConnectorBuilder extends App {
|
||||
|
||||
val genMethodNames1 = List(
|
||||
val genMethodNames = List(
|
||||
// "getAdapterInfo",
|
||||
"getAdapterInfo",
|
||||
// "getAdapterInfo",
|
||||
// "getUser", // have problem, return type not common
|
||||
// "getBanks",
|
||||
"getBanksFuture",
|
||||
// "getBank",
|
||||
"getBankFuture",
|
||||
// "getBankAccountsForUser",
|
||||
"getBankAccountsForUserFuture",
|
||||
"getCustomersByUserIdFuture",
|
||||
// "getBankAccount",
|
||||
// "checkBankAccountExists",
|
||||
"checkBankAccountExistsFuture",
|
||||
"getBankAccountsBalances",
|
||||
// "getBanksLegacy",
|
||||
// "getBank",
|
||||
// "getBankLegacy",
|
||||
// "getBankAccountsForUser",
|
||||
// "getCustomersByUserIdFuture",
|
||||
// "getBankAccount",
|
||||
// "checkBankAccountExists",
|
||||
// "getCoreBankAccounts",
|
||||
"getCoreBankAccountsFuture",
|
||||
// "getCoreBankAccountsFuture",
|
||||
// "getTransactions",
|
||||
"getTransactionsCore",
|
||||
// "getTransactionsCore",
|
||||
// "getTransaction",
|
||||
// "getTransactionRequests210", //have problem params are not simple object
|
||||
// "getCounterparties",
|
||||
@ -54,7 +52,7 @@ object RestConnectorBuilder extends App {
|
||||
// "createCounterparty" // not support
|
||||
)
|
||||
//For vSept2018
|
||||
val genMethodNames = List(
|
||||
val genMethodNames2 = List(
|
||||
// "createOrUpdateKycCheck",
|
||||
// "createOrUpdateKycDocument",
|
||||
// "createOrUpdateKycMedia",
|
||||
@ -64,7 +62,7 @@ object RestConnectorBuilder extends App {
|
||||
// "getKycMedias",
|
||||
// "getKycStatuses",
|
||||
// "createBankAccount",
|
||||
"createCustomer",
|
||||
// "createCustomer",
|
||||
// "createMeeting",
|
||||
// "createMessage"
|
||||
)
|
||||
|
||||
@ -28,14 +28,13 @@ import java.util.UUID.randomUUID
|
||||
import java.util.Date
|
||||
|
||||
import akka.http.scaladsl.model.{HttpProtocol, _}
|
||||
import akka.http.scaladsl.model.headers.RawHeader
|
||||
import akka.util.ByteString
|
||||
import code.api.APIFailureNewStyle
|
||||
import code.api.ResourceDocs1_4_0.MessageDocsSwaggerDefinitions.inboundStatus
|
||||
import code.api.cache.Caching
|
||||
import code.api.util.APIUtil.{AdapterImplementation, MessageDoc, OBPReturnType, saveConnectorMetric}
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util.ExampleValue._
|
||||
import code.api.util.{CallContext, OBPQueryParam}
|
||||
import code.api.util.{CallContext, NewStyle, OBPQueryParam}
|
||||
import code.bankconnectors._
|
||||
import code.bankconnectors.vJune2017.AuthInfo
|
||||
import code.kafka.{KafkaHelper, Topics}
|
||||
@ -43,9 +42,8 @@ import code.util.AkkaHttpClient._
|
||||
import code.util.Helper.MdcLoggable
|
||||
import com.openbankproject.commons.dto._
|
||||
import com.openbankproject.commons.model._
|
||||
import com.tesobe.CacheKeyFromArguments
|
||||
import com.tesobe.{CacheKeyFromArguments, CacheKeyOmit}
|
||||
import net.liftweb.common.{Box, Empty, _}
|
||||
import net.liftweb.json._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
@ -54,10 +52,11 @@ import scala.concurrent.{Await, Future}
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
import scala.reflect.runtime.universe._
|
||||
|
||||
import code.api.util.ExampleValue._
|
||||
|
||||
import code.api.util.APIUtil._
|
||||
import code.methodrouting.MethodRoutingParam
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import net.liftweb.json._
|
||||
|
||||
trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable {
|
||||
//this one import is for implicit convert, don't delete
|
||||
@ -79,6 +78,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
val authInfoExample = AuthInfo(userId = "userId", username = "username", cbsToken = "cbsToken")
|
||||
val errorCodeExample = "INTERNAL-OBP-ADAPTER-6001: ..."
|
||||
|
||||
val connectorName = "rest_vMar2019"
|
||||
|
||||
/*
|
||||
All the following code is created automatclly.
|
||||
@ -166,16 +166,16 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
|
||||
|
||||
//---------------- dynamic start -------------------please don't modify this line
|
||||
// ---------- create on Thu Jun 13 11:07:28 CST 2019
|
||||
// ---------- create on Tue Jul 23 18:38:46 CEST 2019
|
||||
|
||||
messageDocs += MessageDoc(
|
||||
process = "obp.createCustomer",
|
||||
process = "obp.getBankAccountsBalances",
|
||||
messageFormat = messageFormat,
|
||||
description = "Create Customer",
|
||||
outboundTopic = Some(Topics.createTopicByClassName(OutBoundCreateCustomer.getClass.getSimpleName).request),
|
||||
inboundTopic = Some(Topics.createTopicByClassName(OutBoundCreateCustomer.getClass.getSimpleName).response),
|
||||
description = "Get Bank Accounts Balances",
|
||||
outboundTopic = None,
|
||||
inboundTopic = None,
|
||||
exampleOutboundMessage = (
|
||||
OutBoundCreateCustomer(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value,
|
||||
OutBoundGetBankAccountsBalances(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value,
|
||||
sessionId=Some(sessionIdExample.value),
|
||||
consumerId=Some(consumerIdExample.value),
|
||||
generalContext=Some(List( BasicGeneralContext(key=keyExample.value,
|
||||
@ -201,30 +201,11 @@ messageDocs += MessageDoc(
|
||||
userOwners=List( InternalBasicUser(userId=userIdExample.value,
|
||||
emailAddress=emailExample.value,
|
||||
name=usernameExample.value))))))))),
|
||||
bankId=BankId(bankIdExample.value),
|
||||
legalName=legalNameExample.value,
|
||||
mobileNumber=mobileNumberExample.value,
|
||||
email=emailExample.value,
|
||||
faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")),
|
||||
url=urlExample.value),
|
||||
dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")),
|
||||
relationshipStatus=relationshipStatusExample.value,
|
||||
dependents=dependentsExample.value.toInt,
|
||||
dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList,
|
||||
highestEducationAttained=highestEducationAttainedExample.value,
|
||||
employmentStatus=employmentStatusExample.value,
|
||||
kycStatus=kycStatusExample.value.toBoolean,
|
||||
lastOkDate=parseDate(outBoundCreateCustomerLastOkDateExample.value).getOrElse(sys.error("outBoundCreateCustomerLastOkDateExample.value is not validate date format.")),
|
||||
creditRating=Some( CreditRating(rating=ratingExample.value,
|
||||
source=sourceExample.value)),
|
||||
creditLimit=Some( AmountOfMoney(currency=currencyExample.value,
|
||||
amount=creditLimitAmountExample.value)),
|
||||
title=titleExample.value,
|
||||
branchId=branchIdExample.value,
|
||||
nameSuffix=nameSuffixExample.value)
|
||||
bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value),
|
||||
accountId=AccountId(accountIdExample.value))))
|
||||
),
|
||||
exampleInboundMessage = (
|
||||
InBoundCreateCustomer(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value,
|
||||
InBoundGetBankAccountsBalances(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value,
|
||||
sessionId=Some(sessionIdExample.value),
|
||||
generalContext=Some(List( BasicGeneralContext(key=keyExample.value,
|
||||
value=valueExample.value)))),
|
||||
@ -233,48 +214,42 @@ messageDocs += MessageDoc(
|
||||
status=inboundStatusMessageStatusExample.value,
|
||||
errorCode=inboundStatusMessageErrorCodeExample.value,
|
||||
text=inboundStatusMessageTextExample.value))),
|
||||
data= CustomerCommons(customerId=customerIdExample.value,
|
||||
data= AccountsBalances(accounts=List( AccountBalance(id=accountIdExample.value,
|
||||
label=labelExample.value,
|
||||
bankId=bankIdExample.value,
|
||||
number=customerNumberExample.value,
|
||||
legalName=legalNameExample.value,
|
||||
mobileNumber=mobileNumberExample.value,
|
||||
email=emailExample.value,
|
||||
faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")),
|
||||
url=urlExample.value),
|
||||
dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")),
|
||||
relationshipStatus=relationshipStatusExample.value,
|
||||
dependents=dependentsExample.value.toInt,
|
||||
dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList,
|
||||
highestEducationAttained=highestEducationAttainedExample.value,
|
||||
employmentStatus=employmentStatusExample.value,
|
||||
creditRating= CreditRating(rating=ratingExample.value,
|
||||
source=sourceExample.value),
|
||||
creditLimit= CreditLimit(currency=currencyExample.value,
|
||||
amount=creditLimitAmountExample.value),
|
||||
kycStatus=kycStatusExample.value.toBoolean,
|
||||
lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")),
|
||||
title=customerTitleExample.value,
|
||||
branchId=branchIdExample.value,
|
||||
nameSuffix=nameSuffixExample.value))
|
||||
accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value,
|
||||
address=accountRoutingAddressExample.value)),
|
||||
balance= AmountOfMoney(currency=balanceCurrencyExample.value,
|
||||
amount=balanceAmountExample.value))),
|
||||
overallBalance= AmountOfMoney(currency=currencyExample.value,
|
||||
amount="string"),
|
||||
overallBalanceDate=new Date()))
|
||||
),
|
||||
adapterImplementation = Some(AdapterImplementation("- Core", 1))
|
||||
)
|
||||
// url example: /createCustomer
|
||||
override def createCustomer(bankId: BankId, legalName: String, mobileNumber: String, email: String, faceImage: CustomerFaceImageTrait, dateOfBirth: Date, relationshipStatus: String, dependents: Int, dobOfDependents: List[Date], highestEducationAttained: String, employmentStatus: String, kycStatus: Boolean, lastOkDate: Date, creditRating: Option[CreditRatingTrait], creditLimit: Option[AmountOfMoneyTrait], title: String, branchId: String, nameSuffix: String, callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = {
|
||||
import net.liftweb.json.Serialization.write
|
||||
|
||||
val url = getUrl("createCustomer")
|
||||
val outboundAdapterCallContext = Box(callContext.map(_.toOutboundAdapterCallContext)).openOrThrowException(NoCallContext)
|
||||
val jsonStr = write(OutBoundCreateCustomer(outboundAdapterCallContext , bankId, legalName, mobileNumber, email, faceImage, dateOfBirth, relationshipStatus, dependents, dobOfDependents, highestEducationAttained, employmentStatus, kycStatus, lastOkDate, creditRating, creditLimit, title, branchId, nameSuffix))
|
||||
sendPostRequest[InBoundCreateCustomer](url, callContext, jsonStr)
|
||||
.map{ boxedResult =>
|
||||
boxedResult match {
|
||||
case Full(result) => (Full(result.data), buildCallContext(result.inboundAdapterCallContext, callContext))
|
||||
case result: EmptyBox => (result, callContext) // Empty and Failure all match this case
|
||||
}
|
||||
// url example: /getBankAccountsBalances/bankIdAccountIds/{bankIdAccountIds}
|
||||
override def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], @CacheKeyOmit callContext: Option[CallContext]): OBPReturnType[Box[AccountsBalances]] = saveConnectorMetric {
|
||||
/**
|
||||
* Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)"
|
||||
* is just a temporary value filed with UUID values in order to prevent any ambiguity.
|
||||
* The real value will be assigned by Macro during compile time at this line of a code:
|
||||
* https://github.com/OpenBankProject/scala-macros/blob/master/macros/src/main/scala/com/tesobe/CacheKeyFromArgumentsMacro.scala#L49
|
||||
*/
|
||||
var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)
|
||||
CacheKeyFromArguments.buildCacheKey {
|
||||
Caching.memoizeWithProvider(Some(cacheKey.toString()))(banksTTL second){
|
||||
val url = getUrl("getBankAccountsBalances" , ("bankIdAccountIds", bankIdAccountIds))
|
||||
sendGetRequest[InBoundGetBankAccountsBalances](url, callContext)
|
||||
.map { boxedResult =>
|
||||
boxedResult match {
|
||||
case Full(result) => (Full(result.data), buildCallContext(result.inboundAdapterCallContext, callContext))
|
||||
case result: EmptyBox => (result, callContext) // Empty and Failure all match this case
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}("getBankAccountsBalances")
|
||||
|
||||
//---------------- dynamic end ---------------------please don't modify this line
|
||||
|
||||
@ -282,6 +257,7 @@ messageDocs += MessageDoc(
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private[this] def sendGetRequest[T: TypeTag : Manifest](url: String, callContext: Option[CallContext]) =
|
||||
@ -296,8 +272,12 @@ messageDocs += MessageDoc(
|
||||
private[this] def sendDelteRequest[T: TypeTag : Manifest](url: String, callContext: Option[CallContext]) =
|
||||
sendRequest[T](url, callContext, HttpMethods.DELETE)
|
||||
|
||||
//TODO every connector should implement this method to build authorization headers with callContext
|
||||
private[this] implicit def buildHeaders(callContext: Option[CallContext]): List[HttpHeader] = Nil
|
||||
//In RestConnector, we use the headers to propagate the parameters to Adapter. The parameters come from the CallContext.outboundAdapterAuthInfo.userAuthContext
|
||||
//We can set them from UserOauthContext or the http request headers.
|
||||
private[this] implicit def buildHeaders(callContext: Option[CallContext]): List[HttpHeader] = {
|
||||
val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext])
|
||||
generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value))
|
||||
}
|
||||
|
||||
private[this] def buildAdapterCallContext(callContext: Option[CallContext]): OutboundAdapterCallContext = callContext.map(_.toOutboundAdapterCallContext).orNull
|
||||
|
||||
@ -314,6 +294,17 @@ messageDocs += MessageDoc(
|
||||
private[this] val baseUrl = "http://localhost:8080/restConnector"
|
||||
|
||||
private[this] def getUrl(methodName: String, variables: (String, Any)*): String = {
|
||||
// rest connector can have url value in the parameters, key is url
|
||||
val urlInMethodRouting = NewStyle.function.getMethodRoutings(Some(methodName))
|
||||
.flatMap(_.parameters).flatten
|
||||
.find(_.key == "url")
|
||||
.map(_.value)
|
||||
|
||||
|
||||
if(urlInMethodRouting.isDefined) {
|
||||
return urlInMethodRouting.get
|
||||
}
|
||||
|
||||
// convert any type value to string, to fill in the url
|
||||
def urlValueConverter(obj: Any):String = {
|
||||
val value = obj match {
|
||||
@ -341,6 +332,7 @@ messageDocs += MessageDoc(
|
||||
|
||||
private[this] def sendRequest[T: TypeTag : Manifest](url: String, callContext: Option[CallContext], method: HttpMethod, entityJsonString: String = ""): Future[Box[T]] = {
|
||||
val request = prepareHttpRequest(url, method, HttpProtocol("HTTP/1.1"), entityJsonString).withHeaders(callContext)
|
||||
logger.debug(s"RestConnector_vMar2019 request is : $request")
|
||||
val responseFuture = makeHttpRequest(request)
|
||||
val jsonType = typeOf[T]
|
||||
responseFuture.map {
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
package code.methodrouting
|
||||
|
||||
import code.api.util.CustomJsonFormats
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.{Box, Empty, EmptyBox, Full}
|
||||
import net.liftweb.json
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import net.liftweb.json.Serialization.write
|
||||
|
||||
object MappedMethodRoutingProvider extends MethodRoutingProvider {
|
||||
object MappedMethodRoutingProvider extends MethodRoutingProvider with CustomJsonFormats{
|
||||
|
||||
override def getById(methodRoutingId: String): Box[MethodRoutingT] = MethodRouting.find(
|
||||
By(MethodRouting.MethodRoutingId, methodRoutingId)
|
||||
@ -42,12 +45,18 @@ object MappedMethodRoutingProvider extends MethodRoutingProvider {
|
||||
// if not supply bankIdPattern, isExactMatch must be false
|
||||
val isExactMatch = if(bankIdPattern.isDefined) methodRouting.isBankIdExactMatch else false
|
||||
|
||||
val existsMethodRoutingParameters = methodRouting.parameters match {
|
||||
case Some(parameters) if (parameters.nonEmpty) => parameters
|
||||
case _ => List.empty[MethodRoutingParam]
|
||||
}
|
||||
|
||||
tryo{
|
||||
entityToPersist
|
||||
.MethodName(methodRouting.methodName)
|
||||
.BankIdPattern(bankIdPattern.orNull)
|
||||
.IsBankIdExactMatch(isExactMatch)
|
||||
.ConnectorName(methodRouting.connectorName)
|
||||
.Parameters(write(existsMethodRoutingParameters))
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
@ -59,7 +68,7 @@ object MappedMethodRoutingProvider extends MethodRoutingProvider {
|
||||
|
||||
}
|
||||
|
||||
class MethodRouting extends MethodRoutingT with LongKeyedMapper[MethodRouting] with IdPK {
|
||||
class MethodRouting extends MethodRoutingT with LongKeyedMapper[MethodRouting] with IdPK with CustomJsonFormats{
|
||||
|
||||
override def getSingleton = MethodRouting
|
||||
|
||||
@ -70,12 +79,16 @@ class MethodRouting extends MethodRoutingT with LongKeyedMapper[MethodRouting] w
|
||||
}
|
||||
object IsBankIdExactMatch extends MappedBoolean(this)
|
||||
object ConnectorName extends MappedString(this, 255)
|
||||
object Parameters extends MappedString(this, 5000)
|
||||
|
||||
override def methodRoutingId: Option[String] = Option(MethodRoutingId.get)
|
||||
override def methodName: String = MethodName.get
|
||||
override def bankIdPattern: Option[String] = Option(BankIdPattern.get)
|
||||
override def isBankIdExactMatch: Boolean = IsBankIdExactMatch.get
|
||||
override def connectorName: String = ConnectorName.get
|
||||
|
||||
//Here we store all the key-value paris in one big String filed in database.
|
||||
override def parameters: Option[List[MethodRoutingParam]] = Option(json.parse(if (Parameters.get != null) Parameters.get else "[]").extract[List[MethodRoutingParam]])
|
||||
}
|
||||
|
||||
object MethodRouting extends MethodRouting with LongKeyedMetaMapper[MethodRouting] {
|
||||
|
||||
@ -24,17 +24,21 @@ trait MethodRoutingT {
|
||||
*/
|
||||
def isBankIdExactMatch: Boolean
|
||||
def connectorName: String
|
||||
def parameters: Option[List[MethodRoutingParam]]
|
||||
}
|
||||
|
||||
case class MethodRoutingCommons(methodName: String,
|
||||
connectorName: String,
|
||||
isBankIdExactMatch: Boolean,
|
||||
bankIdPattern: Option[String],
|
||||
methodRoutingId: Option[String] = None
|
||||
parameters: Option[List[MethodRoutingParam]] = None,
|
||||
methodRoutingId: Option[String] = None,
|
||||
) extends MethodRoutingT with JsonFieldReName
|
||||
|
||||
object MethodRoutingCommons extends Converter[MethodRoutingT, MethodRoutingCommons]
|
||||
|
||||
case class MethodRoutingParam(key: String, value: String)
|
||||
|
||||
trait MethodRoutingProvider {
|
||||
def getById(methodRoutingId: String): Box[MethodRoutingT]
|
||||
|
||||
|
||||
@ -31,7 +31,8 @@ class MappedBankAccount extends BankAccount with LongKeyedMapper[MappedBankAccou
|
||||
|
||||
object accountLabel extends MappedString(this, 255)
|
||||
|
||||
//the last time this account was updated via hbci
|
||||
//the last time this account was updated via hbci [when transaction data was refreshed from the bank.]
|
||||
//It means last transaction refresh date only used for HBCI now.
|
||||
object accountLastUpdate extends MappedDateTime(this)
|
||||
|
||||
object mAccountRoutingScheme extends MappedString(this, 32)
|
||||
|
||||
@ -15,7 +15,7 @@ import net.liftweb.mapper._
|
||||
*/
|
||||
object MappedWebUiPropsProvider extends WebUiPropsProvider {
|
||||
// default webUiProps value cached seconds
|
||||
private val webUiPropsTTL = APIUtil.getPropsAsIntValue("webui.props.cache.ttl.seconds", 20)
|
||||
private val webUiPropsTTL = APIUtil.getPropsAsIntValue("webui.props.cache.ttl.seconds", 0)
|
||||
|
||||
override def getAll(): List[WebUiPropsT] = WebUiProps.findAll()
|
||||
|
||||
|
||||
1
obp-api/src/main/scripts/migrate/migrate_00000018.sql
Normal file
1
obp-api/src/main/scripts/migrate/migrate_00000018.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE "methodrouting" ADD "parameters" varchar(5000) NULL;
|
||||
@ -0,0 +1,277 @@
|
||||
package code.api.v3_1_0
|
||||
|
||||
import net.liftweb.json.JValue
|
||||
import org.scalatest.Tag
|
||||
import io.swagger.parser.OpenAPIParser
|
||||
import java.util
|
||||
import code.api.ResourceDocs1_4_0.ResourceDocsV140ServerSetup
|
||||
import code.api.util.{ApiVersion, CustomJsonFormats}
|
||||
import code.api.v1_4_0.JSONFactory1_4_0.ImplementedByJson
|
||||
import net.liftweb.json
|
||||
|
||||
import scala.collection.immutable.List
|
||||
class ResourceDocsTest extends ResourceDocsV140ServerSetup with CustomJsonFormats{
|
||||
|
||||
object VersionOfApi extends Tag(ApiVersion.v1_4_0.toString)
|
||||
object ApiEndpoint1 extends Tag("Get Swagger ResourceDoc")
|
||||
object ApiEndpoint2 extends Tag("Get OBP ResourceDoc ")
|
||||
|
||||
|
||||
feature(s"test ${ApiEndpoint1.name} ") {
|
||||
|
||||
case class RoleJson (
|
||||
role: String,
|
||||
requires_bank_id: Boolean
|
||||
)
|
||||
|
||||
//This case class is for API_Explorer, it should make sure api_explorer can get proper doc.
|
||||
case class ResourceDocJson(operation_id: String,
|
||||
request_verb: String,
|
||||
request_url: String,
|
||||
summary: String, // Summary of call should be 120 characters max
|
||||
description: String, // Description of call in markdown
|
||||
example_request_body: JValue, // An example request body
|
||||
success_response_body: JValue, // Success response body
|
||||
error_response_bodies: List[String],
|
||||
implemented_by: ImplementedByJson,
|
||||
is_core : Boolean,
|
||||
is_psd2 : Boolean,
|
||||
is_obwg : Boolean, // This may be tracking isCore
|
||||
tags : List[String],
|
||||
roles: List[RoleJson],
|
||||
is_featured: Boolean,
|
||||
special_instructions: String,
|
||||
specified_url: String // This is the URL that we want people to call.
|
||||
)
|
||||
|
||||
case class ResourceDocsJson (resource_docs : List[ResourceDocJson])
|
||||
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v4.0.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v3.1.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v3.0.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v2.2.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v2.1.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v2.0.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.4.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.3.0" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint1.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.2.1" / "obp").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
responseGetObp.body.extract[ResourceDocsJson]
|
||||
}
|
||||
}
|
||||
|
||||
feature(s"test ${ApiEndpoint2.name} ") {
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v4.0.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v4.0.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
if (!errors.isEmpty) logger.info(s"Here is the wrong swagger json: $swaggerJsonString")
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v3.1.1", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v3.1.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v3.0.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v3.0.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v2.2.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v2.2.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v2.1.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v2.1.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v2.0.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v2.0.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v1.4.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.4.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v1.3.0", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.3.0" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
scenario(s"We will test ${ApiEndpoint2.name} Api - v1.2.1", ApiEndpoint2, VersionOfApi) {
|
||||
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v1.2.1" / "swagger").GET
|
||||
val responseGetObp = makeGetRequest(requestGetObp)
|
||||
And("We should get 200 and the response can be extract to case classes")
|
||||
responseGetObp.code should equal(200)
|
||||
val swaggerJsonString = json.compactRender(responseGetObp.body)
|
||||
|
||||
val validatedSwaggerResult = ValidateSwaggerString(swaggerJsonString)
|
||||
val errors = validatedSwaggerResult._1
|
||||
errors.isEmpty should be (true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Note: it is tricky to validate the swagger string, I just find this : https://github.com/swagger-api/swagger-parser/issues/718
|
||||
//So follow it to call the `Validate` method:
|
||||
//https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Validate.java#L46
|
||||
def ValidateSwaggerString (swaggerJsonString: String)= {
|
||||
val result = new OpenAPIParser().readContents(swaggerJsonString, null, null)
|
||||
val messageList: util.List[String] = result.getMessages()
|
||||
|
||||
val errors = new util.HashSet[String](messageList)
|
||||
val warnings = new util.HashSet[String]
|
||||
|
||||
val sb = new StringBuilder
|
||||
|
||||
if (!errors.isEmpty) {
|
||||
sb.append("Errors:").append(System.lineSeparator)
|
||||
errors.forEach((msg: String) => sb.append("\t-").append(msg).append(System.lineSeparator))
|
||||
}
|
||||
|
||||
if (!warnings.isEmpty) {
|
||||
sb.append("Warnings: ").append(System.lineSeparator)
|
||||
warnings.forEach((msg: String) => sb.append("\t-").append(msg).append(System.lineSeparator))
|
||||
}
|
||||
|
||||
if (!errors.isEmpty) {
|
||||
sb.append(System.lineSeparator)
|
||||
sb.append("[error] Spec has ").append(errors.size).append(" errors.")
|
||||
System.err.println(sb.toString)
|
||||
System.exit(1)
|
||||
}
|
||||
else if (!warnings.isEmpty) {
|
||||
sb.append(System.lineSeparator)
|
||||
sb.append("[info] Spec has ").append(warnings.size).append(" recommendation(s).")
|
||||
}
|
||||
else { // we say "issues" here rather than "errors" to account for both errors and issues.
|
||||
sb.append("No validation issues detected.")
|
||||
}
|
||||
val allMessages = sb.toString
|
||||
logger.info(s"validatedSwaggerResult.errors $errors")
|
||||
logger.info(s"validatedSwaggerResult.warnings $warnings")
|
||||
logger.info(s"validatedSwaggerResult.allMessages $allMessages")
|
||||
|
||||
(errors, warnings, allMessages)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package code.api.ResourceDocs1_4_0
|
||||
|
||||
import code.setup.ServerSetupWithTestData
|
||||
|
||||
trait ResourceDocsV140ServerSetup extends ServerSetupWithTestData {
|
||||
|
||||
def ResourceDocsV1_4Request = baseRequest / "obp" / "v1.4.0"
|
||||
def ResourceDocsV2_0Request = baseRequest / "obp" / "v2.0.0"
|
||||
def ResourceDocsV2_1Request = baseRequest / "obp" / "v2.1.0"
|
||||
def ResourceDocsV2_2Request = baseRequest / "obp" / "v2.2.0"
|
||||
def ResourceDocsV3_0Request = baseRequest / "obp" / "v3.0.0"
|
||||
def ResourceDocsV3_1Request = baseRequest / "obp" / "v3.1.0"
|
||||
def ResourceDocsV4_0Request = baseRequest / "obp" / "v4.0.0"
|
||||
|
||||
}
|
||||
@ -20,6 +20,7 @@ class AccountTest extends V310ServerSetup with DefaultUsers {
|
||||
object VersionOfApi extends Tag(ApiVersion.v3_1_0.toString)
|
||||
object ApiEndpoint1 extends Tag(nameOf(Implementations3_1_0.updateAccount))
|
||||
object ApiEndpoint2 extends Tag(nameOf(Implementations3_1_0.createAccount))
|
||||
object ApiEndpoint3 extends Tag(nameOf(Implementations3_1_0.getBankAccountsBalances))
|
||||
|
||||
lazy val testBankId = testBankId1
|
||||
lazy val putCreateAccountJSONV310 = SwaggerDefinitionsJSON.createAccountJSONV220.copy(user_id = resourceUser1.userId)
|
||||
@ -119,4 +120,19 @@ class AccountTest extends V310ServerSetup with DefaultUsers {
|
||||
|
||||
}
|
||||
|
||||
feature(s"test ${ApiEndpoint3.name}") {
|
||||
scenario("We will test ${ApiEndpoint3.name}", ApiEndpoint3, VersionOfApi) {
|
||||
Given("The test bank and test accounts")
|
||||
val requestGet = (v3_1_0_Request / "banks" / testBankId.value / "balances").GET <@ (user1)
|
||||
|
||||
val responseGet = makeGetRequest(requestGet)
|
||||
responseGet.code should equal(200)
|
||||
responseGet.body.extract[AccountsBalancesV310Json].accounts.size > 0 should be (true)
|
||||
responseGet.body.extract[AccountsBalancesV310Json].overall_balance.currency.nonEmpty should be (true)
|
||||
responseGet.body.extract[AccountsBalancesV310Json].overall_balance.amount.nonEmpty should be (true)
|
||||
responseGet.body.extract[AccountsBalancesV310Json].overall_balance_date.getTime >0 should be (true)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -32,11 +32,13 @@ import code.api.util.ApiVersion
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0
|
||||
import code.entitlement.Entitlement
|
||||
import code.methodrouting.MethodRoutingCommons
|
||||
import code.methodrouting.{MethodRoutingCommons, MethodRoutingParam}
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import net.liftweb.json.Serialization.write
|
||||
import org.scalatest.Tag
|
||||
|
||||
import scala.collection.immutable.List
|
||||
|
||||
class MethodRoutingTest extends V310ServerSetup {
|
||||
|
||||
/**
|
||||
@ -52,7 +54,7 @@ class MethodRoutingTest extends V310ServerSetup {
|
||||
object ApiEndpoint3 extends Tag(nameOf(Implementations3_1_0.getMethodRoutings))
|
||||
object ApiEndpoint4 extends Tag(nameOf(Implementations3_1_0.deleteMethodRouting))
|
||||
|
||||
val rightEntity = MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_.*"))
|
||||
val rightEntity = MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_.*"), Some(List(MethodRoutingParam("url", "http://mydomain.com/xxx"))))
|
||||
val wrongEntity = MethodRoutingCommons("getBank", "rest_vMar2019", false, Some("some_bankId_([")) // wrong regex
|
||||
|
||||
|
||||
|
||||
@ -84,6 +84,10 @@ case class OutBoundGetCoreBankAccounts(outboundAdapterCallContext: OutboundAdapt
|
||||
bankIdAccountIds: List[BankIdAccountId]) extends TopicTrait
|
||||
case class InBoundGetCoreBankAccounts(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[CoreAccount]) extends InBoundTrait[List[CoreAccount]]
|
||||
|
||||
case class OutBoundGetBankAccountsBalances(outboundAdapterCallContext: OutboundAdapterCallContext,
|
||||
bankIdAccountIds: List[BankIdAccountId]) extends TopicTrait
|
||||
|
||||
case class InBoundGetBankAccountsBalances(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: AccountsBalances) extends InBoundTrait[AccountsBalances]
|
||||
|
||||
case class OutBoundGetCoreBankAccountsHeld(outboundAdapterCallContext: OutboundAdapterCallContext,
|
||||
bankIdAccountIds: List[BankIdAccountId]) extends TopicTrait
|
||||
|
||||
@ -184,6 +184,7 @@ trait BankAccount{
|
||||
def iban : Option[String]
|
||||
def number : String
|
||||
def bankId : BankId
|
||||
//It means last transaction refresh date only used for HBCI now.
|
||||
def lastUpdate : Date
|
||||
def branchId: String
|
||||
def accountRoutingScheme: String
|
||||
@ -298,6 +299,20 @@ case class CoreAccount(
|
||||
accountRoutings: List[AccountRouting]
|
||||
)
|
||||
|
||||
case class AccountBalance(
|
||||
id: String,
|
||||
label: String,
|
||||
bankId: String,
|
||||
accountRoutings: List[AccountRouting],
|
||||
balance: AmountOfMoney
|
||||
)
|
||||
|
||||
case class AccountsBalances(
|
||||
accounts: List[AccountBalance],
|
||||
overallBalance: AmountOfMoney,
|
||||
overallBalanceDate: Date
|
||||
)
|
||||
|
||||
case class AccountHeld(
|
||||
id: String,
|
||||
bankId: String,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user