mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 19:56:59 +00:00
OBV 400 added the create Product, get Product and get Products
This commit is contained in:
parent
6e92c92619
commit
7a537a5b6e
@ -4334,6 +4334,33 @@ object SwaggerDefinitionsJSON {
|
||||
)
|
||||
|
||||
val atmsJsonV400 = AtmsJsonV400(List(atmJsonV400))
|
||||
|
||||
val productJsonV400 = ProductJsonV400(
|
||||
bank_id = bankIdExample.value,
|
||||
code = "product_code",
|
||||
parent_product_code = "parent",
|
||||
name = "product name",
|
||||
more_info_url = moreInfoUrlExample.value,
|
||||
terms_and_conditions_url = termsAndConditionsUrlExample.value,
|
||||
details = "Details",
|
||||
description = "Description",
|
||||
meta = metaJson,
|
||||
Some(List(productAttributeResponseJson))
|
||||
)
|
||||
|
||||
val productsJsonV400 = ProductsJsonV400(products = List(productJsonV400))
|
||||
|
||||
val putProductJsonV400 = PutProductJsonV400(
|
||||
bank_id = bankIdExample.value,
|
||||
parent_product_code = "parent",
|
||||
name = "product name",
|
||||
more_info_url = moreInfoUrlExample.value,
|
||||
terms_and_conditions_url = termsAndConditionsUrlExample.value,
|
||||
details = "Details",
|
||||
description = "Description",
|
||||
meta = metaJson
|
||||
)
|
||||
|
||||
|
||||
//The common error or success format.
|
||||
//Just some helper format to use in Json
|
||||
|
||||
@ -33,7 +33,6 @@ import java.nio.charset.Charset
|
||||
import java.text.{ParsePosition, SimpleDateFormat}
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.{Calendar, Date, UUID}
|
||||
|
||||
import code.UserRefreshes.UserRefreshes
|
||||
import code.accountholders.AccountHolders
|
||||
import code.api.Constant._
|
||||
@ -42,6 +41,7 @@ import code.api.builder.OBP_APIBuilder
|
||||
import code.api.oauth1a.Arithmetics
|
||||
import code.api.oauth1a.OauthParams._
|
||||
import code.api.util.APIUtil.ResourceDoc.{findPathVariableNames, isPathVariable}
|
||||
import code.api.util.ApiRole.{canCreateProduct, canCreateProductAtAnyBank}
|
||||
import code.api.util.ApiTag.{ResourceDocTag, apiTagBank, apiTagNewStyle}
|
||||
import code.api.util.Glossary.GlossaryItem
|
||||
import code.api.util.JwsUtil.getJwsHeaderValue
|
||||
@ -4050,4 +4050,21 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
|
||||
APIUtil.getPropsValue("email_domain_to_entitlement_mappings").map(extractor).getOrElse(Nil)
|
||||
}
|
||||
|
||||
val getProductsIsPublic = APIUtil.getPropsAsBoolValue("apiOptions.getProductsIsPublic", true)
|
||||
|
||||
val createProductEntitlements = canCreateProduct :: canCreateProductAtAnyBank :: Nil
|
||||
|
||||
val createProductEntitlementsRequiredText = UserHasMissingRoles + createProductEntitlements.mkString(" or ")
|
||||
|
||||
val productHiearchyAndCollectionNote =
|
||||
"""
|
||||
|
|
||||
|Product hiearchy vs Product Collections:
|
||||
|
|
||||
|* You can define a hierarchy of products - so that a child Product inherits attributes of its parent Product - using the parent_product_code in Product.
|
||||
|
|
||||
|* You can define a collection (also known as baskets or buckets) of products using Product Collections.
|
||||
|
|
||||
""".stripMargin
|
||||
}
|
||||
|
||||
@ -1221,8 +1221,8 @@ object ExampleValue {
|
||||
lazy val roleNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
|
||||
glossaryItems += makeGlossaryItem("role_name", roleNameExample)
|
||||
|
||||
lazy val refundExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
|
||||
glossaryItems += makeGlossaryItem("refund", refundExample)
|
||||
lazy val termsAndConditionsUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
|
||||
glossaryItems += makeGlossaryItem("terms_and_conditions_url_example", termsAndConditionsUrlExample)
|
||||
|
||||
lazy val canAddUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
|
||||
glossaryItems += makeGlossaryItem("can_add_url", canAddUrlExample)
|
||||
|
||||
@ -607,6 +607,7 @@ trait APIMethods220 {
|
||||
family = product.family,
|
||||
superFamily = product.super_family,
|
||||
moreInfoUrl = product.more_info_url,
|
||||
termsAndConditionsUrl = null,
|
||||
details = product.details,
|
||||
description = product.description,
|
||||
metaLicenceId = product.meta.license.id,
|
||||
|
||||
@ -2430,22 +2430,6 @@ trait APIMethods310 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val productHiearchyAndCollectionNote =
|
||||
"""
|
||||
|
|
||||
|Product hiearchy vs Product Collections:
|
||||
|
|
||||
|* You can define a hierarchy of products - so that a child Product inherits attributes of its parent Product - using the parent_product_code in Product.
|
||||
|
|
||||
|* You can define a collection (also known as baskets or buckets) of products using Product Collections.
|
||||
|
|
||||
""".stripMargin
|
||||
|
||||
|
||||
val createProductEntitlements = canCreateProduct :: canCreateProductAtAnyBank :: Nil
|
||||
val createProductEntitlementsRequiredText = UserHasMissingRoles + createProductEntitlements.mkString(" or ")
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
createProduct,
|
||||
implementedInApiVersion,
|
||||
@ -2511,6 +2495,7 @@ trait APIMethods310 {
|
||||
family = product.family,
|
||||
superFamily = product.super_family,
|
||||
moreInfoUrl = product.more_info_url,
|
||||
termsAndConditionsUrl = null,
|
||||
details = product.details,
|
||||
description = product.description,
|
||||
metaLicenceId = product.meta.license.id,
|
||||
@ -2526,8 +2511,6 @@ trait APIMethods310 {
|
||||
}
|
||||
|
||||
|
||||
val getProductsIsPublic = APIUtil.getPropsAsBoolValue("apiOptions.getProductsIsPublic", true)
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
getProduct,
|
||||
implementedInApiVersion,
|
||||
|
||||
@ -59,6 +59,7 @@ import code.views.Views
|
||||
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
import com.openbankproject.commons.dto.GetProductsParam
|
||||
import com.openbankproject.commons.model.enums.DynamicEntityOperation._
|
||||
import com.openbankproject.commons.model.enums.{TransactionRequestStatus, _}
|
||||
import com.openbankproject.commons.model.{ListResult, _}
|
||||
@ -9619,7 +9620,186 @@ trait APIMethods400 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getProducts,
|
||||
implementedInApiVersion,
|
||||
"getProducts",
|
||||
"GET",
|
||||
"/banks/BANK_ID/products",
|
||||
"Get Products",
|
||||
s"""Returns information about the financial products offered by a bank specified by BANK_ID including:
|
||||
|
|
||||
|* Name
|
||||
|* Code
|
||||
|* Parent Product Code
|
||||
|* More info URL
|
||||
|* Terms And Conditions URL
|
||||
|* Description
|
||||
|* Terms and Conditions
|
||||
|* License the data under this endpoint is released under
|
||||
|
|
||||
|Can filter with attributes name and values.
|
||||
|URL params example: /banks/some-bank-id/products?manager=John&count=8
|
||||
|
|
||||
|${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin,
|
||||
emptyObjectJson,
|
||||
productsJsonV310,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
BankNotFound,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagProduct, apiTagNewStyle)
|
||||
)
|
||||
lazy val getProducts : OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "products" :: Nil JsonGet req => {
|
||||
cc => {
|
||||
for {
|
||||
(_, callContext) <- getProductsIsPublic match {
|
||||
case false => authenticatedAccess(cc)
|
||||
case true => anonymousAccess(cc)
|
||||
}
|
||||
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
|
||||
params = req.params.toList.map(kv => GetProductsParam(kv._1, kv._2))
|
||||
products <- Future(Connector.connector.vend.getProducts(bankId, params)) map {
|
||||
unboxFullOrFail(_, callContext, ProductNotFoundByProductCode)
|
||||
}
|
||||
} yield {
|
||||
(JSONFactory400.createProductsJson(products), HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
createProduct,
|
||||
implementedInApiVersion,
|
||||
nameOf(createProduct),
|
||||
"PUT",
|
||||
"/banks/BANK_ID/products/PRODUCT_CODE",
|
||||
"Create Product",
|
||||
s"""Create or Update Product for the Bank.
|
||||
|
|
||||
|
|
||||
|Typical Super Family values / Asset classes are:
|
||||
|
|
||||
|Debt
|
||||
|Equity
|
||||
|FX
|
||||
|Commodity
|
||||
|Derivative
|
||||
|
|
||||
|$productHiearchyAndCollectionNote
|
||||
|
|
||||
|
|
||||
|${authenticationRequiredMessage(true) }
|
||||
|
|
||||
|
|
||||
|""",
|
||||
putProductJsonV400,
|
||||
productJsonV400,
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
$BankNotFound,
|
||||
UserHasMissingRoles,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagProduct, apiTagNewStyle),
|
||||
Some(List(canCreateProduct, canCreateProductAtAnyBank))
|
||||
)
|
||||
lazy val createProduct: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonPut json -> _ => {
|
||||
cc =>
|
||||
for {
|
||||
(Full(u), callContext) <- SS.user
|
||||
_ <- NewStyle.function.hasAtLeastOneEntitlement(failMsg = createProductEntitlementsRequiredText)(bankId.value, u.userId, createProductEntitlements, callContext)
|
||||
failMsg = s"$InvalidJsonFormat The Json body should be the $PutProductJsonV400 "
|
||||
product <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
json.extract[PutProductJsonV400]
|
||||
}
|
||||
parentProductCode <- product.parent_product_code.trim.nonEmpty match {
|
||||
case false =>
|
||||
Future(Empty)
|
||||
case true =>
|
||||
Future(Connector.connector.vend.getProduct(bankId, ProductCode(product.parent_product_code))) map {
|
||||
getFullBoxOrFail(_, callContext, ParentProductNotFoundByProductCode + " {" + product.parent_product_code + "}", 400)
|
||||
}
|
||||
}
|
||||
success <- Future(Connector.connector.vend.createOrUpdateProduct(
|
||||
bankId = bankId.value,
|
||||
code = productCode.value,
|
||||
parentProductCode = parentProductCode.map(_.code.value).toOption,
|
||||
name = product.name,
|
||||
category = null,
|
||||
family = null,
|
||||
superFamily = null,
|
||||
moreInfoUrl = product.more_info_url,
|
||||
termsAndConditionsUrl = product.terms_and_conditions_url,
|
||||
details = product.details,
|
||||
description = product.description,
|
||||
metaLicenceId = product.meta.license.id,
|
||||
metaLicenceName = product.meta.license.name
|
||||
)) map {
|
||||
connectorEmptyResponse(_, callContext)
|
||||
}
|
||||
} yield {
|
||||
(JSONFactory400.createProductJson(success), HttpCode.`201`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getProduct,
|
||||
implementedInApiVersion,
|
||||
nameOf(getProduct),
|
||||
"GET",
|
||||
"/banks/BANK_ID/products/PRODUCT_CODE",
|
||||
"Get Bank Product",
|
||||
s"""Returns information about a financial Product offered by the bank specified by BANK_ID and PRODUCT_CODE including:
|
||||
|
|
||||
|* Name
|
||||
|* Code
|
||||
|* Parent Product Code
|
||||
|* Category
|
||||
|* Family
|
||||
|* Super Family
|
||||
|* More info URL
|
||||
|* Description
|
||||
|* Terms and Conditions
|
||||
|* License the data under this endpoint is released under
|
||||
|
|
||||
|${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin,
|
||||
emptyObjectJson,
|
||||
productJsonV400,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
$BankNotFound,
|
||||
ProductNotFoundByProductCode,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagProduct, apiTagNewStyle)
|
||||
)
|
||||
|
||||
lazy val getProduct: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonGet _ => {
|
||||
cc => {
|
||||
for {
|
||||
(_, callContext) <- getProductsIsPublic match {
|
||||
case false => authenticatedAccess(cc)
|
||||
case true => anonymousAccess(cc)
|
||||
}
|
||||
product <- Future(Connector.connector.vend.getProduct(bankId, productCode)) map {
|
||||
unboxFullOrFail(_, callContext, ProductNotFoundByProductCode)
|
||||
}
|
||||
(productAttributes, callContext) <- NewStyle.function.getProductAttributesByBankAndCode(bankId, productCode, callContext)
|
||||
} yield {
|
||||
(JSONFactory400.createProductJson(product, productAttributes), HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private def createDynamicEndpointMethod(bankId: Option[String], json: JValue, cc: CallContext) = {
|
||||
|
||||
@ -28,7 +28,6 @@ package code.api.v4_0_0
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
import code.api.attributedefinition.AttributeDefinition
|
||||
import code.api.util.APIUtil
|
||||
import code.api.util.APIUtil.{DateWithDay, DateWithSeconds, stringOptionOrNull, stringOrNull}
|
||||
@ -40,8 +39,8 @@ import code.api.v2_1_0.{IbanJson, JSONFactory210, PostCounterpartyBespokeJson, R
|
||||
import code.api.v2_2_0.CounterpartyMetadataJson
|
||||
import code.api.v3_0_0.JSONFactory300._
|
||||
import code.api.v3_0_0._
|
||||
import code.api.v3_1_0.JSONFactory310.createAccountAttributeJson
|
||||
import code.api.v3_1_0.{AccountAttributeResponseJson, RedisCallLimitJson}
|
||||
import code.api.v3_1_0.JSONFactory310.{createAccountAttributeJson, createProductAttributesJson}
|
||||
import code.api.v3_1_0.{AccountAttributeResponseJson, ProductAttributeResponseWithoutBankIdJson, RedisCallLimitJson}
|
||||
import code.apicollection.ApiCollectionTrait
|
||||
import code.apicollectionendpoint.ApiCollectionEndpointTrait
|
||||
import code.atms.Atms.Atm
|
||||
@ -567,6 +566,31 @@ case class MySpaces(
|
||||
bank_ids: List[String],
|
||||
)
|
||||
|
||||
case class ProductJsonV400(
|
||||
bank_id: String,
|
||||
code: String,
|
||||
parent_product_code: String,
|
||||
name: String,
|
||||
more_info_url: String,
|
||||
terms_and_conditions_url: String,
|
||||
details: String,
|
||||
description: String,
|
||||
meta: MetaJsonV140,
|
||||
product_attributes: Option[List[ProductAttributeResponseWithoutBankIdJson]]
|
||||
)
|
||||
|
||||
case class ProductsJsonV400(products: List[ProductJsonV400])
|
||||
|
||||
case class PutProductJsonV400(
|
||||
bank_id: String,
|
||||
parent_product_code: String,
|
||||
name: String,
|
||||
more_info_url: String,
|
||||
terms_and_conditions_url: String,
|
||||
details: String,
|
||||
description: String,
|
||||
meta: MetaJsonV140
|
||||
)
|
||||
case class CounterpartyJson400(
|
||||
name: String,
|
||||
description: String,
|
||||
@ -1516,6 +1540,38 @@ object JSONFactory400 {
|
||||
balanceInquiryFee = Some(atmJsonV400.balance_inquiry_fee)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def createProductJson(product: Product) : ProductJsonV400 = {
|
||||
ProductJsonV400(
|
||||
bank_id = product.bankId.toString,
|
||||
code = product.code.value,
|
||||
parent_product_code = product.parentProductCode.value,
|
||||
name = product.name,
|
||||
more_info_url = product.moreInfoUrl,
|
||||
terms_and_conditions_url = product.moreInfoUrl,
|
||||
details = product.details,
|
||||
description = product.description,
|
||||
meta = createMetaJson(product.meta),
|
||||
None
|
||||
)
|
||||
}
|
||||
def createProductsJson(productsList: List[Product]) : ProductsJsonV400 = {
|
||||
ProductsJsonV400(productsList.map(createProductJson))
|
||||
}
|
||||
|
||||
def createProductJson(product: Product, productAttributes: List[ProductAttribute]) : ProductJsonV400 = {
|
||||
ProductJsonV400(
|
||||
bank_id = product.bankId.toString,
|
||||
code = product.code.value,
|
||||
parent_product_code = product.parentProductCode.value,
|
||||
name = product.name,
|
||||
more_info_url = product.moreInfoUrl,
|
||||
terms_and_conditions_url = product.termsAndConditionsUrl,
|
||||
details = product.details,
|
||||
description = product.description,
|
||||
meta = createMetaJson(product.meta),
|
||||
product_attributes = Some(createProductAttributesJson(productAttributes))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1588,6 +1588,7 @@ trait Connector extends MdcLoggable {
|
||||
family : String,
|
||||
superFamily : String,
|
||||
moreInfoUrl : String,
|
||||
termsAndConditionsUrl : String,
|
||||
details : String,
|
||||
description : String,
|
||||
metaLicenceId : String,
|
||||
|
||||
@ -1140,11 +1140,12 @@ object KafkaMappedConnector_JVMcompatible extends Connector with KafkaHelper wit
|
||||
family : String,
|
||||
superFamily : String,
|
||||
moreInfoUrl : String,
|
||||
termsAndConditionsUrl: String,
|
||||
details : String,
|
||||
description : String,
|
||||
metaLicenceId : String,
|
||||
metaLicenceName : String): Box[Product] = {
|
||||
LocalMappedConnector.createOrUpdateProduct(bankId, code, parentProductCode, name, category, family, superFamily, moreInfoUrl, details, description, metaLicenceId, metaLicenceName)
|
||||
LocalMappedConnector.createOrUpdateProduct(bankId, code, parentProductCode, name, category, family, superFamily, moreInfoUrl, termsAndConditionsUrl, details, description, metaLicenceId, metaLicenceName)
|
||||
}
|
||||
|
||||
override def getProduct(bankId: BankId, productCode: ProductCode): Box[Product] = {
|
||||
|
||||
@ -2721,6 +2721,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
family: String,
|
||||
superFamily: String,
|
||||
moreInfoUrl: String,
|
||||
termsAndConditionsUrl: String,
|
||||
details: String,
|
||||
description: String,
|
||||
metaLicenceId: String,
|
||||
@ -2742,6 +2743,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
.mFamily(family)
|
||||
.mSuperFamily(superFamily)
|
||||
.mMoreInfoUrl(moreInfoUrl)
|
||||
.mTermsAndConditionsUrl(termsAndConditionsUrl)
|
||||
.mDetails(details)
|
||||
.mDescription(description)
|
||||
.mLicenseId(metaLicenceId)
|
||||
@ -2759,6 +2761,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
.mFamily(family)
|
||||
.mSuperFamily(superFamily)
|
||||
.mMoreInfoUrl(moreInfoUrl)
|
||||
.mTermsAndConditionsUrl(termsAndConditionsUrl)
|
||||
.mDetails(details)
|
||||
.mDescription(description)
|
||||
.mLicenseId(metaLicenceId)
|
||||
|
||||
@ -2713,6 +2713,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
@ -2750,6 +2751,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
@ -5523,7 +5525,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
|
||||
exampleInboundMessage = (
|
||||
InBoundGetProductCollectionItemsTree(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext,
|
||||
status=MessageDocsSwaggerDefinitions.inboundStatus,
|
||||
data=List( ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode=collectionCodeExample.value,
|
||||
data=List(ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode=collectionCodeExample.value,
|
||||
memberProductCode=memberProductCodeExample.value),
|
||||
product= ProductCommons(bankId=BankId(bankIdExample.value),
|
||||
code=ProductCode(productCodeExample.value),
|
||||
@ -5533,6 +5535,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
|
||||
@ -2852,6 +2852,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
@ -2889,6 +2890,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
@ -5720,6 +5722,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
|
||||
@ -2833,6 +2833,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable {
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
@ -2870,6 +2871,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable {
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
@ -5701,6 +5703,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable {
|
||||
family=familyExample.value,
|
||||
superFamily=superFamilyExample.value,
|
||||
moreInfoUrl=moreInfoUrlExample.value,
|
||||
termsAndConditionsUrl=termsAndConditionsUrlExample.value,
|
||||
details=detailsExample.value,
|
||||
description=descriptionExample.value,
|
||||
meta=Meta( License(id=idExample.value,
|
||||
|
||||
@ -39,6 +39,7 @@ class MappedProduct extends Product with LongKeyedMapper[MappedProduct] with IdP
|
||||
object mFamily extends MappedString(this, 50)
|
||||
object mSuperFamily extends MappedString(this, 50)
|
||||
object mMoreInfoUrl extends MappedString(this, 2000) // use URL field?
|
||||
object mTermsAndConditionsUrl extends MappedString(this, 2000) // use URL field?
|
||||
object mDetails extends MappedString(this, 2000)
|
||||
object mDescription extends MappedString(this, 2000)
|
||||
|
||||
@ -57,6 +58,7 @@ class MappedProduct extends Product with LongKeyedMapper[MappedProduct] with IdP
|
||||
override def family : String = mFamily.get
|
||||
override def superFamily : String = mSuperFamily.get
|
||||
override def moreInfoUrl: String = mMoreInfoUrl.get
|
||||
override def termsAndConditionsUrl: String = mTermsAndConditionsUrl.get
|
||||
override def details: String = mDetails.get
|
||||
override def description: String = mDescription.get
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ class ProductsTest extends ServerSetup with DefaultUsers with V140ServerSetup {
|
||||
family : String,
|
||||
superFamily : String,
|
||||
moreInfoUrl: String,
|
||||
termsAndConditionsUrl: String,
|
||||
details: String,
|
||||
description: String,
|
||||
meta: Meta) extends Product
|
||||
@ -40,11 +41,11 @@ class ProductsTest extends ServerSetup with DefaultUsers with V140ServerSetup {
|
||||
)
|
||||
|
||||
|
||||
val fakeProduct1 = ProductImpl(BankWithLicense, ProductCode("prod1"), ProductCode(""), "name 1", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo1.html", "", "", fakeMeta)
|
||||
val fakeProduct2 = ProductImpl(BankWithLicense, ProductCode("prod2"), ProductCode(""), "name 2", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo2.html", "", "", fakeMeta)
|
||||
val fakeProduct1 = ProductImpl(BankWithLicense, ProductCode("prod1"), ProductCode(""), "name 1", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo1.html", "http://www.example.com/termsAndConditionsUrl1.html","", "", fakeMeta)
|
||||
val fakeProduct2 = ProductImpl(BankWithLicense, ProductCode("prod2"), ProductCode(""), "name 2", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo2.html", "http://www.example.com/termsAndConditionsUrl2.html", "","", fakeMeta)
|
||||
|
||||
// Should not be returned (no license)
|
||||
val fakeProduct3 = ProductImpl(BankWithoutLicense, ProductCode("prod3"), ProductCode(""), "name 3", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo3.html", "", "", fakeMetaNoLicense)
|
||||
val fakeProduct3 = ProductImpl(BankWithoutLicense, ProductCode("prod3"), ProductCode(""), "name 3", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo3.html", "http://www.example.com/termsAndConditionsUrl3.html", "","", fakeMetaNoLicense)
|
||||
|
||||
|
||||
// This mock provider is returning same branches for the fake banks
|
||||
|
||||
156
obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala
Normal file
156
obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala
Normal file
@ -0,0 +1,156 @@
|
||||
/**
|
||||
Open Bank Project - API
|
||||
Copyright (C) 2011-2019, TESOBE GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Email: contact@tesobe.com
|
||||
TESOBE GmbH
|
||||
Osloerstrasse 16/17
|
||||
Berlin 13359, Germany
|
||||
|
||||
This product includes software developed at
|
||||
TESOBE (http://www.tesobe.com/)
|
||||
*/
|
||||
package code.api.v4_0_0
|
||||
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0
|
||||
import code.entitlement.Entitlement
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.openbankproject.commons.model.ErrorMessage
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import net.liftweb.json.Serialization.write
|
||||
import org.scalatest.Tag
|
||||
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
|
||||
class ProductTest extends V400ServerSetup {
|
||||
|
||||
override def beforeAll(): Unit = {
|
||||
super.beforeAll()
|
||||
}
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
super.afterAll()
|
||||
}
|
||||
|
||||
/**
|
||||
* Test tags
|
||||
* Example: To run tests with tag "getPermissions":
|
||||
* mvn test -D tagsToInclude
|
||||
*
|
||||
* This is made possible by the scalatest maven plugin
|
||||
*/
|
||||
object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString)
|
||||
object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createProduct))
|
||||
object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getProduct))
|
||||
object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getProducts))
|
||||
|
||||
lazy val testBankId = randomBankId
|
||||
lazy val parentPutProductJsonV400: PutProductJsonV400 = SwaggerDefinitionsJSON.putProductJsonV400.copy(parent_product_code ="")
|
||||
def createProduct(code: String, json: PutProductJsonV400) = {
|
||||
When("We try to create a product v4.0.0")
|
||||
val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / code).PUT <@ (user1)
|
||||
val response400 = makePutRequest(request400, write(json))
|
||||
Then("We should get a 201")
|
||||
response400.code should equal(201)
|
||||
val product = response400.body.extract[ProductJsonV400]
|
||||
product.code shouldBe code
|
||||
product.parent_product_code shouldBe json.parent_product_code
|
||||
product.bank_id shouldBe testBankId
|
||||
product.name shouldBe json.name
|
||||
product.more_info_url shouldBe json.more_info_url
|
||||
product.terms_and_conditions_url shouldBe json.terms_and_conditions_url
|
||||
product.details shouldBe json.details
|
||||
product.description shouldBe json.description
|
||||
product
|
||||
}
|
||||
|
||||
feature("Create Product v4.0.0") {
|
||||
scenario("We will call the Add endpoint without a user credentials", ApiEndpoint1, VersionOfApi) {
|
||||
When("We make a request v4.0.0")
|
||||
val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / "CODE").PUT
|
||||
val response400 = makePutRequest(request400, write(parentPutProductJsonV400))
|
||||
Then("We should get a 401")
|
||||
response400.code should equal(401)
|
||||
And("error should be " + UserNotLoggedIn)
|
||||
response400.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
|
||||
}
|
||||
scenario("We will call the Add endpoint without a proper role", ApiEndpoint1, VersionOfApi) {
|
||||
When("We make a request v4.0.0")
|
||||
val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / "CODE").PUT <@(user1)
|
||||
val response400 = makePutRequest(request400, write(parentPutProductJsonV400))
|
||||
Then("We should get a 403")
|
||||
response400.code should equal(403)
|
||||
val createProductEntitlements = canCreateProduct :: canCreateProductAtAnyBank :: Nil
|
||||
val createProductEntitlementsRequiredText = UserHasMissingRoles + createProductEntitlements.mkString(" or ")
|
||||
And("error should be " + createProductEntitlementsRequiredText)
|
||||
response400.body.extract[ErrorMessage].message contains (createProductEntitlementsRequiredText) should be (true)
|
||||
}
|
||||
scenario("We will call the Add endpoint with user credentials and role", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, VersionOfApi) {
|
||||
|
||||
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProduct.toString)
|
||||
|
||||
// Create an grandparent
|
||||
val grandparent: ProductJsonV400 = createProduct(code = "GRANDPARENT_CODE", json = parentPutProductJsonV400)
|
||||
|
||||
// Create an parent
|
||||
val product: ProductJsonV400 = createProduct(code = "PARENT_CODE", json = parentPutProductJsonV400.copy(parent_product_code = grandparent.code))
|
||||
|
||||
// Get
|
||||
val requestGet400 = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.code ).GET <@(user1)
|
||||
val responseGet400 = makeGetRequest(requestGet400)
|
||||
Then("We should get a 200")
|
||||
responseGet400.code should equal(200)
|
||||
val product1 = responseGet400.body.extract[ProductJsonV400]
|
||||
|
||||
// Create an child
|
||||
val childPutProductJsonV400 = parentPutProductJsonV400.copy(parent_product_code = product.code)
|
||||
createProduct(code = "PRODUCT_CODE", json = childPutProductJsonV400)
|
||||
|
||||
// Get
|
||||
val requestGetAll400 = (v4_0_0_Request / "banks" / product.bank_id / "products").GET <@(user1)
|
||||
val responseGetAll400 = makeGetRequest(requestGetAll400)
|
||||
Then("We should get a 200")
|
||||
responseGetAll400.code should equal(200)
|
||||
val products: ProductsJsonV400 = responseGetAll400.body.extract[ProductsJsonV400]
|
||||
products.products.size shouldBe 3
|
||||
|
||||
}
|
||||
scenario("Test the getProducts by url parameters", ApiEndpoint3, VersionOfApi) {
|
||||
|
||||
When("We need to first create the products ")
|
||||
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProduct.toString)
|
||||
createProduct(code = "PRODUCT_CODE", json = parentPutProductJsonV400)
|
||||
|
||||
|
||||
When("we grant the CanCreateProductAttribute role")
|
||||
Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProductAttribute.toString)
|
||||
|
||||
val requestGetAll400 = (v4_0_0_Request / "banks" / testBankId / "products").GET <@(user1)
|
||||
val responseGetAll400 = makeGetRequest(requestGetAll400)
|
||||
Then("We should get a 200")
|
||||
responseGetAll400.code should equal(200)
|
||||
val products: ProductsJsonV400 = responseGetAll400.body.extract[ProductsJsonV400]
|
||||
products.products.head.code should be ("PRODUCT_CODE")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -369,6 +369,7 @@ case class ProductCommons(bankId: BankId,
|
||||
family : String,
|
||||
superFamily : String,
|
||||
moreInfoUrl: String,
|
||||
termsAndConditionsUrl: String,
|
||||
details: String,
|
||||
description: String,
|
||||
meta: Meta) extends Product
|
||||
|
||||
@ -380,6 +380,7 @@ trait Product {
|
||||
def family : String
|
||||
def superFamily : String
|
||||
def moreInfoUrl: String
|
||||
def termsAndConditionsUrl: String
|
||||
def details :String
|
||||
def description: String
|
||||
def meta : Meta
|
||||
|
||||
Loading…
Reference in New Issue
Block a user