Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
Marko Milić 2022-10-12 08:41:14 +02:00
commit 2ab9f3f528
19 changed files with 1022 additions and 9 deletions

View File

@ -39,7 +39,7 @@ import code.accountattribute.MappedAccountAttribute
import code.accountholders.MapperAccountHolders
import code.actorsystem.ObpActorSystem
import code.api.Constant._
import code.api.ResourceDocs1_4_0.ResourceDocs300.{ResourceDocs310, ResourceDocs400}
import code.api.ResourceDocs1_4_0.ResourceDocs300.{ResourceDocs310, ResourceDocs400, ResourceDocs500}
import code.api.ResourceDocs1_4_0._
import code.api._
import code.api.attributedefinition.AttributeDefinition
@ -102,6 +102,7 @@ import code.apicollectionendpoint.ApiCollectionEndpoint
import code.apicollection.ApiCollection
import code.bankattribute.BankAttribute
import code.connectormethod.ConnectorMethod
import code.customeraccountlinks.CustomerAccountLink
import code.dynamicMessageDoc.DynamicMessageDoc
import code.dynamicResourceDoc.DynamicResourceDoc
import code.endpointMapping.EndpointMapping
@ -466,6 +467,7 @@ class Boot extends MdcLoggable {
LiftRules.statelessDispatch.append(ResourceDocs300)
LiftRules.statelessDispatch.append(ResourceDocs310)
LiftRules.statelessDispatch.append(ResourceDocs400)
LiftRules.statelessDispatch.append(ResourceDocs500)
////////////////////////////////////////////////////
@ -967,7 +969,8 @@ object ToSchemify {
BankAttribute,
RateLimiting,
MappedCustomerDependant,
AttributeDefinition
AttributeDefinition,
CustomerAccountLink
)
// The following tables are accessed directly via Mapper / JDBC

View File

@ -104,6 +104,22 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md
ImplementationsResourceDocs.getResourceDocsObpV400,
ImplementationsResourceDocs.getResourceDocsSwagger,
ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp,
// ImplementationsResourceDocs.getStaticResourceDocsObp
)
routes.foreach(route => {
oauthServe(apiPrefix {
route
})
})
}
// Hack to provide Resource Docs / Swagger on endpoints other than 1.4.0 where it is defined.
object ResourceDocs500 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable {
val version: ApiVersion = ApiVersion.v5_0_0 // = "4.0.0" // We match other api versions so API explorer can easily use the path.
val versionStatus = "BLEEDING-EDGE"
val routes = List(
ImplementationsResourceDocs.getResourceDocsObpV400,
ImplementationsResourceDocs.getResourceDocsSwagger,
ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp,
// ImplementationsResourceDocs.getStaticResourceDocsObp
)
routes.foreach(route => {

View File

@ -4905,6 +4905,26 @@ object SwaggerDefinitionsJSON {
card_attributes = List(cardAttributeCommons),
brand = brandExample.value
)
val createCustomerAccountLinkJson = CreateCustomerAccountLinkJson(
customer_id = customerIdExample.value,
account_id = accountIdExample.value,
relationship_type= relationshipTypeExample.value
)
val updateCustomerAccountLinkJson = UpdateCustomerAccountLinkJson(
relationship_type= relationshipTypeExample.value
)
val customerAccountLinkJson = CustomerAccountLinkJson(
customer_account_link_id = customerAccountLinkIdExample.value,
customer_id = customerIdExample.value,
account_id = accountIdExample.value,
relationship_type= relationshipTypeExample.value
)
val customerAccountLinksJson = CustomerAccountLinksJson(
List(customerAccountLinkJson)
)
//The common error or success format.
//Just some helper format to use in Json
case class NotSupportedYet()

View File

@ -249,6 +249,21 @@ object ApiRole {
case class CanGetCardsForBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetCardsForBank = CanGetCardsForBank()
case class CanCreateCustomerAccountLink(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateCustomerAccountLink = CanCreateCustomerAccountLink()
case class CanUpdateCustomerAccountLink(requiresBankId: Boolean = true) extends ApiRole
lazy val canUpdateCustomerAccountLink = CanUpdateCustomerAccountLink()
case class CanDeleteCustomerAccountLink(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteCustomerAccountLink = CanDeleteCustomerAccountLink()
case class CanGetCustomerAccountLink(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetCustomerAccountLink = CanGetCustomerAccountLink()
case class CanGetCustomerAccountLinks(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetCustomerAccountLinks = CanGetCustomerAccountLinks()
case class CanCreateBranch(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateBranch = CanCreateBranch()

View File

@ -401,6 +401,7 @@ object ErrorMessages {
val InvalidCardNumber = "OBP-30200: Card not found. Please specify a valid value for CARD_NUMBER. "
val CustomerAccountLinkNotFound = "OBP-30204: Customer Account Link not found"
val EntitlementIsBankRole = "OBP-30205: This entitlement is a Bank Role. Please set bank_id to a valid bank id."
val EntitlementIsSystemRole = "OBP-30206: This entitlement is a System Role. Please set bank_id to empty string."
@ -428,6 +429,12 @@ object ErrorMessages {
val EntitlementCannotBeGrantedGrantorIssue = "OBP-30221: Entitlement cannot be granted due to the grantor's insufficient privileges."
val CounterpartyNotFoundByRoutings = "OBP-30222: Counterparty not found. Please specify valid value for Routings."
val AccountAlreadyExistsForCustomer = "OBP-30223: The Account is already linked to a Customer at the bank specified by BANK_ID"
val CreateCustomerAccountLinkError = "OBP-30224: Could not create the customer account link."
val CustomerAccountLinkNotFoundById = "OBP-30225: Customer Account Link not found. Please specify valid values for CUSTOMER_ACCOUNT_LINK_ID."
val GetCustomerAccountLinksError = "OBP-30226: Could not get the customer account links."
val UpdateCustomerAccountLinkError = "OBP-30227: Could not update the customer account link."
val DeleteCustomerAccountLinkError = "OBP-30228: Could not delete the customer account link."
val CreateSystemViewError = "OBP-30250: Could not create the system view"
val DeleteSystemViewError = "OBP-30251: Could not delete the system view"

View File

@ -40,7 +40,10 @@ object ExampleValue {
lazy val sessionIdExample = ConnectorField("b4e0352a-9a0f-4bfa-b30b-9003aa467f50", s"A string that MUST uniquely identify the session on this OBP instance, can be used in all cache. ")
lazy val userIdExample = ConnectorField("9ca9a7e4-6d02-40e3-a129-0b2bf89de9b1", s"A string that MUST uniquely identify the user on this OBP instance.")
glossaryItems += makeGlossaryItem("User.userId", userIdExample)
glossaryItems += makeGlossaryItem("User.userId", userIdExample)
lazy val relationshipTypeExample = ConnectorField("Owner", s"Relationship between two parties.")
glossaryItems += makeGlossaryItem("Customer.relationshipType", relationshipTypeExample)
lazy val usernameExample = ConnectorField("felixsmith", s"The username the user uses to authenticate.")
@ -59,6 +62,9 @@ object ExampleValue {
lazy val customerIdExample = ConnectorField("7uy8a7e4-6d02-40e3-a129-0b2bf89de8uh", s"A non human friendly string that identifies the customer and is used in URLs. This SHOULD NOT be the customer number. The combination of customerId and bankId MUST be unique on an OBP instance. customerId SHOULD be unique on an OBP instance. Ideally customerId is a UUID. A mapping between customer number and customer id is kept in OBP.")
glossaryItems += makeGlossaryItem("Customer.customerId", customerIdExample)
lazy val customerAccountLinkIdExample = ConnectorField("xyz8a7e4-6d02-40e3-a129-0b2bf89de8uh", s"A non human friendly string that identifies the Customer Account Link and is used in URLs. ")
glossaryItems += makeGlossaryItem("Customer.customerAccountLinkId", customerAccountLinkIdExample)
lazy val customerAttributeId = ConnectorField("7uy8a7e4-6d02-40e3-a129-0b2bf89de8uh", s"A non human friendly string that identifies the customer attribute and is used in URLs.")
glossaryItems += makeGlossaryItem("Customer.customerAttributeId", customerAttributeId)

View File

@ -3,7 +3,6 @@ package code.api.util
import java.util.Date
import java.util.UUID.randomUUID
import akka.http.scaladsl.model.HttpMethod
import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT}
import code.api.{APIFailureNewStyle, Constant, JsonResponseException}
@ -69,6 +68,7 @@ import code.api.v4_0_0.JSONFactory400
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
import code.bankattribute.BankAttribute
import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod}
import code.customeraccountlinks.CustomerAccountLinkTrait
import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc}
import code.dynamicResourceDoc.{DynamicResourceDocProvider, JsonDynamicResourceDoc}
import code.endpointMapping.{EndpointMappingProvider, EndpointMappingT}
@ -3736,5 +3736,36 @@ object NewStyle extends MdcLoggable{
i => (connectorEmptyResponse(i._1, callContext), i._2)
}
}
def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String, callContext: Option[CallContext]): OBPReturnType[CustomerAccountLinkTrait] =
Connector.connector.vend.createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, CreateCustomerAccountLinkError), i._2)
}
def getCustomerAccountLinksByCustomerId(customerId: String, callContext: Option[CallContext]): OBPReturnType[List[CustomerAccountLinkTrait]] =
Connector.connector.vend.getCustomerAccountLinksByCustomerId(customerId: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, GetCustomerAccountLinksError), i._2)
}
def getCustomerAccountLinksByAccountId(accountId: String, callContext: Option[CallContext]): OBPReturnType[List[CustomerAccountLinkTrait]] =
Connector.connector.vend.getCustomerAccountLinksByAccountId(accountId: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, GetCustomerAccountLinksError), i._2)
}
def getCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]): OBPReturnType[CustomerAccountLinkTrait] =
Connector.connector.vend.getCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, CustomerAccountLinkNotFoundById), i._2)
}
def deleteCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]): OBPReturnType[Boolean] =
Connector.connector.vend.deleteCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, DeleteCustomerAccountLinkError), i._2)
}
def updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String, callContext: Option[CallContext]): OBPReturnType[CustomerAccountLinkTrait] =
Connector.connector.vend.updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, UpdateCustomerAccountLinkError), i._2)
}
}
}

