mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 15:06:50 +00:00
Merge pull request #2146 from oldbig/feature/customer_special_dynamic_records
Add customer special dynamic entities
This commit is contained in:
commit
9163c063b5
@ -4,12 +4,13 @@ import java.util.UUID.randomUUID
|
||||
import code.api.OBPRestHelper
|
||||
import code.api.builder.OBP_APIBuilder
|
||||
import code.api.cache.Caching
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints, DynamicEntityHelper}
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints}
|
||||
import code.api.dynamic.entity.helper.DynamicEntityHelper
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc, canReadStaticResourceDoc}
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.ExampleValue.endpointMappingRequestBodyExample
|
||||
import code.api.util.{APIUtil, _}
|
||||
import code.api.util._
|
||||
import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson
|
||||
import code.api.v1_4_0.{APIMethods140, JSONFactory1_4_0, OBPAPI1_4_0}
|
||||
import code.api.v2_2_0.{APIMethods220, OBPAPI2_2_0}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
package code.api.dynamic.endpoint
|
||||
|
||||
import code.DynamicData.{DynamicData, DynamicDataProvider}
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEntityHelper, DynamicEntityInfo, EntityName, MockResponseHolder}
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, MockResponseHolder}
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper.DynamicReq
|
||||
import code.api.dynamic.endpoint.helper.MockResponseHolder
|
||||
import code.api.util.APIUtil.{fullBoxOrException, _}
|
||||
import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo, EntityName}
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util.NewStyle.HttpCode
|
||||
import code.api.util._
|
||||
@ -98,7 +99,7 @@ trait APIMethodsDynamicEndpoint {
|
||||
DynamicEndpointHelper.getEntityNameKeyAndValue(responseMappingString, pathParams)
|
||||
}
|
||||
dynamicData <- Future {
|
||||
DynamicDataProvider.connectorMethodProvider.vend.getAll(bankId, entityName)
|
||||
DynamicDataProvider.connectorMethodProvider.vend.getAll(bankId, entityName, None, false)
|
||||
}
|
||||
dynamicJsonData = JArray(dynamicData.map(it => net.liftweb.json.parse(it.dataJson)).map(_.asInstanceOf[JObject]))
|
||||
// //We only get the value, but not sure the field name of it.
|
||||
@ -127,7 +128,7 @@ trait APIMethodsDynamicEndpoint {
|
||||
}
|
||||
//build the entity body according to the request json and mapping
|
||||
entityBody = JsonUtils.buildJson(json, requestMappingJvalue)
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(CREATE, entityName, Some(entityBody.asInstanceOf[JObject]), None, None, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(CREATE, entityName, Some(entityBody.asInstanceOf[JObject]), None, None, None, None, false, Some(cc))
|
||||
singleObject: JValue = unboxResult(box.asInstanceOf[Box[JValue]], entityName)
|
||||
responseBodyScheme = DynamicEndpointHelper.prepareMappingFields(responseMappingJvalue)
|
||||
responseBody = JsonUtils.buildJson(singleObject, responseBodyScheme)
|
||||
@ -139,13 +140,13 @@ trait APIMethodsDynamicEndpoint {
|
||||
(entityName, entityIdKey, entityIdValueFromUrl) <- NewStyle.function.tryons(s"$InvalidEndpointMapping `response_mapping` must be linked to at least one valid dynamic entity!", 400, cc.callContext) {
|
||||
DynamicEndpointHelper.getEntityNameKeyAndValue(responseMappingString, pathParams)
|
||||
}
|
||||
dynamicData = DynamicDataProvider.connectorMethodProvider.vend.getAll(bankId, entityName)
|
||||
dynamicData = DynamicDataProvider.connectorMethodProvider.vend.getAll(bankId, entityName, None,false)
|
||||
dynamicJsonData = JArray(dynamicData.map(it => net.liftweb.json.parse(it.dataJson)).map(_.asInstanceOf[JObject]))
|
||||
entityObject = DynamicEndpointHelper.getObjectByKeyValuePair(dynamicJsonData, entityIdKey, entityIdValueFromUrl.get)
|
||||
isDeleted <- NewStyle.function.tryons(s"$InvalidEndpointMapping `response_mapping` must be linked to at least one valid dynamic entity!", 400, cc.callContext) {
|
||||
val entityIdName = DynamicEntityHelper.createEntityId(entityName)
|
||||
val entityIdValue = (entityObject \ entityIdName).asInstanceOf[JString].s
|
||||
DynamicDataProvider.connectorMethodProvider.vend.delete(bankId, entityName, entityIdValue).head
|
||||
DynamicDataProvider.connectorMethodProvider.vend.delete(bankId, entityName, entityIdValue, None, false).head
|
||||
}
|
||||
} yield {
|
||||
JBool(isDeleted)
|
||||
@ -155,16 +156,16 @@ trait APIMethodsDynamicEndpoint {
|
||||
(entityName, entityIdKey, entityIdValueFromUrl) <- NewStyle.function.tryons(s"$InvalidEndpointMapping `response_mapping` must be linked to at least one valid dynamic entity!", 400, cc.callContext) {
|
||||
DynamicEndpointHelper.getEntityNameKeyAndValue(responseMappingString, pathParams)
|
||||
}
|
||||
dynamicData = DynamicDataProvider.connectorMethodProvider.vend.getAll(bankId, entityName)
|
||||
dynamicData = DynamicDataProvider.connectorMethodProvider.vend.getAll(bankId, entityName, None, false)
|
||||
dynamicJsonData = JArray(dynamicData.map(it => net.liftweb.json.parse(it.dataJson)).map(_.asInstanceOf[JObject]))
|
||||
entityObject = DynamicEndpointHelper.getObjectByKeyValuePair(dynamicJsonData, entityIdKey, entityIdValueFromUrl.get)
|
||||
_ <- NewStyle.function.tryons(s"$InvalidEndpointMapping `response_mapping` must be linked to at least one valid dynamic entity!", 400, cc.callContext) {
|
||||
val entityIdName = DynamicEntityHelper.createEntityId(entityName)
|
||||
val entityIdValue = (entityObject \ entityIdName).asInstanceOf[JString].s
|
||||
DynamicDataProvider.connectorMethodProvider.vend.delete(bankId, entityName, entityIdValue).head
|
||||
DynamicDataProvider.connectorMethodProvider.vend.delete(bankId, entityName, entityIdValue, None, false).head
|
||||
}
|
||||
entityBody = JsonUtils.buildJson(json, requestMappingJvalue)
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(CREATE, entityName, Some(entityBody.asInstanceOf[JObject]), None, bankId, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(CREATE, entityName, Some(entityBody.asInstanceOf[JObject]), None, bankId, None, None, false, Some(cc))
|
||||
singleObject: JValue = unboxResult(box.asInstanceOf[Box[JValue]], entityName)
|
||||
responseBodyScheme = DynamicEndpointHelper.prepareMappingFields(responseMappingJvalue)
|
||||
responseBody = JsonUtils.buildJson(singleObject, responseBodyScheme)
|
||||
|
||||
@ -1043,7 +1043,7 @@ object DynamicEndpointHelper extends RestHelper {
|
||||
def deleteObjectByKeyValuePair (dynamicDataList: List[DynamicDataT], jsonArray: JArray, key:String, value:String): JValue = {
|
||||
val dynamicDataJson = getObjectByKeyValuePair(jsonArray: JArray, key:String, value:String)
|
||||
val (dynamicEntityName, dynamicDateId) = findDynamicData(dynamicDataList, dynamicDataJson)
|
||||
JBool(DynamicDataProvider.connectorMethodProvider.vend.delete(None, dynamicEntityName, dynamicDateId).getOrElse(false))
|
||||
JBool(DynamicDataProvider.connectorMethodProvider.vend.delete(None, dynamicEntityName, dynamicDateId, None, false).getOrElse(false))
|
||||
}
|
||||
|
||||
def addedBankToPath(swagger: String, bankId: Option[String]): JValue = {
|
||||
|
||||
@ -1,449 +0,0 @@
|
||||
package code.api.dynamic.endpoint.helper
|
||||
|
||||
import code.api.util.APIUtil.{EmptyBody, ResourceDoc, authenticationRequiredMessage, generateUUID}
|
||||
import code.api.util.ApiRole.getOrCreateDynamicApiRole
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.ErrorMessages.{InvalidJsonFormat, UnknownError, UserHasMissingRoles, UserNotLoggedIn}
|
||||
import code.api.util._
|
||||
import com.openbankproject.commons.model.enums.{DynamicEntityFieldType, DynamicEntityOperation}
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import net.liftweb.json.JsonDSL._
|
||||
import net.liftweb.json._
|
||||
import net.liftweb.util.StringHelpers
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
||||
object EntityName {
|
||||
// unapply result structure: (BankId, entityName, id)
|
||||
def unapply(url: List[String]): Option[(Option[String], String, String)] = url match {
|
||||
//no bank:
|
||||
//eg: /FooBar21
|
||||
case entityName :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == None && definitionMap._1._2 == entityName && definitionMap._2.bankId.isEmpty)
|
||||
.map(_ => (None, entityName, ""))
|
||||
//eg: /FooBar21/FOO_BAR21_ID
|
||||
case entityName :: id :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == None && definitionMap._1._2 == entityName && definitionMap._2.bankId.isEmpty)
|
||||
.map(_ => (None, entityName, id))
|
||||
|
||||
//contains Bank:
|
||||
//eg: /Banks/BANK_ID/FooBar21
|
||||
case "banks" :: bankId :: entityName :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == Some(bankId) && definitionMap._1._2 == entityName && definitionMap._2.bankId == Some(bankId))
|
||||
.map(_ => (Some(bankId), entityName, ""))
|
||||
//eg: /Banks/BANK_ID/FooBar21/FOO_BAR21_ID
|
||||
case "banks" :: bankId :: entityName :: id :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == Some(bankId) && definitionMap._1._2 == entityName && definitionMap._2.bankId == Some(bankId))
|
||||
.map(_ => (Some(bankId),entityName, id))
|
||||
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
object DynamicEntityHelper {
|
||||
private val implementedInApiVersion = ApiVersion.v4_0_0
|
||||
|
||||
// (Some(BankId), EntityName, DynamicEntityInfo)
|
||||
def definitionsMap: Map[(Option[String], String), DynamicEntityInfo] = NewStyle.function.getDynamicEntities(None).map(it => ((it.bankId, it.entityName), DynamicEntityInfo(it.metadataJson, it.entityName, it.bankId))).toMap
|
||||
|
||||
def dynamicEntityRoles: List[String] = NewStyle.function.getDynamicEntities(None).flatMap(dEntity => DynamicEntityInfo.roleNames(dEntity.entityName, dEntity.bankId))
|
||||
|
||||
def doc: ArrayBuffer[ResourceDoc] = {
|
||||
val docs = operationToResourceDoc.values.toList
|
||||
collection.mutable.ArrayBuffer(docs:_*)
|
||||
}
|
||||
|
||||
def createEntityId(entityName: String) = {
|
||||
// (?<=[a-z0-9])(?=[A-Z]) --> mean `Positive Lookbehind (?<=[a-z0-9])` && Positive Lookahead (?=[A-Z]) --> So we can find the space to replace to `_`
|
||||
val regexPattern = "(?<=[a-z0-9])(?=[A-Z])|-"
|
||||
// eg: entityName = PetEntity => entityIdName = pet_entity_id
|
||||
s"${entityName}_Id".replaceAll(regexPattern, "_").toLowerCase
|
||||
}
|
||||
|
||||
def operationToResourceDoc: Map[(DynamicEntityOperation, String), ResourceDoc] = {
|
||||
val addPrefix = APIUtil.getPropsAsBoolValue("dynamic_entities_have_prefix", true)
|
||||
|
||||
// record exists tag names, to avoid duplicated dynamic tag name.
|
||||
var existsTagNames = ApiTag.staticTagNames
|
||||
// match string that start with _, e.g: "_abc"
|
||||
val Regex = "(_+)(.+)".r
|
||||
|
||||
|
||||
//convert entity name to tag name, example:
|
||||
// Csem-case -> Csem Case
|
||||
// _Csem-case -> _Csem Case
|
||||
// Csem_case -> Csem Case
|
||||
// _Csem_case -> _Csem Case
|
||||
// csem-case -> Csem Case
|
||||
def prettyTagName(s: String) = s.capitalize.split("(?<=[^-_])[-_]+").reduceLeft(_ + " " + _.capitalize)
|
||||
|
||||
def apiTag(entityName: String, singularName: String): ResourceDocTag = {
|
||||
|
||||
val existsSameStaticEntity: Boolean = existsTagNames
|
||||
.exists(it => it.equalsIgnoreCase(singularName) || it.equalsIgnoreCase(entityName))
|
||||
|
||||
|
||||
val tagName = if(addPrefix || existsSameStaticEntity) {
|
||||
var name = singularName match {
|
||||
case Regex(a,b) => s"$a${b.capitalize}"
|
||||
case v => s"_${v.capitalize}"
|
||||
}
|
||||
|
||||
while(existsTagNames.exists(it => it.equalsIgnoreCase(name))) {
|
||||
name = s"_$name"
|
||||
}
|
||||
prettyTagName(name)
|
||||
} else {
|
||||
prettyTagName(singularName.capitalize)
|
||||
}
|
||||
|
||||
existsTagNames += tagName
|
||||
ApiTag(tagName)
|
||||
}
|
||||
val fun: DynamicEntityInfo => mutable.Map[(DynamicEntityOperation, String), ResourceDoc] = createDocs(apiTag)
|
||||
val docs: Iterable[((DynamicEntityOperation, String), ResourceDoc)] = definitionsMap.values.flatMap(fun)
|
||||
docs.toMap
|
||||
}
|
||||
|
||||
// TODO the requestBody and responseBody is not correct ref type
|
||||
/**
|
||||
*
|
||||
* @param fun (singularName, entityName) => ResourceDocTag
|
||||
* @param dynamicEntityInfo dynamicEntityInfo
|
||||
* @return all ResourceDoc of given dynamicEntity
|
||||
*/
|
||||
private def createDocs(fun: (String, String) => ResourceDocTag)
|
||||
(dynamicEntityInfo: DynamicEntityInfo): mutable.Map[(DynamicEntityOperation, String), ResourceDoc] = {
|
||||
val entityName = dynamicEntityInfo.entityName
|
||||
// e.g: "someMultiple-part_Name" -> ["Some", "Multiple", "Part", "Name"]
|
||||
val capitalizedNameParts = entityName.split("(?<=[a-z0-9])(?=[A-Z])|-|_").map(_.capitalize).filterNot(_.trim.isEmpty)
|
||||
val splitName = s"""${capitalizedNameParts.mkString(" ")}"""
|
||||
val splitNameWithBankId = if (dynamicEntityInfo.bankId.isDefined)
|
||||
s"""$splitName(${dynamicEntityInfo.bankId.getOrElse("")})"""
|
||||
else
|
||||
s"""$splitName"""
|
||||
|
||||
val idNameInUrl = StringHelpers.snakify(dynamicEntityInfo.idName).toUpperCase()
|
||||
val listName = dynamicEntityInfo.listName
|
||||
val bankId = dynamicEntityInfo.bankId
|
||||
val resourceDocUrl = if(bankId.isDefined) s"/banks/${bankId.getOrElse("")}/$entityName" else s"/$entityName"
|
||||
|
||||
val endPoint = APIUtil.dynamicEndpointStub
|
||||
|
||||
// (operationType, entityName) -> ResourceDoc
|
||||
val resourceDocs = scala.collection.mutable.Map[(DynamicEntityOperation, String),ResourceDoc]()
|
||||
val apiTag: ResourceDocTag = fun(entityName,splitNameWithBankId)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.GET_ALL, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildGetAllFunctionName(bankId, entityName),
|
||||
"GET",
|
||||
s"$resourceDocUrl",
|
||||
s"Get $splitName List",
|
||||
s"""Get $splitName List.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|Can do filter on the fields
|
||||
|e.g: /${entityName}?name=James%20Brown&number=123.456&number=11.11
|
||||
|Will do filter by this rule: name == "James Brown" && (number==123.456 || number=11.11)
|
||||
|""".stripMargin,
|
||||
EmptyBody,
|
||||
dynamicEntityInfo.getExampleList,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
Some(List(dynamicEntityInfo.canGetRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.GET_ONE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildGetOneFunctionName(bankId, entityName),
|
||||
"GET",
|
||||
s"$resourceDocUrl/$idNameInUrl",
|
||||
s"Get $splitName by id",
|
||||
s"""Get $splitName by id.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|""".stripMargin,
|
||||
EmptyBody,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
Some(List(dynamicEntityInfo.canGetRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.CREATE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildCreateFunctionName(bankId, entityName),
|
||||
"POST",
|
||||
s"$resourceDocUrl",
|
||||
s"Create new $splitName",
|
||||
s"""Create new $splitName.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
dynamicEntityInfo.getSingleExampleWithoutId,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
Some(List(dynamicEntityInfo.canCreateRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.UPDATE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildUpdateFunctionName(bankId, entityName),
|
||||
"PUT",
|
||||
s"$resourceDocUrl/$idNameInUrl",
|
||||
s"Update $splitName",
|
||||
s"""Update $splitName.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
dynamicEntityInfo.getSingleExampleWithoutId,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
Some(List(dynamicEntityInfo.canUpdateRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.DELETE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildDeleteFunctionName(bankId, entityName),
|
||||
"DELETE",
|
||||
s"$resourceDocUrl/$idNameInUrl",
|
||||
s"Delete $splitName by id",
|
||||
s"""Delete $splitName by id
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
dynamicEntityInfo.getSingleExampleWithoutId,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
Some(List(dynamicEntityInfo.canDeleteRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs
|
||||
}
|
||||
|
||||
private def buildCreateFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_create${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildUpdateFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_update${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildDeleteFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_delete${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildGetOneFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_getSingle${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildGetAllFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_get${entityName}List_${bankId.getOrElse("")}"
|
||||
|
||||
@inline
|
||||
private def buildOperationId(bankId:Option[String], entityName: String, fun: (Option[String], String) => String): String = {
|
||||
APIUtil.buildOperationId(implementedInApiVersion, fun(bankId, entityName))
|
||||
}
|
||||
|
||||
def buildCreateOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildCreateFunctionName)
|
||||
def buildUpdateOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildUpdateFunctionName)
|
||||
def buildDeleteOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildDeleteFunctionName)
|
||||
def buildGetOneOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildGetOneFunctionName)
|
||||
def buildGetAllOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildGetAllFunctionName)
|
||||
|
||||
private def methodRoutingExample(entityName: String) =
|
||||
s"""
|
||||
|MethodRouting settings example:
|
||||
|
|
||||
|<details>
|
||||
|
|
||||
|```
|
||||
|{
|
||||
| "is_bank_id_exact_match":false,
|
||||
| "method_name":"dynamicEntityProcess",
|
||||
| "connector_name":"rest_vMar2019",
|
||||
| "bank_id_pattern":".*",
|
||||
| "parameters":[
|
||||
| {
|
||||
| "key":"entityName",
|
||||
| "value":"$entityName"
|
||||
| }
|
||||
| {
|
||||
| "key":"url",
|
||||
| "value":"http://mydomain.com/xxx"
|
||||
| }
|
||||
| ]
|
||||
|}
|
||||
|```
|
||||
|
|
||||
|</details>
|
||||
|""".stripMargin
|
||||
|
||||
}
|
||||
case class DynamicEntityInfo(definition: String, entityName: String, bankId: Option[String]) {
|
||||
|
||||
import net.liftweb.json
|
||||
|
||||
val subEntities: List[DynamicEntityInfo] = Nil
|
||||
|
||||
val idName = StringUtils.uncapitalize(entityName) + "Id"
|
||||
|
||||
val listName = StringHelpers.snakify(entityName).replaceFirst("[-_]*$", "_list")
|
||||
|
||||
val singleName = StringHelpers.snakify(entityName).replaceFirst("[-_]*$", "")
|
||||
|
||||
val jsonTypeMap: Map[String, Class[_]] = DynamicEntityFieldType.nameToValue.mapValues(_.jValueType)
|
||||
|
||||
val definitionJson = json.parse(definition).asInstanceOf[JObject]
|
||||
val entity = (definitionJson \ entityName).asInstanceOf[JObject]
|
||||
|
||||
val description = entity \ "description" match {
|
||||
case JString(s) if StringUtils.isNotBlank(s) =>
|
||||
s"""
|
||||
|${s.capitalize}
|
||||
|""".stripMargin
|
||||
case _ => ""
|
||||
}
|
||||
|
||||
val fieldsDescription = {
|
||||
val descriptions = (entity \ "properties")
|
||||
.asInstanceOf[JObject]
|
||||
.obj
|
||||
.filter(field =>
|
||||
field.value \ "description" match {
|
||||
case JString(s) if StringUtils.isNotBlank(s) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
if(descriptions.nonEmpty) {
|
||||
descriptions
|
||||
.map(field => s"""* ${field.name}: ${(field.value \ "description").asInstanceOf[JString].s}""")
|
||||
.mkString("**Property List:** \n\n", "\n", "")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
def toResponse(result: JObject, id: Option[String]): JObject = {
|
||||
|
||||
val fieldNameToTypeName: Map[String, String] = (entity \ "properties")
|
||||
.asInstanceOf[JObject]
|
||||
.obj
|
||||
.map(field => (field.name, (field.value \ "type").asInstanceOf[JString].s))
|
||||
.toMap
|
||||
|
||||
val fieldNameToType: Map[String, Class[_]] = fieldNameToTypeName
|
||||
.mapValues(jsonTypeMap(_))
|
||||
|
||||
val fields = result.obj.filter(it => fieldNameToType.keySet.contains(it.name))
|
||||
|
||||
(id, fields.exists(_.name == idName)) match {
|
||||
case (Some(idValue), false) => JObject(JField(idName, JString(idValue)) :: fields)
|
||||
case _ => JObject(fields)
|
||||
}
|
||||
}
|
||||
|
||||
def getSingleExampleWithoutId: JObject = {
|
||||
val fields = (entity \ "properties").asInstanceOf[JObject].obj
|
||||
|
||||
def extractExample(typeAndExample: JValue): JValue = {
|
||||
val example = typeAndExample \ "example"
|
||||
(example, (typeAndExample \ "type")) match {
|
||||
case (JString(s), JString("boolean")) => JBool(s.toLowerCase().toBoolean)
|
||||
case (JString(s), JString("integer")) => JInt(s.toLong)
|
||||
case (JString(s), JString("number")) => JDouble(s.toDouble)
|
||||
case _ => example
|
||||
}
|
||||
}
|
||||
val exampleFields = fields.map(field => JField(field.name, extractExample(field.value)))
|
||||
JObject(exampleFields)
|
||||
}
|
||||
val bankIdJObject: JObject = ("bank-id" -> ExampleValue.bankIdExample.value)
|
||||
|
||||
def getSingleExample: JObject = if (bankId.isDefined){
|
||||
val SingleObject: JObject = (singleName -> (JObject(JField(idName, JString(generateUUID())) :: getSingleExampleWithoutId.obj)))
|
||||
bankIdJObject merge SingleObject
|
||||
} else{
|
||||
(singleName -> (JObject(JField(idName, JString(generateUUID())) :: getSingleExampleWithoutId.obj)))
|
||||
}
|
||||
|
||||
def getExampleList: JObject = if (bankId.isDefined){
|
||||
val objectList: JObject = (listName -> JArray(List(getSingleExample)))
|
||||
bankIdJObject merge objectList
|
||||
} else{
|
||||
(listName -> JArray(List(getSingleExample)))
|
||||
}
|
||||
|
||||
val canCreateRole: ApiRole = DynamicEntityInfo.canCreateRole(entityName, bankId)
|
||||
val canUpdateRole: ApiRole = DynamicEntityInfo.canUpdateRole(entityName, bankId)
|
||||
val canGetRole: ApiRole = DynamicEntityInfo.canGetRole(entityName, bankId)
|
||||
val canDeleteRole: ApiRole = DynamicEntityInfo.canDeleteRole(entityName, bankId)
|
||||
}
|
||||
|
||||
object DynamicEntityInfo {
|
||||
def canCreateRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanCreateDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canUpdateRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanUpdateDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canGetRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanGetDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canDeleteRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanDeleteDynamicEntity_" + entityName, bankId.isDefined)
|
||||
|
||||
def roleNames(entityName: String, bankId:Option[String]): List[String] = List(
|
||||
canCreateRole(entityName, bankId),
|
||||
canUpdateRole(entityName, bankId),
|
||||
canGetRole(entityName, bankId),
|
||||
canDeleteRole(entityName, bankId)
|
||||
).map(_.toString())
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
package code.api.dynamic.entity
|
||||
|
||||
import code.DynamicData.{DynamicData, DynamicDataProvider}
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEntityHelper, DynamicEntityInfo, EntityName, MockResponseHolder}
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, MockResponseHolder}
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper.DynamicReq
|
||||
import code.api.dynamic.endpoint.helper.MockResponseHolder
|
||||
import code.api.util.APIUtil.{fullBoxOrException, _}
|
||||
import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo, EntityName}
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util.NewStyle.HttpCode
|
||||
import code.api.util._
|
||||
@ -64,7 +65,7 @@ trait APIMethodsDynamicEntity {
|
||||
case map if map.isEmpty => resultList
|
||||
case params =>
|
||||
val filteredWithFieldValue = resultList.arr.filter { jValue =>
|
||||
params.forall { kv =>
|
||||
params.filter(_._1!="locale").forall { kv =>
|
||||
val (path, values) = kv
|
||||
values.exists(JsonUtils.isFieldEquals(jValue, path, _))
|
||||
}
|
||||
@ -75,13 +76,25 @@ trait APIMethodsDynamicEntity {
|
||||
}
|
||||
|
||||
lazy val genericEndpoint: OBPEndpoint = {
|
||||
case EntityName(bankId, entityName, id) JsonGet req => { cc =>
|
||||
case EntityName(bankId, entityName, id, isPersonalEntity) JsonGet req => { cc =>
|
||||
val listName = StringHelpers.snakify(entityName).replaceFirst("[-_]*$", "_list")
|
||||
val singleName = StringHelpers.snakify(entityName).replaceFirst("[-_]*$", "")
|
||||
val isGetAll = StringUtils.isBlank(id)
|
||||
|
||||
// e.g: "someMultiple-part_Name" -> ["Some", "Multiple", "Part", "Name"]
|
||||
val capitalizedNameParts = entityName.split("(?<=[a-z0-9])(?=[A-Z])|-|_").map(_.capitalize).filterNot(_.trim.isEmpty)
|
||||
val splitName = s"""${capitalizedNameParts.mkString(" ")}"""
|
||||
val splitNameWithBankId = if (bankId.isDefined)
|
||||
s"""$splitName(${bankId.getOrElse("")})"""
|
||||
else
|
||||
s"""$splitName"""
|
||||
val mySplitNameWithBankId = s"My$splitNameWithBankId"
|
||||
|
||||
val operation: DynamicEntityOperation = if (StringUtils.isBlank(id)) GET_ALL else GET_ONE
|
||||
val resourceDoc = DynamicEntityHelper.operationToResourceDoc.get(operation -> entityName)
|
||||
val resourceDoc = if(isPersonalEntity)
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> mySplitNameWithBankId)
|
||||
else
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
val operationId = resourceDoc.map(_.operationId).orNull
|
||||
val callContext = cc.copy(operationId = Some(operationId), resourceDocument = resourceDoc)
|
||||
// process before authentication interceptor, get intercept result
|
||||
@ -99,7 +112,11 @@ trait APIMethodsDynamicEntity {
|
||||
}
|
||||
}
|
||||
|
||||
_ <- NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canGetRole(entityName, bankId), callContext)
|
||||
_ <- if (isPersonalEntity) {
|
||||
Future.successful(true)
|
||||
} else {
|
||||
NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canGetRole(entityName, bankId), callContext)
|
||||
}
|
||||
|
||||
// process after authentication interceptor, get intercept result
|
||||
jsonResponse: Box[ErrorMessage] = afterAuthenticateInterceptResult(callContext, operationId).collect({
|
||||
@ -109,7 +126,11 @@ trait APIMethodsDynamicEntity {
|
||||
jsonResponse.isEmpty
|
||||
}
|
||||
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, None, Option(id).filter(StringUtils.isNotBlank), bankId, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, None, Option(id).filter(StringUtils.isNotBlank), bankId, None,
|
||||
Some(u.userId),
|
||||
isPersonalEntity,
|
||||
Some(cc)
|
||||
)
|
||||
|
||||
_ <- Helper.booleanToFuture(EntityNotFoundByEntityId, 404, cc = callContext) {
|
||||
box.isDefined
|
||||
@ -139,8 +160,7 @@ trait APIMethodsDynamicEntity {
|
||||
(jValue, HttpCode.`200`(Some(cc)))
|
||||
}
|
||||
}
|
||||
|
||||
case EntityName(bankId, entityName, _) JsonPost json -> _ => { cc =>
|
||||
case EntityName(bankId, entityName, _, isPersonalEntity) JsonPost json -> _ => { cc =>
|
||||
val singleName = StringHelpers.snakify(entityName).replaceFirst("[-_]*$", "")
|
||||
val operation: DynamicEntityOperation = CREATE
|
||||
// e.g: "someMultiple-part_Name" -> ["Some", "Multiple", "Part", "Name"]
|
||||
@ -150,7 +170,13 @@ trait APIMethodsDynamicEntity {
|
||||
s"""$splitName(${bankId.getOrElse("")})"""
|
||||
else
|
||||
s"""$splitName"""
|
||||
val resourceDoc = DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
val mySplitNameWithBankId = s"My$splitNameWithBankId"
|
||||
|
||||
val resourceDoc = if(isPersonalEntity)
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> mySplitNameWithBankId)
|
||||
else
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
|
||||
val operationId = resourceDoc.map(_.operationId).orNull
|
||||
val callContext = cc.copy(operationId = Some(operationId), resourceDocument = resourceDoc)
|
||||
|
||||
@ -167,7 +193,12 @@ trait APIMethodsDynamicEntity {
|
||||
("", callContext)
|
||||
}
|
||||
}
|
||||
_ <- NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canCreateRole(entityName, bankId), callContext)
|
||||
|
||||
_ <- if (isPersonalEntity) {
|
||||
Future.successful(true)
|
||||
} else {
|
||||
NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canCreateRole(entityName, bankId), callContext)
|
||||
}
|
||||
|
||||
// process after authentication interceptor, get intercept result
|
||||
jsonResponse: Box[ErrorMessage] = afterAuthenticateInterceptResult(callContext, operationId).collect({
|
||||
@ -177,7 +208,7 @@ trait APIMethodsDynamicEntity {
|
||||
jsonResponse.isEmpty
|
||||
}
|
||||
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, Some(json.asInstanceOf[JObject]), None, bankId, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, Some(json.asInstanceOf[JObject]), None, bankId, None, Some(u.userId), isPersonalEntity, Some(cc))
|
||||
singleObject: JValue = unboxResult(box.asInstanceOf[Box[JValue]], entityName)
|
||||
} yield {
|
||||
val result: JObject = (singleName -> singleObject)
|
||||
@ -190,7 +221,7 @@ trait APIMethodsDynamicEntity {
|
||||
(entity, HttpCode.`201`(Some(cc)))
|
||||
}
|
||||
}
|
||||
case EntityName(bankId, entityName, id) JsonPut json -> _ => { cc =>
|
||||
case EntityName(bankId, entityName, id, isPersonalEntity) JsonPut json -> _ => { cc =>
|
||||
val singleName = StringHelpers.snakify(entityName).replaceFirst("[-_]*$", "")
|
||||
val operation: DynamicEntityOperation = UPDATE
|
||||
// e.g: "someMultiple-part_Name" -> ["Some", "Multiple", "Part", "Name"]
|
||||
@ -200,7 +231,13 @@ trait APIMethodsDynamicEntity {
|
||||
s"""$splitName(${bankId.getOrElse("")})"""
|
||||
else
|
||||
s"""$splitName"""
|
||||
val resourceDoc = DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
val mySplitNameWithBankId = s"My$splitNameWithBankId"
|
||||
|
||||
val resourceDoc = if(isPersonalEntity)
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> mySplitNameWithBankId)
|
||||
else
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
|
||||
val operationId = resourceDoc.map(_.operationId).orNull
|
||||
val callContext = cc.copy(operationId = Some(operationId), resourceDocument = resourceDoc)
|
||||
|
||||
@ -217,7 +254,11 @@ trait APIMethodsDynamicEntity {
|
||||
("", callContext)
|
||||
}
|
||||
}
|
||||
_ <- NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canUpdateRole(entityName, bankId), callContext)
|
||||
_ <- if (isPersonalEntity) {
|
||||
Future.successful(true)
|
||||
} else {
|
||||
NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canUpdateRole(entityName, bankId), callContext)
|
||||
}
|
||||
|
||||
// process after authentication interceptor, get intercept result
|
||||
jsonResponse: Box[ErrorMessage] = afterAuthenticateInterceptResult(callContext, operationId).collect({
|
||||
@ -227,11 +268,17 @@ trait APIMethodsDynamicEntity {
|
||||
jsonResponse.isEmpty
|
||||
}
|
||||
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ONE, entityName, None, Some(id), bankId, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ONE, entityName, None, Some(id), bankId, None,
|
||||
Some(u.userId),
|
||||
isPersonalEntity,
|
||||
Some(cc))
|
||||
_ <- Helper.booleanToFuture(EntityNotFoundByEntityId, 404, cc = callContext) {
|
||||
box.isDefined
|
||||
}
|
||||
(box: Box[JValue], _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, Some(json.asInstanceOf[JObject]), Some(id), bankId, None, Some(cc))
|
||||
(box: Box[JValue], _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, Some(json.asInstanceOf[JObject]), Some(id), bankId, None,
|
||||
Some(u.userId),
|
||||
isPersonalEntity,
|
||||
Some(cc))
|
||||
singleObject: JValue = unboxResult(box.asInstanceOf[Box[JValue]], entityName)
|
||||
} yield {
|
||||
val result: JObject = (singleName -> singleObject)
|
||||
@ -244,7 +291,7 @@ trait APIMethodsDynamicEntity {
|
||||
(entity, HttpCode.`200`(Some(cc)))
|
||||
}
|
||||
}
|
||||
case EntityName(bankId, entityName, id) JsonDelete _ => { cc =>
|
||||
case EntityName(bankId, entityName, id, isPersonalEntity) JsonDelete _ => { cc =>
|
||||
val operation: DynamicEntityOperation = DELETE
|
||||
// e.g: "someMultiple-part_Name" -> ["Some", "Multiple", "Part", "Name"]
|
||||
val capitalizedNameParts = entityName.split("(?<=[a-z0-9])(?=[A-Z])|-|_").map(_.capitalize).filterNot(_.trim.isEmpty)
|
||||
@ -253,7 +300,13 @@ trait APIMethodsDynamicEntity {
|
||||
s"""$splitName(${bankId.getOrElse("")})"""
|
||||
else
|
||||
s"""$splitName"""
|
||||
val resourceDoc = DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
val mySplitNameWithBankId = s"My$splitNameWithBankId"
|
||||
|
||||
val resourceDoc = if(isPersonalEntity)
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> mySplitNameWithBankId)
|
||||
else
|
||||
DynamicEntityHelper.operationToResourceDoc.get(operation -> splitNameWithBankId)
|
||||
|
||||
val operationId = resourceDoc.map(_.operationId).orNull
|
||||
val callContext = cc.copy(operationId = Some(operationId), resourceDocument = resourceDoc)
|
||||
|
||||
@ -270,7 +323,12 @@ trait APIMethodsDynamicEntity {
|
||||
("", callContext)
|
||||
}
|
||||
}
|
||||
_ <- NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canDeleteRole(entityName, bankId), callContext)
|
||||
|
||||
_ <- if (isPersonalEntity) {
|
||||
Future.successful(true)
|
||||
} else {
|
||||
NewStyle.function.hasEntitlement(bankId.getOrElse(""), u.userId, DynamicEntityInfo.canDeleteRole(entityName, bankId), callContext)
|
||||
}
|
||||
|
||||
// process after authentication interceptor, get intercept result
|
||||
jsonResponse: Box[ErrorMessage] = afterAuthenticateInterceptResult(callContext, operationId).collect({
|
||||
@ -280,14 +338,22 @@ trait APIMethodsDynamicEntity {
|
||||
jsonResponse.isEmpty
|
||||
}
|
||||
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ONE, entityName, None, Some(id), bankId, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ONE, entityName, None, Some(id), bankId, None,
|
||||
Some(u.userId),
|
||||
isPersonalEntity,
|
||||
Some(cc)
|
||||
)
|
||||
_ <- Helper.booleanToFuture(EntityNotFoundByEntityId, 404, cc = callContext) {
|
||||
box.isDefined
|
||||
}
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, None, Some(id), bankId, None, Some(cc))
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(operation, entityName, None, Some(id), bankId, None,
|
||||
Some(u.userId),
|
||||
isPersonalEntity,
|
||||
Some(cc)
|
||||
)
|
||||
deleteResult: JBool = unboxResult(box.asInstanceOf[Box[JBool]], entityName)
|
||||
} yield {
|
||||
(deleteResult, HttpCode.`204`(Some(cc)))
|
||||
(deleteResult, HttpCode.`200`(Some(cc)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,27 +18,46 @@ import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
||||
object EntityName {
|
||||
// unapply result structure: (BankId, entityName, id)
|
||||
def unapply(url: List[String]): Option[(Option[String], String, String)] = url match {
|
||||
//no bank:
|
||||
// unapply result structure: (BankId, entityName, id, isPersonalEntity)
|
||||
def unapply(url: List[String]): Option[(Option[String], String, String, Boolean)] = url match {
|
||||
|
||||
//eg: /my/FooBar21
|
||||
case "my" :: entityName :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == None && definitionMap._1._2 == entityName && definitionMap._2.bankId.isEmpty && definitionMap._2.hasPersonalEntity)
|
||||
.map(_ => (None, entityName, "", true))
|
||||
//eg: /my/FooBar21/FOO_BAR21_ID
|
||||
case "my" :: entityName :: id :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == None && definitionMap._1._2 == entityName && definitionMap._2.bankId.isEmpty && definitionMap._2.hasPersonalEntity)
|
||||
.map(_ => (None, entityName, id, true))
|
||||
|
||||
//eg: /FooBar21
|
||||
case entityName :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1 == entityName && definitionMap._2.bankId.isEmpty)
|
||||
.map(_ => (None, entityName, ""))
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == None && definitionMap._1._2 == entityName && definitionMap._2.bankId.isEmpty)
|
||||
.map(_ => (None, entityName, "", false))
|
||||
//eg: /FooBar21/FOO_BAR21_ID
|
||||
case entityName :: id :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1 == entityName && definitionMap._2.bankId.isEmpty)
|
||||
.map(_ => (None, entityName, id))
|
||||
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == None && definitionMap._1._2 == entityName && definitionMap._2.bankId.isEmpty)
|
||||
.map(_ => (None, entityName, id, false))
|
||||
|
||||
|
||||
//eg: /Banks/BANK_ID/my/FooBar21
|
||||
case "banks" :: bankId :: "my" :: entityName :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == Some(bankId) && definitionMap._1._2 == entityName && definitionMap._2.bankId == Some(bankId) && definitionMap._2.hasPersonalEntity)
|
||||
.map(_ => (Some(bankId), entityName, "", true))
|
||||
//eg: /Banks/BANK_ID/my/FooBar21/FOO_BAR21_ID
|
||||
case "banks" :: bankId :: "my" :: entityName :: id :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == Some(bankId) && definitionMap._1._2 == entityName && definitionMap._2.bankId == Some(bankId) && definitionMap._2.hasPersonalEntity)
|
||||
.map(_ => (Some(bankId),entityName, id, true))
|
||||
|
||||
//contains Bank:
|
||||
//eg: /Banks/BANK_ID/FooBar21
|
||||
case "banks" :: bankId :: entityName :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1 == entityName && definitionMap._2.bankId == Some(bankId))
|
||||
.map(_ => (Some(bankId), entityName, ""))
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == Some(bankId) && definitionMap._1._2 == entityName && definitionMap._2.bankId == Some(bankId))
|
||||
.map(_ => (Some(bankId), entityName, "", false))
|
||||
//eg: /Banks/BANK_ID/FooBar21/FOO_BAR21_ID
|
||||
case "banks" :: bankId :: entityName :: id :: Nil =>
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1 == entityName && definitionMap._2.bankId == Some(bankId))
|
||||
.map(_ => (Some(bankId),entityName, id))
|
||||
DynamicEntityHelper.definitionsMap.find(definitionMap => definitionMap._1._1 == Some(bankId) && definitionMap._1._2 == entityName && definitionMap._2.bankId == Some(bankId))
|
||||
.map(_ => (Some(bankId),entityName, id, false))//no bank:
|
||||
|
||||
case _ => None
|
||||
}
|
||||
@ -46,10 +65,11 @@ object EntityName {
|
||||
|
||||
object DynamicEntityHelper {
|
||||
private val implementedInApiVersion = ApiVersion.v4_0_0
|
||||
|
||||
// (Some(BankId), EntityName, DynamicEntityInfo)
|
||||
def definitionsMap: Map[(Option[String], String), DynamicEntityInfo] = NewStyle.function.getDynamicEntities(None, true).map(it => ((it.bankId, it.entityName), DynamicEntityInfo(it.metadataJson, it.entityName, it.bankId, it.hasPersonalEntity))).toMap
|
||||
|
||||
def definitionsMap: Map[String, DynamicEntityInfo] = NewStyle.function.getDynamicEntities(None).map(it => (it.entityName, DynamicEntityInfo(it.metadataJson, it.entityName, it.bankId))).toMap
|
||||
|
||||
def dynamicEntityRoles: List[String] = NewStyle.function.getDynamicEntities(None).flatMap(dEntity => DynamicEntityInfo.roleNames(dEntity.entityName, dEntity.bankId))
|
||||
def dynamicEntityRoles: List[String] = NewStyle.function.getDynamicEntities(None, true).flatMap(dEntity => DynamicEntityInfo.roleNames(dEntity.entityName, dEntity.bankId))
|
||||
|
||||
def doc: ArrayBuffer[ResourceDoc] = {
|
||||
val docs = operationToResourceDoc.values.toList
|
||||
@ -118,25 +138,34 @@ object DynamicEntityHelper {
|
||||
private def createDocs(fun: (String, String) => ResourceDocTag)
|
||||
(dynamicEntityInfo: DynamicEntityInfo): mutable.Map[(DynamicEntityOperation, String), ResourceDoc] = {
|
||||
val entityName = dynamicEntityInfo.entityName
|
||||
val hasPersonalEntity = dynamicEntityInfo.hasPersonalEntity
|
||||
|
||||
// e.g: "someMultiple-part_Name" -> ["Some", "Multiple", "Part", "Name"]
|
||||
val capitalizedNameParts = entityName.split("(?<=[a-z0-9])(?=[A-Z])|-|_").map(_.capitalize).filterNot(_.trim.isEmpty)
|
||||
val splitName = capitalizedNameParts.mkString(" ")
|
||||
val splitName = s"""${capitalizedNameParts.mkString(" ")}"""
|
||||
val splitNameWithBankId = if (dynamicEntityInfo.bankId.isDefined)
|
||||
s"""$splitName(${dynamicEntityInfo.bankId.getOrElse("")})"""
|
||||
else
|
||||
s"""$splitName"""
|
||||
|
||||
val mySplitNameWithBankId = s"My$splitNameWithBankId"
|
||||
|
||||
val idNameInUrl = StringHelpers.snakify(dynamicEntityInfo.idName).toUpperCase()
|
||||
val listName = dynamicEntityInfo.listName
|
||||
val bankId = dynamicEntityInfo.bankId
|
||||
val resourceDocUrl = if(bankId.isDefined) s"/banks/BANK_ID/$entityName" else s"/$entityName"
|
||||
val resourceDocUrl = if(bankId.isDefined) s"/banks/${bankId.getOrElse("")}/$entityName" else s"/$entityName"
|
||||
val myResourceDocUrl = if(bankId.isDefined) s"/banks/${bankId.getOrElse("")}/my/$entityName" else s"/my/$entityName"
|
||||
|
||||
val endPoint = APIUtil.dynamicEndpointStub
|
||||
|
||||
// (operationType, entityName) -> ResourceDoc
|
||||
val resourceDocs = scala.collection.mutable.Map[(DynamicEntityOperation, String),ResourceDoc]()
|
||||
val apiTag: ResourceDocTag = fun(splitName, entityName)
|
||||
val apiTag: ResourceDocTag = fun(entityName,splitNameWithBankId)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.GET_ALL, entityName) -> ResourceDoc(
|
||||
resourceDocs += (DynamicEntityOperation.GET_ALL, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildGetAllFunctionName(entityName),
|
||||
buildGetAllFunctionName(bankId, entityName),
|
||||
"GET",
|
||||
s"$resourceDocUrl",
|
||||
s"Get $splitName List",
|
||||
@ -164,10 +193,11 @@ object DynamicEntityHelper {
|
||||
Some(List(dynamicEntityInfo.canGetRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
resourceDocs += (DynamicEntityOperation.GET_ONE, entityName) -> ResourceDoc(
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.GET_ONE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildGetOneFunctionName(entityName),
|
||||
buildGetOneFunctionName(bankId, entityName),
|
||||
"GET",
|
||||
s"$resourceDocUrl/$idNameInUrl",
|
||||
s"Get $splitName by id",
|
||||
@ -192,10 +222,10 @@ object DynamicEntityHelper {
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.CREATE, entityName) -> ResourceDoc(
|
||||
resourceDocs += (DynamicEntityOperation.CREATE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildCreateFunctionName(entityName),
|
||||
buildCreateFunctionName(bankId, entityName),
|
||||
"POST",
|
||||
s"$resourceDocUrl",
|
||||
s"Create new $splitName",
|
||||
@ -222,10 +252,10 @@ object DynamicEntityHelper {
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.UPDATE, entityName) -> ResourceDoc(
|
||||
resourceDocs += (DynamicEntityOperation.UPDATE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildUpdateFunctionName(entityName),
|
||||
buildUpdateFunctionName(bankId, entityName),
|
||||
"PUT",
|
||||
s"$resourceDocUrl/$idNameInUrl",
|
||||
s"Update $splitName",
|
||||
@ -252,10 +282,10 @@ object DynamicEntityHelper {
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.DELETE, entityName) -> ResourceDoc(
|
||||
resourceDocs += (DynamicEntityOperation.DELETE, splitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildDeleteFunctionName(entityName),
|
||||
buildDeleteFunctionName(bankId, entityName),
|
||||
"DELETE",
|
||||
s"$resourceDocUrl/$idNameInUrl",
|
||||
s"Delete $splitName by id",
|
||||
@ -279,25 +309,163 @@ object DynamicEntityHelper {
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
if(hasPersonalEntity){ //only hasPersonalEntity == true, then create the myEndpoints
|
||||
resourceDocs += (DynamicEntityOperation.GET_ALL, mySplitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildGetAllFunctionName(bankId, s"My$entityName"),
|
||||
"GET",
|
||||
s"$myResourceDocUrl",
|
||||
s"Get My $splitName List",
|
||||
s"""Get My $splitName List.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|Can do filter on the fields
|
||||
|e.g: /${entityName}?name=James%20Brown&number=123.456&number=11.11
|
||||
|Will do filter by this rule: name == "James Brown" && (number==123.456 || number=11.11)
|
||||
|""".stripMargin,
|
||||
EmptyBody,
|
||||
dynamicEntityInfo.getExampleList,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.GET_ONE, mySplitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildGetOneFunctionName(bankId, s"My$entityName"),
|
||||
"GET",
|
||||
s"$myResourceDocUrl/$idNameInUrl",
|
||||
s"Get My $splitName by id",
|
||||
s"""Get My $splitName by id.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|""".stripMargin,
|
||||
EmptyBody,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.CREATE, mySplitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildCreateFunctionName(bankId, s"My$entityName"),
|
||||
"POST",
|
||||
s"$myResourceDocUrl",
|
||||
s"Create new My $splitName",
|
||||
s"""Create new My $splitName.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
dynamicEntityInfo.getSingleExampleWithoutId,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.UPDATE, mySplitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildUpdateFunctionName(bankId, s"My$entityName"),
|
||||
"PUT",
|
||||
s"$myResourceDocUrl/$idNameInUrl",
|
||||
s"Update My $splitName",
|
||||
s"""Update My $splitName.
|
||||
|${dynamicEntityInfo.description}
|
||||
|
|
||||
|${dynamicEntityInfo.fieldsDescription}
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
dynamicEntityInfo.getSingleExampleWithoutId,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
Some(List(dynamicEntityInfo.canUpdateRole)),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
|
||||
resourceDocs += (DynamicEntityOperation.DELETE, mySplitNameWithBankId) -> ResourceDoc(
|
||||
endPoint,
|
||||
implementedInApiVersion,
|
||||
buildDeleteFunctionName(bankId, s"My$entityName"),
|
||||
"DELETE",
|
||||
s"$myResourceDocUrl/$idNameInUrl",
|
||||
s"Delete My $splitName by id",
|
||||
s"""Delete My $splitName by id
|
||||
|
|
||||
|${methodRoutingExample(entityName)}
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
dynamicEntityInfo.getSingleExampleWithoutId,
|
||||
dynamicEntityInfo.getSingleExample,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic),
|
||||
createdByBankId= dynamicEntityInfo.bankId
|
||||
)
|
||||
}
|
||||
resourceDocs
|
||||
}
|
||||
|
||||
private def buildCreateFunctionName(entityName: String) = s"dynamicEntity_create$entityName"
|
||||
private def buildUpdateFunctionName(entityName: String) = s"dynamicEntity_update$entityName"
|
||||
private def buildDeleteFunctionName(entityName: String) = s"dynamicEntity_delete$entityName"
|
||||
private def buildGetOneFunctionName(entityName: String) = s"dynamicEntity_getSingle$entityName"
|
||||
private def buildGetAllFunctionName(entityName: String) = s"dynamicEntity_get${entityName}List"
|
||||
private def buildCreateFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_create${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildUpdateFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_update${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildDeleteFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_delete${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildGetOneFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_getSingle${entityName}_${bankId.getOrElse("")}"
|
||||
private def buildGetAllFunctionName(bankId:Option[String], entityName: String) = s"dynamicEntity_get${entityName}List_${bankId.getOrElse("")}"
|
||||
|
||||
@inline
|
||||
private def buildOperationId(entityName: String, fun: String => String): String = {
|
||||
APIUtil.buildOperationId(implementedInApiVersion, fun(entityName))
|
||||
private def buildOperationId(bankId:Option[String], entityName: String, fun: (Option[String], String) => String): String = {
|
||||
APIUtil.buildOperationId(implementedInApiVersion, fun(bankId, entityName))
|
||||
}
|
||||
|
||||
def buildCreateOperationId(entityName: String) = buildOperationId(entityName, buildCreateFunctionName)
|
||||
def buildUpdateOperationId(entityName: String) = buildOperationId(entityName, buildUpdateFunctionName)
|
||||
def buildDeleteOperationId(entityName: String) = buildOperationId(entityName, buildDeleteFunctionName)
|
||||
def buildGetOneOperationId(entityName: String) = buildOperationId(entityName, buildGetOneFunctionName)
|
||||
def buildGetAllOperationId(entityName: String) = buildOperationId(entityName, buildGetAllFunctionName)
|
||||
def buildCreateOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildCreateFunctionName)
|
||||
def buildUpdateOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildUpdateFunctionName)
|
||||
def buildDeleteOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildDeleteFunctionName)
|
||||
def buildGetOneOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildGetOneFunctionName)
|
||||
def buildGetAllOperationId(bankId:Option[String], entityName: String) = buildOperationId(bankId, entityName, buildGetAllFunctionName)
|
||||
|
||||
private def methodRoutingExample(entityName: String) =
|
||||
s"""
|
||||
@ -328,7 +496,7 @@ object DynamicEntityHelper {
|
||||
|""".stripMargin
|
||||
|
||||
}
|
||||
case class DynamicEntityInfo(definition: String, entityName: String, bankId: Option[String]) {
|
||||
case class DynamicEntityInfo(definition: String, entityName: String, bankId: Option[String], hasPersonalEntity: Boolean) {
|
||||
|
||||
import net.liftweb.json
|
||||
|
||||
@ -429,10 +597,28 @@ case class DynamicEntityInfo(definition: String, entityName: String, bankId: Opt
|
||||
}
|
||||
|
||||
object DynamicEntityInfo {
|
||||
def canCreateRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanCreateDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canUpdateRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanUpdateDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canGetRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanGetDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canDeleteRole(entityName: String, bankId:Option[String]): ApiRole = getOrCreateDynamicApiRole("CanDeleteDynamicEntity_" + entityName, bankId.isDefined)
|
||||
def canCreateRole(entityName: String, bankId:Option[String]): ApiRole =
|
||||
if(bankId.isDefined)
|
||||
getOrCreateDynamicApiRole("CanCreateDynamicEntity_" + entityName, true)
|
||||
else
|
||||
getOrCreateDynamicApiRole("CanCreateDynamicEntity_System" + entityName, false)
|
||||
def canUpdateRole(entityName: String, bankId:Option[String]): ApiRole =
|
||||
if(bankId.isDefined)
|
||||
getOrCreateDynamicApiRole("CanUpdateDynamicEntity_" + entityName, true)
|
||||
else
|
||||
getOrCreateDynamicApiRole("CanUpdateDynamicEntity_System" + entityName, false)
|
||||
|
||||
def canGetRole(entityName: String, bankId:Option[String]): ApiRole =
|
||||
if(bankId.isDefined)
|
||||
getOrCreateDynamicApiRole("CanGetDynamicEntity_" + entityName, true)
|
||||
else
|
||||
getOrCreateDynamicApiRole("CanGetDynamicEntity_System" + entityName, false)
|
||||
|
||||
def canDeleteRole(entityName: String, bankId:Option[String]): ApiRole =
|
||||
if(bankId.isDefined)
|
||||
getOrCreateDynamicApiRole("CanDeleteDynamicEntity_" + entityName, true)
|
||||
else
|
||||
getOrCreateDynamicApiRole("CanDeleteDynamicEntity_System" + entityName, false)
|
||||
|
||||
def roleNames(entityName: String, bankId:Option[String]): List[String] = List(
|
||||
canCreateRole(entityName, bankId),
|
||||
|
||||
@ -43,7 +43,7 @@ import code.api.UKOpenBanking.v3_1_0.OBP_UKOpenBanking_310
|
||||
import code.api.berlin.group.v1.OBP_BERLIN_GROUP_1
|
||||
import code.api.builder.OBP_APIBuilder
|
||||
import code.api.dynamic.endpoint.OBPAPIDynamicEndpoint
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints, DynamicEntityHelper}
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints}
|
||||
import code.api.oauth1a.Arithmetics
|
||||
import code.api.oauth1a.OauthParams._
|
||||
import code.api.util.APIUtil.ResourceDoc.{findPathVariableNames, isPathVariable}
|
||||
@ -55,6 +55,8 @@ import code.api.v1_2.ErrorMessage
|
||||
import code.api.v2_0_0.CreateEntitlementJSON
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
|
||||
import code.api.dynamic.entity.OBPAPIDynamicEntity
|
||||
import code.api._
|
||||
import code.api.dynamic.entity.helper.DynamicEntityHelper
|
||||
import code.api.v5_0_0.OBPAPI5_0_0
|
||||
import code.api.{DirectLogin, _}
|
||||
import code.authtypevalidation.AuthenticationTypeValidationProvider
|
||||
@ -85,7 +87,7 @@ import dispatch.url
|
||||
import javassist.expr.{ExprEditor, MethodCall}
|
||||
import javassist.{ClassPool, LoaderClassPath}
|
||||
import net.liftweb.actor.LAFuture
|
||||
import net.liftweb.common.{Empty, _}
|
||||
import net.liftweb.common._
|
||||
import net.liftweb.http._
|
||||
import net.liftweb.http.js.JE.JsRaw
|
||||
import net.liftweb.http.provider.HTTPParam
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
package code.api.util
|
||||
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEntityHelper}
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
|
||||
import code.api.dynamic.entity.helper.DynamicEntityHelper
|
||||
import com.openbankproject.commons.util.{JsonAble, ReflectUtils}
|
||||
import net.liftweb.json.{Formats, JsonAST}
|
||||
import net.liftweb.json.JsonDSL._
|
||||
@ -566,23 +567,23 @@ object ApiRole {
|
||||
case class CanDeleteWebUiProps(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canDeleteWebUiProps = CanDeleteWebUiProps()
|
||||
|
||||
case class CanGetDynamicEntities(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canGetDynamicEntities = CanGetDynamicEntities()
|
||||
case class CanGetSystemLevelDynamicEntities(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canGetSystemLevelDynamicEntities = CanGetSystemLevelDynamicEntities()
|
||||
|
||||
case class CanCreateDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canCreateDynamicEntity = CanCreateDynamicEntity()
|
||||
case class CanCreateSystemLevelDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canCreateSystemLevelDynamicEntity = CanCreateSystemLevelDynamicEntity()
|
||||
|
||||
case class CanCreateBankLevelDynamicEntity(requiresBankId: Boolean = true) extends ApiRole
|
||||
lazy val canCreateBankLevelDynamicEntity = CanCreateBankLevelDynamicEntity()
|
||||
|
||||
case class CanUpdateDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canUpdateDynamicEntity = CanUpdateDynamicEntity()
|
||||
case class CanUpdateSystemLevelDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canUpdateSystemDynamicEntity = CanUpdateSystemLevelDynamicEntity()
|
||||
|
||||
case class CanUpdateBankLevelDynamicEntity(requiresBankId: Boolean = true) extends ApiRole
|
||||
lazy val canUpdateBankLevelDynamicEntity = CanUpdateBankLevelDynamicEntity()
|
||||
|
||||
case class CanDeleteDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canDeleteDynamicEntity = CanDeleteDynamicEntity()
|
||||
case class CanDeleteSystemLevelDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canDeleteSystemLevelDynamicEntity = CanDeleteSystemLevelDynamicEntity()
|
||||
|
||||
case class CanDeleteBankLevelDynamicEntity(requiresBankId: Boolean = true) extends ApiRole
|
||||
lazy val canDeleteBankLevelDynamicEntity = CanDeleteBankLevelDynamicEntity()
|
||||
|
||||
@ -63,9 +63,10 @@ import code.validation.{JsonSchemaValidationProvider, JsonValidation}
|
||||
import net.liftweb.http.JsonResponse
|
||||
import net.liftweb.util.Props
|
||||
import code.api.JsonResponseException
|
||||
import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEntityHelper, DynamicEntityInfo}
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
|
||||
import code.api.v4_0_0.JSONFactory400
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
|
||||
import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo}
|
||||
import code.bankattribute.BankAttribute
|
||||
import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod}
|
||||
import code.customeraccountlinks.CustomerAccountLinkTrait
|
||||
@ -3104,7 +3105,7 @@ object NewStyle extends MdcLoggable{
|
||||
else APIUtil.getPropsValue(s"dynamicEntity.cache.ttl.seconds", "30").toInt
|
||||
}
|
||||
|
||||
def getDynamicEntities(bankId: Option[String]): List[DynamicEntityT] = {
|
||||
def getDynamicEntities(bankId: Option[String], returnBothBankAndSystemLevel: Boolean): List[DynamicEntityT] = {
|
||||
import scala.concurrent.duration._
|
||||
|
||||
validateBankId(bankId, None)
|
||||
@ -3112,7 +3113,7 @@ object NewStyle extends MdcLoggable{
|
||||
var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)
|
||||
CacheKeyFromArguments.buildCacheKey {
|
||||
Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(dynamicEntityTTL second) {
|
||||
DynamicEntityProvider.connectorMethodProvider.vend.getDynamicEntities(bankId)
|
||||
DynamicEntityProvider.connectorMethodProvider.vend.getDynamicEntities(bankId, returnBothBankAndSystemLevel)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3161,6 +3162,8 @@ object NewStyle extends MdcLoggable{
|
||||
entityId: Option[String],
|
||||
bankId: Option[String],
|
||||
queryParameters: Option[Map[String, List[String]]],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean,
|
||||
callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = {
|
||||
import DynamicEntityOperation._
|
||||
validateBankId(bankId, callContext)
|
||||
@ -3213,7 +3216,7 @@ object NewStyle extends MdcLoggable{
|
||||
// @(variable-binding pattern), we can use the empty variable
|
||||
// If there is not instance in requestBody, we just call the `dynamicEntityProcess` directly.
|
||||
case empty @None =>
|
||||
Connector.connector.vend.dynamicEntityProcess(operation, entityName, empty, entityId, bankId, queryParameters, callContext)
|
||||
Connector.connector.vend.dynamicEntityProcess(operation, entityName, empty, entityId, bankId, queryParameters, userId, isPersonalEntity, callContext)
|
||||
// @(variable-binding pattern), we can use both v and body variables.
|
||||
case requestBody @Some(body) =>
|
||||
// If the request body is existing, we need to validate the body first.
|
||||
@ -3221,7 +3224,7 @@ object NewStyle extends MdcLoggable{
|
||||
dynamicEntity.validateEntityJson(body, callContext).flatMap {
|
||||
// If there is no error in the request body
|
||||
case None =>
|
||||
Connector.connector.vend.dynamicEntityProcess(operation, entityName, requestBody, entityId, bankId, queryParameters, callContext)
|
||||
Connector.connector.vend.dynamicEntityProcess(operation, entityName, requestBody, entityId, bankId, queryParameters, userId, isPersonalEntity, callContext)
|
||||
// If there are errors, we need to show them to end user.
|
||||
case Some(errorMsg) =>
|
||||
Helper.booleanToFuture(s"$DynamicEntityInstanceValidateFail details: $errorMsg", cc=callContext)(false)
|
||||
|
||||
@ -13,10 +13,11 @@ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{jsonDynamicResourceDoc
|
||||
import code.api.UKOpenBanking.v2_0_0.OBP_UKOpenBanking_200
|
||||
import code.api.UKOpenBanking.v3_1_0.OBP_UKOpenBanking_310
|
||||
import code.api.berlin.group.v1.OBP_BERLIN_GROUP_1
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
|
||||
import code.api.dynamic.endpoint.helper.practise.{DynamicEndpointCodeGenerator, PractiseEndpoint}
|
||||
import code.api.dynamic.endpoint.helper.{CompiledObjects, DynamicEndpointHelper, DynamicEndpoints, DynamicEntityHelper, DynamicEntityInfo}
|
||||
import code.api.dynamic.endpoint.helper.{CompiledObjects, DynamicEndpointHelper, DynamicEndpoints}
|
||||
import code.api.util.APIUtil.{fullBoxOrException, _}
|
||||
import code.api.util.ApiRole.{canCreateEntitlementAtAnyBank, _}
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.DynamicUtil.Validation
|
||||
import code.api.util.ErrorMessages.{BankNotFound, _}
|
||||
@ -41,6 +42,7 @@ import code.api.v3_1_0._
|
||||
import code.api.v4_0_0.JSONFactory400._
|
||||
import code.api.dynamic.endpoint.helper._
|
||||
import code.api.dynamic.endpoint.helper.practise.PractiseEndpoint
|
||||
import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo}
|
||||
import code.api.v5_0_0.OBPAPI5_0_0
|
||||
import code.api.{ChargePolicy, Constant, JsonResponseException}
|
||||
import code.apicollection.MappedApiCollectionsProvider
|
||||
@ -58,7 +60,7 @@ import code.loginattempts.LoginAttempt
|
||||
import code.metadata.counterparties.{Counterparties, MappedCounterparty}
|
||||
import code.metadata.tags.Tags
|
||||
import code.model.dataAccess.{AuthUser, BankAccountCreation}
|
||||
import code.model.{toUserExtended, _}
|
||||
import code.model._
|
||||
import code.ratelimiting.RateLimitingDI
|
||||
import code.scope.Scope
|
||||
import code.snippet.{WebUIPlaceholder, WebUITemplate}
|
||||
@ -1987,13 +1989,13 @@ trait APIMethods400 {
|
||||
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getDynamicEntities,
|
||||
getSystemDynamicEntities,
|
||||
implementedInApiVersion,
|
||||
nameOf(getDynamicEntities),
|
||||
nameOf(getSystemDynamicEntities),
|
||||
"GET",
|
||||
"/management/dynamic-entities",
|
||||
"Get Dynamic Entities",
|
||||
s"""Get the all Dynamic Entities.""",
|
||||
"/management/system-dynamic-entities",
|
||||
"Get System Dynamic Entities",
|
||||
s"""Get all System Dynamic Entities """,
|
||||
EmptyBody,
|
||||
ListResult(
|
||||
"dynamic_entities",
|
||||
@ -2005,15 +2007,14 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canGetDynamicEntities))
|
||||
Some(List(canGetSystemLevelDynamicEntities))
|
||||
)
|
||||
|
||||
|
||||
lazy val getDynamicEntities: OBPEndpoint = {
|
||||
case "management" :: "dynamic-entities" :: Nil JsonGet req => {
|
||||
lazy val getSystemDynamicEntities: OBPEndpoint = {
|
||||
case "management" :: "system-dynamic-entities" :: Nil JsonGet req => {
|
||||
cc =>
|
||||
for {
|
||||
dynamicEntities <- Future(NewStyle.function.getDynamicEntities(None))
|
||||
dynamicEntities <- Future(NewStyle.function.getDynamicEntities(None, false))
|
||||
} yield {
|
||||
val listCommons: List[DynamicEntityCommons] = dynamicEntities
|
||||
val jObjects = listCommons.map(_.jValue)
|
||||
@ -2042,14 +2043,14 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canGetBankLevelDynamicEntities, canGetDynamicEntities))
|
||||
Some(List(canGetBankLevelDynamicEntities))
|
||||
)
|
||||
|
||||
lazy val getBankLevelDynamicEntities: OBPEndpoint = {
|
||||
case "management" :: "banks" :: bankId :: "dynamic-entities" :: Nil JsonGet req => {
|
||||
cc =>
|
||||
for {
|
||||
dynamicEntities <- Future(NewStyle.function.getDynamicEntities(Some(bankId)))
|
||||
dynamicEntities <- Future(NewStyle.function.getDynamicEntities(Some(bankId),false))
|
||||
} yield {
|
||||
val listCommons: List[DynamicEntityCommons] = dynamicEntities
|
||||
val jObjects = listCommons.map(_.jValue)
|
||||
@ -2076,13 +2077,13 @@ trait APIMethods400 {
|
||||
}
|
||||
|
||||
private def createDynamicEntityDoc = ResourceDoc(
|
||||
createDynamicEntity,
|
||||
createSystemDynamicEntity,
|
||||
implementedInApiVersion,
|
||||
nameOf(createDynamicEntity),
|
||||
nameOf(createSystemDynamicEntity),
|
||||
"POST",
|
||||
"/management/dynamic-entities",
|
||||
"Create Dynamic Entity",
|
||||
s"""Create a DynamicEntity.
|
||||
"/management/system-dynamic-entities",
|
||||
"Create System Level Dynamic Entity",
|
||||
s"""Create a system level Dynamic Entity.
|
||||
|
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
@ -2099,12 +2100,11 @@ trait APIMethods400 {
|
||||
|```
|
||||
|${ReferenceType.referenceTypeAndExample.mkString("\n")}
|
||||
|```
|
||||
| Note: BankId filed is optional,
|
||||
| if you add it, the entity will be the Bank level.
|
||||
| if you omit it, the entity will be the System level.
|
||||
|
|
||||
|Note: if you set `hasPersonalEntity` = false, then OBP will not generate the CRUD my FooBar endpoints.
|
||||
|""",
|
||||
dynamicEntityRequestBodyExample,
|
||||
dynamicEntityResponseBodyExample,
|
||||
dynamicEntityRequestBodyExample.copy(bankId = None),
|
||||
dynamicEntityResponseBodyExample.copy(bankId = None),
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
@ -2112,12 +2112,12 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canCreateDynamicEntity)))
|
||||
Some(List(canCreateSystemLevelDynamicEntity)))
|
||||
|
||||
lazy val createDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "dynamic-entities" :: Nil JsonPost json -> _ => {
|
||||
lazy val createSystemDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "system-dynamic-entities" :: Nil JsonPost json -> _ => {
|
||||
cc =>
|
||||
val dynamicEntity = DynamicEntityCommons(json.asInstanceOf[JObject], None, cc.userId)
|
||||
val dynamicEntity = DynamicEntityCommons(json.asInstanceOf[JObject], None, cc.userId, None)
|
||||
createDynamicEntityMethod(cc, dynamicEntity)
|
||||
}
|
||||
}
|
||||
@ -2145,9 +2145,7 @@ trait APIMethods400 {
|
||||
|```
|
||||
|${ReferenceType.referenceTypeAndExample.mkString("\n")}
|
||||
|```
|
||||
| Note: BankId filed is optional,
|
||||
| if you add it, the entity will be the Bank level.
|
||||
| if you omit it, the entity will be the System level.
|
||||
| Note: if you set `hasPersonalEntity` = false, then OBP will not generate the CRUD my FooBar endpoints.
|
||||
|""",
|
||||
dynamicEntityRequestBodyExample.copy(bankId = None),
|
||||
dynamicEntityResponseBodyExample,
|
||||
@ -2159,11 +2157,11 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canCreateBankLevelDynamicEntity, canCreateDynamicEntity)))
|
||||
Some(List(canCreateBankLevelDynamicEntity)))
|
||||
lazy val createBankLevelDynamicEntity: OBPEndpoint = {
|
||||
case "management" ::"banks" :: BankId(bankId) :: "dynamic-entities" :: Nil JsonPost json -> _ => {
|
||||
cc =>
|
||||
val dynamicEntity = DynamicEntityCommons(json.asInstanceOf[JObject], None, cc.userId).copy(bankId = Some(bankId.value))
|
||||
val dynamicEntity = DynamicEntityCommons(json.asInstanceOf[JObject], None, cc.userId, Some(bankId.value))
|
||||
createDynamicEntityMethod(cc, dynamicEntity)
|
||||
}
|
||||
}
|
||||
@ -2173,14 +2171,14 @@ trait APIMethods400 {
|
||||
for {
|
||||
// Check whether there are uploaded data, only if no uploaded data allow to update DynamicEntity.
|
||||
(entity, _) <- NewStyle.function.getDynamicEntityById(bankId, dynamicEntityId, cc.callContext)
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entity.entityName, None, None, entity.bankId, None, cc.callContext)
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entity.entityName, None, None, entity.bankId, None, None, false, cc.callContext)
|
||||
resultList: JArray = unboxResult(box.asInstanceOf[Box[JArray]], entity.entityName)
|
||||
_ <- Helper.booleanToFuture(DynamicEntityOperationNotAllowed, cc = cc.callContext) {
|
||||
resultList.arr.isEmpty
|
||||
}
|
||||
|
||||
jsonObject = json.asInstanceOf[JObject]
|
||||
dynamicEntity = DynamicEntityCommons(jsonObject, Some(dynamicEntityId), cc.userId).copy(bankId = bankId)
|
||||
dynamicEntity = DynamicEntityCommons(jsonObject, Some(dynamicEntityId), cc.userId, bankId)
|
||||
Full(result) <- NewStyle.function.createOrUpdateDynamicEntity(dynamicEntity, cc.callContext)
|
||||
} yield {
|
||||
val commonsData: DynamicEntityCommons = result
|
||||
@ -2190,13 +2188,13 @@ trait APIMethods400 {
|
||||
|
||||
|
||||
private def updateDynamicEntityDoc = ResourceDoc(
|
||||
updateDynamicEntity,
|
||||
updateSystemDynamicEntity,
|
||||
implementedInApiVersion,
|
||||
nameOf(updateDynamicEntity),
|
||||
nameOf(updateSystemDynamicEntity),
|
||||
"PUT",
|
||||
"/management/dynamic-entities/DYNAMIC_ENTITY_ID",
|
||||
"Update Dynamic Entity",
|
||||
s"""Update a DynamicEntity.
|
||||
"/management/system-dynamic-entities/DYNAMIC_ENTITY_ID",
|
||||
"Update System Level Dynamic Entity",
|
||||
s"""Update a System Level Dynamic Entity.
|
||||
|
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
@ -2215,17 +2213,18 @@ trait APIMethods400 {
|
||||
|```
|
||||
|""",
|
||||
dynamicEntityRequestBodyExample.copy(bankId = None),
|
||||
dynamicEntityResponseBodyExample,
|
||||
dynamicEntityResponseBodyExample.copy(bankId= None),
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
DynamicEntityNotFoundByDynamicEntityId,
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canUpdateDynamicEntity)))
|
||||
lazy val updateDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "dynamic-entities" :: dynamicEntityId :: Nil JsonPut json -> _ => {
|
||||
Some(List(canUpdateSystemDynamicEntity)))
|
||||
lazy val updateSystemDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "system-dynamic-entities" :: dynamicEntityId :: Nil JsonPut json -> _ => {
|
||||
cc =>
|
||||
updateDynamicEntityMethod(None, dynamicEntityId, json, cc)
|
||||
}
|
||||
@ -2266,7 +2265,7 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canUpdateBankLevelDynamicEntity, canUpdateDynamicEntity)))
|
||||
Some(List(canUpdateBankLevelDynamicEntity)))
|
||||
lazy val updateBankLevelDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "banks" :: bankId :: "dynamic-entities" :: dynamicEntityId :: Nil JsonPut json -> _ => {
|
||||
cc =>
|
||||
@ -2275,12 +2274,12 @@ trait APIMethods400 {
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
deleteDynamicEntity,
|
||||
deleteSystemDynamicEntity,
|
||||
implementedInApiVersion,
|
||||
nameOf(deleteDynamicEntity),
|
||||
nameOf(deleteSystemDynamicEntity),
|
||||
"DELETE",
|
||||
"/management/dynamic-entities/DYNAMIC_ENTITY_ID",
|
||||
"Delete Dynamic Entity",
|
||||
"/management/system-dynamic-entities/DYNAMIC_ENTITY_ID",
|
||||
"Delete System Level Dynamic Entity",
|
||||
s"""Delete a DynamicEntity specified by DYNAMIC_ENTITY_ID.
|
||||
|
|
||||
|""",
|
||||
@ -2292,9 +2291,9 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canDeleteDynamicEntity)))
|
||||
lazy val deleteDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "dynamic-entities" :: dynamicEntityId :: Nil JsonDelete _ => {
|
||||
Some(List(canDeleteSystemLevelDynamicEntity)))
|
||||
lazy val deleteSystemDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "system-dynamic-entities" :: dynamicEntityId :: Nil JsonDelete _ => {
|
||||
cc =>
|
||||
deleteDynamicEntityMethod(None, dynamicEntityId, cc)
|
||||
}
|
||||
@ -2304,14 +2303,14 @@ trait APIMethods400 {
|
||||
for {
|
||||
// Check whether there are uploaded data, only if no uploaded data allow to delete DynamicEntity.
|
||||
(entity, _) <- NewStyle.function.getDynamicEntityById(bankId, dynamicEntityId, cc.callContext)
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entity.entityName, None, None, entity.bankId, None, cc.callContext)
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entity.entityName, None, None, entity.bankId, None, None, false, cc.callContext)
|
||||
resultList: JArray = unboxResult(box.asInstanceOf[Box[JArray]], entity.entityName)
|
||||
_ <- Helper.booleanToFuture(DynamicEntityOperationNotAllowed, cc = cc.callContext) {
|
||||
resultList.arr.isEmpty
|
||||
}
|
||||
deleted: Box[Boolean] <- NewStyle.function.deleteDynamicEntity(bankId, dynamicEntityId)
|
||||
} yield {
|
||||
(deleted, HttpCode.`204`(cc.callContext))
|
||||
(deleted, HttpCode.`200`(cc.callContext))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2334,7 +2333,7 @@ trait APIMethods400 {
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle),
|
||||
Some(List(canDeleteBankLevelDynamicEntity, canDeleteDynamicEntity)))
|
||||
Some(List(canDeleteBankLevelDynamicEntity)))
|
||||
lazy val deleteBankLevelDynamicEntity: OBPEndpoint = {
|
||||
case "management" :: "banks" :: bankId :: "dynamic-entities" :: dynamicEntityId :: Nil JsonDelete _ => {
|
||||
cc =>
|
||||
@ -2405,6 +2404,7 @@ trait APIMethods400 {
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
InvalidJsonFormat,
|
||||
DynamicEntityNotFoundByDynamicEntityId,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagManageDynamicEntity, apiTagApi, apiTagNewStyle)
|
||||
@ -2414,18 +2414,19 @@ trait APIMethods400 {
|
||||
case "my" :: "dynamic-entities" :: dynamicEntityId :: Nil JsonPut json -> _ => {
|
||||
cc =>
|
||||
for {
|
||||
// Check whether there are uploaded data, only if no uploaded data allow to update DynamicEntity.
|
||||
(entity, _) <- NewStyle.function.getDynamicEntityById(None, dynamicEntityId, cc.callContext)
|
||||
_ <- Helper.booleanToFuture(InvalidMyDynamicEntityUser, cc=cc.callContext) {
|
||||
entity.userId.equals(cc.userId)
|
||||
dynamicEntities <- Future(NewStyle.function.getDynamicEntitiesByUserId(cc.userId))
|
||||
entityOption = dynamicEntities.find(_.dynamicEntityId.equals(Some(dynamicEntityId)))
|
||||
myEntity <- NewStyle.function.tryons(InvalidMyDynamicEntityUser, 400, cc.callContext) {
|
||||
entityOption.get
|
||||
}
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entity.entityName, None, None, entity.bankId, None, cc.callContext)
|
||||
resultList: JArray = unboxResult(box.asInstanceOf[Box[JArray]], entity.entityName)
|
||||
// Check whether there are uploaded data, only if no uploaded data allow to update DynamicEntity.
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, myEntity.entityName, None, myEntity.dynamicEntityId, myEntity.bankId, None, Some(myEntity.userId), false, cc.callContext)
|
||||
resultList: JArray = unboxResult(box.asInstanceOf[Box[JArray]], myEntity.entityName)
|
||||
_ <- Helper.booleanToFuture(DynamicEntityOperationNotAllowed, cc=cc.callContext) {
|
||||
resultList.arr.isEmpty
|
||||
}
|
||||
jsonObject = json.asInstanceOf[JObject]
|
||||
dynamicEntity = DynamicEntityCommons(jsonObject, Some(dynamicEntityId), cc.userId)
|
||||
dynamicEntity = DynamicEntityCommons(jsonObject, Some(dynamicEntityId), cc.userId, myEntity.bankId)
|
||||
Full(result) <- NewStyle.function.createOrUpdateDynamicEntity(dynamicEntity, cc.callContext)
|
||||
} yield {
|
||||
val commonsData: DynamicEntityCommons = result
|
||||
@ -2457,17 +2458,18 @@ trait APIMethods400 {
|
||||
case "my" :: "dynamic-entities" :: dynamicEntityId :: Nil JsonDelete _ => {
|
||||
cc =>
|
||||
for {
|
||||
// Check whether there are uploaded data, only if no uploaded data allow to delete DynamicEntity.
|
||||
(entity, _) <- NewStyle.function.getDynamicEntityById(None, dynamicEntityId, cc.callContext)
|
||||
_ <- Helper.booleanToFuture(InvalidMyDynamicEntityUser, cc=cc.callContext) {
|
||||
entity.userId.equals(cc.userId)
|
||||
dynamicEntities <- Future(NewStyle.function.getDynamicEntitiesByUserId(cc.userId))
|
||||
entityOption = dynamicEntities.find(_.dynamicEntityId.equals(Some(dynamicEntityId)))
|
||||
myEntity <- NewStyle.function.tryons(InvalidMyDynamicEntityUser, 400, cc.callContext) {
|
||||
entityOption.get
|
||||
}
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, entity.entityName, None, None, entity.bankId, None, cc.callContext)
|
||||
resultList: JArray = unboxResult(box.asInstanceOf[Box[JArray]], entity.entityName)
|
||||
// Check whether there are uploaded data, only if no uploaded data allow to delete DynamicEntity.
|
||||
(box, _) <- NewStyle.function.invokeDynamicConnector(GET_ALL, myEntity.entityName, None, myEntity.dynamicEntityId, myEntity.bankId, None, Some(myEntity.userId), false, cc.callContext)
|
||||
resultList: JArray = unboxResult(box.asInstanceOf[Box[JArray]], myEntity.entityName)
|
||||
_ <- Helper.booleanToFuture(DynamicEntityOperationNotAllowed, cc=cc.callContext) {
|
||||
resultList.arr.isEmpty
|
||||
}
|
||||
deleted: Box[Boolean] <- NewStyle.function.deleteDynamicEntity(None, dynamicEntityId)
|
||||
deleted: Box[Boolean] <- NewStyle.function.deleteDynamicEntity(myEntity.bankId, dynamicEntityId)
|
||||
} yield {
|
||||
(deleted, HttpCode.`200`(cc.callContext))
|
||||
}
|
||||
|
||||
@ -2534,6 +2534,8 @@ trait Connector extends MdcLoggable {
|
||||
entityId: Option[String],
|
||||
bankId: Option[String],
|
||||
queryParameters: Option[Map[String, List[String]]],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean,
|
||||
callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = Future{(Failure(setUnimplementedError), callContext)}
|
||||
|
||||
def dynamicEndpointProcess(url: String, jValue: JValue, method: HttpMethod, params: Map[String, List[String]], pathParams: Map[String, String],
|
||||
|
||||
@ -4420,35 +4420,37 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
entityId: Option[String],
|
||||
bankId: Option[String],
|
||||
queryParameters: Option[Map[String, List[String]]],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean,
|
||||
callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = {
|
||||
|
||||
Future {
|
||||
val processResult: Box[JValue] = operation.asInstanceOf[Any] match {
|
||||
case GET_ALL => Full {
|
||||
val dataList = DynamicDataProvider.connectorMethodProvider.vend.getAllDataJson(bankId, entityName)
|
||||
val dataList = DynamicDataProvider.connectorMethodProvider.vend.getAllDataJson(bankId, entityName, userId, isPersonalEntity)
|
||||
JArray(dataList)
|
||||
}
|
||||
case GET_ONE => {
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend
|
||||
.get(bankId, entityName, entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required.")))
|
||||
.get(bankId, entityName, entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required.")),userId, isPersonalEntity)
|
||||
.map(it => json.parse(it.dataJson))
|
||||
boxedEntity
|
||||
}
|
||||
case CREATE => {
|
||||
val body = requestBody.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument please supply the requestBody."))
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend.save(bankId, entityName, body)
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend.save(bankId, entityName, body, userId, isPersonalEntity)
|
||||
.map(it => json.parse(it.dataJson))
|
||||
boxedEntity
|
||||
}
|
||||
case UPDATE => {
|
||||
val body = requestBody.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument please supply the requestBody."))
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend.update(bankId, entityName, body, entityId.get)
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend.update(bankId, entityName, body, entityId.get, userId, isPersonalEntity)
|
||||
.map(it => json.parse(it.dataJson))
|
||||
boxedEntity
|
||||
}
|
||||
case DELETE => {
|
||||
val id = entityId.getOrElse(throw new RuntimeException(s"$DynamicEntityMissArgument the entityId is required. "))
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend.delete(bankId, entityName, id)
|
||||
val boxedEntity: Box[JValue] = DynamicDataProvider.connectorMethodProvider.vend.delete(bankId, entityName, id, userId, isPersonalEntity)
|
||||
.map(it => JBool(it))
|
||||
boxedEntity
|
||||
}
|
||||
|
||||
@ -6487,10 +6487,12 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
entityId: Option[String],
|
||||
bankId: Option[String],
|
||||
queryParameters: Option[Map[String, List[String]]],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean,
|
||||
callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = {
|
||||
import com.openbankproject.commons.dto.{OutBoundDynamicEntityProcess => OutBound, InBoundDynamicEntityProcess => InBound}
|
||||
val url = getUrl(callContext, "dynamicEntityProcess")
|
||||
val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , operation, entityName, requestBody, entityId, bankId, queryParameters)
|
||||
val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , operation, entityName, requestBody, entityId, bankId, queryParameters, userId, isPersonalEntity)
|
||||
val result: OBPReturnType[Box[JValue]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext))
|
||||
result
|
||||
}
|
||||
|
||||
@ -6470,10 +6470,12 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable {
|
||||
entityId: Option[String],
|
||||
bankId: Option[String],
|
||||
queryParameters: Option[Map[String, List[String]]],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean,
|
||||
callContext: Option[CallContext]): OBPReturnType[Box[JValue]] = {
|
||||
import com.openbankproject.commons.dto.{InBoundDynamicEntityProcess => InBound, OutBoundDynamicEntityProcess => OutBound}
|
||||
val procedureName = StringHelpers.snakify("dynamicEntityProcess")
|
||||
val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , operation, entityName, requestBody, entityId, bankId, queryParameters)
|
||||
val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , operation, entityName, requestBody, entityId, bankId, queryParameters,userId, isPersonalEntity)
|
||||
val result: OBPReturnType[Box[JValue]] = sendRequest[InBound](procedureName, req, callContext).map(convertToTuple(callContext))
|
||||
result
|
||||
}
|
||||
|
||||
@ -17,25 +17,29 @@ trait DynamicDataT {
|
||||
def dynamicEntityName: String
|
||||
def dataJson: String
|
||||
def bankId: Option[String]
|
||||
def userId: Option[String]
|
||||
def isPersonalEntity: Boolean
|
||||
}
|
||||
|
||||
case class DynamicDataCommons(dynamicEntityName: String,
|
||||
dataJson: String,
|
||||
dynamicDataId: Option[String] = None,
|
||||
bankId: Option[String]
|
||||
bankId: Option[String],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean
|
||||
) extends DynamicDataT with JsonFieldReName
|
||||
|
||||
object DynamicDataCommons extends Converter[DynamicDataT, DynamicDataCommons]
|
||||
|
||||
|
||||
trait DynamicDataProvider {
|
||||
def save(bankId: Option[String], entityName: String, requestBody: JObject): Box[DynamicDataT]
|
||||
def update(bankId: Option[String], entityName: String, requestBody: JObject, id: String): Box[DynamicDataT]
|
||||
def get(bankId: Option[String], entityName: String, id: String): Box[DynamicDataT]
|
||||
def getAllDataJson(bankId: Option[String], entityName: String): List[JObject]
|
||||
def getAll(bankId: Option[String], entityName: String): List[DynamicDataT]
|
||||
def delete(bankId: Option[String], entityName: String, id: String): Box[Boolean]
|
||||
def existsData(dbankId: Option[String], ynamicEntityName: String): Boolean
|
||||
def save(bankId: Option[String], entityName: String, requestBody: JObject, userId: Option[String], isPersonalEntity: Boolean): Box[DynamicDataT]
|
||||
def update(bankId: Option[String], entityName: String, requestBody: JObject, id: String, userId: Option[String], isPersonalEntity: Boolean): Box[DynamicDataT]
|
||||
def get(bankId: Option[String], entityName: String, id: String, userId: Option[String], isPersonalEntity: Boolean): Box[DynamicDataT]
|
||||
def getAllDataJson(bankId: Option[String], entityName: String, userId: Option[String], isPersonalEntity: Boolean): List[JObject]
|
||||
def getAll(bankId: Option[String], entityName: String, userId: Option[String], isPersonalEntity: Boolean): List[DynamicDataT]
|
||||
def delete(bankId: Option[String], entityName: String, id: String, userId: Option[String], isPersonalEntity: Boolean): Box[Boolean]
|
||||
def existsData(bankId: Option[String], dynamicEntityName: String, userId: Option[String], isPersonalEntity: Boolean): Boolean
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ trait DynamicEntityT {
|
||||
* @return
|
||||
*/
|
||||
def userId: String
|
||||
def hasPersonalEntity: Boolean
|
||||
|
||||
/**
|
||||
* Add Option(bank_id) to Dynamic Entity.
|
||||
@ -287,7 +288,7 @@ object ReferenceType {
|
||||
)
|
||||
|
||||
def referenceTypeNames: List[String] = {
|
||||
val dynamicRefs: List[String] = NewStyle.function.getDynamicEntities(None)
|
||||
val dynamicRefs: List[String] = NewStyle.function.getDynamicEntities(None, true)
|
||||
.map(entity => s"reference:${entity.entityName}")
|
||||
|
||||
val staticRefs: List[String] = staticRefTypeToValidateFunction.keys.toList
|
||||
@ -347,7 +348,7 @@ object ReferenceType {
|
||||
} else {
|
||||
val dynamicEntityName = typeName.replace("reference:", "")
|
||||
val errorMsg = s"""$dynamicEntityName not found by the id value '$value', propertyName is '$propertyName'"""
|
||||
NewStyle.function.invokeDynamicConnector(DynamicEntityOperation.GET_ONE,dynamicEntityName, None, Some(value), None, None, callContext)
|
||||
NewStyle.function.invokeDynamicConnector(DynamicEntityOperation.GET_ONE,dynamicEntityName, None, Some(value), None, None, None, false,callContext)
|
||||
.recover {
|
||||
case _: Throwable => errorMsg
|
||||
}
|
||||
@ -363,7 +364,8 @@ case class DynamicEntityCommons(entityName: String,
|
||||
metadataJson: String,
|
||||
dynamicEntityId: Option[String] = None,
|
||||
userId: String,
|
||||
bankId: Option[String]
|
||||
bankId: Option[String] ,
|
||||
hasPersonalEntity: Boolean
|
||||
) extends DynamicEntityT with JsonFieldReName
|
||||
|
||||
object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommons] {
|
||||
@ -374,7 +376,6 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
|
||||
* @param jsonObject the follow schema json:
|
||||
* {{{
|
||||
* {
|
||||
* "BankId": "gh.29.uk",
|
||||
* "FooBar": {
|
||||
* "description": "description of this entity, can be markdown text.",
|
||||
* "required": [
|
||||
@ -400,7 +401,7 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
|
||||
* @param dynamicEntityId
|
||||
* @return object of DynamicEntityCommons
|
||||
*/
|
||||
def apply(jsonObject: JObject, dynamicEntityId: Option[String], userId: String): DynamicEntityCommons = {
|
||||
def apply(jsonObject: JObject, dynamicEntityId: Option[String], userId: String, bankId: Option[String]): DynamicEntityCommons = {
|
||||
|
||||
def checkFormat(requirement: Boolean, message: String) = {
|
||||
if (!requirement) throw new IllegalArgumentException(message)
|
||||
@ -410,11 +411,11 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
|
||||
|
||||
// validate whether json is object and have a single field, currently support one entity definition
|
||||
checkFormat(fields.nonEmpty, s"$DynamicEntityInstanceValidateFail The Json root object should have a single entity, but current have none.")
|
||||
checkFormat(fields.size <= 2, s"$DynamicEntityInstanceValidateFail The Json root object should at most two fields: entity and BankId, but current entityNames: ${fields.map(_.name).mkString(", ")}")
|
||||
|
||||
val bankId: Option[String] = fields.filter(_.name=="bankId").map(_.value.asInstanceOf[JString].values).headOption
|
||||
checkFormat(fields.size <= 2, s"$DynamicEntityInstanceValidateFail The Json root object should at most two fields: entity and hasPersonalEntity, but current entityNames: ${fields.map(_.name).mkString(", ")}")
|
||||
|
||||
val JField(entityName, metadataJson) = fields.filter(_.name!="bankId").head
|
||||
val hasPersonalEntity: Boolean = fields.filter(_.name=="hasPersonalEntity").map(_.value.asInstanceOf[JBool].values).headOption.getOrElse(true)
|
||||
|
||||
val JField(entityName, metadataJson) = fields.filter(_.name!="hasPersonalEntity").head
|
||||
|
||||
val namePattern = "[-_A-Za-z0-9]+".r.pattern
|
||||
// validate entity name
|
||||
@ -519,7 +520,7 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
|
||||
}
|
||||
})
|
||||
|
||||
DynamicEntityCommons(entityName, compactRender(jsonObject), dynamicEntityId, userId, bankId)
|
||||
DynamicEntityCommons(entityName, compactRender(jsonObject), dynamicEntityId, userId, bankId, hasPersonalEntity)
|
||||
}
|
||||
|
||||
private def allowedFieldType: List[String] = DynamicEntityFieldType.values.map(_.toString) ++: ReferenceType.referenceTypeNames
|
||||
@ -529,7 +530,7 @@ object DynamicEntityCommons extends Converter[DynamicEntityT, DynamicEntityCommo
|
||||
* example case classes, as an example schema of DynamicEntity, for request body example usage
|
||||
* @param FooBar
|
||||
*/
|
||||
case class DynamicEntityFooBar(bankId: Option[String], FooBar: DynamicEntityDefinition, dynamicEntityId: Option[String] = None, userId: Option[String] = None)
|
||||
case class DynamicEntityFooBar(bankId: Option[String], FooBar: DynamicEntityDefinition, dynamicEntityId: Option[String] = None, userId: Option[String] = None, hasPersonalEntity:Boolean = true)
|
||||
case class DynamicEntityDefinition(description: String, required: List[String],properties: DynamicEntityFullBarFields)
|
||||
case class DynamicEntityFullBarFields(name: DynamicEntityStringTypeExample, number: DynamicEntityIntTypeExample)
|
||||
case class DynamicEntityStringTypeExample(`type`: DynamicEntityFieldType, minLength: Int, maxLength: Int, example: String, description: String)
|
||||
@ -544,7 +545,7 @@ trait DynamicEntityProvider {
|
||||
// so --> here can not use bankId as parameters:
|
||||
def getByEntityName(bankId: Option[String], entityName: String): Box[DynamicEntityT]
|
||||
|
||||
def getDynamicEntities(bankId: Option[String]): List[DynamicEntityT]
|
||||
def getDynamicEntities(bankId: Option[String], returnBothBankAndSystemLevel: Boolean): List[DynamicEntityT]
|
||||
|
||||
def getDynamicEntitiesByUserId(userId: String): List[DynamicEntity]
|
||||
|
||||
|
||||
@ -13,104 +13,148 @@ import net.liftweb.util.Helpers.tryo
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
object MappedDynamicDataProvider extends DynamicDataProvider with CustomJsonFormats{
|
||||
override def save(bankId: Option[String], entityName: String, requestBody: JObject): Box[DynamicDataT] = {
|
||||
override def save(bankId: Option[String], entityName: String, requestBody: JObject, userId: Option[String], isPersonalEntity: Boolean): Box[DynamicDataT] = {
|
||||
val idName = getIdName(entityName)
|
||||
val JString(idValue) = (requestBody \ idName).asInstanceOf[JString]
|
||||
val dynamicData: DynamicData = DynamicData.create.DynamicDataId(idValue)
|
||||
val result = saveOrUpdate(bankId, entityName, requestBody, dynamicData)
|
||||
val result = saveOrUpdate(bankId, entityName, requestBody, userId, isPersonalEntity, dynamicData)
|
||||
result
|
||||
}
|
||||
override def update(bankId: Option[String], entityName: String, requestBody: JObject, id: String): Box[DynamicDataT] = {
|
||||
val dynamicData = get(bankId, entityName, id).openOrThrowException(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynameicDataId=$id").asInstanceOf[DynamicData]
|
||||
saveOrUpdate(bankId, entityName, requestBody, dynamicData)
|
||||
override def update(bankId: Option[String], entityName: String, requestBody: JObject, id: String, userId: Option[String], isPersonalEntity: Boolean): Box[DynamicDataT] = {
|
||||
val dynamicData = get(bankId, entityName, id, userId, isPersonalEntity).openOrThrowException(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynamicDataId=$id").asInstanceOf[DynamicData]
|
||||
saveOrUpdate(bankId, entityName, requestBody, userId, isPersonalEntity, dynamicData)
|
||||
}
|
||||
|
||||
override def get(bankId: Option[String],entityName: String, id: String): Box[DynamicDataT] = {
|
||||
if(bankId.isEmpty){
|
||||
override def get(bankId: Option[String],entityName: String, id: String, userId: Option[String], isPersonalEntity: Boolean): Box[DynamicDataT] = {
|
||||
if(bankId.isEmpty && !isPersonalEntity ){ //isPersonalEntity == false, get all the data, no need for specific userId.
|
||||
//forced the empty also to a error here. this is get Dynamic by Id, if it return Empty, better show the error in this level.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicDataId, id),
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
NullRef(DynamicData.BankId),
|
||||
By(DynamicData.UserId, userId.getOrElse(null)),
|
||||
By(DynamicData.IsPersonalEntity, false),
|
||||
NullRef(DynamicData.BankId)
|
||||
) match {
|
||||
case Full(dynamicData) => Full(dynamicData)
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynameicDataId=$id")
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynamicDataId=$id")
|
||||
}
|
||||
} else{
|
||||
} else if(bankId.isEmpty && isPersonalEntity){ //isPersonalEntity == true, get all the data for specific userId.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicDataId, id),
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.UserId, userId.getOrElse(null)),
|
||||
By(DynamicData.IsPersonalEntity, true),
|
||||
NullRef(DynamicData.BankId)
|
||||
) match {
|
||||
case Full(dynamicData) => Full(dynamicData)
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynamicDataId=$id, userId = $userId")
|
||||
}
|
||||
} else if(bankId.isDefined && !isPersonalEntity ){ //isPersonalEntity == false, get all the data, no need for specific userId.
|
||||
//forced the empty also to a error here. this is get Dynamic by Id, if it return Empty, better show the error in this level.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicDataId, id),
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.BankId, bankId.get)
|
||||
By(DynamicData.IsPersonalEntity, false),
|
||||
By(DynamicData.BankId, bankId.get),
|
||||
) match {
|
||||
case Full(dynamicData) => Full(dynamicData)
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynameicDataId=$id")
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynamicDataId=$id, bankId= ${bankId.get}")
|
||||
}
|
||||
}else{ //isPersonalEntity == true, get all the data for specific userId.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicDataId, id),
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.BankId, bankId.get),
|
||||
By(DynamicData.UserId, userId.get),
|
||||
By(DynamicData.IsPersonalEntity, true)
|
||||
) match {
|
||||
case Full(dynamicData) => Full(dynamicData)
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynamicDataId=$id, bankId= ${bankId.get}, userId = ${userId.get}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override def getAllDataJson(bankId: Option[String], entityName: String): List[JObject] = {
|
||||
if(bankId.isEmpty){
|
||||
DynamicData.findAll(
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
NullRef(DynamicData.BankId)
|
||||
).map(it => json.parse(it.dataJson)).map(_.asInstanceOf[JObject])
|
||||
} else {
|
||||
DynamicData.findAll(
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.BankId, bankId.get)
|
||||
).map(it => json.parse(it.dataJson)).map(_.asInstanceOf[JObject])
|
||||
}
|
||||
override def getAllDataJson(bankId: Option[String], entityName: String, userId: Option[String], isPersonalEntity: Boolean): List[JObject] = {
|
||||
getAll(bankId: Option[String], entityName: String, userId: Option[String], isPersonalEntity)
|
||||
.map(it => json.parse(it.dataJson))
|
||||
.map(_.asInstanceOf[JObject])
|
||||
}
|
||||
|
||||
override def getAll(bankId: Option[String], entityName: String): List[DynamicDataT] = {
|
||||
if(bankId.isEmpty) {
|
||||
override def getAll(bankId: Option[String], entityName: String, userId: Option[String], isPersonalEntity: Boolean): List[DynamicDataT] = {
|
||||
if(bankId.isEmpty && !isPersonalEntity){ //isPersonalEntity == false, get all the data, no need for specific userId.
|
||||
DynamicData.findAll(
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.IsPersonalEntity, false),
|
||||
NullRef(DynamicData.BankId),
|
||||
)
|
||||
} else if(bankId.isEmpty && isPersonalEntity){ //isPersonalEntity == true, get all the data for specific userId.
|
||||
DynamicData.findAll(
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.UserId, userId.getOrElse(null)),
|
||||
By(DynamicData.IsPersonalEntity, true),
|
||||
NullRef(DynamicData.BankId)
|
||||
)
|
||||
} else if(bankId.isDefined && !isPersonalEntity){ //isPersonalEntity == false, get all the data, no need for specific userId.
|
||||
DynamicData.findAll(
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.IsPersonalEntity, false),
|
||||
By(DynamicData.BankId, bankId.get),
|
||||
)
|
||||
}else{
|
||||
DynamicData.findAll(
|
||||
DynamicData.findAll(//isPersonalEntity == true, get all the data for specific userId.
|
||||
By(DynamicData.DynamicEntityName, entityName),
|
||||
By(DynamicData.BankId, bankId.get)
|
||||
By(DynamicData.BankId, bankId.get),
|
||||
By(DynamicData.UserId, userId.getOrElse(null)),
|
||||
By(DynamicData.IsPersonalEntity, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override def delete(bankId: Option[String], entityName: String, id: String) = {
|
||||
//forced the empty also to a error here. this is get Dynamic by Id, if it return Empty, better show the error in this level.
|
||||
//Note: DynamicDataId is UniqueIndex
|
||||
DynamicData.find(By(DynamicData.DynamicDataId, id), By(DynamicData.DynamicEntityName, entityName)) match {
|
||||
case Full(dynamicData) => Full(dynamicData.delete_!)
|
||||
case _ => Failure(s"$DynamicDataNotFound dynamicEntityName=$entityName, dynamicDataId=$id")
|
||||
}
|
||||
override def delete(bankId: Option[String], entityName: String, id: String, userId: Option[String], isPersonalEntity: Boolean) = {
|
||||
get(bankId, entityName, id, userId, isPersonalEntity).map(_.asInstanceOf[DynamicData].delete_!)
|
||||
}
|
||||
|
||||
override def existsData(bankId: Option[String], dynamicEntityName: String): Boolean = {
|
||||
if(bankId.isEmpty){
|
||||
override def existsData(bankId: Option[String], dynamicEntityName: String, userId: Option[String], isPersonalEntity: Boolean): Boolean = {
|
||||
if(bankId.isEmpty && !isPersonalEntity){//isPersonalEntity == false, get all the data, no need for specific userId.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicEntityName, dynamicEntityName),
|
||||
NullRef(DynamicData.BankId)
|
||||
NullRef(DynamicData.BankId),
|
||||
By(DynamicData.IsPersonalEntity, false)
|
||||
).isDefined
|
||||
} else if(bankId.isDefined && !isPersonalEntity){//isPersonalEntity == false, get all the data, no need for specific userId.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicEntityName, dynamicEntityName),
|
||||
By(DynamicData.BankId, bankId.get),
|
||||
By(DynamicData.IsPersonalEntity, false)
|
||||
).nonEmpty
|
||||
} else if(bankId.isEmpty && isPersonalEntity){ //isPersonalEntity == true, get all the data for specific userId.
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicEntityName, dynamicEntityName),
|
||||
NullRef(DynamicData.BankId),
|
||||
By(DynamicData.IsPersonalEntity, true),
|
||||
By(DynamicData.UserId, userId.getOrElse(null))
|
||||
).nonEmpty
|
||||
} else {
|
||||
DynamicData.find(
|
||||
By(DynamicData.DynamicEntityName, dynamicEntityName),
|
||||
By(DynamicData.BankId, bankId.get)
|
||||
By(DynamicData.BankId, bankId.get),
|
||||
By(DynamicData.IsPersonalEntity, true),
|
||||
By(DynamicData.UserId, userId.getOrElse(null))
|
||||
).nonEmpty
|
||||
}
|
||||
}
|
||||
|
||||
private def saveOrUpdate(bankId: Option[String], entityName: String, requestBody: JObject, dynamicData: => DynamicData): Box[DynamicData] = {
|
||||
private def saveOrUpdate(bankId: Option[String], entityName: String, requestBody: JObject, userId: Option[String], isPersonalEntity: Boolean, dynamicData: => DynamicData): Box[DynamicData] = {
|
||||
val data: DynamicData = dynamicData
|
||||
|
||||
val dataStr = json.compactRender(requestBody)
|
||||
tryo {
|
||||
if(bankId.isDefined){
|
||||
data.DataJson(dataStr).DynamicEntityName(entityName).BankId(bankId.get).saveMe()
|
||||
} else{
|
||||
data.DataJson(dataStr).DynamicEntityName(entityName).BankId(null).saveMe()
|
||||
}
|
||||
val dataStr = json.compactRender(requestBody)
|
||||
data.DataJson(dataStr)
|
||||
.DynamicEntityName(entityName)
|
||||
.BankId(bankId.getOrElse(null))
|
||||
.UserId(userId.getOrElse(null))
|
||||
.IsPersonalEntity(isPersonalEntity)
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,11 +173,17 @@ class DynamicData extends DynamicDataT with LongKeyedMapper[DynamicData] with Id
|
||||
object DataJson extends MappedText(this)
|
||||
|
||||
object BankId extends MappedString(this,255)
|
||||
|
||||
object UserId extends MappedString(this,255)
|
||||
|
||||
object IsPersonalEntity extends MappedBoolean(this)
|
||||
|
||||
override def dynamicDataId: Option[String] = Option(DynamicDataId.get)
|
||||
override def dynamicEntityName: String = DynamicEntityName.get
|
||||
override def dataJson: String = DataJson.get
|
||||
override def bankId: Option[String] = Some(BankId.get)
|
||||
override def bankId: Option[String] = Option(BankId.get)
|
||||
override def userId: Option[String] = Option(UserId.get)
|
||||
override def isPersonalEntity: Boolean = IsPersonalEntity.get
|
||||
}
|
||||
|
||||
object DynamicData extends DynamicData with LongKeyedMetaMapper[DynamicData] {
|
||||
|
||||
@ -11,17 +11,18 @@ import org.apache.commons.lang3.StringUtils
|
||||
object MappedDynamicEntityProvider extends DynamicEntityProvider with CustomJsonFormats with MdcLoggable {
|
||||
|
||||
override def getById(bankId: Option[String], dynamicEntityId: String): Box[DynamicEntityT] = {
|
||||
if (bankId.isEmpty)
|
||||
DynamicEntity.find(By(DynamicEntity.DynamicEntityId, dynamicEntityId))
|
||||
if (bankId.isEmpty)//If bankId is empty, we only return the system level entities
|
||||
DynamicEntity.find(
|
||||
By(DynamicEntity.DynamicEntityId, dynamicEntityId),
|
||||
NullRef(DynamicEntity.BankId))
|
||||
else
|
||||
DynamicEntity.find(
|
||||
By(DynamicEntity.DynamicEntityId, dynamicEntityId),
|
||||
By(DynamicEntity.BankId, bankId.get
|
||||
))
|
||||
By(DynamicEntity.BankId, bankId.get))
|
||||
}
|
||||
|
||||
override def getByEntityName(bankId: Option[String], entityName: String): Box[DynamicEntityT] =
|
||||
if (bankId.isEmpty)
|
||||
if (bankId.isEmpty)//If Bank id is empty, we only return the system level entity
|
||||
DynamicEntity.find(
|
||||
By(DynamicEntity.EntityName, entityName),
|
||||
NullRef(DynamicEntity.BankId)
|
||||
@ -33,9 +34,11 @@ object MappedDynamicEntityProvider extends DynamicEntityProvider with CustomJson
|
||||
)
|
||||
|
||||
|
||||
override def getDynamicEntities(bankId: Option[String]): List[DynamicEntity] = {
|
||||
if (bankId.isEmpty)
|
||||
override def getDynamicEntities(bankId: Option[String], returnBothBankAndSystemLevel: Boolean): List[DynamicEntity] = {
|
||||
if(returnBothBankAndSystemLevel)
|
||||
DynamicEntity.findAll()
|
||||
else if (bankId.isEmpty)//If Bank id is empty, we only return the system level entity
|
||||
DynamicEntity.findAll(NullRef(DynamicEntity.BankId))
|
||||
else
|
||||
DynamicEntity.findAll(By(DynamicEntity.BankId, bankId.get))
|
||||
}
|
||||
@ -63,6 +66,7 @@ object MappedDynamicEntityProvider extends DynamicEntityProvider with CustomJson
|
||||
.MetadataJson(dynamicEntity.metadataJson)
|
||||
.UserId(dynamicEntity.userId)
|
||||
.BankId(dynamicEntity.bankId.getOrElse(null))
|
||||
.HasPersonalEntity(dynamicEntity.hasPersonalEntity)
|
||||
.saveMe()
|
||||
} catch {
|
||||
case e =>
|
||||
@ -94,12 +98,14 @@ class DynamicEntity extends DynamicEntityT with LongKeyedMapper[DynamicEntity] w
|
||||
object MetadataJson extends MappedText(this)
|
||||
object UserId extends MappedString(this, 255)
|
||||
object BankId extends MappedString(this, 255)
|
||||
object HasPersonalEntity extends MappedBoolean(this)
|
||||
|
||||
override def dynamicEntityId: Option[String] = Option(DynamicEntityId.get)
|
||||
override def entityName: String = EntityName.get
|
||||
override def metadataJson: String = MetadataJson.get
|
||||
override def userId: String = UserId.get
|
||||
override def bankId: Option[String] = if (BankId.get == null || BankId.get.isEmpty) None else Some(BankId.get)
|
||||
override def hasPersonalEntity: Boolean = HasPersonalEntity.get
|
||||
}
|
||||
|
||||
object DynamicEntity extends DynamicEntity with LongKeyedMetaMapper[DynamicEntity] {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package code.entitlement
|
||||
|
||||
import code.api.dynamic.endpoint.helper.DynamicEntityInfo
|
||||
import code.api.dynamic.entity.helper.DynamicEntityInfo
|
||||
import code.api.util.ApiRole.{CanCreateEntitlementAtAnyBank, CanCreateEntitlementAtOneBank}
|
||||
import code.api.util.{ErrorMessages, NotificationUtil}
|
||||
import code.util.{MappedUUID, UUIDString}
|
||||
|
||||
@ -325,12 +325,12 @@ class AuthenticationTypeValidationTest extends V400ServerSetup {
|
||||
|
||||
feature(s"test AuthenticationTypeValidation endpoints version $VersionOfApi - Validate dynamic entity endpoint request body") {
|
||||
scenario(s"We will call the endpoint $ApiEndpoint1 with invalid FooBar", ApiEndpoint1, VersionOfApi) {
|
||||
addOneAuthenticationTypeValidation(allowedDirectLogin, s"OBPv4.0.0-dynamicEntity_createFooBar_${bankId}")
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addOneAuthenticationTypeValidation(allowedDirectLogin, s"OBPv4.0.0-dynamicEntity_createFooBar_")
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response= makePostRequest(request, newFooBar)
|
||||
Then("We should get a 400")
|
||||
response.code should equal(400)
|
||||
@ -344,11 +344,11 @@ class AuthenticationTypeValidationTest extends V400ServerSetup {
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint1 with valid FooBar", ApiEndpoint1, VersionOfApi) {
|
||||
addOneAuthenticationTypeValidation(allowedAll, s"OBPv4.0.0-dynamicEntity_createFooBar_${bankId}")
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response= makePostRequest(request, newFooBar)
|
||||
Then("We should get a 201")
|
||||
response.code should equal(201)
|
||||
@ -402,13 +402,12 @@ class AuthenticationTypeValidationTest extends V400ServerSetup {
|
||||
response
|
||||
}
|
||||
// prepare one dynamic entity FooBar
|
||||
private def addDynamicEntity(): APIResponse = {
|
||||
grantEntitlement(canCreateDynamicEntity)
|
||||
val request = (v4_0_0_Request / "management" / "dynamic-entities").POST <@ user1
|
||||
private def addSystemDynamicEntity(): APIResponse = {
|
||||
grantEntitlement(canCreateSystemLevelDynamicEntity)
|
||||
val request = (v4_0_0_Request / "management" / "system-dynamic-entities").POST <@ user1
|
||||
val fooBar =
|
||||
s"""
|
||||
|{
|
||||
| "bankId": "$bankId",
|
||||
| "FooBar": {
|
||||
| "description": "description of this entity, can be markdown text.",
|
||||
| "required": [
|
||||
|
||||
@ -770,7 +770,9 @@ class DynamicEndpointHelperTest extends FlatSpec with Matchers {
|
||||
dynamicDataId: Option[String],
|
||||
dynamicEntityName: String,
|
||||
dataJson: String,
|
||||
bankId: Option[String]
|
||||
bankId: Option[String],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean
|
||||
)extends DynamicDataT
|
||||
|
||||
val dataJsonString = """{
|
||||
@ -788,7 +790,7 @@ class DynamicEndpointHelperTest extends FlatSpec with Matchers {
|
||||
|}
|
||||
|}""".stripMargin
|
||||
val dynamicDataJson = json.parse(dataJsonString)
|
||||
val dynamicDataList = List(DataTest(Some("1"),"PetEntity",dataJsonString, Some(testBankId1.value)), DataTest(Some("2"),"PetEntity2",dataJsonString2, Some(testBankId1.value)))
|
||||
val dynamicDataList = List(DataTest(Some("1"),"PetEntity",dataJsonString, Some(testBankId1.value), None, false), DataTest(Some("2"),"PetEntity2",dataJsonString2, Some(testBankId1.value), None, false))
|
||||
|
||||
|
||||
val expectedResult = ("PetEntity", "1")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -88,10 +88,10 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
}
|
||||
|
||||
scenario(s"We will call the dynamic entity endpoint without authentication", VersionOfApi) {
|
||||
addDynamicEntity()
|
||||
addSystemDynamicEntity()
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST
|
||||
val request = (dynamicEntity_Request / "FooBar").POST
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error", "OBP-20006"))
|
||||
|
||||
Then("We should get a 401")
|
||||
@ -410,11 +410,11 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
////// dynamic entity
|
||||
feature(s"test dynamic entity endpoints Force-Error, version $VersionOfApi - authenticated access") {
|
||||
scenario(s"We will call the endpoint $ApiEndpoint3 with Force-Error have wrong format header", VersionOfApi) {
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error" -> "OBP-xxxx"))
|
||||
|
||||
Then("We should get a 400")
|
||||
@ -426,11 +426,11 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
}
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint3 with Force-Error header value not support by current endpoint", VersionOfApi) {
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error" -> "OBP-20009"))
|
||||
Then("We should get a 400")
|
||||
response.code should equal(400)
|
||||
@ -441,11 +441,11 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
}
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint3 with Response-Code header value is not Int", VersionOfApi) {
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error" -> "OBP-20006"), ("Response-Code" -> "not_integer"))
|
||||
Then("We should get a 400")
|
||||
response.code should equal(400)
|
||||
@ -456,11 +456,11 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
}
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint3 with correct Force-Error header value", VersionOfApi) {
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error" -> "OBP-20006"))
|
||||
Then("We should get a 403")
|
||||
response.code should equal(403)
|
||||
@ -473,11 +473,11 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
}
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint3 with correct Force-Error header value and Response-Code value", VersionOfApi) {
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error" -> "OBP-20006"), ("Response-Code" -> "444"))
|
||||
Then("We should get a 444")
|
||||
response.code should equal(444)
|
||||
@ -491,11 +491,11 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint3 with correct Force-Error header value, but 'enable.force_error=false'", VersionOfApi) {
|
||||
setPropsValues("enable.force_error"->"false")
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response = makePostRequest(request, correctFooBar, ("Force-Error" -> "OBP-20006"))
|
||||
Then("We should not get a 403")
|
||||
response.code should not equal(403)
|
||||
@ -630,13 +630,12 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
}
|
||||
|
||||
// prepare one dynamic entity FooBar
|
||||
private def addDynamicEntity(): APIResponse = {
|
||||
addEntitlement(canCreateDynamicEntity)
|
||||
val request = (v4_0_0_Request / "management" / "dynamic-entities").POST <@ user1
|
||||
private def addSystemDynamicEntity(): APIResponse = {
|
||||
addEntitlement(canCreateSystemLevelDynamicEntity)
|
||||
val request = (v4_0_0_Request / "management" / "system-dynamic-entities").POST <@ user1
|
||||
val fooBar =
|
||||
s"""
|
||||
|{
|
||||
| "bankId": "$bankId",
|
||||
| "FooBar": {
|
||||
| "description": "description of this entity, can be markdown text.",
|
||||
| "required": [
|
||||
|
||||
@ -49,7 +49,7 @@ class GetScannedApiVersionsTest extends V400ServerSetup {
|
||||
|
||||
feature("Get all scanned API versions should works") {
|
||||
scenario("We get all the scanned API versions", ApiEndpoint, VersionOfApi) {
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateDynamicEntity.toString)
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemLevelDynamicEntity.toString)
|
||||
When("We make a request v4.0.0")
|
||||
val request = (v4_0_0_Request / "api" / "versions").GET
|
||||
|
||||
|
||||
@ -327,12 +327,12 @@ class JsonSchemaValidationTest extends V400ServerSetup {
|
||||
|
||||
feature(s"test JSON Schema Validation endpoints version $VersionOfApi - Validate dynamic entity endpoint request body") {
|
||||
scenario(s"We will call the endpoint $ApiEndpoint1 with invalid FooBar", ApiEndpoint1, VersionOfApi) {
|
||||
addOneValidation(jsonSchemaFooBar, s"OBPv4.0.0-dynamicEntity_createFooBar_${bankId}")
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addOneValidation(jsonSchemaFooBar, s"OBPv4.0.0-dynamicEntity_createFooBar_")
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response= makePostRequest(request, wrongFooBar)
|
||||
Then("We should get a 400")
|
||||
response.code should equal(400)
|
||||
@ -345,11 +345,11 @@ class JsonSchemaValidationTest extends V400ServerSetup {
|
||||
|
||||
scenario(s"We will call the endpoint $ApiEndpoint1 with valid FooBar", ApiEndpoint1, VersionOfApi) {
|
||||
addOneValidation(jsonSchemaFooBar, s"OBPv4.0.0-dynamicEntity_createFooBar_${bankId}")
|
||||
addDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_FooBar", bankId)
|
||||
addSystemDynamicEntity()
|
||||
addStringEntitlement("CanCreateDynamicEntity_SystemFooBar", "")
|
||||
|
||||
When("We make a request v4.0.0")
|
||||
val request = (dynamicEntity_Request / "banks" / bankId / "FooBar").POST <@ user1
|
||||
val request = (dynamicEntity_Request / "FooBar").POST <@ user1
|
||||
val response= makePostRequest(request, correctFooBar)
|
||||
Then("We should get a 201")
|
||||
response.code should equal(201)
|
||||
@ -404,13 +404,12 @@ class JsonSchemaValidationTest extends V400ServerSetup {
|
||||
response
|
||||
}
|
||||
// prepare one dynamic entity FooBar
|
||||
private def addDynamicEntity(): APIResponse = {
|
||||
addEntitlement(canCreateDynamicEntity)
|
||||
val request = (v4_0_0_Request / "management" / "dynamic-entities").POST <@ user1
|
||||
private def addSystemDynamicEntity(): APIResponse = {
|
||||
addEntitlement(canCreateSystemLevelDynamicEntity)
|
||||
val request = (v4_0_0_Request / "management" / "system-dynamic-entities").POST <@ user1
|
||||
val fooBar =
|
||||
s"""
|
||||
|{
|
||||
| "bankId": "$bankId",
|
||||
| "FooBar": {
|
||||
| "description": "description of this entity, can be markdown text.",
|
||||
| "required": [
|
||||
|
||||
Binary file not shown.
@ -986,7 +986,9 @@ case class OutBoundDynamicEntityProcess (outboundAdapterCallContext: OutboundAda
|
||||
requestBody: Option[JObject],
|
||||
entityId: Option[String],
|
||||
bankId: Option[String],
|
||||
queryParameters: Option[Map[String, List[String]]]) extends TopicTrait
|
||||
queryParameters: Option[Map[String, List[String]]],
|
||||
userId: Option[String],
|
||||
isPersonalEntity: Boolean)extends TopicTrait
|
||||
case class InBoundDynamicEntityProcess (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: JValue) extends InBoundTrait[JValue]
|
||||
|
||||
// because swagger generate not support JValue type, so here supply too xxxDoc TO generate correct request and response body example
|
||||
|
||||
Loading…
Reference in New Issue
Block a user