View File

@ -1,7 +1,6 @@
package code.api.v5_0_0
import java.util.Date
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.util.APIUtil._
import code.api.util.ApiRole._
@ -38,6 +37,7 @@ import net.liftweb.util.Props
import java.util.concurrent.ThreadLocalRandom
import code.accountattribute.AccountAttributeX
import code.util.Helper.booleanToFuture
import scala.collection.immutable.{List, Nil}
import scala.collection.mutable.ArrayBuffer
@ -1443,6 +1443,241 @@ trait APIMethods500 {
}
}
staticResourceDocs += ResourceDoc(
createCustomerAccountLink,
implementedInApiVersion,
nameOf(createCustomerAccountLink),
"POST",
"/banks/BANK_ID/customer-account-links",
"Create Customer Account Link",
s"""Link a Customer to a Account
|
|${authenticationRequiredMessage(true)}
|
|""",
createCustomerAccountLinkJson,
customerAccountLinkJson,
List(
$UserNotLoggedIn,
$BankNotFound,
BankAccountNotFound,
InvalidJsonFormat,
CustomerNotFoundByCustomerId,
UserHasMissingRoles,
AccountAlreadyExistsForCustomer,
CreateCustomerAccountLinkError,
UnknownError
),
List(apiTagCustomer, apiTagAccount),
Some(List(canCreateCustomerAccountLink)))
lazy val createCustomerAccountLink : OBPEndpoint = {
case "banks" :: BankId(bankId):: "customer-account-links" :: Nil JsonPost json -> _ => {
cc =>
for {
(_, _,callContext) <- SS.userBank
postedData <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $CreateCustomerAccountLinkJson ", 400, callContext) {
json.extract[CreateCustomerAccountLinkJson]
}
(customer, callContext) <- NewStyle.function.getCustomerByCustomerId(postedData.customer_id, callContext)
_ <- booleanToFuture(s"Bank of the customer specified by the CUSTOMER_ID(${customer.bankId}) has to matches BANK_ID(${bankId.value}) in URL", 400, callContext) {
customer.bankId == bankId.value
}
(_, callContext) <- NewStyle.function.getBankAccount(bankId, AccountId(postedData.account_id), callContext)
_ <- booleanToFuture("Field customer_id is not defined in the posted json!", 400, callContext) {
postedData.customer_id.nonEmpty
}
(customerAccountLinkExists, callContext) <- Connector.connector.vend.getCustomerAccountLink(postedData.customer_id, postedData.account_id, callContext)
_ <- booleanToFuture(AccountAlreadyExistsForCustomer, 400, callContext) {
customerAccountLinkExists.isEmpty
}
(customerAccountLink, callContext) <- NewStyle.function.createCustomerAccountLink(postedData.customer_id, postedData.account_id, postedData.relationship_type, callContext)
} yield {
(JSONFactory500.createCustomerAccountLinkJson(customerAccountLink), HttpCode.`201`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getCustomerAccountLinksByCustomerId,
implementedInApiVersion,
nameOf(getCustomerAccountLinksByCustomerId),
"GET",
"/banks/BANK_ID/customers/CUSTOMER_ID/customer-account-links",
"Get Customer Account Links by CUSTOMER_ID",
s""" Get Customer Account Links by CUSTOMER_ID
|
|${authenticationRequiredMessage(true)}
|
|""",
EmptyBody,
customerAccountLinksJson,
List(
$UserNotLoggedIn,
$BankNotFound,
CustomerNotFoundByCustomerId,
UserHasMissingRoles,
UnknownError
),
List(apiTagCustomer, apiTagNewStyle),
Some(List(canGetCustomerAccountLinks)))
lazy val getCustomerAccountLinksByCustomerId : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "customers" :: customerId :: "customer-account-links" :: Nil JsonGet _ => {
cc =>
for {
(customer, callContext) <- NewStyle.function.getCustomerByCustomerId(customerId, cc.callContext)
_ <- booleanToFuture(s"Bank of the customer specified by the CUSTOMER_ID(${customer.bankId}) has to matches BANK_ID(${bankId.value}) in URL", 400, callContext) {
customer.bankId == bankId.value
}
(customerAccountLinks, callContext) <- NewStyle.function.getCustomerAccountLinksByCustomerId(customerId, callContext)
} yield {
(JSONFactory500.createCustomerAccountLinksJon(customerAccountLinks), HttpCode.`200`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getCustomerAccountLinksByAccountId,
implementedInApiVersion,
nameOf(getCustomerAccountLinksByAccountId),
"GET",
"/banks/BANK_ID/accounts/ACCOUNT_ID/customer-account-links",
"Get Customer Account Links by ACCOUNT_ID",
s""" Get Customer Account Links by ACCOUNT_ID
|
|${authenticationRequiredMessage(true)}
|
|""",
EmptyBody,
customerAccountLinksJson,
List(
$UserNotLoggedIn,
$BankNotFound,
BankAccountNotFound,
UserHasMissingRoles,
UnknownError
),
List(apiTagCustomer, apiTagNewStyle),
Some(List(canGetCustomerAccountLinks)))
lazy val getCustomerAccountLinksByAccountId : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "accounts" :: accountId :: "customer-account-links" :: Nil JsonGet _ => {
cc =>
for {
(_, _,callContext) <- SS.userBank
(customerAccountLinks, callContext) <- NewStyle.function.getCustomerAccountLinksByAccountId(accountId, callContext)
} yield {
(JSONFactory500.createCustomerAccountLinksJon(customerAccountLinks), HttpCode.`200`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getCustomerAccountLinkById,
implementedInApiVersion,
nameOf(getCustomerAccountLinkById),
"GET",
"/banks/BANK_ID/customer-account-links/CUSTOMER_ACCOUNT_LINK_ID",
"Get Customer Account Link by Id",
s""" Get Customer Account Link by CUSTOMER_ACCOUNT_LINK_ID
|
|${authenticationRequiredMessage(true)}
|
|""",
EmptyBody,
customerAccountLinkJson,
List(
$UserNotLoggedIn,
$BankNotFound,
UserHasMissingRoles,
UnknownError
),
List(apiTagCustomer, apiTagNewStyle),
Some(List(canGetCustomerAccountLink)))
lazy val getCustomerAccountLinkById : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "customer-account-links" :: customerAccountLinkId :: Nil JsonGet _ => {
cc =>
for {
(_, _,callContext) <- SS.userBank
(customerAccountLink, callContext) <- NewStyle.function.getCustomerAccountLinkById(customerAccountLinkId, callContext)
} yield {
(JSONFactory500.createCustomerAccountLinkJson(customerAccountLink), HttpCode.`200`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
updateCustomerAccountLinkById,
implementedInApiVersion,
nameOf(updateCustomerAccountLinkById),
"PUT",
"/banks/BANK_ID/customer-account-links/CUSTOMER_ACCOUNT_LINK_ID",
"Update Customer Account Link by Id",
s""" Update Customer Account Link by CUSTOMER_ACCOUNT_LINK_ID
|
|${authenticationRequiredMessage(true)}
|
|""",
updateCustomerAccountLinkJson,
customerAccountLinkJson,
List(
$UserNotLoggedIn,
$BankNotFound,
UserHasMissingRoles,
UnknownError
),
List(apiTagCustomer, apiTagNewStyle),
Some(List(canUpdateCustomerAccountLink)))
lazy val updateCustomerAccountLinkById : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "customer-account-links" :: customerAccountLinkId :: Nil JsonPut json -> _ => {
cc =>
for {
(Full(u), _,callContext) <- SS.userBank
postedData <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $UpdateCustomerAccountLinkJson ", 400, callContext) {
json.extract[UpdateCustomerAccountLinkJson]
}
(_, callContext) <- NewStyle.function.getCustomerAccountLinkById(customerAccountLinkId, callContext)
(customerAccountLink, callContext) <- NewStyle.function.updateCustomerAccountLinkById(customerAccountLinkId, postedData.relationship_type, callContext)
} yield {
(JSONFactory500.createCustomerAccountLinkJson(customerAccountLink), HttpCode.`200`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
deleteCustomerAccountLinkById,
implementedInApiVersion,
nameOf(deleteCustomerAccountLinkById),
"DELETE",
"/banks/BANK_ID/customer-account-links/CUSTOMER_ACCOUNT_LINK_ID",
"Delete Customer Account Link",
s""" Delete Customer Account Link by CUSTOMER_ACCOUNT_LINK_ID
|
|${authenticationRequiredMessage(true)}
|
|""",
EmptyBody,
EmptyBody,
List(
$UserNotLoggedIn,
$BankNotFound,
UserHasMissingRoles,
UnknownError
),
List(apiTagCustomer, apiTagNewStyle),
Some(List(canDeleteCustomerAccountLink)))
lazy val deleteCustomerAccountLinkById : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "customer-account-links" :: customerAccountLinkId :: Nil JsonDelete _ => {
cc =>
for {
(Full(u), _,callContext) <- SS.userBank
(_, callContext) <- NewStyle.function.getCustomerAccountLinkById(customerAccountLinkId, callContext)
(deleted, callContext) <- NewStyle.function.deleteCustomerAccountLinkById(customerAccountLinkId, callContext)
} yield {
(Full(deleted), HttpCode.`204`(callContext))
}
}
}
}
}

View File

@ -28,7 +28,6 @@ package code.api.v5_0_0
import java.lang
import java.util.Date
import code.api.util.APIUtil.{stringOptionOrNull, stringOrNull}
import code.api.v1_2_1.BankRoutingJsonV121
import code.api.v1_4_0.JSONFactory1_4_0.{CustomerFaceImageJson, MetaJsonV140}
@ -40,6 +39,7 @@ import code.api.v3_0_0.{CustomerAttributeResponseJsonV300, JSONFactory300}
import code.api.v3_1_0.{AccountAttributeResponseJson, AccountBasicV310, CustomerWithAttributesJsonV310, PhysicalCardWithAttributesJsonV310, PostConsentEntitlementJsonV310}
import code.api.v4_0_0.BankAttributeBankResponseJsonV400
import code.bankattribute.BankAttribute
import code.customeraccountlinks.CustomerAccountLinkTrait
import com.openbankproject.commons.model.{AccountAttribute, AccountRouting, AccountRoutingJsonV121, AmountOfMoneyJsonV121, Bank, BankAccount, CardAttribute, Customer, CustomerAttribute, PhysicalCardTrait, User, UserAuthContext, UserAuthContextUpdate, View, ViewBasic}
import net.liftweb.json.JsonAST.JValue
@ -349,6 +349,28 @@ case class UpdatePhysicalCardJsonV500(
brand: String
)
case class CreateCustomerAccountLinkJson(
customer_id: String,
account_id: String,
relationship_type: String
)
case class UpdateCustomerAccountLinkJson(
relationship_type: String
)
case class CustomerAccountLinkJson(
customer_account_link_id: String,
customer_id: String,
account_id: String,
relationship_type: String
)
case class CustomerAccountLinksJson(
links:List[CustomerAccountLinkJson]
)
object JSONFactory500 {
def createUserAuthContextJson(userAuthContext: UserAuthContext): UserAuthContextJsonV500 = {
@ -560,5 +582,19 @@ object JSONFactory500 {
brand = stringOptionOrNull(card.brand)
)
}
def createCustomerAccountLinkJson(customerAccountLink: CustomerAccountLinkTrait): CustomerAccountLinkJson ={
CustomerAccountLinkJson(
customerAccountLink.customerAccountLinkId,
customerAccountLink.customerId,
customerAccountLink.accountId,
customerAccountLink.relationshipType
)
}
def createCustomerAccountLinksJon(customerAccountLinks: List[CustomerAccountLinkTrait]): CustomerAccountLinksJson = {
CustomerAccountLinksJson(customerAccountLinks.map(createCustomerAccountLinkJson))
}
}

View File

@ -2,7 +2,6 @@ package code.bankconnectors
import java.util.Date
import java.util.UUID.randomUUID
import _root_.akka.http.scaladsl.model.HttpMethod
import code.accountholders.{AccountHolders, MapperAccountHolders}
import code.api.attributedefinition.AttributeDefinition
@ -22,6 +21,7 @@ import code.bankconnectors.rest.RestConnector_vMar2019
import code.bankconnectors.storedprocedure.StoredProcedureConnector_vDec2019
import code.bankconnectors.vMay2019.KafkaMappedConnector_vMay2019
import code.bankconnectors.vSept2018.KafkaMappedConnector_vSept2018
import code.customeraccountlinks.CustomerAccountLinkTrait
import code.endpointTag.EndpointTagT
import code.fx.fx.TTL
import code.management.ImporterAPI.ImporterTransaction
@ -2574,5 +2574,19 @@ trait Connector extends MdcLoggable {
message: String,
callContext: Option[CallContext]
): OBPReturnType[Box[String]] = Future{(Failure(setUnimplementedError), callContext)}
def getCustomerAccountLink(customerId: String, accountId: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAccountLinkTrait]] = Future{(Failure(setUnimplementedError), callContext)}
def getCustomerAccountLinksByCustomerId(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAccountLinkTrait]]] = Future{(Failure(setUnimplementedError), callContext)}
def getCustomerAccountLinksByAccountId(accountId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAccountLinkTrait]]] = Future{(Failure(setUnimplementedError), callContext)}
def getCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAccountLinkTrait]] = Future{(Failure(setUnimplementedError), callContext)}
def deleteCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = Future{(Failure(setUnimplementedError), callContext)}
def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAccountLinkTrait]] = Future{(Failure(setUnimplementedError), callContext)}
def updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAccountLinkTrait]] = Future{(Failure(setUnimplementedError), callContext)}
}

View File

@ -2,7 +2,6 @@ package code.bankconnectors
import java.util.Date
import java.util.UUID.randomUUID
import _root_.akka.http.scaladsl.model.HttpMethod
import code.DynamicData.DynamicDataProvider
import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT}
@ -31,6 +30,7 @@ import code.cardattribute.CardAttributeX
import code.cards.MappedPhysicalCard
import code.context.{UserAuthContextProvider, UserAuthContextUpdateProvider}
import code.customer._
import code.customeraccountlinks.CustomerAccountLinkTrait
import code.customeraddress.CustomerAddressX
import code.customerattribute.CustomerAttributeX
import code.database.authorisation.Authorisations
@ -5560,5 +5560,34 @@ object LocalMappedConnector extends Connector with MdcLoggable {
} else
Future{(Full("Success"), callContext)}
}
override def getCustomerAccountLink(customerId: String, accountId: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAccountLinkTrait]] = Future{
(CustomerAccountLinkTrait.customerAccountLink.vend.getCustomerAccountLink(customerId, accountId), callContext)
}
override def getCustomerAccountLinksByCustomerId(customerId: String, callContext: Option[CallContext]) = Future{
(CustomerAccountLinkTrait.customerAccountLink.vend.getCustomerAccountLinksByCustomerId(customerId),callContext)
}
override def getCustomerAccountLinksByAccountId(accountId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAccountLinkTrait]]] = Future{
(CustomerAccountLinkTrait.customerAccountLink.vend.getCustomerAccountLinksByAccountId(accountId),callContext)
}
override def getCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]) = Future{
(CustomerAccountLinkTrait.customerAccountLink.vend.getCustomerAccountLinkById(customerAccountLinkId),callContext)
}
override def deleteCustomerAccountLinkById(customerAccountLinkId: String, callContext: Option[CallContext]) =
CustomerAccountLinkTrait.customerAccountLink.vend.deleteCustomerAccountLinkById(customerAccountLinkId).map {(_, callContext)}
override def updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String, callContext: Option[CallContext]) = Future{
(CustomerAccountLinkTrait.customerAccountLink.vend.updateCustomerAccountLinkById(customerAccountLinkId, relationshipType),callContext)
}
override def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAccountLinkTrait]] = Future{
CustomerAccountLinkTrait.customerAccountLink.vend.createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) map { ( _, callContext) }
}
}

View File

@ -0,0 +1,58 @@
package code.customeraccountlinks
import code.api.util.APIUtil
import code.remotedata.RemotedataCustomerAccountLinks
import net.liftweb.common.Box
import net.liftweb.util.SimpleInjector
import scala.concurrent.Future
object CustomerAccountLinkTrait extends SimpleInjector {
val customerAccountLink = new Inject(buildOne _) {}
def buildOne: CustomerAccountLinkProvider =
APIUtil.getPropsAsBoolValue("use_akka", false) match {
case false => MappedCustomerAccountLinkProvider
case true => RemotedataCustomerAccountLinks // We will use Akka as a middleware
}
}
trait CustomerAccountLinkProvider {
def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait]
def getOrCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait]
def getCustomerAccountLinkByCustomerId(customerId: String): Box[CustomerAccountLinkTrait]
def getCustomerAccountLinksByCustomerId(customerId: String): Box[List[CustomerAccountLinkTrait]]
def getCustomerAccountLinksByAccountId(accountId: String): Box[List[CustomerAccountLinkTrait]]
def getCustomerAccountLink(customerId: String, accountId: String): Box[CustomerAccountLinkTrait]
def getCustomerAccountLinkById(customerAccountLinkId: String): Box[CustomerAccountLinkTrait]
def updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String): Box[CustomerAccountLinkTrait]
def getCustomerAccountLinks: Box[List[CustomerAccountLinkTrait]]
def bulkDeleteCustomerAccountLinks(): Boolean
def deleteCustomerAccountLinkById(customerAccountLinkId: String): Future[Box[Boolean]]
}
class RemotedataCustomerAccountLinkProviderCaseClass {
case class createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String)
case class getOrCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String)
case class getCustomerAccountLinkByCustomerId(customerId: String)
case class getCustomerAccountLinksByCustomerId(customerId: String)
case class getCustomerAccountLinksByAccountId(accountId: String)
case class getCustomerAccountLinkById(customerAccountLinkId: String)
case class updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String)
case class getCustomerAccountLink(customerId: String, accountId: String)
case class getCustomerAccountLinks()
case class bulkDeleteCustomerAccountLinks()
case class deleteCustomerAccountLinkById(customerAccountLinkId: String)
}
object RemotedataCustomerAccountLinkProviderCaseClass extends RemotedataCustomerAccountLinkProviderCaseClass
trait CustomerAccountLinkTrait {
def customerAccountLinkId: String
def customerId: String
def accountId: String
def relationshipType: String
}

View File

@ -0,0 +1,112 @@
package code.customeraccountlinks
import code.api.util.ErrorMessages
import code.util.{MappedUUID, UUIDString}
import net.liftweb.common.{Box, Empty, Failure, Full}
import net.liftweb.mapper._
import scala.concurrent.Future
import com.openbankproject.commons.ExecutionContext.Implicits.global
import net.liftweb.util.Helpers.tryo
object MappedCustomerAccountLinkProvider extends CustomerAccountLinkProvider {
def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait] = {
tryo {
CustomerAccountLink.create
.CustomerId(customerId)
.AccountId(accountId)
.RelationshipType(relationshipType)
.saveMe()
}
}
def getOrCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait] = {
getCustomerAccountLink(accountId, customerId) match {
case Empty =>
val createCustomerAccountLink = CustomerAccountLink.create
.CustomerId(customerId)
.AccountId(accountId)
.RelationshipType(relationshipType)
.saveMe()
Some(createCustomerAccountLink)
case everythingElse => everythingElse
}
}
def getCustomerAccountLinkByCustomerId(customerId: String): Box[CustomerAccountLinkTrait] = {
CustomerAccountLink.find(
By(CustomerAccountLink.CustomerId, customerId))
}
def getCustomerAccountLinksByCustomerId(customerId: String): Box[List[CustomerAccountLinkTrait]] = {
tryo {
CustomerAccountLink.findAll(
By(CustomerAccountLink.CustomerId, customerId))
}
}
def getCustomerAccountLinksByAccountId(accountId: String): Box[List[CustomerAccountLinkTrait]] = {
tryo {
CustomerAccountLink.findAll(
By(CustomerAccountLink.AccountId, accountId)).sortWith(_.id.get < _.id.get)
}
}
def getCustomerAccountLink(customerId: String, accountId : String): Box[CustomerAccountLinkTrait] = {
CustomerAccountLink.find(
By(CustomerAccountLink.CustomerId, customerId),
By(CustomerAccountLink.AccountId, accountId)
)
}
def getCustomerAccountLinkById(customerAccountLinkId: String): Box[CustomerAccountLinkTrait] = {
CustomerAccountLink.find(
By(CustomerAccountLink.CustomerAccountLinkId, customerAccountLinkId)
)
}
def updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String): Box[CustomerAccountLinkTrait] = {
CustomerAccountLink.find(By(CustomerAccountLink.CustomerAccountLinkId, customerAccountLinkId)) match {
case Full(t) => Full(t.RelationshipType(relationshipType).saveMe())
case Empty => Empty ?~! ErrorMessages.CustomerAccountLinkNotFound
case Failure(msg, exception, chain) => Failure(msg, exception, chain)
}
}
def getCustomerAccountLinks: Box[List[CustomerAccountLinkTrait]] = {
tryo {CustomerAccountLink.findAll()}
}
def bulkDeleteCustomerAccountLinks(): Boolean = {
CustomerAccountLink.bulkDelete_!!()
}
def deleteCustomerAccountLinkById(customerAccountLinkId: String): Future[Box[Boolean]] = {
Future {
CustomerAccountLink.find(By(CustomerAccountLink.CustomerAccountLinkId, customerAccountLinkId)) match {
case Full(t) => Full(t.delete_!)
case Empty => Empty ?~! ErrorMessages.CustomerAccountLinkNotFound
case Failure(msg, exception, chain) => Failure(msg, exception, chain)
}
}
}
}
class CustomerAccountLink extends CustomerAccountLinkTrait with LongKeyedMapper[CustomerAccountLink] with IdPK with CreatedUpdated {
def getSingleton = CustomerAccountLink
object CustomerAccountLinkId extends MappedUUID(this)
object CustomerId extends UUIDString(this)
object AccountId extends UUIDString(this)
object RelationshipType extends MappedString(this, 255)
override def customerAccountLinkId: String = CustomerAccountLinkId.get
override def customerId: String = CustomerId.get // id.toString
override def accountId: String = AccountId.get
override def relationshipType: String = RelationshipType.get
}
object CustomerAccountLink extends CustomerAccountLink with LongKeyedMetaMapper[CustomerAccountLink] {
override def dbIndexes = UniqueIndex(CustomerAccountLinkId) :: UniqueIndex(AccountId, CustomerId) :: super.dbIndexes
}

View File

@ -0,0 +1,56 @@
package code.remotedata
import akka.pattern.ask
import code.actorsystem.ObpActorInit
import code.customeraccountlinks.{RemotedataCustomerAccountLinkProviderCaseClass, CustomerAccountLinkTrait, CustomerAccountLinkProvider}
import net.liftweb.common._
import scala.concurrent.Future
object RemotedataCustomerAccountLinks extends ObpActorInit with CustomerAccountLinkProvider {
val cc = RemotedataCustomerAccountLinkProviderCaseClass
def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) : Box[CustomerAccountLinkTrait] = getValueFromFuture(
(actor ? cc.createCustomerAccountLink(accountId, customerId, relationshipType)).mapTo[Box[CustomerAccountLinkTrait]]
)
def getOrCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) : Box[CustomerAccountLinkTrait] = getValueFromFuture(
(actor ? cc.getOrCreateCustomerAccountLink(accountId, customerId, relationshipType)).mapTo[Box[CustomerAccountLinkTrait]]
)
def getCustomerAccountLinkByCustomerId(customerId: String): Box[CustomerAccountLinkTrait] = getValueFromFuture(
(actor ? cc.getCustomerAccountLinkByCustomerId(customerId)).mapTo[Box[CustomerAccountLinkTrait]]
)
def getCustomerAccountLinksByCustomerId(customerId: String): Box[List[CustomerAccountLinkTrait]] = getValueFromFuture(
(actor ? cc.getCustomerAccountLinksByCustomerId(customerId)).mapTo[Box[List[CustomerAccountLinkTrait]]]
)
def getCustomerAccountLinksByAccountId(accountId: String): Box[List[CustomerAccountLinkTrait]] = getValueFromFuture(
(actor ? cc.getCustomerAccountLinksByAccountId(accountId)).mapTo[Box[List[CustomerAccountLinkTrait]]]
)
def getCustomerAccountLinkById(customerAccountLinkId: String): Box[CustomerAccountLinkTrait] = getValueFromFuture(
(actor ? cc.getCustomerAccountLinkById(customerAccountLinkId)).mapTo[Box[CustomerAccountLinkTrait]]
)
def updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String): Box[CustomerAccountLinkTrait] = getValueFromFuture(
(actor ? cc.updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String)).mapTo[Box[CustomerAccountLinkTrait]]
)
def getCustomerAccountLink(customerId: String, accountId: String): Box[CustomerAccountLinkTrait] = getValueFromFuture(
(actor ? cc.getCustomerAccountLink(accountId, customerId)).mapTo[Box[CustomerAccountLinkTrait]]
)
def getCustomerAccountLinks: Box[List[CustomerAccountLinkTrait]] = getValueFromFuture(
(actor ? cc.getCustomerAccountLinks()).mapTo[Box[List[CustomerAccountLinkTrait]]]
)
def bulkDeleteCustomerAccountLinks(): Boolean = getValueFromFuture(
(actor ? cc.bulkDeleteCustomerAccountLinks()).mapTo[Boolean]
)
def deleteCustomerAccountLinkById(customerAccountLinkId: String): Future[Box[Boolean]] =
(actor ? cc.deleteCustomerAccountLinkById(customerAccountLinkId)).mapTo[Box[Boolean]]
}

View File

@ -0,0 +1,66 @@
package code.remotedata
import akka.actor.Actor
import akka.pattern.pipe
import code.actorsystem.ObpActorHelper
import code.customeraccountlinks.{MappedCustomerAccountLinkProvider, RemotedataCustomerAccountLinkProviderCaseClass}
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.ExecutionContext.Implicits.global
class RemotedataCustomerAccountLinksActor extends Actor with ObpActorHelper with MdcLoggable {
val mapper = MappedCustomerAccountLinkProvider
val cc = RemotedataCustomerAccountLinkProviderCaseClass
def receive: PartialFunction[Any, Unit] = {
case cc.createCustomerAccountLink(customerId: String, accountId: String, relationshipType) =>
logger.debug(s"createCustomerAccountLink($accountId, $relationshipType)")
sender ! (mapper.createCustomerAccountLink(accountId, customerId, relationshipType))
case cc.getOrCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType) =>
logger.debug(s"getOrCreateCustomerAccountLink($accountId, $relationshipType)")
sender ! (mapper.getOrCreateCustomerAccountLink(accountId, customerId, relationshipType))
case cc.getCustomerAccountLinkByCustomerId(customerId: String) =>
logger.debug(s"getCustomerAccountLinkByCustomerId($customerId)")
sender ! (mapper.getCustomerAccountLinkByCustomerId(customerId))
case cc.getCustomerAccountLinksByCustomerId(customerId: String) =>
logger.debug(s"getCustomerAccountLinksByCustomerId($customerId)")
sender ! (mapper.getCustomerAccountLinksByCustomerId(customerId))
case cc.getCustomerAccountLinksByAccountId(accountId: String) =>
logger.debug(s"getCustomerAccountLinksByAccountId($accountId)")
sender ! (mapper.getCustomerAccountLinksByAccountId(accountId))
case cc.getCustomerAccountLinkById(customerAccountLinkId: String)=>
logger.debug(s"getCustomerAccountLinkById($customerAccountLinkId)")
sender ! (mapper.getCustomerAccountLinkById(customerAccountLinkId))
case cc.updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String)=>
logger.debug(s"updateCustomerAccountLinkById($customerAccountLinkId, $relationshipType)")
sender ! (mapper.updateCustomerAccountLinkById(customerAccountLinkId, relationshipType))
case cc.getCustomerAccountLink(customerId: String, accountId: String) =>
logger.debug(s"getCustomerAccountLink($accountId, $customerId)")
sender ! (mapper.getCustomerAccountLink(accountId, customerId))
case cc.getCustomerAccountLinks() =>
logger.debug(s"getCustomerAccountLinks()")
sender ! (mapper.getCustomerAccountLinks)
case cc.bulkDeleteCustomerAccountLinks() =>
logger.debug(s"bulkDeleteCustomerAccountLinks()")
sender ! (mapper.bulkDeleteCustomerAccountLinks())
case cc.deleteCustomerAccountLinkById(customerAccountLinkId) =>
logger.debug(s"deleteCustomerAccountLink($customerAccountLinkId)")
mapper.deleteCustomerAccountLinkById(customerAccountLinkId) pipeTo sender
case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message)
}
}

View File

@ -78,6 +78,26 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
feature(s"test ${ApiEndpoint1.name} ") {
scenario(s"We will test ${ApiEndpoint1.name} Api -v5.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / "v5.0.0" / "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]
responseGetObp.code should equal(200)
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv5.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / "OBPv5.0.0" / "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]
responseGetObp.code should equal(200)
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
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)
@ -336,6 +356,30 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
}
feature(s"test ${ApiEndpoint2.name} ") {
scenario(s"We will test ${ApiEndpoint2.name} Api - v5.0.0/v5.0.0 ", ApiEndpoint2, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / "v5.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 - v5.0.0/v4.0.0", ApiEndpoint2, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_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 - v4.0.0", ApiEndpoint2, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v4.0.0" / "swagger").GET
val responseGetObp = makeGetRequest(requestGetObp)
@ -445,6 +489,16 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
}
feature(s"test ${ApiEndpoint3.name} ") {
scenario(s"We will test ${ApiEndpoint3.name} Api -v5.0.0/v4.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v5.0.0" / "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]
responseGetObp.code should equal(200)
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint3.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v4.0.0" / "obp").GET
val responseGetObp = makeGetRequest(requestGetObp)

View File

@ -11,5 +11,6 @@ trait ResourceDocsV140ServerSetup extends ServerSetupWithTestData {
def ResourceDocsV3_0Request = baseRequest / "obp" / "v3.0.0"
def ResourceDocsV3_1Request = baseRequest / "obp" / "v3.1.0"
def ResourceDocsV4_0Request = baseRequest / "obp" / "v4.0.0"
def ResourceDocsV5_0Request = baseRequest / "obp" / "v5.0.0"
}

View File

@ -0,0 +1,236 @@
package code.api.v5_0_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0
import code.setup.DefaultUsers
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.util.ApiVersion
import org.scalatest.Tag
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole
import code.api.util.ApiRole.{canCreateCustomerAccountLink, canDeleteCustomerAccountLink, canGetCustomerAccountLink, canGetCustomerAccountLinks, canUpdateCustomerAccountLink}
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
import code.entitlement.Entitlement
import com.openbankproject.commons.model.ErrorMessage
import net.liftweb.json.Serialization.write
class CustomerAccountLinkTest extends V500ServerSetup with DefaultUsers {
object VersionOfApi extends Tag(ApiVersion.v5_0_0.toString)
object ApiEndpoint1 extends Tag(nameOf(Implementations5_0_0.createCustomerAccountLink))
object ApiEndpoint2 extends Tag(nameOf(Implementations5_0_0.getCustomerAccountLinkById))
object ApiEndpoint3 extends Tag(nameOf(Implementations5_0_0.updateCustomerAccountLinkById))
object ApiEndpoint4 extends Tag(nameOf(Implementations5_0_0.getCustomerAccountLinksByCustomerId))
object ApiEndpoint5 extends Tag(nameOf(Implementations5_0_0.getCustomerAccountLinksByAccountId))
object ApiEndpoint6 extends Tag(nameOf(Implementations5_0_0.deleteCustomerAccountLinkById))
feature(s"customer account link $VersionOfApi - Error cases ") {
lazy val testBankId = randomBankId
lazy val testAccountId = testAccountId1
lazy val createCustomerAccountLinkJson = SwaggerDefinitionsJSON.createCustomerAccountLinkJson
lazy val updateCustomerAccountLinkJson = SwaggerDefinitionsJSON.updateCustomerAccountLinkJson
lazy val customerAccountLinkId1 = "wrongId"
lazy val customerId1 = "wrongId"
scenario("We will call the endpoints without user credentials", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, ApiEndpoint6, VersionOfApi) {
val requestApiEndpoint1 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links" ).POST
val responseApiEndpoint1 = makePostRequest(requestApiEndpoint1, write(createCustomerAccountLinkJson))
Then("We should get a 401")
responseApiEndpoint1.code should equal(401)
And("error should be " + UserNotLoggedIn)
responseApiEndpoint1.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
Then(s"We make a request $VersionOfApi $ApiEndpoint2")
val requestApiEndpoint2 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1 ).GET
val responseApiEndpoint2 = makeGetRequest(requestApiEndpoint2)
Then("We should get a 401")
responseApiEndpoint2.code should equal(401)
And("error should be " + UserNotLoggedIn)
responseApiEndpoint2.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
Then(s"We make a request $VersionOfApi $ApiEndpoint3")
val requestApiEndpoint3 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1 ).PUT
val responseApiEndpoint3 = makePutRequest(requestApiEndpoint3, write(updateCustomerAccountLinkJson))
Then("We should get a 401")
responseApiEndpoint2.code should equal(401)
And("error should be " + UserNotLoggedIn)
responseApiEndpoint2.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
Then(s"We make a request $VersionOfApi $ApiEndpoint4")
val requestApiEndpoint4 = (v5_0_0_Request / "banks" / testBankId /"customers"/customerId1 / "customer-account-links" )
val responseApiEndpoint4 = makeGetRequest(requestApiEndpoint4)
Then("We should get a 401")
responseApiEndpoint4.code should equal(401)
And("error should be " + UserNotLoggedIn)
responseApiEndpoint4.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
Then(s"We make a request $VersionOfApi $ApiEndpoint5")
val requestApiEndpoint5 = (v5_0_0_Request / "banks" / testBankId /"accounts"/testAccountId.value / "customer-account-links")
val responseApiEndpoint5 = makeGetRequest(requestApiEndpoint5)
Then("We should get a 401")
responseApiEndpoint5.code should equal(401)
And("error should be " + UserNotLoggedIn)
responseApiEndpoint5.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
Then(s"We make a request $VersionOfApi $ApiEndpoint6")
val requestApiEndpoint6 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1)
val responseApiEndpoint6 = makeDeleteRequest(requestApiEndpoint6)
Then("We should get a 401")
responseApiEndpoint2.code should equal(401)
And("error should be " + UserNotLoggedIn)
responseApiEndpoint2.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
}
scenario("We will call the endpoint without roles", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, ApiEndpoint6, VersionOfApi) {
val requestApiEndpoint1 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links" ).POST <@(user1)
val responseApiEndpoint1 = makePostRequest(requestApiEndpoint1, write(createCustomerAccountLinkJson))
Then("We should get a 403")
responseApiEndpoint1.code should equal(403)
And("error should be " + UserHasMissingRoles)
responseApiEndpoint1.body.extract[ErrorMessage].message contains (UserHasMissingRoles) should be (true)
responseApiEndpoint1.body.extract[ErrorMessage].message contains (canCreateCustomerAccountLink.toString()) should be (true)
Then(s"We make a request $VersionOfApi $ApiEndpoint2")
val requestApiEndpoint2 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1 ).GET <@(user1)
val responseApiEndpoint2 = makeGetRequest(requestApiEndpoint2)
Then("We should get a 403")
responseApiEndpoint2.code should equal(403)
And("error should be " + UserHasMissingRoles)
responseApiEndpoint2.body.extract[ErrorMessage].message contains (UserHasMissingRoles) should be (true)
responseApiEndpoint2.body.extract[ErrorMessage].message contains (canGetCustomerAccountLink.toString()) should be (true)
Then(s"We make a request $VersionOfApi $ApiEndpoint3")
val requestApiEndpoint3 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1 ).PUT<@(user1)
val responseApiEndpoint3 = makePutRequest(requestApiEndpoint3, write(updateCustomerAccountLinkJson))
Then("We should get a 403")
responseApiEndpoint3.code should equal(403)
And("error should be " + UserHasMissingRoles)
responseApiEndpoint3.body.extract[ErrorMessage].message contains (UserHasMissingRoles) should be (true)
responseApiEndpoint3.body.extract[ErrorMessage].message contains (canUpdateCustomerAccountLink.toString()) should be (true)
Then(s"We make a request $VersionOfApi $ApiEndpoint4")
val requestApiEndpoint4 = (v5_0_0_Request / "banks" / testBankId /"customers"/customerId1 / "customer-account-links" ).GET <@(user1)
val responseApiEndpoint4 = makeGetRequest(requestApiEndpoint4)
Then("We should get a 403")
responseApiEndpoint4.code should equal(403)
And("error should be " + UserHasMissingRoles)
responseApiEndpoint4.body.extract[ErrorMessage].message contains (UserHasMissingRoles) should be (true)
responseApiEndpoint4.body.extract[ErrorMessage].message contains (canGetCustomerAccountLinks.toString()) should be (true)
Then(s"We make a request $VersionOfApi $ApiEndpoint5")
val requestApiEndpoint5 = (v5_0_0_Request / "banks" / testBankId /"accounts"/testAccountId.value / "customer-account-links").GET<@(user1)
val responseApiEndpoint5 = makeGetRequest(requestApiEndpoint5)
Then("We should get a 403")
responseApiEndpoint5.code should equal(403)
And("error should be " + UserHasMissingRoles)
responseApiEndpoint5.body.extract[ErrorMessage].message contains (UserHasMissingRoles) should be (true)
responseApiEndpoint5.body.extract[ErrorMessage].message contains (canGetCustomerAccountLink.toString()) should be (true)
Then(s"We make a request $VersionOfApi $ApiEndpoint6")
val requestApiEndpoint6 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1).DELETE <@(user1)
val responseApiEndpoint6 = makeDeleteRequest(requestApiEndpoint6)
Then("We should get a 403")
responseApiEndpoint6.code should equal(403)
And("error should be " + UserHasMissingRoles)
responseApiEndpoint6.body.extract[ErrorMessage].message contains (UserHasMissingRoles) should be (true)
responseApiEndpoint6.body.extract[ErrorMessage].message contains (canDeleteCustomerAccountLink.toString()) should be (true)
}
}
feature(s"Create Account $VersionOfApi - Success access") {
scenario("We will call the endpoint with user credentials", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5, ApiEndpoint6, VersionOfApi) {
When(s"We make a request $VersionOfApi $ApiEndpoint1")
lazy val testBankId = randomBankId
lazy val testAccountId = testAccountId1
val customerId = createAndGetCustomerIdViaEndpoint(testBankId, user1)
lazy val createCustomerAccountLinkJson = SwaggerDefinitionsJSON.createCustomerAccountLinkJson.copy(customer_id = customerId, account_id= testAccountId.value)
lazy val updateCustomerAccountLinkJson = SwaggerDefinitionsJSON.updateCustomerAccountLinkJson.copy(relationship_type ="test")
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, ApiRole.canCreateCustomerAccountLink.toString())
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, ApiRole.canUpdateCustomerAccountLink.toString())
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, ApiRole.canGetCustomerAccountLink.toString())
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, ApiRole.canGetCustomerAccountLinks.toString())
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, ApiRole.canDeleteCustomerAccountLink.toString())
val requestApiEndpoint1 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links" ).POST <@(user1)
val responseApiEndpoint1 = makePostRequest(requestApiEndpoint1, write(createCustomerAccountLinkJson))
Then("We should get a 201")
responseApiEndpoint1.code should equal(201)
val customerAccountLinkJson1 = responseApiEndpoint1.body.extract[CustomerAccountLinkJson]
val customerAccountLinkId1 = customerAccountLinkJson1.customer_account_link_id
customerAccountLinkId1.nonEmpty should be (true)
Then(s"We make a request $VersionOfApi $ApiEndpoint2")
val requestApiEndpoint2 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1 ).GET <@(user1)
val responseApiEndpoint2 = makeGetRequest(requestApiEndpoint2)
Then("We should get a 200")
responseApiEndpoint2.code should equal(200)
val customerAccountLinkJson2 = responseApiEndpoint2.body.extract[CustomerAccountLinkJson]
val customerAccountLinkId2 = customerAccountLinkJson2.customer_account_link_id
customerAccountLinkId2 should be (customerAccountLinkId1)
Then(s"We make a request $VersionOfApi $ApiEndpoint3")
val requestApiEndpoint3 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1 ).PUT <@(user1)
val responseApiEndpoint3 = makePutRequest(requestApiEndpoint3, write(updateCustomerAccountLinkJson))
Then("We should get a 200")
responseApiEndpoint3.code should equal(200)
val customerAccountLinkJson3 = responseApiEndpoint3.body.extract[CustomerAccountLinkJson]
val customerAccountLinkId3 = customerAccountLinkJson3.customer_account_link_id
customerAccountLinkId3 should be (customerAccountLinkId1)
Then(s"We make a request $VersionOfApi $ApiEndpoint4")
val requestApiEndpoint4 = (v5_0_0_Request / "banks" / testBankId /"customers"/customerId / "customer-account-links" ).GET <@(user1)
val responseApiEndpoint4 = makeGetRequest(requestApiEndpoint4)
Then("We should get a 200")
responseApiEndpoint4.code should equal(200)
val customerAccountLinkJson4 = responseApiEndpoint4.body.extract[CustomerAccountLinksJson]
val customerAccountLinkId4 = customerAccountLinkJson4.links.head.customer_account_link_id
customerAccountLinkId4 should be (customerAccountLinkId1)
Then(s"We make a request $VersionOfApi $ApiEndpoint5")
val requestApiEndpoint5 = (v5_0_0_Request / "banks" / testBankId /"accounts"/testAccountId.value / "customer-account-links").GET <@(user1)
val responseApiEndpoint5 = makeGetRequest(requestApiEndpoint5)
Then("We should get a 200")
responseApiEndpoint5.code should equal(200)
val customerAccountLinkJson5 = responseApiEndpoint5.body.extract[CustomerAccountLinksJson]
val customerAccountLinkId5 = customerAccountLinkJson5.links.head.customer_account_link_id
customerAccountLinkId5 should be (customerAccountLinkId1)
Then(s"We make a request $VersionOfApi $ApiEndpoint6")
val requestApiEndpoint6 = (v5_0_0_Request / "banks" / testBankId / "customer-account-links"/customerAccountLinkId1).DELETE <@(user1)
val responseApiEndpoint6 = makeDeleteRequest(requestApiEndpoint6)
Then("We should get a 204")
responseApiEndpoint6.code should equal(204)
Then(s"We call $ApiEndpoint5 should return empty list")
val responseApiEndpoint5AfterDelete = makeGetRequest(requestApiEndpoint5)
Then("We should get a 200")
responseApiEndpoint5AfterDelete.code should equal(200)
val customerAccountLinkJson5AfterDelete = responseApiEndpoint5AfterDelete.body.extract[CustomerAccountLinksJson]
customerAccountLinkJson5AfterDelete.links.length should be (0)
}
}
}

View File

@ -1,5 +1,8 @@
package code.api.v5_0_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.util.APIUtil.OAuth.{Consumer, Token}
import code.api.util.ApiRole.CanCreateCustomer
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole.CanCreateCustomer
import code.api.v3_1_0.CustomerJsonV310
@ -8,6 +11,7 @@ import code.entitlement.Entitlement
import code.setup.{APIResponse, DefaultUsers, ServerSetupWithTestData}
import com.openbankproject.commons.util.ApiShortVersions
import dispatch.Req
import code.api.util.APIUtil.OAuth._
import net.liftweb.json.Serialization.write
import scala.util.Random.nextInt
@ -28,6 +32,20 @@ trait V500ServerSetup extends ServerSetupWithTestData with DefaultUsers {
val bank = banksJson.banks(randomPosition)
bank.id
}
// This will call create customer ,then return the customerId
def createAndGetCustomerIdViaEndpoint(bankId:String, consumerAndToken: Option[(Consumer, Token)]) = {
val postCustomerJson = SwaggerDefinitionsJSON.postCustomerJsonV310
def createCustomer(consumerAndToken: Option[(Consumer, Token)]) ={
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanCreateCustomer.toString)
val request310 = (v5_0_0_Request / "banks" / bankId / "customers").POST <@(user1)
val response310 = makePostRequest(request310, write(postCustomerJson))
response310.code should equal(201)
response310.body.extract[CustomerJsonV310]
}
createCustomer(consumerAndToken).customer_id
}
def createCustomerEndpointV500(bankId: String, legalName: String, mobilePhoneNumber: String): CustomerJsonV310 = {
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanCreateCustomer.toString)