From 51108d465ba23ee8ff6b1cc38b753ccbd1dee3ec Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 26 Jul 2021 16:33:08 +0200 Subject: [PATCH 001/293] feature/added the EndpointTag Model --- .../main/scala/bootstrap/liftweb/Boot.scala | 4 +- .../endpointTag/EndpointMappingProvider.scala | 54 ++++++++++++++++ .../MappedEndpointMappingProvider.scala | 61 +++++++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala create mode 100644 obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 349e2a934..f94294208 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -104,6 +104,7 @@ import code.connectormethod.ConnectorMethod import code.dynamicMessageDoc.DynamicMessageDoc import code.dynamicResourceDoc.DynamicResourceDoc import code.endpointMapping.EndpointMapping +import code.endpointTag.EndpointTag import code.snippet.{OAuthAuthorisation, OAuthWorkedThanks} import code.socialmedia.MappedSocialMedia import code.standingorders.StandingOrder @@ -928,7 +929,8 @@ object ToSchemify { AuthenticationTypeValidation, ConnectorMethod, DynamicResourceDoc, - DynamicMessageDoc + DynamicMessageDoc, + EndpointTag )++ APIBuilder_Connector.allAPIBuilderModels // start grpc server diff --git a/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala new file mode 100644 index 000000000..2f4db28e7 --- /dev/null +++ b/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala @@ -0,0 +1,54 @@ +package code.endpointTag + +/* For Connector endpoint routing, star connector use this provider to find proxy connector name */ + +import com.openbankproject.commons.model.{Converter, JsonFieldReName} +import net.liftweb.common.Box +import net.liftweb.json.Formats +import net.liftweb.json.JsonAST.{JField, JNull, JObject, JString} +import net.liftweb.util.SimpleInjector + +object EndpointTagProvider extends SimpleInjector { + + val endpointTagProvider = new Inject(buildOne _) {} + + def buildOne: MappedEndpointTagProvider.type = MappedEndpointTagProvider +} + +trait EndpointTagT { + def endpointTagId: Option[String] + def operationId: String + def tagName: String +} + +case class EndpointTagCommons( + endpointTagId: Option[String], + operationId: String, + tagName: String, + ) extends EndpointTagT with JsonFieldReName { + /** + * when serialized to json, the Option field will be not shown, this endpoint just generate a full fields json, include all None value fields + * @return JObject include all fields + */ + def toJson(implicit format: Formats) = { + JObject(List( + JField("operation_id", JString(this.operationId)), + JField("endpoint_mapping_id", this.endpointTagId.map(JString(_)).getOrElse(JNull)), + JField("tagName", JString(this.tagName)) + )) + } +} + +object EndpointTagCommons extends Converter[EndpointTagT, EndpointTagCommons] + +trait EndpointTagProvider { + def getById(endpointTagId: String): Box[EndpointTagT] + + def getByOperationId(operationId: String): Box[EndpointTagT] + + def getAllEndpointTags: List[EndpointTagT] + + def createOrUpdate(endpointTag: EndpointTagT): Box[EndpointTagT] + + def delete(endpointTagId: String):Box[Boolean] +} \ No newline at end of file diff --git a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala new file mode 100644 index 000000000..7c7718b06 --- /dev/null +++ b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala @@ -0,0 +1,61 @@ +package code.endpointTag + +import code.api.util.CustomJsonFormats +import code.util.MappedUUID +import net.liftweb.common.{Box, Empty, EmptyBox, Full} +import net.liftweb.mapper._ +import net.liftweb.util.Helpers.tryo +import org.apache.commons.lang3.StringUtils + +object MappedEndpointTagProvider extends EndpointTagProvider with CustomJsonFormats{ + + override def getById(endpointTagId: String): Box[EndpointTagT] = { + getByEndpointTagId(endpointTagId) + } + + override def getByOperationId(operationId: String): Box[EndpointTagT] = { + EndpointTag.find(By(EndpointTag.OperationId, operationId)) + } + + override def createOrUpdate(endpointTag: EndpointTagT): Box[EndpointTagT] = { + //to find exists endpointTag, if endpointTagId supplied, query by endpointTagId, or use endpointName and endpointTagId to do query + val existsEndpointTag: Box[EndpointTag] = endpointTag.endpointTagId match { + case Some(id) if (StringUtils.isNotBlank(id)) => getByEndpointTagId(id) + case _ => Empty + } + val entityToPersist = existsEndpointTag match { + case _: EmptyBox => EndpointTag.create + case Full(endpointTag) => endpointTag + } + + tryo{ + entityToPersist + .OperationId(endpointTag.operationId) + .TagName(endpointTag.tagName) + .saveMe() + } + } + + override def delete(endpointTagId: String): Box[Boolean] = getByEndpointTagId(endpointTagId).map(_.delete_!) + + private[this] def getByEndpointTagId(endpointTagId: String): Box[EndpointTag] = EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)) + + override def getAllEndpointTags: List[EndpointTagT] = EndpointTag.findAll() +} + +class EndpointTag extends EndpointTagT with LongKeyedMapper[EndpointTag] with IdPK with CustomJsonFormats{ + + override def getSingleton = EndpointTag + + object EndpointTagId extends MappedUUID(this) + object OperationId extends MappedString(this, 255) + object TagName extends MappedString(this, 255) + + override def endpointTagId: Option[String] = Option(EndpointTagId.get) + override def operationId: String = OperationId.get + override def tagName: String = TagName.get +} + +object EndpointTag extends EndpointTag with LongKeyedMetaMapper[EndpointTag] { + override def dbIndexes = UniqueIndex(EndpointTagId) ::UniqueIndex(OperationId) :: super.dbIndexes +} \ No newline at end of file From 54bb138e14d5c979c36c4034bd27a6f91713cfc1 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 28 Jul 2021 22:02:24 +0200 Subject: [PATCH 002/293] feature/added the default cache time for `getDynamicResourceDocsTTL` and `getStaticResourceDocsTTL` --- .../code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index eb38f8b48..3525ed164 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -211,8 +211,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth //implicit val scalaCache = ScalaCache(GuavaCache(underlyingGuavaCache)) // if upload DynamicEntity, will generate corresponding endpoints, when current cache timeout, the new endpoints will be shown. // so if you want the new generated endpoints shown timely, set this value to a small number, or set to a big number - val getDynamicResourceDocsTTL : Int = APIUtil.getPropsValue(s"dynamicResourceDocsObp.cache.ttl.seconds", "0").toInt - val getStaticResourceDocsTTL : Int = APIUtil.getPropsValue(s"staticResourceDocsObp.cache.ttl.seconds", "0").toInt + val getDynamicResourceDocsTTL : Int = APIUtil.getPropsValue(s"dynamicResourceDocsObp.cache.ttl.seconds", "3600").toInt + val getStaticResourceDocsTTL : Int = APIUtil.getPropsValue(s"staticResourceDocsObp.cache.ttl.seconds", "86400").toInt /** * From 9dcb0e00e8f65de1c98a63d55dde74a85e2e3a26 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 28 Jul 2021 22:09:21 +0200 Subject: [PATCH 003/293] refactor/tweaked the cache key for getResourceDocs methods, keep it the same as API_Explorer side. --- .../ResourceDocsAPIMethods.scala | 34 +++++++++++++------ .../scala/code/api/v3_1_0/APIMethods310.scala | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 3525ed164..d8423ac8f 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -224,7 +224,10 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth */ private def getStaticResourceDocsObpCached(requestedApiVersion : ApiVersion, resourceDocTags: Option[List[ResourceDocTag]], - partialFunctionNames: Option[List[String]] + partialFunctionNames: Option[List[String]], + languageParam: Option[LanguageParam], + contentParam: Option[ContentParam], + cacheModifierParam: Option[String] ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -253,7 +256,10 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth */ private def getAllResourceDocsObpCached(requestedApiVersion : ApiVersion, resourceDocTags: Option[List[ResourceDocTag]], - partialFunctionNames: Option[List[String]] + partialFunctionNames: Option[List[String]], + languageParam: Option[LanguageParam], + contentParam: Option[ContentParam], + cacheModifierParam: Option[String] ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -302,7 +308,10 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth private def getResourceDocsObpDynamicCached(requestedApiVersion : ApiVersion, resourceDocTags: Option[List[ResourceDocTag]], - partialFunctionNames: Option[List[String]] + partialFunctionNames: Option[List[String]], + languageParam: Option[LanguageParam], + contentParam: Option[ContentParam], + cacheModifierParam: Option[String] ): Option[JValue] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { @@ -475,7 +484,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth // Note: description uses html markup because original markdown doesn't easily support "_" and there are multiple versions of markdown. def getResourceDocsObp : OBPEndpoint = { case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { - val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam) = ResourceDocsAPIMethodsUtil.getParams() + val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() cc => for { (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { @@ -500,13 +509,13 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case _ => contentParam match { case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions) + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) Future(dynamicDocs.map(successJsonResponse(_))) case Some(STATIC) => - val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions) + val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) Future(staticDocs.map(successJsonResponse(_))) case _ => - val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions) + val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) Future(docs.map(successJsonResponse(_))) } } @@ -557,7 +566,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case "resource-docs" :: requestedApiVersionString :: "swagger" :: Nil JsonGet _ => { cc =>{ for { - (resourceDocTags, partialFunctions, languageParam, contentParam, apiCollectionIdParam) <- tryo(ResourceDocsAPIMethodsUtil.getParams()) + (resourceDocTags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) <- tryo(ResourceDocsAPIMethodsUtil.getParams()) requestedApiVersion <- tryo(ApiVersionUtils.valueOf(requestedApiVersionString)) ?~! s"$InvalidApiVersionString Current Version is $requestedApiVersionString" _ <- booleanToBox(versionIsAllowed(requestedApiVersion), s"$ApiVersionNotSupported Current Version is $requestedApiVersionString") staticJson <- getResourceDocsSwaggerCached(requestedApiVersionString, resourceDocTags, partialFunctions) @@ -802,7 +811,7 @@ object ResourceDocsAPIMethodsUtil extends MdcLoggable{ case _ => None } - def getParams() : (Option[List[ResourceDocTag]], Option[List[String]], Option[LanguageParam], Option[ContentParam], Option[String]) = { + def getParams() : (Option[List[ResourceDocTag]], Option[List[String]], Option[LanguageParam], Option[ContentParam], Option[String], Option[String]) = { val rawTagsParam = S.param("tags") @@ -868,8 +877,13 @@ object ResourceDocsAPIMethodsUtil extends MdcLoggable{ x <- S.param("api-collection-id") } yield x logger.info(s"apiCollectionIdParam is $apiCollectionIdParam") + + val cacheModifierParam = for { + x <- S.param("cache-modifier") + } yield x + logger.info(s"cacheModifierParam is $cacheModifierParam") - (tags, partialFunctionNames, languageParam, contentParam, apiCollectionIdParam) + (tags, partialFunctionNames, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) } diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 8c7e5f51e..1c4a10121 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -3241,7 +3241,7 @@ trait APIMethods310 { lazy val getMessageDocsSwagger: OBPEndpoint = { case "message-docs" :: restConnectorVersion ::"swagger2.0" :: Nil JsonGet _ => { - val (resourceDocTags, partialFunctions, languageParam, contentParam, apiCollectionIdParam) = ResourceDocsAPIMethodsUtil.getParams() + val (resourceDocTags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() cc => { for { (_, callContext) <- anonymousAccess(cc) From b9a91f9727ff52ed0e6593d4cff583e3148c23ea Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 29 Jul 2021 00:57:17 +0200 Subject: [PATCH 004/293] feature/added the get/update endpointTag endpoints --- .../SwaggerDefinitionsJSON.scala | 10 +++ .../main/scala/code/api/util/ApiRole.scala | 12 +++ .../scala/code/api/util/ErrorMessages.scala | 5 ++ .../scala/code/api/util/ExampleValue.scala | 7 ++ .../main/scala/code/api/util/NewStyle.scala | 14 +++- .../scala/code/api/v4_0_0/APIMethods400.scala | 75 +++++++++++++++++++ .../code/api/v4_0_0/JSONFactory4.0.0.scala | 10 +++ .../scala/code/bankconnectors/Connector.scala | 6 +- .../bankconnectors/LocalMappedConnector.scala | 29 ++++++- .../MappedEndpointMappingProvider.scala | 2 +- 10 files changed, 166 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index a8e7f9d97..b91e54f5b 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -2436,6 +2436,16 @@ object SwaggerDefinitionsJSON { host = "dynamic_entity" ) + val endpointTagJson400 = EndpointTagJson400( + tag_name = tagNameExample.value + ) + + val endpointTagResponseJson400 = EndpointTagResponseJson400( + endpoint_tag_id = endpointTagIdExample.value, + operation_id = operationIdExample.value, + tag_name = tagNameExample.value + ) + val metricsJson = MetricsJson( metrics = List(metricJson) ) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 9c0647904..1b177725d 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -764,6 +764,18 @@ object ApiRole { case class CanGetUserInvitation(requiresBankId: Boolean = true) extends ApiRole lazy val canGetUserInvitation = CanGetUserInvitation() + case class CanCreateEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canCreateEndpointTag = CanCreateEndpointTag() + + case class CanUpdateEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canUpdateEndpointTag = CanUpdateEndpointTag() + + case class CanDeleteEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canDeleteEndpointTag = CanDeleteEndpointTag() + + case class CanGetEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetEndpointTag = CanGetEndpointTag() + private val dynamicApiRoles = new ConcurrentHashMap[String, ApiRole] private case class DynamicApiRole(role: String, requiresBankId: Boolean = false) extends ApiRole{ diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index f6e02924d..74602e94e 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -344,6 +344,11 @@ object ErrorMessages { val UpdateAtmLocationCategoriesException = "OBP-30095: Could not update the Atm Location Categories." + val CreateEndpointTagError = "OBP-30096: Could not insert the Endpoint Tag." + val UpdateEndpointTagError = "OBP-30097: Could not update the Endpoint Tag." + val UnknownEndpointTagError = "OBP-30098: Unknown Endpoint Tag error. " + val EndpointTagNotFoundByEndpointTagId = "OBP-30099: Invalid ENDPOINT_TAG_ID. Please specify a valid value for ENDPOINT_TAG_ID." + // Meetings val MeetingsNotSupported = "OBP-30101: Meetings are not supported on this server." val MeetingApiKeyNotConfigured = "OBP-30102: Meeting provider API Key is not configured." diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 5ced88d16..5112ca9cf 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -232,6 +232,13 @@ object ExampleValue { lazy val operationIdExample = ConnectorField("OBPv4.0.0-getBanks", "A uniquely identify the obp endpoint on OBP instance, you can get it from Get Resource endpoints.") glossaryItems += makeGlossaryItem("ApiCollectionEndpoint.operationId", operationIdExample) + + lazy val tagNameExample = ConnectorField("BankAccountTag1", "The endpoint tag name") + glossaryItems += makeGlossaryItem("EndpointTag.tagName", tagNameExample) + + lazy val endpointTagIdExample = ConnectorField("7uy8a7e4-6d02-40e3-a129-0b2bf89de8uh", "A string that MUST uniquely identify the endpointTag on this OBP instance, can be used in all cache.") + glossaryItems += makeGlossaryItem("EndpointTag.endpointTagId", endpointTagIdExample) + lazy val accountTypeExample = ConnectorField("AC","A short code that represents the type of the account as provided by the bank.") diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 5bfa5519a..4a9f0fd77 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -3,7 +3,6 @@ package code.api.util import java.io import java.util.Date import java.util.UUID.randomUUID - import akka.http.scaladsl.model.HttpMethod import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT} import code.api.APIFailureNewStyle @@ -68,6 +67,7 @@ import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod} import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc} import code.dynamicResourceDoc.{DynamicResourceDocProvider, JsonDynamicResourceDoc} import code.endpointMapping.{EndpointMappingProvider, EndpointMappingT} +import code.endpointTag.EndpointTagT import net.liftweb.json object NewStyle { @@ -274,6 +274,18 @@ object NewStyle { } } + def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[EndpointTagT] = { + Connector.connector.vend.createOrUpdateEndpointTag(endpointTag, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$CreateEndpointTagError", 400), i._2) + } + } + + def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[EndpointTagT] = { + Connector.connector.vend.getEndpointTag(endpointTagId, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$EndpointTagNotFoundByEndpointTagId Current ENDPOINT_TAG_ID is $endpointTagId", 404), i._2) + } + } + def getBank(bankId : BankId, callContext: Option[CallContext]) : OBPReturnType[Bank] = { Connector.connector.vend.getBank(bankId, callContext) map { unboxFullOrFail(_, callContext, s"$BankNotFound Current BankId is $bankId", 404) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index caea521fb..8e30151de 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9099,6 +9099,81 @@ trait APIMethods400 { } } } + + staticResourceDocs += ResourceDoc( + createEndpointTag, + implementedInApiVersion, + nameOf(createEndpointTag), + "POST", + "/management/endpoints/OPERATION_ID/tag", + "Create Endpoint Tag", + s"""Create Endpoint Tag""", + endpointTagJson400, + endpointTagResponseJson400, + List( + $UserNotLoggedIn, + UserHasMissingRoles, + InvalidJsonFormat, + UnknownError + ), + List(apiTagManageDynamicEndpoint, apiTagApi, apiTagNewStyle), + Some(List(canCreateDynamicEndpoint))) + lazy val createEndpointTag: OBPEndpoint = { + case "management" :: "endpoints" :: operationId :: "tag" :: Nil JsonPost json -> _ => { + cc => + for { + endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { + json.extract[EndpointTagJson400] + } + (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(None,operationId,endpointTag.tag_name), cc.callContext) + } yield { + (EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + ), HttpCode.`201`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + updateEndpointTag, + implementedInApiVersion, + nameOf(updateEndpointTag), + "PUT", + "/management/endpoints/OPERATION_ID/tag/ENDPOINT_TAG_ID", + "Update Endpoint Tag", + s"""Update Endpoint Tag""", + endpointTagJson400, + endpointTagResponseJson400, + List( + $UserNotLoggedIn, + UserHasMissingRoles, + EndpointTagNotFoundByEndpointTagId, + InvalidJsonFormat, + UnknownError + ), + List(apiTagManageDynamicEndpoint, apiTagApi, apiTagNewStyle), + Some(List(canUpdateDynamicEndpoint))) + lazy val updateEndpointTag: OBPEndpoint = { + case "management" :: "endpoints" :: operationId :: "tag" :: endpointTagId :: Nil JsonPut json -> _ => { + cc => + for { + endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { + json.extract[EndpointTagJson400] + } + (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) + (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(Some(endpointTagId),operationId,endpointTag.tag_name), cc.callContext) + } yield { + (EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + ), HttpCode.`201`(cc.callContext)) + } + } + } + } private def createDynamicEndpointMethod(bankId: Option[String], json: JValue, cc: CallContext) = { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index fc8012a8b..37b5fb04c 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -545,6 +545,16 @@ case class DynamicEndpointHostJson400( host: String ) +case class EndpointTagJson400( + tag_name: String, +) + +case class EndpointTagResponseJson400( + endpoint_tag_id: String, + operation_id: String, + tag_name: String +) + case class CounterpartyJson400( name: String, description: String, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index f666c019c..78b54a390 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -2,7 +2,6 @@ package code.bankconnectors import java.util.Date import java.util.UUID.randomUUID - import _root_.akka.http.scaladsl.model.HttpMethod import code.accountholders.{AccountHolders, MapperAccountHolders} import code.api.attributedefinition.AttributeDefinition @@ -21,6 +20,7 @@ import code.bankconnectors.vJune2017.KafkaMappedConnector_vJune2017 import code.bankconnectors.vMar2017.KafkaMappedConnector_vMar2017 import code.bankconnectors.vMay2019.KafkaMappedConnector_vMay2019 import code.bankconnectors.vSept2018.KafkaMappedConnector_vSept2018 +import code.endpointTag.EndpointTagT import code.fx.fx.TTL import code.management.ImporterAPI.ImporterTransaction import code.model.dataAccess.{BankAccountRouting, ResourceUser} @@ -1558,7 +1558,11 @@ trait Connector extends MdcLoggable { def createOrUpdateAtmLegacy(atm: AtmT): Box[AtmT] = Failure(setUnimplementedError) def createOrUpdateAtm(atm: AtmT, callContext: Option[CallContext]): OBPReturnType[Box[AtmT]] = Future{Failure(setUnimplementedError)} + + def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) + def createOrUpdateProduct( bankId : String, code : String, diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 2fcd318fe..c43f4ee3b 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2,7 +2,6 @@ package code.bankconnectors import java.util.Date import java.util.UUID.randomUUID - import _root_.akka.http.scaladsl.model.HttpMethod import code.DynamicData.DynamicDataProvider import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT} @@ -32,6 +31,7 @@ import code.customeraddress.CustomerAddressX import code.customerattribute.CustomerAttributeX import code.database.authorisation.Authorisations import code.directdebit.DirectDebits +import code.endpointTag.{EndpointTag, EndpointTagT} import code.fx.fx.TTL import code.fx.{MappedFXRate, fx} import code.kycchecks.KycChecks @@ -2479,6 +2479,33 @@ object LocalMappedConnector extends Connector with MdcLoggable { override def createOrUpdateAtm(atm: AtmT, callContext: Option[CallContext]): OBPReturnType[Box[AtmT]] = Future{ (createOrUpdateAtmLegacy(atm), callContext) } + + override def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future( + (EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)), callContext) + ) + + override def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + (EndpointTag.find( + By(EndpointTag.EndpointTagId, endpointTag.endpointTagId.getOrElse("")), + ) match { + case Full(x) => + tryo { + x + .OperationId(endpointTag.operationId) + .TagName(endpointTag.tagName) + .saveMe() + } ?~! UpdateEndpointTagError + case Empty => + tryo { + EndpointTag.create + .OperationId(endpointTag.operationId) + .TagName(endpointTag.tagName) + .saveMe() + } ?~! CreateEndpointTagError + case _ => + Failure(UnknownEndpointTagError) + }, callContext) + } override def createOrUpdateAtmLegacy(atm: AtmT): Box[AtmT] = { diff --git a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala index 7c7718b06..861daf87d 100644 --- a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala +++ b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala @@ -57,5 +57,5 @@ class EndpointTag extends EndpointTagT with LongKeyedMapper[EndpointTag] with Id } object EndpointTag extends EndpointTag with LongKeyedMetaMapper[EndpointTag] { - override def dbIndexes = UniqueIndex(EndpointTagId) ::UniqueIndex(OperationId) :: super.dbIndexes + override def dbIndexes = UniqueIndex(EndpointTagId) :: super.dbIndexes } \ No newline at end of file From 2be63b3c92adb47e31f10ad8fd10b6becedacf10 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 29 Jul 2021 14:14:00 +0200 Subject: [PATCH 005/293] feature/enhanced the error handling for create and update EndpointTag --- .../main/scala/code/api/util/ErrorMessages.scala | 1 + .../src/main/scala/code/api/util/NewStyle.scala | 6 ++++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 15 ++++++++++++--- .../scala/code/bankconnectors/Connector.scala | 2 ++ .../bankconnectors/LocalMappedConnector.scala | 8 +++++++- .../MappedEndpointMappingProvider.scala | 2 +- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 74602e94e..c9b7ccf5c 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -348,6 +348,7 @@ object ErrorMessages { val UpdateEndpointTagError = "OBP-30097: Could not update the Endpoint Tag." val UnknownEndpointTagError = "OBP-30098: Unknown Endpoint Tag error. " val EndpointTagNotFoundByEndpointTagId = "OBP-30099: Invalid ENDPOINT_TAG_ID. Please specify a valid value for ENDPOINT_TAG_ID." + val EndpointTagAlreadyExists = "OBP-30100: EndpointTag already exists." // Meetings val MeetingsNotSupported = "OBP-30101: Meetings are not supported on this server." diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 4a9f0fd77..f583add94 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -279,6 +279,12 @@ object NewStyle { i => (unboxFullOrFail(i._1, callContext, s"$CreateEndpointTagError", 400), i._2) } } + + def checkEndpointTagExists(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Boolean] = { + Connector.connector.vend.getEndpointTag(operationId: String, tagName:String, callContext) map { + i => (i._1.isDefined, i._2) + } + } def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[EndpointTagT] = { Connector.connector.vend.getEndpointTag(endpointTagId, callContext) map { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index cf7a80f0c..4e75e4cd2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9116,7 +9116,7 @@ trait APIMethods400 { InvalidJsonFormat, UnknownError ), - List(apiTagManageDynamicEndpoint, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagApi, apiTagNewStyle), Some(List(canCreateDynamicEndpoint))) lazy val createEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tag" :: Nil JsonPost json -> _ => { @@ -9125,6 +9125,10 @@ trait APIMethods400 { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { json.extract[EndpointTagJson400] } + (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name})", cc=callContext) { + (!endpointTagExisted) + } (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(None,operationId,endpointTag.tag_name), cc.callContext) } yield { (EndpointTagResponseJson400( @@ -9143,7 +9147,7 @@ trait APIMethods400 { "PUT", "/management/endpoints/OPERATION_ID/tag/ENDPOINT_TAG_ID", "Update Endpoint Tag", - s"""Update Endpoint Tag""", + s"""Update Endpoint Tag, you can only update the tag_name here, operation_id can not be updated.""", endpointTagJson400, endpointTagResponseJson400, List( @@ -9153,7 +9157,7 @@ trait APIMethods400 { InvalidJsonFormat, UnknownError ), - List(apiTagManageDynamicEndpoint, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagApi, apiTagNewStyle), Some(List(canUpdateDynamicEndpoint))) lazy val updateEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tag" :: endpointTagId :: Nil JsonPut json -> _ => { @@ -9162,7 +9166,12 @@ trait APIMethods400 { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { json.extract[EndpointTagJson400] } + (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) + (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name}), please choose another tag_name", cc=callContext) { + (!endpointTagExisted) + } (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(Some(endpointTagId),operationId,endpointTag.tag_name), cc.callContext) } yield { (EndpointTagResponseJson400( diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 78b54a390..a4fd2da36 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1560,6 +1560,8 @@ trait Connector extends MdcLoggable { def createOrUpdateAtm(atm: AtmT, callContext: Option[CallContext]): OBPReturnType[Box[AtmT]] = Future{Failure(setUnimplementedError)} def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + + def getEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index c43f4ee3b..8b710f7aa 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2491,7 +2491,6 @@ object LocalMappedConnector extends Connector with MdcLoggable { case Full(x) => tryo { x - .OperationId(endpointTag.operationId) .TagName(endpointTag.tagName) .saveMe() } ?~! UpdateEndpointTagError @@ -2506,6 +2505,13 @@ object LocalMappedConnector extends Connector with MdcLoggable { Failure(UnknownEndpointTagError) }, callContext) } + + override def getEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + (EndpointTag.find( + By(EndpointTag.OperationId, operationId), + By(EndpointTag.TagName, tagName), + ), callContext) + } override def createOrUpdateAtmLegacy(atm: AtmT): Box[AtmT] = { diff --git a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala index 861daf87d..1770e8356 100644 --- a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala +++ b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala @@ -57,5 +57,5 @@ class EndpointTag extends EndpointTagT with LongKeyedMapper[EndpointTag] with Id } object EndpointTag extends EndpointTag with LongKeyedMetaMapper[EndpointTag] { - override def dbIndexes = UniqueIndex(EndpointTagId) :: super.dbIndexes + override def dbIndexes = UniqueIndex(EndpointTagId) :: UniqueIndex(OperationId, TagName) ::super.dbIndexes } \ No newline at end of file From 57478ec511c5c26b6cca383febe5e156ed8534bb Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 29 Jul 2021 16:25:50 +0200 Subject: [PATCH 006/293] feature/added the getEndpointTags endpoint --- .../scala/code/api/util/ErrorMessages.scala | 2 +- .../main/scala/code/api/util/NewStyle.scala | 6 ++ .../scala/code/api/v4_0_0/APIMethods400.scala | 76 +++++++++++++++++-- .../scala/code/bankconnectors/Connector.scala | 2 + .../bankconnectors/LocalMappedConnector.scala | 4 + 5 files changed, 83 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index c9b7ccf5c..2fd57dfd3 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -561,7 +561,7 @@ object ErrorMessages { val InvalidConnectorResponseForCreateChallenge = "OBP-50215: Connector did not return the set of challenge we requested." val InvalidConnectorResponseForSaveDoubleEntryBookTransaction = "OBP-50216: The Connector did not return a valid response for saving double-entry transaction." val InvalidConnectorResponseForCancelPayment = "OBP-50217: Connector did not return the transaction we requested." - + val InvalidConnectorResponseForGetEndpointTags = "OBP-50218: Connector did not return the set of endpoint tags we requested." // Adapter Exceptions (OBP-6XXXX) // Reserved for adapter (south of Kafka) messages diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index f583add94..39fcb1b57 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -291,6 +291,12 @@ object NewStyle { i => (unboxFullOrFail(i._1, callContext, s"$EndpointTagNotFoundByEndpointTagId Current ENDPOINT_TAG_ID is $endpointTagId", 404), i._2) } } + + def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[List[EndpointTagT]] = { + Connector.connector.vend.getEndpointTags(operationId, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForGetEndpointTags Current OPERATION_ID is $operationId", 404), i._2) + } + } def getBank(bankId : BankId, callContext: Option[CallContext]) : OBPReturnType[Bank] = { Connector.connector.vend.getBank(bankId, callContext) map { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 4e75e4cd2..cbbe9c3ec 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9105,7 +9105,7 @@ trait APIMethods400 { implementedInApiVersion, nameOf(createEndpointTag), "POST", - "/management/endpoints/OPERATION_ID/tag", + "/management/endpoints/OPERATION_ID/tags", "Create Endpoint Tag", s"""Create Endpoint Tag""", endpointTagJson400, @@ -9117,9 +9117,9 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canCreateDynamicEndpoint))) + Some(List(canCreateEndpointTag))) lazy val createEndpointTag: OBPEndpoint = { - case "management" :: "endpoints" :: operationId :: "tag" :: Nil JsonPost json -> _ => { + case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { cc => for { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { @@ -9145,7 +9145,7 @@ trait APIMethods400 { implementedInApiVersion, nameOf(updateEndpointTag), "PUT", - "/management/endpoints/OPERATION_ID/tag/ENDPOINT_TAG_ID", + "/management/endpoints/OPERATION_ID/tags/ENDPOINT_TAG_ID", "Update Endpoint Tag", s"""Update Endpoint Tag, you can only update the tag_name here, operation_id can not be updated.""", endpointTagJson400, @@ -9158,9 +9158,9 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canUpdateDynamicEndpoint))) + Some(List(canUpdateEndpointTag))) lazy val updateEndpointTag: OBPEndpoint = { - case "management" :: "endpoints" :: operationId :: "tag" :: endpointTagId :: Nil JsonPut json -> _ => { + case "management" :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonPut json -> _ => { cc => for { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { @@ -9182,6 +9182,70 @@ trait APIMethods400 { } } } + + staticResourceDocs += ResourceDoc( + getEndpointTags, + implementedInApiVersion, + nameOf(getEndpointTags), + "GET", + "/management/endpoints/OPERATION_ID/tags", + "Get Endpoint Tags", + s"""Get Endpoint Tags.""", + EmptyBody, + endpointTagResponseJson400 :: Nil, + List( + $UserNotLoggedIn, + UserHasMissingRoles, + UnknownError + ), + List(apiTagApi, apiTagApi, apiTagNewStyle), + Some(List(canGetEndpointTag))) + lazy val getEndpointTags: OBPEndpoint = { + case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { + cc => + for { + (endpointTags, callContext) <- NewStyle.function.getEndpointTags(operationId, cc.callContext) + } yield { + (endpointTags.map(endpointTagT => EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + )), HttpCode.`201`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getEndpointTags, + implementedInApiVersion, + nameOf(getEndpointTags), + "GET", + "/management/endpoints/OPERATION_ID/tags", + "Get Endpoint Tags", + s"""Get Endpoint Tags.""", + EmptyBody, + endpointTagResponseJson400 :: Nil, + List( + $UserNotLoggedIn, + UserHasMissingRoles, + UnknownError + ), + List(apiTagApi, apiTagApi, apiTagNewStyle), + Some(List(canGetEndpointTag))) + lazy val getEndpointTags: OBPEndpoint = { + case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { + cc => + for { + (endpointTags, callContext) <- NewStyle.function.getEndpointTags(operationId, cc.callContext) + } yield { + (endpointTags.map(endpointTagT => EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + )), HttpCode.`201`(cc.callContext)) + } + } + } } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index a4fd2da36..638ba09b5 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1565,6 +1565,8 @@ trait Connector extends MdcLoggable { def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) + def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future(Failure(setUnimplementedError)) + def createOrUpdateProduct( bankId : String, code : String, diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 8b710f7aa..d77dface3 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2483,6 +2483,10 @@ object LocalMappedConnector extends Connector with MdcLoggable { override def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future( (EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)), callContext) ) + + override def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future( + (tryo{EndpointTag.findAll(By(EndpointTag.OperationId, operationId))}, callContext) + ) override def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ (EndpointTag.find( From e4e326e393698d80d767958558baf4dd58edb768 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 29 Jul 2021 16:54:33 +0200 Subject: [PATCH 007/293] feature/added the deleteEndpointTag endpoint --- .../main/scala/code/api/util/NewStyle.scala | 6 ++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 30 +++++++++---------- .../scala/code/bankconnectors/Connector.scala | 2 ++ .../bankconnectors/LocalMappedConnector.scala | 4 +++ 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 39fcb1b57..6daf86b1f 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -292,6 +292,12 @@ object NewStyle { } } + def deleteEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Boolean] = { + Connector.connector.vend.deleteEndpointTag(endpointTagId, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$UnknownEndpointTagError Current ENDPOINT_TAG_ID is $endpointTagId", 404), i._2) + } + } + def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[List[EndpointTagT]] = { Connector.connector.vend.getEndpointTags(operationId, callContext) map { i => (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForGetEndpointTags Current OPERATION_ID is $operationId", 404), i._2) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index cbbe9c3ec..5507b2e98 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9216,33 +9216,31 @@ trait APIMethods400 { } staticResourceDocs += ResourceDoc( - getEndpointTags, + deleteEndpointTag, implementedInApiVersion, - nameOf(getEndpointTags), - "GET", - "/management/endpoints/OPERATION_ID/tags", - "Get Endpoint Tags", - s"""Get Endpoint Tags.""", + nameOf(deleteEndpointTag), + "DELETE", + "/management/endpoints/OPERATION_ID/tags/ENDPOINT_TAG_ID", + "Delete Endpoint Tag", + s"""Delete Endpoint Tag.""", EmptyBody, - endpointTagResponseJson400 :: Nil, + Full(true), List( $UserNotLoggedIn, UserHasMissingRoles, UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canGetEndpointTag))) - lazy val getEndpointTags: OBPEndpoint = { - case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { + Some(List(canDeleteEndpointTag))) + lazy val deleteEndpointTag: OBPEndpoint = { + case "management" :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonDelete _ => { cc => for { - (endpointTags, callContext) <- NewStyle.function.getEndpointTags(operationId, cc.callContext) + (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) + + (deleted, callContext) <- NewStyle.function.deleteEndpointTag(endpointTagId, cc.callContext) } yield { - (endpointTags.map(endpointTagT => EndpointTagResponseJson400( - endpointTagT.endpointTagId.getOrElse(""), - endpointTagT.operationId, - endpointTagT.tagName - )), HttpCode.`201`(cc.callContext)) + (Full(deleted), HttpCode.`200`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 638ba09b5..1a16d2b70 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1565,6 +1565,8 @@ trait Connector extends MdcLoggable { def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) + def deleteEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[Boolean]] = Future(Failure(setUnimplementedError)) + def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future(Failure(setUnimplementedError)) def createOrUpdateProduct( diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index d77dface3..58da604c7 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2484,6 +2484,10 @@ object LocalMappedConnector extends Connector with MdcLoggable { (EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)), callContext) ) + override def deleteEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[Boolean]] = Future( + (EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)).map(_.delete_!), callContext) + ) + override def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future( (tryo{EndpointTag.findAll(By(EndpointTag.OperationId, operationId))}, callContext) ) From f8e83d57cf05f3fdcc97f03d923bf7de7dffce16 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 30 Jul 2021 14:54:36 +0200 Subject: [PATCH 008/293] feature/added the bankLevel CURD EndpointTag endpoints --- .../main/scala/code/api/util/ApiRole.scala | 12 ++ .../code/api/v1_4_0/JSONFactory1_4_0.scala | 6 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 148 ++++++++++++++++++ .../scala/code/bankconnectors/Connector.scala | 2 + .../bankconnectors/LocalMappedConnector.scala | 7 +- .../MappedEndpointMappingProvider.scala | 2 +- 6 files changed, 173 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 1b177725d..e139c93fb 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -776,6 +776,18 @@ object ApiRole { case class CanGetEndpointTag(requiresBankId: Boolean = false) extends ApiRole lazy val canGetEndpointTag = CanGetEndpointTag() + case class CanBankLevelCreateEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canBankLevelCreateEndpointTag = CanBankLevelCreateEndpointTag() + + case class CanBankLevelUpdateEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canBankLevelUpdateEndpointTag = CanBankLevelUpdateEndpointTag() + + case class CanBankLevelDeleteEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canBankLevelDeleteEndpointTag = CanBankLevelDeleteEndpointTag() + + case class CanBankLevelGetEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canBankLevelGetEndpointTag = CanBankLevelGetEndpointTag() + private val dynamicApiRoles = new ConcurrentHashMap[String, ApiRole] private case class DynamicApiRole(role: String, requiresBankId: Boolean = false) extends ApiRole{ diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index 68511e926..467f69235 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -6,6 +6,7 @@ import java.util.Date import code.api.util.APIUtil.{EmptyBody, PrimaryDataBody, ResourceDoc} import code.api.util.Glossary.glossaryItems import code.api.util.{APIUtil, ApiRole, ConnectorField, CustomJsonFormats, ExampleValue, PegdownOptions} +import code.bankconnectors.LocalMappedConnector.getEndpointTagsBox import com.openbankproject.commons.model.ListResult import code.crm.CrmEvent.CrmEvent import com.openbankproject.commons.model.TransactionRequestTypeCharge @@ -17,7 +18,6 @@ import net.liftweb.json.Extraction.decompose import net.liftweb.json.{Formats, JDouble, JInt, JString} import net.liftweb.json.JsonAST.{JArray, JBool, JNothing, JObject, JValue} import net.liftweb.util.StringHelpers - import code.util.Helper.MdcLoggable import org.apache.commons.lang3.StringUtils @@ -480,6 +480,8 @@ object JSONFactory1_4_0 extends MdcLoggable{ } val description = rd.description.stripMargin.trim ++ fieldsDescription + + val endpointTags = getEndpointTagsBox(rd.operationId).map(_.tagName) ResourceDocJson( operation_id = rd.operationId, @@ -493,7 +495,7 @@ object JSONFactory1_4_0 extends MdcLoggable{ success_response_body = rd.successResponseBody, error_response_bodies = rd.errorResponseBodies, implemented_by = ImplementedByJson(rd.implementedInApiVersion.fullyQualifiedVersion, rd.partialFunctionName), // was rd.implementedInApiVersion.noV - tags = rd.tags.map(i => i.tag), + tags = endpointTags ++ rd.tags.map(i => i.tag), typed_request_body = createTypedBody(rd.exampleRequestBody), typed_success_response_body = createTypedBody(rd.successResponseBody), roles = rd.roles, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 5507b2e98..95662f475 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9245,6 +9245,154 @@ trait APIMethods400 { } } + staticResourceDocs += ResourceDoc( + createBankLevelEndpointTag, + implementedInApiVersion, + nameOf(createBankLevelEndpointTag), + "POST", + "/management/banks/BANK_ID/endpoints/OPERATION_ID/tags", + "Create Bank Level Endpoint Tag", + s"""Create Bank Level Endpoint Tag""", + endpointTagJson400, + endpointTagResponseJson400, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + InvalidJsonFormat, + UnknownError + ), + List(apiTagApi, apiTagApi, apiTagNewStyle), + Some(List(canBankLevelCreateEndpointTag))) + lazy val createBankLevelEndpointTag: OBPEndpoint = { + case "management" :: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { + cc => + for { + endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { + json.extract[EndpointTagJson400] + } + (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name})", cc=callContext) { + (!endpointTagExisted) + } + (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(None,operationId,endpointTag.tag_name), cc.callContext) + } yield { + (EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + ), HttpCode.`201`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + updateBankLevelEndpointTag, + implementedInApiVersion, + nameOf(updateBankLevelEndpointTag), + "PUT", + "/management/banks/BANK_ID/endpoints/OPERATION_ID/tags/ENDPOINT_TAG_ID", + "Update Bank Level Endpoint Tag", + s"""Update Endpoint Tag, you can only update the tag_name here, operation_id can not be updated.""", + endpointTagJson400, + endpointTagResponseJson400, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + EndpointTagNotFoundByEndpointTagId, + InvalidJsonFormat, + UnknownError + ), + List(apiTagApi, apiTagApi, apiTagNewStyle), + Some(List(canBankLevelUpdateEndpointTag))) + lazy val updateBankLevelEndpointTag: OBPEndpoint = { + case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonPut json -> _ => { + cc => + for { + endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { + json.extract[EndpointTagJson400] + } + (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) + (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name}), please choose another tag_name", cc=callContext) { + (!endpointTagExisted) + } + (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(Some(endpointTagId),operationId,endpointTag.tag_name), cc.callContext) + } yield { + (EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + ), HttpCode.`201`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getBankLevelEndpointTags, + implementedInApiVersion, + nameOf(getBankLevelEndpointTags), + "GET", + "/management/banks/BANK_ID/endpoints/OPERATION_ID/tags", + "Get Bank Level Endpoint Tags", + s"""Get Bank Level Endpoint Tags.""", + EmptyBody, + endpointTagResponseJson400 :: Nil, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagApi, apiTagApi, apiTagNewStyle), + Some(List(canBankLevelGetEndpointTag))) + lazy val getBankLevelEndpointTags: OBPEndpoint = { + case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { + cc => + for { + (endpointTags, callContext) <- NewStyle.function.getEndpointTags(operationId, cc.callContext) + } yield { + (endpointTags.map(endpointTagT => EndpointTagResponseJson400( + endpointTagT.endpointTagId.getOrElse(""), + endpointTagT.operationId, + endpointTagT.tagName + )), HttpCode.`201`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + deleteBankLevelEndpointTag, + implementedInApiVersion, + nameOf(deleteBankLevelEndpointTag), + "DELETE", + "/management/banks/BANK_ID/endpoints/OPERATION_ID/tags/ENDPOINT_TAG_ID", + "Delete Bank Level Endpoint Tag", + s"""Delete Bank Level Endpoint Tag.""", + EmptyBody, + Full(true), + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagApi, apiTagApi, apiTagNewStyle), + Some(List(canBankLevelDeleteEndpointTag))) + lazy val deleteBankLevelEndpointTag: OBPEndpoint = { + case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonDelete _ => { + cc => + for { + (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) + + (deleted, callContext) <- NewStyle.function.deleteEndpointTag(endpointTagId, cc.callContext) + } yield { + (Full(deleted), HttpCode.`200`(callContext)) + } + } + } + } private def createDynamicEndpointMethod(bankId: Option[String], json: JValue, cc: CallContext) = { diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 1a16d2b70..0ec26546e 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1565,6 +1565,8 @@ trait Connector extends MdcLoggable { def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) + def getBankLevelEndpointTag(bankId:String, endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) + def deleteEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[Boolean]] = Future(Failure(setUnimplementedError)) def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future(Failure(setUnimplementedError)) diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 58da604c7..01010bf24 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2489,8 +2489,13 @@ object LocalMappedConnector extends Connector with MdcLoggable { ) override def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future( - (tryo{EndpointTag.findAll(By(EndpointTag.OperationId, operationId))}, callContext) + (tryo{getEndpointTagsBox(operationId : String)}, callContext) ) + + def getEndpointTagsBox(operationId : String) : List[EndpointTagT] = EndpointTag.findAll( + By(EndpointTag.OperationId, operationId), + OrderBy(EndpointTag.updatedAt, Descending) + ) override def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ (EndpointTag.find( diff --git a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala index 1770e8356..d2c1b60a3 100644 --- a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala +++ b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala @@ -43,7 +43,7 @@ object MappedEndpointTagProvider extends EndpointTagProvider with CustomJsonForm override def getAllEndpointTags: List[EndpointTagT] = EndpointTag.findAll() } -class EndpointTag extends EndpointTagT with LongKeyedMapper[EndpointTag] with IdPK with CustomJsonFormats{ +class EndpointTag extends EndpointTagT with LongKeyedMapper[EndpointTag] with IdPK with CreatedUpdated with CustomJsonFormats{ override def getSingleton = EndpointTag From a79a04cf1f0b4a62ad26c6161c6acac4293576a5 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 30 Jul 2021 15:43:16 +0200 Subject: [PATCH 009/293] feature/WIP --- obp-api/src/main/scala/code/api/util/NewStyle.scala | 2 +- .../main/scala/code/api/v4_0_0/APIMethods400.scala | 12 ++++++------ .../main/scala/code/bankconnectors/Connector.scala | 2 ++ .../code/bankconnectors/LocalMappedConnector.scala | 10 ++++++++++ .../code/endpointTag/EndpointMappingProvider.scala | 7 +++++-- .../endpointTag/MappedEndpointMappingProvider.scala | 4 +++- 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 6daf86b1f..04aa1b6c6 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -280,7 +280,7 @@ object NewStyle { } } - def checkEndpointTagExists(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Boolean] = { + def checkEndpointTagExists(bankId: Option[String], operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Boolean] = { Connector.connector.vend.getEndpointTag(operationId: String, tagName:String, callContext) map { i => (i._1.isDefined, i._2) } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 95662f475..cb6663ced 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9101,13 +9101,13 @@ trait APIMethods400 { } staticResourceDocs += ResourceDoc( - createEndpointTag, + createSystemLevelEndpointTag, implementedInApiVersion, - nameOf(createEndpointTag), + nameOf(createSystemLevelEndpointTag), "POST", "/management/endpoints/OPERATION_ID/tags", - "Create Endpoint Tag", - s"""Create Endpoint Tag""", + "Create System Level Endpoint Tag", + s"""Create System Level Endpoint Tag""", endpointTagJson400, endpointTagResponseJson400, List( @@ -9118,14 +9118,14 @@ trait APIMethods400 { ), List(apiTagApi, apiTagApi, apiTagNewStyle), Some(List(canCreateEndpointTag))) - lazy val createEndpointTag: OBPEndpoint = { + lazy val createSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { cc => for { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { json.extract[EndpointTagJson400] } - (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(None, operationId, endpointTag.tag_name, cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name})", cc=callContext) { (!endpointTagExisted) } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 0ec26546e..79b7f0f44 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1562,6 +1562,8 @@ trait Connector extends MdcLoggable { def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} def getEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + + def getBankLevelEndpointTag(bankId: String, operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 01010bf24..e84e8889b 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2525,7 +2525,17 @@ object LocalMappedConnector extends Connector with MdcLoggable { By(EndpointTag.TagName, tagName), ), callContext) } + + override def getBankLevelEndpointTag(bankId: String, operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + (EndpointTag.find( + By(EndpointTag.OperationId, operationId), + By(EndpointTag.TagName, tagName), + By(EndpointTag.TagName, tagName), + ), callContext) + } + + override def createOrUpdateAtmLegacy(atm: AtmT): Box[AtmT] = { val isAccessibleString = optionBooleanToString(atm.isAccessible) diff --git a/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala index 2f4db28e7..382adcba7 100644 --- a/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala +++ b/obp-api/src/main/scala/code/endpointTag/EndpointMappingProvider.scala @@ -18,13 +18,15 @@ object EndpointTagProvider extends SimpleInjector { trait EndpointTagT { def endpointTagId: Option[String] def operationId: String - def tagName: String + def tagName: String + def bankId: Option[String] } case class EndpointTagCommons( endpointTagId: Option[String], operationId: String, tagName: String, + bankId: Option[String], ) extends EndpointTagT with JsonFieldReName { /** * when serialized to json, the Option field will be not shown, this endpoint just generate a full fields json, include all None value fields @@ -34,7 +36,8 @@ case class EndpointTagCommons( JObject(List( JField("operation_id", JString(this.operationId)), JField("endpoint_mapping_id", this.endpointTagId.map(JString(_)).getOrElse(JNull)), - JField("tagName", JString(this.tagName)) + JField("tagName", JString(this.tagName)), + JField("bankId", JString(this.bankId.getOrElse(""))) )) } } diff --git a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala index d2c1b60a3..8f8ce64bd 100644 --- a/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala +++ b/obp-api/src/main/scala/code/endpointTag/MappedEndpointMappingProvider.scala @@ -50,12 +50,14 @@ class EndpointTag extends EndpointTagT with LongKeyedMapper[EndpointTag] with Id object EndpointTagId extends MappedUUID(this) object OperationId extends MappedString(this, 255) object TagName extends MappedString(this, 255) + object BankId extends MappedString(this, 255) override def endpointTagId: Option[String] = Option(EndpointTagId.get) override def operationId: String = OperationId.get override def tagName: String = TagName.get + override def bankId: Option[String] = if (BankId.get == null || BankId.get.isEmpty) None else Some(BankId.get) } object EndpointTag extends EndpointTag with LongKeyedMetaMapper[EndpointTag] { - override def dbIndexes = UniqueIndex(EndpointTagId) :: UniqueIndex(OperationId, TagName) ::super.dbIndexes + override def dbIndexes = UniqueIndex(EndpointTagId) ::super.dbIndexes } \ No newline at end of file From 968f1070715dff760303cc58cbdbdeca27bbd595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 2 Aug 2021 16:54:12 +0200 Subject: [PATCH 010/293] feature/Add a function in order to use glosarry item at resource doc --- .../src/main/scala/code/api/util/Glossary.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index e4a4f1e02..2d903f0d5 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -10,6 +10,23 @@ import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue object Glossary { + def getGlossaryItemAsHtml(title: String): String = { + glossaryItems.find(_.title.toLowerCase == title.toLowerCase) match { + case Some(foundItem) => + val buttonTitle = foundItem.title + val id = foundItem.title.replace(" ", "-").toLowerCase + s""" + |
+ | + | + |
+ |

+ |""".stripMargin + case None => "" + } + + } + // reason of description is function: because we want make description is dynamic, so description can read // webui_ props dynamic instead of a constant string. case class GlossaryItem( From 7e491f2ca219ec955651fcf6d424be3c86294ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 2 Aug 2021 18:20:05 +0200 Subject: [PATCH 011/293] =?UTF-8?q?feature/Add=20a=20function=20in=20order?= =?UTF-8?q?=20to=20make=20=D0=B0=20collapsible=20section=20containing=20ma?= =?UTF-8?q?rkdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/scala/code/api/util/Glossary.scala | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 2d903f0d5..80063d7f5 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -10,18 +10,21 @@ import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue object Glossary { - def getGlossaryItemAsHtml(title: String): String = { + def getGlossaryItem(title: String): String = { glossaryItems.find(_.title.toLowerCase == title.toLowerCase) match { case Some(foundItem) => - val buttonTitle = foundItem.title - val id = foundItem.title.replace(" ", "-").toLowerCase - s""" - |
- | - | - |
- |

- |""".stripMargin + /** + * Two important rules: + * 1. Make sure you have an **empty line** after the closing `` tag, otherwise the markdown/code blocks won't show correctly. + * 2. Make sure you have an **empty line** after the closing `` tag if you have multiple collapsible sections. + */ + s""" + |
+ | ${foundItem.title} + | + | ${foundItem.description.apply()} + |
+ |""".stripMargin case None => "" } @@ -113,7 +116,7 @@ object Glossary { title = "Cheat Sheet", description = s""" - |## A selection of links to get you started using the Open Bank Project API platform, applications and tools. + |### A selection of links to get you started using the Open Bank Project API platform, applications and tools. | |[OBP API Installation](https://github.com/OpenBankProject/OBP-API/blob/develop/README.md) | From 55516a42d23210c260806e3c069be654356d8d3c Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 2 Aug 2021 23:18:06 +0200 Subject: [PATCH 012/293] feature/added the bank level endpoint tag endpoints --- .../SwaggerDefinitionsJSON.scala | 9 +- .../main/scala/code/api/util/ApiRole.scala | 32 +-- .../main/scala/code/api/util/NewStyle.scala | 46 ++++- .../code/api/v1_4_0/JSONFactory1_4_0.scala | 4 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 147 +++++++------- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 9 +- .../scala/code/bankconnectors/Connector.scala | 18 +- .../bankconnectors/LocalMappedConnector.scala | 101 +++++++--- .../code/api/v4_0_0/EndpointTagTest.scala | 189 ++++++++++++++++++ 9 files changed, 420 insertions(+), 135 deletions(-) create mode 100644 obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index b91e54f5b..1b8e0eb82 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -2440,7 +2440,14 @@ object SwaggerDefinitionsJSON { tag_name = tagNameExample.value ) - val endpointTagResponseJson400 = EndpointTagResponseJson400( + val systemLevelEndpointTagResponseJson400 = SystemLevelEndpointTagResponseJson400( + endpoint_tag_id = endpointTagIdExample.value, + operation_id = operationIdExample.value, + tag_name = tagNameExample.value + ) + + val bankLevelEndpointTagResponseJson400 = BankLevelEndpointTagResponseJson400( + bank_id = bankIdExample.value, endpoint_tag_id = endpointTagIdExample.value, operation_id = operationIdExample.value, tag_name = tagNameExample.value diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index e139c93fb..2d2d07055 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -764,29 +764,29 @@ object ApiRole { case class CanGetUserInvitation(requiresBankId: Boolean = true) extends ApiRole lazy val canGetUserInvitation = CanGetUserInvitation() - case class CanCreateEndpointTag(requiresBankId: Boolean = false) extends ApiRole - lazy val canCreateEndpointTag = CanCreateEndpointTag() + case class CanCreateSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canSystemLevelCreateEndpointTag = CanCreateSystemLevelEndpointTag() - case class CanUpdateEndpointTag(requiresBankId: Boolean = false) extends ApiRole - lazy val canUpdateEndpointTag = CanUpdateEndpointTag() + case class CanUpdateSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canUpdateSystemLevelEndpointTag = CanUpdateSystemLevelEndpointTag() - case class CanDeleteEndpointTag(requiresBankId: Boolean = false) extends ApiRole - lazy val canDeleteEndpointTag = CanDeleteEndpointTag() + case class CanDeleteSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canDeleteSystemLevelEndpointTag = CanDeleteSystemLevelEndpointTag() - case class CanGetEndpointTag(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetEndpointTag = CanGetEndpointTag() + case class CanGetSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLevelEndpointTag = CanGetSystemLevelEndpointTag() - case class CanBankLevelCreateEndpointTag(requiresBankId: Boolean = true) extends ApiRole - lazy val canBankLevelCreateEndpointTag = CanBankLevelCreateEndpointTag() + case class CanCreateBankLevelEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canCreateBankLevelEndpointTag = CanCreateBankLevelEndpointTag() - case class CanBankLevelUpdateEndpointTag(requiresBankId: Boolean = true) extends ApiRole - lazy val canBankLevelUpdateEndpointTag = CanBankLevelUpdateEndpointTag() + case class CanUpdateBankLevelEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canUpdateBankLevelEndpointTag = CanUpdateBankLevelEndpointTag() - case class CanBankLevelDeleteEndpointTag(requiresBankId: Boolean = true) extends ApiRole - lazy val canBankLevelDeleteEndpointTag = CanBankLevelDeleteEndpointTag() + case class CanDeleteBankLevelEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canDeleteBankLevelEndpointTag = CanDeleteBankLevelEndpointTag() - case class CanBankLevelGetEndpointTag(requiresBankId: Boolean = true) extends ApiRole - lazy val canBankLevelGetEndpointTag = CanBankLevelGetEndpointTag() + case class CanGetBankLevelEndpointTag(requiresBankId: Boolean = true) extends ApiRole + lazy val canGetBankLevelEndpointTag = CanGetBankLevelEndpointTag() private val dynamicApiRoles = new ConcurrentHashMap[String, ApiRole] diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 04aa1b6c6..b010d6389 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -273,21 +273,45 @@ object NewStyle { i => (unboxFullOrFail(i._1, callContext, s"$CreateAtmError", 400), i._2) } } - - def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[EndpointTagT] = { - Connector.connector.vend.createOrUpdateEndpointTag(endpointTag, callContext) map { + + def createSystemLevelEndpointTag(operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[EndpointTagT] = { + Connector.connector.vend.createSystemLevelEndpointTag(operationId, tagName, callContext) map { i => (unboxFullOrFail(i._1, callContext, s"$CreateEndpointTagError", 400), i._2) } } - def checkEndpointTagExists(bankId: Option[String], operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Boolean] = { - Connector.connector.vend.getEndpointTag(operationId: String, tagName:String, callContext) map { + def updateSystemLevelEndpointTag(endpointTagId: String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[EndpointTagT] = { + Connector.connector.vend.updateSystemLevelEndpointTag(endpointTagId: String, operationId:String, tagName:String, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$UpdateEndpointTagError", 400), i._2) + } + } + + def createBankLevelEndpointTag(bankId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[EndpointTagT] = { + Connector.connector.vend.createBankLevelEndpointTag(bankId, operationId, tagName, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$CreateEndpointTagError", 400), i._2) + } + } + + def updateBankLevelEndpointTag(bankId:String, endpointTagId: String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[EndpointTagT] = { + Connector.connector.vend.updateBankLevelEndpointTag(bankId, endpointTagId, operationId, tagName, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$UpdateEndpointTagError", 400), i._2) + } + } + + def checkSystemLevelEndpointTagExists(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Boolean] = { + Connector.connector.vend.getSystemLevelEndpointTag(operationId: String, tagName: String, callContext) map { + i => (i._1.isDefined, i._2) + } + } + + def checkBankLevelEndpointTagExists(bankId: String, operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Boolean] = { + Connector.connector.vend.getBankLevelEndpointTag(bankId: String, operationId: String, tagName: String, callContext) map { i => (i._1.isDefined, i._2) } } def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[EndpointTagT] = { - Connector.connector.vend.getEndpointTag(endpointTagId, callContext) map { + Connector.connector.vend.getEndpointTagById(endpointTagId, callContext) map { i => (unboxFullOrFail(i._1, callContext, s"$EndpointTagNotFoundByEndpointTagId Current ENDPOINT_TAG_ID is $endpointTagId", 404), i._2) } } @@ -298,8 +322,14 @@ object NewStyle { } } - def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[List[EndpointTagT]] = { - Connector.connector.vend.getEndpointTags(operationId, callContext) map { + def getSystemLevelEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[List[EndpointTagT]] = { + Connector.connector.vend.getSystemLevelEndpointTags(operationId, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForGetEndpointTags Current OPERATION_ID is $operationId", 404), i._2) + } + } + + def getBankLevelEndpointTags(bankId:String, operationId : String, callContext: Option[CallContext]) : OBPReturnType[List[EndpointTagT]] = { + Connector.connector.vend.getBankLevelEndpointTags(bankId, operationId, callContext) map { i => (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForGetEndpointTags Current OPERATION_ID is $operationId", 404), i._2) } } diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index 467f69235..bbdc7ab63 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -6,7 +6,7 @@ import java.util.Date import code.api.util.APIUtil.{EmptyBody, PrimaryDataBody, ResourceDoc} import code.api.util.Glossary.glossaryItems import code.api.util.{APIUtil, ApiRole, ConnectorField, CustomJsonFormats, ExampleValue, PegdownOptions} -import code.bankconnectors.LocalMappedConnector.getEndpointTagsBox +import code.bankconnectors.LocalMappedConnector.getAllEndpointTagsBox import com.openbankproject.commons.model.ListResult import code.crm.CrmEvent.CrmEvent import com.openbankproject.commons.model.TransactionRequestTypeCharge @@ -481,7 +481,7 @@ object JSONFactory1_4_0 extends MdcLoggable{ val description = rd.description.stripMargin.trim ++ fieldsDescription - val endpointTags = getEndpointTagsBox(rd.operationId).map(_.tagName) + val endpointTags = getAllEndpointTagsBox(rd.operationId).map(_.tagName) ResourceDocJson( operation_id = rd.operationId, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index cb6663ced..10d448c4e 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -3,7 +3,6 @@ package code.api.v4_0_0 import code.DynamicData.{DynamicData, DynamicDataProvider} import code.DynamicEndpoint.DynamicEndpointSwagger import code.accountattribute.AccountAttributeX -import code.api.{ChargePolicy, JsonResponseException} import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil.{fullBoxOrException, _} import code.api.util.ApiRole._ @@ -23,25 +22,29 @@ import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0 import code.api.v2_0_0.{EntitlementJSONs, JSONFactory200} import code.api.v2_1_0._ import code.api.v3_0_0.JSONFactory300 -import code.api.v3_0_0.JSONFactory300.transformToAtmFromV300 import code.api.v3_1_0._ +import code.api.v4_0_0.JSONFactory400._ import code.api.v4_0_0.dynamic.DynamicEndpointHelper.DynamicReq -import code.api.v4_0_0.JSONFactory400.{createAccountBalancesJson, createBalancesJson, createBankAccountJSON, createCallsLimitJson, createNewCoreBankAccountJson} -import code.api.v4_0_0.dynamic.practise.PractiseEndpoint -import code.api.v4_0_0.dynamic.{CompiledObjects, DynamicEndpointHelper, DynamicEntityHelper, DynamicEntityInfo, EntityName, MockResponseHolder} +import code.api.v4_0_0.dynamic.practise.{DynamicEndpointCodeGenerator, PractiseEndpoint} +import code.api.v4_0_0.dynamic._ +import code.api.{ChargePolicy, JsonResponseException} import code.apicollection.MappedApiCollectionsProvider import code.apicollectionendpoint.MappedApiCollectionEndpointsProvider import code.authtypevalidation.JsonAuthTypeValidation import code.bankconnectors.{Connector, DynamicConnector, InternalConnector} import code.connectormethod.{JsonConnectorMethod, JsonConnectorMethodMethodBody} -import code.consent.{ConsentStatus, Consents, MappedConsent} +import code.consent.{ConsentStatus, Consents} import code.dynamicEntity.{DynamicEntityCommons, ReferenceType} +import code.dynamicMessageDoc.JsonDynamicMessageDoc +import code.dynamicResourceDoc.JsonDynamicResourceDoc +import code.endpointMapping.EndpointMappingCommons import code.entitlement.Entitlement import code.metadata.counterparties.{Counterparties, MappedCounterparty} import code.metadata.tags.Tags import code.model.dataAccess.{AuthUser, BankAccountCreation} import code.model.{toUserExtended, _} import code.ratelimiting.RateLimitingDI +import code.snippet.{WebUIPlaceholder, WebUITemplate} import code.transactionChallenge.MappedExpectedChallengeAnswer import code.transactionrequests.MappedTransactionRequestProvider import code.transactionrequests.TransactionRequests.TransactionChallengeTypes._ @@ -53,38 +56,30 @@ import code.util.Helper.booleanToFuture import code.util.{Helper, JsonSchemaUtil} import code.validation.JsonValidation import code.views.Views +import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global -import com.openbankproject.commons.model.{ListResult, _} import com.openbankproject.commons.model.enums.DynamicEntityOperation._ import com.openbankproject.commons.model.enums.{TransactionRequestStatus, _} +import com.openbankproject.commons.model.{ListResult, _} import com.openbankproject.commons.util.{ApiVersion, JsonUtils, ScannedApiVersion} import deletion.{DeleteAccountCascade, DeleteProductCascade, DeleteTransactionCascade} -import net.liftweb.common.{Box, Empty, Failure, Full, ParamFailure} +import net.liftweb.common._ import net.liftweb.http.rest.RestHelper import net.liftweb.http.{JsonResponse, Req, S} -import net.liftweb.json.JsonAST.{JField, JValue} +import net.liftweb.json.JsonAST.JValue import net.liftweb.json.JsonDSL._ import net.liftweb.json.Serialization.write import net.liftweb.json.{compactRender, prettyRender, _} import net.liftweb.mapper.By import net.liftweb.util.Helpers.now +import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To, XHTMLMailBodyType} import net.liftweb.util.{Helpers, Mailer, StringHelpers} import org.apache.commons.collections4.CollectionUtils import org.apache.commons.lang3.StringUtils -import java.util.{Calendar, Date} -import code.dynamicMessageDoc.JsonDynamicMessageDoc -import code.dynamicResourceDoc.JsonDynamicResourceDoc import java.net.URLEncoder - -import code.api.v4_0_0.dynamic.practise.DynamicEndpointCodeGenerator -import code.endpointMapping.EndpointMappingCommons -import code.snippet.{WebUIPlaceholder, WebUITemplate} -import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue -import net.liftweb.json -import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To, XHTMLMailBodyType} - +import java.util.{Calendar, Date} import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future @@ -4888,7 +4883,7 @@ trait APIMethods400 { nameOf(getDynamicEndpoint), "GET", "/management/dynamic-endpoints/DYNAMIC_ENDPOINT_ID", - " Get Dynamic Endpoint", + "Get Dynamic Endpoint", s"""Get a Dynamic Endpoint. | | @@ -9109,7 +9104,7 @@ trait APIMethods400 { "Create System Level Endpoint Tag", s"""Create System Level Endpoint Tag""", endpointTagJson400, - endpointTagResponseJson400, + bankLevelEndpointTagResponseJson400, List( $UserNotLoggedIn, UserHasMissingRoles, @@ -9117,7 +9112,7 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canCreateEndpointTag))) + Some(List(canSystemLevelCreateEndpointTag))) lazy val createSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { cc => @@ -9125,31 +9120,31 @@ trait APIMethods400 { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { json.extract[EndpointTagJson400] } - (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(None, operationId, endpointTag.tag_name, cc.callContext) + (endpointTagExisted, callContext) <- NewStyle.function.checkSystemLevelEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name})", cc=callContext) { (!endpointTagExisted) } - (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(None,operationId,endpointTag.tag_name), cc.callContext) + (endpointTag, callContext) <- NewStyle.function.createSystemLevelEndpointTag(operationId,endpointTag.tag_name, cc.callContext) } yield { - (EndpointTagResponseJson400( - endpointTagT.endpointTagId.getOrElse(""), - endpointTagT.operationId, - endpointTagT.tagName + (SystemLevelEndpointTagResponseJson400( + endpointTag.endpointTagId.getOrElse(""), + endpointTag.operationId, + endpointTag.tagName ), HttpCode.`201`(cc.callContext)) } } } staticResourceDocs += ResourceDoc( - updateEndpointTag, + updateSystemLevelEndpointTag, implementedInApiVersion, - nameOf(updateEndpointTag), + nameOf(updateSystemLevelEndpointTag), "PUT", "/management/endpoints/OPERATION_ID/tags/ENDPOINT_TAG_ID", - "Update Endpoint Tag", - s"""Update Endpoint Tag, you can only update the tag_name here, operation_id can not be updated.""", + "Update System Level Endpoint Tag", + s"""Update System Level Endpoint Tag, you can only update the tag_name here, operation_id can not be updated.""", endpointTagJson400, - endpointTagResponseJson400, + bankLevelEndpointTagResponseJson400, List( $UserNotLoggedIn, UserHasMissingRoles, @@ -9158,23 +9153,22 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canUpdateEndpointTag))) - lazy val updateEndpointTag: OBPEndpoint = { + Some(List(canUpdateSystemLevelEndpointTag))) + lazy val updateSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonPut json -> _ => { cc => for { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { json.extract[EndpointTagJson400] } - (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) - (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + (endpointTagExisted, callContext) <- NewStyle.function.checkSystemLevelEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name}), please choose another tag_name", cc=callContext) { (!endpointTagExisted) } - (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(Some(endpointTagId),operationId,endpointTag.tag_name), cc.callContext) + (endpointTagT, callContext) <- NewStyle.function.updateSystemLevelEndpointTag(endpointTagId, operationId,endpointTag.tag_name, cc.callContext) } yield { - (EndpointTagResponseJson400( + (SystemLevelEndpointTagResponseJson400( endpointTagT.endpointTagId.getOrElse(""), endpointTagT.operationId, endpointTagT.tagName @@ -9184,45 +9178,45 @@ trait APIMethods400 { } staticResourceDocs += ResourceDoc( - getEndpointTags, + getSystemLevelEndpointTags, implementedInApiVersion, - nameOf(getEndpointTags), + nameOf(getSystemLevelEndpointTags), "GET", "/management/endpoints/OPERATION_ID/tags", - "Get Endpoint Tags", - s"""Get Endpoint Tags.""", + "Get System Level Endpoint Tags", + s"""Get System Level Endpoint Tags.""", EmptyBody, - endpointTagResponseJson400 :: Nil, + bankLevelEndpointTagResponseJson400 :: Nil, List( $UserNotLoggedIn, UserHasMissingRoles, UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canGetEndpointTag))) - lazy val getEndpointTags: OBPEndpoint = { + Some(List(canGetSystemLevelEndpointTag))) + lazy val getSystemLevelEndpointTags: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { cc => for { - (endpointTags, callContext) <- NewStyle.function.getEndpointTags(operationId, cc.callContext) + (endpointTags, callContext) <- NewStyle.function.getSystemLevelEndpointTags(operationId, cc.callContext) } yield { - (endpointTags.map(endpointTagT => EndpointTagResponseJson400( + (endpointTags.map(endpointTagT => SystemLevelEndpointTagResponseJson400( endpointTagT.endpointTagId.getOrElse(""), endpointTagT.operationId, endpointTagT.tagName - )), HttpCode.`201`(cc.callContext)) + )), HttpCode.`200`(cc.callContext)) } } } staticResourceDocs += ResourceDoc( - deleteEndpointTag, + deleteSystemLevelEndpointTag, implementedInApiVersion, - nameOf(deleteEndpointTag), + nameOf(deleteSystemLevelEndpointTag), "DELETE", "/management/endpoints/OPERATION_ID/tags/ENDPOINT_TAG_ID", - "Delete Endpoint Tag", - s"""Delete Endpoint Tag.""", + "Delete System Level Endpoint Tag", + s"""Delete System Level Endpoint Tag.""", EmptyBody, Full(true), List( @@ -9231,8 +9225,8 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canDeleteEndpointTag))) - lazy val deleteEndpointTag: OBPEndpoint = { + Some(List(canDeleteSystemLevelEndpointTag))) + lazy val deleteSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonDelete _ => { cc => for { @@ -9240,7 +9234,7 @@ trait APIMethods400 { (deleted, callContext) <- NewStyle.function.deleteEndpointTag(endpointTagId, cc.callContext) } yield { - (Full(deleted), HttpCode.`200`(callContext)) + (Full(deleted), HttpCode.`204`(callContext)) } } } @@ -9254,7 +9248,7 @@ trait APIMethods400 { "Create Bank Level Endpoint Tag", s"""Create Bank Level Endpoint Tag""", endpointTagJson400, - endpointTagResponseJson400, + bankLevelEndpointTagResponseJson400, List( $UserNotLoggedIn, $BankNotFound, @@ -9263,7 +9257,7 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canBankLevelCreateEndpointTag))) + Some(List(canCreateBankLevelEndpointTag))) lazy val createBankLevelEndpointTag: OBPEndpoint = { case "management" :: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { cc => @@ -9271,13 +9265,14 @@ trait APIMethods400 { endpointTag <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $EndpointTagJson400", 400, cc.callContext) { json.extract[EndpointTagJson400] } - (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) + (endpointTagExisted, callContext) <- NewStyle.function.checkBankLevelEndpointTagExists(bankId, operationId, endpointTag.tag_name, cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name})", cc=callContext) { (!endpointTagExisted) } - (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(None,operationId,endpointTag.tag_name), cc.callContext) + (endpointTagT, callContext) <- NewStyle.function.createBankLevelEndpointTag(bankId, operationId, endpointTag.tag_name, cc.callContext) } yield { - (EndpointTagResponseJson400( + (BankLevelEndpointTagResponseJson400( + endpointTagT.bankId.getOrElse(""), endpointTagT.endpointTagId.getOrElse(""), endpointTagT.operationId, endpointTagT.tagName @@ -9295,7 +9290,7 @@ trait APIMethods400 { "Update Bank Level Endpoint Tag", s"""Update Endpoint Tag, you can only update the tag_name here, operation_id can not be updated.""", endpointTagJson400, - endpointTagResponseJson400, + bankLevelEndpointTagResponseJson400, List( $UserNotLoggedIn, $BankNotFound, @@ -9305,7 +9300,7 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canBankLevelUpdateEndpointTag))) + Some(List(canUpdateBankLevelEndpointTag))) lazy val updateBankLevelEndpointTag: OBPEndpoint = { case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonPut json -> _ => { cc => @@ -9314,13 +9309,14 @@ trait APIMethods400 { json.extract[EndpointTagJson400] } (_, callContext) <- NewStyle.function.getEndpointTag(endpointTagId, cc.callContext) - (endpointTagExisted, callContext) <- NewStyle.function.checkEndpointTagExists(operationId, endpointTag.tag_name, cc.callContext) - _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name}), please choose another tag_name", cc=callContext) { + (endpointTagExisted, callContext) <- NewStyle.function.checkBankLevelEndpointTagExists(bankId, operationId, endpointTag.tag_name, cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"$EndpointTagAlreadyExists BANK_ID($bankId), OPERATION_ID ($operationId) and tag_name(${endpointTag.tag_name}), please choose another tag_name", cc=callContext) { (!endpointTagExisted) } - (endpointTagT, callContext) <- NewStyle.function.createOrUpdateEndpointTag(code.endpointTag.EndpointTagCommons(Some(endpointTagId),operationId,endpointTag.tag_name), cc.callContext) + (endpointTagT, callContext) <- NewStyle.function.updateBankLevelEndpointTag(bankId, endpointTagId, operationId, endpointTag.tag_name, cc.callContext) } yield { - (EndpointTagResponseJson400( + (BankLevelEndpointTagResponseJson400( + endpointTagT.bankId.getOrElse(""), endpointTagT.endpointTagId.getOrElse(""), endpointTagT.operationId, endpointTagT.tagName @@ -9338,7 +9334,7 @@ trait APIMethods400 { "Get Bank Level Endpoint Tags", s"""Get Bank Level Endpoint Tags.""", EmptyBody, - endpointTagResponseJson400 :: Nil, + bankLevelEndpointTagResponseJson400 :: Nil, List( $UserNotLoggedIn, $BankNotFound, @@ -9346,18 +9342,19 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canBankLevelGetEndpointTag))) + Some(List(canGetBankLevelEndpointTag))) lazy val getBankLevelEndpointTags: OBPEndpoint = { case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { cc => for { - (endpointTags, callContext) <- NewStyle.function.getEndpointTags(operationId, cc.callContext) + (endpointTags, callContext) <- NewStyle.function.getBankLevelEndpointTags(bankId, operationId, cc.callContext) } yield { - (endpointTags.map(endpointTagT => EndpointTagResponseJson400( + (endpointTags.map(endpointTagT => BankLevelEndpointTagResponseJson400( + endpointTagT.bankId.getOrElse(""), endpointTagT.endpointTagId.getOrElse(""), endpointTagT.operationId, endpointTagT.tagName - )), HttpCode.`201`(cc.callContext)) + )), HttpCode.`200`(cc.callContext)) } } } @@ -9379,7 +9376,7 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canBankLevelDeleteEndpointTag))) + Some(List(canDeleteBankLevelEndpointTag))) lazy val deleteBankLevelEndpointTag: OBPEndpoint = { case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonDelete _ => { cc => @@ -9388,7 +9385,7 @@ trait APIMethods400 { (deleted, callContext) <- NewStyle.function.deleteEndpointTag(endpointTagId, cc.callContext) } yield { - (Full(deleted), HttpCode.`200`(callContext)) + (Full(deleted), HttpCode.`204`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 37b5fb04c..957653c17 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -549,7 +549,14 @@ case class EndpointTagJson400( tag_name: String, ) -case class EndpointTagResponseJson400( +case class SystemLevelEndpointTagResponseJson400( + endpoint_tag_id: String, + operation_id: String, + tag_name: String +) + +case class BankLevelEndpointTagResponseJson400( + bank_id: String, endpoint_tag_id: String, operation_id: String, tag_name: String diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 79b7f0f44..d61bb6ed7 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1559,19 +1559,25 @@ trait Connector extends MdcLoggable { def createOrUpdateAtm(atm: AtmT, callContext: Option[CallContext]): OBPReturnType[Box[AtmT]] = Future{Failure(setUnimplementedError)} - def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + def createSystemLevelEndpointTag(operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} - def getEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + def updateSystemLevelEndpointTag(endpointTagId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + + def createBankLevelEndpointTag(bankId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + + def updateBankLevelEndpointTag(bankId:String, endpointTagId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} + + def getSystemLevelEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} def getBankLevelEndpointTag(bankId: String, operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{Failure(setUnimplementedError)} - def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) - - def getBankLevelEndpointTag(bankId:String, endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) + def getEndpointTagById(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future(Failure(setUnimplementedError)) def deleteEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[Boolean]] = Future(Failure(setUnimplementedError)) - def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future(Failure(setUnimplementedError)) + def getSystemLevelEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future(Failure(setUnimplementedError)) + + def getBankLevelEndpointTags(bankId:String, operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future(Failure(setUnimplementedError)) def createOrUpdateProduct( bankId : String, diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index e84e8889b..9cda9c0ab 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2480,7 +2480,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { (createOrUpdateAtmLegacy(atm), callContext) } - override def getEndpointTag(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future( + override def getEndpointTagById(endpointTagId : String, callContext: Option[CallContext]) : OBPReturnType[Box[EndpointTagT]] = Future( (EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)), callContext) ) @@ -2488,42 +2488,91 @@ object LocalMappedConnector extends Connector with MdcLoggable { (EndpointTag.find(By(EndpointTag.EndpointTagId, endpointTagId)).map(_.delete_!), callContext) ) - override def getEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future( - (tryo{getEndpointTagsBox(operationId : String)}, callContext) + override def getSystemLevelEndpointTags(operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future( + (tryo{getSystemLevelEndpointTagsBox(operationId : String)}, callContext) ) - def getEndpointTagsBox(operationId : String) : List[EndpointTagT] = EndpointTag.findAll( + override def getBankLevelEndpointTags(bankId:String, operationId : String, callContext: Option[CallContext]) : OBPReturnType[Box[List[EndpointTagT]]] = Future( + (tryo{getBankLevelEndpointTagsBox(bankId:String, operationId : String)}, callContext) + ) + + def getAllEndpointTagsBox(operationId : String) : List[EndpointTagT] = EndpointTag.findAll( By(EndpointTag.OperationId, operationId), OrderBy(EndpointTag.updatedAt, Descending) ) - override def createOrUpdateEndpointTag(endpointTag: EndpointTagT, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ - (EndpointTag.find( - By(EndpointTag.EndpointTagId, endpointTag.endpointTagId.getOrElse("")), - ) match { - case Full(x) => - tryo { - x - .TagName(endpointTag.tagName) - .saveMe() - } ?~! UpdateEndpointTagError - case Empty => - tryo { - EndpointTag.create - .OperationId(endpointTag.operationId) - .TagName(endpointTag.tagName) - .saveMe() - } ?~! CreateEndpointTagError - case _ => - Failure(UnknownEndpointTagError) - }, callContext) + def getSystemLevelEndpointTagsBox(operationId : String) : List[EndpointTagT] = EndpointTag.findAll( + By(EndpointTag.OperationId, operationId), + OrderBy(EndpointTag.updatedAt, Descending) + ).filter(_.bankId == None) + + def getBankLevelEndpointTagsBox(bankId:String, operationId : String) : List[EndpointTagT] = EndpointTag.findAll( + By(EndpointTag.BankId, bankId), + By(EndpointTag.OperationId, operationId), + OrderBy(EndpointTag.updatedAt, Descending) + ) + + override def createSystemLevelEndpointTag(operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + ( + tryo { + EndpointTag.create + .BankId(null) + .OperationId(operationId) + .TagName(tagName) + .saveMe() + } ?~! CreateEndpointTagError, + callContext + ) + } + + override def updateSystemLevelEndpointTag(endpointTagId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + ( + EndpointTag.find( + By(EndpointTag.EndpointTagId, endpointTagId) + ).map(endpointTag => + endpointTag + .BankId(null) + .OperationId(operationId) + .TagName(tagName) + .saveMe() + ) + , callContext + ) } - override def getEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + override def createBankLevelEndpointTag(bankId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + ( + tryo { + EndpointTag.create + .BankId(bankId) + .OperationId(operationId) + .TagName(tagName) + .saveMe() + } ?~! CreateEndpointTagError, + callContext + ) + } + + override def updateBankLevelEndpointTag(bankId:String, endpointTagId:String, operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ + ( + EndpointTag.find( + By(EndpointTag.EndpointTagId, endpointTagId) + ).map(endpointTag => + endpointTag + .BankId(bankId) + .OperationId(operationId) + .TagName(tagName) + .saveMe() + ) + , callContext + ) + } + + override def getSystemLevelEndpointTag(operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ (EndpointTag.find( By(EndpointTag.OperationId, operationId), By(EndpointTag.TagName, tagName), - ), callContext) + ).filter(_.bankId == None), callContext) } override def getBankLevelEndpointTag(bankId: String, operationId: String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala new file mode 100644 index 000000000..c4e485581 --- /dev/null +++ b/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala @@ -0,0 +1,189 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH +Osloerstrasse 16/17 +Berlin 13359, Germany + +This product includes software developed at +TESOBE (http://www.tesobe.com/) + */ +package code.api.v4_0_0 + +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole +import code.api.v4_0_0.APIMethods400.Implementations4_0_0 +import code.entitlement.Entitlement +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write +import org.scalatest.Tag + +class EndpointTagTest extends V400ServerSetup { + + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createSystemLevelEndpointTag)) + object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.updateSystemLevelEndpointTag)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getSystemLevelEndpointTags)) + object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.deleteSystemLevelEndpointTag)) + object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.createBankLevelEndpointTag)) + object ApiEndpoint6 extends Tag(nameOf(Implementations4_0_0.updateBankLevelEndpointTag)) + object ApiEndpoint7 extends Tag(nameOf(Implementations4_0_0.getBankLevelEndpointTags)) + object ApiEndpoint8 extends Tag(nameOf(Implementations4_0_0.deleteBankLevelEndpointTag)) + + val operationIdInUrl = "OBPv4.0.0-getBanks" + + feature("Test System Level Endpoint Tag Endpoints ") { + scenario("We test CURD the Endpoint Tag Endpoints", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) { + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanCreateSystemLevelEndpointTag.toString) + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateSystemLevelEndpointTag.toString) + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanGetSystemLevelEndpointTag.toString) + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanDeleteSystemLevelEndpointTag.toString) + + When(s"First we test the $ApiEndpoint1") + val request = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags").POST <@ (user1) + lazy val endpointTagJson= SwaggerDefinitionsJSON.endpointTagJson400 + + val response = makePostRequest(request, write(endpointTagJson)) + Then("We should get a 201") + response.code should equal(201) + + val endpointTagResponseJson400 = response.body.extract[SystemLevelEndpointTagResponseJson400] + + val endpointTagId = endpointTagResponseJson400.endpoint_tag_id + val tagName = endpointTagResponseJson400.tag_name + tagName should equal(endpointTagJson.tag_name) + + Then(s"we test the $ApiEndpoint2") + val updateRequestEndpointTag = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags"/ endpointTagId).PUT <@ (user1) + + lazy val endpointTagUpdatedJson = endpointTagJson.copy(tag_name = "update1") + + val updateResponseEndpointTagJson = makePutRequest(updateRequestEndpointTag, write(endpointTagUpdatedJson)) + Then("We should get a 201") + updateResponseEndpointTagJson.code should equal(201) + val updatedEndpointTag = updateResponseEndpointTagJson.body.extract[SystemLevelEndpointTagResponseJson400] + + val updatedTagName = updatedEndpointTag.tag_name + updatedTagName should equal(endpointTagUpdatedJson.tag_name) + + + Then(s"we test the $ApiEndpoint3") + val requestGet = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags").GET <@ (user1) + + val responseGet = makeGetRequest(requestGet) + Then("We should get a 200") + responseGet.code should equal(200) + + val getEndpointTags = responseGet.body.extract[List[SystemLevelEndpointTagResponseJson400]] + +// getEndpointTags.length should be (1) +// getEndpointTags.head should be (updatedEndpointTag) + + + Then(s"we test the $ApiEndpoint4") + val requestDelete = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags"/ endpointTagId).DELETE <@ (user1) + + val responseDelete = makeDeleteRequest(requestDelete) + Then("We should get a 204") + responseDelete.code should equal(204) + + val responseGetAfterDelete = makeGetRequest(requestGet) + Then("We should get a 200") + responseGetAfterDelete.code should equal(200) + + val endpointTagsJsonGetAfterDelete = responseGetAfterDelete.body.extract[List[SystemLevelEndpointTagResponseJson400]] + + endpointTagsJsonGetAfterDelete.length should be (0) + } + } + + feature("Test Bank Level Endpoint Tag Endpoints ") { + scenario("We test CURD the Endpoint Tag Endpoints", ApiEndpoint5, ApiEndpoint6, ApiEndpoint7, ApiEndpoint8, VersionOfApi) { + Entitlement.entitlement.vend.addEntitlement(testBankId1.value, resourceUser1.userId, ApiRole.CanCreateBankLevelEndpointTag.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId1.value, resourceUser1.userId, ApiRole.CanUpdateBankLevelEndpointTag.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId1.value, resourceUser1.userId, ApiRole.CanGetBankLevelEndpointTag.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId1.value, resourceUser1.userId, ApiRole.CanDeleteBankLevelEndpointTag.toString) + + When(s"First we test the $ApiEndpoint5") + val request = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags").POST <@ (user1) + lazy val endpointTagJson= SwaggerDefinitionsJSON.endpointTagJson400 + + val response = makePostRequest(request, write(endpointTagJson)) + Then("We should get a 201") + response.code should equal(201) + + val endpointTagResponseJson400 = response.body.extract[BankLevelEndpointTagResponseJson400] + + val endpointTagId = endpointTagResponseJson400.endpoint_tag_id + val tagName = endpointTagResponseJson400.tag_name + tagName should equal(endpointTagJson.tag_name) + + Then(s"we test the $ApiEndpoint6") + val updateRequestEndpointTag = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags"/ endpointTagId).PUT <@ (user1) + + lazy val endpointTagUpdatedJson = endpointTagJson.copy(tag_name = "update1") + + val updateResponseEndpointTagJson = makePutRequest(updateRequestEndpointTag, write(endpointTagUpdatedJson)) + Then("We should get a 201") + updateResponseEndpointTagJson.code should equal(201) + val updatedEndpointTag = updateResponseEndpointTagJson.body.extract[BankLevelEndpointTagResponseJson400] + + val updatedTagName = updatedEndpointTag.tag_name + updatedTagName should equal(endpointTagUpdatedJson.tag_name) + + + Then(s"we test the $ApiEndpoint7") + val requestGet = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags").GET <@ (user1) + + val responseGet = makeGetRequest(requestGet) + Then("We should get a 200") + responseGet.code should equal(200) + + val getEndpointTags = responseGet.body.extract[List[BankLevelEndpointTagResponseJson400]] + + getEndpointTags.length should be (1) + getEndpointTags.head should be (updatedEndpointTag) + + + Then(s"we test the $ApiEndpoint8") + val requestDelete = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags"/ endpointTagId).DELETE <@ (user1) + + val responseDelete = makeDeleteRequest(requestDelete) + Then("We should get a 204") + responseDelete.code should equal(204) + + val responseGetAfterDelete = makeGetRequest(requestGet) + Then("We should get a 200") + responseGetAfterDelete.code should equal(200) + + val endpointTagsJsonGetAfterDelete = responseGetAfterDelete.body.extract[List[BankLevelEndpointTagResponseJson400]] + + endpointTagsJsonGetAfterDelete.length should be (0) + } + } + +} From d8dfe158851eedb3ab2bc820117ecea2b62b51ea Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 2 Aug 2021 23:33:04 +0200 Subject: [PATCH 013/293] tests/added the missing roles tests --- .../code/api/v4_0_0/EndpointTagTest.scala | 89 ++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala index c4e485581..7174b951e 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EndpointTagTest.scala @@ -100,9 +100,8 @@ class EndpointTagTest extends V400ServerSetup { val getEndpointTags = responseGet.body.extract[List[SystemLevelEndpointTagResponseJson400]] -// getEndpointTags.length should be (1) -// getEndpointTags.head should be (updatedEndpointTag) - + getEndpointTags.length should be (1) + getEndpointTags.head should be (updatedEndpointTag) Then(s"we test the $ApiEndpoint4") val requestDelete = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags"/ endpointTagId).DELETE <@ (user1) @@ -119,6 +118,49 @@ class EndpointTagTest extends V400ServerSetup { endpointTagsJsonGetAfterDelete.length should be (0) } + + scenario("We test roles the Endpoint Tag Endpoints", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) { + When(s"First we test the $ApiEndpoint1") + val request = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags").POST <@ (user1) + lazy val endpointTagJson= SwaggerDefinitionsJSON.endpointTagJson400 + + val response = makePostRequest(request, write(endpointTagJson)) + Then("We should get a 403") + response.code should equal(403) + response.body.toString contains(s"${ApiRole.CanCreateSystemLevelEndpointTag.toString}") should be (true) + + + Then(s"we test the $ApiEndpoint2") + val updateRequestEndpointTag = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags"/ "1").PUT <@ (user1) + + lazy val endpointTagUpdatedJson = endpointTagJson.copy(tag_name = "update1") + + val updateResponseEndpointTagJson = makePutRequest(updateRequestEndpointTag, write(endpointTagUpdatedJson)) + Then("We should get a 403") + updateResponseEndpointTagJson.code should equal(403) + updateResponseEndpointTagJson.body.toString contains(s"${ApiRole.CanUpdateSystemLevelEndpointTag.toString}") should be (true) + + + Then(s"we test the $ApiEndpoint3") + val requestGet = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags").GET <@ (user1) + + val responseGet = makeGetRequest(requestGet) + Then("We should get a 403") + responseGet.code should equal(403) + + responseGet.body.toString contains(s"${ApiRole.CanGetSystemLevelEndpointTag.toString}") should be (true) + + + + Then(s"we test the $ApiEndpoint4") + val requestDelete = (v4_0_0_Request / "management" / "endpoints" / operationIdInUrl /"tags"/ "1").DELETE <@ (user1) + + val responseDelete = makeDeleteRequest(requestDelete) + Then("We should get a 403") + responseDelete.code should equal(403) + responseDelete.body.toString contains(s"${ApiRole.CanDeleteSystemLevelEndpointTag.toString}") should be (true) + + } } feature("Test Bank Level Endpoint Tag Endpoints ") { @@ -184,6 +226,47 @@ class EndpointTagTest extends V400ServerSetup { endpointTagsJsonGetAfterDelete.length should be (0) } + + scenario("We test roles the Endpoint Tag Endpoints", ApiEndpoint5, ApiEndpoint6, ApiEndpoint7, ApiEndpoint8, VersionOfApi) { + When(s"First we test the $ApiEndpoint5") + val request = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags").POST <@ (user1) + lazy val endpointTagJson= SwaggerDefinitionsJSON.endpointTagJson400 + + val response = makePostRequest(request, write(endpointTagJson)) + Then("We should get a 403") + response.code should equal(403) + + response.body.toString contains(s"${ApiRole.CanCreateBankLevelEndpointTag.toString}") should be (true) + + Then(s"we test the $ApiEndpoint6") + val updateRequestEndpointTag = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags"/ "1").PUT <@ (user1) + + lazy val endpointTagUpdatedJson = endpointTagJson.copy(tag_name = "update1") + + val updateResponseEndpointTagJson = makePutRequest(updateRequestEndpointTag, write(endpointTagUpdatedJson)) + Then("We should get a 403") + updateResponseEndpointTagJson.code should equal(403) + updateResponseEndpointTagJson.body.toString contains(s"${ApiRole.CanUpdateBankLevelEndpointTag.toString}") should be (true) + + + Then(s"we test the $ApiEndpoint7") + val requestGet = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags").GET <@ (user1) + + val responseGet = makeGetRequest(requestGet) + Then("We should get a 403") + responseGet.code should equal(403) + responseGet.body.toString contains(s"${ApiRole.CanGetBankLevelEndpointTag.toString}") should be (true) + + + Then(s"we test the $ApiEndpoint8") + val requestDelete = (v4_0_0_Request / "management" /"banks"/testBankId1.value / "endpoints" / operationIdInUrl /"tags"/ "1").DELETE <@ (user1) + + val responseDelete = makeDeleteRequest(requestDelete) + Then("We should get a 403") + responseDelete.code should equal(403) + responseDelete.body.toString contains(s"${ApiRole.CanDeleteBankLevelEndpointTag.toString}") should be (true) + + } } } From 87138abe238cf1b369f411faee54a3fcb04766b8 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Tue, 3 Aug 2021 09:12:40 +0200 Subject: [PATCH 014/293] Tweaking getGlossaryItem / and a Resource Doc to use it WIP --- obp-api/src/main/scala/code/api/util/Glossary.scala | 13 +++++++++---- .../main/scala/code/api/v4_0_0/APIMethods400.scala | 9 +++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 80063d7f5..75b7f523c 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2,16 +2,19 @@ package code.api.util import code.api.util.APIUtil.{getOAuth2ServerUrl, getObpApiRoot, getServerUrl} import code.api.util.ExampleValue.{accountIdExample, bankIdExample, customerIdExample, userIdExample} +import code.util.Helper.MdcLoggable import scala.collection.mutable.ArrayBuffer - import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue -object Glossary { +object Glossary extends MdcLoggable { def getGlossaryItem(title: String): String = { - glossaryItems.find(_.title.toLowerCase == title.toLowerCase) match { + + logger.debug(s"getGlossaryItem says Hello. title to find is: $title") + + val something = glossaryItems.find(_.title.toLowerCase == title.toLowerCase) match { case Some(foundItem) => /** * Two important rules: @@ -24,10 +27,12 @@ object Glossary { | | ${foundItem.description.apply()} | + | |""".stripMargin case None => "" } - + logger.debug(s"getGlossaryItem says markdown to return is $something") + something } // reason of description is function: because we want make description is dynamic, so description can read diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index dbdd1394f..3f675beb7 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -7140,6 +7140,9 @@ trait APIMethods400 { | |${authenticationRequiredMessage(true)} | + |${Glossary.getGlossaryItem("API Collection")} + | + | |""", EmptyBody, Full(true), @@ -7171,6 +7174,9 @@ trait APIMethods400 { "/my/api-collections/API_COLLECTION_NAME/api-collection-endpoints", "Create My Api Collection Endpoint", s"""Create Api Collection Endpoint. + | + |${Glossary.getGlossaryItem("API Collection")} + | | |${authenticationRequiredMessage(true)} | @@ -7317,6 +7323,9 @@ trait APIMethods400 { "/my/api-collections/API_COLLECTION_NAME/api-collection-endpoints/OPERATION_ID", "Delete My Api Collection Endpoint", s"""Delete Api Collection Endpoint By Id + | + | + |${Glossary.getGlossaryItem("API Collection")} | |${authenticationRequiredMessage(true)} | From 49ad3040a4034601e4eaacd284c970ab59a7f9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 3 Aug 2021 09:38:23 +0200 Subject: [PATCH 015/293] feature/Tweak function getGlossaryItem, add new line --- obp-api/src/main/scala/code/api/util/Glossary.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 75b7f523c..5e3551423 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -25,9 +25,9 @@ object Glossary extends MdcLoggable { |
| ${foundItem.title} | - | ${foundItem.description.apply()} + | ${foundItem.htmlDescription} |
- | + |

|""".stripMargin case None => "" } From e8f2a587c11bbb8c2d14e3b61cdeacbe7f726d89 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 3 Aug 2021 10:06:42 +0200 Subject: [PATCH 016/293] refactor/typo --- obp-api/src/main/scala/code/api/util/ApiRole.scala | 2 +- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 2d2d07055..70bfe9d55 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -765,7 +765,7 @@ object ApiRole { lazy val canGetUserInvitation = CanGetUserInvitation() case class CanCreateSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole - lazy val canSystemLevelCreateEndpointTag = CanCreateSystemLevelEndpointTag() + lazy val canCreateSystemLevelEndpointTag = CanCreateSystemLevelEndpointTag() case class CanUpdateSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole lazy val canUpdateSystemLevelEndpointTag = CanUpdateSystemLevelEndpointTag() diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 10d448c4e..026eea711 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9112,7 +9112,7 @@ trait APIMethods400 { UnknownError ), List(apiTagApi, apiTagApi, apiTagNewStyle), - Some(List(canSystemLevelCreateEndpointTag))) + Some(List(canCreateSystemLevelEndpointTag))) lazy val createSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { cc => From 59ff16a43e3dba2afaede54e2eed9955b31b1238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 3 Aug 2021 11:30:41 +0200 Subject: [PATCH 017/293] feature/Tweak function getGlossaryItem, style html tag --- obp-api/src/main/scala/code/api/util/Glossary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 5e3551423..3d657dc6d 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -23,7 +23,7 @@ object Glossary extends MdcLoggable { */ s""" |
- | ${foundItem.title} + | ${foundItem.title} | | ${foundItem.htmlDescription} |
From 507e59d9b9361d01d21ccdf450c443b408655d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 3 Aug 2021 11:53:37 +0200 Subject: [PATCH 018/293] bugfix/Fix the migraton script populateNewFieldIsDeleted --- .../scala/code/api/util/migration/MigrationOfResourceUser.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala index 841f5a87b..40e798266 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala @@ -28,7 +28,7 @@ object MigrationOfResourceUser { val emptyDeletedField = for { - user <- ResourceUser.findAll() if user.isDeleted == false + user <- ResourceUser.findAll() if user.isDeleted.getOrElse(false) == false } yield { user.IsDeleted(false).saveMe() } From 13fa3a2cb5099a4f3c66e770f4d2c9356f754673 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 5 Aug 2021 09:47:43 +0200 Subject: [PATCH 019/293] feature/revert the footer sandbox-introduction-link div --- obp-api/src/main/scala/code/snippet/WebUI.scala | 5 ++++- obp-api/src/main/webapp/templates-hidden/default.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index f928434ae..52f5f5477 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -236,7 +236,10 @@ class WebUI extends MdcLoggable{ "#api_documentation_content *" #> scala.xml.Unparsed(htmlDescription) } - + // Points to the documentation. Probably a sandbox specific link is good. + def apiDocumentationLink: CssSel = { + ".api-documentation-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_api_documentation_url", "https://github.com/OpenBankProject/OBP-API/wiki")) + } // For example customers and credentials // This relies on the page for sandbox documentation having an anchor called example-customer-logins def exampleSandboxCredentialsLink: CssSel = { diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 4d609ca1b..477e41728 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -205,7 +205,7 @@ Berlin 13359, Germany Github
  • - API + API Documentation
  • From 82a4d5cc4745482e6e9a30999d53a5926804fa4c Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 5 Aug 2021 11:35:12 +0200 Subject: [PATCH 020/293] bugfix/tweaked the createResourceDocJson cache key --- .../code/api/v1_4_0/JSONFactory1_4_0.scala | 61 ++++++++++--------- .../bankconnectors/LocalMappedConnector.scala | 6 +- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index bbdc7ab63..46848c09d 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -4,6 +4,7 @@ import code.api.berlin.group.v1_3.JvalueCaseClass import java.util.Date import code.api.util.APIUtil.{EmptyBody, PrimaryDataBody, ResourceDoc} +import code.api.util.ApiTag.ResourceDocTag import code.api.util.Glossary.glossaryItems import code.api.util.{APIUtil, ApiRole, ConnectorField, CustomJsonFormats, ExampleValue, PegdownOptions} import code.bankconnectors.LocalMappedConnector.getAllEndpointTagsBox @@ -447,7 +448,9 @@ object JSONFactory1_4_0 extends MdcLoggable{ def createResourceDocJson(rd: ResourceDoc) : ResourceDocJson = { // if this calculate conversion already happened before, just return that value // if not calculated before, just do conversion - createResourceDocJsonMemo.computeIfAbsent(rd, _=>{ + val endpointTags = getAllEndpointTagsBox(rd.operationId).map(endpointTag =>ResourceDocTag(endpointTag.tagName)) + val resourceDocUpdatedTags = rd.copy(tags = endpointTags++ rd.tags) + createResourceDocJsonMemo.computeIfAbsent(resourceDocUpdatedTags, _=>{ // There are multiple flavours of markdown. For instance, original markdown emphasises underscores (surrounds _ with ()) // But we don't want to have to escape underscores (\_) in our documentation // Thus we use a flavour of markdown that ignores underscores in words. (Github markdown does this too) @@ -458,53 +461,51 @@ object JSONFactory1_4_0 extends MdcLoggable{ // 2rd: Dynamic endpoint endpoints, // 3rd: all the user created endpoints, val fieldsDescription = - if(rd.tags.toString.contains("Dynamic-Entity") - ||rd.tags.toString.contains("Dynamic-Endpoint") - ||rd.roles.toString.contains("DynamicEntity") - ||rd.roles.toString.contains("DynamicEntities") - ||rd.roles.toString.contains("DynamicEndpoint")) { + if(resourceDocUpdatedTags.tags.toString.contains("Dynamic-Entity") + ||resourceDocUpdatedTags.tags.toString.contains("Dynamic-Endpoint") + ||resourceDocUpdatedTags.roles.toString.contains("DynamicEntity") + ||resourceDocUpdatedTags.roles.toString.contains("DynamicEntities") + ||resourceDocUpdatedTags.roles.toString.contains("DynamicEndpoint")) { "" } else{ //1st: prepare the description from URL - val urlParametersDescription: String = prepareUrlParameterDescription(rd.requestUrl) + val urlParametersDescription: String = prepareUrlParameterDescription(resourceDocUpdatedTags.requestUrl) //2rd: get the fields description from the post json body: val exampleRequestBodyFieldsDescription = - if (rd.requestVerb=="POST" ){ - prepareJsonFieldDescription(rd.exampleRequestBody,"request") + if (resourceDocUpdatedTags.requestVerb=="POST" ){ + prepareJsonFieldDescription(resourceDocUpdatedTags.exampleRequestBody,"request") } else { "" } //3rd: get the fields description from the response body: - val responseFieldsDescription = prepareJsonFieldDescription(rd.successResponseBody,"response") + val responseFieldsDescription = prepareJsonFieldDescription(resourceDocUpdatedTags.successResponseBody,"response") urlParametersDescription ++ exampleRequestBodyFieldsDescription ++ responseFieldsDescription } - val description = rd.description.stripMargin.trim ++ fieldsDescription + val description = resourceDocUpdatedTags.description.stripMargin.trim ++ fieldsDescription - val endpointTags = getAllEndpointTagsBox(rd.operationId).map(_.tagName) - ResourceDocJson( - operation_id = rd.operationId, - request_verb = rd.requestVerb, - request_url = rd.requestUrl, - summary = rd.summary.replaceFirst("""\.(\s*)$""", "$1"), // remove the ending dot in summary + operation_id = resourceDocUpdatedTags.operationId, + request_verb = resourceDocUpdatedTags.requestVerb, + request_url = resourceDocUpdatedTags.requestUrl, + summary = resourceDocUpdatedTags.summary.replaceFirst("""\.(\s*)$""", "$1"), // remove the ending dot in summary // Strip the margin character (|) and line breaks and convert from markdown to html description = PegdownOptions.convertPegdownToHtmlTweaked(description), //.replaceAll("\n", ""), description_markdown = description, - example_request_body = rd.exampleRequestBody, - success_response_body = rd.successResponseBody, - error_response_bodies = rd.errorResponseBodies, - implemented_by = ImplementedByJson(rd.implementedInApiVersion.fullyQualifiedVersion, rd.partialFunctionName), // was rd.implementedInApiVersion.noV - tags = endpointTags ++ rd.tags.map(i => i.tag), - typed_request_body = createTypedBody(rd.exampleRequestBody), - typed_success_response_body = createTypedBody(rd.successResponseBody), - roles = rd.roles, - is_featured = rd.isFeatured, - special_instructions = PegdownOptions.convertPegdownToHtmlTweaked(rd.specialInstructions.getOrElse("").stripMargin), - specified_url = rd.specifiedUrl.getOrElse(""), - connector_methods = rd.connectorMethods + example_request_body = resourceDocUpdatedTags.exampleRequestBody, + success_response_body = resourceDocUpdatedTags.successResponseBody, + error_response_bodies = resourceDocUpdatedTags.errorResponseBodies, + implemented_by = ImplementedByJson(resourceDocUpdatedTags.implementedInApiVersion.fullyQualifiedVersion, resourceDocUpdatedTags.partialFunctionName), // was resourceDocUpdatedTags.implementedInApiVersion.noV + tags = resourceDocUpdatedTags.tags.map(i => i.tag), + typed_request_body = createTypedBody(resourceDocUpdatedTags.exampleRequestBody), + typed_success_response_body = createTypedBody(resourceDocUpdatedTags.successResponseBody), + roles = resourceDocUpdatedTags.roles, + is_featured = resourceDocUpdatedTags.isFeatured, + special_instructions = PegdownOptions.convertPegdownToHtmlTweaked(resourceDocUpdatedTags.specialInstructions.getOrElse("").stripMargin), + specified_url = resourceDocUpdatedTags.specifiedUrl.getOrElse(""), + connector_methods = resourceDocUpdatedTags.connectorMethods ) - }) + }) } def createResourceDocsJson(resourceDocList: List[ResourceDoc]) : ResourceDocsJson = { diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 9cda9c0ab..d75e97bd2 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2498,18 +2498,18 @@ object LocalMappedConnector extends Connector with MdcLoggable { def getAllEndpointTagsBox(operationId : String) : List[EndpointTagT] = EndpointTag.findAll( By(EndpointTag.OperationId, operationId), - OrderBy(EndpointTag.updatedAt, Descending) + OrderBy(EndpointTag.TagName, Ascending) ) def getSystemLevelEndpointTagsBox(operationId : String) : List[EndpointTagT] = EndpointTag.findAll( By(EndpointTag.OperationId, operationId), - OrderBy(EndpointTag.updatedAt, Descending) + OrderBy(EndpointTag.TagName, Ascending) ).filter(_.bankId == None) def getBankLevelEndpointTagsBox(bankId:String, operationId : String) : List[EndpointTagT] = EndpointTag.findAll( By(EndpointTag.BankId, bankId), By(EndpointTag.OperationId, operationId), - OrderBy(EndpointTag.updatedAt, Descending) + OrderBy(EndpointTag.TagName, Ascending) ) override def createSystemLevelEndpointTag(operationId:String, tagName:String, callContext: Option[CallContext]): OBPReturnType[Box[EndpointTagT]] = Future{ From 7d330e0be9d9c18d79093f5b44060bb1609db7d7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 5 Aug 2021 13:28:06 +0200 Subject: [PATCH 021/293] refactor/enhanced the error handling for fx endpoints --- obp-api/src/main/scala/code/api/util/NewStyle.scala | 2 +- obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index b010d6389..f890b473a 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -890,7 +890,7 @@ object NewStyle { def isValidCurrencyISOCode(currencyCode: String, callContext: Option[CallContext]) = { - tryons(failMsg = InvalidISOCurrencyCode,400, callContext) { + tryons(failMsg = InvalidISOCurrencyCode+s" Current currencyCode is $currencyCode",400, callContext) { assert(APIUtil.isValidCurrencyISOCode(currencyCode)) } } diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 160362515..1ab6bd33c 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -670,6 +670,8 @@ trait APIMethods220 { (bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound _ <- NewStyle.function.hasAllEntitlements(bank.bankId.value, u.userId, createFxEntitlementsRequiredForSpecificBank, createFxEntitlementsRequiredForAnyBank, callContext) fx <- tryo {json.extract[FXRateJsonV220]} ?~! ErrorMessages.InvalidJsonFormat + _ <- booleanToBox(APIUtil.isValidCurrencyISOCode(fx.from_currency_code),InvalidISOCurrencyCode+s"Current from_currency_code is ${fx.from_currency_code}") + _ <- booleanToBox(APIUtil.isValidCurrencyISOCode(fx.to_currency_code),InvalidISOCurrencyCode+s"Current to_currency_code is ${fx.to_currency_code}") success <- Connector.connector.vend.createOrUpdateFXRate( bankId = fx.bank_id, fromCurrencyCode = fx.from_currency_code, From 37adab53785b47ffe944fca1d16e84b7f3026b3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 20:52:39 +0000 Subject: [PATCH 022/293] Bump elasticsearch from 6.8.13 to 6.8.17 in /obp-api Bumps [elasticsearch](https://github.com/elastic/elasticsearch) from 6.8.13 to 6.8.17. - [Release notes](https://github.com/elastic/elasticsearch/releases) - [Commits](https://github.com/elastic/elasticsearch/compare/v6.8.13...v6.8.17) --- updated-dependencies: - dependency-name: org.elasticsearch:elasticsearch dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- obp-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/pom.xml b/obp-api/pom.xml index 57e6af0be..9396eb38d 100644 --- a/obp-api/pom.xml +++ b/obp-api/pom.xml @@ -210,7 +210,7 @@ org.elasticsearch elasticsearch - 6.8.13 + 6.8.17 com.sksamuel.elastic4s From 1a3efc62c8c03b292da0bc4187610308fa861a4b Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Tue, 10 Aug 2021 07:19:21 +0200 Subject: [PATCH 023/293] /docfix Tweaking glossary items / Collection resource docs --- obp-api/src/main/scala/code/api/util/Glossary.scala | 10 +++++----- .../src/main/scala/code/api/v4_0_0/APIMethods400.scala | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 75b7f523c..f518dadd3 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -31,7 +31,7 @@ object Glossary extends MdcLoggable { |""".stripMargin case None => "" } - logger.debug(s"getGlossaryItem says markdown to return is $something") + logger.debug(s"getGlossaryItem says the text to return is $something") something } @@ -2106,9 +2106,8 @@ object Glossary extends MdcLoggable { glossaryItems += GlossaryItem( - title = "API Collection", - description = - s"""|An API Collection is a collection of endpoints grouped together for a certain purpose. + title = "API Collections", + description = s"""An API Collection is a collection of endpoints grouped together for a certain purpose. | |Having read access to a Collection does not constitute execute access on the endpoints in the Collection. | @@ -2122,7 +2121,8 @@ object Glossary extends MdcLoggable { | |If you share a Collection it can't be modified by anyone else, but anyone can use it as a basis for their own Favourites or another collection. | -|At the time of writing (July 2021), there are 13 endpoints for controlling Collections. +|There are over 13 endpoints for controlling Collections. +|Some of these endpoints require Entitlements to Roles and some operate on your own personal collections such as your favourites. | """) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 3f675beb7..abcfbc30f 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -7137,10 +7137,11 @@ trait APIMethods400 { "/my/api-collections/API_COLLECTION_ID", "Delete My Api Collection", s"""Delete Api Collection By API_COLLECTION_ID + | + |${Glossary.getGlossaryItem("API Collections")} | |${authenticationRequiredMessage(true)} | - |${Glossary.getGlossaryItem("API Collection")} | | |""", @@ -7175,7 +7176,7 @@ trait APIMethods400 { "Create My Api Collection Endpoint", s"""Create Api Collection Endpoint. | - |${Glossary.getGlossaryItem("API Collection")} + |${Glossary.getGlossaryItem("API Collections")} | | |${authenticationRequiredMessage(true)} @@ -7322,10 +7323,10 @@ trait APIMethods400 { "DELETE", "/my/api-collections/API_COLLECTION_NAME/api-collection-endpoints/OPERATION_ID", "Delete My Api Collection Endpoint", - s"""Delete Api Collection Endpoint By Id + s"""${Glossary.getGlossaryItem("API Collections")} | | - |${Glossary.getGlossaryItem("API Collection")} + |Delete Api Collection Endpoint By Id | |${authenticationRequiredMessage(true)} | From 0dcb65013600c2b1b2e293620d40f7a30e88a0c0 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Tue, 10 Aug 2021 09:08:44 +0200 Subject: [PATCH 024/293] /docfix Enhanced Bank glossary item --- .../src/main/scala/code/api/util/Glossary.scala | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index f518dadd3..962ba944c 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -602,8 +602,19 @@ object Glossary extends MdcLoggable { title = "Bank", description = """ - |The entity that represents the financial institution or bank within a financial group. - |Open Bank Project is a multi-bank API. Each bank resource contains basic identifying information such as name, logo and website. + |A Bank (aka Space) represents a financial institution, brand or organisaitonal unit under which resources such as endpoints and entities exist. +| +|Both standard entities (e.g. financial products and bank accounts in the OBP standard) and dynamic entities and endpoints (created by you or your organisation) can exist at the Bank level. +| +|The Bank is important because many Roles can be granted at the Bank level. In this way, it's possible to create segregated or partitioned sets of endpoints and data structures in a single OBP instance. +| +|A User creating a Bank (if they have the right so to do), automatically gets the Entitlement to grant any Role for that Bank. Thus the creator of a Bank / Space becomes the "god" of that Bank / Space. +| +|Basic attributes for the bank resource include identifying information such as name, logo and website. +| +|Using the OBP endpoints for bank accounts it's possible to view accounts at one Bank or aggregate accounts from all Banks connected to the OBP instance. +| +|See also Props settings named "brand". """) From c93e7629ee98800de176761067450ca060921986 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 10 Aug 2021 17:25:04 +0200 Subject: [PATCH 025/293] bugfix/fixed the missing guard for CanReadResourceDoc role --- .../ResourceDocsAPIMethods.scala | 6 ++-- .../ResourceDocs1_4_0/ResourceDocsTest.scala | 33 +++++++++++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index d8423ac8f..8bd66165a 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -1,11 +1,11 @@ package code.api.ResourceDocs1_4_0 import java.util.UUID.randomUUID - import code.api.OBPRestHelper import code.api.builder.OBP_APIBuilder import code.api.cache.Caching import code.api.util.APIUtil._ +import code.api.util.ApiRole.canReadResourceDoc import code.api.util.ApiTag._ import code.api.util.ExampleValue.endpointMappingRequestBodyExample import code.api.util.{APIUtil, _} @@ -479,7 +479,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth List(apiTagDocumentation, apiTagApi) ) - val resourceDocsRequireRole = APIUtil.getPropsAsBoolValue("resource_docs_requires_role", false) + def resourceDocsRequireRole = APIUtil.getPropsAsBoolValue("resource_docs_requires_role", false) // Provides resource documents so that API Explorer (or other apps) can display API documentation // Note: description uses html markup because original markdown doesn't easily support "_" and there are multiple versions of markdown. def getResourceDocsObp : OBPEndpoint = { @@ -494,7 +494,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth _ <- resourceDocsRequireRole match { case false => Future() case true => // If set resource_docs_requires_role=true, we need check the the roles as well - Future(NewStyle.function.ownEntitlement("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc, cc.callContext)) + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc::Nil, cc.callContext) } requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} _ <- Helper.booleanToFuture(s"$ApiVersionNotSupported $requestedApiVersionString", 400, callContext)(versionIsAllowed(requestedApiVersion)) diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index f242e89b7..31e6a48ac 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -1,10 +1,12 @@ package code.api.ResourceDocs1_4_0 -import java.util +import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import code.api.util.APIUtil.OAuth._ +import java.util import code.api.util.{ApiRole, CustomJsonFormats} import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson -import code.setup.PropsReset +import code.setup.{DefaultUsers, PropsReset} import com.openbankproject.commons.util.{ApiVersion, Functions} import io.swagger.parser.OpenAPIParser import net.liftweb.json @@ -15,7 +17,7 @@ import org.scalatest.Tag import scala.xml.NodeSeq -class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset { +class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with DefaultUsers{ object VersionOfApi extends Tag(ApiVersion.v1_4_0.toString) object ApiEndpoint1 extends Tag("Get OBP ResourceDoc") object ApiEndpoint2 extends Tag("Get Swagger ResourceDoc ") @@ -301,6 +303,31 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset { //This should not throw any exceptions responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props", ApiEndpoint1, VersionOfApi) { + setPropsValues( + "resource_docs_requires_role" -> "true", + ) + val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(401) + responseGetObp.toString contains(UserNotLoggedIn) should be (true) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) { + setPropsValues( + "resource_docs_requires_role" -> "true", + ) + val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v4.0.0" / "obp").GET <@ (user1) + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(403) + responseGetObp.toString contains(UserHasMissingRoles) should be (true) + } + } feature(s"test ${ApiEndpoint2.name} ") { From d84dc859ac6e8a28bd48550eb038deb8ca0b9a75 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Wed, 11 Aug 2021 13:15:06 +0200 Subject: [PATCH 026/293] /docfix Tweaking Get Glossary docs --- obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index fb7f76c2b..f6a83672d 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -2027,8 +2027,11 @@ trait APIMethods300 { nameOf(getApiGlossary), "GET", "/api/glossary", - "Get API Glossary", - """Returns the glossary of the API + "Get Glossary of the API", + """Get API Glossary + | + |Returns the glossary of the API + | |""", emptyObjectJson, glossaryItemsJsonV300, From 7eda79db2760d57d81d26c95e88cb403472bc7d8 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Wed, 11 Aug 2021 13:15:53 +0200 Subject: [PATCH 027/293] /docfix Modifying Connector glossary item --- .../main/scala/code/api/util/Glossary.scala | 82 +++++++++++-------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 962ba944c..d18624200 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -434,42 +434,60 @@ object Glossary extends MdcLoggable { + // ***Note***! Don't use "--" (double hyphen) in the description because API Explorer scala.xml.XML.loadString cannot parse. + glossaryItems += GlossaryItem( title = "Connector", description = - s"""In OBP, we use the term "Connector" to mean the Scala/Java/Other JVM code in OBP that connects directly or indirectly to the systems of record i.e. the Core Banking Systems, Payment Systems and Databases. + s"""In OBP, most internal functions / methods can have different implementations which follow the same interface. | - |Several Connectors are present in the OBP source code and all must implement the Connector interface -|- but, except when using the Star Connector, only one of them is active at any one time. -| -| The active connector is defined in the OBP Props file. -| -| A "Direct Connector" is considered to be one that talks directly to the system of record or existing service layer. -| -| i.e. API -> Connector -> CBS -| -| An "Indirect Connector" is considered one which pairs with an Adapter which in turn talks to the system of record or service layer. -| -| i.e. API -> Connector -> Adapter -> CBS -| -| The advantage of a Direct connector is that its perhaps simpler. The disadvantage is that you have to code in a JVM language, understand a bit about OBP internals and a bit of Scala. -| -| The advantage of the Indirect Connector is that you can write the Adapter in any language and the Connector and Adapter are decoupled (you just have to respect the Outbound / Inbound message format). -| -| The default Connector in OBP is a Direct Connector called "mapped". It is called the "mapped" connector because it talks directly to the OBP database (Postgres, MySQL, Oracle, MSSQL etc.) via the Liftweb ORM which is called Mapper. -| -|If you want to create your own (Direct) Connector you can fork any of the connectors within OBP. -| -| -| There is a special Connector called the Star Connector which can use functions from all the normal connectors. -| -| Using the Star Connector we can dynamically reroute function calls to different Connectors per function per bank_id. -| -| The OBP API Manager has a GUI to manage this or you can use the OBP Method Routing APIs to set destinations for each function call. -| -| Note: We generate the source code for individual connectors automatically. -| - |""" + |These functions are called connector methods and their implementations. + | + |The default implementation of the connector is the "mapped" connector. + | + |It's called "mapped" because the default datasource on OBP is a relational database, and access to that database is always done through an Object-Relational Mapper (ORM) called Mapper (from a framework we use called Liftweb). + | + |However, there are multiple available connector implementations (aka connectors) and you can mix and match them using the Star connector and you can write your own in Scala. You can also write Adapters in any language which respond to messages sent by the connector. + | + |Let's start with an ASCII art diagram: + | +|
    +				 |[=============]                                                                      [============]       [============]
    +				 |[.............]                                                                      [............]       [............]
    +				 |[...OBP API...] ===> OBP Endpoints call multiple connector functions / methods. ===> [  Connector ] ===>  [  Database  ]
    +				 |[.............]        Each method has input parameters and a return type            [  (Mapped)  ]       [  (Adapter) ]
    +				 |[=============]          Every implementation must respect the interface             [============]       [============]
    +				 |
    +				 |
    + |we use the term "Connector" to mean the Scala/Java/Other JVM code in OBP that connects directly or indirectly to the systems of record i.e. the Core Banking Systems, Payment Systems and Databases. + | + | + | A "Direct Connector" is considered to be one that talks directly to the system of record or existing service layer. + | + | i.e. API -> Connector -> CBS + | + | An "Indirect Connector" is considered one which pairs with an Adapter which in turn talks to the system of record or service layer. + | + | i.e. API -> Connector -> Adapter -> CBS + | + | The advantage of a Direct connector is that its perhaps simpler. The disadvantage is that you have to code in a JVM language, understand a bit about OBP internals and a bit of Scala. + | + | The advantage of the Indirect Connector is that you can write the Adapter in any language and the Connector and Adapter are decoupled (you just have to respect the Outbound / Inbound message format). + | + | The default Connector in OBP is a Direct Connector called "mapped". It is called the "mapped" connector because it talks directly to the OBP database (Postgres, MySQL, Oracle, MSSQL etc.) via the Liftweb ORM which is called Mapper. + | + |If you want to create your own (Direct) Connector you can fork any of the connectors within OBP. + | + | + | There is a special Connector called the Star Connector which can use functions from all the normal connectors. + | + | Using the Star Connector we can dynamically reroute function calls to different Connectors per function per bank_id. + | + | The OBP API Manager has a GUI to manage this or you can use the OBP Method Routing APIs to set destinations for each function call. + | + | Note: We generate the source code for individual connectors automatically. + | + |""" ) From e4a3ea97d66731ea479cd99b2df5c51392c760e6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 12 Aug 2021 11:03:41 +0200 Subject: [PATCH 028/293] feature/added the getBankLevelDynamicResourceDocsObp endpoint --- .../ResourceDocs1_4_0/ResourceDocs140.scala | 1 + .../ResourceDocsAPIMethods.scala | 87 +++++- .../main/scala/code/api/util/ApiRole.scala | 3 + .../ResourceDocs1_4_0/ResourceDocsTest.scala | 270 +++++++++++++++++- 4 files changed, 354 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index c75627f35..7438422a3 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -10,6 +10,7 @@ object ResourceDocs140 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "STABLE" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger ) routes.foreach(route => { diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 8bd66165a..a94e4a648 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -19,7 +19,7 @@ import code.api.v4_0_0.{APIMethods400, OBPAPI4_0_0} import code.apicollectionendpoint.MappedApiCollectionEndpointsProvider import code.util.Helper.MdcLoggable import com.github.dwickern.macros.NameOf.nameOf -import com.openbankproject.commons.model.{ListResult, User} +import com.openbankproject.commons.model.{BankId, ListResult, User} import com.openbankproject.commons.model.enums.ContentParam.{ALL, DYNAMIC, STATIC} import com.openbankproject.commons.model.enums.LanguageParam._ import com.openbankproject.commons.model.enums.{ContentParam, LanguageParam} @@ -526,6 +526,91 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } } + localResourceDocs += ResourceDoc( + getBankLevelDynamicResourceDocsObp, + implementedInApiVersion, + nameOf(getBankLevelDynamicResourceDocsObp), + "GET", + "/banks/BANK_ID/resource-docs/API_VERSION/obp", + "Get Bank Level Dynamic Resource Docs.", + s"""Get documentation about the RESTful resources on this server including example bodies for POST and PUT requests. + | + |This is the native data format used to document OBP endpoints. Each endpoint has a Resource Doc (a Scala case class) defined in the source code. + | + | This endpoint is used by OBP API Explorer to display and work with the API documentation. + | + | Most (but not all) fields are also available in swagger format. (The Swagger endpoint is built from Resource Docs.) + | + | API_VERSION is the version you want documentation about e.g. v3.0.0 + | + | You may filter this endpoint with tags parameter e.g. ?tags=Account,Bank + | + | You may filter this endpoint with functions parameter e.g. ?functions=enableDisableConsumers,getConnectorMetrics + | + | For possible function values, see implemented_by.function in the JSON returned by this endpoint or the OBP source code or the footer of the API Explorer which produces a comma separated list of functions that reflect the server or filtering by API Explorer based on tags etc. + | + | You may filter this endpoint using the 'content' url parameter, e.g. ?content=dynamic + | if set content=dynamic, only show dynamic endpoints, if content=static, only show the static endpoints. if omit this parameter, we will show all the endpoints. + | + | You may need some other language resource docs, now we support en and zh , e.g. ?language=zh + | + | You can filter with api-collection-id, but api-collection-id can not be used with others together. If api-collection-id is used in URL, it will ignore all other parameters. + | + |See the Resource Doc endpoint for more information. + | + |Following are more examples: + |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp + |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp?tags=Account,Bank + |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp?functions=getBanks,bankById + |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?language=zh + |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?content=static,dynamic,all + |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 + | + |
      + |
    • operation_id is concatenation of "v", version and function and should be unique (used for DOM element IDs etc. maybe used to link to source code)
    • + |
    • version references the version that the API call is defined in.
    • + |
    • function is the (scala) partial function that implements this endpoint. It is unique per version of the API.
    • + |
    • request_url is empty for the root call, else the path. It contains the standard prefix (e.g. /obp) and the implemented version (the version where this endpoint was defined) e.g. /obp/v1.2.0/resource
    • + |
    • specified_url (recommended to use) is empty for the root call, else the path. It contains the standard prefix (e.g. /obp) and the version specified in the call e.g. /obp/v3.1.0/resource. In OBP, endpoints are first made available at the request_url, but the same resource (function call) is often made available under later versions (specified_url). To access the latest version of all endpoints use the latest version available on your OBP instance e.g. /obp/v3.1.0 - To get the original version use the request_url. We recommend to use the specified_url since non semantic improvements are more likely to be applied to later implementations of the call.
    • + |
    • summary is a short description inline with the swagger terminology.
    • + |
    • description may contain html markup (generated from markdown on the server).
    • + |
    + """, + emptyObjectJson, + emptyObjectJson, + UnknownError :: Nil, + List(apiTagDocumentation, apiTagApi) + ) + + // Provides resource documents so that API Explorer (or other apps) can display API documentation + // Note: description uses html markup because original markdown doesn't easily support "_" and there are multiple versions of markdown. + def getBankLevelDynamicResourceDocsObp : OBPEndpoint = { + case "banks" :: bankId :: "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { + val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() + cc => + for { + (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { + case false => anonymousAccess(cc) + case true => authenticatedAccess(cc) // If set resource_docs_requires_role=true, we need check the authentication + } + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), Option(cc)) + _ <- resourceDocsRequireRole match { + case false => Future() + case true => // If set resource_docs_requires_role=true, we need check the the roles as well + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + ApiRole.canReadDynamicResourceDocsAtOneBank.toString)( + bankId, u.map(_.userId).getOrElse(""), ApiRole.canReadDynamicResourceDocsAtOneBank::Nil, cc.callContext + ) + } + requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} + json <- NewStyle.function.tryons(s"$UnknownError Can not create dynamic resource docs.", 400, callContext) { + getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam).map(successJsonResponse(_)).get + } + } yield { + (Full(json), HttpCode.`200`(callContext)) + } + } + } + localResourceDocs += ResourceDoc( getResourceDocsSwagger, diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 70bfe9d55..27ea919c9 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -594,6 +594,9 @@ object ApiRole { case class CanReadResourceDoc(requiresBankId: Boolean = false) extends ApiRole lazy val canReadResourceDoc = CanReadResourceDoc() + case class CanReadDynamicResourceDocsAtOneBank(requiresBankId: Boolean = true) extends ApiRole + lazy val canReadDynamicResourceDocsAtOneBank = CanReadDynamicResourceDocsAtOneBank() + case class CanReadGlossary(requiresBankId: Boolean = false) extends ApiRole lazy val canReadGlossary = CanReadGlossary() diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index 31e6a48ac..cdcbad917 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -1,5 +1,6 @@ package code.api.ResourceDocs1_4_0 +import code.api.ResourceDocs1_4_0.ResourceDocs140.ImplementationsResourceDocs import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} import code.api.util.APIUtil.OAuth._ @@ -8,6 +9,7 @@ import code.api.util.{ApiRole, CustomJsonFormats} import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson import code.setup.{DefaultUsers, PropsReset} import com.openbankproject.commons.util.{ApiVersion, Functions} +import com.github.dwickern.macros.NameOf.nameOf import io.swagger.parser.OpenAPIParser import net.liftweb.json import net.liftweb.json.JsonAST._ @@ -19,8 +21,9 @@ import scala.xml.NodeSeq class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with DefaultUsers{ object VersionOfApi extends Tag(ApiVersion.v1_4_0.toString) - object ApiEndpoint1 extends Tag("Get OBP ResourceDoc") - object ApiEndpoint2 extends Tag("Get Swagger ResourceDoc ") + object ApiEndpoint1 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsObp)) + object ApiEndpoint2 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsSwagger)) + object ApiEndpoint3 extends Tag(nameOf(ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp)) override def beforeEach() = { @@ -326,6 +329,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with val responseDocs = responseGetObp.body.extract[ResourceDocsJson] responseGetObp.code should equal(403) responseGetObp.toString contains(UserHasMissingRoles) should be (true) + responseGetObp.toString contains( ApiRole.canReadResourceDoc.toString()) should be (true) } } @@ -438,10 +442,264 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } } - - - - + + feature(s"test ${ApiEndpoint3.name} ") { + scenario(s"We will test ${ApiEndpoint3.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv4.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v3.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + org.scalameta.logger.elem(responseGetObp) + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv3.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv3.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v3.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv3.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv3.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v2.2.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv2.2.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv2.2.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v2.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv2.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv2.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v2.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv2.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv2.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.4.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv1.4.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv1.4.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.3.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv1.3.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv1.3.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.2.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -OBPv1.2.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv1.2.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + + scenario(s"We will test ${ApiEndpoint3.name} Api -BGv1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "BGv1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.3" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "BGv1.3" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v3.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v3.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -UKv3.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "UKv3.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v4.0.0 - resource_docs_requires_role props", ApiEndpoint1, VersionOfApi) { + setPropsValues( + "resource_docs_requires_role" -> "true", + ) + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(401) + responseGetObp.toString contains(UserNotLoggedIn) should be (true) + } + + scenario(s"We will test ${ApiEndpoint3.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) { + setPropsValues( + "resource_docs_requires_role" -> "true", + ) + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v4.0.0" / "obp").GET <@ (user1) + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(403) + responseGetObp.toString contains(UserHasMissingRoles) should be (true) + responseGetObp.toString contains(ApiRole.canReadDynamicResourceDocsAtOneBank.toString) should be (true) + } + + } //Note: it is tricky to validate the swagger string, I just find this : https://github.com/swagger-api/swagger-parser/issues/718 //So follow it to call the `Validate` method: //https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Validate.java#L46 From 466a74226f804218e0a0f4882096cda7e9f72fa4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 12 Aug 2021 15:39:32 +0200 Subject: [PATCH 029/293] feature/add the all the versions for getBankLevelDynamicResourceDocsObp endpoint --- .../ResourceDocs1_4_0/ResourceDocs140.scala | 18 ++-- .../ResourceDocsAPIMethods.scala | 87 ++++++------------- .../main/scala/code/api/util/APIUtil.scala | 3 +- .../dynamic/DynamicEndpointHelper.scala | 3 +- .../v4_0_0/dynamic/DynamicEntityHelper.scala | 15 ++-- 5 files changed, 52 insertions(+), 74 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index 7438422a3..47bb7b0ed 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -25,7 +25,8 @@ object ResourceDocs200 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "DRAFT" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -39,7 +40,8 @@ object ResourceDocs210 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "DRAFT" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -52,7 +54,8 @@ object ResourceDocs220 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "DRAFT" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -65,7 +68,8 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "DRAFT" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -77,7 +81,8 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "DRAFT" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { @@ -91,7 +96,8 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val versionStatus = "BLEEDING-EDGE" val routes = List( ImplementationsResourceDocs.getResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index a94e4a648..3d6d2c968 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -311,12 +311,14 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth partialFunctionNames: Option[List[String]], languageParam: Option[LanguageParam], contentParam: Option[ContentParam], - cacheModifierParam: Option[String] + cacheModifierParam: Option[String], + bankId:Option[String] ): Option[JValue] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getDynamicResourceDocsTTL second) { val dynamicDocs = (DynamicEntityHelper.doc ++ DynamicEndpointHelper.doc ++ DynamicEndpoints.dynamicResourceDocs) + .filter(rd => if (bankId.isDefined) rd.bankId == bankId else true) .filter(rd => rd.implementedInApiVersion == requestedApiVersion) .map(it => it.specifiedUrl match { case Some(_) => it @@ -423,13 +425,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth - localResourceDocs += ResourceDoc( - getResourceDocsObp, - implementedInApiVersion, - "getResourceDocsObp", - "GET", - "/resource-docs/API_VERSION/obp", - "Get Resource Docs.", + def getResourceDocsDescription(bankUrl: String) = s"""Get documentation about the RESTful resources on this server including example bodies for POST and PUT requests. | |This is the native data format used to document OBP endpoints. Each endpoint has a Resource Doc (a Scala case class) defined in the source code. @@ -456,12 +452,12 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth |See the Resource Doc endpoint for more information. | |Following are more examples: - |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp - |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp?tags=Account,Bank - |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp?functions=getBanks,bankById - |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?language=zh - |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?content=static,dynamic,all - |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 + |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v3.1.0/obp + |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v3.1.0/obp?tags=Account,Bank + |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v3.1.0/obp?functions=getBanks,bankById + |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v4.0.0/obp?language=zh + |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v4.0.0/obp?content=static,dynamic,all + |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 | |
      |
    • operation_id is concatenation of "v", version and function and should be unique (used for DOM element IDs etc. maybe used to link to source code)
    • @@ -472,7 +468,18 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth |
    • summary is a short description inline with the swagger terminology.
    • |
    • description may contain html markup (generated from markdown on the server).
    • |
    - """, + """ + + + + localResourceDocs += ResourceDoc( + getResourceDocsObp, + implementedInApiVersion, + "getResourceDocsObp", + "GET", + "/resource-docs/API_VERSION/obp", + "Get Resource Docs.", + getResourceDocsDescription(""), emptyObjectJson, emptyObjectJson, //exampleResourceDocsJson UnknownError :: Nil, @@ -509,7 +516,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case _ => contentParam match { case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None) Future(dynamicDocs.map(successJsonResponse(_))) case Some(STATIC) => val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) @@ -533,49 +540,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth "GET", "/banks/BANK_ID/resource-docs/API_VERSION/obp", "Get Bank Level Dynamic Resource Docs.", - s"""Get documentation about the RESTful resources on this server including example bodies for POST and PUT requests. - | - |This is the native data format used to document OBP endpoints. Each endpoint has a Resource Doc (a Scala case class) defined in the source code. - | - | This endpoint is used by OBP API Explorer to display and work with the API documentation. - | - | Most (but not all) fields are also available in swagger format. (The Swagger endpoint is built from Resource Docs.) - | - | API_VERSION is the version you want documentation about e.g. v3.0.0 - | - | You may filter this endpoint with tags parameter e.g. ?tags=Account,Bank - | - | You may filter this endpoint with functions parameter e.g. ?functions=enableDisableConsumers,getConnectorMetrics - | - | For possible function values, see implemented_by.function in the JSON returned by this endpoint or the OBP source code or the footer of the API Explorer which produces a comma separated list of functions that reflect the server or filtering by API Explorer based on tags etc. - | - | You may filter this endpoint using the 'content' url parameter, e.g. ?content=dynamic - | if set content=dynamic, only show dynamic endpoints, if content=static, only show the static endpoints. if omit this parameter, we will show all the endpoints. - | - | You may need some other language resource docs, now we support en and zh , e.g. ?language=zh - | - | You can filter with api-collection-id, but api-collection-id can not be used with others together. If api-collection-id is used in URL, it will ignore all other parameters. - | - |See the Resource Doc endpoint for more information. - | - |Following are more examples: - |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp - |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp?tags=Account,Bank - |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/obp?functions=getBanks,bankById - |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?language=zh - |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?content=static,dynamic,all - |${getObpApiRoot}/v3.1.0/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 - | - |
      - |
    • operation_id is concatenation of "v", version and function and should be unique (used for DOM element IDs etc. maybe used to link to source code)
    • - |
    • version references the version that the API call is defined in.
    • - |
    • function is the (scala) partial function that implements this endpoint. It is unique per version of the API.
    • - |
    • request_url is empty for the root call, else the path. It contains the standard prefix (e.g. /obp) and the implemented version (the version where this endpoint was defined) e.g. /obp/v1.2.0/resource
    • - |
    • specified_url (recommended to use) is empty for the root call, else the path. It contains the standard prefix (e.g. /obp) and the version specified in the call e.g. /obp/v3.1.0/resource. In OBP, endpoints are first made available at the request_url, but the same resource (function call) is often made available under later versions (specified_url). To access the latest version of all endpoints use the latest version available on your OBP instance e.g. /obp/v3.1.0 - To get the original version use the request_url. We recommend to use the specified_url since non semantic improvements are more likely to be applied to later implementations of the call.
    • - |
    • summary is a short description inline with the swagger terminology.
    • - |
    • description may contain html markup (generated from markdown on the server).
    • - |
    - """, + getResourceDocsDescription("/banks/BANK_ID"), emptyObjectJson, emptyObjectJson, UnknownError :: Nil, @@ -602,8 +567,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth ) } requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} - json <- NewStyle.function.tryons(s"$UnknownError Can not create dynamic resource docs.", 400, callContext) { - getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam).map(successJsonResponse(_)).get + json <- NewStyle.function.tryons(s"$UnknownError Can not create dynamic resource docs.", 400, callContext) { + getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, Some(bankId)).map(successJsonResponse(_)).get } } yield { (Full(json), HttpCode.`200`(callContext)) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 932a9525b..4f65b20d6 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1347,7 +1347,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ var roles: Option[List[ApiRole]] = None, isFeatured: Boolean = false, specialInstructions: Option[String] = None, - var specifiedUrl: Option[String] = None // A derived value: Contains the called version (added at run time). See the resource doc for resource doc! + var specifiedUrl: Option[String] = None, // A derived value: Contains the called version (added at run time). See the resource doc for resource doc! + bankId: Option[String] = None //we need to filter the resource Doc by BankId ) { // this code block will be merged to constructor. { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala index 6f643f6fe..35885e3dc 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala @@ -294,7 +294,8 @@ object DynamicEndpointHelper extends RestHelper { successResponseBody, errorResponseBodies, tags, - roles + roles, + bankId= bankId ) DynamicEndpointItem(path, successCode, doc) } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala index 7b628b777..fb5100b27 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala @@ -154,7 +154,8 @@ object DynamicEntityHelper { UnknownError ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), - Some(List(dynamicEntityInfo.canGetRole)) + Some(List(dynamicEntityInfo.canGetRole)), + bankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.GET_ONE, entityName) -> ResourceDoc( endPoint, @@ -180,7 +181,8 @@ object DynamicEntityHelper { UnknownError ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), - Some(List(dynamicEntityInfo.canGetRole)) + Some(List(dynamicEntityInfo.canGetRole)), + bankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.CREATE, entityName) -> ResourceDoc( @@ -209,7 +211,8 @@ object DynamicEntityHelper { UnknownError ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), - Some(List(dynamicEntityInfo.canCreateRole)) + Some(List(dynamicEntityInfo.canCreateRole)), + bankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.UPDATE, entityName) -> ResourceDoc( @@ -238,7 +241,8 @@ object DynamicEntityHelper { UnknownError ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), - Some(List(dynamicEntityInfo.canUpdateRole)) + Some(List(dynamicEntityInfo.canUpdateRole)), + bankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.DELETE, entityName) -> ResourceDoc( @@ -264,7 +268,8 @@ object DynamicEntityHelper { UnknownError ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), - Some(List(dynamicEntityInfo.canDeleteRole)) + Some(List(dynamicEntityInfo.canDeleteRole)), + bankId= dynamicEntityInfo.bankId ) resourceDocs From cc287f51492292ce1f00a27672a1aec8bfdbb9a7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 12 Aug 2021 17:03:31 +0200 Subject: [PATCH 030/293] refactor/tweaked the getResourceDocsDescription method --- .../ResourceDocsAPIMethods.scala | 57 ++++++------------- 1 file changed, 16 insertions(+), 41 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 3d6d2c968..d06b32005 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -385,35 +385,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth "GET", "/dummy", "Test Resource Doc.", - """ - |I am only a test Resource Doc - | - |It's turtles all the way down. - | - |#This should be H1 - | - |##This should be H2 - | - |###This should be H3 - | - |####This should be H4 - | - |Here is a list with two items: - | - |* One - |* Two - | - |There are underscores by them selves _ - | - |There are _underscores_ around a word - | - |There are underscores_in_words - | - |There are 'underscores_in_words_inside_quotes' - | - |There are (underscores_in_words_in_brackets) - | - |_etc_...""", + """I am only a test Resource Doc""", emptyObjectJson, emptyObjectJson, UnknownError :: Nil, @@ -425,7 +397,10 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth - def getResourceDocsDescription(bankUrl: String) = + def getResourceDocsDescription(isBankLevelResourceDoc: Boolean) = { + + val endpointBankIdPath = if (isBankLevelResourceDoc) "/banks/BANK_ID" else "" + s"""Get documentation about the RESTful resources on this server including example bodies for POST and PUT requests. | |This is the native data format used to document OBP endpoints. Each endpoint has a Resource Doc (a Scala case class) defined in the source code. @@ -452,12 +427,12 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth |See the Resource Doc endpoint for more information. | |Following are more examples: - |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v3.1.0/obp - |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v3.1.0/obp?tags=Account,Bank - |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v3.1.0/obp?functions=getBanks,bankById - |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v4.0.0/obp?language=zh - |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v4.0.0/obp?content=static,dynamic,all - |${getObpApiRoot}/v3.1.0$bankUrl/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 + |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v3.1.0/obp + |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v3.1.0/obp?tags=Account,Bank + |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v3.1.0/obp?functions=getBanks,bankById + |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v4.0.0/obp?language=zh + |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v4.0.0/obp?content=static,dynamic,all + |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 | |
      |
    • operation_id is concatenation of "v", version and function and should be unique (used for DOM element IDs etc. maybe used to link to source code)
    • @@ -469,7 +444,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth |
    • description may contain html markup (generated from markdown on the server).
    • |
    """ - + } localResourceDocs += ResourceDoc( @@ -479,9 +454,9 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth "GET", "/resource-docs/API_VERSION/obp", "Get Resource Docs.", - getResourceDocsDescription(""), + getResourceDocsDescription(false), emptyObjectJson, - emptyObjectJson, //exampleResourceDocsJson + exampleResourceDocsJson, UnknownError :: Nil, List(apiTagDocumentation, apiTagApi) ) @@ -540,9 +515,9 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth "GET", "/banks/BANK_ID/resource-docs/API_VERSION/obp", "Get Bank Level Dynamic Resource Docs.", - getResourceDocsDescription("/banks/BANK_ID"), - emptyObjectJson, + getResourceDocsDescription(true), emptyObjectJson, + exampleResourceDocsJson, UnknownError :: Nil, List(apiTagDocumentation, apiTagApi) ) From 15393a0bbe8c40b7b6dc7c5e9c6b37f7132bc927 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 13 Aug 2021 14:00:11 +0200 Subject: [PATCH 031/293] bugfix/support the spaces in password --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 4f65b20d6..942e10431 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -692,9 +692,10 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } /** only A-Z, a-z, 0-9, all allowed characters for password and max length <= 512 */ + /** also support space now */ def checkMediumPassword(value:String): String ={ val valueLength = value.length - val regex = """^([A-Za-z0-9!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~]+)$""".r + val regex = """^([A-Za-z0-9!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~ ]+)$""".r value match { case regex(e) if(valueLength <= 512) => SILENCE_IS_GOLDEN case regex(e) if(valueLength > 512) => ErrorMessages.InvalidValueLength From e283fb480ff77538ffcadbce97e69a713380baa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 13 Aug 2021 17:21:51 +0200 Subject: [PATCH 032/293] feature/Add is_active (boolean) to Product Attribute POST and GET APIs - WIP --- .../code/api/util/migration/Migration.scala | 12 ++ .../MigrationOfProductAttribute.scala | 56 ++++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 180 ++++++++++++++++++ .../code/api/v4_0_0/JSONFactory4.0.0.scala | 26 ++- .../MappedProductAttributeProvider.scala | 12 +- .../commons/model/CommonModel.scala | 3 +- .../commons/model/CommonModelTrait.scala | 2 + 7 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfProductAttribute.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 77557e398..b8fc85153 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -81,6 +81,7 @@ object Migration extends MdcLoggable { alterColumnDetailsAtTableTransactionRequest() deleteDuplicatedRowsInTheTableUserAuthContext() populateTheFieldDeletedAtResourceUser(startedBeforeSchemifier) + populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -247,6 +248,17 @@ object Migration extends MdcLoggable { } } } + private def populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.populateTheFieldIsActiveAtProductAttribute(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfProductAttribute.populateTheFieldIsActive(name) + } + } + } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfProductAttribute.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProductAttribute.scala new file mode 100644 index 000000000..a47576f10 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProductAttribute.scala @@ -0,0 +1,56 @@ +package code.api.util.migration + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} + +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.model.Consumer +import code.productAttributeattribute.MappedProductAttribute +import net.liftweb.mapper.DB +import net.liftweb.util.DefaultConnectionIdentifier + +object MigrationOfProductAttribute { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def populateTheFieldIsActive(name: String): Boolean = { + DbFunction.tableExists(MappedProductAttribute, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + // Make back up + DbFunction.makeBackUpOfTable(MappedProductAttribute) + + val emptyDeletedField = + for { + attribute <- MappedProductAttribute.findAll() if attribute.isActive.isEmpty == true + } yield { + attribute.IsActive(true).saveMe() + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Updated number of rows: + |${emptyDeletedField.size} + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${Consumer._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } +} diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index e8c765b0a..0d39455f8 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5443,6 +5443,186 @@ trait APIMethods400 { } } + + val productAttributeGeneralInfo = + s""" + |Product Attributes are used to describe a financial Product with a list of typed key value pairs. + | + |Each Product Attribute is linked to its Product by PRODUCT_CODE + | + | + """.stripMargin + + staticResourceDocs += ResourceDoc( + createProductAttribute, + implementedInApiVersion, + nameOf(createProductAttribute), + "POST", + "/banks/BANK_ID/products/PRODUCT_CODE/attribute", + "Create Product Attribute", + s""" Create Product Attribute + | + |$productAttributeGeneralInfo + | + |Typical product attributes might be: + | + |ISIN (for International bonds) + |VKN (for German bonds) + |REDCODE (markit short code for credit derivative) + |LOAN_ID (e.g. used for Anacredit reporting) + | + |ISSUE_DATE (When the bond was issued in the market) + |MATURITY_DATE (End of life time of a product) + |TRADABLE + | + |See [FPML](http://www.fpml.org/) for more examples. + | + | + |The type field must be one of "STRING", "INTEGER", "DOUBLE" or DATE_WITH_DAY" + | + | + | + |${authenticationRequiredMessage(true)} + | + |""", + productAttributeJson, + productAttributeResponseJson, + List( + InvalidJsonFormat, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canCreateProductAttribute)) + ) + + lazy val createProductAttribute : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "attribute" :: Nil JsonPost json -> _=> { + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId, u.userId, canCreateProductAttribute, callContext) + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) + failMsg = s"$InvalidJsonFormat The Json body should be the $ProductAttributeJson " + postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[ProductAttributeJson] + } + failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + + s"${ProductAttributeType.DOUBLE}(12.1234), ${ProductAttributeType.STRING}(TAX_NUMBER), ${ProductAttributeType.INTEGER}(123) and ${ProductAttributeType.DATE_WITH_DAY}(2012-04-23)" + productAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { + ProductAttributeType.withName(postedData.`type`) + } + + (productAttribute, callContext) <- NewStyle.function.createOrUpdateProductAttribute( + BankId(bankId), + ProductCode(productCode), + None, + postedData.name, + productAttributeType, + postedData.value, + callContext: Option[CallContext] + ) + } yield { + (createProductAttributeJson(productAttribute), HttpCode.`201`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + updateProductAttribute, + implementedInApiVersion, + nameOf(updateProductAttribute), + "PUT", + "/banks/BANK_ID/products/PRODUCT_CODE/attributes/PRODUCT_ATTRIBUTE_ID", + "Update Product Attribute", + s""" Update Product Attribute. + | + + |$productAttributeGeneralInfo + | + |Update one Product Attribute by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + productAttributeJson, + productAttributeResponseJson, + List( + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle)) + + lazy val updateProductAttribute : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "attributes" :: productAttributeId :: Nil JsonPut json -> _ =>{ + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId, u.userId, canUpdateProductAttribute, callContext) + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) + failMsg = s"$InvalidJsonFormat The Json body should be the $ProductAttributeJson " + postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[ProductAttributeJson] + } + failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + + s"${ProductAttributeType.DOUBLE}(12.1234), ${ProductAttributeType.STRING}(TAX_NUMBER), ${ProductAttributeType.INTEGER}(123) and ${ProductAttributeType.DATE_WITH_DAY}(2012-04-23)" + productAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { + ProductAttributeType.withName(postedData.`type`) + } + (_, callContext) <- NewStyle.function.getProductAttributeById(productAttributeId, callContext) + (productAttribute, callContext) <- NewStyle.function.createOrUpdateProductAttribute( + BankId(bankId), + ProductCode(productCode), + Some(productAttributeId), + postedData.name, + productAttributeType, + postedData.value, + callContext: Option[CallContext] + ) + } yield { + (createProductAttributeJson(productAttribute), HttpCode.`200`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getProductAttribute, + implementedInApiVersion, + nameOf(getProductAttribute), + "GET", + "/banks/BANK_ID/products/PRODUCT_CODE/attributes/PRODUCT_ATTRIBUTE_ID", + "Get Product Attribute", + s""" Get Product Attribute + | + |$productAttributeGeneralInfo + | + |Get one product attribute by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + productAttributeResponseJson, + List( + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle)) + + lazy val getProductAttribute : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "attributes" :: productAttributeId :: Nil JsonGet _ => { + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId, u.userId, canGetProductAttribute, callContext) + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) + (productAttribute, callContext) <- NewStyle.function.getProductAttributeById(productAttributeId, callContext) + + } yield { + (createProductAttributeJson(productAttribute), HttpCode.`200`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( createOrUpdateTransactionAttributeDefinition, implementedInApiVersion, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 957653c17..ac626237c 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -38,8 +38,8 @@ import code.api.v1_4_0.JSONFactory1_4_0.{LocationJsonV140, MetaJsonV140, Transac import code.api.v2_0_0.{EntitlementJSONs, JSONFactory200, TransactionRequestChargeJsonV200} import code.api.v2_1_0.{IbanJson, JSONFactory210, PostCounterpartyBespokeJson, ResourceUserJSON} import code.api.v2_2_0.CounterpartyMetadataJson -import code.api.v3_0_0.JSONFactory300.{createAccountRoutingsJSON, createAccountRulesJSON, createLocationJson, createMetaJson, transformToAddressFromV300} -import code.api.v3_0_0.{AccountRuleJsonV300, AddressJsonV300, CustomerAttributeResponseJsonV300, OpeningTimesV300, ViewJSON300, ViewsJSON300} +import code.api.v3_0_0.JSONFactory300._ +import code.api.v3_0_0._ import code.api.v3_1_0.JSONFactory310.createAccountAttributeJson import code.api.v3_1_0.{AccountAttributeResponseJson, RedisCallLimitJson} import code.apicollection.ApiCollectionTrait @@ -650,6 +650,16 @@ case class JsonValidationV400(operation_id: String, json_schema: JsonSchemaV400) // Validation related END +case class ProductAttributeResponseJson( + bank_id: String, + product_code: String, + product_attribute_id: String, + name: String, + `type`: String, + value: String, + is_active: Option[Boolean] + ) + case class IbanCheckerJsonV400( is_valid: Boolean, details: Option[IbanDetailsJsonV400] @@ -1358,6 +1368,18 @@ object JSONFactory400 { ) } + + def createProductAttributeJson(productAttribute: ProductAttribute): ProductAttributeResponseJson = + ProductAttributeResponseJson( + bank_id = productAttribute.bankId.value, + product_code = productAttribute.productCode.value, + product_attribute_id = productAttribute.productAttributeId, + name = productAttribute.name, + `type` = productAttribute.attributeType.toString, + value = productAttribute.value, + is_active = productAttribute.isActive + ) + def createApiCollectionEndpointsJsonV400(apiCollectionEndpoints: List[ApiCollectionEndpointTrait]) = { ApiCollectionEndpointsJson400(apiCollectionEndpoints.map(apiCollectionEndpoint => createApiCollectionEndpointJsonV400(apiCollectionEndpoint))) } diff --git a/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala b/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala index fc1754952..bd4cb384b 100644 --- a/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala +++ b/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala @@ -2,10 +2,11 @@ package code.productAttributeattribute import code.productattribute.ProductAttributeProvider import code.util.{AttributeQueryTrait, MappedUUID, UUIDString} +import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.model.enums.ProductAttributeType import com.openbankproject.commons.model.{BankId, ProductAttribute, ProductCode} import net.liftweb.common.{Box, Empty, Full} -import net.liftweb.mapper.{BaseMappedField, _} +import net.liftweb.mapper.{BaseMappedField, MappedBoolean, _} import net.liftweb.util.Helpers.tryo import com.openbankproject.commons.ExecutionContext.Implicits.global @@ -82,6 +83,10 @@ class MappedProductAttribute extends ProductAttribute with LongKeyedMapper[Mappe object mValue extends MappedString(this, 255) + object IsActive extends MappedBoolean(this) { + override def defaultValue = true + } + override def bankId: BankId = BankId(mBankId.get) @@ -94,8 +99,9 @@ class MappedProductAttribute extends ProductAttribute with LongKeyedMapper[Mappe override def attributeType: ProductAttributeType.Value = ProductAttributeType.withName(mType.get) override def value: String = mValue.get - - + + override def isActive: Option[Boolean] = if (IsActive.jdbcFriendly(IsActive.calcFieldName) == null) { None } else Some(IsActive.get) + } // diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala index d26212e2e..cb58573d3 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala @@ -71,7 +71,8 @@ case class ProductAttributeCommons( productAttributeId :String, name :String, attributeType : ProductAttributeType.Value, - value :String) extends ProductAttribute + value :String, + isActive: Option[Boolean] = None) extends ProductAttribute object ProductAttributeCommons extends Converter[ProductAttribute, ProductAttributeCommons] diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala index d0af2ab9e..a53d71265 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala @@ -257,6 +257,8 @@ trait ProductAttribute { def attributeType: ProductAttributeType.Value def value: String + + def isActive: Option[Boolean] } From 273d32f04237fe907cd4182ed8503e100f353259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 13 Aug 2021 23:11:12 +0200 Subject: [PATCH 033/293] feature/Add is_active (boolean) to Product Attribute POST and GET APIs - tweak frozen tests --- .../RestConnector_vMar2019_frozen_meta_data | Bin 96085 -> 96114 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data index 682753c46c8bb4d1012217e608d1b6f5a60c1d7e..58f4d39e087162721117c1654020381449c46c6f 100644 GIT binary patch delta 61 zcmV-D0K)&(?gjGh1+aj`m!J;;6PLek0Tm<$Q*?4^ZfA4=2x)UcV{~bDWpn@!PjGZ; TZ*E&cZ*Od6VQyWsuf(RZ3<4P) delta 31 pcmV+)0O0@f?giEE1+aj`lPY-=lW))!mmd%TLX&*T6tf$}SF-p{4rBlT From 0be4aad4c56a77970d464971e33ac6060515f53b Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 16 Aug 2021 11:02:47 +0200 Subject: [PATCH 034/293] docfix/added more info for Glossary.connector --- .../scala/code/api/util/ExampleValue.scala | 3 -- .../main/scala/code/api/util/Glossary.scala | 33 ++++++++++++++----- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 5112ca9cf..45a5212a0 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -1292,9 +1292,6 @@ object ExampleValue { lazy val chargeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("charge", chargeExample) - lazy val connectorExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) - glossaryItems += makeGlossaryItem("connector", connectorExample) - lazy val kycDocumentIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("kyc_document_id", kycDocumentIdExample) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index d18624200..980182b14 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -447,18 +447,33 @@ object Glossary extends MdcLoggable { | |It's called "mapped" because the default datasource on OBP is a relational database, and access to that database is always done through an Object-Relational Mapper (ORM) called Mapper (from a framework we use called Liftweb). | - |However, there are multiple available connector implementations (aka connectors) and you can mix and match them using the Star connector and you can write your own in Scala. You can also write Adapters in any language which respond to messages sent by the connector. | - |Let's start with an ASCII art diagram: - | -|
    -				 |[=============]                                                                      [============]       [============]
    -				 |[.............]                                                                      [............]       [............]
    -				 |[...OBP API...] ===> OBP Endpoints call multiple connector functions / methods. ===> [  Connector ] ===>  [  Database  ]
    -				 |[.............]        Each method has input parameters and a return type            [  (Mapped)  ]       [  (Adapter) ]
    -				 |[=============]          Every implementation must respect the interface             [============]       [============]
    +				 |
    +				 |[=============]                                                                     [============]       [============]
    +				 |[.............]                                                                     [            ]       [            ]
    +				 |[...OBP API...] ===> OBP Endpoints call connector functions (aka methods) ===>      [  Connector ] ===>  [  Database  ]
    +				 |[.............]          The default implementation is called "Mapped"              [  (Mapped)  ]       [  (Adapter) ]
    +				 |[=============]              The Mapped Connector talks to a Database               [============]       [============]
     				 |
     				 |
    + | + |However, there are multiple available connector implementations - and you can also mix and create your own.| + | + |E.g. Kafka + | + |
    +				 |[=============]                              [============]       [============]     [============]       [============]
    +				 |[             ]                              [            ]       [            ]     [            ]       [            ]
    +				 |[   OBP API   ] ===> Kafka Connector   ===>  [  Kafka     ] ===>  [  Kafka     ]     [  OBP Kafka ]  ===> [  CBS       ]
    +				 |[             ]      Puts OBP Messages       [  Connector ]       [  Cluster   ]     [  Adapter   ]       [            ]
    +				 |[=============]       onto a Kafka           [============]       [============]     [============]       [============]
    +				 |
    +				 |
    + | + | + | + |You can mix and match them using the Star connector and you can write your own in Scala. You can also write Adapters in any language which respond to messages sent by the connector. + | |we use the term "Connector" to mean the Scala/Java/Other JVM code in OBP that connects directly or indirectly to the systems of record i.e. the Core Banking Systems, Payment Systems and Databases. | | From 8e2ed0454ce70f66074d746b343423f6d9997c0a Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 17 Aug 2021 10:13:29 +0200 Subject: [PATCH 035/293] feature/OBPv400 added new endpoint getResourceDocsObpV400 - WIP - step1 --- .../ResourceDocs1_4_0/ResourceDocs140.scala | 2 +- .../ResourceDocsAPIMethods.scala | 91 ++++++++++++++++--- .../code/api/v1_4_0/JSONFactory1_4_0.scala | 21 ++++- .../scala/code/api/v4_0_0/APIMethods400.scala | 2 +- .../api/v1_4_0/JSONFactory1_4_0Test.scala | 4 +- 5 files changed, 98 insertions(+), 22 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index 47bb7b0ed..e1dfd2a4c 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -95,7 +95,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val version: ApiVersion = ApiVersion.v4_0_0 // = "4.0.0" // We match other api versions so API explorer can easily use the path. val versionStatus = "BLEEDING-EDGE" val routes = List( - ImplementationsResourceDocs.getResourceDocsObp, + ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp ) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index d06b32005..c06420927 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -227,7 +227,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth partialFunctionNames: Option[List[String]], languageParam: Option[LanguageParam], contentParam: Option[ContentParam], - cacheModifierParam: Option[String] + cacheModifierParam: Option[String], + withMeta:Boolean ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -240,7 +241,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getStaticResourceDocsTTL second) { logger.debug(s"Generating OBP Resource Docs requestedApiVersion is $requestedApiVersion") - val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames) + val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, withMeta) resourceDocJson.map(resourceDocsJsonToJsonResponse) } } @@ -259,7 +260,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth partialFunctionNames: Option[List[String]], languageParam: Option[LanguageParam], contentParam: Option[ContentParam], - cacheModifierParam: Option[String] + cacheModifierParam: Option[String], + withMeta:Boolean ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -300,7 +302,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth val allDocs = staticDocs.map( _ ++ filteredDocs) - val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames) + val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, withMeta) resourceDocJson.map(resourceDocsJsonToJsonResponse) } } @@ -312,7 +314,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth languageParam: Option[LanguageParam], contentParam: Option[ContentParam], cacheModifierParam: Option[String], - bankId:Option[String] + bankId:Option[String], + withMeta:Boolean ): Option[JValue] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { @@ -344,7 +347,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case None => dynamicDocs } - val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames) + val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, withMeta) resourceDocJson.map(resourceDocsJsonToJsonResponse) }}} @@ -352,14 +355,15 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth private def resourceDocsToResourceDocJson(rd: Option[List[ResourceDoc]], resourceDocTags: Option[List[ResourceDocTag]], - partialFunctionNames: Option[List[String]]): Option[ResourceDocsJson] = + partialFunctionNames: Option[List[String]], + withMeta:Boolean): Option[ResourceDocsJson] = for { resourceDocs <- rd } yield { // Filter val rdFiltered = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, resourceDocTags, partialFunctionNames) // Format the data as json - JSONFactory1_4_0.createResourceDocsJson(rdFiltered) + JSONFactory1_4_0.createResourceDocsJson(rdFiltered, withMeta) } private val getChineseVersionResourceDocs : Box[JsonResponse] = { @@ -392,7 +396,9 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth List(apiTagDocumentation)) - val exampleResourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc)) + val exampleResourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), false) + + val exampleResourceDocsJsonV400 = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), true) @@ -485,19 +491,19 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case _ if(apiCollectionIdParam.isDefined) => val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) val resourceDocs = ResourceDoc.getResourceDocs(operationIds) - val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs) + val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs,false) val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) Future(resourceDocsJsonJValue.map(successJsonResponse(_))) case _ => contentParam match { case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None) + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, false) Future(dynamicDocs.map(successJsonResponse(_))) case Some(STATIC) => - val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) + val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, false) Future(staticDocs.map(successJsonResponse(_))) case _ => - val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam) + val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, false) Future(docs.map(successJsonResponse(_))) } } @@ -507,6 +513,63 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } } + + localResourceDocs += ResourceDoc( + getResourceDocsObpV400, + implementedInApiVersion, + nameOf(getResourceDocsObpV400), + "GET", + "/resource-docs/API_VERSION/obp", + "Get Resource Docs with Meta", + getResourceDocsDescription(false), + emptyObjectJson, + exampleResourceDocsJsonV400, + UnknownError :: Nil, + List(apiTagDocumentation, apiTagApi) + ) + + def getResourceDocsObpV400 : OBPEndpoint = { + case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { + val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() + cc => + for { + (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { + case false => anonymousAccess(cc) + case true => authenticatedAccess(cc) // If set resource_docs_requires_role=true, we need check the authentication + } + _ <- resourceDocsRequireRole match { + case false => Future() + case true => // If set resource_docs_requires_role=true, we need check the the roles as well + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc::Nil, cc.callContext) + } + requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} + _ <- Helper.booleanToFuture(s"$ApiVersionNotSupported $requestedApiVersionString", 400, callContext)(versionIsAllowed(requestedApiVersion)) + json <- languageParam match { + case Some(ZH) => Future(getChineseVersionResourceDocs) + case _ if(apiCollectionIdParam.isDefined) => + val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) + val resourceDocs = ResourceDoc.getResourceDocs(operationIds) + val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs,true) + val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) + Future(resourceDocsJsonJValue.map(successJsonResponse(_))) + case _ => + contentParam match { + case Some(DYNAMIC) => + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, true) + Future(dynamicDocs.map(successJsonResponse(_))) + case Some(STATIC) => + val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, true) + Future(staticDocs.map(successJsonResponse(_))) + case _ => + val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, true) + Future(docs.map(successJsonResponse(_))) + } + } + } yield { + (json, HttpCode.`200`(callContext)) + } + } + } localResourceDocs += ResourceDoc( getBankLevelDynamicResourceDocsObp, @@ -543,7 +606,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} json <- NewStyle.function.tryons(s"$UnknownError Can not create dynamic resource docs.", 400, callContext) { - getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, Some(bankId)).map(successJsonResponse(_)).get + getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, Some(bankId), false).map(successJsonResponse(_)).get } } yield { (Full(json), HttpCode.`200`(callContext)) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index 46848c09d..7d775a88d 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -325,7 +325,10 @@ object JSONFactory1_4_0 extends MdcLoggable{ function : String // The val / partial function that implements the call e.g. "getBranches" ) - + case class ResourceDocMeta( + response_date: Date, + count: Int + ) // Used to describe the OBP API calls for documentation and API discovery purposes case class ResourceDocJson(operation_id: String, implemented_by: ImplementedByJson, @@ -350,7 +353,10 @@ object JSONFactory1_4_0 extends MdcLoggable{ // Creates the json resource_docs - case class ResourceDocsJson (resource_docs : List[ResourceDocJson]) + case class ResourceDocsJson ( + resource_docs : List[ResourceDocJson], + meta: Option[ResourceDocMeta] = None + ) /** * get the glossaryItem.title by the input string @@ -508,8 +514,15 @@ object JSONFactory1_4_0 extends MdcLoggable{ }) } - def createResourceDocsJson(resourceDocList: List[ResourceDoc]) : ResourceDocsJson = { - ResourceDocsJson(resourceDocList.map(createResourceDocJson)) + def createResourceDocsJson(resourceDocList: List[ResourceDoc], withMeta:Boolean) : ResourceDocsJson = { + if(withMeta){ + ResourceDocsJson( + resourceDocList.map(createResourceDocJson), + meta=Some(ResourceDocMeta(new Date(), resourceDocList.length)) + ) + } else { + ResourceDocsJson(resourceDocList.map(createResourceDocJson)) + } } //please check issue first: https://github.com/OpenBankProject/OBP-API/issues/877 diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index e8c765b0a..a4e195180 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9423,7 +9423,7 @@ trait APIMethods400 { DynamicEndpointHelper.getRoles(dynamicEndpointInfo) } _ <- NewStyle.function.tryons(InvalidJsonFormat+"Can not generate OBP external Resource Docs", 400, cc.callContext) { - JSONFactory1_4_0.createResourceDocsJson(dynamicEndpointInfo.resourceDocs.toList) + JSONFactory1_4_0.createResourceDocsJson(dynamicEndpointInfo.resourceDocs.toList, false) } (dynamicEndpoint, callContext) <- NewStyle.function.createDynamicEndpoint(bankId, cc.userId, postedJson.swaggerString, cc.callContext) _ <- NewStyle.function.tryons(InvalidJsonFormat+s"Can not grant these roles ${roles.toString} ", 400, cc.callContext) { diff --git a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala index 16e1ed64a..9d9412596 100644 --- a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala +++ b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala @@ -84,7 +84,7 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers { scenario("createResourceDocsJson should work well, no exception is good enough") { val resourceDoc: mutable.Seq[ResourceDoc] = OBPAPI3_0_0.allResourceDocs - val result = JSONFactory1_4_0.createResourceDocsJson(resourceDoc.toList) + val result = JSONFactory1_4_0.createResourceDocsJson(resourceDoc.toList, false) } scenario("createTypedBody should work well, no exception is good enough") { @@ -97,7 +97,7 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers { scenario("validate all the resouceDocs json schema, no exception is good enough") { val resourceDocsRaw= OBPAPI3_0_0.allResourceDocs - val resourceDocs = JSONFactory1_4_0.createResourceDocsJson(resourceDocsRaw.toList) + val resourceDocs = JSONFactory1_4_0.createResourceDocsJson(resourceDocsRaw.toList,false) for{ resouceDoc <- resourceDocs.resource_docs From 485df5febeb6a38885cd6a326f612def2a26892b Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 17 Aug 2021 11:02:09 +0200 Subject: [PATCH 036/293] feature/OBPv400 added new endpoint getResourceDocsObpV400 - WIP - step2 --- .../ResourceDocsAPIMethods.scala | 126 ++++++++---------- 1 file changed, 52 insertions(+), 74 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index c06420927..756a74d25 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -473,44 +473,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth def getResourceDocsObp : OBPEndpoint = { case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() - cc => - for { - (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { - case false => anonymousAccess(cc) - case true => authenticatedAccess(cc) // If set resource_docs_requires_role=true, we need check the authentication - } - _ <- resourceDocsRequireRole match { - case false => Future() - case true => // If set resource_docs_requires_role=true, we need check the the roles as well - NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc::Nil, cc.callContext) - } - requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} - _ <- Helper.booleanToFuture(s"$ApiVersionNotSupported $requestedApiVersionString", 400, callContext)(versionIsAllowed(requestedApiVersion)) - json <- languageParam match { - case Some(ZH) => Future(getChineseVersionResourceDocs) - case _ if(apiCollectionIdParam.isDefined) => - val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) - val resourceDocs = ResourceDoc.getResourceDocs(operationIds) - val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs,false) - val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) - Future(resourceDocsJsonJValue.map(successJsonResponse(_))) - case _ => - contentParam match { - case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, false) - Future(dynamicDocs.map(successJsonResponse(_))) - case Some(STATIC) => - val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, false) - Future(staticDocs.map(successJsonResponse(_))) - case _ => - val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, false) - Future(docs.map(successJsonResponse(_))) - } - } - } yield { - (json, HttpCode.`200`(callContext)) - } - + cc => + getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam, false) } } @@ -532,45 +496,59 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() cc => - for { - (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { - case false => anonymousAccess(cc) - case true => authenticatedAccess(cc) // If set resource_docs_requires_role=true, we need check the authentication - } - _ <- resourceDocsRequireRole match { - case false => Future() - case true => // If set resource_docs_requires_role=true, we need check the the roles as well - NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc::Nil, cc.callContext) - } - requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} - _ <- Helper.booleanToFuture(s"$ApiVersionNotSupported $requestedApiVersionString", 400, callContext)(versionIsAllowed(requestedApiVersion)) - json <- languageParam match { - case Some(ZH) => Future(getChineseVersionResourceDocs) - case _ if(apiCollectionIdParam.isDefined) => - val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) - val resourceDocs = ResourceDoc.getResourceDocs(operationIds) - val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs,true) - val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) - Future(resourceDocsJsonJValue.map(successJsonResponse(_))) - case _ => - contentParam match { - case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, true) - Future(dynamicDocs.map(successJsonResponse(_))) - case Some(STATIC) => - val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, true) - Future(staticDocs.map(successJsonResponse(_))) - case _ => - val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, true) - Future(docs.map(successJsonResponse(_))) - } - } - } yield { - (json, HttpCode.`200`(callContext)) - } + getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam, true) } } + private def getApiLevelResourceDocs( + cc: CallContext, + requestedApiVersionString: String, + tags: Option[List[ResourceDocTag]], + partialFunctions: Option[List[String]], + languageParam: Option[LanguageParam], + contentParam: Option[ContentParam], + apiCollectionIdParam: Option[String], + cacheModifierParam: Option[String], + withMeta: Boolean + ) = { + for { + (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { + case false => anonymousAccess(cc) + case true => authenticatedAccess(cc) // If set resource_docs_requires_role=true, we need check the authentication + } + _ <- resourceDocsRequireRole match { + case false => Future() + case true => // If set resource_docs_requires_role=true, we need check the the roles as well + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc :: Nil, cc.callContext) + } + requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} + _ <- Helper.booleanToFuture(s"$ApiVersionNotSupported $requestedApiVersionString", 400, callContext)(versionIsAllowed(requestedApiVersion)) + json <- languageParam match { + case Some(ZH) => Future(getChineseVersionResourceDocs) + case _ if (apiCollectionIdParam.isDefined) => + val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) + val resourceDocs = ResourceDoc.getResourceDocs(operationIds) + val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, withMeta) + val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) + Future(resourceDocsJsonJValue.map(successJsonResponse(_))) + case _ => + contentParam match { + case Some(DYNAMIC) => + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, withMeta) + Future(dynamicDocs.map(successJsonResponse(_))) + case Some(STATIC) => + val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, withMeta) + Future(staticDocs.map(successJsonResponse(_))) + case _ => + val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, withMeta) + Future(docs.map(successJsonResponse(_))) + } + } + } yield { + (json, HttpCode.`200`(callContext)) + } + } + localResourceDocs += ResourceDoc( getBankLevelDynamicResourceDocsObp, implementedInApiVersion, From 52b6162489a6e6afadee2b27e6a5072bffea5414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 17 Aug 2021 12:33:09 +0200 Subject: [PATCH 037/293] bugfix/Fix the migraton script populateNewFieldIsDeleted 2 --- obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala index 8d8ad31c5..82ed93bfc 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala @@ -108,7 +108,7 @@ class ResourceUser extends LongKeyedMapper[ResourceUser] with User with ManyToMa override def createdByConsentId = if(CreatedByConsentId.get == null) None else if (CreatedByConsentId.get.isEmpty) None else Some(CreatedByConsentId.get) //null --> None override def createdByUserInvitationId = if(CreatedByUserInvitationId.get == null) None else if (CreatedByUserInvitationId.get.isEmpty) None else Some(CreatedByUserInvitationId.get) //null --> None - override def isDeleted: Option[Boolean] = if(IsDeleted.get == null) None else Some(IsDeleted.get) // null --> false + override def isDeleted: Option[Boolean] = if(IsDeleted.jdbcFriendly(IsDeleted.calcFieldName) == null) None else Some(IsDeleted.get) // null --> None } object ResourceUser extends ResourceUser with LongKeyedMetaMapper[ResourceUser]{ From 870274d3bae6eab446858ccea734eb263d6674e7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 17 Aug 2021 14:28:59 +0200 Subject: [PATCH 038/293] feature/OBPv400 added new endpoint getResourceDocsObpV400 - WIP - step3 --- .../ResourceDocsAPIMethods.scala | 28 +++++++++---------- .../main/scala/code/api/util/APIUtil.scala | 2 +- .../code/api/v1_4_0/JSONFactory1_4_0.scala | 16 ++++++----- .../dynamic/DynamicEndpointHelper.scala | 2 +- .../v4_0_0/dynamic/DynamicEntityHelper.scala | 10 +++---- .../api/v1_4_0/JSONFactory1_4_0Test.scala | 2 +- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 756a74d25..0b7564993 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -228,7 +228,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth languageParam: Option[LanguageParam], contentParam: Option[ContentParam], cacheModifierParam: Option[String], - withMeta:Boolean + isNewVersion:Boolean ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -241,7 +241,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getStaticResourceDocsTTL second) { logger.debug(s"Generating OBP Resource Docs requestedApiVersion is $requestedApiVersion") - val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, withMeta) + val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, isNewVersion) resourceDocJson.map(resourceDocsJsonToJsonResponse) } } @@ -261,7 +261,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth languageParam: Option[LanguageParam], contentParam: Option[ContentParam], cacheModifierParam: Option[String], - withMeta:Boolean + isNewVersion:Boolean ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -302,7 +302,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth val allDocs = staticDocs.map( _ ++ filteredDocs) - val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, withMeta) + val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, isNewVersion) resourceDocJson.map(resourceDocsJsonToJsonResponse) } } @@ -315,13 +315,13 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth contentParam: Option[ContentParam], cacheModifierParam: Option[String], bankId:Option[String], - withMeta:Boolean + isNewVersion:Boolean ): Option[JValue] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getDynamicResourceDocsTTL second) { val dynamicDocs = (DynamicEntityHelper.doc ++ DynamicEndpointHelper.doc ++ DynamicEndpoints.dynamicResourceDocs) - .filter(rd => if (bankId.isDefined) rd.bankId == bankId else true) + .filter(rd => if (bankId.isDefined) rd.createdByBankId == bankId else true) .filter(rd => rd.implementedInApiVersion == requestedApiVersion) .map(it => it.specifiedUrl match { case Some(_) => it @@ -347,7 +347,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case None => dynamicDocs } - val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, withMeta) + val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, isNewVersion) resourceDocJson.map(resourceDocsJsonToJsonResponse) }}} @@ -356,14 +356,14 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth private def resourceDocsToResourceDocJson(rd: Option[List[ResourceDoc]], resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]], - withMeta:Boolean): Option[ResourceDocsJson] = + isNewVersion:Boolean): Option[ResourceDocsJson] = for { resourceDocs <- rd } yield { // Filter val rdFiltered = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, resourceDocTags, partialFunctionNames) // Format the data as json - JSONFactory1_4_0.createResourceDocsJson(rdFiltered, withMeta) + JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isNewVersion) } private val getChineseVersionResourceDocs : Box[JsonResponse] = { @@ -509,7 +509,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth contentParam: Option[ContentParam], apiCollectionIdParam: Option[String], cacheModifierParam: Option[String], - withMeta: Boolean + isNewVersion: Boolean ) = { for { (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { @@ -528,19 +528,19 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case _ if (apiCollectionIdParam.isDefined) => val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) val resourceDocs = ResourceDoc.getResourceDocs(operationIds) - val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, withMeta) + val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isNewVersion) val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) Future(resourceDocsJsonJValue.map(successJsonResponse(_))) case _ => contentParam match { case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, withMeta) + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, isNewVersion) Future(dynamicDocs.map(successJsonResponse(_))) case Some(STATIC) => - val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, withMeta) + val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, isNewVersion) Future(staticDocs.map(successJsonResponse(_))) case _ => - val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, withMeta) + val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, isNewVersion) Future(docs.map(successJsonResponse(_))) } } diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 942e10431..0363008ec 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1349,7 +1349,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ isFeatured: Boolean = false, specialInstructions: Option[String] = None, var specifiedUrl: Option[String] = None, // A derived value: Contains the called version (added at run time). See the resource doc for resource doc! - bankId: Option[String] = None //we need to filter the resource Doc by BankId + createdByBankId: Option[String] = None //we need to filter the resource Doc by BankId ) { // this code block will be merged to constructor. { diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index 7d775a88d..95ba25ba2 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -347,7 +347,8 @@ object JSONFactory1_4_0 extends MdcLoggable{ is_featured: Boolean, special_instructions: String, specified_url: String, // Derived value. The Url when called under a certain version. - connector_methods: List[String] // this is the connector methods which need to be connected by this endpoint. + connector_methods: List[String], // this is the connector methods which need to be connected by this endpoint. + created_by_bank_id: Option[String] = None ) @@ -451,7 +452,7 @@ object JSONFactory1_4_0 extends MdcLoggable{ private val createResourceDocJsonMemo = new ConcurrentHashMap[ResourceDoc, ResourceDocJson] - def createResourceDocJson(rd: ResourceDoc) : ResourceDocJson = { + def createResourceDocJson(rd: ResourceDoc, isNewVersion:Boolean) : ResourceDocJson = { // if this calculate conversion already happened before, just return that value // if not calculated before, just do conversion val endpointTags = getAllEndpointTagsBox(rd.operationId).map(endpointTag =>ResourceDocTag(endpointTag.tagName)) @@ -509,19 +510,20 @@ object JSONFactory1_4_0 extends MdcLoggable{ is_featured = resourceDocUpdatedTags.isFeatured, special_instructions = PegdownOptions.convertPegdownToHtmlTweaked(resourceDocUpdatedTags.specialInstructions.getOrElse("").stripMargin), specified_url = resourceDocUpdatedTags.specifiedUrl.getOrElse(""), - connector_methods = resourceDocUpdatedTags.connectorMethods + connector_methods = resourceDocUpdatedTags.connectorMethods, + created_by_bank_id= if (isNewVersion) rd.createdByBankId else None // only for V400 we show the bankId ) }) } - def createResourceDocsJson(resourceDocList: List[ResourceDoc], withMeta:Boolean) : ResourceDocsJson = { - if(withMeta){ + def createResourceDocsJson(resourceDocList: List[ResourceDoc], isNewVersion:Boolean) : ResourceDocsJson = { + if(isNewVersion){ ResourceDocsJson( - resourceDocList.map(createResourceDocJson), + resourceDocList.map(createResourceDocJson(_,isNewVersion)), meta=Some(ResourceDocMeta(new Date(), resourceDocList.length)) ) } else { - ResourceDocsJson(resourceDocList.map(createResourceDocJson)) + ResourceDocsJson(resourceDocList.map(createResourceDocJson(_,false))) } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala index 35885e3dc..fa9461c1f 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEndpointHelper.scala @@ -295,7 +295,7 @@ object DynamicEndpointHelper extends RestHelper { errorResponseBodies, tags, roles, - bankId= bankId + createdByBankId= bankId ) DynamicEndpointItem(path, successCode, doc) } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala index fb5100b27..7ad2b08ad 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/dynamic/DynamicEntityHelper.scala @@ -155,7 +155,7 @@ object DynamicEntityHelper { ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), Some(List(dynamicEntityInfo.canGetRole)), - bankId= dynamicEntityInfo.bankId + createdByBankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.GET_ONE, entityName) -> ResourceDoc( endPoint, @@ -182,7 +182,7 @@ object DynamicEntityHelper { ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), Some(List(dynamicEntityInfo.canGetRole)), - bankId= dynamicEntityInfo.bankId + createdByBankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.CREATE, entityName) -> ResourceDoc( @@ -212,7 +212,7 @@ object DynamicEntityHelper { ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), Some(List(dynamicEntityInfo.canCreateRole)), - bankId= dynamicEntityInfo.bankId + createdByBankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.UPDATE, entityName) -> ResourceDoc( @@ -242,7 +242,7 @@ object DynamicEntityHelper { ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), Some(List(dynamicEntityInfo.canUpdateRole)), - bankId= dynamicEntityInfo.bankId + createdByBankId= dynamicEntityInfo.bankId ) resourceDocs += (DynamicEntityOperation.DELETE, entityName) -> ResourceDoc( @@ -269,7 +269,7 @@ object DynamicEntityHelper { ), List(apiTag, apiTagNewStyle, apiTagDynamicEntity, apiTagDynamic), Some(List(dynamicEntityInfo.canDeleteRole)), - bankId= dynamicEntityInfo.bankId + createdByBankId= dynamicEntityInfo.bankId ) resourceDocs diff --git a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala index 9d9412596..c9145169f 100644 --- a/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala +++ b/obp-api/src/test/scala/code/api/v1_4_0/JSONFactory1_4_0Test.scala @@ -79,7 +79,7 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers { scenario("createResourceDocJson should work well, no exception is good enough") { val resourceDoc: ResourceDoc = OBPAPI3_0_0.allResourceDocs(5) - val result: ResourceDocJson = JSONFactory1_4_0.createResourceDocJson(resourceDoc) + val result: ResourceDocJson = JSONFactory1_4_0.createResourceDocJson(resourceDoc,false) } scenario("createResourceDocsJson should work well, no exception is good enough") { From d27d181b022700e8d930b4b7751000853b0b21ff Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 17 Aug 2021 15:30:47 +0200 Subject: [PATCH 039/293] feature/OBPv400 added new endpoint getResourceDocsObpV400 - WIP - step4 --- .../ResourceDocsAPIMethods.scala | 26 +++++++++---------- .../code/api/v1_4_0/JSONFactory1_4_0.scala | 10 +++---- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 0b7564993..b72219aff 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -228,7 +228,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth languageParam: Option[LanguageParam], contentParam: Option[ContentParam], cacheModifierParam: Option[String], - isNewVersion:Boolean + isVersion4OrHigher:Boolean ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -241,7 +241,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getStaticResourceDocsTTL second) { logger.debug(s"Generating OBP Resource Docs requestedApiVersion is $requestedApiVersion") - val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, isNewVersion) + val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, isVersion4OrHigher) resourceDocJson.map(resourceDocsJsonToJsonResponse) } } @@ -261,7 +261,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth languageParam: Option[LanguageParam], contentParam: Option[ContentParam], cacheModifierParam: Option[String], - isNewVersion:Boolean + isVersion4OrHigher:Boolean ) : Box[JValue] = { /** * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" @@ -302,7 +302,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth val allDocs = staticDocs.map( _ ++ filteredDocs) - val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, isNewVersion) + val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, isVersion4OrHigher) resourceDocJson.map(resourceDocsJsonToJsonResponse) } } @@ -315,7 +315,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth contentParam: Option[ContentParam], cacheModifierParam: Option[String], bankId:Option[String], - isNewVersion:Boolean + isVersion4OrHigher:Boolean ): Option[JValue] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { @@ -347,7 +347,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case None => dynamicDocs } - val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, isNewVersion) + val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, isVersion4OrHigher) resourceDocJson.map(resourceDocsJsonToJsonResponse) }}} @@ -356,14 +356,14 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth private def resourceDocsToResourceDocJson(rd: Option[List[ResourceDoc]], resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]], - isNewVersion:Boolean): Option[ResourceDocsJson] = + isVersion4OrHigher:Boolean): Option[ResourceDocsJson] = for { resourceDocs <- rd } yield { // Filter val rdFiltered = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, resourceDocTags, partialFunctionNames) // Format the data as json - JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isNewVersion) + JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isVersion4OrHigher) } private val getChineseVersionResourceDocs : Box[JsonResponse] = { @@ -509,7 +509,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth contentParam: Option[ContentParam], apiCollectionIdParam: Option[String], cacheModifierParam: Option[String], - isNewVersion: Boolean + isVersion4OrHigher: Boolean ) = { for { (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { @@ -528,19 +528,19 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case _ if (apiCollectionIdParam.isDefined) => val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) val resourceDocs = ResourceDoc.getResourceDocs(operationIds) - val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isNewVersion) + val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher) val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson)) Future(resourceDocsJsonJValue.map(successJsonResponse(_))) case _ => contentParam match { case Some(DYNAMIC) => - val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, isNewVersion) + val dynamicDocs: Box[JValue] = getResourceDocsObpDynamicCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, None, isVersion4OrHigher) Future(dynamicDocs.map(successJsonResponse(_))) case Some(STATIC) => - val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, isNewVersion) + val staticDocs: Box[JValue] = getStaticResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, isVersion4OrHigher) Future(staticDocs.map(successJsonResponse(_))) case _ => - val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, isNewVersion) + val docs: Box[JValue] = getAllResourceDocsObpCached(requestedApiVersion, tags, partialFunctions, languageParam, contentParam, cacheModifierParam, isVersion4OrHigher) Future(docs.map(successJsonResponse(_))) } } diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index 95ba25ba2..60e4ec7c3 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -452,7 +452,7 @@ object JSONFactory1_4_0 extends MdcLoggable{ private val createResourceDocJsonMemo = new ConcurrentHashMap[ResourceDoc, ResourceDocJson] - def createResourceDocJson(rd: ResourceDoc, isNewVersion:Boolean) : ResourceDocJson = { + def createResourceDocJson(rd: ResourceDoc, isVersion4OrHigher:Boolean) : ResourceDocJson = { // if this calculate conversion already happened before, just return that value // if not calculated before, just do conversion val endpointTags = getAllEndpointTagsBox(rd.operationId).map(endpointTag =>ResourceDocTag(endpointTag.tagName)) @@ -511,15 +511,15 @@ object JSONFactory1_4_0 extends MdcLoggable{ special_instructions = PegdownOptions.convertPegdownToHtmlTweaked(resourceDocUpdatedTags.specialInstructions.getOrElse("").stripMargin), specified_url = resourceDocUpdatedTags.specifiedUrl.getOrElse(""), connector_methods = resourceDocUpdatedTags.connectorMethods, - created_by_bank_id= if (isNewVersion) rd.createdByBankId else None // only for V400 we show the bankId + created_by_bank_id= if (isVersion4OrHigher) rd.createdByBankId else None // only for V400 we show the bankId ) }) } - def createResourceDocsJson(resourceDocList: List[ResourceDoc], isNewVersion:Boolean) : ResourceDocsJson = { - if(isNewVersion){ + def createResourceDocsJson(resourceDocList: List[ResourceDoc], isVersion4OrHigher:Boolean) : ResourceDocsJson = { + if(isVersion4OrHigher){ ResourceDocsJson( - resourceDocList.map(createResourceDocJson(_,isNewVersion)), + resourceDocList.map(createResourceDocJson(_,isVersion4OrHigher)), meta=Some(ResourceDocMeta(new Date(), resourceDocList.length)) ) } else { From b25ca952c80839d5f2ce9f920a3c49b4a8351eb0 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 18 Aug 2021 00:30:00 +0200 Subject: [PATCH 040/293] feature/OBPv400 added new endpoint getResourceDocsObpV400 - WIP - step5 --- .../ResourceDocs1_4_0/ResourceDocsAPIMethods.scala | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index b72219aff..05bec74ad 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -167,9 +167,13 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth requestedApiVersion match { // only `obp` standard show the `localResouceDocs` - case version: ScannedApiVersion if(version.apiStandard == obp.toString) => activePlusLocalResourceDocs ++= localResourceDocs - // all other standards only show their own apis. - case _ => ; + case version: ScannedApiVersion + if(version.apiStandard == obp.toString && version==ApiVersion.v4_0_0) => + activePlusLocalResourceDocs ++= localResourceDocs.filterNot(_.partialFunctionName == nameOf(getResourceDocsObp)) + case version: ScannedApiVersion + if(version.apiStandard == obp.toString && version!=ApiVersion.v4_0_0) => + activePlusLocalResourceDocs ++= localResourceDocs.filterNot(_.partialFunctionName == nameOf(getResourceDocsObpV400)) + case _ => ; // all other standards only show their own apis. } @@ -484,7 +488,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth nameOf(getResourceDocsObpV400), "GET", "/resource-docs/API_VERSION/obp", - "Get Resource Docs with Meta", + "Get Resource Docs", getResourceDocsDescription(false), emptyObjectJson, exampleResourceDocsJsonV400, From 5924c8208da97e42773190826276a3f4f66487d9 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 18 Aug 2021 12:42:34 +0200 Subject: [PATCH 041/293] feature/added webui_api_documentation_bottom_url and webui_privacy_policy_url --- obp-api/src/main/resources/props/sample.props.template | 5 +++++ obp-api/src/main/scala/code/snippet/WebUI.scala | 7 ++++++- obp-api/src/main/webapp/templates-hidden/default.html | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 9f1937b3c..70c39857e 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -409,6 +409,8 @@ webui_sandbox_introduction= # NOTE: if this is *not set*, the Introduction Button on /index will link the user to /introduction # If this is set, the Introduction Button will link the user to the URL defined above. (but the page /introduction will still exist so you might want to populate webui_sandbox_introduction anyway.) webui_api_documentation_url = https://github.com/OpenBankProject/OBP-API/wiki +# now, we hava a new props for the bottom ` API Documentation` menu. +#webui_api_documentation_bottom_url =https://github.com/OpenBankProject/OBP-API/wiki ################################################################################### # Link for SDKs @@ -469,6 +471,9 @@ webui_override_style_sheet = ## Link to agree to Terms & Conditions, shown on signup page webui_agree_terms_url = +## Link to Privacy Policy, shown in the bottom page +#webui_privacy_policy_url = + # URL to load (additional) vendor support content #webui_vendor_support_content_url = http://127.0.0.1:8080/plain.html diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index 52f5f5477..944bfb9ca 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -201,6 +201,11 @@ class WebUI extends MdcLoggable{ ".termsAndConditions-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_agree_terms_url", "")) } + // Points to the documentation. Probably a sandbox specific link is good. + def privacyPolicyLink: CssSel = { + ".privacy-policy-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_privacy_policy_url", "https://openbankproject.com/privacy-policy")) + } + def sandboxIntroductionLink: CssSel = { val webUiApiDocumentation = getWebUiPropsValue("webui_api_documentation_url",s"${getServerUrl}/introduction") val apiDocumentation = @@ -238,7 +243,7 @@ class WebUI extends MdcLoggable{ } // Points to the documentation. Probably a sandbox specific link is good. def apiDocumentationLink: CssSel = { - ".api-documentation-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_api_documentation_url", "https://github.com/OpenBankProject/OBP-API/wiki")) + ".api-documentation-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_api_documentation_bottom_url", "https://github.com/OpenBankProject/OBP-API/wiki")) } // For example customers and credentials // This relies on the page for sandbox documentation having an anchor called example-customer-logins diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 477e41728..adc78ef08 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -196,7 +196,7 @@ Berlin 13359, Germany Conditions
  • - Privacy Policy + Privacy Policy
  • Twitter From 275d83eef8ef8c83acb9f3511429c08ac61bdcb3 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 18 Aug 2021 12:43:37 +0200 Subject: [PATCH 042/293] docfix/added the webui_api_documentation_bottom_url and webui_privacy_policy_url to release_notes.md --- release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release_notes.md b/release_notes.md index 08559fbc2..98b19b26a 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,8 @@ ### Most recent changes at top of file ``` Date Commit Action +18/08/2021 5924c820 Added props: webui_api_documentation_bottom_url, default is https://github.com/OpenBankProject/OBP-API/wiki + Added props: webui_privacy_policy_url, default is https://openbankproject.com/privacy-policy 30/06/2021 cf2dd987 Changed props, static will cache 24 hours, dynamic only 1 hour as default. dynamicResourceDocsObp.cache.ttl.seconds=3600 staticResourceDocsObp.cache.ttl.seconds=86400 From 83c3b4fa516d74007f48837604976139a28dce08 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 18 Aug 2021 16:21:36 +0200 Subject: [PATCH 043/293] feature/added the props webui_favicon_link_url --- obp-api/src/main/resources/props/sample.props.template | 3 +++ obp-api/src/main/scala/code/snippet/WebUI.scala | 3 +++ obp-api/src/main/webapp/templates-hidden/default.html | 1 + 3 files changed, 7 insertions(+) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 70c39857e..7add90410 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -462,6 +462,9 @@ webui_main_partners=[\ # Prefix for all page titles (note the trailing space!) webui_page_title_prefix = Open Bank Project: +# set the favicon icon +#webui_favicon_link_url =/favicon.ico + # Main style sheet. Add your own if need be. webui_main_style_sheet = /media/css/website.css diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index 944bfb9ca..2a3b018d9 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -326,6 +326,9 @@ class WebUI extends MdcLoggable{ "#main_style_sheet [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_main_style_sheet", "/media/css/website.css")) } + def faviconLink: CssSel = { + "#favicon_link [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_favicon_link_url", "/favicon.ico")) + } def getStartedText: CssSel = { diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index adc78ef08..57103f807 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -37,6 +37,7 @@ Berlin 13359, Germany Open Bank Project: + From cb5d3009105d27ef5c308e4c94c9c0e46ad57e38 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 18 Aug 2021 16:22:49 +0200 Subject: [PATCH 044/293] feature/added the webui_favicon_link_url to release_notes.md --- release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release_notes.md b/release_notes.md index 98b19b26a..0b00bcd2a 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action +18/08/2021 83c3b4fa Added props: webui_favicon_link_url, default is /favicon.ico 18/08/2021 5924c820 Added props: webui_api_documentation_bottom_url, default is https://github.com/OpenBankProject/OBP-API/wiki Added props: webui_privacy_policy_url, default is https://openbankproject.com/privacy-policy 30/06/2021 cf2dd987 Changed props, static will cache 24 hours, dynamic only 1 hour as default. From 346b0e1468ac5860410a1f0ae84d776826894b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 18 Aug 2021 17:13:58 +0200 Subject: [PATCH 045/293] feature/Tweak user invitation error flow --- .../scala/code/snippet/UserInvitation.scala | 13 +- .../main/webapp/user-invitation-error.html | 112 ++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/main/webapp/user-invitation-error.html diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index dcc1fb53c..229a9e40d 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -36,7 +36,7 @@ import code.util.Helper import code.util.Helper.MdcLoggable import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.openbankproject.commons.model.User -import net.liftweb.common.Box +import net.liftweb.common.{Box, Full} import net.liftweb.http.{RequestVar, S, SHtml} import net.liftweb.util.CssSel import net.liftweb.util.Helpers._ @@ -162,6 +162,17 @@ class UserInvitation extends MdcLoggable { } & "#register-consumer-success" #> "" } + userInvitation match { + case Full(payload) if payload.status == "CREATED" => // All good + case _ => + firstNameVar.set("None") + lastNameVar.set("None") + devEmailVar.set("None") + companyVar.set("None") + countryVar.set("None") + usernameVar.set("None") + S.error("Cannot complete your user invitation. Please check the invitation link. Your invitation could be invalid or completed.") + } register } diff --git a/obp-api/src/main/webapp/user-invitation-error.html b/obp-api/src/main/webapp/user-invitation-error.html new file mode 100644 index 000000000..6ed82331c --- /dev/null +++ b/obp-api/src/main/webapp/user-invitation-error.html @@ -0,0 +1,112 @@ + +
    +
    + +
    +
    +

    Complete your user invitation

    +

    Please complete the information about the user invitation application below.

    +

    All fields are required unless marked as 'optional'

    +
    + +
    + +
    +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + + +
    +
    + + +
    +
    + + + + +
    +
    +
    + + + + +
    + +
    +
    +
    +
    +
    + + From 2fe077a4e5ffbab096753007b342ad187fc0f7ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 19 Aug 2021 11:24:20 +0200 Subject: [PATCH 046/293] feature/Tweak user invitation error messages --- .../main/resources/i18n/lift-core.properties | 4 +- .../scala/code/snippet/UserInvitation.scala | 5 +- .../main/webapp/user-invitation-error.html | 112 ------------------ obp-api/src/main/webapp/user-invitation.html | 16 +-- 4 files changed, 14 insertions(+), 123 deletions(-) delete mode 100644 obp-api/src/main/webapp/user-invitation-error.html diff --git a/obp-api/src/main/resources/i18n/lift-core.properties b/obp-api/src/main/resources/i18n/lift-core.properties index f8a735d9e..35b1aa61d 100644 --- a/obp-api/src/main/resources/i18n/lift-core.properties +++ b/obp-api/src/main/resources/i18n/lift-core.properties @@ -372,4 +372,6 @@ invalid.username=Invalid Username: \ 2) Usernames MUST be between 8 and 100 characters long \ 3) Usernames MUST NOT start with _ or . \ 4) Usernames MUST NOT contain __ or ._ or ._ or .. \ -5) Usernames MUST NOT end with _ or . \ No newline at end of file +5) Usernames MUST NOT end with _ or . + +your.username.is.not.unique = Your username is not unique. Please enter a different one. \ No newline at end of file diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 229a9e40d..27f34b5b8 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -74,7 +74,8 @@ class UserInvitation extends MdcLoggable { devEmailVar.set(email) companyVar.set(userInvitation.map(_.company).getOrElse("None")) countryVar.set(userInvitation.map(_.country).getOrElse("None")) - usernameVar.set(firstNameVar.is.toLowerCase + "." + lastNameVar.is.toLowerCase()) + // Propose the username only for the first time. In case an end user manually change it we must not override it. + if(usernameVar.isEmpty) usernameVar.set(firstNameVar.is.toLowerCase + "." + lastNameVar.is.toLowerCase()) def submitButtonDefense(): Unit = { val verifyingTime = ZonedDateTime.now(ZoneOffset.UTC) @@ -130,7 +131,7 @@ class UserInvitation extends MdcLoggable { showError(Helper.i18n("your.secret.link.is.not.valid")) } def showErrorsForUsername() = { - showError(Helper.i18n("unique.username")) + showError(Helper.i18n("your.username.is.not.unique")) } def showErrorsForStatus() = { showError(Helper.i18n("user.invitation.is.already.finished")) diff --git a/obp-api/src/main/webapp/user-invitation-error.html b/obp-api/src/main/webapp/user-invitation-error.html deleted file mode 100644 index 6ed82331c..000000000 --- a/obp-api/src/main/webapp/user-invitation-error.html +++ /dev/null @@ -1,112 +0,0 @@ - -
    -
    - -
    -
    -

    Complete your user invitation

    -

    Please complete the information about the user invitation application below.

    -

    All fields are required unless marked as 'optional'

    -
    - -
    - -
    -
    - -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - - - -
    -
    - - -
    -
    - - - - -
    -
    -
    - - - - -
    - -
    -
    -
    -
    -
    - - diff --git a/obp-api/src/main/webapp/user-invitation.html b/obp-api/src/main/webapp/user-invitation.html index 6ed82331c..dcc2fccb8 100644 --- a/obp-api/src/main/webapp/user-invitation.html +++ b/obp-api/src/main/webapp/user-invitation.html @@ -68,7 +68,7 @@ Berlin 13359, Germany -
    +
    @@ -78,7 +78,7 @@ Berlin 13359, Germany
    -
    +
    @@ -87,8 +87,13 @@ Berlin 13359, Germany
    + +
    + +
    + - - -
    - -
    From 298af62dbd6b6b760934c922809d8ea0ae38b806 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 19 Aug 2021 15:18:26 +0200 Subject: [PATCH 047/293] bugfix/removed isSandboxMode method --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 7 +------ obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala | 2 +- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 6 ++++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 0363008ec..3e7d2c07b 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2659,8 +2659,6 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ for { (user, callContext) <- OAuth2Login.getUserFuture(cc) } yield { - if (!APIUtil.isSandboxMode && user.isDefined) - AuthUser.updateUserAccountViewsFuture(user.openOrThrowException("Can not be empty here"), callContext) (user, callContext) } } // Direct Login i.e DirectLogin: token=eyJhbGciOiJIUzI1NiJ9.eyIiOiIifQ.Y0jk1EQGB4XgdqmYZUHT6potmH3mKj5mEaA9qrIXXWQ @@ -2838,7 +2836,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ * Better also check the logic for needToRefreshUser method. */ def refreshUserIfRequired(user: Box[User], callContext: Option[CallContext]) = { - if(!APIUtil.isSandboxMode && user.isDefined && UserRefreshes.UserRefreshes.vend.needToRefreshUser(user.head.userId)) + if(user.isDefined && UserRefreshes.UserRefreshes.vend.needToRefreshUser(user.head.userId)) user.map(AuthUser.updateUserAccountViewsFuture(_, callContext)) else None @@ -3053,9 +3051,6 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ otherAccountRoutingAddress: String )= createOBPId(s"$thisBankId$thisAccountId$counterpartyName$otherAccountRoutingScheme$otherAccountRoutingAddress") - //TODO, now we have the star connector, it will break the isSandboxMode method logic. Need to double check how to use this method now. - val isSandboxMode: Boolean = (APIUtil.getPropsValue("connector").openOrThrowException(attemptedToOpenAnEmptyBox).toString).equalsIgnoreCase("mapped") - def isDataFromOBPSide (methodName: String, argNameToValue: Array[(String, AnyRef)] = Array.empty): Boolean = { val connectorNameInProps = APIUtil.getPropsValue("connector").openOrThrowException(attemptedToOpenAnEmptyBox) //if the connector == mapped, then the data is always over obp database diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 1c4a10121..c1bc9b69e 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1973,7 +1973,7 @@ trait APIMethods310 { _ <- NewStyle.function.hasEntitlement("", userId, canRefreshUser, callContext) startTime <- Future{Helpers.now} _ <- NewStyle.function.findByUserId(userId, callContext) - _ <- if (APIUtil.isSandboxMode) Future{} else AuthUser.updateUserAccountViewsFuture(u, callContext) + _ <- Future{refreshUserIfRequired(Full(u), callContext)} endTime <- Future{Helpers.now} durationTime = endTime.getTime - startTime.getTime } yield { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index a4e195180..f00ad47d2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -1105,8 +1105,10 @@ trait APIMethods400 { } } } yield { - //TODO, remove this `isSandboxMode` logic, the challenges should come from other places. - val challenges : List[ChallengeJson] = if(APIUtil.isSandboxMode){ + //TODO, remove this `connector` guard logic, the challenges should come from other places. + // The OBP mapped V400 payment.challenges are not done yet, the we should use `createChallengesC2` instead of `createChallenges` in createTransactionRequestv400 method, + // and get the challenges from connector level, not prepare them here. + val challenges : List[ChallengeJson] = if(APIUtil.getPropsValue("connector").openOrThrowException(attemptedToOpenAnEmptyBox).toString.equalsIgnoreCase("mapped")){ MappedExpectedChallengeAnswer .findAll(By(MappedExpectedChallengeAnswer.mTransactionRequestId, createdTransactionRequest.id.value)) .map(mappedExpectedChallengeAnswer => From 2ad1a3b0e6697ec5039afb1f9746785790a2a403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 20 Aug 2021 12:10:03 +0200 Subject: [PATCH 048/293] feature/Update Akka, Rest and Stored Procedure connector's implementations via the builder --- .../scala/code/api/util/ExampleValue.scala | 141 +- .../akka/AkkaConnector_vDec2018.scala | 3539 +++--- .../rest/RestConnector_vMar2019.scala | 9576 ++++++----------- .../StoredProcedureConnector_vDec2019.scala | 124 +- .../RestConnector_vMar2019_frozen_meta_data | Bin 96114 -> 112092 bytes 5 files changed, 5777 insertions(+), 7603 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 45a5212a0..fe70fd0a5 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -23,6 +23,7 @@ object ExampleValue { val NoDescriptionProvided = "no-description-provided" val NoExampleProvided = "no-example-provided" + val booleanTrue = "true" lazy val bankIdGlossary = glossaryItems.find(_.title == "Bank.bank_id").map(_.textDescription) @@ -91,7 +92,7 @@ object ExampleValue { lazy val dependentsExample = ConnectorField("1", s"the number of dependents") glossaryItems += makeGlossaryItem("Customer.dependents", dependentsExample) - lazy val kycStatusExample = ConnectorField("true", s"This is boolean to indicate if the cusomter's KYC has been checked.") + lazy val kycStatusExample = ConnectorField(booleanTrue, s"This is boolean to indicate if the cusomter's KYC has been checked.") glossaryItems += makeGlossaryItem("Customer.kycStatus", kycStatusExample) lazy val urlExample = ConnectorField("http://www.example.com/id-docs/123/image.png", s"The URL ") @@ -144,7 +145,7 @@ object ExampleValue { lazy val otherAccountProviderExample = ConnectorField("", s"")//TODO, not sure what is this field for? glossaryItems += makeGlossaryItem("Transaction.otherAccountProvider", otherAccountProviderExample) - lazy val isBeneficiaryExample = ConnectorField("true", s"This is a boolean. True if the originAccount can send money to the Counterparty") + lazy val isBeneficiaryExample = ConnectorField(booleanTrue, s"This is a boolean. True if the originAccount can send money to the Counterparty") glossaryItems += makeGlossaryItem("Counterparty.isBeneficiary", isBeneficiaryExample) lazy val counterpartyNameExample = ConnectorField("John Smith Ltd.", s"The name of a Counterparty. Ideally unique for an Account") @@ -464,7 +465,7 @@ object ExampleValue { lazy val inboundAvroSchemaExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("DynamicMessageDoc.inboundAvroSchema", inboundAvroSchemaExample) - lazy val canSeeImagesExample = ConnectorField("true",NoDescriptionProvided) + lazy val canSeeImagesExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_images", canSeeImagesExample) lazy val topConsumersExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -473,10 +474,10 @@ object ExampleValue { lazy val smsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("sms", smsExample) - lazy val maximumResponseTimeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val maximumResponseTimeExample = ConnectorField("60",NoDescriptionProvided) glossaryItems += makeGlossaryItem("maximum_response_time", maximumResponseTimeExample) - lazy val cancelledExample = ConnectorField("true",NoDescriptionProvided) + lazy val cancelledExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("cancelled", cancelledExample) lazy val entitlementRequestsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -509,7 +510,7 @@ object ExampleValue { lazy val canAddCommentExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_add_comment", canAddCommentExample) - lazy val frequencyExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val frequencyExample = ConnectorField("5",NoDescriptionProvided) glossaryItems += makeGlossaryItem("frequency", frequencyExample) lazy val ordersExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -524,13 +525,13 @@ object ExampleValue { lazy val canSeeOtherAccountRoutingSchemeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_other_account_routing_scheme", canSeeOtherAccountRoutingSchemeExample) - lazy val canDeleteCorporateLocationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canDeleteCorporateLocationExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_delete_corporate_location", canDeleteCorporateLocationExample) lazy val fromExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("from", fromExample) - lazy val httpMethodExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val httpMethodExample = ConnectorField("GET",NoDescriptionProvided) glossaryItems += makeGlossaryItem("http_method", httpMethodExample) lazy val developerEmailExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -548,7 +549,7 @@ object ExampleValue { lazy val portsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("ports", portsExample) - lazy val perSecondExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val perSecondExample = ConnectorField("1000",NoDescriptionProvided) glossaryItems += makeGlossaryItem("per_second", perSecondExample) lazy val challengeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -557,7 +558,7 @@ object ExampleValue { lazy val appNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("app_name", appNameExample) - lazy val executionDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val executionDateExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("execution_date", executionDateExample) lazy val technologyExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -593,13 +594,13 @@ object ExampleValue { lazy val sandboxTanExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("sandbox_tan", sandboxTanExample) - lazy val corporateLocationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val corporateLocationExample = ConnectorField("10",NoDescriptionProvided) glossaryItems += makeGlossaryItem("corporate_location", corporateLocationExample) - lazy val enabledExample = ConnectorField("true",NoDescriptionProvided) + lazy val enabledExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("enabled", enabledExample) - lazy val durationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val durationExample = ConnectorField("10",NoDescriptionProvided) glossaryItems += makeGlossaryItem("duration", durationExample) lazy val canSeeBankAccountTypeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -617,10 +618,10 @@ object ExampleValue { lazy val accountAttributeIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("account_attribute_id", accountAttributeIdExample) - lazy val closingTimeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val closingTimeExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("closing_time", closingTimeExample) - lazy val lastFailureDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val lastFailureDateExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("last_failure_date", lastFailureDateExample) lazy val whereExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -671,7 +672,7 @@ object ExampleValue { lazy val creatorExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("creator", creatorExample) - lazy val activeExample = ConnectorField("true",NoDescriptionProvided) + lazy val activeExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("active", activeExample) lazy val canSeeOtherAccountMetadataExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -857,7 +858,7 @@ object ExampleValue { lazy val canSeeTransactionFinishDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_transaction_finish_date", canSeeTransactionFinishDateExample) - lazy val satisfiedExample = ConnectorField("true",NoDescriptionProvided) + lazy val satisfiedExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("satisfied", satisfiedExample) lazy val canSeeOtherAccountIbanExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1421,7 +1422,7 @@ object ExampleValue { lazy val isFirehoseExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("is_firehose", isFirehoseExample) - lazy val okExample = ConnectorField("true",NoDescriptionProvided) + lazy val okExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("ok", okExample) lazy val bankRoutingExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1445,7 +1446,7 @@ object ExampleValue { lazy val dependentEndpointsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("dependent_endpoints", dependentEndpointsExample) - lazy val hasDepositCapabilityExample = ConnectorField("true",NoDescriptionProvided) + lazy val hasDepositCapabilityExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("ATM.has_deposit_capability", hasDepositCapabilityExample) lazy val toCounterpartyExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1469,10 +1470,10 @@ object ExampleValue { lazy val canSeeCommentsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_comments", canSeeCommentsExample) - lazy val canEditOwnerCommentExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canEditOwnerCommentExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_edit_owner_comment", canEditOwnerCommentExample) - lazy val canAddCounterpartyExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canAddCounterpartyExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_add_counterparty", canAddCounterpartyExample) lazy val markdownExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1499,19 +1500,19 @@ object ExampleValue { lazy val accountRoutingExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("account_routing", accountRoutingExample) - lazy val requestedCurrentRateAmount2Example = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val requestedCurrentRateAmount2Example = ConnectorField("20",NoDescriptionProvided) glossaryItems += makeGlossaryItem("requested_current_rate_amount2", requestedCurrentRateAmount2Example) lazy val narrativeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("narrative", narrativeExample) - lazy val canSeeOtherAccountRoutingAddressExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeOtherAccountRoutingAddressExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_other_account_routing_address", canSeeOtherAccountRoutingAddressExample) lazy val statusesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("statuses", statusesExample) - lazy val callsMadeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val callsMadeExample = ConnectorField("50",NoDescriptionProvided) glossaryItems += makeGlossaryItem("calls_made", callsMadeExample) lazy val currentStateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1523,10 +1524,10 @@ object ExampleValue { lazy val customersExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("customers", customersExample) - lazy val scheduledDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val scheduledDateExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("scheduled_date", scheduledDateExample) - lazy val allowedAttemptsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val allowedAttemptsExample = ConnectorField("5",NoDescriptionProvided) glossaryItems += makeGlossaryItem("allowed_attempts", allowedAttemptsExample) lazy val hostedByExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1544,7 +1545,7 @@ object ExampleValue { lazy val tuesdayExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("tuesday", tuesdayExample) - lazy val canQueryAvailableFundsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canQueryAvailableFundsExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_query_available_funds", canQueryAvailableFundsExample) lazy val otherAccountSecondaryRoutingSchemeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1583,7 +1584,7 @@ object ExampleValue { lazy val cardNumberExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("card_number", cardNumberExample) - lazy val instructedamountExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val instructedamountExample = ConnectorField("100",NoDescriptionProvided) glossaryItems += makeGlossaryItem("instructedamount", instructedamountExample) lazy val userCustomerLinkIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1592,7 +1593,7 @@ object ExampleValue { lazy val outboundTopicExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("outbound_topic", outboundTopicExample) - lazy val postCodeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val postCodeExample = ConnectorField("789",NoDescriptionProvided) glossaryItems += makeGlossaryItem("post_code", postCodeExample) lazy val superFamilyExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1616,7 +1617,7 @@ object ExampleValue { lazy val roleExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("role", roleExample) - lazy val requireScopesForListedRolesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val requireScopesForListedRolesExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("require_scopes_for_listed_roles", requireScopesForListedRolesExample) lazy val branchTypeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1625,10 +1626,10 @@ object ExampleValue { lazy val fullNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("full_name", fullNameExample) - lazy val canCreateDirectDebitExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canCreateDirectDebitExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_create_direct_debit", canCreateDirectDebitExample) - lazy val futureDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val futureDateExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("future_date", futureDateExample) lazy val toTransferToAccountExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1643,7 +1644,7 @@ object ExampleValue { lazy val documentNumberExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("document_number", documentNumberExample) - lazy val canSeeOtherAccountNationalIdentifierExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeOtherAccountNationalIdentifierExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_other_account_national_identifier", canSeeOtherAccountNationalIdentifierExample) lazy val canSeeTransactionStartDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1655,7 +1656,7 @@ object ExampleValue { lazy val cacheExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("cache", cacheExample) - lazy val canSeeBankRoutingAddressExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeBankRoutingAddressExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_bank_routing_address", canSeeBankRoutingAddressExample) lazy val usersExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1667,7 +1668,7 @@ object ExampleValue { lazy val ktyExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("kty", ktyExample) - lazy val canBeSeenOnViewsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canBeSeenOnViewsExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_be_seen_on_views", canBeSeenOnViewsExample) lazy val fromPersonExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1679,7 +1680,7 @@ object ExampleValue { lazy val createdByUserExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("created_by_user", createdByUserExample) - lazy val taxNumberExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val taxNumberExample = ConnectorField("456",NoDescriptionProvided) glossaryItems += makeGlossaryItem("tax_number", taxNumberExample) lazy val presentExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1688,7 +1689,7 @@ object ExampleValue { lazy val metadataExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("metadata", metadataExample) - lazy val canSeeTransactionAmountExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeTransactionAmountExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_transaction_amount", canSeeTransactionAmountExample) lazy val methodRoutingIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1706,16 +1707,16 @@ object ExampleValue { lazy val bespokeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("bespoke", bespokeExample) - lazy val codeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val codeExample = ConnectorField("125",NoDescriptionProvided) glossaryItems += makeGlossaryItem("code", codeExample) - lazy val countryCodeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val countryCodeExample = ConnectorField("1254",NoDescriptionProvided) glossaryItems += makeGlossaryItem("country_code", countryCodeExample) - lazy val canSeeBankAccountCreditLimitExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeBankAccountCreditLimitExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_bank_account_credit_limit", canSeeBankAccountCreditLimitExample) - lazy val canSeeOtherAccountNumberExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeOtherAccountNumberExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_other_account_number", canSeeOtherAccountNumberExample) lazy val orderExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1733,10 +1734,10 @@ object ExampleValue { lazy val taxResidenceExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("tax_residence", taxResidenceExample) - lazy val isActiveExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val isActiveExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("is_active", isActiveExample) - lazy val canSeeBankAccountBankNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeBankAccountBankNameExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_bank_account_bank_name", canSeeBankAccountBankNameExample) lazy val firstNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1751,19 +1752,19 @@ object ExampleValue { lazy val transactionIdsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("transaction_ids", transactionIdsExample) - lazy val canSeeBankAccountOwnersExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeBankAccountOwnersExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_bank_account_owners", canSeeBankAccountOwnersExample) - lazy val actualDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val actualDateExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("actual_date", actualDateExample) lazy val exampleOutboundMessageExample = ConnectorField("{}","this will the json object") glossaryItems += makeGlossaryItem("example_outbound_message", exampleOutboundMessageExample) - lazy val canDeleteWhereTagExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canDeleteWhereTagExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_delete_where_tag", canDeleteWhereTagExample) - lazy val canSeeUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeUrlExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_url", canSeeUrlExample) lazy val versionExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1778,10 +1779,10 @@ object ExampleValue { lazy val allowedActionsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("allowed_actions", allowedActionsExample) - lazy val rankAmount1Example = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val rankAmount1Example = ConnectorField("100",NoDescriptionProvided) glossaryItems += makeGlossaryItem("rank_amount1", rankAmount1Example) - lazy val durationTimeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val durationTimeExample = ConnectorField("60",NoDescriptionProvided) glossaryItems += makeGlossaryItem("duration_time", durationTimeExample) lazy val noneExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1790,13 +1791,13 @@ object ExampleValue { lazy val implementedInVersionExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("implemented_in_version", implementedInVersionExample) - lazy val canSeeImageUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeImageUrlExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_image_url", canSeeImageUrlExample) lazy val toTransferToPhoneExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("to_transfer_to_phone", toTransferToPhoneExample) - lazy val perDayExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val perDayExample = ConnectorField("4000",NoDescriptionProvided) glossaryItems += makeGlossaryItem("per_day", perDayExample) lazy val elasticSearchExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1805,7 +1806,7 @@ object ExampleValue { lazy val reasonRequestedExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("reason_requested", reasonRequestedExample) - lazy val perWeekExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val perWeekExample = ConnectorField("50000",NoDescriptionProvided) glossaryItems += makeGlossaryItem("per_week", perWeekExample) lazy val productsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1823,7 +1824,7 @@ object ExampleValue { lazy val apiVersionExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("api_version", apiVersionExample) - lazy val perSecondCallLimitExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val perSecondCallLimitExample = ConnectorField("10",NoDescriptionProvided) glossaryItems += makeGlossaryItem("per_second_call_limit", perSecondCallLimitExample) lazy val messagesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1835,19 +1836,19 @@ object ExampleValue { lazy val eExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("e", eExample) - lazy val canSeeCorporateLocationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeCorporateLocationExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_corporate_location", canSeeCorporateLocationExample) lazy val userExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("user", userExample) - lazy val lastLockDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val lastLockDateExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("last_lock_date", lastLockDateExample) lazy val requestedCurrentRateAmount1Example = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("requested_current_rate_amount1", requestedCurrentRateAmount1Example) - lazy val toCurrencyCodeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val toCurrencyCodeExample = ConnectorField("EUR",NoDescriptionProvided) glossaryItems += makeGlossaryItem("to_currency_code", toCurrencyCodeExample) lazy val dobOfDependantsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1880,10 +1881,10 @@ object ExampleValue { lazy val mondayExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("monday", mondayExample) - lazy val requiredfieldinfoExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val requiredfieldinfoExample = ConnectorField("false",NoDescriptionProvided) glossaryItems += makeGlossaryItem("requiredfieldinfo", requiredfieldinfoExample) - lazy val canSeeWhereTagExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeWhereTagExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_where_tag", canSeeWhereTagExample) lazy val fromDepartmentExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1895,7 +1896,7 @@ object ExampleValue { lazy val otherAccountSecondaryRoutingAddressExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("other_account_secondary_routing_address", otherAccountSecondaryRoutingAddressExample) - lazy val perMonthExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val perMonthExample = ConnectorField("500",NoDescriptionProvided) glossaryItems += makeGlossaryItem("per_month", perMonthExample) lazy val inboundTopicExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1952,10 +1953,10 @@ object ExampleValue { lazy val toSandboxTanExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("to_sandbox_tan", toSandboxTanExample) - lazy val canAddTagExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canAddTagExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_add_tag", canAddTagExample) - lazy val canSeeBankAccountLabelExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeBankAccountLabelExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_bank_account_label", canSeeBankAccountLabelExample) lazy val serviceAvailableExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1979,7 +1980,7 @@ object ExampleValue { lazy val driveUpExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("drive_up", driveUpExample) - lazy val canAddMoreInfoExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canAddMoreInfoExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_add_more_info", canAddMoreInfoExample) lazy val detailExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -1991,13 +1992,13 @@ object ExampleValue { lazy val transactionRequestTypesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("transaction_request_types", transactionRequestTypesExample) - lazy val canAddImageUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canAddImageUrlExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_add_image_url", canAddImageUrlExample) lazy val jwksUrisExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("jwks_uris", jwksUrisExample) - lazy val canSeeOtherAccountSwiftBicExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeOtherAccountSwiftBicExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_other_account_swift_bic", canSeeOtherAccountSwiftBicExample) lazy val staffUserIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -2009,7 +2010,7 @@ object ExampleValue { lazy val validFromExample = ConnectorField("2020-01-27",NoDescriptionProvided) glossaryItems += makeGlossaryItem("valid_from", validFromExample) - lazy val canDeleteImageExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canDeleteImageExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_delete_image", canDeleteImageExample) lazy val toExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) @@ -2021,25 +2022,25 @@ object ExampleValue { lazy val productAttributesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("product_attributes", productAttributesExample) - lazy val canSeeTransactionDescriptionExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeTransactionDescriptionExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_transaction_description", canSeeTransactionDescriptionExample) lazy val faceImageExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("face_image", faceImageExample) - lazy val canSeeBankAccountNumberExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val canSeeBankAccountNumberExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_see_bank_account_number", canSeeBankAccountNumberExample) lazy val glossaryItemsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("glossary_items", glossaryItemsExample) - lazy val isBankIdExactMatchExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val isBankIdExactMatchExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("is_bank_id_exact_match", isBankIdExactMatchExample) - lazy val isPublicExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val isPublicExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("is_public", isPublicExample) - lazy val isAccessibleExample = ConnectorField("true",NoDescriptionProvided) + lazy val isAccessibleExample = ConnectorField(booleanTrue,NoDescriptionProvided) glossaryItems += makeGlossaryItem("ATM.is_accessible", isAccessibleExample) lazy val entitlementIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) diff --git a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala index e23b60335..d61643811 100644 --- a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala +++ b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala @@ -15,7 +15,8 @@ import code.bankconnectors.akka.actor.{AkkaConnectorActorInit, AkkaConnectorHelp import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.dto._ import com.openbankproject.commons.model._ -import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, CustomerAttributeType, ProductAttributeType, StrongCustomerAuthentication, TransactionAttributeType, TransactionRequestStatus} +import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus +import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, ChallengeType, CustomerAttributeType, ProductAttributeType, StrongCustomerAuthentication, TransactionAttributeType, TransactionRequestStatus} import com.sksamuel.avro4s.SchemaFor import net.liftweb.common.{Box, Full} import net.liftweb.json.parse @@ -306,8 +307,48 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2020-06-17T14:19:04Z +// ---------- created on 2021-08-19T16:36:57Z + messageDocs += validateAndCheckIbanNumberDoc + def validateAndCheckIbanNumberDoc = MessageDoc( + process = "obp.validateAndCheckIbanNumber", + messageFormat = messageFormat, + description = "Validate And Check Iban Number", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateAndCheckIbanNumber(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + iban=ibanExample.value) + ), + exampleInboundMessage = ( + InBoundValidateAndCheckIbanNumber(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= IbanChecker(isValid=true, + details=Some( IbanDetails(bic=bicExample.value, + bank=bankExample.value, + branch="string", + address=addressExample.value, + city=cityExample.value, + zip="string", + phone=phoneExample.value, + country="string", + countryIso="string", + sepaCreditTransfer=sepaCreditTransferExample.value, + sepaDirectDebit=sepaDirectDebitExample.value, + sepaSddCore=sepaSddCoreExample.value, + sepaB2b=sepaB2bExample.value, + sepaCardClearing=sepaCardClearingExample.value)))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def validateAndCheckIbanNumber(iban: String, callContext: Option[CallContext]): OBPReturnType[Box[IbanChecker]] = { + import com.openbankproject.commons.dto.{InBoundValidateAndCheckIbanNumber => InBound, OutBoundValidateAndCheckIbanNumber => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[IbanChecker](callContext)) + } + messageDocs += getChallengeThresholdDoc def getChallengeThresholdDoc = MessageDoc( process = "obp.getChallengeThreshold", @@ -323,19 +364,19 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { transactionRequestType=transactionRequestTypeExample.value, currency=currencyExample.value, userId=userIdExample.value, - username="string") + username=usernameExample.value) ), exampleInboundMessage = ( InBoundGetChallengeThreshold(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= AmountOfMoney(currency=currencyExample.value, - amount="string")) + amount=amountExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getChallengeThreshold(bankId: String, accountId: String, viewId: String, transactionRequestType: String, currency: String, userId: String, username: String, callContext: Option[CallContext]): OBPReturnType[Box[AmountOfMoney]] = { - import com.openbankproject.commons.dto.{OutBoundGetChallengeThreshold => OutBound, InBoundGetChallengeThreshold => InBound} + import com.openbankproject.commons.dto.{InBoundGetChallengeThreshold => InBound, OutBoundGetChallengeThreshold => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, viewId, transactionRequestType, currency, userId, username) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AmountOfMoney](callContext)) @@ -354,7 +395,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { accountId=AccountId(accountIdExample.value), viewId=ViewId(viewIdExample.value), userId=userIdExample.value, - username="string", + username=usernameExample.value, transactionRequestType=transactionRequestTypeExample.value, currency=currencyExample.value) ), @@ -362,18 +403,57 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { InBoundGetChargeLevel(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= AmountOfMoney(currency=currencyExample.value, - amount="string")) + amount=amountExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getChargeLevel(bankId: BankId, accountId: AccountId, viewId: ViewId, userId: String, username: String, transactionRequestType: String, currency: String, callContext: Option[CallContext]): OBPReturnType[Box[AmountOfMoney]] = { - import com.openbankproject.commons.dto.{OutBoundGetChargeLevel => OutBound, InBoundGetChargeLevel => InBound} + import com.openbankproject.commons.dto.{InBoundGetChargeLevel => InBound, OutBoundGetChargeLevel => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, viewId, userId, username, transactionRequestType, currency) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AmountOfMoney](callContext)) } + messageDocs += getChargeLevelC2Doc + def getChargeLevelC2Doc = MessageDoc( + process = "obp.getChargeLevelC2", + messageFormat = messageFormat, + description = "Get Charge Level C2", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChargeLevelC2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + viewId=ViewId(viewIdExample.value), + userId=userIdExample.value, + username=usernameExample.value, + transactionRequestType=transactionRequestTypeExample.value, + currency=currencyExample.value, + amount=amountExample.value, + toAccountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + customAttributes=List( CustomAttribute(name=nameExample.value, + attributeType=com.openbankproject.commons.model.enums.AttributeType.example, + value=valueExample.value))) + ), + exampleInboundMessage = ( + InBoundGetChargeLevelC2(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChargeLevelC2(bankId: BankId, accountId: AccountId, viewId: ViewId, userId: String, username: String, transactionRequestType: String, currency: String, amount: String, toAccountRoutings: List[AccountRouting], customAttributes: List[CustomAttribute], callContext: Option[CallContext]): OBPReturnType[Box[AmountOfMoney]] = { + import com.openbankproject.commons.dto.{InBoundGetChargeLevelC2 => InBound, OutBoundGetChargeLevelC2 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, viewId, userId, username, transactionRequestType, currency, amount, toAccountRoutings, customAttributes) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[AmountOfMoney](callContext)) + } + messageDocs += createChallengeDoc def createChallengeDoc = MessageDoc( process = "obp.createChallenge", @@ -387,7 +467,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { accountId=AccountId(accountIdExample.value), userId=userIdExample.value, transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - transactionRequestId="string", + transactionRequestId=transactionRequestIdExample.value, scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS)) ), exampleInboundMessage = ( @@ -399,7 +479,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createChallenge(bankId: BankId, accountId: AccountId, userId: String, transactionRequestType: TransactionRequestType, transactionRequestId: String, scaMethod: Option[StrongCustomerAuthentication.SCA], callContext: Option[CallContext]): OBPReturnType[Box[String]] = { - import com.openbankproject.commons.dto.{OutBoundCreateChallenge => OutBound, InBoundCreateChallenge => InBound} + import com.openbankproject.commons.dto.{InBoundCreateChallenge => InBound, OutBoundCreateChallenge => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, userId, transactionRequestType, transactionRequestId, scaMethod) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[String](callContext)) @@ -416,26 +496,68 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateChallenges(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - userIds=List(userIdExample.value), + userIds=listExample.value.split("[,;]").toList, transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - transactionRequestId="string", + transactionRequestId=transactionRequestIdExample.value, scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS)) ), exampleInboundMessage = ( InBoundCreateChallenges(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List("string")) + data=listExample.value.split("[,;]").toList) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createChallenges(bankId: BankId, accountId: AccountId, userIds: List[String], transactionRequestType: TransactionRequestType, transactionRequestId: String, scaMethod: Option[StrongCustomerAuthentication.SCA], callContext: Option[CallContext]): OBPReturnType[Box[List[String]]] = { - import com.openbankproject.commons.dto.{OutBoundCreateChallenges => OutBound, InBoundCreateChallenges => InBound} + import com.openbankproject.commons.dto.{InBoundCreateChallenges => InBound, OutBoundCreateChallenges => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, userIds, transactionRequestType, transactionRequestId, scaMethod) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[String]](callContext)) } + messageDocs += createChallengesC2Doc + def createChallengesC2Doc = MessageDoc( + process = "obp.createChallengesC2", + messageFormat = messageFormat, + description = "Create Challenges C2", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateChallengesC2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + userIds=listExample.value.split("[,;]").toList, + challengeType=com.openbankproject.commons.model.enums.ChallengeType.example, + transactionRequestId=Some(transactionRequestIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + consentId=Some(consentIdExample.value), + authenticationMethodId=Some("string")) + ), + exampleInboundMessage = ( + InBoundCreateChallengesC2(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string")))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createChallengesC2(userIds: List[String], challengeType: ChallengeType.Value, transactionRequestId: Option[String], scaMethod: Option[StrongCustomerAuthentication.SCA], scaStatus: Option[SCAStatus], consentId: Option[String], authenticationMethodId: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundCreateChallengesC2 => InBound, OutBoundCreateChallengesC2 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userIds, challengeType, transactionRequestId, scaMethod, scaStatus, consentId, authenticationMethodId) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + messageDocs += validateChallengeAnswerDoc def validateChallengeAnswerDoc = MessageDoc( process = "obp.validateChallengeAnswer", @@ -445,8 +567,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundValidateChallengeAnswer(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - challengeId="string", - hashOfSuppliedAnswer="string") + challengeId=challengeIdExample.value, + hashOfSuppliedAnswer=hashOfSuppliedAnswerExample.value) ), exampleInboundMessage = ( InBoundValidateChallengeAnswer(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -457,12 +579,159 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def validateChallengeAnswer(challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundValidateChallengeAnswer => OutBound, InBoundValidateChallengeAnswer => InBound} + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswer => InBound, OutBoundValidateChallengeAnswer => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, challengeId, hashOfSuppliedAnswer) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) } + messageDocs += validateChallengeAnswerC2Doc + def validateChallengeAnswerC2Doc = MessageDoc( + process = "obp.validateChallengeAnswerC2", + messageFormat = messageFormat, + description = "Validate Challenge Answer C2", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateChallengeAnswerC2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=Some(transactionRequestIdExample.value), + consentId=Some(consentIdExample.value), + challengeId=challengeIdExample.value, + hashOfSuppliedAnswer=hashOfSuppliedAnswerExample.value) + ), + exampleInboundMessage = ( + InBoundValidateChallengeAnswerC2(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string"))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def validateChallengeAnswerC2(transactionRequestId: Option[String], consentId: Option[String], challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswerC2 => InBound, OutBoundValidateChallengeAnswerC2 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId, consentId, challengeId, hashOfSuppliedAnswer) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + + messageDocs += getChallengesByTransactionRequestIdDoc + def getChallengesByTransactionRequestIdDoc = MessageDoc( + process = "obp.getChallengesByTransactionRequestId", + messageFormat = messageFormat, + description = "Get Challenges By Transaction Request Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallengesByTransactionRequestId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=transactionRequestIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallengesByTransactionRequestId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string")))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallengesByTransactionRequestId(transactionRequestId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundGetChallengesByTransactionRequestId => InBound, OutBoundGetChallengesByTransactionRequestId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + + messageDocs += getChallengesByConsentIdDoc + def getChallengesByConsentIdDoc = MessageDoc( + process = "obp.getChallengesByConsentId", + messageFormat = messageFormat, + description = "Get Challenges By Consent Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallengesByConsentId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + consentId=consentIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallengesByConsentId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string")))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallengesByConsentId(consentId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundGetChallengesByConsentId => InBound, OutBoundGetChallengesByConsentId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, consentId) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + + messageDocs += getChallengeDoc + def getChallengeDoc = MessageDoc( + process = "obp.getChallenge", + messageFormat = messageFormat, + description = "Get Challenge", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallenge(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + challengeId=challengeIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallenge(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string"))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallenge(challengeId: String, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundGetChallenge => InBound, OutBoundGetChallenge => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, challengeId) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + messageDocs += getUserDoc def getUserDoc = MessageDoc( process = "obp.getUser", @@ -471,26 +740,99 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetUser(name=usernameExample.value, - password="string") + OutBoundGetUser(name=userNameExample.value, + password=passwordExample.value) ), exampleInboundMessage = ( InBoundGetUser(status=MessageDocsSwaggerDefinitions.inboundStatus, data= InboundUser(email=emailExample.value, - password="string", - displayName="string")) + password=passwordExample.value, + displayName=displayNameExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getUser(name: String, password: String): Box[InboundUser] = { - import com.openbankproject.commons.dto.{OutBoundGetUser => OutBound, InBoundGetUser => InBound} + import com.openbankproject.commons.dto.{InBoundGetUser => InBound, OutBoundGetUser => OutBound} val callContext: Option[CallContext] = None val req = OutBound(name, password) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[InboundUser](callContext)) } + messageDocs += checkExternalUserCredentialsDoc + def checkExternalUserCredentialsDoc = MessageDoc( + process = "obp.checkExternalUserCredentials", + messageFormat = messageFormat, + description = "Check External User Credentials", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCheckExternalUserCredentials(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + username=usernameExample.value, + password=passwordExample.value) + ), + exampleInboundMessage = ( + InBoundCheckExternalUserCredentials(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= InboundExternalUser(aud=audExample.value, + exp=expExample.value, + iat=iatExample.value, + iss=issExample.value, + sub=subExample.value, + azp=Some("string"), + email=Some(emailExample.value), + emailVerified=Some(emailVerifiedExample.value), + name=Some(userNameExample.value), + userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, + value=valueExample.value))))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def checkExternalUserCredentials(username: String, password: String, callContext: Option[CallContext]): Box[InboundExternalUser] = { + import com.openbankproject.commons.dto.{InBoundCheckExternalUserCredentials => InBound, OutBoundCheckExternalUserCredentials => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, username, password) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[InboundExternalUser](callContext)) + } + + messageDocs += checkExternalUserExistsDoc + def checkExternalUserExistsDoc = MessageDoc( + process = "obp.checkExternalUserExists", + messageFormat = messageFormat, + description = "Check External User Exists", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCheckExternalUserExists(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + username=usernameExample.value) + ), + exampleInboundMessage = ( + InBoundCheckExternalUserExists(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= InboundExternalUser(aud=audExample.value, + exp=expExample.value, + iat=iatExample.value, + iss=issExample.value, + sub=subExample.value, + azp=Some("string"), + email=Some(emailExample.value), + emailVerified=Some(emailVerifiedExample.value), + name=Some(userNameExample.value), + userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, + value=valueExample.value))))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def checkExternalUserExists(username: String, callContext: Option[CallContext]): Box[InboundExternalUser] = { + import com.openbankproject.commons.dto.{InBoundCheckExternalUserExists => InBound, OutBoundCheckExternalUserExists => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, username) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[InboundExternalUser](callContext)) + } + messageDocs += getBankAccountOldDoc def getBankAccountOldDoc = MessageDoc( process = "obp.getBankAccountOld", @@ -506,25 +848,28 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { InBoundGetBankAccountOld(status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBankAccountOld(bankId: BankId, accountId: AccountId): Box[BankAccount] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountOld => OutBound, InBoundGetBankAccountOld => InBound} + import com.openbankproject.commons.dto.{InBoundGetBankAccountOld => InBound, OutBoundGetBankAccountOld => OutBound} val callContext: Option[CallContext] = None val req = OutBound(bankId, accountId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) @@ -547,25 +892,28 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBankAccountByIban(iban: String, callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountByIban => OutBound, InBoundGetBankAccountByIban => InBound} + import com.openbankproject.commons.dto.{InBoundGetBankAccountByIban => InBound, OutBoundGetBankAccountByIban => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[BankAccountCommons](callContext)) @@ -581,33 +929,36 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundGetBankAccountByRouting(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=Some(BankId(bankIdExample.value)), - scheme="string", - address="string") + scheme=schemeExample.value, + address=addressExample.value) ), exampleInboundMessage = ( InBoundGetBankAccountByRouting(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBankAccountByRouting(bankId: Option[BankId], scheme: String, address: String, callContext: Option[CallContext]): Box[(BankAccount, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountByRouting => OutBound, InBoundGetBankAccountByRouting => InBound} + import com.openbankproject.commons.dto.{InBoundGetBankAccountByRouting => InBound, OutBoundGetBankAccountByRouting => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, scheme, address) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[BankAccountCommons](callContext)) @@ -630,25 +981,28 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value))) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[List[BankAccount]]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccounts => OutBound, InBoundGetBankAccounts => InBound} + import com.openbankproject.commons.dto.{InBoundGetBankAccounts => InBound, OutBoundGetBankAccounts => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[BankAccountCommons]](callContext)) @@ -669,7 +1023,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetBankAccountsBalances(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= AccountsBalances(accounts=List( AccountBalance(id=accountIdExample.value, + data= AccountsBalances(accounts=List( AccountBalance(id=idExample.value, label=labelExample.value, bankId=bankIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, @@ -677,14 +1031,14 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { balance= AmountOfMoney(currency=balanceCurrencyExample.value, amount=balanceAmountExample.value))), overallBalance= AmountOfMoney(currency=currencyExample.value, - amount="string"), - overallBalanceDate=new Date())) + amount=amountExample.value), + overallBalanceDate=toDate(overallBalanceDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[AccountsBalances]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsBalances => OutBound, InBoundGetBankAccountsBalances => InBound} + import com.openbankproject.commons.dto.{InBoundGetBankAccountsBalances => InBound, OutBoundGetBankAccountsBalances => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AccountsBalances](callContext)) @@ -705,10 +1059,10 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetBankAccountsHeld(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( AccountHeld(id="string", - label = labelExample.value, + data=List( AccountHeld(id=idExample.value, + label=labelExample.value, bankId=bankIdExample.value, - number="string", + number=numberExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value))))) ), @@ -716,7 +1070,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getBankAccountsHeld(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[List[AccountHeld]]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsHeld => OutBound, InBoundGetBankAccountsHeld => InBound} + import com.openbankproject.commons.dto.{InBoundGetBankAccountsHeld => InBound, OutBoundGetBankAccountsHeld => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[AccountHeld]](callContext)) @@ -738,22 +1092,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetCounterpartyTrait(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) @@ -762,7 +1116,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCounterpartyTrait(bankId: BankId, accountId: AccountId, couterpartyId: String, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyTrait => OutBound, InBoundGetCounterpartyTrait => InBound} + import com.openbankproject.commons.dto.{InBoundGetCounterpartyTrait => InBound, OutBoundGetCounterpartyTrait => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, couterpartyId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CounterpartyTraitCommons](callContext)) @@ -782,22 +1136,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetCounterpartyByCounterpartyId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) @@ -806,7 +1160,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCounterpartyByCounterpartyId(counterpartyId: CounterpartyId, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyByCounterpartyId => OutBound, InBoundGetCounterpartyByCounterpartyId => InBound} + import com.openbankproject.commons.dto.{InBoundGetCounterpartyByCounterpartyId => InBound, OutBoundGetCounterpartyByCounterpartyId => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, counterpartyId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CounterpartyTraitCommons](callContext)) @@ -826,22 +1180,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetCounterpartyByIban(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) @@ -850,12 +1204,58 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCounterpartyByIban(iban: String, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyByIban => OutBound, InBoundGetCounterpartyByIban => InBound} + import com.openbankproject.commons.dto.{InBoundGetCounterpartyByIban => InBound, OutBoundGetCounterpartyByIban => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CounterpartyTraitCommons](callContext)) } + messageDocs += getCounterpartyByIbanAndBankAccountIdDoc + def getCounterpartyByIbanAndBankAccountIdDoc = MessageDoc( + process = "obp.getCounterpartyByIbanAndBankAccountId", + messageFormat = messageFormat, + description = "Get Counterparty By Iban And Bank Account Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCounterpartyByIbanAndBankAccountId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + iban=ibanExample.value, + bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value)) + ), + exampleInboundMessage = ( + InBoundGetCounterpartyByIbanAndBankAccountId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, + currency=currencyExample.value, + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, + counterpartyId=counterpartyIdExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, + isBeneficiary=isBeneficiaryExample.value.toBoolean, + bespoke=List( CounterpartyBespoke(key=keyExample.value, + value=valueExample.value)))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCounterpartyByIbanAndBankAccountId(iban: String, bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { + import com.openbankproject.commons.dto.{InBoundGetCounterpartyByIbanAndBankAccountId => InBound, OutBoundGetCounterpartyByIbanAndBankAccountId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban, bankId, accountId) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[CounterpartyTraitCommons](callContext)) + } + messageDocs += getCounterpartiesDoc def getCounterpartiesDoc = MessageDoc( process = "obp.getCounterparties", @@ -865,29 +1265,29 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetCounterparties(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), + thisBankId=BankId(thisBankIdExample.value), + thisAccountId=AccountId(thisAccountIdExample.value), viewId=ViewId(viewIdExample.value)) ), exampleInboundMessage = ( InBoundGetCounterparties(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + data=List( CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))))) @@ -896,7 +1296,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCounterparties(thisBankId: BankId, thisAccountId: AccountId, viewId: ViewId, callContext: Option[CallContext]): OBPReturnType[Box[List[CounterpartyTrait]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterparties => OutBound, InBoundGetCounterparties => InBound} + import com.openbankproject.commons.dto.{InBoundGetCounterparties => InBound, OutBoundGetCounterparties => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, thisBankId, thisAccountId, viewId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CounterpartyTraitCommons]](callContext)) @@ -915,57 +1315,132 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { accountId=AccountId(accountIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( InBoundGetTransactionsCore(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( TransactionCore(id=TransactionId(transactionIdExample.value), + data=List( TransactionCore(id=TransactionId(idExample.value), thisAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - otherAccount= CounterpartyCore(kind="string", + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + otherAccount= CounterpartyCore(kind=kindExample.value, counterpartyId=counterpartyIdExample.value, counterpartyName=counterpartyNameExample.value, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=Some(bankRoutingAddressExample.value), - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=Some(accountRoutingAddressExample.value), + thisBankId=BankId(thisBankIdExample.value), + thisAccountId=AccountId(thisAccountIdExample.value), + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=Some(otherBankRoutingAddressExample.value), + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=Some(otherAccountRoutingAddressExample.value), otherAccountProvider=otherAccountProviderExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean), transactionType=transactionTypeExample.value, - amount=BigDecimal("123.321"), + amount=BigDecimal(amountExample.value), currency=currencyExample.value, - description=Some("string"), - startDate=new Date(), - finishDate=new Date(), - balance=BigDecimal(balanceAmountExample.value)))) + description=Some(descriptionExample.value), + startDate=toDate(startDateExample), + finishDate=toDate(finishDateExample), + balance=BigDecimal(balanceExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getTransactionsCore(bankId: BankId, accountId: AccountId, queryParams: List[OBPQueryParam], callContext: Option[CallContext]): OBPReturnType[Box[List[TransactionCore]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionsCore => OutBound, InBoundGetTransactionsCore => InBound} + import com.openbankproject.commons.dto.{InBoundGetTransactionsCore => InBound, OutBoundGetTransactionsCore => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[TransactionCore]](callContext)) } + messageDocs += getPhysicalCardsForUserDoc + def getPhysicalCardsForUserDoc = MessageDoc( + process = "obp.getPhysicalCardsForUser", + messageFormat = messageFormat, + description = "Get Physical Cards For User", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetPhysicalCardsForUser( UserCommons(userPrimaryKey=UserPrimaryKey(123), + userId=userIdExample.value, + idGivenByProvider="string", + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true))) + ), + exampleInboundMessage = ( + InBoundGetPhysicalCardsForUser(status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( PhysicalCard(cardId=cardIdExample.value, + bankId=bankIdExample.value, + bankCardNumber=bankCardNumberExample.value, + cardType=cardTypeExample.value, + nameOnCard=nameOnCardExample.value, + issueNumber=issueNumberExample.value, + serialNumber=serialNumberExample.value, + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, + allows=List(com.openbankproject.commons.model.CardAction.DEBIT), + account= BankAccountCommons(accountId=AccountId(accountIdExample.value), + accountType=accountTypeExample.value, + balance=BigDecimal(balanceExample.value), + currency=currencyExample.value, + name=bankAccountNameExample.value, + label=labelExample.value, + number=accountNumberExample.value, + bankId=BankId(bankIdExample.value), + lastUpdate=toDate(bankAccountLastUpdateExample), + branchId=branchIdExample.value, + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, + value=accountRuleValueExample.value)), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), + reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), + reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), + customerId=customerIdExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getPhysicalCardsForUser(user: User): Box[List[PhysicalCard]] = { + import com.openbankproject.commons.dto.{InBoundGetPhysicalCardsForUser => InBound, OutBoundGetPhysicalCardsForUser => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(user) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[List[PhysicalCard]](callContext)) + } + messageDocs += getPhysicalCardForBankDoc def getPhysicalCardForBankDoc = MessageDoc( process = "obp.getPhysicalCardForBank", @@ -988,42 +1463,45 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getPhysicalCardForBank(bankId: BankId, cardId: String, callContext: Option[CallContext]): OBPReturnType[Box[PhysicalCardTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetPhysicalCardForBank => OutBound, InBoundGetPhysicalCardForBank => InBound} + import com.openbankproject.commons.dto.{InBoundGetPhysicalCardForBank => InBound, OutBoundGetPhysicalCardForBank => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, cardId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[PhysicalCard](callContext)) @@ -1050,7 +1528,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deletePhysicalCardForBank(bankId: BankId, cardId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeletePhysicalCardForBank => OutBound, InBoundDeletePhysicalCardForBank => InBound} + import com.openbankproject.commons.dto.{InBoundDeletePhysicalCardForBank => InBound, OutBoundDeletePhysicalCardForBank => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, cardId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -1077,13 +1555,16 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( InBoundGetPhysicalCardsForBank(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -1095,42 +1576,45 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getPhysicalCardsForBank(bank: Bank, user: User, queryParams: List[OBPQueryParam], callContext: Option[CallContext]): OBPReturnType[Box[List[PhysicalCard]]] = { - import com.openbankproject.commons.dto.{OutBoundGetPhysicalCardsForBank => OutBound, InBoundGetPhysicalCardsForBank => InBound} + import com.openbankproject.commons.dto.{InBoundGetPhysicalCardsForBank => InBound, OutBoundGetPhysicalCardsForBank => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bank, user, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[PhysicalCard]](callContext)) @@ -1150,22 +1634,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { cardType=cardTypeExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), - allows=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, + allows=allowsExample.value.split("[,;]").toList, accountId=accountIdExample.value, bankId=bankIdExample.value, - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value) ), exampleInboundMessage = ( @@ -1178,42 +1662,45 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createPhysicalCard(bankCardNumber: String, nameOnCard: String, cardType: String, issueNumber: String, serialNumber: String, validFrom: Date, expires: Date, enabled: Boolean, cancelled: Boolean, onHotList: Boolean, technology: String, networks: List[String], allows: List[String], accountId: String, bankId: String, replacement: Option[CardReplacementInfo], pinResets: List[PinResetInfo], collected: Option[CardCollectionInfo], posted: Option[CardPostedInfo], customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[PhysicalCard]] = { - import com.openbankproject.commons.dto.{OutBoundCreatePhysicalCard => OutBound, InBoundCreatePhysicalCard => InBound} + import com.openbankproject.commons.dto.{InBoundCreatePhysicalCard => InBound, OutBoundCreatePhysicalCard => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[PhysicalCard](callContext)) @@ -1234,22 +1721,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { cardType=cardTypeExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), - allows=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, + allows=allowsExample.value.split("[,;]").toList, accountId=accountIdExample.value, bankId=bankIdExample.value, - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value) ), exampleInboundMessage = ( @@ -1262,42 +1749,45 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def updatePhysicalCard(cardId: String, bankCardNumber: String, nameOnCard: String, cardType: String, issueNumber: String, serialNumber: String, validFrom: Date, expires: Date, enabled: Boolean, cancelled: Boolean, onHotList: Boolean, technology: String, networks: List[String], allows: List[String], accountId: String, bankId: String, replacement: Option[CardReplacementInfo], pinResets: List[PinResetInfo], collected: Option[CardCollectionInfo], posted: Option[CardPostedInfo], customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[PhysicalCardTrait]] = { - import com.openbankproject.commons.dto.{OutBoundUpdatePhysicalCard => OutBound, InBoundUpdatePhysicalCard => InBound} + import com.openbankproject.commons.dto.{InBoundUpdatePhysicalCard => InBound, OutBoundUpdatePhysicalCard => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, cardId, bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[PhysicalCard](callContext)) @@ -1314,42 +1804,48 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundMakePaymentv210(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - transactionRequestId = TransactionRequestId(uuidExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transactionRequestId=TransactionRequestId(transactionRequestIdExample.value), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), - amount=BigDecimal("123.321"), - description="string", + amount=amountExample.value), + description=descriptionExample.value), + amount=BigDecimal(amountExample.value), + description=descriptionExample.value, transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( InBoundMakePaymentv210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -1360,12 +1856,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def makePaymentv210(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestId: TransactionRequestId, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amount: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionId]] = { - import com.openbankproject.commons.dto.{OutBoundMakePaymentv210 => OutBound, InBoundMakePaymentv210 => InBound} - val fromAccountCommons: BankAccountCommons = fromAccount - val toAccountCommons: BankAccountCommons = toAccount - val transactionRequestCommonBodyJSONCommons: TransactionRequestCommonBodyJSONCommons = transactionRequestCommonBody - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccountCommons, toAccountCommons, transactionRequestId, transactionRequestCommonBodyJSONCommons, amount, description, transactionRequestType, chargePolicy) - val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + import com.openbankproject.commons.dto.{InBoundMakePaymentv210 => InBound, OutBoundMakePaymentv210 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccount, toAccount, transactionRequestId, transactionRequestCommonBody, amount, description, transactionRequestType, chargePolicy) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionId](callContext)) } @@ -1381,109 +1874,118 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), detailsPlain="string", - chargePolicy="string", - challengeType=Some("string"), + chargePolicy=chargePolicyExample.value, + challengeType=Some(challengeTypeExample.value), scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS)) ), exampleInboundMessage = ( InBoundCreateTransactionRequestv210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= TransactionRequest(id=TransactionRequestId("string"), + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -1498,134 +2000,188 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createTransactionRequestv210(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, challengeType: Option[String], scaMethod: Option[StrongCustomerAuthentication.SCA], callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionRequestv210 => OutBound, InBoundCreateTransactionRequestv210 => InBound} + import com.openbankproject.commons.dto.{InBoundCreateTransactionRequestv210 => InBound, OutBoundCreateTransactionRequestv210 => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, viewId, fromAccount, toAccount, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy, challengeType, scaMethod) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionRequest](callContext)) } - - messageDocs += notifyTransactionRequestDoc - def notifyTransactionRequestDoc = MessageDoc( - process = "obp.notifyTransactionRequest", + + messageDocs += createTransactionRequestv400Doc + def createTransactionRequestv400Doc = MessageDoc( + process = "obp.createTransactionRequestv400", messageFormat = messageFormat, - description = "Notify Transaction Request", + description = "Create Transaction Requestv400", outboundTopic = None, inboundTopic = None, - exampleOutboundMessage = OutBoundNotifyTransactionRequest(outboundAdapterCallContext = MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - fromAccount = BankAccountCommons(accountId = AccountId(accountIdExample.value), - accountType = accountTypeExample.value, - balance = BigDecimal(balanceAmountExample.value), - currency = currencyExample.value, - name = bankAccountNameExample.value, - label = labelExample.value, - number = bankAccountNumberExample.value, - bankId = BankId(bankIdExample.value), - lastUpdate = parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), - branchId = branchIdExample.value, - accountRoutings = List(AccountRouting(scheme = accountRoutingSchemeExample.value, - address = accountRoutingAddressExample.value)), - accountRules = List(AccountRule(scheme = accountRuleSchemeExample.value, - value = accountRuleValueExample.value)), - accountHolder = bankAccountAccountHolderExample.value), - toAccount = BankAccountCommons(accountId = AccountId(accountIdExample.value), - accountType = accountTypeExample.value, - balance = BigDecimal(balanceAmountExample.value), - currency = currencyExample.value, - name = bankAccountNameExample.value, - label = labelExample.value, - number = bankAccountNumberExample.value, - bankId = BankId(bankIdExample.value), - lastUpdate = parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), - branchId = branchIdExample.value, - accountRoutings = List(AccountRouting(scheme = accountRoutingSchemeExample.value, - address = accountRoutingAddressExample.value)), - accountRules = List(AccountRule(scheme = accountRuleSchemeExample.value, - value = accountRuleValueExample.value)), - accountHolder = bankAccountAccountHolderExample.value), - transactionRequest = TransactionRequest(id = TransactionRequestId("string"), - `type` = transactionRequestTypeExample.value, - from = TransactionRequestAccount(bank_id = "string", - account_id = "string"), - body = TransactionRequestBodyAllTypes(to_sandbox_tan = Some(TransactionRequestAccount(bank_id = "string", - account_id = "string")), - to_sepa = Some(TransactionRequestIban("string")), - to_counterparty = Some(TransactionRequestCounterpartyId("string")), - to_transfer_to_phone = Some(TransactionRequestTransferToPhone(value = AmountOfMoneyJsonV121(currency = currencyExample.value, - amount = "string"), - description = "string", - message = "string", - from = FromAccountTransfer(mobile_phone_number = "string", - nickname = "string"), - to = ToAccountTransferToPhone("string"))), - to_transfer_to_atm = Some(TransactionRequestTransferToAtm(value = AmountOfMoneyJsonV121(currency = currencyExample.value, - amount = "string"), - description = "string", - message = "string", - from = FromAccountTransfer(mobile_phone_number = "string", - nickname = "string"), - to = ToAccountTransferToAtm(legal_name = "string", - date_of_birth = "string", - mobile_phone_number = "string", - kyc_document = ToAccountTransferToAtmKycDocument(`type` = "string", - number = "string")))), - to_transfer_to_account = Some(TransactionRequestTransferToAccount(value = AmountOfMoneyJsonV121(currency = currencyExample.value, - amount = "string"), - description = "string", - transfer_type = "string", - future_date = "string", - to = ToAccountTransferToAccount(name = "string", - bank_code = "string", - branch_number = "string", - account = ToAccountTransferToAccountAccount(number = accountNumberExample.value, - iban = ibanExample.value)))), - to_sepa_credit_transfers = Some(SepaCreditTransfers(debtorAccount = PaymentAccount("string"), - instructedAmount = AmountOfMoneyJsonV121(currency = currencyExample.value, - amount = "string"), - creditorAccount = PaymentAccount("string"), - creditorName = "string")), - value = AmountOfMoney(currency = currencyExample.value, - amount = "string"), - description = "string"), - transaction_ids = "string", - status = "string", - start_date = new Date(), - end_date = new Date(), - challenge = TransactionRequestChallenge(id = "string", - allowed_attempts = 123, - challenge_type = "string"), - charge = TransactionRequestCharge(summary = "string", - value = AmountOfMoney(currency = currencyExample.value, - amount = "string")), - charge_policy = "string", - counterparty_id = CounterpartyId(counterpartyIdExample.value), - name = "string", - this_bank_id = BankId(bankIdExample.value), - this_account_id = AccountId(accountIdExample.value), - this_view_id = ViewId(viewIdExample.value), - other_account_routing_scheme = "string", - other_account_routing_address = "string", - other_bank_routing_scheme = "string", - other_bank_routing_address = "string", - is_beneficiary = true, - future_date = Some("string")) + exampleOutboundMessage = ( + OutBoundCreateTransactionRequestv400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), + userId=userIdExample.value, + idGivenByProvider="string", + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), + viewId=ViewId(viewIdExample.value), + fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), + accountType=accountTypeExample.value, + balance=BigDecimal(balanceExample.value), + currency=currencyExample.value, + name=bankAccountNameExample.value, + label=labelExample.value, + number=bankAccountNumberExample.value, + bankId=BankId(bankIdExample.value), + lastUpdate=toDate(bankAccountLastUpdateExample), + branchId=branchIdExample.value, + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, + value=accountRuleValueExample.value)), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), + accountType=accountTypeExample.value, + balance=BigDecimal(balanceExample.value), + currency=currencyExample.value, + name=bankAccountNameExample.value, + label=labelExample.value, + number=bankAccountNumberExample.value, + bankId=BankId(bankIdExample.value), + lastUpdate=toDate(bankAccountLastUpdateExample), + branchId=branchIdExample.value, + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, + value=accountRuleValueExample.value)), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), + transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value), + detailsPlain="string", + chargePolicy=chargePolicyExample.value, + challengeType=Some(challengeTypeExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + reasons=Some(List( TransactionRequestReason(code=codeExample.value, + documentNumber=Some(documentNumberExample.value), + amount=Some(amountExample.value), + currency=Some(currencyExample.value), + description=Some(descriptionExample.value)))), + berlinGroupPayments=Some( SepaCreditTransfersBerlinGroupV13(endToEndIdentification=Some("string"), + instructionIdentification=Some("string"), + debtorName=Some("string"), + debtorAccount=PaymentAccount("string"), + debtorId=Some("string"), + ultimateDebtor=Some("string"), + instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + currencyOfTransfer=Some("string"), + exchangeRateInformation=Some("string"), + creditorAccount=PaymentAccount("string"), + creditorAgent=Some("string"), + creditorAgentName=Some("string"), + creditorName="string", + creditorId=Some("string"), + creditorAddress=Some("string"), + creditorNameAndAddress=Some("string"), + ultimateCreditor=Some("string"), + purposeCode=Some("string"), + chargeBearer=Some("string"), + serviceLevel=Some("string"), + remittanceInformationUnstructured=Some("string"), + remittanceInformationUnstructuredArray=Some("string"), + remittanceInformationStructured=Some("string"), + remittanceInformationStructuredArray=Some("string"), + requestedExecutionDate=Some("string"), + requestedExecutionTime=Some("string")))) ), - exampleInboundMessage = InBoundNotifyTransactionRequest( - inboundAdapterCallContext = MessageDocsSwaggerDefinitions.inboundAdapterCallContext, - status = MessageDocsSwaggerDefinitions.inboundStatus, - data = TransactionRequestStatusValue(TransactionRequestStatus.FORWARDED.toString) + exampleInboundMessage = ( + InBoundCreateTransactionRequestv400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), + `type`=transactionRequestTypeExample.value, + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), + to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), + to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to= ToAccountTransferToAtm(legal_name="string", + date_of_birth="string", + mobile_phone_number="string", + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), + to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + transfer_type="string", + future_date="string", + to= ToAccountTransferToAccount(name=nameExample.value, + bank_code="string", + branch_number="string", + account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, + iban=ibanExample.value)))), + to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), + instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + creditorAccount=PaymentAccount("string"), + creditorName="string")), + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value), + transaction_ids="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, + allowed_attempts=123, + challenge_type="string"), + charge= TransactionRequestCharge(summary=summaryExample.value, + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value)), + charge_policy="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, + this_bank_id=BankId(bankIdExample.value), + this_account_id=AccountId(accountIdExample.value), + this_view_id=ViewId(viewIdExample.value), + other_account_routing_scheme="string", + other_account_routing_address="string", + other_bank_routing_scheme="string", + other_bank_routing_address="string", + is_beneficiary=true, + future_date=Some("string"))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - override def notifyTransactionRequest(fromAccount: BankAccount, toAccount: BankAccount, transactionRequest: TransactionRequest, callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequestStatusValue]] = { - import com.openbankproject.commons.dto.{OutBoundNotifyTransactionRequest => OutBound, InBoundNotifyTransactionRequest => InBound} - val fromAccountCommons: BankAccountCommons = fromAccount - val toAccountCommons: BankAccountCommons = toAccount - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccountCommons, toAccountCommons, transactionRequest) - val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) - response.map(convertToTuple[TransactionRequestStatusValue](callContext)) + override def createTransactionRequestv400(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, challengeType: Option[String], scaMethod: Option[StrongCustomerAuthentication.SCA], reasons: Option[List[TransactionRequestReason]], berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13], callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { + import com.openbankproject.commons.dto.{InBoundCreateTransactionRequestv400 => InBound, OutBoundCreateTransactionRequestv400 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, viewId, fromAccount, toAccount, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy, challengeType, scaMethod, reasons, berlinGroupPayments) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[TransactionRequest](callContext)) } - + messageDocs += getTransactionRequests210Doc def getTransactionRequests210Doc = MessageDoc( process = "obp.getTransactionRequests210", @@ -1638,85 +2194,91 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), exampleInboundMessage = ( InBoundGetTransactionRequests210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( TransactionRequest(id=TransactionRequestId("string"), + data=List( TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -1731,7 +2293,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getTransactionRequests210(initiator: User, fromAccount: BankAccount, callContext: Option[CallContext]): Box[(List[TransactionRequest], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionRequests210 => OutBound, InBoundGetTransactionRequests210 => InBound} + import com.openbankproject.commons.dto.{InBoundGetTransactionRequests210 => InBound, OutBoundGetTransactionRequests210 => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, fromAccount) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[TransactionRequest]](callContext)) @@ -1746,68 +2308,68 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetTransactionRequestImpl(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - transactionRequestId=TransactionRequestId("string")) + transactionRequestId=TransactionRequestId(transactionRequestIdExample.value)) ), exampleInboundMessage = ( InBoundGetTransactionRequestImpl(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= TransactionRequest(id=TransactionRequestId("string"), + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -1822,7 +2384,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getTransactionRequestImpl(transactionRequestId: TransactionRequestId, callContext: Option[CallContext]): Box[(TransactionRequest, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionRequestImpl => OutBound, InBoundGetTransactionRequestImpl => InBound} + import com.openbankproject.commons.dto.{InBoundGetTransactionRequestImpl => InBound, OutBoundGetTransactionRequestImpl => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionRequest](callContext)) @@ -1839,76 +2401,79 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateTransactionAfterChallengeV210(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - transactionRequest= TransactionRequest(id=TransactionRequestId("string"), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transactionRequest= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -1922,63 +2487,63 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundCreateTransactionAfterChallengeV210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= TransactionRequest(id=TransactionRequestId("string"), + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -1993,7 +2558,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createTransactionAfterChallengeV210(fromAccount: BankAccount, transactionRequest: TransactionRequest, callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionAfterChallengeV210 => OutBound, InBoundCreateTransactionAfterChallengeV210 => InBound} + import com.openbankproject.commons.dto.{InBoundCreateTransactionAfterChallengeV210 => InBound, OutBoundCreateTransactionAfterChallengeV210 => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccount, transactionRequest) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionRequest](callContext)) @@ -2013,33 +2578,36 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { accountType=accountTypeExample.value, accountLabel="string", branchId=branchIdExample.value, - accountRoutings=List(AccountRouting(accountRoutingSchemeExample.value, accountRoutingAddressExample.value)) - ) + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value))) ), exampleInboundMessage = ( InBoundUpdateBankAccount(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def updateBankAccount(bankId: BankId, accountId: AccountId, accountType: String, accountLabel: String, branchId: String, accountRoutings: List[AccountRouting], callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateBankAccount => OutBound, InBoundUpdateBankAccount => InBound} + import com.openbankproject.commons.dto.{InBoundUpdateBankAccount => InBound, OutBoundUpdateBankAccount => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, accountType, accountLabel, branchId, accountRoutings) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[BankAccountCommons](callContext)) @@ -2062,33 +2630,36 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { initialBalance=BigDecimal("123.321"), accountHolderName="string", branchId=branchIdExample.value, - accountRoutings=List(AccountRouting(accountRoutingSchemeExample.value, accountRoutingAddressExample.value)) - ) + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value))) ), exampleInboundMessage = ( InBoundCreateBankAccount(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createBankAccount(bankId: BankId, accountId: AccountId, accountType: String, accountLabel: String, currency: String, initialBalance: BigDecimal, accountHolderName: String, branchId: String, accountRoutings: List[AccountRouting], callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundCreateBankAccount => OutBound, InBoundCreateBankAccount => InBound} + import com.openbankproject.commons.dto.{InBoundCreateBankAccount => InBound, OutBoundCreateBankAccount => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, accountType, accountLabel, currency, initialBalance, accountHolderName, branchId, accountRoutings) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[BankAccountCommons](callContext)) @@ -2113,13 +2684,88 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def accountExists(bankId: BankId, accountNumber: String): Box[Boolean] = { - import com.openbankproject.commons.dto.{OutBoundAccountExists => OutBound, InBoundAccountExists => InBound} + import com.openbankproject.commons.dto.{InBoundAccountExists => InBound, OutBoundAccountExists => OutBound} val callContext: Option[CallContext] = None val req = OutBound(bankId, accountNumber) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) } + messageDocs += getProductsDoc + def getProductsDoc = MessageDoc( + process = "obp.getProducts", + messageFormat = messageFormat, + description = "Get Products", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetProducts(bankId=BankId(bankIdExample.value), + params=List( GetProductsParam(name=nameExample.value, + value=valueExample.value.split("[,;]").toList))) + ), + exampleInboundMessage = ( + InBoundGetProducts(status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCommons(bankId=BankId(bankIdExample.value), + code=ProductCode(productCodeExample.value), + parentProductCode=ProductCode(parentProductCodeExample.value), + name=nameExample.value, + category=categoryExample.value, + family=familyExample.value, + superFamily=superFamilyExample.value, + moreInfoUrl=moreInfoUrlExample.value, + details=detailsExample.value, + description=descriptionExample.value, + meta=Meta( License(id=idExample.value, + name=nameExample.value))))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getProducts(bankId: BankId, params: List[GetProductsParam]): Box[List[Product]] = { + import com.openbankproject.commons.dto.{InBoundGetProducts => InBound, OutBoundGetProducts => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, params) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[List[ProductCommons]](callContext)) + } + + messageDocs += getProductDoc + def getProductDoc = MessageDoc( + process = "obp.getProduct", + messageFormat = messageFormat, + description = "Get Product", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetProduct(bankId=BankId(bankIdExample.value), + productCode=ProductCode(productCodeExample.value)) + ), + exampleInboundMessage = ( + InBoundGetProduct(status=MessageDocsSwaggerDefinitions.inboundStatus, + data= ProductCommons(bankId=BankId(bankIdExample.value), + code=ProductCode(productCodeExample.value), + parentProductCode=ProductCode(parentProductCodeExample.value), + name=nameExample.value, + category=categoryExample.value, + family=familyExample.value, + superFamily=superFamilyExample.value, + moreInfoUrl=moreInfoUrlExample.value, + details=detailsExample.value, + description=descriptionExample.value, + meta=Meta( License(id=idExample.value, + name=nameExample.value)))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getProduct(bankId: BankId, productCode: ProductCode): Box[Product] = { + import com.openbankproject.commons.dto.{InBoundGetProduct => InBound, OutBoundGetProduct => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, productCode) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[ProductCommons](callContext)) + } + messageDocs += getBranchDoc def getBranchDoc = MessageDoc( process = "obp.getBranch", @@ -2137,67 +2783,67 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { status=MessageDocsSwaggerDefinitions.inboundStatus, data= BranchTCommons(branchId=BranchId(branchIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), lobbyString=Some(LobbyString("string")), driveUpString=Some(DriveUpString("string")), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), branchRouting=Some( Routing(scheme=branchRoutingSchemeExample.value, address=branchRoutingAddressExample.value)), - lobby=Some( Lobby(monday=List( OpeningTimes(openingTime="string", - closingTime="string")), - tuesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - wednesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - thursday=List( OpeningTimes(openingTime="string", - closingTime="string")), - friday=List( OpeningTimes(openingTime="string", - closingTime="string")), - saturday=List( OpeningTimes(openingTime="string", - closingTime="string")), - sunday=List( OpeningTimes(openingTime="string", - closingTime="string")))), - driveUp=Some( DriveUp(monday= OpeningTimes(openingTime="string", - closingTime="string"), - tuesday= OpeningTimes(openingTime="string", - closingTime="string"), - wednesday= OpeningTimes(openingTime="string", - closingTime="string"), - thursday= OpeningTimes(openingTime="string", - closingTime="string"), - friday= OpeningTimes(openingTime="string", - closingTime="string"), - saturday= OpeningTimes(openingTime="string", - closingTime="string"), - sunday= OpeningTimes(openingTime="string", - closingTime="string"))), - isAccessible=Some(true), + lobby=Some( Lobby(monday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + tuesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + wednesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + thursday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + friday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + saturday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + sunday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)))), + driveUp=Some( DriveUp(monday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + tuesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + wednesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + thursday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + friday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + saturday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + sunday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value))), + isAccessible=Some(isAccessibleExample.value.toBoolean), accessibleFeatures=Some("string"), - branchType=Some("string"), - moreInfo=Some("string"), - phoneNumber=Some("string"), + branchType=Some(branchTypeExample.value), + moreInfo=Some(moreInfoExample.value), + phoneNumber=Some(phoneNumberExample.value), isDeleted=Some(true))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBranch(bankId: BankId, branchId: BranchId, callContext: Option[CallContext]): Future[Box[(BranchT, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBranch => OutBound, InBoundGetBranch => InBound} + import com.openbankproject.commons.dto.{InBoundGetBranch => InBound, OutBoundGetBranch => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, branchId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[BranchTCommons](callContext)) @@ -2215,75 +2861,75 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=BankId(bankIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( InBoundGetBranches(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( BranchTCommons(branchId=BranchId(branchIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), lobbyString=Some(LobbyString("string")), driveUpString=Some(DriveUpString("string")), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), branchRouting=Some( Routing(scheme=branchRoutingSchemeExample.value, address=branchRoutingAddressExample.value)), - lobby=Some( Lobby(monday=List( OpeningTimes(openingTime="string", - closingTime="string")), - tuesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - wednesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - thursday=List( OpeningTimes(openingTime="string", - closingTime="string")), - friday=List( OpeningTimes(openingTime="string", - closingTime="string")), - saturday=List( OpeningTimes(openingTime="string", - closingTime="string")), - sunday=List( OpeningTimes(openingTime="string", - closingTime="string")))), - driveUp=Some( DriveUp(monday= OpeningTimes(openingTime="string", - closingTime="string"), - tuesday= OpeningTimes(openingTime="string", - closingTime="string"), - wednesday= OpeningTimes(openingTime="string", - closingTime="string"), - thursday= OpeningTimes(openingTime="string", - closingTime="string"), - friday= OpeningTimes(openingTime="string", - closingTime="string"), - saturday= OpeningTimes(openingTime="string", - closingTime="string"), - sunday= OpeningTimes(openingTime="string", - closingTime="string"))), - isAccessible=Some(true), + lobby=Some( Lobby(monday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + tuesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + wednesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + thursday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + friday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + saturday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + sunday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)))), + driveUp=Some( DriveUp(monday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + tuesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + wednesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + thursday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + friday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + saturday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + sunday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value))), + isAccessible=Some(isAccessibleExample.value.toBoolean), accessibleFeatures=Some("string"), - branchType=Some("string"), - moreInfo=Some("string"), - phoneNumber=Some("string"), + branchType=Some(branchTypeExample.value), + moreInfo=Some(moreInfoExample.value), + phoneNumber=Some(phoneNumberExample.value), isDeleted=Some(true)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getBranches(bankId: BankId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Future[Box[(List[BranchT], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBranches => OutBound, InBoundGetBranches => InBound} + import com.openbankproject.commons.dto.{InBoundGetBranches => InBound, OutBoundGetBranches => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[BranchTCommons]](callContext)) @@ -2299,30 +2945,30 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundGetAtm(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), - atmId=AtmId("string")) + atmId=AtmId(atmIdExample.value)) ), exampleInboundMessage = ( InBoundGetAtm(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= AtmTCommons(atmId=AtmId("string"), + data= AtmTCommons(atmId=AtmId(atmIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), OpeningTimeOnMonday=Some("string"), ClosingTimeOnMonday=Some("string"), OpeningTimeOnTuesday=Some("string"), @@ -2337,16 +2983,29 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ClosingTimeOnSaturday=Some("string"), OpeningTimeOnSunday=Some("string"), ClosingTimeOnSunday=Some("string"), - isAccessible=Some(true), - locatedAt=Some("string"), - moreInfo=Some("string"), - hasDepositCapability=Some(true))) + isAccessible=Some(isAccessibleExample.value.toBoolean), + locatedAt=Some(locatedAtExample.value), + moreInfo=Some(moreInfoExample.value), + hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), + supportedLanguages=Some(supportedLanguagesExample.value.split("[,;]").toList), + services=Some(listExample.value.split("[,;]").toList), + accessibilityFeatures=Some(accessibilityFeaturesExample.value.split("[,;]").toList), + supportedCurrencies=Some(supportedCurrenciesExample.value.split("[,;]").toList), + notes=Some(listExample.value.split("[,;]").toList), + locationCategories=Some(listExample.value.split("[,;]").toList), + minimumWithdrawal=Some("string"), + branchIdentification=Some("string"), + siteIdentification=Some(siteIdentification.value), + siteName=Some("string"), + cashWithdrawalNationalFee=Some(cashWithdrawalNationalFeeExample.value), + cashWithdrawalInternationalFee=Some(cashWithdrawalInternationalFeeExample.value), + balanceInquiryFee=Some(balanceInquiryFeeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getAtm(bankId: BankId, atmId: AtmId, callContext: Option[CallContext]): Future[Box[(AtmT, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetAtm => OutBound, InBoundGetAtm => InBound} + import com.openbankproject.commons.dto.{InBoundGetAtm => InBound, OutBoundGetAtm => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, atmId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AtmTCommons](callContext)) @@ -2364,31 +3023,31 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=BankId(bankIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( InBoundGetAtms(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( AtmTCommons(atmId=AtmId("string"), + data=List( AtmTCommons(atmId=AtmId(atmIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), OpeningTimeOnMonday=Some("string"), ClosingTimeOnMonday=Some("string"), OpeningTimeOnTuesday=Some("string"), @@ -2403,21 +3062,66 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ClosingTimeOnSaturday=Some("string"), OpeningTimeOnSunday=Some("string"), ClosingTimeOnSunday=Some("string"), - isAccessible=Some(true), - locatedAt=Some("string"), - moreInfo=Some("string"), - hasDepositCapability=Some(true)))) + isAccessible=Some(isAccessibleExample.value.toBoolean), + locatedAt=Some(locatedAtExample.value), + moreInfo=Some(moreInfoExample.value), + hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), + supportedLanguages=Some(supportedLanguagesExample.value.split("[,;]").toList), + services=Some(listExample.value.split("[,;]").toList), + accessibilityFeatures=Some(accessibilityFeaturesExample.value.split("[,;]").toList), + supportedCurrencies=Some(supportedCurrenciesExample.value.split("[,;]").toList), + notes=Some(listExample.value.split("[,;]").toList), + locationCategories=Some(listExample.value.split("[,;]").toList), + minimumWithdrawal=Some("string"), + branchIdentification=Some("string"), + siteIdentification=Some(siteIdentification.value), + siteName=Some("string"), + cashWithdrawalNationalFee=Some(cashWithdrawalNationalFeeExample.value), + cashWithdrawalInternationalFee=Some(cashWithdrawalInternationalFeeExample.value), + balanceInquiryFee=Some(balanceInquiryFeeExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getAtms(bankId: BankId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Future[Box[(List[AtmT], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetAtms => OutBound, InBoundGetAtms => InBound} + import com.openbankproject.commons.dto.{InBoundGetAtms => InBound, OutBoundGetAtms => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[AtmTCommons]](callContext)) } + messageDocs += getCurrentFxRateDoc + def getCurrentFxRateDoc = MessageDoc( + process = "obp.getCurrentFxRate", + messageFormat = messageFormat, + description = "Get Current Fx Rate", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCurrentFxRate(bankId=BankId(bankIdExample.value), + fromCurrencyCode=fromCurrencyCodeExample.value, + toCurrencyCode=toCurrencyCodeExample.value) + ), + exampleInboundMessage = ( + InBoundGetCurrentFxRate(status=MessageDocsSwaggerDefinitions.inboundStatus, + data= FXRateCommons(bankId=BankId(bankIdExample.value), + fromCurrencyCode=fromCurrencyCodeExample.value, + toCurrencyCode=toCurrencyCodeExample.value, + conversionValue=conversionValueExample.value.toDouble, + inverseConversionValue=inverseConversionValueExample.value.toDouble, + effectiveDate=toDate(effectiveDateExample))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCurrentFxRate(bankId: BankId, fromCurrencyCode: String, toCurrencyCode: String): Box[FXRate] = { + import com.openbankproject.commons.dto.{InBoundGetCurrentFxRate => InBound, OutBoundGetCurrentFxRate => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, fromCurrencyCode, toCurrencyCode) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[FXRateCommons](callContext)) + } + messageDocs += createTransactionAfterChallengev300Doc def createTransactionAfterChallengev300Doc = MessageDoc( process = "obp.createTransactionAfterChallengev300", @@ -2430,87 +3134,93 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - transReqId=TransactionRequestId("string"), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transReqId=TransactionRequestId(transactionRequestIdExample.value), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value)) ), exampleInboundMessage = ( InBoundCreateTransactionAfterChallengev300(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= TransactionRequest(id=TransactionRequestId("string"), + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -2525,7 +3235,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createTransactionAfterChallengev300(initiator: User, fromAccount: BankAccount, transReqId: TransactionRequestId, transactionRequestType: TransactionRequestType, callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionAfterChallengev300 => OutBound, InBoundCreateTransactionAfterChallengev300 => InBound} + import com.openbankproject.commons.dto.{InBoundCreateTransactionAfterChallengev300 => InBound, OutBoundCreateTransactionAfterChallengev300 => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, fromAccount, transReqId, transactionRequestType) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionRequest](callContext)) @@ -2543,63 +3253,72 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - toCounterparty= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + toCounterparty= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=counterpartyNameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=counterpartyOtherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=counterpartyOtherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=counterpartyOtherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, + otherBankRoutingAddress=counterpartyOtherBankRoutingAddressExample.value, + otherBranchRoutingScheme=counterpartyOtherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=counterpartyOtherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( InBoundMakePaymentv300(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -2610,108 +3329,12 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def makePaymentv300(initiator: User, fromAccount: BankAccount, toAccount: BankAccount, toCounterparty: CounterpartyTrait, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, transactionRequestType: TransactionRequestType, chargePolicy: String, callContext: Option[CallContext]): Future[Box[(TransactionId, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundMakePaymentv300 => OutBound, InBoundMakePaymentv300 => InBound} + import com.openbankproject.commons.dto.{InBoundMakePaymentv300 => InBound, OutBoundMakePaymentv300 => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, fromAccount, toAccount, toCounterparty, transactionRequestCommonBody, transactionRequestType, chargePolicy) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionId](callContext)) } - - messageDocs += makePaymentV400Doc - def makePaymentV400Doc = MessageDoc( - process = "obp.makePaymentV400", - messageFormat = messageFormat, - description = "Make Payment V400", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundMakePaymentV400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - transactionRequest= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), - `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id=bank_idExample.value, - account_id=account_idExample.value), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, - account_id=account_idExample.value)), - to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), - to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), - to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount=amountExample.value), - description=descriptionExample.value, - message=messageExample.value, - from= FromAccountTransfer(mobile_phone_number="string", - nickname=nicknameExample.value), - to=ToAccountTransferToPhone(toExample.value))), - to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount=amountExample.value), - description=descriptionExample.value, - message=messageExample.value, - from= FromAccountTransfer(mobile_phone_number="string", - nickname=nicknameExample.value), - to= ToAccountTransferToAtm(legal_name="string", - date_of_birth="string", - mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, - number=numberExample.value)))), - to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount=amountExample.value), - description=descriptionExample.value, - transfer_type="string", - future_date="string", - to= ToAccountTransferToAccount(name=nameExample.value, - bank_code="string", - branch_number="string", - account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, - iban=ibanExample.value)))), - to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), - instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount=amountExample.value), - creditorAccount=PaymentAccount("string"), - creditorName="string")), - value= AmountOfMoney(currency=currencyExample.value, - amount=amountExample.value), - description=descriptionExample.value), - transaction_ids="string", - status=statusExample.value, - start_date=toDate(transactionRequestStartDateExample), - end_date=toDate(transactionRequestEndDateExample), - challenge= TransactionRequestChallenge(id=challengeIdExample.value, - allowed_attempts=123, - challenge_type="string"), - charge= TransactionRequestCharge(summary=summaryExample.value, - value= AmountOfMoney(currency=currencyExample.value, - amount=amountExample.value)), - charge_policy="string", - counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), - name=nameExample.value, - this_bank_id=BankId(bankIdExample.value), - this_account_id=AccountId(accountIdExample.value), - this_view_id=ViewId(viewIdExample.value), - other_account_routing_scheme="string", - other_account_routing_address="string", - other_bank_routing_scheme="string", - other_bank_routing_address="string", - is_beneficiary=true, - future_date=Some("string")), - reasons=Some(List( TransactionRequestReason(code=codeExample.value, - documentNumber=Some(documentNumberExample.value), - amount=Some(amountExample.value), - currency=Some(currencyExample.value), - description=Some(descriptionExample.value))))) - ), - exampleInboundMessage = ( - InBoundMakePaymentV400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, - status=MessageDocsSwaggerDefinitions.inboundStatus, - data=TransactionId(transactionIdExample.value)) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - - override def makePaymentV400(transactionRequest: TransactionRequest, reasons: Option[List[TransactionRequestReason]], callContext: Option[CallContext]): Future[Box[(TransactionId, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{InBoundMakePaymentV400 => InBound, OutBoundMakePaymentV400 => OutBound} - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequest, reasons) - val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) - response.map(convertToTuple[TransactionId](callContext)) - } - + messageDocs += createTransactionRequestv300Doc def createTransactionRequestv300Doc = MessageDoc( process = "obp.createTransactionRequestv300", @@ -2724,126 +3347,135 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - toCounterparty= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + toCounterparty= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=counterpartyNameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=counterpartyOtherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=counterpartyOtherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=counterpartyOtherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, + otherBankRoutingAddress=counterpartyOtherBankRoutingAddressExample.value, + otherBranchRoutingScheme=counterpartyOtherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=counterpartyOtherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), detailsPlain="string", - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( InBoundCreateTransactionRequestv300(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= TransactionRequest(id=TransactionRequestId("string"), + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -2858,12 +3490,135 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createTransactionRequestv300(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, toCounterparty: CounterpartyTrait, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, callContext: Option[CallContext]): Future[Box[(TransactionRequest, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionRequestv300 => OutBound, InBoundCreateTransactionRequestv300 => InBound} + import com.openbankproject.commons.dto.{InBoundCreateTransactionRequestv300 => InBound, OutBoundCreateTransactionRequestv300 => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, viewId, fromAccount, toAccount, toCounterparty, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionRequest](callContext)) } + messageDocs += makePaymentV400Doc + def makePaymentV400Doc = MessageDoc( + process = "obp.makePaymentV400", + messageFormat = messageFormat, + description = "Make Payment V400", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundMakePaymentV400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequest= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), + `type`=transactionRequestTypeExample.value, + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), + to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), + to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to= ToAccountTransferToAtm(legal_name="string", + date_of_birth="string", + mobile_phone_number="string", + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), + to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + transfer_type="string", + future_date="string", + to= ToAccountTransferToAccount(name=nameExample.value, + bank_code="string", + branch_number="string", + account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, + iban=ibanExample.value)))), + to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), + instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + creditorAccount=PaymentAccount("string"), + creditorName="string")), + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value), + transaction_ids="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, + allowed_attempts=123, + challenge_type="string"), + charge= TransactionRequestCharge(summary=summaryExample.value, + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value)), + charge_policy="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, + this_bank_id=BankId(bankIdExample.value), + this_account_id=AccountId(accountIdExample.value), + this_view_id=ViewId(viewIdExample.value), + other_account_routing_scheme="string", + other_account_routing_address="string", + other_bank_routing_scheme="string", + other_bank_routing_address="string", + is_beneficiary=true, + future_date=Some("string")), + reasons=Some(List( TransactionRequestReason(code=codeExample.value, + documentNumber=Some(documentNumberExample.value), + amount=Some(amountExample.value), + currency=Some(currencyExample.value), + description=Some(descriptionExample.value))))) + ), + exampleInboundMessage = ( + InBoundMakePaymentV400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=TransactionId(transactionIdExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def makePaymentV400(transactionRequest: TransactionRequest, reasons: Option[List[TransactionRequestReason]], callContext: Option[CallContext]): Future[Box[(TransactionId, Option[CallContext])]] = { + import com.openbankproject.commons.dto.{InBoundMakePaymentV400 => InBound, OutBoundMakePaymentV400 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequest, reasons) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[TransactionId](callContext)) + } + + messageDocs += cancelPaymentV400Doc + def cancelPaymentV400Doc = MessageDoc( + process = "obp.cancelPaymentV400", + messageFormat = messageFormat, + description = "Cancel Payment V400", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCancelPaymentV400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionId=TransactionId(transactionIdExample.value)) + ), + exampleInboundMessage = ( + InBoundCancelPaymentV400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CancelPayment(canBeCancelled=true, + startSca=Some(true))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def cancelPaymentV400(transactionId: TransactionId, callContext: Option[CallContext]): OBPReturnType[Box[CancelPayment]] = { + import com.openbankproject.commons.dto.{InBoundCancelPaymentV400 => InBound, OutBoundCancelPaymentV400 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionId) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[CancelPayment](callContext)) + } + messageDocs += createCounterpartyDoc def createCounterpartyDoc = MessageDoc( process = "obp.createCounterparty", @@ -2873,21 +3628,21 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundCreateCounterparty(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - name="string", - description="string", + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - createdByUserId="string", - thisBankId="string", - thisAccountId="string", - thisViewId="string", - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + createdByUserId=createdByUserIdExample.value, + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))) @@ -2895,22 +3650,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundCreateCounterparty(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) @@ -2919,7 +3674,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createCounterparty(name: String, description: String, currency: String, createdByUserId: String, thisBankId: String, thisAccountId: String, thisViewId: String, otherAccountRoutingScheme: String, otherAccountRoutingAddress: String, otherAccountSecondaryRoutingScheme: String, otherAccountSecondaryRoutingAddress: String, otherBankRoutingScheme: String, otherBankRoutingAddress: String, otherBranchRoutingScheme: String, otherBranchRoutingAddress: String, isBeneficiary: Boolean, bespoke: List[CounterpartyBespoke], callContext: Option[CallContext]): Box[(CounterpartyTrait, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundCreateCounterparty => OutBound, InBoundCreateCounterparty => InBound} + import com.openbankproject.commons.dto.{InBoundCreateCounterparty => InBound, OutBoundCreateCounterparty => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, name, description, currency, createdByUserId, thisBankId, thisAccountId, thisViewId, otherAccountRoutingScheme, otherAccountRoutingAddress, otherAccountSecondaryRoutingScheme, otherAccountSecondaryRoutingAddress, otherBankRoutingScheme, otherBankRoutingAddress, otherBranchRoutingScheme, otherBranchRoutingAddress, isBeneficiary, bespoke) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CounterpartyTraitCommons](callContext)) @@ -2946,7 +3701,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def checkCustomerNumberAvailable(bankId: BankId, customerNumber: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundCheckCustomerNumberAvailable => OutBound, InBoundCheckCustomerNumberAvailable => InBound} + import com.openbankproject.commons.dto.{InBoundCheckCustomerNumberAvailable => InBound, OutBoundCheckCustomerNumberAvailable => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerNumber) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -2965,16 +3720,16 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, highestEducationAttained=highestEducationAttainedExample.value, employmentStatus=employmentStatusExample.value, kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(outBoundCreateCustomerLastOkDateExample.value).getOrElse(sys.error("outBoundCreateCustomerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(outBoundCreateCustomerLastOkDateExample), creditRating=Some( CreditRating(rating=ratingExample.value, source=sourceExample.value)), creditLimit=Some( AmountOfMoney(currency=currencyExample.value, @@ -2992,9 +3747,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3005,7 +3760,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) @@ -3014,7 +3769,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createCustomer(bankId: BankId, legalName: String, mobileNumber: String, email: String, faceImage: CustomerFaceImageTrait, dateOfBirth: Date, relationshipStatus: String, dependents: Int, dobOfDependents: List[Date], highestEducationAttained: String, employmentStatus: String, kycStatus: Boolean, lastOkDate: Date, creditRating: Option[CreditRatingTrait], creditLimit: Option[AmountOfMoneyTrait], title: String, branchId: String, nameSuffix: String, callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundCreateCustomer => OutBound, InBoundCreateCustomer => InBound} + import com.openbankproject.commons.dto.{InBoundCreateCustomer => InBound, OutBoundCreateCustomer => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, legalName, mobileNumber, email, faceImage, dateOfBirth, relationshipStatus, dependents, dobOfDependents, highestEducationAttained, employmentStatus, kycStatus, lastOkDate, creditRating, creditLimit, title, branchId, nameSuffix) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerCommons](callContext)) @@ -3043,9 +3798,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3056,7 +3811,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) @@ -3065,7 +3820,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def updateCustomerScaData(customerId: String, mobileNumber: Option[String], email: Option[String], customerNumber: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerScaData => OutBound, InBoundUpdateCustomerScaData => InBound} + import com.openbankproject.commons.dto.{InBoundUpdateCustomerScaData => InBound, OutBoundUpdateCustomerScaData => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, mobileNumber, email, customerNumber) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerCommons](callContext)) @@ -3081,7 +3836,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundUpdateCustomerCreditData(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, - creditRating=Some("string"), + creditRating=Some(creditRatingExample.value), creditSource=Some("string"), creditLimit=Some( AmountOfMoney(currency=currencyExample.value, amount=creditLimitAmountExample.value))) @@ -3095,9 +3850,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3108,7 +3863,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) @@ -3117,7 +3872,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def updateCustomerCreditData(customerId: String, creditRating: Option[String], creditSource: Option[String], creditLimit: Option[AmountOfMoney], callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerCreditData => OutBound, InBoundUpdateCustomerCreditData => InBound} + import com.openbankproject.commons.dto.{InBoundUpdateCustomerCreditData => InBound, OutBoundUpdateCustomerCreditData => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, creditRating, creditSource, creditLimit) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerCommons](callContext)) @@ -3134,9 +3889,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundUpdateCustomerGeneralData(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, legalName=Some(legalNameExample.value), - faceImage=Some( CustomerFaceImage(date=new Date(), + faceImage=Some( CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value)), - dateOfBirth=Some(parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format."))), + dateOfBirth=Some(toDate(dateOfBirthExample)), relationshipStatus=Some(relationshipStatusExample.value), dependents=Some(dependentsExample.value.toInt), highestEducationAttained=Some(highestEducationAttainedExample.value), @@ -3154,9 +3909,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3167,7 +3922,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) @@ -3176,7 +3931,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def updateCustomerGeneralData(customerId: String, legalName: Option[String], faceImage: Option[CustomerFaceImageTrait], dateOfBirth: Option[Date], relationshipStatus: Option[String], dependents: Option[Int], highestEducationAttained: Option[String], employmentStatus: Option[String], title: Option[String], branchId: Option[String], nameSuffix: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerGeneralData => OutBound, InBoundUpdateCustomerGeneralData => InBound} + import com.openbankproject.commons.dto.{InBoundUpdateCustomerGeneralData => InBound, OutBoundUpdateCustomerGeneralData => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, legalName, faceImage, dateOfBirth, relationshipStatus, dependents, highestEducationAttained, employmentStatus, title, branchId, nameSuffix) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerCommons](callContext)) @@ -3202,9 +3957,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3215,7 +3970,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) @@ -3224,7 +3979,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomerByCustomerId(customerId: String, callContext: Option[CallContext]): Future[Box[(Customer, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerByCustomerId => OutBound, InBoundGetCustomerByCustomerId => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerByCustomerId => InBound, OutBoundGetCustomerByCustomerId => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerCommons](callContext)) @@ -3251,9 +4006,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3264,7 +4019,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) @@ -3273,7 +4028,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomerByCustomerNumber(customerNumber: String, bankId: BankId, callContext: Option[CallContext]): Future[Box[(Customer, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerByCustomerNumber => OutBound, InBoundGetCustomerByCustomerNumber => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerByCustomerNumber => InBound, OutBoundGetCustomerByCustomerNumber => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerNumber, bankId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerCommons](callContext)) @@ -3294,24 +4049,24 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { InBoundGetCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CustomerAddressCommons(customerId=customerIdExample.value, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - status="string", - tags="string", - insertDate=new Date()))) + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + status=statusExample.value, + tags=tagsExample.value, + insertDate=toDate(insertDateExample)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getCustomerAddress(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAddress]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerAddress => OutBound, InBoundGetCustomerAddress => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerAddress => InBound, OutBoundGetCustomerAddress => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CustomerAddressCommons]](callContext)) @@ -3327,39 +4082,39 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundCreateCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - tags="string", - status="string") + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + tags=tagsExample.value, + status=statusExample.value) ), exampleInboundMessage = ( InBoundCreateCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerAddressCommons(customerId=customerIdExample.value, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - status="string", - tags="string", - insertDate=new Date())) + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + status=statusExample.value, + tags=tagsExample.value, + insertDate=toDate(insertDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createCustomerAddress(customerId: String, line1: String, line2: String, line3: String, city: String, county: String, state: String, postcode: String, countryCode: String, tags: String, status: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAddress]] = { - import com.openbankproject.commons.dto.{OutBoundCreateCustomerAddress => OutBound, InBoundCreateCustomerAddress => InBound} + import com.openbankproject.commons.dto.{InBoundCreateCustomerAddress => InBound, OutBoundCreateCustomerAddress => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, line1, line2, line3, city, county, state, postcode, countryCode, tags, status) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerAddressCommons](callContext)) @@ -3374,40 +4129,40 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundUpdateCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - tags="string", - status="string") + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + tags=tagsExample.value, + status=statusExample.value) ), exampleInboundMessage = ( InBoundUpdateCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerAddressCommons(customerId=customerIdExample.value, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - status="string", - tags="string", - insertDate=new Date())) + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + status=statusExample.value, + tags=tagsExample.value, + insertDate=toDate(insertDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def updateCustomerAddress(customerAddressId: String, line1: String, line2: String, line3: String, city: String, county: String, state: String, postcode: String, countryCode: String, tags: String, status: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAddress]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerAddress => OutBound, InBoundUpdateCustomerAddress => InBound} + import com.openbankproject.commons.dto.{InBoundUpdateCustomerAddress => InBound, OutBoundUpdateCustomerAddress => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAddressId, line1, line2, line3, city, county, state, postcode, countryCode, tags, status) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerAddressCommons](callContext)) @@ -3422,7 +4177,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundDeleteCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - customerAddressId="string") + customerAddressId=customerAddressIdExample.value) ), exampleInboundMessage = ( InBoundDeleteCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -3433,7 +4188,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deleteCustomerAddress(customerAddressId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteCustomerAddress => OutBound, InBoundDeleteCustomerAddress => InBound} + import com.openbankproject.commons.dto.{InBoundDeleteCustomerAddress => InBound, OutBoundDeleteCustomerAddress => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAddressId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -3449,22 +4204,22 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundCreateTaxResidence(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, - domain="string", - taxNumber="string") + domain=domainExample.value, + taxNumber=taxNumberExample.value) ), exampleInboundMessage = ( InBoundCreateTaxResidence(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= TaxResidenceCommons(customerId=customerIdExample.value, - taxResidenceId="string", - domain="string", - taxNumber="string")) + taxResidenceId=taxResidenceIdExample.value, + domain=domainExample.value, + taxNumber=taxNumberExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createTaxResidence(customerId: String, domain: String, taxNumber: String, callContext: Option[CallContext]): OBPReturnType[Box[TaxResidence]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTaxResidence => OutBound, InBoundCreateTaxResidence => InBound} + import com.openbankproject.commons.dto.{InBoundCreateTaxResidence => InBound, OutBoundCreateTaxResidence => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, domain, taxNumber) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TaxResidenceCommons](callContext)) @@ -3485,15 +4240,15 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { InBoundGetTaxResidence(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( TaxResidenceCommons(customerId=customerIdExample.value, - taxResidenceId="string", - domain="string", - taxNumber="string"))) + taxResidenceId=taxResidenceIdExample.value, + domain=domainExample.value, + taxNumber=taxNumberExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getTaxResidence(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[TaxResidence]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTaxResidence => OutBound, InBoundGetTaxResidence => InBound} + import com.openbankproject.commons.dto.{InBoundGetTaxResidence => InBound, OutBoundGetTaxResidence => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[TaxResidenceCommons]](callContext)) @@ -3519,7 +4274,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deleteTaxResidence(taxResourceId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteTaxResidence => OutBound, InBoundDeleteTaxResidence => InBound} + import com.openbankproject.commons.dto.{InBoundDeleteTaxResidence => InBound, OutBoundDeleteTaxResidence => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, taxResourceId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -3537,8 +4292,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=BankId(bankIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( InBoundGetCustomers(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -3549,9 +4304,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3562,7 +4317,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value))) @@ -3571,7 +4326,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomers(bankId: BankId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Future[Box[List[Customer]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomers => OutBound, InBoundGetCustomers => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomers => InBound, OutBoundGetCustomers => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CustomerCommons]](callContext)) @@ -3587,7 +4342,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundGetCustomersByCustomerPhoneNumber(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), - phoneNumber="string") + phoneNumber=phoneNumberExample.value) ), exampleInboundMessage = ( InBoundGetCustomersByCustomerPhoneNumber(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -3598,9 +4353,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -3611,7 +4366,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value))) @@ -3620,7 +4375,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomersByCustomerPhoneNumber(bankId: BankId, phoneNumber: String, callContext: Option[CallContext]): OBPReturnType[Box[List[Customer]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomersByCustomerPhoneNumber => OutBound, InBoundGetCustomersByCustomerPhoneNumber => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomersByCustomerPhoneNumber => InBound, OutBoundGetCustomersByCustomerPhoneNumber => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, phoneNumber) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CustomerCommons]](callContext)) @@ -3641,18 +4396,18 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetCheckbookOrders(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= CheckbookOrdersJson(account= AccountV310Json(bank_id="string", - account_id="string", + data= CheckbookOrdersJson(account= AccountV310Json(bank_id=bank_idExample.value, + account_id=account_idExample.value, account_type="string", - account_routings=List( AccountRoutingJsonV121(scheme="string", - address="string")), - branch_routings=List( BranchRoutingJsonV141(scheme="string", - address="string"))), + account_routings=List( AccountRoutingJsonV121(scheme=schemeExample.value, + address=addressExample.value)), + branch_routings=List( BranchRoutingJsonV141(scheme=schemeExample.value, + address=addressExample.value))), orders=List(OrderJson( OrderObjectJson(order_id="string", order_date="string", number_of_checkbooks="string", distribution_channel="string", - status="string", + status=statusExample.value, first_check_number="string", shipping_code="string"))))) ), @@ -3660,7 +4415,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCheckbookOrders(bankId: String, accountId: String, callContext: Option[CallContext]): Future[Box[(CheckbookOrdersJson, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCheckbookOrders => OutBound, InBoundGetCheckbookOrders => InBound} + import com.openbankproject.commons.dto.{InBoundGetCheckbookOrders => InBound, OutBoundGetCheckbookOrders => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CheckbookOrdersJson](callContext)) @@ -3689,7 +4444,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getStatusOfCreditCardOrder(bankId: String, accountId: String, callContext: Option[CallContext]): Future[Box[(List[CardObjectJson], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetStatusOfCreditCardOrder => OutBound, InBoundGetStatusOfCreditCardOrder => InBound} + import com.openbankproject.commons.dto.{InBoundGetStatusOfCreditCardOrder => InBound, OutBoundGetStatusOfCreditCardOrder => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CardObjectJson]](callContext)) @@ -3711,7 +4466,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundCreateUserAuthContext(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= UserAuthContextCommons(userAuthContextId="string", + data= UserAuthContextCommons(userAuthContextId=userAuthContextIdExample.value, userId=userIdExample.value, key=keyExample.value, value=valueExample.value)) @@ -3720,7 +4475,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createUserAuthContext(userId: String, key: String, value: String, callContext: Option[CallContext]): OBPReturnType[Box[UserAuthContext]] = { - import com.openbankproject.commons.dto.{OutBoundCreateUserAuthContext => OutBound, InBoundCreateUserAuthContext => InBound} + import com.openbankproject.commons.dto.{InBoundCreateUserAuthContext => InBound, OutBoundCreateUserAuthContext => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId, key, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[UserAuthContextCommons](callContext)) @@ -3742,18 +4497,18 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundCreateUserAuthContextUpdate(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= UserAuthContextUpdateCommons(userAuthContextUpdateId="string", + data= UserAuthContextUpdateCommons(userAuthContextUpdateId=userAuthContextUpdateIdExample.value, userId=userIdExample.value, key=keyExample.value, value=valueExample.value, - challenge="string", - status="string")) + challenge=challengeExample.value, + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createUserAuthContextUpdate(userId: String, key: String, value: String, callContext: Option[CallContext]): OBPReturnType[Box[UserAuthContextUpdate]] = { - import com.openbankproject.commons.dto.{OutBoundCreateUserAuthContextUpdate => OutBound, InBoundCreateUserAuthContextUpdate => InBound} + import com.openbankproject.commons.dto.{InBoundCreateUserAuthContextUpdate => InBound, OutBoundCreateUserAuthContextUpdate => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId, key, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[UserAuthContextUpdateCommons](callContext)) @@ -3779,7 +4534,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deleteUserAuthContexts(userId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteUserAuthContexts => OutBound, InBoundDeleteUserAuthContexts => InBound} + import com.openbankproject.commons.dto.{InBoundDeleteUserAuthContexts => InBound, OutBoundDeleteUserAuthContexts => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -3794,7 +4549,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundDeleteUserAuthContextById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - userAuthContextId="string") + userAuthContextId=userAuthContextIdExample.value) ), exampleInboundMessage = ( InBoundDeleteUserAuthContextById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -3805,7 +4560,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deleteUserAuthContextById(userAuthContextId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteUserAuthContextById => OutBound, InBoundDeleteUserAuthContextById => InBound} + import com.openbankproject.commons.dto.{InBoundDeleteUserAuthContextById => InBound, OutBoundDeleteUserAuthContextById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userAuthContextId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -3825,7 +4580,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetUserAuthContexts(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( UserAuthContextCommons(userAuthContextId="string", + data=List( UserAuthContextCommons(userAuthContextId=userAuthContextIdExample.value, userId=userIdExample.value, key=keyExample.value, value=valueExample.value))) @@ -3834,7 +4589,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getUserAuthContexts(userId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[UserAuthContext]]] = { - import com.openbankproject.commons.dto.{OutBoundGetUserAuthContexts => OutBound, InBoundGetUserAuthContexts => InBound} + import com.openbankproject.commons.dto.{InBoundGetUserAuthContexts => InBound, OutBoundGetUserAuthContexts => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[UserAuthContextCommons]](callContext)) @@ -3850,9 +4605,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleOutboundMessage = ( OutBoundCreateOrUpdateProductAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId=Some("string"), - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=Some(productAttributeIdExample.value), + name=nameExample.value, productAttributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, value=valueExample.value) ), @@ -3860,17 +4615,18 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value)) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateProductAttribute => OutBound, InBoundCreateOrUpdateProductAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateProductAttribute => InBound, OutBoundCreateOrUpdateProductAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[ProductAttributeCommons](callContext)) @@ -3885,23 +4641,24 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetProductAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - productAttributeId="string") + productAttributeId=productAttributeIdExample.value) ), exampleInboundMessage = ( InBoundGetProductAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value)) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getProductAttributeById(productAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductAttributeById => OutBound, InBoundGetProductAttributeById => InBound} + import com.openbankproject.commons.dto.{InBoundGetProductAttributeById => InBound, OutBoundGetProductAttributeById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, productAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[ProductAttributeCommons](callContext)) @@ -3916,24 +4673,25 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetProductAttributesByBankAndCode(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - bank=BankId(bankIdExample.value), - productCode=ProductCode("string")) + bank=BankId(bankExample.value), + productCode=ProductCode(productCodeExample.value)) ), exampleInboundMessage = ( InBoundGetProductAttributesByBankAndCode(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getProductAttributesByBankAndCode(bank: BankId, productCode: ProductCode, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductAttributesByBankAndCode => OutBound, InBoundGetProductAttributesByBankAndCode => InBound} + import com.openbankproject.commons.dto.{InBoundGetProductAttributesByBankAndCode => InBound, OutBoundGetProductAttributesByBankAndCode => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bank, productCode) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[ProductAttributeCommons]](callContext)) @@ -3948,7 +4706,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundDeleteProductAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - productAttributeId="string") + productAttributeId=productAttributeIdExample.value) ), exampleInboundMessage = ( InBoundDeleteProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -3959,7 +4717,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deleteProductAttribute(productAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteProductAttribute => OutBound, InBoundDeleteProductAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundDeleteProductAttribute => InBound, OutBoundDeleteProductAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, productAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) @@ -3974,16 +4732,16 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetAccountAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - accountAttributeId="string") + accountAttributeId=accountAttributeIdExample.value) ), exampleInboundMessage = ( InBoundGetAccountAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value)) ), @@ -3991,7 +4749,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getAccountAttributeById(accountAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetAccountAttributeById => OutBound, InBoundGetAccountAttributeById => InBound} + import com.openbankproject.commons.dto.{InBoundGetAccountAttributeById => InBound, OutBoundGetAccountAttributeById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AccountAttributeCommons](callContext)) @@ -4022,7 +4780,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getTransactionAttributeById(transactionAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionAttributeById => OutBound, InBoundGetTransactionAttributeById => InBound} + import com.openbankproject.commons.dto.{InBoundGetTransactionAttributeById => InBound, OutBoundGetTransactionAttributeById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionAttributeCommons](callContext)) @@ -4039,9 +4797,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateOrUpdateAccountAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - productAttributeId=Some("string"), - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=Some(productAttributeIdExample.value), + name=nameExample.value, accountAttributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value) ), @@ -4050,9 +4808,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { status=MessageDocsSwaggerDefinitions.inboundStatus, data= AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value)) ), @@ -4060,7 +4818,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createOrUpdateAccountAttribute(bankId: BankId, accountId: AccountId, productCode: ProductCode, productAttributeId: Option[String], name: String, accountAttributeType: AccountAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateAccountAttribute => OutBound, InBoundCreateOrUpdateAccountAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateAccountAttribute => InBound, OutBoundCreateOrUpdateAccountAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, productCode, productAttributeId, name, accountAttributeType, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AccountAttributeCommons](callContext)) @@ -4078,7 +4836,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=BankId(bankIdExample.value), customerId=CustomerId(customerIdExample.value), customerAttributeId=Some(customerAttributeIdExample.value), - name="string", + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.CustomerAttributeType.example, value=valueExample.value) ), @@ -4096,7 +4854,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createOrUpdateCustomerAttribute(bankId: BankId, customerId: CustomerId, customerAttributeId: Option[String], name: String, attributeType: CustomerAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateCustomerAttribute => OutBound, InBoundCreateOrUpdateCustomerAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateCustomerAttribute => InBound, OutBoundCreateOrUpdateCustomerAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, customerAttributeId, name, attributeType, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerAttributeCommons](callContext)) @@ -4114,7 +4872,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=BankId(bankIdExample.value), transactionId=TransactionId(transactionIdExample.value), transactionAttributeId=Some(transactionAttributeIdExample.value), - name="string", + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.TransactionAttributeType.example, value=valueExample.value) ), @@ -4132,7 +4890,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createOrUpdateTransactionAttribute(bankId: BankId, transactionId: TransactionId, transactionAttributeId: Option[String], name: String, attributeType: TransactionAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateTransactionAttribute => OutBound, InBoundCreateOrUpdateTransactionAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateTransactionAttribute => InBound, OutBoundCreateOrUpdateTransactionAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, transactionId, transactionAttributeId, name, attributeType, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionAttributeCommons](callContext)) @@ -4149,22 +4907,23 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateAccountAttributes(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), + productCode=ProductCode(productCodeExample.value), accountAttributes=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))) ), exampleInboundMessage = ( InBoundCreateAccountAttributes(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value))) ), @@ -4172,7 +4931,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createAccountAttributes(bankId: BankId, accountId: AccountId, productCode: ProductCode, accountAttributes: List[ProductAttribute], callContext: Option[CallContext]): OBPReturnType[Box[List[AccountAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundCreateAccountAttributes => OutBound, InBoundCreateAccountAttributes => InBound} + import com.openbankproject.commons.dto.{InBoundCreateAccountAttributes => InBound, OutBoundCreateAccountAttributes => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, productCode, accountAttributes) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[AccountAttributeCommons]](callContext)) @@ -4195,9 +4954,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value))) ), @@ -4205,7 +4964,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getAccountAttributesByAccount(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[List[AccountAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetAccountAttributesByAccount => OutBound, InBoundGetAccountAttributesByAccount => InBound} + import com.openbankproject.commons.dto.{InBoundGetAccountAttributesByAccount => InBound, OutBoundGetAccountAttributesByAccount => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[AccountAttributeCommons]](callContext)) @@ -4237,7 +4996,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomerAttributes(bankId: BankId, customerId: CustomerId, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerAttributes => OutBound, InBoundGetCustomerAttributes => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerAttributes => InBound, OutBoundGetCustomerAttributes => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CustomerAttributeCommons]](callContext)) @@ -4258,13 +5017,13 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetCustomerIdsByAttributeNameValues(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List("string")) + data=listExample.value.split("[,;]").toList) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getCustomerIdsByAttributeNameValues(bankId: BankId, nameValues: Map[String,List[String]], callContext: Option[CallContext]): OBPReturnType[Box[List[String]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerIdsByAttributeNameValues => OutBound, InBoundGetCustomerIdsByAttributeNameValues => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerIdsByAttributeNameValues => InBound, OutBoundGetCustomerIdsByAttributeNameValues => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, nameValues) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[String]](callContext)) @@ -4285,9 +5044,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -4298,7 +5057,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value))) @@ -4306,7 +5065,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetCustomerAttributesForCustomers(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data = List( + data= List( CustomerAndAttribute( MessageDocsSwaggerDefinitions.customerCommons, List(MessageDocsSwaggerDefinitions.customerAttribute) @@ -4318,10 +5077,10 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomerAttributesForCustomers(customers: List[Customer], callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAndAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerAttributesForCustomers => OutBound, InBoundGetCustomerAttributesForCustomers => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerAttributesForCustomers => InBound, OutBoundGetCustomerAttributesForCustomers => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customers) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) - response.map(convertToTuple[List[CustomerAndAttribute]](callContext)) + response.map(convertToTuple[List[CustomerAndAttribute]](callContext)) } messageDocs += getTransactionIdsByAttributeNameValuesDoc @@ -4339,13 +5098,13 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetTransactionIdsByAttributeNameValues(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List("string")) + data=listExample.value.split("[,;]").toList) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getTransactionIdsByAttributeNameValues(bankId: BankId, nameValues: Map[String,List[String]], callContext: Option[CallContext]): OBPReturnType[Box[List[String]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionIdsByAttributeNameValues => OutBound, InBoundGetTransactionIdsByAttributeNameValues => InBound} + import com.openbankproject.commons.dto.{InBoundGetTransactionIdsByAttributeNameValues => InBound, OutBoundGetTransactionIdsByAttributeNameValues => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, nameValues) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[String]](callContext)) @@ -4377,7 +5136,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getTransactionAttributes(bankId: BankId, transactionId: TransactionId, callContext: Option[CallContext]): OBPReturnType[Box[List[TransactionAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionAttributes => OutBound, InBoundGetTransactionAttributes => InBound} + import com.openbankproject.commons.dto.{InBoundGetTransactionAttributes => InBound, OutBoundGetTransactionAttributes => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, transactionId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[TransactionAttributeCommons]](callContext)) @@ -4408,7 +5167,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCustomerAttributeById(customerAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerAttributeById => OutBound, InBoundGetCustomerAttributeById => InBound} + import com.openbankproject.commons.dto.{InBoundGetCustomerAttributeById => InBound, OutBoundGetCustomerAttributeById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerAttributeCommons](callContext)) @@ -4426,7 +5185,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=Some(BankId(bankIdExample.value)), cardId=Some(cardIdExample.value), cardAttributeId=Some(cardAttributeIdExample.value), - name="string", + name=nameExample.value, cardAttributeType=com.openbankproject.commons.model.enums.CardAttributeType.example, value=valueExample.value) ), @@ -4444,7 +5203,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def createOrUpdateCardAttribute(bankId: Option[BankId], cardId: Option[String], cardAttributeId: Option[String], name: String, cardAttributeType: CardAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[CardAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateCardAttribute => OutBound, InBoundCreateOrUpdateCardAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateCardAttribute => InBound, OutBoundCreateOrUpdateCardAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, cardId, cardAttributeId, name, cardAttributeType, value) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CardAttributeCommons](callContext)) @@ -4475,7 +5234,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCardAttributeById(cardAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[CardAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetCardAttributeById => OutBound, InBoundGetCardAttributeById => InBound} + import com.openbankproject.commons.dto.{InBoundGetCardAttributeById => InBound, OutBoundGetCardAttributeById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, cardAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CardAttributeCommons](callContext)) @@ -4506,7 +5265,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def getCardAttributesFromProvider(cardId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CardAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCardAttributesFromProvider => OutBound, InBoundGetCardAttributesFromProvider => InBound} + import com.openbankproject.commons.dto.{InBoundGetCardAttributesFromProvider => InBound, OutBoundGetCardAttributesFromProvider => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, cardId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[CardAttributeCommons]](callContext)) @@ -4521,25 +5280,25 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundCreateAccountApplication(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - productCode=ProductCode("string"), + productCode=ProductCode(productCodeExample.value), userId=Some(userIdExample.value), customerId=Some(customerIdExample.value)) ), exampleInboundMessage = ( InBoundCreateAccountApplication(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + data= AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string")) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createAccountApplication(productCode: ProductCode, userId: Option[String], customerId: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[AccountApplication]] = { - import com.openbankproject.commons.dto.{OutBoundCreateAccountApplication => OutBound, InBoundCreateAccountApplication => InBound} + import com.openbankproject.commons.dto.{InBoundCreateAccountApplication => InBound, OutBoundCreateAccountApplication => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, productCode, userId, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AccountApplicationCommons](callContext)) @@ -4558,18 +5317,18 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetAllAccountApplication(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + data=List( AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string"))) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getAllAccountApplication(callContext: Option[CallContext]): OBPReturnType[Box[List[AccountApplication]]] = { - import com.openbankproject.commons.dto.{OutBoundGetAllAccountApplication => OutBound, InBoundGetAllAccountApplication => InBound} + import com.openbankproject.commons.dto.{InBoundGetAllAccountApplication => InBound, OutBoundGetAllAccountApplication => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[AccountApplicationCommons]](callContext)) @@ -4584,23 +5343,23 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetAccountApplicationById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - accountApplicationId="string") + accountApplicationId=accountApplicationIdExample.value) ), exampleInboundMessage = ( InBoundGetAccountApplicationById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + data= AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string")) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getAccountApplicationById(accountApplicationId: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountApplication]] = { - import com.openbankproject.commons.dto.{OutBoundGetAccountApplicationById => OutBound, InBoundGetAccountApplicationById => InBound} + import com.openbankproject.commons.dto.{InBoundGetAccountApplicationById => InBound, OutBoundGetAccountApplicationById => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountApplicationId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AccountApplicationCommons](callContext)) @@ -4615,24 +5374,24 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundUpdateAccountApplicationStatus(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - accountApplicationId="string", - status="string") + accountApplicationId=accountApplicationIdExample.value, + status=statusExample.value) ), exampleInboundMessage = ( InBoundUpdateAccountApplicationStatus(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + data= AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string")) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def updateAccountApplicationStatus(accountApplicationId: String, status: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountApplication]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateAccountApplicationStatus => OutBound, InBoundUpdateAccountApplicationStatus => InBound} + import com.openbankproject.commons.dto.{InBoundUpdateAccountApplicationStatus => InBound, OutBoundUpdateAccountApplicationStatus => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountApplicationId, status) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[AccountApplicationCommons](callContext)) @@ -4647,20 +5406,20 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetOrCreateProductCollection(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - collectionCode="string", - productCodes=List("string")) + collectionCode=collectionCodeExample.value, + productCodes=listExample.value.split("[,;]").toList) ), exampleInboundMessage = ( InBoundGetOrCreateProductCollection(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( ProductCollectionCommons(collectionCode="string", - productCode="string"))) + data=List( ProductCollectionCommons(collectionCode=collectionCodeExample.value, + productCode=productCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getOrCreateProductCollection(collectionCode: String, productCodes: List[String], callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollection]]] = { - import com.openbankproject.commons.dto.{OutBoundGetOrCreateProductCollection => OutBound, InBoundGetOrCreateProductCollection => InBound} + import com.openbankproject.commons.dto.{InBoundGetOrCreateProductCollection => InBound, OutBoundGetOrCreateProductCollection => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, productCodes) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[ProductCollectionCommons]](callContext)) @@ -4675,19 +5434,19 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetProductCollection(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - collectionCode="string") + collectionCode=collectionCodeExample.value) ), exampleInboundMessage = ( InBoundGetProductCollection(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( ProductCollectionCommons(collectionCode="string", - productCode="string"))) + data=List( ProductCollectionCommons(collectionCode=collectionCodeExample.value, + productCode=productCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getProductCollection(collectionCode: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollection]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductCollection => OutBound, InBoundGetProductCollection => InBound} + import com.openbankproject.commons.dto.{InBoundGetProductCollection => InBound, OutBoundGetProductCollection => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[ProductCollectionCommons]](callContext)) @@ -4702,20 +5461,20 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetOrCreateProductCollectionItem(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - collectionCode="string", - memberProductCodes=List("string")) + collectionCode=collectionCodeExample.value, + memberProductCodes=listExample.value.split("[,;]").toList) ), exampleInboundMessage = ( InBoundGetOrCreateProductCollectionItem(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( ProductCollectionItemCommons(collectionCode="string", - memberProductCode="string"))) + data=List( ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + memberProductCode=memberProductCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getOrCreateProductCollectionItem(collectionCode: String, memberProductCodes: List[String], callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItem]]] = { - import com.openbankproject.commons.dto.{OutBoundGetOrCreateProductCollectionItem => OutBound, InBoundGetOrCreateProductCollectionItem => InBound} + import com.openbankproject.commons.dto.{InBoundGetOrCreateProductCollectionItem => InBound, OutBoundGetOrCreateProductCollectionItem => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, memberProductCodes) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[ProductCollectionItemCommons]](callContext)) @@ -4730,24 +5489,24 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetProductCollectionItem(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - collectionCode="string") + collectionCode=collectionCodeExample.value) ), exampleInboundMessage = ( InBoundGetProductCollectionItem(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( ProductCollectionItemCommons(collectionCode="string", - memberProductCode="string"))) + data=List( ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + memberProductCode=memberProductCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getProductCollectionItem(collectionCode: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItem]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductCollectionItem => OutBound, InBoundGetProductCollectionItem => InBound} + import com.openbankproject.commons.dto.{InBoundGetProductCollectionItem => InBound, OutBoundGetProductCollectionItem => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[ProductCollectionItemCommons]](callContext)) } - + messageDocs += getProductCollectionItemsTreeDoc def getProductCollectionItemsTreeDoc = MessageDoc( process = "obp.getProductCollectionItemsTree", @@ -4757,41 +5516,42 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { inboundTopic = None, exampleOutboundMessage = ( OutBoundGetProductCollectionItemsTree(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - collectionCode="string", + collectionCode=collectionCodeExample.value, bankId=bankIdExample.value) ), exampleInboundMessage = ( InBoundGetProductCollectionItemsTree(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List(ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode="string", - memberProductCode="string"), - product= ProductCommons(bankId=BankId(bankIdExample.value), - code=ProductCode("string"), - parentProductCode=ProductCode("string"), - name="string", - category="string", - family="string", - superFamily="string", - moreInfoUrl="string", - details="string", - description="string", - meta=Meta( License(id="string", - name="string"))), - attributes=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", - attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))))) + data=List( ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + memberProductCode=memberProductCodeExample.value), + product= ProductCommons(bankId=BankId(bankIdExample.value), + code=ProductCode(productCodeExample.value), + parentProductCode=ProductCode(parentProductCodeExample.value), + name=nameExample.value, + category=categoryExample.value, + family=familyExample.value, + superFamily=superFamilyExample.value, + moreInfoUrl=moreInfoUrlExample.value, + details=detailsExample.value, + description=descriptionExample.value, + meta=Meta( License(id=idExample.value, + name=nameExample.value))), + attributes=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, + attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getProductCollectionItemsTree(collectionCode: String, bankId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItemsTree]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductCollectionItemsTree => OutBound, InBoundGetProductCollectionItemsTree => InBound} + import com.openbankproject.commons.dto.{InBoundGetProductCollectionItemsTree => InBound, OutBoundGetProductCollectionItemsTree => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, bankId) - val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) - response.map(convertToTuple[List[ProductCollectionItemsTree]](callContext)) + val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) + response.map(convertToTuple[List[ProductCollectionItemsTree]](callContext)) } messageDocs += createMeetingDoc @@ -4807,55 +5567,61 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { staffUser= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), customerUser= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), - providerId="string", - purposeId="string", - when=new Date(), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, + when=toDate(whenExample), sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string", - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value, + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string"))) + status=statusExample.value))) ), exampleInboundMessage = ( InBoundCreateMeeting(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= MeetingCommons(meetingId="string", - providerId="string", - purposeId="string", + data= MeetingCommons(meetingId=meetingIdExample.value, + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, bankId=bankIdExample.value, - present= MeetingPresent(staffUserId="string", - customerUserId="string"), + present= MeetingPresent(staffUserId=staffUserIdExample.value, + customerUserId=customerUserIdExample.value), keys= MeetingKeys(sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string"), - when=new Date(), - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value), + when=toDate(whenExample), + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string")))) + status=statusExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createMeeting(bankId: BankId, staffUser: User, customerUser: User, providerId: String, purposeId: String, when: Date, sessionId: String, customerToken: String, staffToken: String, creator: ContactDetails, invitees: List[Invitee], callContext: Option[CallContext]): OBPReturnType[Box[Meeting]] = { - import com.openbankproject.commons.dto.{OutBoundCreateMeeting => OutBound, InBoundCreateMeeting => InBound} + import com.openbankproject.commons.dto.{InBoundCreateMeeting => InBound, OutBoundCreateMeeting => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, staffUser, customerUser, providerId, purposeId, when, sessionId, customerToken, staffToken, creator, invitees) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[MeetingCommons](callContext)) @@ -4874,36 +5640,39 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value)) + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true))) ), exampleInboundMessage = ( InBoundGetMeetings(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( MeetingCommons(meetingId="string", - providerId="string", - purposeId="string", + data=List( MeetingCommons(meetingId=meetingIdExample.value, + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, bankId=bankIdExample.value, - present= MeetingPresent(staffUserId="string", - customerUserId="string"), + present= MeetingPresent(staffUserId=staffUserIdExample.value, + customerUserId=customerUserIdExample.value), keys= MeetingKeys(sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string"), - when=new Date(), - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value), + when=toDate(whenExample), + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string"))))) + status=statusExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getMeetings(bankId: BankId, user: User, callContext: Option[CallContext]): OBPReturnType[Box[List[Meeting]]] = { - import com.openbankproject.commons.dto.{OutBoundGetMeetings => OutBound, InBoundGetMeetings => InBound} + import com.openbankproject.commons.dto.{InBoundGetMeetings => InBound, OutBoundGetMeetings => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, user) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[MeetingCommons]](callContext)) @@ -4922,37 +5691,40 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), - meetingId="string") + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), + meetingId=meetingIdExample.value) ), exampleInboundMessage = ( InBoundGetMeeting(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= MeetingCommons(meetingId="string", - providerId="string", - purposeId="string", + data= MeetingCommons(meetingId=meetingIdExample.value, + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, bankId=bankIdExample.value, - present= MeetingPresent(staffUserId="string", - customerUserId="string"), + present= MeetingPresent(staffUserId=staffUserIdExample.value, + customerUserId=customerUserIdExample.value), keys= MeetingKeys(sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string"), - when=new Date(), - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value), + when=toDate(whenExample), + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string")))) + status=statusExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getMeeting(bankId: BankId, user: User, meetingId: String, callContext: Option[CallContext]): OBPReturnType[Box[Meeting]] = { - import com.openbankproject.commons.dto.{OutBoundGetMeeting => OutBound, InBoundGetMeeting => InBound} + import com.openbankproject.commons.dto.{InBoundGetMeeting => InBound, OutBoundGetMeeting => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, user, meetingId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[MeetingCommons](callContext)) @@ -4969,14 +5741,14 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateOrUpdateKycCheck(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, - id="string", + id=idExample.value, customerNumber=customerNumberExample.value, - date=new Date(), - how="string", - staffUserId="string", + date=toDate(dateExample), + how=howExample.value, + staffUserId=staffUserIdExample.value, mStaffName="string", mSatisfied=true, - comments="string") + comments=commentsExample.value) ), exampleInboundMessage = ( InBoundCreateOrUpdateKycCheck(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -4985,18 +5757,18 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, idKycCheck="string", customerNumber=customerNumberExample.value, - date=new Date(), - how="string", - staffUserId="string", - staffName="string", - satisfied=true, - comments="string")) + date=toDate(dateExample), + how=howExample.value, + staffUserId=staffUserIdExample.value, + staffName=staffNameExample.value, + satisfied=satisfiedExample.value.toBoolean, + comments=commentsExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createOrUpdateKycCheck(bankId: String, customerId: String, id: String, customerNumber: String, date: Date, how: String, staffUserId: String, mStaffName: String, mSatisfied: Boolean, comments: String, callContext: Option[CallContext]): OBPReturnType[Box[KycCheck]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycCheck => OutBound, InBoundCreateOrUpdateKycCheck => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycCheck => InBound, OutBoundCreateOrUpdateKycCheck => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, id, customerNumber, date, how, staffUserId, mStaffName, mSatisfied, comments) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[KycCheckCommons](callContext)) @@ -5013,13 +5785,13 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateOrUpdateKycDocument(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, - id="string", + id=idExample.value, customerNumber=customerNumberExample.value, - `type`="string", - number="string", - issueDate=new Date(), - issuePlace="string", - expiryDate=new Date()) + `type`=typeExample.value, + number=numberExample.value, + issueDate=toDate(issueDateExample), + issuePlace=issuePlaceExample.value, + expiryDate=toDate(expiryDateExample)) ), exampleInboundMessage = ( InBoundCreateOrUpdateKycDocument(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -5028,17 +5800,17 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, idKycDocument="string", customerNumber=customerNumberExample.value, - `type`="string", - number="string", - issueDate=new Date(), - issuePlace="string", - expiryDate=new Date())) + `type`=typeExample.value, + number=numberExample.value, + issueDate=toDate(issueDateExample), + issuePlace=issuePlaceExample.value, + expiryDate=toDate(expiryDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createOrUpdateKycDocument(bankId: String, customerId: String, id: String, customerNumber: String, `type`: String, number: String, issueDate: Date, issuePlace: String, expiryDate: Date, callContext: Option[CallContext]): OBPReturnType[Box[KycDocument]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycDocument => OutBound, InBoundCreateOrUpdateKycDocument => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycDocument => InBound, OutBoundCreateOrUpdateKycDocument => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, id, customerNumber, `type`, number, issueDate, issuePlace, expiryDate) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[KycDocument](callContext)) @@ -5055,13 +5827,13 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundCreateOrUpdateKycMedia(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, - id="string", + id=idExample.value, customerNumber=customerNumberExample.value, - `type`="string", + `type`=typeExample.value, url=urlExample.value, - date=new Date(), - relatesToKycDocumentId="string", - relatesToKycCheckId="string") + date=toDate(dateExample), + relatesToKycDocumentId=relatesToKycDocumentIdExample.value, + relatesToKycCheckId=relatesToKycCheckIdExample.value) ), exampleInboundMessage = ( InBoundCreateOrUpdateKycMedia(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -5070,17 +5842,17 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, idKycMedia="string", customerNumber=customerNumberExample.value, - `type`="string", + `type`=typeExample.value, url=urlExample.value, - date=new Date(), - relatesToKycDocumentId="string", - relatesToKycCheckId="string")) + date=toDate(dateExample), + relatesToKycDocumentId=relatesToKycDocumentIdExample.value, + relatesToKycCheckId=relatesToKycCheckIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createOrUpdateKycMedia(bankId: String, customerId: String, id: String, customerNumber: String, `type`: String, url: String, date: Date, relatesToKycDocumentId: String, relatesToKycCheckId: String, callContext: Option[CallContext]): OBPReturnType[Box[KycMedia]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycMedia => OutBound, InBoundCreateOrUpdateKycMedia => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycMedia => InBound, OutBoundCreateOrUpdateKycMedia => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, id, customerNumber, `type`, url, date, relatesToKycDocumentId, relatesToKycCheckId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[KycMediaCommons](callContext)) @@ -5098,8 +5870,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { bankId=bankIdExample.value, customerId=customerIdExample.value, customerNumber=customerNumberExample.value, - ok=true, - date=new Date()) + ok=okExample.value.toBoolean, + date=toDate(dateExample)) ), exampleInboundMessage = ( InBoundCreateOrUpdateKycStatus(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -5107,14 +5879,14 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { data= KycStatusCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, customerNumber=customerNumberExample.value, - ok=true, - date=new Date())) + ok=okExample.value.toBoolean, + date=toDate(dateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createOrUpdateKycStatus(bankId: String, customerId: String, customerNumber: String, ok: Boolean, date: Date, callContext: Option[CallContext]): OBPReturnType[Box[KycStatus]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycStatus => OutBound, InBoundCreateOrUpdateKycStatus => InBound} + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycStatus => InBound, OutBoundCreateOrUpdateKycStatus => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, customerNumber, ok, date) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[KycStatusCommons](callContext)) @@ -5138,18 +5910,18 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, idKycCheck="string", customerNumber=customerNumberExample.value, - date=new Date(), - how="string", - staffUserId="string", - staffName="string", - satisfied=true, - comments="string"))) + date=toDate(dateExample), + how=howExample.value, + staffUserId=staffUserIdExample.value, + staffName=staffNameExample.value, + satisfied=satisfiedExample.value.toBoolean, + comments=commentsExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getKycChecks(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycCheck]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycChecks => OutBound, InBoundGetKycChecks => InBound} + import com.openbankproject.commons.dto.{InBoundGetKycChecks => InBound, OutBoundGetKycChecks => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[KycCheckCommons]](callContext)) @@ -5173,17 +5945,17 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, idKycDocument="string", customerNumber=customerNumberExample.value, - `type`="string", - number="string", - issueDate=new Date(), - issuePlace="string", - expiryDate=new Date()))) + `type`=typeExample.value, + number=numberExample.value, + issueDate=toDate(issueDateExample), + issuePlace=issuePlaceExample.value, + expiryDate=toDate(expiryDateExample)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getKycDocuments(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycDocument]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycDocuments => OutBound, InBoundGetKycDocuments => InBound} + import com.openbankproject.commons.dto.{InBoundGetKycDocuments => InBound, OutBoundGetKycDocuments => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[KycDocumentCommons]](callContext)) @@ -5207,17 +5979,17 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, idKycMedia="string", customerNumber=customerNumberExample.value, - `type`="string", + `type`=typeExample.value, url=urlExample.value, - date=new Date(), - relatesToKycDocumentId="string", - relatesToKycCheckId="string"))) + date=toDate(dateExample), + relatesToKycDocumentId=relatesToKycDocumentIdExample.value, + relatesToKycCheckId=relatesToKycCheckIdExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getKycMedias(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycMedia]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycMedias => OutBound, InBoundGetKycMedias => InBound} + import com.openbankproject.commons.dto.{InBoundGetKycMedias => InBound, OutBoundGetKycMedias => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[KycMediaCommons]](callContext)) @@ -5240,14 +6012,14 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { data=List( KycStatusCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, customerNumber=customerNumberExample.value, - ok=true, - date=new Date()))) + ok=okExample.value.toBoolean, + date=toDate(dateExample)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getKycStatuses(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycStatus]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycStatuses => OutBound, InBoundGetKycStatuses => InBound} + import com.openbankproject.commons.dto.{InBoundGetKycStatuses => InBound, OutBoundGetKycStatuses => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[List[KycStatusCommons]](callContext)) @@ -5265,28 +6037,31 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), bankId=BankId(bankIdExample.value), - message="string", - fromDepartment="string", - fromPerson="string") + message=messageExample.value, + fromDepartment=fromDepartmentExample.value, + fromPerson=fromPersonExample.value) ), exampleInboundMessage = ( InBoundCreateMessage(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerMessageCommons(messageId="string", - date=new Date(), - message="string", - fromDepartment="string", - fromPerson="string")) + date=toDate(dateExample), + message=messageExample.value, + fromDepartment=fromDepartmentExample.value, + fromPerson=fromPersonExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createMessage(user: User, bankId: BankId, message: String, fromDepartment: String, fromPerson: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerMessage]] = { - import com.openbankproject.commons.dto.{OutBoundCreateMessage => OutBound, InBoundCreateMessage => InBound} + import com.openbankproject.commons.dto.{InBoundCreateMessage => InBound, OutBoundCreateMessage => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, user, bankId, message, fromDepartment, fromPerson) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[CustomerMessageCommons](callContext)) @@ -5303,41 +6078,47 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { OutBoundMakeHistoricalPayment(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - posted=new Date(), - completed=new Date(), - amount=BigDecimal("123.321"), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + posted=toDate(postedExample), + completed=toDate(completedExample), + amount=BigDecimal(amountExample.value), currency=currencyExample.value, - description="string", + description=descriptionExample.value, transactionRequestType=transactionRequestTypeExample.value, - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( InBoundMakeHistoricalPayment(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -5348,7 +6129,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def makeHistoricalPayment(fromAccount: BankAccount, toAccount: BankAccount, posted: Date, completed: Date, amount: BigDecimal, currency: String, description: String, transactionRequestType: String, chargePolicy: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionId]] = { - import com.openbankproject.commons.dto.{OutBoundMakeHistoricalPayment => OutBound, InBoundMakeHistoricalPayment => InBound} + import com.openbankproject.commons.dto.{InBoundMakeHistoricalPayment => InBound, OutBoundMakeHistoricalPayment => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccount, toAccount, posted, completed, amount, currency, description, transactionRequestType, chargePolicy) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[TransactionId](callContext)) @@ -5368,30 +6149,30 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { customerId=customerIdExample.value, userId=userIdExample.value, counterpartyId=counterpartyIdExample.value, - dateSigned=new Date(), - dateStarts=new Date(), - dateExpires=Some(new Date())) + dateSigned=toDate(dateSignedExample), + dateStarts=toDate(dateStartsExample), + dateExpires=Some(toDate(dateExpiresExample))) ), exampleInboundMessage = ( InBoundCreateDirectDebit(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= DirectDebitTraitCommons(directDebitId="string", + data= DirectDebitTraitCommons(directDebitId=directDebitIdExample.value, bankId=bankIdExample.value, accountId=accountIdExample.value, customerId=customerIdExample.value, userId=userIdExample.value, counterpartyId=counterpartyIdExample.value, - dateSigned=new Date(), - dateCancelled=new Date(), - dateStarts=new Date(), - dateExpires=new Date(), - active=true)) + dateSigned=toDate(dateSignedExample), + dateCancelled=toDate(dateCancelledExample), + dateStarts=toDate(dateStartsExample), + dateExpires=toDate(dateExpiresExample), + active=activeExample.value.toBoolean)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def createDirectDebit(bankId: String, accountId: String, customerId: String, userId: String, counterpartyId: String, dateSigned: Date, dateStarts: Date, dateExpires: Option[Date], callContext: Option[CallContext]): OBPReturnType[Box[DirectDebitTrait]] = { - import com.openbankproject.commons.dto.{OutBoundCreateDirectDebit => OutBound, InBoundCreateDirectDebit => InBound} + import com.openbankproject.commons.dto.{InBoundCreateDirectDebit => InBound, OutBoundCreateDirectDebit => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, customerId, userId, counterpartyId, dateSigned, dateStarts, dateExpires) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[DirectDebitTraitCommons](callContext)) @@ -5417,12 +6198,12 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { ) override def deleteCustomerAttribute(customerAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteCustomerAttribute => OutBound, InBoundDeleteCustomerAttribute => InBound} + import com.openbankproject.commons.dto.{InBoundDeleteCustomerAttribute => InBound, OutBoundDeleteCustomerAttribute => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAttributeId) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2020-06-17T14:19:04Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2021-08-19T16:36:57Z +//---------------- dynamic end ---------------------please don't modify this line } diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 6335c6762..2d9a23fe8 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -26,6 +26,7 @@ Berlin 13359, Germany import java.net.{ConnectException, URLEncoder, UnknownHostException} import java.util.Date import java.util.UUID.randomUUID + import _root_.akka.stream.StreamTcpException import akka.http.scaladsl.model.headers.RawHeader import akka.http.scaladsl.model.{HttpProtocol, _} @@ -48,7 +49,8 @@ import code.util.Helper import code.util.Helper.MdcLoggable import com.openbankproject.commons.dto.{InBoundTrait, _} import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA -import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, DynamicEntityOperation, ProductAttributeType} +import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus +import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, ChallengeType, CustomerAttributeType, DynamicEntityOperation, ProductAttributeType, StrongCustomerAuthentication, TransactionAttributeType} import com.openbankproject.commons.model.{ErrorMessage, TopicTrait, _} import com.openbankproject.commons.util.{JsonUtils, ReflectUtils} import com.tesobe.{CacheKeyFromArguments, CacheKeyOmit} @@ -93,7 +95,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable //---------------- dynamic start -------------------please don't modify this line -// ---------- created on Tue Sep 03 17:49:04 CEST 2019 +// ---------- created on 2021-08-19T16:37:18Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -103,43 +105,11 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAdapterInfo( OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value)))))))))) + OutBoundGetAdapterInfo(MessageDocsSwaggerDefinitions.outboundAdapterCallContext) ), exampleInboundMessage = ( - InBoundGetAdapterInfo(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetAdapterInfo(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= InboundAdapterInfoInternal(errorCode=inboundAdapterInfoInternalErrorCodeExample.value, backendMessages=List( InboundStatusMessage(source=sourceExample.value, status=inboundStatusMessageStatusExample.value, @@ -152,15 +122,54 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAdapterInfo + override def getAdapterInfo(callContext: Option[CallContext]): Future[Box[(InboundAdapterInfoInternal, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetAdapterInfo => OutBound, InBoundGetAdapterInfo => InBound} - val url = getUrl(callContext, "getAdapterInfo") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull ) - val result: OBPReturnType[Box[InboundAdapterInfoInternal]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAdapterInfo => InBound, OutBoundGetAdapterInfo => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAdapterInfo"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[InboundAdapterInfoInternal](callContext)) } - + + messageDocs += validateAndCheckIbanNumberDoc + def validateAndCheckIbanNumberDoc = MessageDoc( + process = "obp.validateAndCheckIbanNumber", + messageFormat = messageFormat, + description = "Validate And Check Iban Number", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundValidateAndCheckIbanNumber(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + iban=ibanExample.value) + ), + exampleInboundMessage = ( + InBoundValidateAndCheckIbanNumber(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= IbanChecker(isValid=true, + details=Some( IbanDetails(bic=bicExample.value, + bank=bankExample.value, + branch="string", + address=addressExample.value, + city=cityExample.value, + zip="string", + phone=phoneExample.value, + country="string", + countryIso="string", + sepaCreditTransfer=sepaCreditTransferExample.value, + sepaDirectDebit=sepaDirectDebitExample.value, + sepaSddCore=sepaSddCoreExample.value, + sepaB2b=sepaB2bExample.value, + sepaCardClearing=sepaCardClearingExample.value)))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def validateAndCheckIbanNumber(iban: String, callContext: Option[CallContext]): OBPReturnType[Box[IbanChecker]] = { + import com.openbankproject.commons.dto.{InBoundValidateAndCheckIbanNumber => InBound, OutBoundValidateAndCheckIbanNumber => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "validateAndCheckIbanNumber"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[IbanChecker](callContext)) + } + messageDocs += getChallengeThresholdDoc def getChallengeThresholdDoc = MessageDoc( process = "obp.getChallengeThreshold", @@ -169,64 +178,31 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetChallengeThreshold(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetChallengeThreshold(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, accountId=accountIdExample.value, viewId=viewIdExample.value, transactionRequestType=transactionRequestTypeExample.value, currency=currencyExample.value, userId=userIdExample.value, - username="string") + username=usernameExample.value) ), exampleInboundMessage = ( - InBoundGetChallengeThreshold(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetChallengeThreshold(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= AmountOfMoney(currency=currencyExample.value, - amount="string")) + amount=amountExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getChallengeThreshold + override def getChallengeThreshold(bankId: String, accountId: String, viewId: String, transactionRequestType: String, currency: String, userId: String, username: String, callContext: Option[CallContext]): OBPReturnType[Box[AmountOfMoney]] = { - import com.openbankproject.commons.dto.{OutBoundGetChallengeThreshold => OutBound, InBoundGetChallengeThreshold => InBound} - val url = getUrl(callContext, "getChallengeThreshold") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, viewId, transactionRequestType, currency, userId, username) - val result: OBPReturnType[Box[AmountOfMoney]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetChallengeThreshold => InBound, OutBoundGetChallengeThreshold => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, viewId, transactionRequestType, currency, userId, username) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getChallengeThreshold"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AmountOfMoney](callContext)) } - + messageDocs += getChargeLevelDoc def getChargeLevelDoc = MessageDoc( process = "obp.getChargeLevel", @@ -235,64 +211,70 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetChargeLevel(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetChargeLevel(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), viewId=ViewId(viewIdExample.value), userId=userIdExample.value, - username="string", + username=usernameExample.value, transactionRequestType=transactionRequestTypeExample.value, currency=currencyExample.value) ), exampleInboundMessage = ( - InBoundGetChargeLevel(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetChargeLevel(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= AmountOfMoney(currency=currencyExample.value, - amount="string")) + amount=amountExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getChargeLevel + override def getChargeLevel(bankId: BankId, accountId: AccountId, viewId: ViewId, userId: String, username: String, transactionRequestType: String, currency: String, callContext: Option[CallContext]): OBPReturnType[Box[AmountOfMoney]] = { - import com.openbankproject.commons.dto.{OutBoundGetChargeLevel => OutBound, InBoundGetChargeLevel => InBound} - val url = getUrl(callContext, "getChargeLevel") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, viewId, userId, username, transactionRequestType, currency) - val result: OBPReturnType[Box[AmountOfMoney]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetChargeLevel => InBound, OutBoundGetChargeLevel => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, viewId, userId, username, transactionRequestType, currency) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getChargeLevel"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AmountOfMoney](callContext)) } - + + messageDocs += getChargeLevelC2Doc + def getChargeLevelC2Doc = MessageDoc( + process = "obp.getChargeLevelC2", + messageFormat = messageFormat, + description = "Get Charge Level C2", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChargeLevelC2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + viewId=ViewId(viewIdExample.value), + userId=userIdExample.value, + username=usernameExample.value, + transactionRequestType=transactionRequestTypeExample.value, + currency=currencyExample.value, + amount=amountExample.value, + toAccountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + customAttributes=List( CustomAttribute(name=nameExample.value, + attributeType=com.openbankproject.commons.model.enums.AttributeType.example, + value=valueExample.value))) + ), + exampleInboundMessage = ( + InBoundGetChargeLevelC2(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChargeLevelC2(bankId: BankId, accountId: AccountId, viewId: ViewId, userId: String, username: String, transactionRequestType: String, currency: String, amount: String, toAccountRoutings: List[AccountRouting], customAttributes: List[CustomAttribute], callContext: Option[CallContext]): OBPReturnType[Box[AmountOfMoney]] = { + import com.openbankproject.commons.dto.{InBoundGetChargeLevelC2 => InBound, OutBoundGetChargeLevelC2 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, viewId, userId, username, transactionRequestType, currency, amount, toAccountRoutings, customAttributes) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getChargeLevelC2"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AmountOfMoney](callContext)) + } + messageDocs += createChallengeDoc def createChallengeDoc = MessageDoc( process = "obp.createChallenge", @@ -301,62 +283,102 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateChallenge(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateChallenge(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), userId=userIdExample.value, transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - transactionRequestId="string", + transactionRequestId=transactionRequestIdExample.value, scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS)) ), exampleInboundMessage = ( - InBoundCreateChallenge(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateChallenge(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data="string") ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createChallenge - override def createChallenge(bankId: BankId, accountId: AccountId, userId: String, transactionRequestType: TransactionRequestType, transactionRequestId: String, scaMethod: Option[SCA], callContext: Option[CallContext]): OBPReturnType[Box[String]] = { - import com.openbankproject.commons.dto.{OutBoundCreateChallenge => OutBound, InBoundCreateChallenge => InBound} - val url = getUrl(callContext, "createChallenge") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, userId, transactionRequestType, transactionRequestId, scaMethod) - val result: OBPReturnType[Box[String]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + + override def createChallenge(bankId: BankId, accountId: AccountId, userId: String, transactionRequestType: TransactionRequestType, transactionRequestId: String, scaMethod: Option[StrongCustomerAuthentication.SCA], callContext: Option[CallContext]): OBPReturnType[Box[String]] = { + import com.openbankproject.commons.dto.{InBoundCreateChallenge => InBound, OutBoundCreateChallenge => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, userId, transactionRequestType, transactionRequestId, scaMethod) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createChallenge"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[String](callContext)) } - + + messageDocs += createChallengesDoc + def createChallengesDoc = MessageDoc( + process = "obp.createChallenges", + messageFormat = messageFormat, + description = "Create Challenges", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateChallenges(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + userIds=listExample.value.split("[,;]").toList, + transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), + transactionRequestId=transactionRequestIdExample.value, + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS)) + ), + exampleInboundMessage = ( + InBoundCreateChallenges(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=listExample.value.split("[,;]").toList) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createChallenges(bankId: BankId, accountId: AccountId, userIds: List[String], transactionRequestType: TransactionRequestType, transactionRequestId: String, scaMethod: Option[StrongCustomerAuthentication.SCA], callContext: Option[CallContext]): OBPReturnType[Box[List[String]]] = { + import com.openbankproject.commons.dto.{InBoundCreateChallenges => InBound, OutBoundCreateChallenges => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, userIds, transactionRequestType, transactionRequestId, scaMethod) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createChallenges"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[String]](callContext)) + } + + messageDocs += createChallengesC2Doc + def createChallengesC2Doc = MessageDoc( + process = "obp.createChallengesC2", + messageFormat = messageFormat, + description = "Create Challenges C2", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateChallengesC2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + userIds=listExample.value.split("[,;]").toList, + challengeType=com.openbankproject.commons.model.enums.ChallengeType.example, + transactionRequestId=Some(transactionRequestIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + consentId=Some(consentIdExample.value), + authenticationMethodId=Some("string")) + ), + exampleInboundMessage = ( + InBoundCreateChallengesC2(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string")))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createChallengesC2(userIds: List[String], challengeType: ChallengeType.Value, transactionRequestId: Option[String], scaMethod: Option[StrongCustomerAuthentication.SCA], scaStatus: Option[SCAStatus], consentId: Option[String], authenticationMethodId: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundCreateChallengesC2 => InBound, OutBoundCreateChallengesC2 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userIds, challengeType, transactionRequestId, scaMethod, scaStatus, consentId, authenticationMethodId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createChallengesC2"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + messageDocs += validateChallengeAnswerDoc def validateChallengeAnswerDoc = MessageDoc( process = "obp.validateChallengeAnswer", @@ -365,125 +387,172 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundValidateChallengeAnswer(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - challengeId="string", - hashOfSuppliedAnswer="string") + OutBoundValidateChallengeAnswer(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + challengeId=challengeIdExample.value, + hashOfSuppliedAnswer=hashOfSuppliedAnswerExample.value) ), exampleInboundMessage = ( - InBoundValidateChallengeAnswer(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundValidateChallengeAnswer(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /validateChallengeAnswer + override def validateChallengeAnswer(challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundValidateChallengeAnswer => OutBound, InBoundValidateChallengeAnswer => InBound} - val url = getUrl(callContext, "validateChallengeAnswer") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , challengeId, hashOfSuppliedAnswer) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswer => InBound, OutBoundValidateChallengeAnswer => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, challengeId, hashOfSuppliedAnswer) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "validateChallengeAnswer"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - - messageDocs += getBankLegacyDoc - def getBankLegacyDoc = MessageDoc( - process = "obp.getBankLegacy", + + messageDocs += validateChallengeAnswerC2Doc + def validateChallengeAnswerC2Doc = MessageDoc( + process = "obp.validateChallengeAnswerC2", messageFormat = messageFormat, - description = "Get Bank Legacy", + description = "Validate Challenge Answer C2", outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankId=BankId(bankIdExample.value)) + OutBoundValidateChallengeAnswerC2(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=Some(transactionRequestIdExample.value), + consentId=Some(consentIdExample.value), + challengeId=challengeIdExample.value, + hashOfSuppliedAnswer=hashOfSuppliedAnswerExample.value) ), exampleInboundMessage = ( - InBoundGetBankLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= BankCommons(bankId=BankId(bankIdExample.value), - shortName=bankShortNameExample.value, - fullName=bankFullNameExample.value, - logoUrl=bankLogoUrlExample.value, - websiteUrl=bankWebsiteUrlExample.value, - bankRoutingScheme=bankRoutingSchemeExample.value, - bankRoutingAddress=bankRoutingAddressExample.value, - swiftBic=bankSwiftBicExample.value, - nationalIdentifier=bankNationalIdentifierExample.value)) + InBoundValidateChallengeAnswerC2(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string"))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankLegacy - override def getBankLegacy(bankId: BankId, callContext: Option[CallContext]): Box[(Bank, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetBankLegacy => OutBound, InBoundGetBankLegacy => InBound} - val url = getUrl(callContext, "getBankLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId) - val result: OBPReturnType[Box[BankCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + + override def validateChallengeAnswerC2(transactionRequestId: Option[String], consentId: Option[String], challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundValidateChallengeAnswerC2 => InBound, OutBoundValidateChallengeAnswerC2 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId, consentId, challengeId, hashOfSuppliedAnswer) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "validateChallengeAnswerC2"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[ChallengeCommons](callContext)) } - + + messageDocs += getChallengesByTransactionRequestIdDoc + def getChallengesByTransactionRequestIdDoc = MessageDoc( + process = "obp.getChallengesByTransactionRequestId", + messageFormat = messageFormat, + description = "Get Challenges By Transaction Request Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallengesByTransactionRequestId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=transactionRequestIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallengesByTransactionRequestId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string")))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallengesByTransactionRequestId(transactionRequestId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundGetChallengesByTransactionRequestId => InBound, OutBoundGetChallengesByTransactionRequestId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getChallengesByTransactionRequestId"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + + messageDocs += getChallengesByConsentIdDoc + def getChallengesByConsentIdDoc = MessageDoc( + process = "obp.getChallengesByConsentId", + messageFormat = messageFormat, + description = "Get Challenges By Consent Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallengesByConsentId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + consentId=consentIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallengesByConsentId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string")))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallengesByConsentId(consentId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ChallengeTrait]]] = { + import com.openbankproject.commons.dto.{InBoundGetChallengesByConsentId => InBound, OutBoundGetChallengesByConsentId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, consentId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getChallengesByConsentId"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ChallengeCommons]](callContext)) + } + + messageDocs += getChallengeDoc + def getChallengeDoc = MessageDoc( + process = "obp.getChallenge", + messageFormat = messageFormat, + description = "Get Challenge", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetChallenge(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + challengeId=challengeIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetChallenge(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= ChallengeCommons(challengeId=challengeIdExample.value, + transactionRequestId=transactionRequestIdExample.value, + expectedAnswer="string", + expectedUserId="string", + salt="string", + successful=true, + challengeType=challengeTypeExample.value, + consentId=Some(consentIdExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + scaStatus=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.example), + authenticationMethodId=Some("string"))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getChallenge(challengeId: String, callContext: Option[CallContext]): OBPReturnType[Box[ChallengeTrait]] = { + import com.openbankproject.commons.dto.{InBoundGetChallenge => InBound, OutBoundGetChallenge => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, challengeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getChallenge"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[ChallengeCommons](callContext)) + } + messageDocs += getBankDoc def getBankDoc = MessageDoc( process = "obp.getBank", @@ -492,44 +561,12 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBank(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBank(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value)) ), exampleInboundMessage = ( - InBoundGetBank(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBank(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankCommons(bankId=BankId(bankIdExample.value), shortName=bankShortNameExample.value, fullName=bankFullNameExample.value, @@ -542,81 +579,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBank + override def getBank(bankId: BankId, callContext: Option[CallContext]): Future[Box[(Bank, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBank => OutBound, InBoundGetBank => InBound} - val url = getUrl(callContext, "getBank") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId) - val result: OBPReturnType[Box[BankCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBank => InBound, OutBoundGetBank => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBank"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankCommons](callContext)) } - - messageDocs += getBanksLegacyDoc - def getBanksLegacyDoc = MessageDoc( - process = "obp.getBanksLegacy", - messageFormat = messageFormat, - description = "Get Banks Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetBanksLegacy( OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value)))))))))) - ), - exampleInboundMessage = ( - InBoundGetBanksLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( BankCommons(bankId=BankId(bankIdExample.value), - shortName=bankShortNameExample.value, - fullName=bankFullNameExample.value, - logoUrl=bankLogoUrlExample.value, - websiteUrl=bankWebsiteUrlExample.value, - bankRoutingScheme=bankRoutingSchemeExample.value, - bankRoutingAddress=bankRoutingAddressExample.value, - swiftBic=bankSwiftBicExample.value, - nationalIdentifier=bankNationalIdentifierExample.value))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getBanksLegacy - override def getBanksLegacy(callContext: Option[CallContext]): Box[(List[Bank], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetBanksLegacy => OutBound, InBoundGetBanksLegacy => InBound} - val url = getUrl(callContext, "getBanksLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull ) - val result: OBPReturnType[Box[List[BankCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getBanksDoc def getBanksDoc = MessageDoc( process = "obp.getBanks", @@ -625,43 +595,11 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBanks( OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value)))))))))) + OutBoundGetBanks(MessageDocsSwaggerDefinitions.outboundAdapterCallContext) ), exampleInboundMessage = ( - InBoundGetBanks(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBanks(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( BankCommons(bankId=BankId(bankIdExample.value), shortName=bankShortNameExample.value, fullName=bankFullNameExample.value, @@ -674,88 +612,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBanks + override def getBanks(callContext: Option[CallContext]): Future[Box[(List[Bank], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBanks => OutBound, InBoundGetBanks => InBound} - val url = getUrl(callContext, "getBanks") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull ) - val result: OBPReturnType[Box[List[BankCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBanks => InBound, OutBoundGetBanks => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBanks"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[BankCommons]](callContext)) } - - messageDocs += getBankAccountsForUserLegacyDoc - def getBankAccountsForUserLegacyDoc = MessageDoc( - process = "obp.getBankAccountsForUserLegacy", - messageFormat = messageFormat, - description = "Get Bank Accounts For User Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetBankAccountsForUserLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - username=usernameExample.value) - ), - exampleInboundMessage = ( - InBoundGetBankAccountsForUserLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( InboundAccountCommons(bankId=bankIdExample.value, - branchId=branchIdExample.value, - accountId=accountIdExample.value, - accountNumber=accountNumberExample.value, - accountType=accountTypeExample.value, - balanceAmount=balanceAmountExample.value, - balanceCurrency=balanceCurrencyExample.value, - owners=inboundAccountOwnersExample.value.split("[,;]").toList, - viewsToGenerate=inboundAccountViewsToGenerateExample.value.split("[,;]").toList, - bankRoutingScheme=bankRoutingSchemeExample.value, - bankRoutingAddress=bankRoutingAddressExample.value, - branchRoutingScheme=branchRoutingSchemeExample.value, - branchRoutingAddress=branchRoutingAddressExample.value, - accountRoutingScheme=accountRoutingSchemeExample.value, - accountRoutingAddress=accountRoutingAddressExample.value))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getBankAccountsForUserLegacy - override def getBankAccountsForUserLegacy(username: String, callContext: Option[CallContext]): Box[(List[InboundAccount], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsForUserLegacy => OutBound, InBoundGetBankAccountsForUserLegacy => InBound} - val url = getUrl(callContext, "getBankAccountsForUserLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , username) - val result: OBPReturnType[Box[List[InboundAccountCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getBankAccountsForUserDoc def getBankAccountsForUserDoc = MessageDoc( process = "obp.getBankAccountsForUser", @@ -764,44 +628,12 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccountsForUser(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBankAccountsForUser(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, username=usernameExample.value) ), exampleInboundMessage = ( - InBoundGetBankAccountsForUser(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBankAccountsForUser(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( InboundAccountCommons(bankId=bankIdExample.value, branchId=branchIdExample.value, accountId=accountIdExample.value, @@ -820,90 +652,158 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccountsForUser + override def getBankAccountsForUser(username: String, callContext: Option[CallContext]): Future[Box[(List[InboundAccount], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsForUser => OutBound, InBoundGetBankAccountsForUser => InBound} - val url = getUrl(callContext, "getBankAccountsForUser") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , username) - val result: OBPReturnType[Box[List[InboundAccountCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBankAccountsForUser => InBound, OutBoundGetBankAccountsForUser => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, username) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccountsForUser"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[InboundAccountCommons]](callContext)) } - - messageDocs += getBankAccountLegacyDoc - def getBankAccountLegacyDoc = MessageDoc( - process = "obp.getBankAccountLegacy", + + messageDocs += getUserDoc + def getUserDoc = MessageDoc( + process = "obp.getUser", messageFormat = messageFormat, - description = "Get Bank Account Legacy", + description = "Get User", outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccountLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), + OutBoundGetUser(name=userNameExample.value, + password=passwordExample.value) + ), + exampleInboundMessage = ( + InBoundGetUser(status=MessageDocsSwaggerDefinitions.inboundStatus, + data= InboundUser(email=emailExample.value, + password=passwordExample.value, + displayName=displayNameExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getUser(name: String, password: String): Box[InboundUser] = { + import com.openbankproject.commons.dto.{InBoundGetUser => InBound, OutBoundGetUser => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(name, password) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getUser"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[InboundUser](callContext)) + } + + messageDocs += checkExternalUserCredentialsDoc + def checkExternalUserCredentialsDoc = MessageDoc( + process = "obp.checkExternalUserCredentials", + messageFormat = messageFormat, + description = "Check External User Credentials", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCheckExternalUserCredentials(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + username=usernameExample.value, + password=passwordExample.value) + ), + exampleInboundMessage = ( + InBoundCheckExternalUserCredentials(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= InboundExternalUser(aud=audExample.value, + exp=expExample.value, + iat=iatExample.value, + iss=issExample.value, + sub=subExample.value, + azp=Some("string"), + email=Some(emailExample.value), + emailVerified=Some(emailVerifiedExample.value), + name=Some(userNameExample.value), userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankId=BankId(bankIdExample.value), + value=valueExample.value))))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def checkExternalUserCredentials(username: String, password: String, callContext: Option[CallContext]): Box[InboundExternalUser] = { + import com.openbankproject.commons.dto.{InBoundCheckExternalUserCredentials => InBound, OutBoundCheckExternalUserCredentials => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, username, password) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "checkExternalUserCredentials"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[InboundExternalUser](callContext)) + } + + messageDocs += checkExternalUserExistsDoc + def checkExternalUserExistsDoc = MessageDoc( + process = "obp.checkExternalUserExists", + messageFormat = messageFormat, + description = "Check External User Exists", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCheckExternalUserExists(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + username=usernameExample.value) + ), + exampleInboundMessage = ( + InBoundCheckExternalUserExists(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= InboundExternalUser(aud=audExample.value, + exp=expExample.value, + iat=iatExample.value, + iss=issExample.value, + sub=subExample.value, + azp=Some("string"), + email=Some(emailExample.value), + emailVerified=Some(emailVerifiedExample.value), + name=Some(userNameExample.value), + userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, + value=valueExample.value))))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def checkExternalUserExists(username: String, callContext: Option[CallContext]): Box[InboundExternalUser] = { + import com.openbankproject.commons.dto.{InBoundCheckExternalUserExists => InBound, OutBoundCheckExternalUserExists => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, username) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "checkExternalUserExists"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[InboundExternalUser](callContext)) + } + + messageDocs += getBankAccountOldDoc + def getBankAccountOldDoc = MessageDoc( + process = "obp.getBankAccountOld", + messageFormat = messageFormat, + description = "Get Bank Account Old", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetBankAccountOld(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)) ), exampleInboundMessage = ( - InBoundGetBankAccountLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBankAccountOld(status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccountLegacy - override def getBankAccountLegacy(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): Box[(BankAccount, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountLegacy => OutBound, InBoundGetBankAccountLegacy => InBound} - val url = getUrl(callContext, "getBankAccountLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + override def getBankAccountOld(bankId: BankId, accountId: AccountId): Box[BankAccount] = { + import com.openbankproject.commons.dto.{InBoundGetBankAccountOld => InBound, OutBoundGetBankAccountOld => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccountOld"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankAccountCommons](callContext)) + } + messageDocs += getBankAccountByIbanDoc def getBankAccountByIbanDoc = MessageDoc( process = "obp.getBankAccountByIban", @@ -912,71 +812,41 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccountByIban(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBankAccountByIban(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, iban=ibanExample.value) ), exampleInboundMessage = ( - InBoundGetBankAccountByIban(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBankAccountByIban(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccountByIban + override def getBankAccountByIban(iban: String, callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountByIban => OutBound, InBoundGetBankAccountByIban => InBound} - val url = getUrl(callContext, "getBankAccountByIban") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , iban) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBankAccountByIban => InBound, OutBoundGetBankAccountByIban => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccountByIban"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankAccountCommons](callContext)) } - + messageDocs += getBankAccountByRoutingDoc def getBankAccountByRoutingDoc = MessageDoc( process = "obp.getBankAccountByRouting", @@ -985,73 +855,43 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccountByRouting(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBankAccountByRouting(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=Some(BankId(bankIdExample.value)), - scheme="string", - address="string") + scheme=schemeExample.value, + address=addressExample.value) ), exampleInboundMessage = ( - InBoundGetBankAccountByRouting(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBankAccountByRouting(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccountByRouting + override def getBankAccountByRouting(bankId: Option[BankId], scheme: String, address: String, callContext: Option[CallContext]): Box[(BankAccount, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountByRouting => OutBound, InBoundGetBankAccountByRouting => InBound} - val url = getUrl(callContext, "getBankAccountByRouting") + import com.openbankproject.commons.dto.{InBoundGetBankAccountByRouting => InBound, OutBoundGetBankAccountByRouting => OutBound} val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, scheme, address) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccountByRouting"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankAccountCommons](callContext)) } - + messageDocs += getBankAccountsDoc def getBankAccountsDoc = MessageDoc( process = "obp.getBankAccounts", @@ -1060,72 +900,42 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccounts(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBankAccounts(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)))) ), exampleInboundMessage = ( - InBoundGetBankAccounts(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBankAccounts(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value))) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccounts + override def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[List[BankAccount]]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccounts => OutBound, InBoundGetBankAccounts => InBound} - val url = getUrl(callContext, "getBankAccounts") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankIdAccountIds) - val result: OBPReturnType[Box[List[BankAccountCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBankAccounts => InBound, OutBoundGetBankAccounts => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccounts"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[BankAccountCommons]](callContext)) } - + messageDocs += getBankAccountsBalancesDoc def getBankAccountsBalancesDoc = MessageDoc( process = "obp.getBankAccountsBalances", @@ -1134,46 +944,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccountsBalances(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBankAccountsBalances(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)))) ), exampleInboundMessage = ( - InBoundGetBankAccountsBalances(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= AccountsBalances(accounts=List( AccountBalance(id=accountIdExample.value, + InBoundGetBankAccountsBalances(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AccountsBalances(accounts=List( AccountBalance(id=idExample.value, label=labelExample.value, bankId=bankIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, @@ -1181,96 +959,19 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable balance= AmountOfMoney(currency=balanceCurrencyExample.value, amount=balanceAmountExample.value))), overallBalance= AmountOfMoney(currency=currencyExample.value, - amount="string"), - overallBalanceDate=new Date())) + amount=amountExample.value), + overallBalanceDate=toDate(overallBalanceDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccountsBalances - override def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], @CacheKeyOmit callContext: Option[CallContext]): OBPReturnType[Box[AccountsBalances]] = saveConnectorMetric { - /** - * Please note that "var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString)" - * is just a temporary value field with UUID values in order to prevent any ambiguity. - * The real value will be assigned by Macro during compile time at this line of a code: - * https://github.com/OpenBankProject/scala-macros/blob/master/macros/src/main/scala/com/tesobe/CacheKeyFromArgumentsMacro.scala#L49 - */ - //Note: here is a bit different, we get the headers from api level and also use them as the cache key. - val basicUserAuthContext = callContext.map(createBasicUserAuthContextJsonFromCallContext(_)) - var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) - CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()+ basicUserAuthContext.toString()))(bankAccountsBalancesTTL second){{ - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsBalances => OutBound, InBoundGetBankAccountsBalances => InBound} - val url = getUrl(callContext, "getBankAccountsBalances") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankIdAccountIds) - val result: OBPReturnType[Box[AccountsBalances]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - }}}}("getBankAccountsBalances") - - messageDocs += getCoreBankAccountsLegacyDoc - def getCoreBankAccountsLegacyDoc = MessageDoc( - process = "obp.getCoreBankAccountsLegacy", - messageFormat = messageFormat, - description = "Get Core Bank Accounts Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetCoreBankAccountsLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value), - accountId=AccountId(accountIdExample.value)))) - ), - exampleInboundMessage = ( - InBoundGetCoreBankAccountsLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( CoreAccount(id=accountIdExample.value, - label=labelExample.value, - bankId=bankIdExample.value, - accountType=accountTypeExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value))))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getCoreBankAccountsLegacy - override def getCoreBankAccountsLegacy(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): Box[(List[CoreAccount], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetCoreBankAccountsLegacy => OutBound, InBoundGetCoreBankAccountsLegacy => InBound} - val url = getUrl(callContext, "getCoreBankAccountsLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankIdAccountIds) - val result: OBPReturnType[Box[List[CoreAccount]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + + override def getBankAccountsBalances(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[AccountsBalances]] = { + import com.openbankproject.commons.dto.{InBoundGetBankAccountsBalances => InBound, OutBoundGetBankAccountsBalances => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccountsBalances"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AccountsBalances](callContext)) } - + messageDocs += getCoreBankAccountsDoc def getCoreBankAccountsDoc = MessageDoc( process = "obp.getCoreBankAccounts", @@ -1279,45 +980,13 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCoreBankAccounts(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCoreBankAccounts(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)))) ), exampleInboundMessage = ( - InBoundGetCoreBankAccounts(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCoreBankAccounts(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CoreAccount(id=accountIdExample.value, label=labelExample.value, bankId=bankIdExample.value, @@ -1327,80 +996,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCoreBankAccounts + override def getCoreBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): Future[Box[(List[CoreAccount], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCoreBankAccounts => OutBound, InBoundGetCoreBankAccounts => InBound} - val url = getUrl(callContext, "getCoreBankAccounts") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankIdAccountIds) - val result: OBPReturnType[Box[List[CoreAccount]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCoreBankAccounts => InBound, OutBoundGetCoreBankAccounts => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCoreBankAccounts"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CoreAccount]](callContext)) } - - messageDocs += getBankAccountsHeldLegacyDoc - def getBankAccountsHeldLegacyDoc = MessageDoc( - process = "obp.getBankAccountsHeldLegacy", - messageFormat = messageFormat, - description = "Get Bank Accounts Held Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetBankAccountsHeldLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value), - accountId=AccountId(accountIdExample.value)))) - ), - exampleInboundMessage = ( - InBoundGetBankAccountsHeldLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( AccountHeld(id="string", - label = labelExample.value, - bankId=bankIdExample.value, - number="string", - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value))))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getBankAccountsHeldLegacy - override def getBankAccountsHeldLegacy(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): Box[List[AccountHeld]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsHeldLegacy => OutBound, InBoundGetBankAccountsHeldLegacy => InBound} - val url = getUrl(callContext, "getBankAccountsHeldLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankIdAccountIds) - val result: OBPReturnType[Box[List[AccountHeld]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getBankAccountsHeldDoc def getBankAccountsHeldDoc = MessageDoc( process = "obp.getBankAccountsHeld", @@ -1409,137 +1012,30 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBankAccountsHeld(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBankAccountsHeld(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankIdAccountIds=List( BankIdAccountId(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)))) ), exampleInboundMessage = ( - InBoundGetBankAccountsHeld(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( AccountHeld(id="string", - label = labelExample.value, + InBoundGetBankAccountsHeld(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( AccountHeld(id=idExample.value, + label=labelExample.value, bankId=bankIdExample.value, - number="string", + number=numberExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBankAccountsHeld + override def getBankAccountsHeld(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[List[AccountHeld]]] = { - import com.openbankproject.commons.dto.{OutBoundGetBankAccountsHeld => OutBound, InBoundGetBankAccountsHeld => InBound} - val url = getUrl(callContext, "getBankAccountsHeld") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankIdAccountIds) - val result: OBPReturnType[Box[List[AccountHeld]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBankAccountsHeld => InBound, OutBoundGetBankAccountsHeld => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankIdAccountIds) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBankAccountsHeld"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[AccountHeld]](callContext)) } - - messageDocs += checkBankAccountExistsLegacyDoc - def checkBankAccountExistsLegacyDoc = MessageDoc( - process = "obp.checkBankAccountExistsLegacy", - messageFormat = messageFormat, - description = "Check Bank Account Exists Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundCheckBankAccountExistsLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankId=BankId(bankIdExample.value), - accountId=AccountId(accountIdExample.value)) - ), - exampleInboundMessage = ( - InBoundCheckBankAccountExistsLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= BankAccountCommons(accountId=AccountId(accountIdExample.value), - accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), - currency=currencyExample.value, - name=bankAccountNameExample.value, - label=labelExample.value, - number=bankAccountNumberExample.value, - bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), - branchId=branchIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, - value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /checkBankAccountExistsLegacy - override def checkBankAccountExistsLegacy(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): Box[(BankAccount, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundCheckBankAccountExistsLegacy => OutBound, InBoundCheckBankAccountExistsLegacy => InBound} - val url = getUrl(callContext, "checkBankAccountExistsLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += checkBankAccountExistsDoc def checkBankAccountExistsDoc = MessageDoc( process = "obp.checkBankAccountExists", @@ -1548,72 +1044,42 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCheckBankAccountExists(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCheckBankAccountExists(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)) ), exampleInboundMessage = ( - InBoundCheckBankAccountExists(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCheckBankAccountExists(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /checkBankAccountExists + override def checkBankAccountExists(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundCheckBankAccountExists => OutBound, InBoundCheckBankAccountExists => InBound} - val url = getUrl(callContext, "checkBankAccountExists") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCheckBankAccountExists => InBound, OutBoundCheckBankAccountExists => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "checkBankAccountExists"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankAccountCommons](callContext)) } - + messageDocs += getCounterpartyTraitDoc def getCounterpartyTraitDoc = MessageDoc( process = "obp.getCounterpartyTrait", @@ -1622,154 +1088,44 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCounterpartyTrait(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCounterpartyTrait(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), couterpartyId="string") ), exampleInboundMessage = ( - InBoundGetCounterpartyTrait(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + InBoundGetCounterpartyTrait(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCounterpartyTrait + override def getCounterpartyTrait(bankId: BankId, accountId: AccountId, couterpartyId: String, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyTrait => OutBound, InBoundGetCounterpartyTrait => InBound} - val url = getUrl(callContext, "getCounterpartyTrait") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, couterpartyId) - val result: OBPReturnType[Box[CounterpartyTraitCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCounterpartyTrait => InBound, OutBoundGetCounterpartyTrait => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, couterpartyId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCounterpartyTrait"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CounterpartyTraitCommons](callContext)) } - - messageDocs += getCounterpartyByCounterpartyIdLegacyDoc - def getCounterpartyByCounterpartyIdLegacyDoc = MessageDoc( - process = "obp.getCounterpartyByCounterpartyIdLegacy", - messageFormat = messageFormat, - description = "Get Counterparty By Counterparty Id Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetCounterpartyByCounterpartyIdLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - counterpartyId=CounterpartyId(counterpartyIdExample.value)) - ), - exampleInboundMessage = ( - InBoundGetCounterpartyByCounterpartyIdLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", - currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", - counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, - isBeneficiary=isBeneficiaryExample.value.toBoolean, - bespoke=List( CounterpartyBespoke(key=keyExample.value, - value=valueExample.value)))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getCounterpartyByCounterpartyIdLegacy - override def getCounterpartyByCounterpartyIdLegacy(counterpartyId: CounterpartyId, callContext: Option[CallContext]): Box[(CounterpartyTrait, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyByCounterpartyIdLegacy => OutBound, InBoundGetCounterpartyByCounterpartyIdLegacy => InBound} - val url = getUrl(callContext, "getCounterpartyByCounterpartyIdLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , counterpartyId) - val result: OBPReturnType[Box[CounterpartyTraitCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getCounterpartyByCounterpartyIdDoc def getCounterpartyByCounterpartyIdDoc = MessageDoc( process = "obp.getCounterpartyByCounterpartyId", @@ -1778,75 +1134,42 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCounterpartyByCounterpartyId(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCounterpartyByCounterpartyId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, counterpartyId=CounterpartyId(counterpartyIdExample.value)) ), exampleInboundMessage = ( - InBoundGetCounterpartyByCounterpartyId(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + InBoundGetCounterpartyByCounterpartyId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCounterpartyByCounterpartyId + override def getCounterpartyByCounterpartyId(counterpartyId: CounterpartyId, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyByCounterpartyId => OutBound, InBoundGetCounterpartyByCounterpartyId => InBound} - val url = getUrl(callContext, "getCounterpartyByCounterpartyId") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , counterpartyId) - val result: OBPReturnType[Box[CounterpartyTraitCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCounterpartyByCounterpartyId => InBound, OutBoundGetCounterpartyByCounterpartyId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, counterpartyId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCounterpartyByCounterpartyId"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CounterpartyTraitCommons](callContext)) } - + messageDocs += getCounterpartyByIbanDoc def getCounterpartyByIbanDoc = MessageDoc( process = "obp.getCounterpartyByIban", @@ -1855,154 +1178,88 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCounterpartyByIban(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCounterpartyByIban(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, iban=ibanExample.value) ), exampleInboundMessage = ( - InBoundGetCounterpartyByIban(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + InBoundGetCounterpartyByIban(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCounterpartyByIban + override def getCounterpartyByIban(iban: String, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartyByIban => OutBound, InBoundGetCounterpartyByIban => InBound} - val url = getUrl(callContext, "getCounterpartyByIban") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , iban) - val result: OBPReturnType[Box[CounterpartyTraitCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCounterpartyByIban => InBound, OutBoundGetCounterpartyByIban => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCounterpartyByIban"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CounterpartyTraitCommons](callContext)) } - - messageDocs += getCounterpartiesLegacyDoc - def getCounterpartiesLegacyDoc = MessageDoc( - process = "obp.getCounterpartiesLegacy", + + messageDocs += getCounterpartyByIbanAndBankAccountIdDoc + def getCounterpartyByIbanAndBankAccountIdDoc = MessageDoc( + process = "obp.getCounterpartyByIbanAndBankAccountId", messageFormat = messageFormat, - description = "Get Counterparties Legacy", + description = "Get Counterparty By Iban And Bank Account Id", outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCounterpartiesLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), - viewId=ViewId(viewIdExample.value)) + OutBoundGetCounterpartyByIbanAndBankAccountId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + iban=ibanExample.value, + bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value)) ), exampleInboundMessage = ( - InBoundGetCounterpartiesLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + InBoundGetCounterpartyByIbanAndBankAccountId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, - value=valueExample.value))))) + value=valueExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCounterpartiesLegacy - override def getCounterpartiesLegacy(thisBankId: BankId, thisAccountId: AccountId, viewId: ViewId, callContext: Option[CallContext]): Box[(List[CounterpartyTrait], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterpartiesLegacy => OutBound, InBoundGetCounterpartiesLegacy => InBound} - val url = getUrl(callContext, "getCounterpartiesLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , thisBankId, thisAccountId, viewId) - val result: OBPReturnType[Box[List[CounterpartyTraitCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + + override def getCounterpartyByIbanAndBankAccountId(iban: String, bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[CounterpartyTrait]] = { + import com.openbankproject.commons.dto.{InBoundGetCounterpartyByIbanAndBankAccountId => InBound, OutBoundGetCounterpartyByIbanAndBankAccountId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, iban, bankId, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCounterpartyByIbanAndBankAccountId"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CounterpartyTraitCommons](callContext)) } - + messageDocs += getCounterpartiesDoc def getCounterpartiesDoc = MessageDoc( process = "obp.getCounterparties", @@ -2011,176 +1268,44 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCounterparties(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), + OutBoundGetCounterparties(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + thisBankId=BankId(thisBankIdExample.value), + thisAccountId=AccountId(thisAccountIdExample.value), viewId=ViewId(viewIdExample.value)) ), exampleInboundMessage = ( - InBoundGetCounterparties(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + InBoundGetCounterparties(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCounterparties + override def getCounterparties(thisBankId: BankId, thisAccountId: AccountId, viewId: ViewId, callContext: Option[CallContext]): OBPReturnType[Box[List[CounterpartyTrait]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCounterparties => OutBound, InBoundGetCounterparties => InBound} - val url = getUrl(callContext, "getCounterparties") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , thisBankId, thisAccountId, viewId) - val result: OBPReturnType[Box[List[CounterpartyTraitCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCounterparties => InBound, OutBoundGetCounterparties => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, thisBankId, thisAccountId, viewId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCounterparties"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CounterpartyTraitCommons]](callContext)) } - - messageDocs += getTransactionsLegacyDoc - def getTransactionsLegacyDoc = MessageDoc( - process = "obp.getTransactionsLegacy", - messageFormat = messageFormat, - description = "Get Transactions Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetTransactionsLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankId=BankId(bankIdExample.value), - accountId=AccountId(accountIdExample.value), - limit=limitExample.value.toInt, - offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") - ), - exampleInboundMessage = ( - InBoundGetTransactionsLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( Transaction(uuid=transactionUuidExample.value, - id=TransactionId(transactionIdExample.value), - thisAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), - accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), - currency=currencyExample.value, - name=bankAccountNameExample.value, - label=labelExample.value, - number=bankAccountNumberExample.value, - bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), - branchId=branchIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, - value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - otherAccount= Counterparty(nationalIdentifier=counterpartyNationalIdentifierExample.value, - kind=counterpartyKindExample.value, - counterpartyId=counterpartyIdExample.value, - counterpartyName=counterpartyNameExample.value, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), - otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, - otherBankRoutingAddress=Some(counterpartyOtherBankRoutingAddressExample.value), - otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, - otherAccountRoutingAddress=Some(counterpartyOtherAccountRoutingAddressExample.value), - otherAccountProvider=counterpartyOtherAccountProviderExample.value, - isBeneficiary=isBeneficiaryExample.value.toBoolean), - transactionType=transactionTypeExample.value, - amount=BigDecimal(transactionAmountExample.value), - currency=currencyExample.value, - description=Some(transactionDescriptionExample.value), - startDate=parseDate(transactionStartDateExample.value).getOrElse(sys.error("transactionStartDateExample.value is not validate date format.")), - finishDate=parseDate(transactionFinishDateExample.value).getOrElse(sys.error("transactionFinishDateExample.value is not validate date format.")), - balance=BigDecimal(balanceAmountExample.value)))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getTransactionsLegacy - override def getTransactionsLegacy(bankId: BankId, accountId: AccountId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Box[(List[Transaction], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionsLegacy => OutBound, InBoundGetTransactionsLegacy => InBound} - val url = getUrl(callContext, "getTransactionsLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[Transaction]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getTransactionsDoc def getTransactionsDoc = MessageDoc( process = "obp.getTransactions", @@ -2189,32 +1314,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetTransactions(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetTransactions(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), limit=limitExample.value.toInt, @@ -2223,38 +1323,34 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable toDate=outBoundGetTransactionsToDateExample.value) ), exampleInboundMessage = ( - InBoundGetTransactions(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetTransactions(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( Transaction(uuid=transactionUuidExample.value, id=TransactionId(transactionIdExample.value), thisAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), otherAccount= Counterparty(nationalIdentifier=counterpartyNationalIdentifierExample.value, kind=counterpartyKindExample.value, counterpartyId=counterpartyIdExample.value, counterpartyName=counterpartyNameExample.value, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), + thisBankId=BankId(thisBankIdExample.value), + thisAccountId=AccountId(thisAccountIdExample.value), otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, otherBankRoutingAddress=Some(counterpartyOtherBankRoutingAddressExample.value), otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, @@ -2265,21 +1361,20 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable amount=BigDecimal(transactionAmountExample.value), currency=currencyExample.value, description=Some(transactionDescriptionExample.value), - startDate=parseDate(transactionStartDateExample.value).getOrElse(sys.error("transactionStartDateExample.value is not validate date format.")), - finishDate=parseDate(transactionFinishDateExample.value).getOrElse(sys.error("transactionFinishDateExample.value is not validate date format.")), - balance=BigDecimal(balanceAmountExample.value)))) + startDate=toDate(transactionStartDateExample), + finishDate=toDate(transactionFinishDateExample), + balance=BigDecimal(balanceExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getTransactions + override def getTransactions(bankId: BankId, accountId: AccountId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): OBPReturnType[Box[List[Transaction]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactions => OutBound, InBoundGetTransactions => InBound} - val url = getUrl(callContext, "getTransactions") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[Transaction]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetTransactions => InBound, OutBoundGetTransactions => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactions"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[Transaction]](callContext)) } - + messageDocs += getTransactionsCoreDoc def getTransactionsCoreDoc = MessageDoc( process = "obp.getTransactionsCore", @@ -2288,191 +1383,65 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetTransactionsCore(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetTransactionsCore(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( - InBoundGetTransactionsCore(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( TransactionCore(id=TransactionId(transactionIdExample.value), + InBoundGetTransactionsCore(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( TransactionCore(id=TransactionId(idExample.value), thisAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - otherAccount= CounterpartyCore(kind="string", + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + otherAccount= CounterpartyCore(kind=kindExample.value, counterpartyId=counterpartyIdExample.value, counterpartyName=counterpartyNameExample.value, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=Some(bankRoutingAddressExample.value), - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=Some(accountRoutingAddressExample.value), + thisBankId=BankId(thisBankIdExample.value), + thisAccountId=AccountId(thisAccountIdExample.value), + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=Some(otherBankRoutingAddressExample.value), + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=Some(otherAccountRoutingAddressExample.value), otherAccountProvider=otherAccountProviderExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean), transactionType=transactionTypeExample.value, - amount=BigDecimal("123.321"), + amount=BigDecimal(amountExample.value), currency=currencyExample.value, - description=Some("string"), - startDate=new Date(), - finishDate=new Date(), - balance=BigDecimal(balanceAmountExample.value)))) + description=Some(descriptionExample.value), + startDate=toDate(startDateExample), + finishDate=toDate(finishDateExample), + balance=BigDecimal(balanceExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getTransactionsCore + override def getTransactionsCore(bankId: BankId, accountId: AccountId, queryParams: List[OBPQueryParam], callContext: Option[CallContext]): OBPReturnType[Box[List[TransactionCore]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionsCore => OutBound, InBoundGetTransactionsCore => InBound} - val url = getUrl(callContext, "getTransactionsCore") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[TransactionCore]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetTransactionsCore => InBound, OutBoundGetTransactionsCore => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactionsCore"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[TransactionCore]](callContext)) } - - messageDocs += getTransactionLegacyDoc - def getTransactionLegacyDoc = MessageDoc( - process = "obp.getTransactionLegacy", - messageFormat = messageFormat, - description = "Get Transaction Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetTransactionLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankId=BankId(bankIdExample.value), - accountId=AccountId(accountIdExample.value), - transactionId=TransactionId(transactionIdExample.value)) - ), - exampleInboundMessage = ( - InBoundGetTransactionLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= Transaction(uuid=transactionUuidExample.value, - id=TransactionId(transactionIdExample.value), - thisAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), - accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), - currency=currencyExample.value, - name=bankAccountNameExample.value, - label=labelExample.value, - number=bankAccountNumberExample.value, - bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), - branchId=branchIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, - value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - otherAccount= Counterparty(nationalIdentifier=counterpartyNationalIdentifierExample.value, - kind=counterpartyKindExample.value, - counterpartyId=counterpartyIdExample.value, - counterpartyName=counterpartyNameExample.value, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), - otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, - otherBankRoutingAddress=Some(counterpartyOtherBankRoutingAddressExample.value), - otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, - otherAccountRoutingAddress=Some(counterpartyOtherAccountRoutingAddressExample.value), - otherAccountProvider=counterpartyOtherAccountProviderExample.value, - isBeneficiary=isBeneficiaryExample.value.toBoolean), - transactionType=transactionTypeExample.value, - amount=BigDecimal(transactionAmountExample.value), - currency=currencyExample.value, - description=Some(transactionDescriptionExample.value), - startDate=parseDate(transactionStartDateExample.value).getOrElse(sys.error("transactionStartDateExample.value is not validate date format.")), - finishDate=parseDate(transactionFinishDateExample.value).getOrElse(sys.error("transactionFinishDateExample.value is not validate date format.")), - balance=BigDecimal(balanceAmountExample.value))) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getTransactionLegacy - override def getTransactionLegacy(bankId: BankId, accountId: AccountId, transactionId: TransactionId, callContext: Option[CallContext]): Box[(Transaction, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionLegacy => OutBound, InBoundGetTransactionLegacy => InBound} - val url = getUrl(callContext, "getTransactionLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, transactionId) - val result: OBPReturnType[Box[Transaction]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getTransactionDoc def getTransactionDoc = MessageDoc( process = "obp.getTransaction", @@ -2481,69 +1450,40 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetTransaction(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetTransaction(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), transactionId=TransactionId(transactionIdExample.value)) ), exampleInboundMessage = ( - InBoundGetTransaction(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetTransaction(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= Transaction(uuid=transactionUuidExample.value, id=TransactionId(transactionIdExample.value), thisAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), otherAccount= Counterparty(nationalIdentifier=counterpartyNationalIdentifierExample.value, kind=counterpartyKindExample.value, counterpartyId=counterpartyIdExample.value, counterpartyName=counterpartyNameExample.value, - thisBankId=BankId(bankIdExample.value), - thisAccountId=AccountId(accountIdExample.value), + thisBankId=BankId(thisBankIdExample.value), + thisAccountId=AccountId(thisAccountIdExample.value), otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, otherBankRoutingAddress=Some(counterpartyOtherBankRoutingAddressExample.value), otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, @@ -2554,21 +1494,92 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable amount=BigDecimal(transactionAmountExample.value), currency=currencyExample.value, description=Some(transactionDescriptionExample.value), - startDate=parseDate(transactionStartDateExample.value).getOrElse(sys.error("transactionStartDateExample.value is not validate date format.")), - finishDate=parseDate(transactionFinishDateExample.value).getOrElse(sys.error("transactionFinishDateExample.value is not validate date format.")), - balance=BigDecimal(balanceAmountExample.value))) + startDate=toDate(transactionStartDateExample), + finishDate=toDate(transactionFinishDateExample), + balance=BigDecimal(balanceExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getTransaction + override def getTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId, callContext: Option[CallContext]): OBPReturnType[Box[Transaction]] = { - import com.openbankproject.commons.dto.{OutBoundGetTransaction => OutBound, InBoundGetTransaction => InBound} - val url = getUrl(callContext, "getTransaction") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, transactionId) - val result: OBPReturnType[Box[Transaction]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetTransaction => InBound, OutBoundGetTransaction => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, transactionId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransaction"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Transaction](callContext)) } - + + messageDocs += getPhysicalCardsForUserDoc + def getPhysicalCardsForUserDoc = MessageDoc( + process = "obp.getPhysicalCardsForUser", + messageFormat = messageFormat, + description = "Get Physical Cards For User", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetPhysicalCardsForUser( UserCommons(userPrimaryKey=UserPrimaryKey(123), + userId=userIdExample.value, + idGivenByProvider="string", + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true))) + ), + exampleInboundMessage = ( + InBoundGetPhysicalCardsForUser(status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( PhysicalCard(cardId=cardIdExample.value, + bankId=bankIdExample.value, + bankCardNumber=bankCardNumberExample.value, + cardType=cardTypeExample.value, + nameOnCard=nameOnCardExample.value, + issueNumber=issueNumberExample.value, + serialNumber=serialNumberExample.value, + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, + allows=List(com.openbankproject.commons.model.CardAction.DEBIT), + account= BankAccountCommons(accountId=AccountId(accountIdExample.value), + accountType=accountTypeExample.value, + balance=BigDecimal(balanceExample.value), + currency=currencyExample.value, + name=bankAccountNameExample.value, + label=labelExample.value, + number=accountNumberExample.value, + bankId=BankId(bankIdExample.value), + lastUpdate=toDate(bankAccountLastUpdateExample), + branchId=branchIdExample.value, + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, + value=accountRuleValueExample.value)), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), + reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), + reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), + customerId=customerIdExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getPhysicalCardsForUser(user: User): Box[List[PhysicalCard]] = { + import com.openbankproject.commons.dto.{InBoundGetPhysicalCardsForUser => InBound, OutBoundGetPhysicalCardsForUser => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(user) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getPhysicalCardsForUser"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[PhysicalCard]](callContext)) + } + messageDocs += getPhysicalCardForBankDoc def getPhysicalCardForBankDoc = MessageDoc( process = "obp.getPhysicalCardForBank", @@ -2577,45 +1588,13 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetPhysicalCardForBank(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetPhysicalCardForBank(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), cardId=cardIdExample.value) ), exampleInboundMessage = ( - InBoundGetPhysicalCardForBank(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetPhysicalCardForBank(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= PhysicalCard(cardId=cardIdExample.value, bankId=bankIdExample.value, bankCardNumber=bankCardNumberExample.value, @@ -2623,48 +1602,50 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getPhysicalCardForBank + override def getPhysicalCardForBank(bankId: BankId, cardId: String, callContext: Option[CallContext]): OBPReturnType[Box[PhysicalCardTrait]] = { - import com.openbankproject.commons.dto.{OutBoundGetPhysicalCardForBank => OutBound, InBoundGetPhysicalCardForBank => InBound} - val url = getUrl(callContext, "getPhysicalCardForBank") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, cardId) - val result: OBPReturnType[Box[PhysicalCard]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetPhysicalCardForBank => InBound, OutBoundGetPhysicalCardForBank => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, cardId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getPhysicalCardForBank"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[PhysicalCard](callContext)) } - + messageDocs += deletePhysicalCardForBankDoc def deletePhysicalCardForBankDoc = MessageDoc( process = "obp.deletePhysicalCardForBank", @@ -2673,58 +1654,25 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundDeletePhysicalCardForBank(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundDeletePhysicalCardForBank(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), cardId=cardIdExample.value) ), exampleInboundMessage = ( - InBoundDeletePhysicalCardForBank(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundDeletePhysicalCardForBank(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /deletePhysicalCardForBank + override def deletePhysicalCardForBank(bankId: BankId, cardId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeletePhysicalCardForBank => OutBound, InBoundDeletePhysicalCardForBank => InBound} - val url = getUrl(callContext, "deletePhysicalCardForBank") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, cardId) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.DELETE, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundDeletePhysicalCardForBank => InBound, OutBoundDeletePhysicalCardForBank => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, cardId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deletePhysicalCardForBank"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += getPhysicalCardsForBankDoc def getPhysicalCardsForBankDoc = MessageDoc( process = "obp.getPhysicalCardsForBank", @@ -2733,32 +1681,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetPhysicalCardsForBank(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetPhysicalCardsForBank(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bank= BankCommons(bankId=BankId(bankIdExample.value), shortName=bankShortNameExample.value, fullName=bankFullNameExample.value, @@ -2771,24 +1694,20 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( - InBoundGetPhysicalCardsForBank(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetPhysicalCardsForBank(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( PhysicalCard(cardId=cardIdExample.value, bankId=bankIdExample.value, bankCardNumber=bankCardNumberExample.value, @@ -2796,164 +1715,50 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getPhysicalCardsForBank + override def getPhysicalCardsForBank(bank: Bank, user: User, queryParams: List[OBPQueryParam], callContext: Option[CallContext]): OBPReturnType[Box[List[PhysicalCard]]] = { - import com.openbankproject.commons.dto.{OutBoundGetPhysicalCardsForBank => OutBound, InBoundGetPhysicalCardsForBank => InBound} - val url = getUrl(callContext, "getPhysicalCardsForBank") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bank, user, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[PhysicalCard]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetPhysicalCardsForBank => InBound, OutBoundGetPhysicalCardsForBank => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bank, user, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getPhysicalCardsForBank"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[PhysicalCard]](callContext)) } - - messageDocs += createPhysicalCardLegacyDoc - def createPhysicalCardLegacyDoc = MessageDoc( - process = "obp.createPhysicalCardLegacy", - messageFormat = messageFormat, - description = "Create Physical Card Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundCreatePhysicalCardLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bankCardNumber=bankCardNumberExample.value, - nameOnCard=nameOnCardExample.value, - cardType=cardTypeExample.value, - issueNumber=issueNumberExample.value, - serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), - allows=List("string"), - accountId=accountIdExample.value, - bankId=bankIdExample.value, - replacement=Some( CardReplacementInfo(requestedDate=new Date(), - reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), - reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), - customerId=customerIdExample.value) - ), - exampleInboundMessage = ( - InBoundCreatePhysicalCardLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= PhysicalCard(cardId=cardIdExample.value, - bankId=bankIdExample.value, - bankCardNumber=bankCardNumberExample.value, - cardType=cardTypeExample.value, - nameOnCard=nameOnCardExample.value, - issueNumber=issueNumberExample.value, - serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), - allows=List(com.openbankproject.commons.model.CardAction.DEBIT), - account= BankAccountCommons(accountId=AccountId(accountIdExample.value), - accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), - currency=currencyExample.value, - name=bankAccountNameExample.value, - label=labelExample.value, - number=accountNumberExample.value, - bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), - branchId=branchIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, - value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), - reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), - reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), - customerId=customerIdExample.value)) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /createPhysicalCardLegacy - override def createPhysicalCardLegacy(bankCardNumber: String, nameOnCard: String, cardType: String, issueNumber: String, serialNumber: String, validFrom: Date, expires: Date, enabled: Boolean, cancelled: Boolean, onHotList: Boolean, technology: String, networks: List[String], allows: List[String], accountId: String, bankId: String, replacement: Option[CardReplacementInfo], pinResets: List[PinResetInfo], collected: Option[CardCollectionInfo], posted: Option[CardPostedInfo], customerId: String, callContext: Option[CallContext]): Box[PhysicalCard] = { - import com.openbankproject.commons.dto.{OutBoundCreatePhysicalCardLegacy => OutBound, InBoundCreatePhysicalCardLegacy => InBound} - val url = getUrl(callContext, "createPhysicalCardLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) - val result: OBPReturnType[Box[PhysicalCard]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += createPhysicalCardDoc def createPhysicalCardDoc = MessageDoc( process = "obp.createPhysicalCard", @@ -2962,65 +1767,33 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreatePhysicalCard(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreatePhysicalCard(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankCardNumber=bankCardNumberExample.value, nameOnCard=nameOnCardExample.value, cardType=cardTypeExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), - allows=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, + allows=allowsExample.value.split("[,;]").toList, accountId=accountIdExample.value, bankId=bankIdExample.value, - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundCreatePhysicalCard(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreatePhysicalCard(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= PhysicalCard(cardId=cardIdExample.value, bankId=bankIdExample.value, bankCardNumber=bankCardNumberExample.value, @@ -3028,48 +1801,50 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createPhysicalCard + override def createPhysicalCard(bankCardNumber: String, nameOnCard: String, cardType: String, issueNumber: String, serialNumber: String, validFrom: Date, expires: Date, enabled: Boolean, cancelled: Boolean, onHotList: Boolean, technology: String, networks: List[String], allows: List[String], accountId: String, bankId: String, replacement: Option[CardReplacementInfo], pinResets: List[PinResetInfo], collected: Option[CardCollectionInfo], posted: Option[CardPostedInfo], customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[PhysicalCard]] = { - import com.openbankproject.commons.dto.{OutBoundCreatePhysicalCard => OutBound, InBoundCreatePhysicalCard => InBound} - val url = getUrl(callContext, "createPhysicalCard") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) - val result: OBPReturnType[Box[PhysicalCard]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreatePhysicalCard => InBound, OutBoundCreatePhysicalCard => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createPhysicalCard"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[PhysicalCard](callContext)) } - + messageDocs += updatePhysicalCardDoc def updatePhysicalCardDoc = MessageDoc( process = "obp.updatePhysicalCard", @@ -3078,66 +1853,34 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdatePhysicalCard(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundUpdatePhysicalCard(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, cardId=cardIdExample.value, bankCardNumber=bankCardNumberExample.value, nameOnCard=nameOnCardExample.value, cardType=cardTypeExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), - allows=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, + allows=allowsExample.value.split("[,;]").toList, accountId=accountIdExample.value, bankId=bankIdExample.value, - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundUpdatePhysicalCard(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundUpdatePhysicalCard(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= PhysicalCard(cardId=cardIdExample.value, bankId=bankIdExample.value, bankCardNumber=bankCardNumberExample.value, @@ -3145,48 +1888,50 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable nameOnCard=nameOnCardExample.value, issueNumber=issueNumberExample.value, serialNumber=serialNumberExample.value, - validFrom=new Date(), - expires=new Date(), - enabled=true, - cancelled=true, - onHotList=true, - technology="string", - networks=List("string"), + validFrom=toDate(validFromExample), + expires=toDate(expiresDateExample), + enabled=enabledExample.value.toBoolean, + cancelled=cancelledExample.value.toBoolean, + onHotList=onHotListExample.value.toBoolean, + technology=technologyExample.value, + networks=networksExample.value.split("[,;]").toList, allows=List(com.openbankproject.commons.model.CardAction.DEBIT), account= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=accountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - replacement=Some( CardReplacementInfo(requestedDate=new Date(), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + replacement=Some( CardReplacementInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.CardReplacementReason.FIRST)), - pinResets=List( PinResetInfo(requestedDate=new Date(), + pinResets=List( PinResetInfo(requestedDate=toDate(requestedDateExample), reasonRequested=com.openbankproject.commons.model.PinResetReason.FORGOT)), - collected=Some(CardCollectionInfo(new Date())), - posted=Some(CardPostedInfo(new Date())), + collected=Some(CardCollectionInfo(toDate(collectedExample))), + posted=Some(CardPostedInfo(toDate(postedExample))), customerId=customerIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updatePhysicalCard + override def updatePhysicalCard(cardId: String, bankCardNumber: String, nameOnCard: String, cardType: String, issueNumber: String, serialNumber: String, validFrom: Date, expires: Date, enabled: Boolean, cancelled: Boolean, onHotList: Boolean, technology: String, networks: List[String], allows: List[String], accountId: String, bankId: String, replacement: Option[CardReplacementInfo], pinResets: List[PinResetInfo], collected: Option[CardCollectionInfo], posted: Option[CardPostedInfo], customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[PhysicalCardTrait]] = { - import com.openbankproject.commons.dto.{OutBoundUpdatePhysicalCard => OutBound, InBoundUpdatePhysicalCard => InBound} - val url = getUrl(callContext, "updatePhysicalCard") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , cardId, bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) - val result: OBPReturnType[Box[PhysicalCard]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdatePhysicalCard => InBound, OutBoundUpdatePhysicalCard => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, cardId, bankCardNumber, nameOnCard, cardType, issueNumber, serialNumber, validFrom, expires, enabled, cancelled, onHotList, technology, networks, allows, accountId, bankId, replacement, pinResets, collected, posted, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updatePhysicalCard"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[PhysicalCard](callContext)) } - + messageDocs += makePaymentv210Doc def makePaymentv210Doc = MessageDoc( process = "obp.makePaymentv210", @@ -3195,94 +1940,67 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundMakePaymentv210(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundMakePaymentv210(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - transactionRequestId = TransactionRequestId(uuidExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transactionRequestId=TransactionRequestId(transactionRequestIdExample.value), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), - amount=BigDecimal("123.321"), - description="string", + amount=amountExample.value), + description=descriptionExample.value), + amount=BigDecimal(amountExample.value), + description=descriptionExample.value, transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( - InBoundMakePaymentv210(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundMakePaymentv210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=TransactionId(transactionIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /makePaymentv210 + override def makePaymentv210(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestId: TransactionRequestId, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amount: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionId]] = { - import com.openbankproject.commons.dto.{OutBoundMakePaymentv210 => OutBound, InBoundMakePaymentv210 => InBound} - val url = getUrl(callContext, "makePaymentv210") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , fromAccount, toAccount, transactionRequestId, transactionRequestCommonBody, amount, description, transactionRequestType, chargePolicy) - val result: OBPReturnType[Box[TransactionId]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundMakePaymentv210 => InBound, OutBoundMakePaymentv210 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccount, toAccount, transactionRequestId, transactionRequestCommonBody, amount, description, transactionRequestType, chargePolicy) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "makePaymentv210"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionId](callContext)) } - + messageDocs += createTransactionRequestv210Doc def createTransactionRequestv210Doc = MessageDoc( process = "obp.createTransactionRequestv210", @@ -3291,145 +2009,122 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateTransactionRequestv210(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateTransactionRequestv210(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), detailsPlain="string", - chargePolicy="string", - challengeType=Some("string"), + chargePolicy=chargePolicyExample.value, + challengeType=Some(challengeTypeExample.value), scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS)) ), exampleInboundMessage = ( - InBoundCreateTransactionRequestv210(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= TransactionRequest(id=TransactionRequestId("string"), + InBoundCreateTransactionRequestv210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -3442,15 +2137,190 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createTransactionRequestv210 - override def createTransactionRequestv210(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, challengeType: Option[String], scaMethod: Option[SCA], callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionRequestv210 => OutBound, InBoundCreateTransactionRequestv210 => InBound} - val url = getUrl(callContext, "createTransactionRequestv210") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , initiator, viewId, fromAccount, toAccount, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy, challengeType, scaMethod) - val result: OBPReturnType[Box[TransactionRequest]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + + override def createTransactionRequestv210(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, challengeType: Option[String], scaMethod: Option[StrongCustomerAuthentication.SCA], callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { + import com.openbankproject.commons.dto.{InBoundCreateTransactionRequestv210 => InBound, OutBoundCreateTransactionRequestv210 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, viewId, fromAccount, toAccount, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy, challengeType, scaMethod) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createTransactionRequestv210"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionRequest](callContext)) } - + + messageDocs += createTransactionRequestv400Doc + def createTransactionRequestv400Doc = MessageDoc( + process = "obp.createTransactionRequestv400", + messageFormat = messageFormat, + description = "Create Transaction Requestv400", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateTransactionRequestv400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), + userId=userIdExample.value, + idGivenByProvider="string", + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), + viewId=ViewId(viewIdExample.value), + fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), + accountType=accountTypeExample.value, + balance=BigDecimal(balanceExample.value), + currency=currencyExample.value, + name=bankAccountNameExample.value, + label=labelExample.value, + number=bankAccountNumberExample.value, + bankId=BankId(bankIdExample.value), + lastUpdate=toDate(bankAccountLastUpdateExample), + branchId=branchIdExample.value, + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, + value=accountRuleValueExample.value)), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), + accountType=accountTypeExample.value, + balance=BigDecimal(balanceExample.value), + currency=currencyExample.value, + name=bankAccountNameExample.value, + label=labelExample.value, + number=bankAccountNumberExample.value, + bankId=BankId(bankIdExample.value), + lastUpdate=toDate(bankAccountLastUpdateExample), + branchId=branchIdExample.value, + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value)), + accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, + value=accountRuleValueExample.value)), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), + transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value), + detailsPlain="string", + chargePolicy=chargePolicyExample.value, + challengeType=Some(challengeTypeExample.value), + scaMethod=Some(com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SMS), + reasons=Some(List( TransactionRequestReason(code=codeExample.value, + documentNumber=Some(documentNumberExample.value), + amount=Some(amountExample.value), + currency=Some(currencyExample.value), + description=Some(descriptionExample.value)))), + berlinGroupPayments=Some( SepaCreditTransfersBerlinGroupV13(endToEndIdentification=Some("string"), + instructionIdentification=Some("string"), + debtorName=Some("string"), + debtorAccount=PaymentAccount("string"), + debtorId=Some("string"), + ultimateDebtor=Some("string"), + instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + currencyOfTransfer=Some("string"), + exchangeRateInformation=Some("string"), + creditorAccount=PaymentAccount("string"), + creditorAgent=Some("string"), + creditorAgentName=Some("string"), + creditorName="string", + creditorId=Some("string"), + creditorAddress=Some("string"), + creditorNameAndAddress=Some("string"), + ultimateCreditor=Some("string"), + purposeCode=Some("string"), + chargeBearer=Some("string"), + serviceLevel=Some("string"), + remittanceInformationUnstructured=Some("string"), + remittanceInformationUnstructuredArray=Some("string"), + remittanceInformationStructured=Some("string"), + remittanceInformationStructuredArray=Some("string"), + requestedExecutionDate=Some("string"), + requestedExecutionTime=Some("string")))) + ), + exampleInboundMessage = ( + InBoundCreateTransactionRequestv400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), + `type`=transactionRequestTypeExample.value, + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), + to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), + to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to= ToAccountTransferToAtm(legal_name="string", + date_of_birth="string", + mobile_phone_number="string", + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), + to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + transfer_type="string", + future_date="string", + to= ToAccountTransferToAccount(name=nameExample.value, + bank_code="string", + branch_number="string", + account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, + iban=ibanExample.value)))), + to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), + instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + creditorAccount=PaymentAccount("string"), + creditorName="string")), + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value), + transaction_ids="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, + allowed_attempts=123, + challenge_type="string"), + charge= TransactionRequestCharge(summary=summaryExample.value, + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value)), + charge_policy="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, + this_bank_id=BankId(bankIdExample.value), + this_account_id=AccountId(accountIdExample.value), + this_view_id=ViewId(viewIdExample.value), + other_account_routing_scheme="string", + other_account_routing_address="string", + other_bank_routing_scheme="string", + other_bank_routing_address="string", + is_beneficiary=true, + future_date=Some("string"))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createTransactionRequestv400(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, challengeType: Option[String], scaMethod: Option[StrongCustomerAuthentication.SCA], reasons: Option[List[TransactionRequestReason]], berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13], callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { + import com.openbankproject.commons.dto.{InBoundCreateTransactionRequestv400 => InBound, OutBoundCreateTransactionRequestv400 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, viewId, fromAccount, toAccount, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy, challengeType, scaMethod, reasons, berlinGroupPayments) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createTransactionRequestv400"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionRequest](callContext)) + } + messageDocs += getTransactionRequests210Doc def getTransactionRequests210Doc = MessageDoc( process = "obp.getTransactionRequests210", @@ -3459,121 +2329,95 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetTransactionRequests210(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetTransactionRequests210(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), exampleInboundMessage = ( - InBoundGetTransactionRequests210(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( TransactionRequest(id=TransactionRequestId("string"), + InBoundGetTransactionRequests210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -3586,15 +2430,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getTransactionRequests210 + override def getTransactionRequests210(initiator: User, fromAccount: BankAccount, callContext: Option[CallContext]): Box[(List[TransactionRequest], Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionRequests210 => OutBound, InBoundGetTransactionRequests210 => InBound} - val url = getUrl(callContext, "getTransactionRequests210") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , initiator, fromAccount) - val result: OBPReturnType[Box[List[TransactionRequest]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetTransactionRequests210 => InBound, OutBoundGetTransactionRequests210 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, fromAccount) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactionRequests210"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[TransactionRequest]](callContext)) } - + messageDocs += getTransactionRequestImplDoc def getTransactionRequestImplDoc = MessageDoc( process = "obp.getTransactionRequestImpl", @@ -3603,101 +2446,69 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetTransactionRequestImpl(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - transactionRequestId=TransactionRequestId("string")) + OutBoundGetTransactionRequestImpl(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequestId=TransactionRequestId(transactionRequestIdExample.value)) ), exampleInboundMessage = ( - InBoundGetTransactionRequestImpl(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= TransactionRequest(id=TransactionRequestId("string"), + InBoundGetTransactionRequestImpl(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -3710,15 +2521,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getTransactionRequestImpl + override def getTransactionRequestImpl(transactionRequestId: TransactionRequestId, callContext: Option[CallContext]): Box[(TransactionRequest, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetTransactionRequestImpl => OutBound, InBoundGetTransactionRequestImpl => InBound} - val url = getUrl(callContext, "getTransactionRequestImpl") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , transactionRequestId) - val result: OBPReturnType[Box[TransactionRequest]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetTransactionRequestImpl => InBound, OutBoundGetTransactionRequestImpl => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequestId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactionRequestImpl"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionRequest](callContext)) } - + messageDocs += createTransactionAfterChallengeV210Doc def createTransactionAfterChallengeV210Doc = MessageDoc( process = "obp.createTransactionAfterChallengeV210", @@ -3727,104 +2537,82 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateTransactionAfterChallengeV210(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateTransactionAfterChallengeV210(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - transactionRequest= TransactionRequest(id=TransactionRequestId("string"), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transactionRequest= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -3836,72 +2624,65 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable future_date=Some("string"))) ), exampleInboundMessage = ( - InBoundCreateTransactionAfterChallengeV210(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= TransactionRequest(id=TransactionRequestId("string"), + InBoundCreateTransactionAfterChallengeV210(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -3914,15 +2695,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createTransactionAfterChallengeV210 + override def createTransactionAfterChallengeV210(fromAccount: BankAccount, transactionRequest: TransactionRequest, callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionAfterChallengeV210 => OutBound, InBoundCreateTransactionAfterChallengeV210 => InBound} - val url = getUrl(callContext, "createTransactionAfterChallengeV210") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , fromAccount, transactionRequest) - val result: OBPReturnType[Box[TransactionRequest]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateTransactionAfterChallengeV210 => InBound, OutBoundCreateTransactionAfterChallengeV210 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccount, transactionRequest) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createTransactionAfterChallengeV210"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionRequest](callContext)) } - + messageDocs += updateBankAccountDoc def updateBankAccountDoc = MessageDoc( process = "obp.updateBankAccount", @@ -3931,76 +2711,47 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdateBankAccount(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundUpdateBankAccount(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, accountLabel="string", branchId=branchIdExample.value, - accountRoutings=List(AccountRouting(accountRoutingSchemeExample.value, accountRoutingAddressExample.value))) + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value))) ), exampleInboundMessage = ( - InBoundUpdateBankAccount(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundUpdateBankAccount(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updateBankAccount + override def updateBankAccount(bankId: BankId, accountId: AccountId, accountType: String, accountLabel: String, branchId: String, accountRoutings: List[AccountRouting], callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateBankAccount => OutBound, InBoundUpdateBankAccount => InBound} - val url = getUrl(callContext, "updateBankAccount") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, accountType, accountLabel, branchId, accountRoutings) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdateBankAccount => InBound, OutBoundUpdateBankAccount => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, accountType, accountLabel, branchId, accountRoutings) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updateBankAccount"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankAccountCommons](callContext)) } - + messageDocs += createBankAccountDoc def createBankAccountDoc = MessageDoc( process = "obp.createBankAccount", @@ -4009,32 +2760,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateBankAccount(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateBankAccount(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, @@ -4043,46 +2769,142 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable initialBalance=BigDecimal("123.321"), accountHolderName="string", branchId=branchIdExample.value, - List(AccountRouting(accountRoutingSchemeExample.value, accountRoutingAddressExample.value)) - ) + accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, + address=accountRoutingAddressExample.value))) ), exampleInboundMessage = ( - InBoundCreateBankAccount(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateBankAccount(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value)) + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createBankAccount + override def createBankAccount(bankId: BankId, accountId: AccountId, accountType: String, accountLabel: String, currency: String, initialBalance: BigDecimal, accountHolderName: String, branchId: String, accountRoutings: List[AccountRouting], callContext: Option[CallContext]): OBPReturnType[Box[BankAccount]] = { - import com.openbankproject.commons.dto.{OutBoundCreateBankAccount => OutBound, InBoundCreateBankAccount => InBound} - val url = getUrl(callContext, "createBankAccount") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, accountType, accountLabel, currency, initialBalance, accountHolderName, branchId, accountRoutings) - val result: OBPReturnType[Box[BankAccountCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateBankAccount => InBound, OutBoundCreateBankAccount => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, accountType, accountLabel, currency, initialBalance, accountHolderName, branchId, accountRoutings) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createBankAccount"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BankAccountCommons](callContext)) } - + + messageDocs += accountExistsDoc + def accountExistsDoc = MessageDoc( + process = "obp.accountExists", + messageFormat = messageFormat, + description = "Account Exists", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundAccountExists(bankId=BankId(bankIdExample.value), + accountNumber=accountNumberExample.value) + ), + exampleInboundMessage = ( + InBoundAccountExists(status=MessageDocsSwaggerDefinitions.inboundStatus, + data=true) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def accountExists(bankId: BankId, accountNumber: String): Box[Boolean] = { + import com.openbankproject.commons.dto.{InBoundAccountExists => InBound, OutBoundAccountExists => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, accountNumber) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "accountExists"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) + } + + messageDocs += getProductsDoc + def getProductsDoc = MessageDoc( + process = "obp.getProducts", + messageFormat = messageFormat, + description = "Get Products", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetProducts(bankId=BankId(bankIdExample.value), + params=List( GetProductsParam(name=nameExample.value, + value=valueExample.value.split("[,;]").toList))) + ), + exampleInboundMessage = ( + InBoundGetProducts(status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCommons(bankId=BankId(bankIdExample.value), + code=ProductCode(productCodeExample.value), + parentProductCode=ProductCode(parentProductCodeExample.value), + name=nameExample.value, + category=categoryExample.value, + family=familyExample.value, + superFamily=superFamilyExample.value, + moreInfoUrl=moreInfoUrlExample.value, + details=detailsExample.value, + description=descriptionExample.value, + meta=Meta( License(id=idExample.value, + name=nameExample.value))))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getProducts(bankId: BankId, params: List[GetProductsParam]): Box[List[Product]] = { + import com.openbankproject.commons.dto.{InBoundGetProducts => InBound, OutBoundGetProducts => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, params) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProducts"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductCommons]](callContext)) + } + + messageDocs += getProductDoc + def getProductDoc = MessageDoc( + process = "obp.getProduct", + messageFormat = messageFormat, + description = "Get Product", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetProduct(bankId=BankId(bankIdExample.value), + productCode=ProductCode(productCodeExample.value)) + ), + exampleInboundMessage = ( + InBoundGetProduct(status=MessageDocsSwaggerDefinitions.inboundStatus, + data= ProductCommons(bankId=BankId(bankIdExample.value), + code=ProductCode(productCodeExample.value), + parentProductCode=ProductCode(parentProductCodeExample.value), + name=nameExample.value, + category=categoryExample.value, + family=familyExample.value, + superFamily=superFamilyExample.value, + moreInfoUrl=moreInfoUrlExample.value, + details=detailsExample.value, + description=descriptionExample.value, + meta=Meta( License(id=idExample.value, + name=nameExample.value)))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getProduct(bankId: BankId, productCode: ProductCode): Box[Product] = { + import com.openbankproject.commons.dto.{InBoundGetProduct => InBound, OutBoundGetProduct => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, productCode) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProduct"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[ProductCommons](callContext)) + } + messageDocs += getBranchDoc def getBranchDoc = MessageDoc( process = "obp.getBranch", @@ -4091,114 +2913,81 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBranch(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBranch(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), branchId=BranchId(branchIdExample.value)) ), exampleInboundMessage = ( - InBoundGetBranch(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBranch(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= BranchTCommons(branchId=BranchId(branchIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), lobbyString=Some(LobbyString("string")), driveUpString=Some(DriveUpString("string")), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), branchRouting=Some( Routing(scheme=branchRoutingSchemeExample.value, address=branchRoutingAddressExample.value)), - lobby=Some( Lobby(monday=List( OpeningTimes(openingTime="string", - closingTime="string")), - tuesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - wednesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - thursday=List( OpeningTimes(openingTime="string", - closingTime="string")), - friday=List( OpeningTimes(openingTime="string", - closingTime="string")), - saturday=List( OpeningTimes(openingTime="string", - closingTime="string")), - sunday=List( OpeningTimes(openingTime="string", - closingTime="string")))), - driveUp=Some( DriveUp(monday= OpeningTimes(openingTime="string", - closingTime="string"), - tuesday= OpeningTimes(openingTime="string", - closingTime="string"), - wednesday= OpeningTimes(openingTime="string", - closingTime="string"), - thursday= OpeningTimes(openingTime="string", - closingTime="string"), - friday= OpeningTimes(openingTime="string", - closingTime="string"), - saturday= OpeningTimes(openingTime="string", - closingTime="string"), - sunday= OpeningTimes(openingTime="string", - closingTime="string"))), - isAccessible=Some(true), + lobby=Some( Lobby(monday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + tuesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + wednesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + thursday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + friday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + saturday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + sunday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)))), + driveUp=Some( DriveUp(monday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + tuesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + wednesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + thursday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + friday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + saturday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + sunday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value))), + isAccessible=Some(isAccessibleExample.value.toBoolean), accessibleFeatures=Some("string"), - branchType=Some("string"), - moreInfo=Some("string"), - phoneNumber=Some("string"), + branchType=Some(branchTypeExample.value), + moreInfo=Some(moreInfoExample.value), + phoneNumber=Some(phoneNumberExample.value), isDeleted=Some(true))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBranch + override def getBranch(bankId: BankId, branchId: BranchId, callContext: Option[CallContext]): Future[Box[(BranchT, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBranch => OutBound, InBoundGetBranch => InBound} - val url = getUrl(callContext, "getBranch") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, branchId) - val result: OBPReturnType[Box[BranchTCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBranch => InBound, OutBoundGetBranch => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, branchId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBranch"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[BranchTCommons](callContext)) } - + messageDocs += getBranchesDoc def getBranchesDoc = MessageDoc( process = "obp.getBranches", @@ -4207,117 +2996,84 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetBranches(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetBranches(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( - InBoundGetBranches(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetBranches(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( BranchTCommons(branchId=BranchId(branchIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), lobbyString=Some(LobbyString("string")), driveUpString=Some(DriveUpString("string")), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), branchRouting=Some( Routing(scheme=branchRoutingSchemeExample.value, address=branchRoutingAddressExample.value)), - lobby=Some( Lobby(monday=List( OpeningTimes(openingTime="string", - closingTime="string")), - tuesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - wednesday=List( OpeningTimes(openingTime="string", - closingTime="string")), - thursday=List( OpeningTimes(openingTime="string", - closingTime="string")), - friday=List( OpeningTimes(openingTime="string", - closingTime="string")), - saturday=List( OpeningTimes(openingTime="string", - closingTime="string")), - sunday=List( OpeningTimes(openingTime="string", - closingTime="string")))), - driveUp=Some( DriveUp(monday= OpeningTimes(openingTime="string", - closingTime="string"), - tuesday= OpeningTimes(openingTime="string", - closingTime="string"), - wednesday= OpeningTimes(openingTime="string", - closingTime="string"), - thursday= OpeningTimes(openingTime="string", - closingTime="string"), - friday= OpeningTimes(openingTime="string", - closingTime="string"), - saturday= OpeningTimes(openingTime="string", - closingTime="string"), - sunday= OpeningTimes(openingTime="string", - closingTime="string"))), - isAccessible=Some(true), + lobby=Some( Lobby(monday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + tuesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + wednesday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + thursday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + friday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + saturday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)), + sunday=List( OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value)))), + driveUp=Some( DriveUp(monday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + tuesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + wednesday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + thursday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + friday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + saturday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value), + sunday= OpeningTimes(openingTime=openingTimeExample.value, + closingTime=closingTimeExample.value))), + isAccessible=Some(isAccessibleExample.value.toBoolean), accessibleFeatures=Some("string"), - branchType=Some("string"), - moreInfo=Some("string"), - phoneNumber=Some("string"), + branchType=Some(branchTypeExample.value), + moreInfo=Some(moreInfoExample.value), + phoneNumber=Some(phoneNumberExample.value), isDeleted=Some(true)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getBranches + override def getBranches(bankId: BankId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Future[Box[(List[BranchT], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetBranches => OutBound, InBoundGetBranches => InBound} - val url = getUrl(callContext, "getBranches") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[BranchTCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetBranches => InBound, OutBoundGetBranches => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getBranches"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[BranchTCommons]](callContext)) } - + messageDocs += getAtmDoc def getAtmDoc = MessageDoc( process = "obp.getAtm", @@ -4326,64 +3082,32 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAtm(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetAtm(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), - atmId=AtmId("string")) + atmId=AtmId(atmIdExample.value)) ), exampleInboundMessage = ( - InBoundGetAtm(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= AtmTCommons(atmId=AtmId("string"), + InBoundGetAtm(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AtmTCommons(atmId=AtmId(atmIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), OpeningTimeOnMonday=Some("string"), ClosingTimeOnMonday=Some("string"), OpeningTimeOnTuesday=Some("string"), @@ -4398,22 +3122,34 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ClosingTimeOnSaturday=Some("string"), OpeningTimeOnSunday=Some("string"), ClosingTimeOnSunday=Some("string"), - isAccessible=Some(true), - locatedAt=Some("string"), - moreInfo=Some("string"), - hasDepositCapability=Some(true))) + isAccessible=Some(isAccessibleExample.value.toBoolean), + locatedAt=Some(locatedAtExample.value), + moreInfo=Some(moreInfoExample.value), + hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), + supportedLanguages=Some(supportedLanguagesExample.value.split("[,;]").toList), + services=Some(listExample.value.split("[,;]").toList), + accessibilityFeatures=Some(accessibilityFeaturesExample.value.split("[,;]").toList), + supportedCurrencies=Some(supportedCurrenciesExample.value.split("[,;]").toList), + notes=Some(listExample.value.split("[,;]").toList), + locationCategories=Some(listExample.value.split("[,;]").toList), + minimumWithdrawal=Some("string"), + branchIdentification=Some("string"), + siteIdentification=Some(siteIdentification.value), + siteName=Some("string"), + cashWithdrawalNationalFee=Some(cashWithdrawalNationalFeeExample.value), + cashWithdrawalInternationalFee=Some(cashWithdrawalInternationalFeeExample.value), + balanceInquiryFee=Some(balanceInquiryFeeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAtm + override def getAtm(bankId: BankId, atmId: AtmId, callContext: Option[CallContext]): Future[Box[(AtmT, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetAtm => OutBound, InBoundGetAtm => InBound} - val url = getUrl(callContext, "getAtm") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, atmId) - val result: OBPReturnType[Box[AtmTCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAtm => InBound, OutBoundGetAtm => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, atmId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAtm"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AtmTCommons](callContext)) } - + messageDocs += getAtmsDoc def getAtmsDoc = MessageDoc( process = "obp.getAtms", @@ -4422,67 +3158,35 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAtms(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetAtms(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( - InBoundGetAtms(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( AtmTCommons(atmId=AtmId("string"), + InBoundGetAtms(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( AtmTCommons(atmId=AtmId(atmIdExample.value), bankId=BankId(bankIdExample.value), - name="string", - address= Address(line1="string", - line2="string", - line3="string", - city="string", - county=Some("string"), - state="string", - postCode="string", - countryCode="string"), - location= Location(latitude=123.123, - longitude=123.123, - date=Some(new Date()), + name=nameExample.value, + address= Address(line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=Some(countyExample.value), + state=stateExample.value, + postCode=postCodeExample.value, + countryCode=countryCodeExample.value), + location= Location(latitude=latitudeExample.value.toDouble, + longitude=longitudeExample.value.toDouble, + date=Some(toDate(dateExample)), user=Some( BasicResourceUser(userId=userIdExample.value, - provider="string", + provider=providerExample.value, username=usernameExample.value))), - meta=Meta( License(id="string", - name="string")), + meta=Meta( License(id=idExample.value, + name=nameExample.value)), OpeningTimeOnMonday=Some("string"), ClosingTimeOnMonday=Some("string"), OpeningTimeOnTuesday=Some("string"), @@ -4497,22 +3201,66 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ClosingTimeOnSaturday=Some("string"), OpeningTimeOnSunday=Some("string"), ClosingTimeOnSunday=Some("string"), - isAccessible=Some(true), - locatedAt=Some("string"), - moreInfo=Some("string"), - hasDepositCapability=Some(true)))) - ), + isAccessible=Some(isAccessibleExample.value.toBoolean), + locatedAt=Some(locatedAtExample.value), + moreInfo=Some(moreInfoExample.value), + hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), + supportedLanguages=Some(supportedLanguagesExample.value.split("[,;]").toList), + services=Some(listExample.value.split("[,;]").toList), + accessibilityFeatures=Some(accessibilityFeaturesExample.value.split("[,;]").toList), + supportedCurrencies=Some(supportedCurrenciesExample.value.split("[,;]").toList), + notes=Some(listExample.value.split("[,;]").toList), + locationCategories=Some(listExample.value.split("[,;]").toList), + minimumWithdrawal=Some("string"), + branchIdentification=Some("string"), + siteIdentification=Some(siteIdentification.value), + siteName=Some("string"), + cashWithdrawalNationalFee=Some(cashWithdrawalNationalFeeExample.value), + cashWithdrawalInternationalFee=Some(cashWithdrawalInternationalFeeExample.value), + balanceInquiryFee=Some(balanceInquiryFeeExample.value)))) + ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAtms + override def getAtms(bankId: BankId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Future[Box[(List[AtmT], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetAtms => OutBound, InBoundGetAtms => InBound} - val url = getUrl(callContext, "getAtms") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[AtmTCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAtms => InBound, OutBoundGetAtms => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAtms"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[AtmTCommons]](callContext)) } - + + messageDocs += getCurrentFxRateDoc + def getCurrentFxRateDoc = MessageDoc( + process = "obp.getCurrentFxRate", + messageFormat = messageFormat, + description = "Get Current Fx Rate", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCurrentFxRate(bankId=BankId(bankIdExample.value), + fromCurrencyCode=fromCurrencyCodeExample.value, + toCurrencyCode=toCurrencyCodeExample.value) + ), + exampleInboundMessage = ( + InBoundGetCurrentFxRate(status=MessageDocsSwaggerDefinitions.inboundStatus, + data= FXRateCommons(bankId=BankId(bankIdExample.value), + fromCurrencyCode=fromCurrencyCodeExample.value, + toCurrencyCode=toCurrencyCodeExample.value, + conversionValue=conversionValueExample.value.toDouble, + inverseConversionValue=inverseConversionValueExample.value.toDouble, + effectiveDate=toDate(effectiveDateExample))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCurrentFxRate(bankId: BankId, fromCurrencyCode: String, toCurrencyCode: String): Box[FXRate] = { + import com.openbankproject.commons.dto.{InBoundGetCurrentFxRate => InBound, OutBoundGetCurrentFxRate => OutBound} + val callContext: Option[CallContext] = None + val req = OutBound(bankId, fromCurrencyCode, toCurrencyCode) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCurrentFxRate"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[FXRateCommons](callContext)) + } + messageDocs += createTransactionAfterChallengev300Doc def createTransactionAfterChallengev300Doc = MessageDoc( process = "obp.createTransactionAfterChallengev300", @@ -4521,123 +3269,97 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateTransactionAfterChallengev300(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateTransactionAfterChallengev300(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - transReqId=TransactionRequestId("string"), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + transReqId=TransactionRequestId(transactionRequestIdExample.value), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value)) ), exampleInboundMessage = ( - InBoundCreateTransactionAfterChallengev300(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= TransactionRequest(id=TransactionRequestId("string"), + InBoundCreateTransactionAfterChallengev300(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -4650,15 +3372,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createTransactionAfterChallengev300 + override def createTransactionAfterChallengev300(initiator: User, fromAccount: BankAccount, transReqId: TransactionRequestId, transactionRequestType: TransactionRequestType, callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequest]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionAfterChallengev300 => OutBound, InBoundCreateTransactionAfterChallengev300 => InBound} - val url = getUrl(callContext, "createTransactionAfterChallengev300") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , initiator, fromAccount, transReqId, transactionRequestType) - val result: OBPReturnType[Box[TransactionRequest]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateTransactionAfterChallengev300 => InBound, OutBoundCreateTransactionAfterChallengev300 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, fromAccount, transReqId, transactionRequestType) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createTransactionAfterChallengev300"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionRequest](callContext)) } - + messageDocs += makePaymentv300Doc def makePaymentv300Doc = MessageDoc( process = "obp.makePaymentv300", @@ -4667,116 +3388,92 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundMakePaymentv300(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundMakePaymentv300(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - toCounterparty= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + toCounterparty= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=counterpartyNameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=counterpartyOtherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=counterpartyOtherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=counterpartyOtherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, + otherBankRoutingAddress=counterpartyOtherBankRoutingAddressExample.value, + otherBranchRoutingScheme=counterpartyOtherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=counterpartyOtherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( - InBoundMakePaymentv300(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundMakePaymentv300(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=TransactionId(transactionIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /makePaymentv300 + override def makePaymentv300(initiator: User, fromAccount: BankAccount, toAccount: BankAccount, toCounterparty: CounterpartyTrait, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, transactionRequestType: TransactionRequestType, chargePolicy: String, callContext: Option[CallContext]): Future[Box[(TransactionId, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundMakePaymentv300 => OutBound, InBoundMakePaymentv300 => InBound} - val url = getUrl(callContext, "makePaymentv300") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , initiator, fromAccount, toAccount, toCounterparty, transactionRequestCommonBody, transactionRequestType, chargePolicy) - val result: OBPReturnType[Box[TransactionId]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundMakePaymentv300 => InBound, OutBoundMakePaymentv300 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, fromAccount, toAccount, toCounterparty, transactionRequestCommonBody, transactionRequestType, chargePolicy) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "makePaymentv300"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionId](callContext)) } - + messageDocs += createTransactionRequestv300Doc def createTransactionRequestv300Doc = MessageDoc( process = "obp.createTransactionRequestv300", @@ -4785,162 +3482,139 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateTransactionRequestv300(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateTransactionRequestv300(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, initiator= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - toCounterparty= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + toCounterparty= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=counterpartyNameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=counterpartyOtherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=counterpartyOtherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=counterpartyOtherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=counterpartyOtherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=counterpartyOtherBankRoutingSchemeExample.value, + otherBankRoutingAddress=counterpartyOtherBankRoutingAddressExample.value, + otherBranchRoutingScheme=counterpartyOtherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=counterpartyOtherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))), transactionRequestType=TransactionRequestType(transactionRequestTypeExample.value), transactionRequestCommonBody= TransactionRequestCommonBodyJSONCommons(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), detailsPlain="string", - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( - InBoundCreateTransactionRequestv300(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= TransactionRequest(id=TransactionRequestId("string"), + InBoundCreateTransactionRequestv300(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), `type`=transactionRequestTypeExample.value, - from= TransactionRequestAccount(bank_id="string", - account_id="string"), - body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id="string", - account_id="string")), - to_sepa=Some(TransactionRequestIban("string")), - to_counterparty=Some(TransactionRequestCounterpartyId("string")), + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), - to=ToAccountTransferToPhone("string"))), + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", - message="string", + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, from= FromAccountTransfer(mobile_phone_number="string", - nickname="string"), + nickname=nicknameExample.value), to= ToAccountTransferToAtm(legal_name="string", date_of_birth="string", mobile_phone_number="string", - kyc_document= ToAccountTransferToAtmKycDocument(`type`="string", - number="string")))), + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), - description="string", + amount=amountExample.value), + description=descriptionExample.value, transfer_type="string", future_date="string", - to= ToAccountTransferToAccount(name="string", + to= ToAccountTransferToAccount(name=nameExample.value, bank_code="string", branch_number="string", account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, iban=ibanExample.value)))), to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, - amount="string"), + amount=amountExample.value), creditorAccount=PaymentAccount("string"), creditorName="string")), value= AmountOfMoney(currency=currencyExample.value, - amount="string"), - description="string"), + amount=amountExample.value), + description=descriptionExample.value), transaction_ids="string", - status="string", - start_date=new Date(), - end_date=new Date(), - challenge= TransactionRequestChallenge(id="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, allowed_attempts=123, challenge_type="string"), - charge= TransactionRequestCharge(summary="string", + charge= TransactionRequestCharge(summary=summaryExample.value, value= AmountOfMoney(currency=currencyExample.value, - amount="string")), + amount=amountExample.value)), charge_policy="string", - counterparty_id=CounterpartyId(counterpartyIdExample.value), - name="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, this_bank_id=BankId(bankIdExample.value), this_account_id=AccountId(accountIdExample.value), this_view_id=ViewId(viewIdExample.value), @@ -4953,15 +3627,137 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createTransactionRequestv300 + override def createTransactionRequestv300(initiator: User, viewId: ViewId, fromAccount: BankAccount, toAccount: BankAccount, toCounterparty: CounterpartyTrait, transactionRequestType: TransactionRequestType, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, detailsPlain: String, chargePolicy: String, callContext: Option[CallContext]): Future[Box[(TransactionRequest, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTransactionRequestv300 => OutBound, InBoundCreateTransactionRequestv300 => InBound} - val url = getUrl(callContext, "createTransactionRequestv300") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , initiator, viewId, fromAccount, toAccount, toCounterparty, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy) - val result: OBPReturnType[Box[TransactionRequest]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateTransactionRequestv300 => InBound, OutBoundCreateTransactionRequestv300 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, initiator, viewId, fromAccount, toAccount, toCounterparty, transactionRequestType, transactionRequestCommonBody, detailsPlain, chargePolicy) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createTransactionRequestv300"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionRequest](callContext)) } - + + messageDocs += makePaymentV400Doc + def makePaymentV400Doc = MessageDoc( + process = "obp.makePaymentV400", + messageFormat = messageFormat, + description = "Make Payment V400", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundMakePaymentV400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionRequest= TransactionRequest(id=TransactionRequestId(transactionRequestIdExample.value), + `type`=transactionRequestTypeExample.value, + from= TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value), + body= TransactionRequestBodyAllTypes(to_sandbox_tan=Some( TransactionRequestAccount(bank_id=bank_idExample.value, + account_id=account_idExample.value)), + to_sepa=Some(TransactionRequestIban(transactionRequestIban.value)), + to_counterparty=Some(TransactionRequestCounterpartyId(transactionRequestCounterpartyIdExample.value)), + to_transfer_to_phone=Some( TransactionRequestTransferToPhone(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to=ToAccountTransferToPhone(toExample.value))), + to_transfer_to_atm=Some( TransactionRequestTransferToAtm(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + message=messageExample.value, + from= FromAccountTransfer(mobile_phone_number="string", + nickname=nicknameExample.value), + to= ToAccountTransferToAtm(legal_name="string", + date_of_birth="string", + mobile_phone_number="string", + kyc_document= ToAccountTransferToAtmKycDocument(`type`=typeExample.value, + number=numberExample.value)))), + to_transfer_to_account=Some( TransactionRequestTransferToAccount(value= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value, + transfer_type="string", + future_date="string", + to= ToAccountTransferToAccount(name=nameExample.value, + bank_code="string", + branch_number="string", + account= ToAccountTransferToAccountAccount(number=accountNumberExample.value, + iban=ibanExample.value)))), + to_sepa_credit_transfers=Some( SepaCreditTransfers(debtorAccount=PaymentAccount("string"), + instructedAmount= AmountOfMoneyJsonV121(currency=currencyExample.value, + amount=amountExample.value), + creditorAccount=PaymentAccount("string"), + creditorName="string")), + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value), + description=descriptionExample.value), + transaction_ids="string", + status=statusExample.value, + start_date=toDate(transactionRequestStartDateExample), + end_date=toDate(transactionRequestEndDateExample), + challenge= TransactionRequestChallenge(id=challengeIdExample.value, + allowed_attempts=123, + challenge_type="string"), + charge= TransactionRequestCharge(summary=summaryExample.value, + value= AmountOfMoney(currency=currencyExample.value, + amount=amountExample.value)), + charge_policy="string", + counterparty_id=CounterpartyId(transactionRequestCounterpartyIdExample.value), + name=nameExample.value, + this_bank_id=BankId(bankIdExample.value), + this_account_id=AccountId(accountIdExample.value), + this_view_id=ViewId(viewIdExample.value), + other_account_routing_scheme="string", + other_account_routing_address="string", + other_bank_routing_scheme="string", + other_bank_routing_address="string", + is_beneficiary=true, + future_date=Some("string")), + reasons=Some(List( TransactionRequestReason(code=codeExample.value, + documentNumber=Some(documentNumberExample.value), + amount=Some(amountExample.value), + currency=Some(currencyExample.value), + description=Some(descriptionExample.value))))) + ), + exampleInboundMessage = ( + InBoundMakePaymentV400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=TransactionId(transactionIdExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def makePaymentV400(transactionRequest: TransactionRequest, reasons: Option[List[TransactionRequestReason]], callContext: Option[CallContext]): Future[Box[(TransactionId, Option[CallContext])]] = { + import com.openbankproject.commons.dto.{InBoundMakePaymentV400 => InBound, OutBoundMakePaymentV400 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionRequest, reasons) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "makePaymentV400"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionId](callContext)) + } + + messageDocs += cancelPaymentV400Doc + def cancelPaymentV400Doc = MessageDoc( + process = "obp.cancelPaymentV400", + messageFormat = messageFormat, + description = "Cancel Payment V400", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCancelPaymentV400(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionId=TransactionId(transactionIdExample.value)) + ), + exampleInboundMessage = ( + InBoundCancelPaymentV400(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CancelPayment(canBeCancelled=true, + startSca=Some(true))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def cancelPaymentV400(transactionId: TransactionId, callContext: Option[CallContext]): OBPReturnType[Box[CancelPayment]] = { + import com.openbankproject.commons.dto.{InBoundCancelPaymentV400 => InBound, OutBoundCancelPaymentV400 => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "cancelPaymentV400"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CancelPayment](callContext)) + } + messageDocs += createCounterpartyDoc def createCounterpartyDoc = MessageDoc( process = "obp.createCounterparty", @@ -4970,92 +3766,59 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateCounterparty(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - name="string", - description="string", + OutBoundCreateCounterparty(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - createdByUserId="string", - thisBankId="string", - thisAccountId="string", - thisViewId="string", - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + createdByUserId=createdByUserIdExample.value, + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value))) ), exampleInboundMessage = ( - InBoundCreateCounterparty(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CounterpartyTraitCommons(createdByUserId="string", - name="string", - description="string", + InBoundCreateCounterparty(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CounterpartyTraitCommons(createdByUserId=createdByUserIdExample.value, + name=nameExample.value, + description=descriptionExample.value, currency=currencyExample.value, - thisBankId="string", - thisAccountId="string", - thisViewId="string", + thisBankId=thisBankIdExample.value, + thisAccountId=thisAccountIdExample.value, + thisViewId=thisViewIdExample.value, counterpartyId=counterpartyIdExample.value, - otherAccountRoutingScheme=accountRoutingSchemeExample.value, - otherAccountRoutingAddress=accountRoutingAddressExample.value, - otherAccountSecondaryRoutingScheme="string", - otherAccountSecondaryRoutingAddress="string", - otherBankRoutingScheme=bankRoutingSchemeExample.value, - otherBankRoutingAddress=bankRoutingAddressExample.value, - otherBranchRoutingScheme=branchRoutingSchemeExample.value, - otherBranchRoutingAddress=branchRoutingAddressExample.value, + otherAccountRoutingScheme=otherAccountRoutingSchemeExample.value, + otherAccountRoutingAddress=otherAccountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme=otherAccountSecondaryRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress=otherAccountSecondaryRoutingAddressExample.value, + otherBankRoutingScheme=otherBankRoutingSchemeExample.value, + otherBankRoutingAddress=otherBankRoutingAddressExample.value, + otherBranchRoutingScheme=otherBranchRoutingSchemeExample.value, + otherBranchRoutingAddress=otherBranchRoutingAddressExample.value, isBeneficiary=isBeneficiaryExample.value.toBoolean, bespoke=List( CounterpartyBespoke(key=keyExample.value, value=valueExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createCounterparty + override def createCounterparty(name: String, description: String, currency: String, createdByUserId: String, thisBankId: String, thisAccountId: String, thisViewId: String, otherAccountRoutingScheme: String, otherAccountRoutingAddress: String, otherAccountSecondaryRoutingScheme: String, otherAccountSecondaryRoutingAddress: String, otherBankRoutingScheme: String, otherBankRoutingAddress: String, otherBranchRoutingScheme: String, otherBranchRoutingAddress: String, isBeneficiary: Boolean, bespoke: List[CounterpartyBespoke], callContext: Option[CallContext]): Box[(CounterpartyTrait, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundCreateCounterparty => OutBound, InBoundCreateCounterparty => InBound} - val url = getUrl(callContext, "createCounterparty") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , name, description, currency, createdByUserId, thisBankId, thisAccountId, thisViewId, otherAccountRoutingScheme, otherAccountRoutingAddress, otherAccountSecondaryRoutingScheme, otherAccountSecondaryRoutingAddress, otherBankRoutingScheme, otherBankRoutingAddress, otherBranchRoutingScheme, otherBranchRoutingAddress, isBeneficiary, bespoke) - val result: OBPReturnType[Box[CounterpartyTraitCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateCounterparty => InBound, OutBoundCreateCounterparty => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, name, description, currency, createdByUserId, thisBankId, thisAccountId, thisViewId, otherAccountRoutingScheme, otherAccountRoutingAddress, otherAccountSecondaryRoutingScheme, otherAccountSecondaryRoutingAddress, otherBankRoutingScheme, otherBankRoutingAddress, otherBranchRoutingScheme, otherBranchRoutingAddress, isBeneficiary, bespoke) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createCounterparty"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CounterpartyTraitCommons](callContext)) } - + messageDocs += checkCustomerNumberAvailableDoc def checkCustomerNumberAvailableDoc = MessageDoc( process = "obp.checkCustomerNumberAvailable", @@ -5064,58 +3827,25 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCheckCustomerNumberAvailable(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCheckCustomerNumberAvailable(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), customerNumber=customerNumberExample.value) ), exampleInboundMessage = ( - InBoundCheckCustomerNumberAvailable(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCheckCustomerNumberAvailable(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /checkCustomerNumberAvailable + override def checkCustomerNumberAvailable(bankId: BankId, customerNumber: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundCheckCustomerNumberAvailable => OutBound, InBoundCheckCustomerNumberAvailable => InBound} - val url = getUrl(callContext, "checkCustomerNumberAvailable") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, customerNumber) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCheckCustomerNumberAvailable => InBound, OutBoundCheckCustomerNumberAvailable => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerNumber) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "checkCustomerNumberAvailable"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += createCustomerDoc def createCustomerDoc = MessageDoc( process = "obp.createCustomer", @@ -5124,46 +3854,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateCustomer(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateCustomer(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, highestEducationAttained=highestEducationAttainedExample.value, employmentStatus=employmentStatusExample.value, kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(outBoundCreateCustomerLastOkDateExample.value).getOrElse(sys.error("outBoundCreateCustomerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(outBoundCreateCustomerLastOkDateExample), creditRating=Some( CreditRating(rating=ratingExample.value, source=sourceExample.value)), creditLimit=Some( AmountOfMoney(currency=currencyExample.value, @@ -5173,24 +3878,17 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable nameSuffix=nameSuffixExample.value) ), exampleInboundMessage = ( - InBoundCreateCustomer(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateCustomer(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5201,22 +3899,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createCustomer + override def createCustomer(bankId: BankId, legalName: String, mobileNumber: String, email: String, faceImage: CustomerFaceImageTrait, dateOfBirth: Date, relationshipStatus: String, dependents: Int, dobOfDependents: List[Date], highestEducationAttained: String, employmentStatus: String, kycStatus: Boolean, lastOkDate: Date, creditRating: Option[CreditRatingTrait], creditLimit: Option[AmountOfMoneyTrait], title: String, branchId: String, nameSuffix: String, callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundCreateCustomer => OutBound, InBoundCreateCustomer => InBound} - val url = getUrl(callContext, "createCustomer") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, legalName, mobileNumber, email, faceImage, dateOfBirth, relationshipStatus, dependents, dobOfDependents, highestEducationAttained, employmentStatus, kycStatus, lastOkDate, creditRating, creditLimit, title, branchId, nameSuffix) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateCustomer => InBound, OutBoundCreateCustomer => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, legalName, mobileNumber, email, faceImage, dateOfBirth, relationshipStatus, dependents, dobOfDependents, highestEducationAttained, employmentStatus, kycStatus, lastOkDate, creditRating, creditLimit, title, branchId, nameSuffix) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createCustomer"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerCommons](callContext)) } - + messageDocs += updateCustomerScaDataDoc def updateCustomerScaDataDoc = MessageDoc( process = "obp.updateCustomerScaData", @@ -5225,56 +3922,24 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdateCustomerScaData(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundUpdateCustomerScaData(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, mobileNumber=Some(mobileNumberExample.value), email=Some(emailExample.value), customerNumber=Some(customerNumberExample.value)) ), exampleInboundMessage = ( - InBoundUpdateCustomerScaData(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundUpdateCustomerScaData(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5285,22 +3950,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updateCustomerScaData + override def updateCustomerScaData(customerId: String, mobileNumber: Option[String], email: Option[String], customerNumber: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerScaData => OutBound, InBoundUpdateCustomerScaData => InBound} - val url = getUrl(callContext, "updateCustomerScaData") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId, mobileNumber, email, customerNumber) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdateCustomerScaData => InBound, OutBoundUpdateCustomerScaData => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, mobileNumber, email, customerNumber) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updateCustomerScaData"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerCommons](callContext)) } - + messageDocs += updateCustomerCreditDataDoc def updateCustomerCreditDataDoc = MessageDoc( process = "obp.updateCustomerCreditData", @@ -5309,57 +3973,25 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdateCustomerCreditData(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, + OutBoundUpdateCustomerCreditData(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - customerId=customerIdExample.value, - creditRating=Some("string"), + creditRating=Some(creditRatingExample.value), creditSource=Some("string"), creditLimit=Some( AmountOfMoney(currency=currencyExample.value, amount=creditLimitAmountExample.value))) ), exampleInboundMessage = ( - InBoundUpdateCustomerCreditData(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundUpdateCustomerCreditData(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5370,22 +4002,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updateCustomerCreditData + override def updateCustomerCreditData(customerId: String, creditRating: Option[String], creditSource: Option[String], creditLimit: Option[AmountOfMoney], callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerCreditData => OutBound, InBoundUpdateCustomerCreditData => InBound} - val url = getUrl(callContext, "updateCustomerCreditData") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId, creditRating, creditSource, creditLimit) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdateCustomerCreditData => InBound, OutBoundUpdateCustomerCreditData => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, creditRating, creditSource, creditLimit) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updateCustomerCreditData"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerCommons](callContext)) } - + messageDocs += updateCustomerGeneralDataDoc def updateCustomerGeneralDataDoc = MessageDoc( process = "obp.updateCustomerGeneralData", @@ -5394,37 +4025,12 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdateCustomerGeneralData(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundUpdateCustomerGeneralData(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, legalName=Some(legalNameExample.value), - faceImage=Some( CustomerFaceImage(date=new Date(), + faceImage=Some( CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value)), - dateOfBirth=Some(parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format."))), + dateOfBirth=Some(toDate(dateOfBirthExample)), relationshipStatus=Some(relationshipStatusExample.value), dependents=Some(dependentsExample.value.toInt), highestEducationAttained=Some(highestEducationAttainedExample.value), @@ -5434,24 +4040,17 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable nameSuffix=Some(nameSuffixExample.value)) ), exampleInboundMessage = ( - InBoundUpdateCustomerGeneralData(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundUpdateCustomerGeneralData(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5462,22 +4061,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updateCustomerGeneralData + override def updateCustomerGeneralData(customerId: String, legalName: Option[String], faceImage: Option[CustomerFaceImageTrait], dateOfBirth: Option[Date], relationshipStatus: Option[String], dependents: Option[Int], highestEducationAttained: Option[String], employmentStatus: Option[String], title: Option[String], branchId: Option[String], nameSuffix: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[Customer]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerGeneralData => OutBound, InBoundUpdateCustomerGeneralData => InBound} - val url = getUrl(callContext, "updateCustomerGeneralData") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId, legalName, faceImage, dateOfBirth, relationshipStatus, dependents, highestEducationAttained, employmentStatus, title, branchId, nameSuffix) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdateCustomerGeneralData => InBound, OutBoundUpdateCustomerGeneralData => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, legalName, faceImage, dateOfBirth, relationshipStatus, dependents, highestEducationAttained, employmentStatus, title, branchId, nameSuffix) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updateCustomerGeneralData"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerCommons](callContext)) } - + messageDocs += getCustomersByUserIdDoc def getCustomersByUserIdDoc = MessageDoc( process = "obp.getCustomersByUserId", @@ -5486,53 +4084,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCustomersByUserId(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCustomersByUserId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, userId=userIdExample.value) ), exampleInboundMessage = ( - InBoundGetCustomersByUserId(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCustomersByUserId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5543,103 +4109,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCustomersByUserId + override def getCustomersByUserId(userId: String, callContext: Option[CallContext]): Future[Box[(List[Customer], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomersByUserId => OutBound, InBoundGetCustomersByUserId => InBound} - val url = getUrl(callContext, "getCustomersByUserId") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , userId) - val result: OBPReturnType[Box[List[CustomerCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCustomersByUserId => InBound, OutBoundGetCustomersByUserId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomersByUserId"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CustomerCommons]](callContext)) } - - messageDocs += getCustomerByCustomerIdLegacyDoc - def getCustomerByCustomerIdLegacyDoc = MessageDoc( - process = "obp.getCustomerByCustomerIdLegacy", - messageFormat = messageFormat, - description = "Get Customer By Customer Id Legacy", - outboundTopic = None, - inboundTopic = None, - exampleOutboundMessage = ( - OutBoundGetCustomerByCustomerIdLegacy(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - customerId=customerIdExample.value) - ), - exampleInboundMessage = ( - InBoundGetCustomerByCustomerIdLegacy(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CustomerCommons(customerId=customerIdExample.value, - bankId=bankIdExample.value, - number=customerNumberExample.value, - legalName=legalNameExample.value, - mobileNumber=mobileNumberExample.value, - email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), - url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), - relationshipStatus=relationshipStatusExample.value, - dependents=dependentsExample.value.toInt, - dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, - highestEducationAttained=highestEducationAttainedExample.value, - employmentStatus=employmentStatusExample.value, - creditRating= CreditRating(rating=ratingExample.value, - source=sourceExample.value), - creditLimit= CreditLimit(currency=currencyExample.value, - amount=creditLimitAmountExample.value), - kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), - title=customerTitleExample.value, - branchId=branchIdExample.value, - nameSuffix=nameSuffixExample.value)) - ), - adapterImplementation = Some(AdapterImplementation("- Core", 1)) - ) - // url example: /getCustomerByCustomerIdLegacy - override def getCustomerByCustomerIdLegacy(customerId: String, callContext: Option[CallContext]): Box[(Customer, Option[CallContext])] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerByCustomerIdLegacy => OutBound, InBoundGetCustomerByCustomerIdLegacy => InBound} - val url = getUrl(callContext, "getCustomerByCustomerIdLegacy") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - + messageDocs += getCustomerByCustomerIdDoc def getCustomerByCustomerIdDoc = MessageDoc( process = "obp.getCustomerByCustomerId", @@ -5648,53 +4132,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCustomerByCustomerId(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCustomerByCustomerId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetCustomerByCustomerId(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCustomerByCustomerId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5705,22 +4157,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCustomerByCustomerId + override def getCustomerByCustomerId(customerId: String, callContext: Option[CallContext]): Future[Box[(Customer, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerByCustomerId => OutBound, InBoundGetCustomerByCustomerId => InBound} - val url = getUrl(callContext, "getCustomerByCustomerId") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCustomerByCustomerId => InBound, OutBoundGetCustomerByCustomerId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerByCustomerId"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerCommons](callContext)) } - + messageDocs += getCustomerByCustomerNumberDoc def getCustomerByCustomerNumberDoc = MessageDoc( process = "obp.getCustomerByCustomerNumber", @@ -5729,54 +4180,22 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCustomerByCustomerNumber(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCustomerByCustomerNumber(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerNumber=customerNumberExample.value, bankId=BankId(bankIdExample.value)) ), exampleInboundMessage = ( - InBoundGetCustomerByCustomerNumber(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCustomerByCustomerNumber(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -5787,22 +4206,21 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCustomerByCustomerNumber + override def getCustomerByCustomerNumber(customerNumber: String, bankId: BankId, callContext: Option[CallContext]): Future[Box[(Customer, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerByCustomerNumber => OutBound, InBoundGetCustomerByCustomerNumber => InBound} - val url = getUrl(callContext, "getCustomerByCustomerNumber") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerNumber, bankId) - val result: OBPReturnType[Box[CustomerCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCustomerByCustomerNumber => InBound, OutBoundGetCustomerByCustomerNumber => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerNumber, bankId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerByCustomerNumber"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerCommons](callContext)) } - + messageDocs += getCustomerAddressDoc def getCustomerAddressDoc = MessageDoc( process = "obp.getCustomerAddress", @@ -5811,69 +4229,36 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCustomerAddress(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetCustomerAddress(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CustomerAddressCommons(customerId=customerIdExample.value, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - status="string", - tags="string", - insertDate=new Date()))) + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + status=statusExample.value, + tags=tagsExample.value, + insertDate=toDate(insertDateExample)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCustomerAddress + override def getCustomerAddress(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAddress]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomerAddress => OutBound, InBoundGetCustomerAddress => InBound} - val url = getUrl(callContext, "getCustomerAddress") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[List[CustomerAddressCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCustomerAddress => InBound, OutBoundGetCustomerAddress => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerAddress"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CustomerAddressCommons]](callContext)) } - + messageDocs += createCustomerAddressDoc def createCustomerAddressDoc = MessageDoc( process = "obp.createCustomerAddress", @@ -5882,79 +4267,46 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateCustomerAddress(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, + OutBoundCreateCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - customerId=customerIdExample.value, - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - tags="string", - status="string") + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + tags=tagsExample.value, + status=statusExample.value) ), exampleInboundMessage = ( - InBoundCreateCustomerAddress(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerAddressCommons(customerId=customerIdExample.value, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - status="string", - tags="string", - insertDate=new Date())) + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + status=statusExample.value, + tags=tagsExample.value, + insertDate=toDate(insertDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createCustomerAddress + override def createCustomerAddress(customerId: String, line1: String, line2: String, line3: String, city: String, county: String, state: String, postcode: String, countryCode: String, tags: String, status: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAddress]] = { - import com.openbankproject.commons.dto.{OutBoundCreateCustomerAddress => OutBound, InBoundCreateCustomerAddress => InBound} - val url = getUrl(callContext, "createCustomerAddress") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId, line1, line2, line3, city, county, state, postcode, countryCode, tags, status) - val result: OBPReturnType[Box[CustomerAddressCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateCustomerAddress => InBound, OutBoundCreateCustomerAddress => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, line1, line2, line3, city, county, state, postcode, countryCode, tags, status) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createCustomerAddress"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerAddressCommons](callContext)) } - + messageDocs += updateCustomerAddressDoc def updateCustomerAddressDoc = MessageDoc( process = "obp.updateCustomerAddress", @@ -5963,79 +4315,46 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdateCustomerAddress(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - tags="string", - status="string") + OutBoundUpdateCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + tags=tagsExample.value, + status=statusExample.value) ), exampleInboundMessage = ( - InBoundUpdateCustomerAddress(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundUpdateCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerAddressCommons(customerId=customerIdExample.value, - customerAddressId="string", - line1="string", - line2="string", - line3="string", - city="string", - county="string", - state="string", - postcode="string", - countryCode="string", - status="string", - tags="string", - insertDate=new Date())) + customerAddressId=customerAddressIdExample.value, + line1=line1Example.value, + line2=line2Example.value, + line3=line3Example.value, + city=cityExample.value, + county=countyExample.value, + state=stateExample.value, + postcode=postcodeExample.value, + countryCode=countryCodeExample.value, + status=statusExample.value, + tags=tagsExample.value, + insertDate=toDate(insertDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updateCustomerAddress + override def updateCustomerAddress(customerAddressId: String, line1: String, line2: String, line3: String, city: String, county: String, state: String, postcode: String, countryCode: String, tags: String, status: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAddress]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateCustomerAddress => OutBound, InBoundUpdateCustomerAddress => InBound} - val url = getUrl(callContext, "updateCustomerAddress") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerAddressId, line1, line2, line3, city, county, state, postcode, countryCode, tags, status) - val result: OBPReturnType[Box[CustomerAddressCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdateCustomerAddress => InBound, OutBoundUpdateCustomerAddress => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAddressId, line1, line2, line3, city, county, state, postcode, countryCode, tags, status) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updateCustomerAddress"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerAddressCommons](callContext)) } - + messageDocs += deleteCustomerAddressDoc def deleteCustomerAddressDoc = MessageDoc( process = "obp.deleteCustomerAddress", @@ -6044,57 +4363,24 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundDeleteCustomerAddress(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - customerAddressId="string") + OutBoundDeleteCustomerAddress(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + customerAddressId=customerAddressIdExample.value) ), exampleInboundMessage = ( - InBoundDeleteCustomerAddress(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundDeleteCustomerAddress(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /deleteCustomerAddress + override def deleteCustomerAddress(customerAddressId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteCustomerAddress => OutBound, InBoundDeleteCustomerAddress => InBound} - val url = getUrl(callContext, "deleteCustomerAddress") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerAddressId) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.DELETE, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundDeleteCustomerAddress => InBound, OutBoundDeleteCustomerAddress => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAddressId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deleteCustomerAddress"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += createTaxResidenceDoc def createTaxResidenceDoc = MessageDoc( process = "obp.createTaxResidence", @@ -6103,62 +4389,29 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateTaxResidence(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, + OutBoundCreateTaxResidence(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - customerId=customerIdExample.value, - domain="string", - taxNumber="string") + domain=domainExample.value, + taxNumber=taxNumberExample.value) ), exampleInboundMessage = ( - InBoundCreateTaxResidence(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateTaxResidence(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= TaxResidenceCommons(customerId=customerIdExample.value, - taxResidenceId="string", - domain="string", - taxNumber="string")) + taxResidenceId=taxResidenceIdExample.value, + domain=domainExample.value, + taxNumber=taxNumberExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createTaxResidence + override def createTaxResidence(customerId: String, domain: String, taxNumber: String, callContext: Option[CallContext]): OBPReturnType[Box[TaxResidence]] = { - import com.openbankproject.commons.dto.{OutBoundCreateTaxResidence => OutBound, InBoundCreateTaxResidence => InBound} - val url = getUrl(callContext, "createTaxResidence") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId, domain, taxNumber) - val result: OBPReturnType[Box[TaxResidenceCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateTaxResidence => InBound, OutBoundCreateTaxResidence => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId, domain, taxNumber) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createTaxResidence"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TaxResidenceCommons](callContext)) } - + messageDocs += getTaxResidenceDoc def getTaxResidenceDoc = MessageDoc( process = "obp.getTaxResidence", @@ -6167,60 +4420,27 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetTaxResidence(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetTaxResidence(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetTaxResidence(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetTaxResidence(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( TaxResidenceCommons(customerId=customerIdExample.value, - taxResidenceId="string", - domain="string", - taxNumber="string"))) + taxResidenceId=taxResidenceIdExample.value, + domain=domainExample.value, + taxNumber=taxNumberExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getTaxResidence + override def getTaxResidence(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[TaxResidence]]] = { - import com.openbankproject.commons.dto.{OutBoundGetTaxResidence => OutBound, InBoundGetTaxResidence => InBound} - val url = getUrl(callContext, "getTaxResidence") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[List[TaxResidenceCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetTaxResidence => InBound, OutBoundGetTaxResidence => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTaxResidence"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[TaxResidenceCommons]](callContext)) } - + messageDocs += deleteTaxResidenceDoc def deleteTaxResidenceDoc = MessageDoc( process = "obp.deleteTaxResidence", @@ -6229,57 +4449,24 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundDeleteTaxResidence(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundDeleteTaxResidence(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, taxResourceId="string") ), exampleInboundMessage = ( - InBoundDeleteTaxResidence(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundDeleteTaxResidence(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /deleteTaxResidence + override def deleteTaxResidence(taxResourceId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteTaxResidence => OutBound, InBoundDeleteTaxResidence => InBound} - val url = getUrl(callContext, "deleteTaxResidence") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , taxResourceId) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.DELETE, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundDeleteTaxResidence => InBound, OutBoundDeleteTaxResidence => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, taxResourceId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deleteTaxResidence"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += getCustomersDoc def getCustomersDoc = MessageDoc( process = "obp.getCustomers", @@ -6288,57 +4475,25 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCustomers(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCustomers(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, - fromDate="string", - toDate="string") + fromDate=fromDateExample.value, + toDate=toDateExample.value) ), exampleInboundMessage = ( - InBoundGetCustomers(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCustomers(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CustomerCommons(customerId=customerIdExample.value, bankId=bankIdExample.value, number=customerNumberExample.value, legalName=legalNameExample.value, mobileNumber=mobileNumberExample.value, email=emailExample.value, - faceImage= CustomerFaceImage(date=parseDate(customerFaceImageDateExample.value).getOrElse(sys.error("customerFaceImageDateExample.value is not validate date format.")), + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), url=urlExample.value), - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")), + dateOfBirth=toDate(dateOfBirthExample), relationshipStatus=relationshipStatusExample.value, dependents=dependentsExample.value.toInt, dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, @@ -6349,22 +4504,70 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable creditLimit= CreditLimit(currency=currencyExample.value, amount=creditLimitAmountExample.value), kycStatus=kycStatusExample.value.toBoolean, - lastOkDate=parseDate(customerLastOkDateExample.value).getOrElse(sys.error("customerLastOkDateExample.value is not validate date format.")), + lastOkDate=toDate(customerLastOkDateExample), title=customerTitleExample.value, branchId=branchIdExample.value, nameSuffix=nameSuffixExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCustomers + override def getCustomers(bankId: BankId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]): Future[Box[List[Customer]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCustomers => OutBound, InBoundGetCustomers => InBound} - val url = getUrl(callContext, "getCustomers") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) - val result: OBPReturnType[Box[List[CustomerCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCustomers => InBound, OutBoundGetCustomers => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, OBPQueryParam.getLimit(queryParams), OBPQueryParam.getOffset(queryParams), OBPQueryParam.getFromDate(queryParams), OBPQueryParam.getToDate(queryParams)) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomers"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CustomerCommons]](callContext)) } - + + messageDocs += getCustomersByCustomerPhoneNumberDoc + def getCustomersByCustomerPhoneNumberDoc = MessageDoc( + process = "obp.getCustomersByCustomerPhoneNumber", + messageFormat = messageFormat, + description = "Get Customers By Customer Phone Number", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCustomersByCustomerPhoneNumber(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + phoneNumber=phoneNumberExample.value) + ), + exampleInboundMessage = ( + InBoundGetCustomersByCustomerPhoneNumber(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( CustomerCommons(customerId=customerIdExample.value, + bankId=bankIdExample.value, + number=customerNumberExample.value, + legalName=legalNameExample.value, + mobileNumber=mobileNumberExample.value, + email=emailExample.value, + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), + url=urlExample.value), + dateOfBirth=toDate(dateOfBirthExample), + relationshipStatus=relationshipStatusExample.value, + dependents=dependentsExample.value.toInt, + dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, + highestEducationAttained=highestEducationAttainedExample.value, + employmentStatus=employmentStatusExample.value, + creditRating= CreditRating(rating=ratingExample.value, + source=sourceExample.value), + creditLimit= CreditLimit(currency=currencyExample.value, + amount=creditLimitAmountExample.value), + kycStatus=kycStatusExample.value.toBoolean, + lastOkDate=toDate(customerLastOkDateExample), + title=customerTitleExample.value, + branchId=branchIdExample.value, + nameSuffix=nameSuffixExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCustomersByCustomerPhoneNumber(bankId: BankId, phoneNumber: String, callContext: Option[CallContext]): OBPReturnType[Box[List[Customer]]] = { + import com.openbankproject.commons.dto.{InBoundGetCustomersByCustomerPhoneNumber => InBound, OutBoundGetCustomersByCustomerPhoneNumber => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, phoneNumber) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomersByCustomerPhoneNumber"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CustomerCommons]](callContext)) + } + messageDocs += getCheckbookOrdersDoc def getCheckbookOrdersDoc = MessageDoc( process = "obp.getCheckbookOrders", @@ -6373,71 +4576,38 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCheckbookOrders(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCheckbookOrders(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, accountId=accountIdExample.value) ), exampleInboundMessage = ( - InBoundGetCheckbookOrders(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= CheckbookOrdersJson(account= AccountV310Json(bank_id="string", - account_id="string", + InBoundGetCheckbookOrders(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CheckbookOrdersJson(account= AccountV310Json(bank_id=bank_idExample.value, + account_id=account_idExample.value, account_type="string", - account_routings=List( AccountRoutingJsonV121(scheme="string", - address="string")), - branch_routings=List( BranchRoutingJsonV141(scheme="string", - address="string"))), + account_routings=List( AccountRoutingJsonV121(scheme=schemeExample.value, + address=addressExample.value)), + branch_routings=List( BranchRoutingJsonV141(scheme=schemeExample.value, + address=addressExample.value))), orders=List(OrderJson( OrderObjectJson(order_id="string", order_date="string", number_of_checkbooks="string", distribution_channel="string", - status="string", + status=statusExample.value, first_check_number="string", shipping_code="string"))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCheckbookOrders + override def getCheckbookOrders(bankId: String, accountId: String, callContext: Option[CallContext]): Future[Box[(CheckbookOrdersJson, Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetCheckbookOrders => OutBound, InBoundGetCheckbookOrders => InBound} - val url = getUrl(callContext, "getCheckbookOrders") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId) - val result: OBPReturnType[Box[CheckbookOrdersJson]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCheckbookOrders => InBound, OutBoundGetCheckbookOrders => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCheckbookOrders"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CheckbookOrdersJson](callContext)) } - + messageDocs += getStatusOfCreditCardOrderDoc def getStatusOfCreditCardOrderDoc = MessageDoc( process = "obp.getStatusOfCreditCardOrder", @@ -6446,60 +4616,27 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetStatusOfCreditCardOrder(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetStatusOfCreditCardOrder(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, accountId=accountIdExample.value) ), exampleInboundMessage = ( - InBoundGetStatusOfCreditCardOrder(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetStatusOfCreditCardOrder(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CardObjectJson(card_type="string", card_description="string", use_type="string"))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getStatusOfCreditCardOrder + override def getStatusOfCreditCardOrder(bankId: String, accountId: String, callContext: Option[CallContext]): Future[Box[(List[CardObjectJson], Option[CallContext])]] = { - import com.openbankproject.commons.dto.{OutBoundGetStatusOfCreditCardOrder => OutBound, InBoundGetStatusOfCreditCardOrder => InBound} - val url = getUrl(callContext, "getStatusOfCreditCardOrder") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId) - val result: OBPReturnType[Box[List[CardObjectJson]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetStatusOfCreditCardOrder => InBound, OutBoundGetStatusOfCreditCardOrder => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getStatusOfCreditCardOrder"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CardObjectJson]](callContext)) } - + messageDocs += createUserAuthContextDoc def createUserAuthContextDoc = MessageDoc( process = "obp.createUserAuthContext", @@ -6508,62 +4645,29 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateUserAuthContext(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateUserAuthContext(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, userId=userIdExample.value, key=keyExample.value, value=valueExample.value) ), exampleInboundMessage = ( - InBoundCreateUserAuthContext(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= UserAuthContextCommons(userAuthContextId="string", + InBoundCreateUserAuthContext(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= UserAuthContextCommons(userAuthContextId=userAuthContextIdExample.value, userId=userIdExample.value, key=keyExample.value, value=valueExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createUserAuthContext + override def createUserAuthContext(userId: String, key: String, value: String, callContext: Option[CallContext]): OBPReturnType[Box[UserAuthContext]] = { - import com.openbankproject.commons.dto.{OutBoundCreateUserAuthContext => OutBound, InBoundCreateUserAuthContext => InBound} - val url = getUrl(callContext, "createUserAuthContext") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , userId, key, value) - val result: OBPReturnType[Box[UserAuthContextCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateUserAuthContext => InBound, OutBoundCreateUserAuthContext => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId, key, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createUserAuthContext"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[UserAuthContextCommons](callContext)) } - + messageDocs += createUserAuthContextUpdateDoc def createUserAuthContextUpdateDoc = MessageDoc( process = "obp.createUserAuthContextUpdate", @@ -6572,64 +4676,31 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateUserAuthContextUpdate(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateUserAuthContextUpdate(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, userId=userIdExample.value, key=keyExample.value, value=valueExample.value) ), exampleInboundMessage = ( - InBoundCreateUserAuthContextUpdate(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= UserAuthContextUpdateCommons(userAuthContextUpdateId="string", + InBoundCreateUserAuthContextUpdate(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= UserAuthContextUpdateCommons(userAuthContextUpdateId=userAuthContextUpdateIdExample.value, userId=userIdExample.value, key=keyExample.value, value=valueExample.value, - challenge="string", - status="string")) + challenge=challengeExample.value, + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createUserAuthContextUpdate + override def createUserAuthContextUpdate(userId: String, key: String, value: String, callContext: Option[CallContext]): OBPReturnType[Box[UserAuthContextUpdate]] = { - import com.openbankproject.commons.dto.{OutBoundCreateUserAuthContextUpdate => OutBound, InBoundCreateUserAuthContextUpdate => InBound} - val url = getUrl(callContext, "createUserAuthContextUpdate") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , userId, key, value) - val result: OBPReturnType[Box[UserAuthContextUpdateCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateUserAuthContextUpdate => InBound, OutBoundCreateUserAuthContextUpdate => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId, key, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createUserAuthContextUpdate"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[UserAuthContextUpdateCommons](callContext)) } - + messageDocs += deleteUserAuthContextsDoc def deleteUserAuthContextsDoc = MessageDoc( process = "obp.deleteUserAuthContexts", @@ -6638,57 +4709,24 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundDeleteUserAuthContexts(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundDeleteUserAuthContexts(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, userId=userIdExample.value) ), exampleInboundMessage = ( - InBoundDeleteUserAuthContexts(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundDeleteUserAuthContexts(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /deleteUserAuthContexts + override def deleteUserAuthContexts(userId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteUserAuthContexts => OutBound, InBoundDeleteUserAuthContexts => InBound} - val url = getUrl(callContext, "deleteUserAuthContexts") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , userId) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.DELETE, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundDeleteUserAuthContexts => InBound, OutBoundDeleteUserAuthContexts => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deleteUserAuthContexts"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += deleteUserAuthContextByIdDoc def deleteUserAuthContextByIdDoc = MessageDoc( process = "obp.deleteUserAuthContextById", @@ -6697,57 +4735,24 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundDeleteUserAuthContextById(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - userAuthContextId="string") + OutBoundDeleteUserAuthContextById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + userAuthContextId=userAuthContextIdExample.value) ), exampleInboundMessage = ( - InBoundDeleteUserAuthContextById(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundDeleteUserAuthContextById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /deleteUserAuthContextById + override def deleteUserAuthContextById(userAuthContextId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteUserAuthContextById => OutBound, InBoundDeleteUserAuthContextById => InBound} - val url = getUrl(callContext, "deleteUserAuthContextById") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , userAuthContextId) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.DELETE, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundDeleteUserAuthContextById => InBound, OutBoundDeleteUserAuthContextById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userAuthContextId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deleteUserAuthContextById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += getUserAuthContextsDoc def getUserAuthContextsDoc = MessageDoc( process = "obp.getUserAuthContexts", @@ -6756,60 +4761,27 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetUserAuthContexts(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetUserAuthContexts(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, userId=userIdExample.value) ), exampleInboundMessage = ( - InBoundGetUserAuthContexts(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( UserAuthContextCommons(userAuthContextId="string", + InBoundGetUserAuthContexts(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( UserAuthContextCommons(userAuthContextId=userAuthContextIdExample.value, userId=userIdExample.value, key=keyExample.value, value=valueExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getUserAuthContexts + override def getUserAuthContexts(userId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[UserAuthContext]]] = { - import com.openbankproject.commons.dto.{OutBoundGetUserAuthContexts => OutBound, InBoundGetUserAuthContexts => InBound} - val url = getUrl(callContext, "getUserAuthContexts") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , userId) - val result: OBPReturnType[Box[List[UserAuthContextCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetUserAuthContexts => InBound, OutBoundGetUserAuthContexts => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, userId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getUserAuthContexts"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[UserAuthContextCommons]](callContext)) } - + messageDocs += createOrUpdateProductAttributeDoc def createOrUpdateProductAttributeDoc = MessageDoc( process = "obp.createOrUpdateProductAttribute", @@ -6818,67 +4790,35 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateProductAttribute(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateProductAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId=Some("string"), - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=Some(productAttributeIdExample.value), + name=nameExample.value, productAttributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, value=valueExample.value) ), exampleInboundMessage = ( - InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value)) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateProductAttribute + override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateProductAttribute => OutBound, InBoundCreateOrUpdateProductAttribute => InBound} - val url = getUrl(callContext, "createOrUpdateProductAttribute") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, productCode, productAttributeId, name, productAttributeType, value) - val result: OBPReturnType[Box[ProductAttributeCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateProductAttribute => InBound, OutBoundCreateOrUpdateProductAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateProductAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[ProductAttributeCommons](callContext)) } - + messageDocs += getProductAttributeByIdDoc def getProductAttributeByIdDoc = MessageDoc( process = "obp.getProductAttributeById", @@ -6887,62 +4827,30 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetProductAttributeById(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - productAttributeId="string") + OutBoundGetProductAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + productAttributeId=productAttributeIdExample.value) ), exampleInboundMessage = ( - InBoundGetProductAttributeById(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetProductAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value)) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getProductAttributeById + override def getProductAttributeById(productAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductAttributeById => OutBound, InBoundGetProductAttributeById => InBound} - val url = getUrl(callContext, "getProductAttributeById") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , productAttributeId) - val result: OBPReturnType[Box[ProductAttributeCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetProductAttributeById => InBound, OutBoundGetProductAttributeById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, productAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProductAttributeById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[ProductAttributeCommons](callContext)) } - + messageDocs += getProductAttributesByBankAndCodeDoc def getProductAttributesByBankAndCodeDoc = MessageDoc( process = "obp.getProductAttributesByBankAndCode", @@ -6951,63 +4859,31 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetProductAttributesByBankAndCode(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - bank=BankId(bankIdExample.value), - productCode=ProductCode("string")) + OutBoundGetProductAttributesByBankAndCode(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bank=BankId(bankExample.value), + productCode=ProductCode(productCodeExample.value)) ), exampleInboundMessage = ( - InBoundGetProductAttributesByBankAndCode(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetProductAttributesByBankAndCode(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getProductAttributesByBankAndCode + override def getProductAttributesByBankAndCode(bank: BankId, productCode: ProductCode, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductAttributesByBankAndCode => OutBound, InBoundGetProductAttributesByBankAndCode => InBound} - val url = getUrl(callContext, "getProductAttributesByBankAndCode") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bank, productCode) - val result: OBPReturnType[Box[List[ProductAttributeCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetProductAttributesByBankAndCode => InBound, OutBoundGetProductAttributesByBankAndCode => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bank, productCode) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProductAttributesByBankAndCode"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductAttributeCommons]](callContext)) } - + messageDocs += deleteProductAttributeDoc def deleteProductAttributeDoc = MessageDoc( process = "obp.deleteProductAttribute", @@ -7016,57 +4892,24 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundDeleteProductAttribute(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - productAttributeId="string") + OutBoundDeleteProductAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + productAttributeId=productAttributeIdExample.value) ), exampleInboundMessage = ( - InBoundDeleteProductAttribute(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundDeleteProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=true) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /deleteProductAttribute + override def deleteProductAttribute(productAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { - import com.openbankproject.commons.dto.{OutBoundDeleteProductAttribute => OutBound, InBoundDeleteProductAttribute => InBound} - val url = getUrl(callContext, "deleteProductAttribute") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , productAttributeId) - val result: OBPReturnType[Box[Boolean]] = sendRequest[InBound](url, HttpMethods.DELETE, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundDeleteProductAttribute => InBound, OutBoundDeleteProductAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, productAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deleteProductAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) } - + messageDocs += getAccountAttributeByIdDoc def getAccountAttributeByIdDoc = MessageDoc( process = "obp.getAccountAttributeById", @@ -7075,63 +4918,61 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAccountAttributeById(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - accountAttributeId="string") + OutBoundGetAccountAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + accountAttributeId=accountAttributeIdExample.value) ), exampleInboundMessage = ( - InBoundGetAccountAttributeById(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetAccountAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAccountAttributeById + override def getAccountAttributeById(accountAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetAccountAttributeById => OutBound, InBoundGetAccountAttributeById => InBound} - val url = getUrl(callContext, "getAccountAttributeById") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , accountAttributeId) - val result: OBPReturnType[Box[AccountAttributeCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAccountAttributeById => InBound, OutBoundGetAccountAttributeById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAccountAttributeById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AccountAttributeCommons](callContext)) } - + + messageDocs += getTransactionAttributeByIdDoc + def getTransactionAttributeByIdDoc = MessageDoc( + process = "obp.getTransactionAttributeById", + messageFormat = messageFormat, + description = "Get Transaction Attribute By Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetTransactionAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + transactionAttributeId=transactionAttributeIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetTransactionAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionAttributeCommons(bankId=BankId(bankIdExample.value), + transactionId=TransactionId(transactionIdExample.value), + transactionAttributeId=transactionAttributeIdExample.value, + attributeType=com.openbankproject.commons.model.enums.TransactionAttributeType.example, + name=transactionAttributeNameExample.value, + value=transactionAttributeValueExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getTransactionAttributeById(transactionAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionAttribute]] = { + import com.openbankproject.commons.dto.{InBoundGetTransactionAttributeById => InBound, OutBoundGetTransactionAttributeById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, transactionAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactionAttributeById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionAttributeCommons](callContext)) + } + messageDocs += createOrUpdateAccountAttributeDoc def createOrUpdateAccountAttributeDoc = MessageDoc( process = "obp.createOrUpdateAccountAttribute", @@ -7140,69 +4981,108 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateAccountAttribute(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateAccountAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - productAttributeId=Some("string"), - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=Some(productAttributeIdExample.value), + name=nameExample.value, accountAttributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value) ), exampleInboundMessage = ( - InBoundCreateOrUpdateAccountAttribute(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateAccountAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateAccountAttribute + override def createOrUpdateAccountAttribute(bankId: BankId, accountId: AccountId, productCode: ProductCode, productAttributeId: Option[String], name: String, accountAttributeType: AccountAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateAccountAttribute => OutBound, InBoundCreateOrUpdateAccountAttribute => InBound} - val url = getUrl(callContext, "createOrUpdateAccountAttribute") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, productCode, productAttributeId, name, accountAttributeType, value) - val result: OBPReturnType[Box[AccountAttributeCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateAccountAttribute => InBound, OutBoundCreateOrUpdateAccountAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, productCode, productAttributeId, name, accountAttributeType, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateAccountAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AccountAttributeCommons](callContext)) } - + + messageDocs += createOrUpdateCustomerAttributeDoc + def createOrUpdateCustomerAttributeDoc = MessageDoc( + process = "obp.createOrUpdateCustomerAttribute", + messageFormat = messageFormat, + description = "Create Or Update Customer Attribute", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateOrUpdateCustomerAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + customerId=CustomerId(customerIdExample.value), + customerAttributeId=Some(customerAttributeIdExample.value), + name=nameExample.value, + attributeType=com.openbankproject.commons.model.enums.CustomerAttributeType.example, + value=valueExample.value) + ), + exampleInboundMessage = ( + InBoundCreateOrUpdateCustomerAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CustomerAttributeCommons(bankId=BankId(bankIdExample.value), + customerId=CustomerId(customerIdExample.value), + customerAttributeId=customerAttributeIdExample.value, + attributeType=com.openbankproject.commons.model.enums.CustomerAttributeType.example, + name=customerAttributeNameExample.value, + value=customerAttributeValueExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createOrUpdateCustomerAttribute(bankId: BankId, customerId: CustomerId, customerAttributeId: Option[String], name: String, attributeType: CustomerAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAttribute]] = { + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateCustomerAttribute => InBound, OutBoundCreateOrUpdateCustomerAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, customerAttributeId, name, attributeType, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateCustomerAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerAttributeCommons](callContext)) + } + + messageDocs += createOrUpdateTransactionAttributeDoc + def createOrUpdateTransactionAttributeDoc = MessageDoc( + process = "obp.createOrUpdateTransactionAttribute", + messageFormat = messageFormat, + description = "Create Or Update Transaction Attribute", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateOrUpdateTransactionAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + transactionId=TransactionId(transactionIdExample.value), + transactionAttributeId=Some(transactionAttributeIdExample.value), + name=nameExample.value, + attributeType=com.openbankproject.commons.model.enums.TransactionAttributeType.example, + value=valueExample.value) + ), + exampleInboundMessage = ( + InBoundCreateOrUpdateTransactionAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= TransactionAttributeCommons(bankId=BankId(bankIdExample.value), + transactionId=TransactionId(transactionIdExample.value), + transactionAttributeId=transactionAttributeIdExample.value, + attributeType=com.openbankproject.commons.model.enums.TransactionAttributeType.example, + name=transactionAttributeNameExample.value, + value=transactionAttributeValueExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createOrUpdateTransactionAttribute(bankId: BankId, transactionId: TransactionId, transactionAttributeId: Option[String], name: String, attributeType: TransactionAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionAttribute]] = { + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateTransactionAttribute => InBound, OutBoundCreateOrUpdateTransactionAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, transactionId, transactionAttributeId, name, attributeType, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateTransactionAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionAttributeCommons](callContext)) + } + messageDocs += createAccountAttributesDoc def createAccountAttributesDoc = MessageDoc( process = "obp.createAccountAttributes", @@ -7211,71 +5091,39 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateAccountAttributes(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateAccountAttributes(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), + productCode=ProductCode(productCodeExample.value), accountAttributes=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))) ), exampleInboundMessage = ( - InBoundCreateAccountAttributes(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateAccountAttributes(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createAccountAttributes + override def createAccountAttributes(bankId: BankId, accountId: AccountId, productCode: ProductCode, accountAttributes: List[ProductAttribute], callContext: Option[CallContext]): OBPReturnType[Box[List[AccountAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundCreateAccountAttributes => OutBound, InBoundCreateAccountAttributes => InBound} - val url = getUrl(callContext, "createAccountAttributes") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId, productCode, accountAttributes) - val result: OBPReturnType[Box[List[AccountAttributeCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateAccountAttributes => InBound, OutBoundCreateAccountAttributes => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, productCode, accountAttributes) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createAccountAttributes"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[AccountAttributeCommons]](callContext)) } - + messageDocs += getAccountAttributesByAccountDoc def getAccountAttributesByAccountDoc = MessageDoc( process = "obp.getAccountAttributesByAccount", @@ -7284,64 +5132,234 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAccountAttributesByAccount(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetAccountAttributesByAccount(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value)) ), exampleInboundMessage = ( - InBoundGetAccountAttributesByAccount(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetAccountAttributesByAccount(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( AccountAttributeCommons(bankId=BankId(bankIdExample.value), accountId=AccountId(accountIdExample.value), - productCode=ProductCode("string"), - accountAttributeId="string", - name="string", + productCode=ProductCode(productCodeExample.value), + accountAttributeId=accountAttributeIdExample.value, + name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.AccountAttributeType.example, value=valueExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAccountAttributesByAccount + override def getAccountAttributesByAccount(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[List[AccountAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetAccountAttributesByAccount => OutBound, InBoundGetAccountAttributesByAccount => InBound} - val url = getUrl(callContext, "getAccountAttributesByAccount") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, accountId) - val result: OBPReturnType[Box[List[AccountAttributeCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAccountAttributesByAccount => InBound, OutBoundGetAccountAttributesByAccount => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAccountAttributesByAccount"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[AccountAttributeCommons]](callContext)) } - + + messageDocs += getCustomerAttributesDoc + def getCustomerAttributesDoc = MessageDoc( + process = "obp.getCustomerAttributes", + messageFormat = messageFormat, + description = "Get Customer Attributes", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCustomerAttributes(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + customerId=CustomerId(customerIdExample.value)) + ), + exampleInboundMessage = ( + InBoundGetCustomerAttributes(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( CustomerAttributeCommons(bankId=BankId(bankIdExample.value), + customerId=CustomerId(customerIdExample.value), + customerAttributeId=customerAttributeIdExample.value, + attributeType=com.openbankproject.commons.model.enums.CustomerAttributeType.example, + name=customerAttributeNameExample.value, + value=customerAttributeValueExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCustomerAttributes(bankId: BankId, customerId: CustomerId, callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAttribute]]] = { + import com.openbankproject.commons.dto.{InBoundGetCustomerAttributes => InBound, OutBoundGetCustomerAttributes => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerAttributes"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CustomerAttributeCommons]](callContext)) + } + + messageDocs += getCustomerIdsByAttributeNameValuesDoc + def getCustomerIdsByAttributeNameValuesDoc = MessageDoc( + process = "obp.getCustomerIdsByAttributeNameValues", + messageFormat = messageFormat, + description = "Get Customer Ids By Attribute Name Values", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCustomerIdsByAttributeNameValues(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + nameValues=Map("some_name" -> List("name1", "name2"))) + ), + exampleInboundMessage = ( + InBoundGetCustomerIdsByAttributeNameValues(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=listExample.value.split("[,;]").toList) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCustomerIdsByAttributeNameValues(bankId: BankId, nameValues: Map[String,List[String]], callContext: Option[CallContext]): OBPReturnType[Box[List[String]]] = { + import com.openbankproject.commons.dto.{InBoundGetCustomerIdsByAttributeNameValues => InBound, OutBoundGetCustomerIdsByAttributeNameValues => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, nameValues) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerIdsByAttributeNameValues"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[String]](callContext)) + } + + messageDocs += getCustomerAttributesForCustomersDoc + def getCustomerAttributesForCustomersDoc = MessageDoc( + process = "obp.getCustomerAttributesForCustomers", + messageFormat = messageFormat, + description = "Get Customer Attributes For Customers", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCustomerAttributesForCustomers(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + customers=List( CustomerCommons(customerId=customerIdExample.value, + bankId=bankIdExample.value, + number=customerNumberExample.value, + legalName=legalNameExample.value, + mobileNumber=mobileNumberExample.value, + email=emailExample.value, + faceImage= CustomerFaceImage(date=toDate(customerFaceImageDateExample), + url=urlExample.value), + dateOfBirth=toDate(dateOfBirthExample), + relationshipStatus=relationshipStatusExample.value, + dependents=dependentsExample.value.toInt, + dobOfDependents=dobOfDependentsExample.value.split("[,;]").map(parseDate).flatMap(_.toSeq).toList, + highestEducationAttained=highestEducationAttainedExample.value, + employmentStatus=employmentStatusExample.value, + creditRating= CreditRating(rating=ratingExample.value, + source=sourceExample.value), + creditLimit= CreditLimit(currency=currencyExample.value, + amount=creditLimitAmountExample.value), + kycStatus=kycStatusExample.value.toBoolean, + lastOkDate=toDate(customerLastOkDateExample), + title=customerTitleExample.value, + branchId=branchIdExample.value, + nameSuffix=nameSuffixExample.value))) + ), + exampleInboundMessage = ( + InBoundGetCustomerAttributesForCustomers(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= List( + CustomerAndAttribute( + MessageDocsSwaggerDefinitions.customerCommons, + List(MessageDocsSwaggerDefinitions.customerAttribute) + ) + ) + ) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCustomerAttributesForCustomers(customers: List[Customer], callContext: Option[CallContext]): OBPReturnType[Box[List[CustomerAndAttribute]]] = { + import com.openbankproject.commons.dto.{InBoundGetCustomerAttributesForCustomers => InBound, OutBoundGetCustomerAttributesForCustomers => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customers) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerAttributesForCustomers"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CustomerAndAttribute]](callContext)) + } + + messageDocs += getTransactionIdsByAttributeNameValuesDoc + def getTransactionIdsByAttributeNameValuesDoc = MessageDoc( + process = "obp.getTransactionIdsByAttributeNameValues", + messageFormat = messageFormat, + description = "Get Transaction Ids By Attribute Name Values", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetTransactionIdsByAttributeNameValues(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + nameValues=Map("some_name" -> List("name1", "name2"))) + ), + exampleInboundMessage = ( + InBoundGetTransactionIdsByAttributeNameValues(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=listExample.value.split("[,;]").toList) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getTransactionIdsByAttributeNameValues(bankId: BankId, nameValues: Map[String,List[String]], callContext: Option[CallContext]): OBPReturnType[Box[List[String]]] = { + import com.openbankproject.commons.dto.{InBoundGetTransactionIdsByAttributeNameValues => InBound, OutBoundGetTransactionIdsByAttributeNameValues => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, nameValues) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactionIdsByAttributeNameValues"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[String]](callContext)) + } + + messageDocs += getTransactionAttributesDoc + def getTransactionAttributesDoc = MessageDoc( + process = "obp.getTransactionAttributes", + messageFormat = messageFormat, + description = "Get Transaction Attributes", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetTransactionAttributes(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + transactionId=TransactionId(transactionIdExample.value)) + ), + exampleInboundMessage = ( + InBoundGetTransactionAttributes(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( TransactionAttributeCommons(bankId=BankId(bankIdExample.value), + transactionId=TransactionId(transactionIdExample.value), + transactionAttributeId=transactionAttributeIdExample.value, + attributeType=com.openbankproject.commons.model.enums.TransactionAttributeType.example, + name=transactionAttributeNameExample.value, + value=transactionAttributeValueExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getTransactionAttributes(bankId: BankId, transactionId: TransactionId, callContext: Option[CallContext]): OBPReturnType[Box[List[TransactionAttribute]]] = { + import com.openbankproject.commons.dto.{InBoundGetTransactionAttributes => InBound, OutBoundGetTransactionAttributes => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, transactionId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getTransactionAttributes"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[TransactionAttributeCommons]](callContext)) + } + + messageDocs += getCustomerAttributeByIdDoc + def getCustomerAttributeByIdDoc = MessageDoc( + process = "obp.getCustomerAttributeById", + messageFormat = messageFormat, + description = "Get Customer Attribute By Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetCustomerAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + customerAttributeId=customerAttributeIdExample.value) + ), + exampleInboundMessage = ( + InBoundGetCustomerAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= CustomerAttributeCommons(bankId=BankId(bankIdExample.value), + customerId=CustomerId(customerIdExample.value), + customerAttributeId=customerAttributeIdExample.value, + attributeType=com.openbankproject.commons.model.enums.CustomerAttributeType.example, + name=customerAttributeNameExample.value, + value=customerAttributeValueExample.value)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getCustomerAttributeById(customerAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerAttribute]] = { + import com.openbankproject.commons.dto.{InBoundGetCustomerAttributeById => InBound, OutBoundGetCustomerAttributeById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCustomerAttributeById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerAttributeCommons](callContext)) + } + messageDocs += createOrUpdateCardAttributeDoc def createOrUpdateCardAttributeDoc = MessageDoc( process = "obp.createOrUpdateCardAttribute", @@ -7350,49 +5368,17 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateCardAttribute(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateCardAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=Some(BankId(bankIdExample.value)), cardId=Some(cardIdExample.value), cardAttributeId=Some(cardAttributeIdExample.value), - name="string", + name=nameExample.value, cardAttributeType=com.openbankproject.commons.model.enums.CardAttributeType.example, value=valueExample.value) ), exampleInboundMessage = ( - InBoundCreateOrUpdateCardAttribute(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateCardAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CardAttributeCommons(bankId=Some(BankId(bankIdExample.value)), cardId=Some(cardIdExample.value), cardAttributeId=Some(cardAttributeIdExample.value), @@ -7402,15 +5388,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateCardAttribute + override def createOrUpdateCardAttribute(bankId: Option[BankId], cardId: Option[String], cardAttributeId: Option[String], name: String, cardAttributeType: CardAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[CardAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateCardAttribute => OutBound, InBoundCreateOrUpdateCardAttribute => InBound} - val url = getUrl(callContext, "createOrUpdateCardAttribute") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, cardId, cardAttributeId, name, cardAttributeType, value) - val result: OBPReturnType[Box[CardAttributeCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateCardAttribute => InBound, OutBoundCreateOrUpdateCardAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, cardId, cardAttributeId, name, cardAttributeType, value) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateCardAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CardAttributeCommons](callContext)) } - + messageDocs += getCardAttributeByIdDoc def getCardAttributeByIdDoc = MessageDoc( process = "obp.getCardAttributeById", @@ -7419,44 +5404,12 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCardAttributeById(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCardAttributeById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, cardAttributeId=cardAttributeIdExample.value) ), exampleInboundMessage = ( - InBoundGetCardAttributeById(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCardAttributeById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CardAttributeCommons(bankId=Some(BankId(bankIdExample.value)), cardId=Some(cardIdExample.value), cardAttributeId=Some(cardAttributeIdExample.value), @@ -7466,15 +5419,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCardAttributeById + override def getCardAttributeById(cardAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[CardAttribute]] = { - import com.openbankproject.commons.dto.{OutBoundGetCardAttributeById => OutBound, InBoundGetCardAttributeById => InBound} - val url = getUrl(callContext, "getCardAttributeById") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , cardAttributeId) - val result: OBPReturnType[Box[CardAttributeCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCardAttributeById => InBound, OutBoundGetCardAttributeById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, cardAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCardAttributeById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CardAttributeCommons](callContext)) } - + messageDocs += getCardAttributesFromProviderDoc def getCardAttributesFromProviderDoc = MessageDoc( process = "obp.getCardAttributesFromProvider", @@ -7483,44 +5435,12 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetCardAttributesFromProvider(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetCardAttributesFromProvider(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, cardId=cardIdExample.value) ), exampleInboundMessage = ( - InBoundGetCardAttributesFromProvider(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetCardAttributesFromProvider(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( CardAttributeCommons(bankId=Some(BankId(bankIdExample.value)), cardId=Some(cardIdExample.value), cardAttributeId=Some(cardAttributeIdExample.value), @@ -7530,15 +5450,14 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getCardAttributesFromProvider + override def getCardAttributesFromProvider(cardId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[CardAttribute]]] = { - import com.openbankproject.commons.dto.{OutBoundGetCardAttributesFromProvider => OutBound, InBoundGetCardAttributesFromProvider => InBound} - val url = getUrl(callContext, "getCardAttributesFromProvider") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , cardId) - val result: OBPReturnType[Box[List[CardAttributeCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetCardAttributesFromProvider => InBound, OutBoundGetCardAttributesFromProvider => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, cardId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getCardAttributesFromProvider"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[CardAttributeCommons]](callContext)) } - + messageDocs += createAccountApplicationDoc def createAccountApplicationDoc = MessageDoc( process = "obp.createAccountApplication", @@ -7547,64 +5466,31 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateAccountApplication(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - productCode=ProductCode("string"), + OutBoundCreateAccountApplication(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + productCode=ProductCode(productCodeExample.value), userId=Some(userIdExample.value), customerId=Some(customerIdExample.value)) ), exampleInboundMessage = ( - InBoundCreateAccountApplication(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + InBoundCreateAccountApplication(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string")) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createAccountApplication + override def createAccountApplication(productCode: ProductCode, userId: Option[String], customerId: Option[String], callContext: Option[CallContext]): OBPReturnType[Box[AccountApplication]] = { - import com.openbankproject.commons.dto.{OutBoundCreateAccountApplication => OutBound, InBoundCreateAccountApplication => InBound} - val url = getUrl(callContext, "createAccountApplication") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , productCode, userId, customerId) - val result: OBPReturnType[Box[AccountApplicationCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateAccountApplication => InBound, OutBoundCreateAccountApplication => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, productCode, userId, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createAccountApplication"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AccountApplicationCommons](callContext)) } - + messageDocs += getAllAccountApplicationDoc def getAllAccountApplicationDoc = MessageDoc( process = "obp.getAllAccountApplication", @@ -7613,61 +5499,28 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAllAccountApplication( OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value)))))))))) + OutBoundGetAllAccountApplication(MessageDocsSwaggerDefinitions.outboundAdapterCallContext) ), exampleInboundMessage = ( - InBoundGetAllAccountApplication(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + InBoundGetAllAccountApplication(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string"))) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAllAccountApplication + override def getAllAccountApplication(callContext: Option[CallContext]): OBPReturnType[Box[List[AccountApplication]]] = { - import com.openbankproject.commons.dto.{OutBoundGetAllAccountApplication => OutBound, InBoundGetAllAccountApplication => InBound} - val url = getUrl(callContext, "getAllAccountApplication") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull ) - val result: OBPReturnType[Box[List[AccountApplicationCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAllAccountApplication => InBound, OutBoundGetAllAccountApplication => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAllAccountApplication"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[AccountApplicationCommons]](callContext)) } - + messageDocs += getAccountApplicationByIdDoc def getAccountApplicationByIdDoc = MessageDoc( process = "obp.getAccountApplicationById", @@ -7676,62 +5529,29 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetAccountApplicationById(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - accountApplicationId="string") + OutBoundGetAccountApplicationById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + accountApplicationId=accountApplicationIdExample.value) ), exampleInboundMessage = ( - InBoundGetAccountApplicationById(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + InBoundGetAccountApplicationById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string")) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getAccountApplicationById + override def getAccountApplicationById(accountApplicationId: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountApplication]] = { - import com.openbankproject.commons.dto.{OutBoundGetAccountApplicationById => OutBound, InBoundGetAccountApplicationById => InBound} - val url = getUrl(callContext, "getAccountApplicationById") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , accountApplicationId) - val result: OBPReturnType[Box[AccountApplicationCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetAccountApplicationById => InBound, OutBoundGetAccountApplicationById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountApplicationId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getAccountApplicationById"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AccountApplicationCommons](callContext)) } - + messageDocs += updateAccountApplicationStatusDoc def updateAccountApplicationStatusDoc = MessageDoc( process = "obp.updateAccountApplicationStatus", @@ -7740,63 +5560,30 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundUpdateAccountApplicationStatus(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - accountApplicationId="string", - status="string") + OutBoundUpdateAccountApplicationStatus(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + accountApplicationId=accountApplicationIdExample.value, + status=statusExample.value) ), exampleInboundMessage = ( - InBoundUpdateAccountApplicationStatus(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= AccountApplicationCommons(accountApplicationId="string", - productCode=ProductCode("string"), + InBoundUpdateAccountApplicationStatus(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= AccountApplicationCommons(accountApplicationId=accountApplicationIdExample.value, + productCode=ProductCode(productCodeExample.value), userId=userIdExample.value, customerId=customerIdExample.value, - dateOfApplication=new Date(), - status="string")) + dateOfApplication=toDate(dateOfApplicationExample), + status=statusExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /updateAccountApplicationStatus + override def updateAccountApplicationStatus(accountApplicationId: String, status: String, callContext: Option[CallContext]): OBPReturnType[Box[AccountApplication]] = { - import com.openbankproject.commons.dto.{OutBoundUpdateAccountApplicationStatus => OutBound, InBoundUpdateAccountApplicationStatus => InBound} - val url = getUrl(callContext, "updateAccountApplicationStatus") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , accountApplicationId, status) - val result: OBPReturnType[Box[AccountApplicationCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundUpdateAccountApplicationStatus => InBound, OutBoundUpdateAccountApplicationStatus => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountApplicationId, status) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "updateAccountApplicationStatus"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[AccountApplicationCommons](callContext)) } - + messageDocs += getOrCreateProductCollectionDoc def getOrCreateProductCollectionDoc = MessageDoc( process = "obp.getOrCreateProductCollection", @@ -7805,59 +5592,26 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetOrCreateProductCollection(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - collectionCode="string", - productCodes=List("string")) + OutBoundGetOrCreateProductCollection(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + collectionCode=collectionCodeExample.value, + productCodes=listExample.value.split("[,;]").toList) ), exampleInboundMessage = ( - InBoundGetOrCreateProductCollection(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( ProductCollectionCommons(collectionCode="string", - productCode="string"))) + InBoundGetOrCreateProductCollection(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCollectionCommons(collectionCode=collectionCodeExample.value, + productCode=productCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getOrCreateProductCollection + override def getOrCreateProductCollection(collectionCode: String, productCodes: List[String], callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollection]]] = { - import com.openbankproject.commons.dto.{OutBoundGetOrCreateProductCollection => OutBound, InBoundGetOrCreateProductCollection => InBound} - val url = getUrl(callContext, "getOrCreateProductCollection") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , collectionCode, productCodes) - val result: OBPReturnType[Box[List[ProductCollectionCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetOrCreateProductCollection => InBound, OutBoundGetOrCreateProductCollection => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, productCodes) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getOrCreateProductCollection"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductCollectionCommons]](callContext)) } - + messageDocs += getProductCollectionDoc def getProductCollectionDoc = MessageDoc( process = "obp.getProductCollection", @@ -7866,58 +5620,25 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetProductCollection(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - collectionCode="string") + OutBoundGetProductCollection(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + collectionCode=collectionCodeExample.value) ), exampleInboundMessage = ( - InBoundGetProductCollection(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( ProductCollectionCommons(collectionCode="string", - productCode="string"))) + InBoundGetProductCollection(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCollectionCommons(collectionCode=collectionCodeExample.value, + productCode=productCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getProductCollection + override def getProductCollection(collectionCode: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollection]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductCollection => OutBound, InBoundGetProductCollection => InBound} - val url = getUrl(callContext, "getProductCollection") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , collectionCode) - val result: OBPReturnType[Box[List[ProductCollectionCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetProductCollection => InBound, OutBoundGetProductCollection => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProductCollection"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductCollectionCommons]](callContext)) } - + messageDocs += getOrCreateProductCollectionItemDoc def getOrCreateProductCollectionItemDoc = MessageDoc( process = "obp.getOrCreateProductCollectionItem", @@ -7926,59 +5647,26 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetOrCreateProductCollectionItem(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - collectionCode="string", - memberProductCodes=List("string")) + OutBoundGetOrCreateProductCollectionItem(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + collectionCode=collectionCodeExample.value, + memberProductCodes=listExample.value.split("[,;]").toList) ), exampleInboundMessage = ( - InBoundGetOrCreateProductCollectionItem(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( ProductCollectionItemCommons(collectionCode="string", - memberProductCode="string"))) + InBoundGetOrCreateProductCollectionItem(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + memberProductCode=memberProductCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getOrCreateProductCollectionItem + override def getOrCreateProductCollectionItem(collectionCode: String, memberProductCodes: List[String], callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItem]]] = { - import com.openbankproject.commons.dto.{OutBoundGetOrCreateProductCollectionItem => OutBound, InBoundGetOrCreateProductCollectionItem => InBound} - val url = getUrl(callContext, "getOrCreateProductCollectionItem") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , collectionCode, memberProductCodes) - val result: OBPReturnType[Box[List[ProductCollectionItemCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetOrCreateProductCollectionItem => InBound, OutBoundGetOrCreateProductCollectionItem => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, memberProductCodes) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getOrCreateProductCollectionItem"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductCollectionItemCommons]](callContext)) } - + messageDocs += getProductCollectionItemDoc def getProductCollectionItemDoc = MessageDoc( process = "obp.getProductCollectionItem", @@ -7987,58 +5675,25 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetProductCollectionItem(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), - collectionCode="string") + OutBoundGetProductCollectionItem(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + collectionCode=collectionCodeExample.value) ), exampleInboundMessage = ( - InBoundGetProductCollectionItem(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( ProductCollectionItemCommons(collectionCode="string", - memberProductCode="string"))) + InBoundGetProductCollectionItem(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + memberProductCode=memberProductCodeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getProductCollectionItem - override def getProductCollectionItem(collectionCode: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItem]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductCollectionItem => OutBound, InBoundGetProductCollectionItem => InBound} - val url = getUrl(callContext, "getProductCollectionItem") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , collectionCode) - val result: OBPReturnType[Box[List[ProductCollectionItemCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } + override def getProductCollectionItem(collectionCode: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItem]]] = { + import com.openbankproject.commons.dto.{InBoundGetProductCollectionItem => InBound, OutBoundGetProductCollectionItem => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProductCollectionItem"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductCollectionItemCommons]](callContext)) + } + messageDocs += getProductCollectionItemsTreeDoc def getProductCollectionItemsTreeDoc = MessageDoc( process = "obp.getProductCollectionItemsTree", @@ -8047,44 +5702,45 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetProductCollectionItemsTree(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, - collectionCode="string", - bankId=bankIdExample.value) - ), + OutBoundGetProductCollectionItemsTree(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + collectionCode=collectionCodeExample.value, + bankId=bankIdExample.value) + ), exampleInboundMessage = ( - InBoundGetProductCollectionItemsTree(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, - status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode="string", - memberProductCode="string"), - product= ProductCommons(bankId=BankId(bankIdExample.value), - code=ProductCode("string"), - parentProductCode=ProductCode("string"), - name="string", - category="string", - family="string", - superFamily="string", - moreInfoUrl="string", - details="string", - description="string", - meta=Meta( License(id="string", - name="string"))), - attributes=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), - productCode=ProductCode("string"), - productAttributeId="string", - name="string", - attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))))) - ), + InBoundGetProductCollectionItemsTree(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + memberProductCode=memberProductCodeExample.value), + product= ProductCommons(bankId=BankId(bankIdExample.value), + code=ProductCode(productCodeExample.value), + parentProductCode=ProductCode(parentProductCodeExample.value), + name=nameExample.value, + category=categoryExample.value, + family=familyExample.value, + superFamily=superFamilyExample.value, + moreInfoUrl=moreInfoUrlExample.value, + details=detailsExample.value, + description=descriptionExample.value, + meta=Meta( License(id=idExample.value, + name=nameExample.value))), + attributes=List( ProductAttributeCommons(bankId=BankId(bankIdExample.value), + productCode=ProductCode(productCodeExample.value), + productAttributeId=productAttributeIdExample.value, + name=nameExample.value, + attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))))) + ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) override def getProductCollectionItemsTree(collectionCode: String, bankId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[ProductCollectionItemsTree]]] = { - import com.openbankproject.commons.dto.{OutBoundGetProductCollectionItemsTree => OutBound, InBoundGetProductCollectionItemsTree => InBound} - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, bankId) - val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProductCollectionItemsTree"), HttpMethods.POST, req, callContext) - response.map(convertToTuple[List[ProductCollectionItemsTree]](callContext)) + import com.openbankproject.commons.dto.{InBoundGetProductCollectionItemsTree => InBound, OutBoundGetProductCollectionItemsTree => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, collectionCode, bankId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getProductCollectionItemsTree"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[ProductCollectionItemsTree]](callContext)) } - + messageDocs += createMeetingDoc def createMeetingDoc = MessageDoc( process = "obp.createMeeting", @@ -8093,98 +5749,71 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateMeeting(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateMeeting(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), staffUser= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), customerUser= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), - providerId="string", - purposeId="string", - when=new Date(), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, + when=toDate(whenExample), sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string", - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value, + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string"))) + status=statusExample.value))) ), exampleInboundMessage = ( - InBoundCreateMeeting(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= MeetingCommons(meetingId="string", - providerId="string", - purposeId="string", + InBoundCreateMeeting(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= MeetingCommons(meetingId=meetingIdExample.value, + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, bankId=bankIdExample.value, - present= MeetingPresent(staffUserId="string", - customerUserId="string"), + present= MeetingPresent(staffUserId=staffUserIdExample.value, + customerUserId=customerUserIdExample.value), keys= MeetingKeys(sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string"), - when=new Date(), - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value), + when=toDate(whenExample), + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string")))) + status=statusExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createMeeting + override def createMeeting(bankId: BankId, staffUser: User, customerUser: User, providerId: String, purposeId: String, when: Date, sessionId: String, customerToken: String, staffToken: String, creator: ContactDetails, invitees: List[Invitee], callContext: Option[CallContext]): OBPReturnType[Box[Meeting]] = { - import com.openbankproject.commons.dto.{OutBoundCreateMeeting => OutBound, InBoundCreateMeeting => InBound} - val url = getUrl(callContext, "createMeeting") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, staffUser, customerUser, providerId, purposeId, when, sessionId, customerToken, staffToken, creator, invitees) - val result: OBPReturnType[Box[MeetingCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateMeeting => InBound, OutBoundCreateMeeting => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, staffUser, customerUser, providerId, purposeId, when, sessionId, customerToken, staffToken, creator, invitees) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createMeeting"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[MeetingCommons](callContext)) } - + messageDocs += getMeetingsDoc def getMeetingsDoc = MessageDoc( process = "obp.getMeetings", @@ -8193,79 +5822,49 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetMeetings(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetMeetings(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value)) + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true))) ), exampleInboundMessage = ( - InBoundGetMeetings(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data=List( MeetingCommons(meetingId="string", - providerId="string", - purposeId="string", + InBoundGetMeetings(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( MeetingCommons(meetingId=meetingIdExample.value, + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, bankId=bankIdExample.value, - present= MeetingPresent(staffUserId="string", - customerUserId="string"), + present= MeetingPresent(staffUserId=staffUserIdExample.value, + customerUserId=customerUserIdExample.value), keys= MeetingKeys(sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string"), - when=new Date(), - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value), + when=toDate(whenExample), + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string"))))) + status=statusExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getMeetings + override def getMeetings(bankId: BankId, user: User, callContext: Option[CallContext]): OBPReturnType[Box[List[Meeting]]] = { - import com.openbankproject.commons.dto.{OutBoundGetMeetings => OutBound, InBoundGetMeetings => InBound} - val url = getUrl(callContext, "getMeetings") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, user) - val result: OBPReturnType[Box[List[MeetingCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetMeetings => InBound, OutBoundGetMeetings => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, user) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getMeetings"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[MeetingCommons]](callContext)) } - + messageDocs += getMeetingDoc def getMeetingDoc = MessageDoc( process = "obp.getMeeting", @@ -8274,80 +5873,50 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetMeeting(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetMeeting(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=BankId(bankIdExample.value), user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), - meetingId="string") + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), + meetingId=meetingIdExample.value) ), exampleInboundMessage = ( - InBoundGetMeeting(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), - data= MeetingCommons(meetingId="string", - providerId="string", - purposeId="string", + InBoundGetMeeting(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= MeetingCommons(meetingId=meetingIdExample.value, + providerId=providerIdExample.value, + purposeId=purposeIdExample.value, bankId=bankIdExample.value, - present= MeetingPresent(staffUserId="string", - customerUserId="string"), + present= MeetingPresent(staffUserId=staffUserIdExample.value, + customerUserId=customerUserIdExample.value), keys= MeetingKeys(sessionId=sessionIdExample.value, - customerToken="string", - staffToken="string"), - when=new Date(), - creator= ContactDetails(name="string", - phone="string", + customerToken=customerTokenExample.value, + staffToken=staffTokenExample.value), + when=toDate(whenExample), + creator= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - invitees=List( Invitee(contactDetails= ContactDetails(name="string", - phone="string", + invitees=List( Invitee(contactDetails= ContactDetails(name=nameExample.value, + phone=phoneExample.value, email=emailExample.value), - status="string")))) + status=statusExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getMeeting + override def getMeeting(bankId: BankId, user: User, meetingId: String, callContext: Option[CallContext]): OBPReturnType[Box[Meeting]] = { - import com.openbankproject.commons.dto.{OutBoundGetMeeting => OutBound, InBoundGetMeeting => InBound} - val url = getUrl(callContext, "getMeeting") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, user, meetingId) - val result: OBPReturnType[Box[MeetingCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetMeeting => InBound, OutBoundGetMeeting => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, user, meetingId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getMeeting"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[MeetingCommons](callContext)) } - + messageDocs += createOrUpdateKycCheckDoc def createOrUpdateKycCheckDoc = MessageDoc( process = "obp.createOrUpdateKycCheck", @@ -8356,75 +5925,42 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateKycCheck(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateKycCheck(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, - id="string", + id=idExample.value, customerNumber=customerNumberExample.value, - date=new Date(), - how="string", - staffUserId="string", + date=toDate(dateExample), + how=howExample.value, + staffUserId=staffUserIdExample.value, mStaffName="string", mSatisfied=true, - comments="string") + comments=commentsExample.value) ), exampleInboundMessage = ( - InBoundCreateOrUpdateKycCheck(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateKycCheck(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= KycCheckCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, idKycCheck="string", customerNumber=customerNumberExample.value, - date=new Date(), - how="string", - staffUserId="string", - staffName="string", - satisfied=true, - comments="string")) + date=toDate(dateExample), + how=howExample.value, + staffUserId=staffUserIdExample.value, + staffName=staffNameExample.value, + satisfied=satisfiedExample.value.toBoolean, + comments=commentsExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateKycCheck + override def createOrUpdateKycCheck(bankId: String, customerId: String, id: String, customerNumber: String, date: Date, how: String, staffUserId: String, mStaffName: String, mSatisfied: Boolean, comments: String, callContext: Option[CallContext]): OBPReturnType[Box[KycCheck]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycCheck => OutBound, InBoundCreateOrUpdateKycCheck => InBound} - val url = getUrl(callContext, "createOrUpdateKycCheck") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, customerId, id, customerNumber, date, how, staffUserId, mStaffName, mSatisfied, comments) - val result: OBPReturnType[Box[KycCheckCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycCheck => InBound, OutBoundCreateOrUpdateKycCheck => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, id, customerNumber, date, how, staffUserId, mStaffName, mSatisfied, comments) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateKycCheck"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[KycCheckCommons](callContext)) } - + messageDocs += createOrUpdateKycDocumentDoc def createOrUpdateKycDocumentDoc = MessageDoc( process = "obp.createOrUpdateKycDocument", @@ -8433,73 +5969,40 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateKycDocument(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateKycDocument(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, - id="string", + id=idExample.value, customerNumber=customerNumberExample.value, - `type`="string", - number="string", - issueDate=new Date(), - issuePlace="string", - expiryDate=new Date()) + `type`=typeExample.value, + number=numberExample.value, + issueDate=toDate(issueDateExample), + issuePlace=issuePlaceExample.value, + expiryDate=toDate(expiryDateExample)) ), exampleInboundMessage = ( - InBoundCreateOrUpdateKycDocument(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateKycDocument(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= KycDocumentCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, idKycDocument="string", customerNumber=customerNumberExample.value, - `type`="string", - number="string", - issueDate=new Date(), - issuePlace="string", - expiryDate=new Date())) + `type`=typeExample.value, + number=numberExample.value, + issueDate=toDate(issueDateExample), + issuePlace=issuePlaceExample.value, + expiryDate=toDate(expiryDateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateKycDocument + override def createOrUpdateKycDocument(bankId: String, customerId: String, id: String, customerNumber: String, `type`: String, number: String, issueDate: Date, issuePlace: String, expiryDate: Date, callContext: Option[CallContext]): OBPReturnType[Box[KycDocument]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycDocument => OutBound, InBoundCreateOrUpdateKycDocument => InBound} - val url = getUrl(callContext, "createOrUpdateKycDocument") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, customerId, id, customerNumber, `type`, number, issueDate, issuePlace, expiryDate) - val result: OBPReturnType[Box[KycDocument]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycDocument => InBound, OutBoundCreateOrUpdateKycDocument => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, id, customerNumber, `type`, number, issueDate, issuePlace, expiryDate) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateKycDocument"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[KycDocument](callContext)) } - + messageDocs += createOrUpdateKycMediaDoc def createOrUpdateKycMediaDoc = MessageDoc( process = "obp.createOrUpdateKycMedia", @@ -8508,73 +6011,40 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateKycMedia(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateKycMedia(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, - id="string", + id=idExample.value, customerNumber=customerNumberExample.value, - `type`="string", + `type`=typeExample.value, url=urlExample.value, - date=new Date(), - relatesToKycDocumentId="string", - relatesToKycCheckId="string") + date=toDate(dateExample), + relatesToKycDocumentId=relatesToKycDocumentIdExample.value, + relatesToKycCheckId=relatesToKycCheckIdExample.value) ), exampleInboundMessage = ( - InBoundCreateOrUpdateKycMedia(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateKycMedia(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= KycMediaCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, idKycMedia="string", customerNumber=customerNumberExample.value, - `type`="string", + `type`=typeExample.value, url=urlExample.value, - date=new Date(), - relatesToKycDocumentId="string", - relatesToKycCheckId="string")) + date=toDate(dateExample), + relatesToKycDocumentId=relatesToKycDocumentIdExample.value, + relatesToKycCheckId=relatesToKycCheckIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateKycMedia + override def createOrUpdateKycMedia(bankId: String, customerId: String, id: String, customerNumber: String, `type`: String, url: String, date: Date, relatesToKycDocumentId: String, relatesToKycCheckId: String, callContext: Option[CallContext]): OBPReturnType[Box[KycMedia]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycMedia => OutBound, InBoundCreateOrUpdateKycMedia => InBound} - val url = getUrl(callContext, "createOrUpdateKycMedia") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, customerId, id, customerNumber, `type`, url, date, relatesToKycDocumentId, relatesToKycCheckId) - val result: OBPReturnType[Box[KycMediaCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycMedia => InBound, OutBoundCreateOrUpdateKycMedia => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, id, customerNumber, `type`, url, date, relatesToKycDocumentId, relatesToKycCheckId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateKycMedia"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[KycMediaCommons](callContext)) } - + messageDocs += createOrUpdateKycStatusDoc def createOrUpdateKycStatusDoc = MessageDoc( process = "obp.createOrUpdateKycStatus", @@ -8583,65 +6053,32 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateOrUpdateKycStatus(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateOrUpdateKycStatus(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, bankId=bankIdExample.value, customerId=customerIdExample.value, customerNumber=customerNumberExample.value, - ok=true, - date=new Date()) + ok=okExample.value.toBoolean, + date=toDate(dateExample)) ), exampleInboundMessage = ( - InBoundCreateOrUpdateKycStatus(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateOrUpdateKycStatus(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= KycStatusCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, customerNumber=customerNumberExample.value, - ok=true, - date=new Date())) + ok=okExample.value.toBoolean, + date=toDate(dateExample))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createOrUpdateKycStatus + override def createOrUpdateKycStatus(bankId: String, customerId: String, customerNumber: String, ok: Boolean, date: Date, callContext: Option[CallContext]): OBPReturnType[Box[KycStatus]] = { - import com.openbankproject.commons.dto.{OutBoundCreateOrUpdateKycStatus => OutBound, InBoundCreateOrUpdateKycStatus => InBound} - val url = getUrl(callContext, "createOrUpdateKycStatus") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , bankId, customerId, customerNumber, ok, date) - val result: OBPReturnType[Box[KycStatusCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateKycStatus => InBound, OutBoundCreateOrUpdateKycStatus => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, customerId, customerNumber, ok, date) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateKycStatus"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[KycStatusCommons](callContext)) } - + messageDocs += getKycChecksDoc def getKycChecksDoc = MessageDoc( process = "obp.getKycChecks", @@ -8650,66 +6087,33 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetKycChecks(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetKycChecks(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetKycChecks(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetKycChecks(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( KycCheckCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, idKycCheck="string", customerNumber=customerNumberExample.value, - date=new Date(), - how="string", - staffUserId="string", - staffName="string", - satisfied=true, - comments="string"))) + date=toDate(dateExample), + how=howExample.value, + staffUserId=staffUserIdExample.value, + staffName=staffNameExample.value, + satisfied=satisfiedExample.value.toBoolean, + comments=commentsExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getKycChecks + override def getKycChecks(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycCheck]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycChecks => OutBound, InBoundGetKycChecks => InBound} - val url = getUrl(callContext, "getKycChecks") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[List[KycCheckCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetKycChecks => InBound, OutBoundGetKycChecks => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getKycChecks"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[KycCheckCommons]](callContext)) } - + messageDocs += getKycDocumentsDoc def getKycDocumentsDoc = MessageDoc( process = "obp.getKycDocuments", @@ -8718,65 +6122,32 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetKycDocuments(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetKycDocuments(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetKycDocuments(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetKycDocuments(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( KycDocumentCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, idKycDocument="string", customerNumber=customerNumberExample.value, - `type`="string", - number="string", - issueDate=new Date(), - issuePlace="string", - expiryDate=new Date()))) + `type`=typeExample.value, + number=numberExample.value, + issueDate=toDate(issueDateExample), + issuePlace=issuePlaceExample.value, + expiryDate=toDate(expiryDateExample)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getKycDocuments + override def getKycDocuments(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycDocument]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycDocuments => OutBound, InBoundGetKycDocuments => InBound} - val url = getUrl(callContext, "getKycDocuments") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[List[KycDocumentCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetKycDocuments => InBound, OutBoundGetKycDocuments => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getKycDocuments"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[KycDocumentCommons]](callContext)) } - + messageDocs += getKycMediasDoc def getKycMediasDoc = MessageDoc( process = "obp.getKycMedias", @@ -8785,65 +6156,32 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetKycMedias(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetKycMedias(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetKycMedias(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetKycMedias(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( KycMediaCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, idKycMedia="string", customerNumber=customerNumberExample.value, - `type`="string", + `type`=typeExample.value, url=urlExample.value, - date=new Date(), - relatesToKycDocumentId="string", - relatesToKycCheckId="string"))) + date=toDate(dateExample), + relatesToKycDocumentId=relatesToKycDocumentIdExample.value, + relatesToKycCheckId=relatesToKycCheckIdExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getKycMedias + override def getKycMedias(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycMedia]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycMedias => OutBound, InBoundGetKycMedias => InBound} - val url = getUrl(callContext, "getKycMedias") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[List[KycMediaCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetKycMedias => InBound, OutBoundGetKycMedias => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getKycMedias"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[KycMediaCommons]](callContext)) } - + messageDocs += getKycStatusesDoc def getKycStatusesDoc = MessageDoc( process = "obp.getKycStatuses", @@ -8852,61 +6190,28 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundGetKycStatuses(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundGetKycStatuses(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, customerId=customerIdExample.value) ), exampleInboundMessage = ( - InBoundGetKycStatuses(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundGetKycStatuses(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=List( KycStatusCommons(bankId=bankIdExample.value, customerId=customerIdExample.value, customerNumber=customerNumberExample.value, - ok=true, - date=new Date()))) + ok=okExample.value.toBoolean, + date=toDate(dateExample)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /getKycStatuses + override def getKycStatuses(customerId: String, callContext: Option[CallContext]): OBPReturnType[Box[List[KycStatus]]] = { - import com.openbankproject.commons.dto.{OutBoundGetKycStatuses => OutBound, InBoundGetKycStatuses => InBound} - val url = getUrl(callContext, "getKycStatuses") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , customerId) - val result: OBPReturnType[Box[List[KycStatusCommons]]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundGetKycStatuses => InBound, OutBoundGetKycStatuses => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "getKycStatuses"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[List[KycStatusCommons]](callContext)) } - + messageDocs += createMessageDoc def createMessageDoc = MessageDoc( process = "obp.createMessage", @@ -8915,70 +6220,40 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundCreateMessage(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundCreateMessage(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, user= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", - provider="string", - emailAddress=emailExample.value, - name=usernameExample.value), + provider=providerExample.value, + emailAddress=emailAddressExample.value, + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), bankId=BankId(bankIdExample.value), - message="string", - fromDepartment="string", - fromPerson="string") + message=messageExample.value, + fromDepartment=fromDepartmentExample.value, + fromPerson=fromPersonExample.value) ), exampleInboundMessage = ( - InBoundCreateMessage(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundCreateMessage(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data= CustomerMessageCommons(messageId="string", - date=new Date(), - message="string", - fromDepartment="string", - fromPerson="string")) + date=toDate(dateExample), + message=messageExample.value, + fromDepartment=fromDepartmentExample.value, + fromPerson=fromPersonExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /createMessage + override def createMessage(user: User, bankId: BankId, message: String, fromDepartment: String, fromPerson: String, callContext: Option[CallContext]): OBPReturnType[Box[CustomerMessage]] = { - import com.openbankproject.commons.dto.{OutBoundCreateMessage => OutBound, InBoundCreateMessage => InBound} - val url = getUrl(callContext, "createMessage") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , user, bankId, message, fromDepartment, fromPerson) - val result: OBPReturnType[Box[CustomerMessageCommons]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result + import com.openbankproject.commons.dto.{InBoundCreateMessage => InBound, OutBoundCreateMessage => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, user, bankId, message, fromDepartment, fromPerson) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createMessage"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[CustomerMessageCommons](callContext)) } - + messageDocs += makeHistoricalPaymentDoc def makeHistoricalPaymentDoc = MessageDoc( process = "obp.makeHistoricalPayment", @@ -8987,94 +6262,137 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable outboundTopic = None, inboundTopic = None, exampleOutboundMessage = ( - OutBoundMakeHistoricalPayment(outboundAdapterCallContext= OutboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - consumerId=Some(consumerIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value))), - outboundAdapterAuthInfo=Some( OutboundAdapterAuthInfo(userId=Some(userIdExample.value), - username=Some(usernameExample.value), - linkedCustomers=Some(List( BasicLinkedCustomer(customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value))), - userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, - value=valueExample.value))), - authViews=Some(List( AuthView(view= ViewBasic(id=viewIdExample.value, - name=viewNameExample.value, - description=viewDescriptionExample.value), - account= AccountBasic(id=accountIdExample.value, - accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, - address=accountRoutingAddressExample.value)), - customerOwners=List( InternalBasicCustomer(bankId=bankIdExample.value, - customerId=customerIdExample.value, - customerNumber=customerNumberExample.value, - legalName=legalNameExample.value, - dateOfBirth=parseDate(dateOfBirthExample.value).getOrElse(sys.error("dateOfBirthExample.value is not validate date format.")))), - userOwners=List( InternalBasicUser(userId=userIdExample.value, - emailAddress=emailExample.value, - name=usernameExample.value))))))))), + OutBoundMakeHistoricalPayment(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), toAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, - balance=BigDecimal(balanceAmountExample.value), + balance=BigDecimal(balanceExample.value), currency=currencyExample.value, name=bankAccountNameExample.value, label=labelExample.value, number=bankAccountNumberExample.value, bankId=BankId(bankIdExample.value), - lastUpdate=parseDate(bankAccountLastUpdateExample.value).getOrElse(sys.error("bankAccountLastUpdateExample.value is not validate date format.")), + lastUpdate=toDate(bankAccountLastUpdateExample), branchId=branchIdExample.value, accountRoutings=List( AccountRouting(scheme=accountRoutingSchemeExample.value, address=accountRoutingAddressExample.value)), accountRules=List( AccountRule(scheme=accountRuleSchemeExample.value, value=accountRuleValueExample.value)), - accountHolder=bankAccountAccountHolderExample.value), - posted=new Date(), - completed=new Date(), - amount=BigDecimal("123.321"), + accountHolder=bankAccountAccountHolderExample.value, + attributes=Some(List( Attribute(name=attributeNameExample.value, + `type`=attributeTypeExample.value, + value=attributeValueExample.value)))), + posted=toDate(postedExample), + completed=toDate(completedExample), + amount=BigDecimal(amountExample.value), currency=currencyExample.value, - description="string", + description=descriptionExample.value, transactionRequestType=transactionRequestTypeExample.value, - chargePolicy="string") + chargePolicy=chargePolicyExample.value) ), exampleInboundMessage = ( - InBoundMakeHistoricalPayment(inboundAdapterCallContext= InboundAdapterCallContext(correlationId=correlationIdExample.value, - sessionId=Some(sessionIdExample.value), - generalContext=Some(List( BasicGeneralContext(key=keyExample.value, - value=valueExample.value)))), - status= Status(errorCode=statusErrorCodeExample.value, - backendMessages=List( InboundStatusMessage(source=sourceExample.value, - status=inboundStatusMessageStatusExample.value, - errorCode=inboundStatusMessageErrorCodeExample.value, - text=inboundStatusMessageTextExample.value))), + InBoundMakeHistoricalPayment(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, data=TransactionId(transactionIdExample.value)) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - // url example: /makeHistoricalPayment - override def makeHistoricalPayment(fromAccount: BankAccount, toAccount: BankAccount, posted: Date, completed: Date, amount: BigDecimal, currency: String, description: String, transactionRequestType: String, chargePolicy: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionId]] = { - import com.openbankproject.commons.dto.{OutBoundMakeHistoricalPayment => OutBound, InBoundMakeHistoricalPayment => InBound} - val url = getUrl(callContext, "makeHistoricalPayment") - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull , fromAccount, toAccount, posted, completed, amount, currency, description, transactionRequestType, chargePolicy) - val result: OBPReturnType[Box[TransactionId]] = sendRequest[InBound](url, HttpMethods.POST, req, callContext).map(convertToTuple(callContext)) - result - } - //---------------- dynamic end ---------------------please don't modify this line + override def makeHistoricalPayment(fromAccount: BankAccount, toAccount: BankAccount, posted: Date, completed: Date, amount: BigDecimal, currency: String, description: String, transactionRequestType: String, chargePolicy: String, callContext: Option[CallContext]): OBPReturnType[Box[TransactionId]] = { + import com.openbankproject.commons.dto.{InBoundMakeHistoricalPayment => InBound, OutBoundMakeHistoricalPayment => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, fromAccount, toAccount, posted, completed, amount, currency, description, transactionRequestType, chargePolicy) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "makeHistoricalPayment"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[TransactionId](callContext)) + } + + messageDocs += createDirectDebitDoc + def createDirectDebitDoc = MessageDoc( + process = "obp.createDirectDebit", + messageFormat = messageFormat, + description = "Create Direct Debit", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateDirectDebit(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=bankIdExample.value, + accountId=accountIdExample.value, + customerId=customerIdExample.value, + userId=userIdExample.value, + counterpartyId=counterpartyIdExample.value, + dateSigned=toDate(dateSignedExample), + dateStarts=toDate(dateStartsExample), + dateExpires=Some(toDate(dateExpiresExample))) + ), + exampleInboundMessage = ( + InBoundCreateDirectDebit(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= DirectDebitTraitCommons(directDebitId=directDebitIdExample.value, + bankId=bankIdExample.value, + accountId=accountIdExample.value, + customerId=customerIdExample.value, + userId=userIdExample.value, + counterpartyId=counterpartyIdExample.value, + dateSigned=toDate(dateSignedExample), + dateCancelled=toDate(dateCancelledExample), + dateStarts=toDate(dateStartsExample), + dateExpires=toDate(dateExpiresExample), + active=activeExample.value.toBoolean)) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createDirectDebit(bankId: String, accountId: String, customerId: String, userId: String, counterpartyId: String, dateSigned: Date, dateStarts: Date, dateExpires: Option[Date], callContext: Option[CallContext]): OBPReturnType[Box[DirectDebitTrait]] = { + import com.openbankproject.commons.dto.{InBoundCreateDirectDebit => InBound, OutBoundCreateDirectDebit => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, customerId, userId, counterpartyId, dateSigned, dateStarts, dateExpires) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createDirectDebit"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[DirectDebitTraitCommons](callContext)) + } + + messageDocs += deleteCustomerAttributeDoc + def deleteCustomerAttributeDoc = MessageDoc( + process = "obp.deleteCustomerAttribute", + messageFormat = messageFormat, + description = "Delete Customer Attribute", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundDeleteCustomerAttribute(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + customerAttributeId=customerAttributeIdExample.value) + ), + exampleInboundMessage = ( + InBoundDeleteCustomerAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=true) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def deleteCustomerAttribute(customerAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { + import com.openbankproject.commons.dto.{InBoundDeleteCustomerAttribute => InBound, OutBoundDeleteCustomerAttribute => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, customerAttributeId) + val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "deleteCustomerAttribute"), HttpMethods.POST, req, callContext) + response.map(convertToTuple[Boolean](callContext)) + } + +// ---------- created on 2021-08-19T16:37:18Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala index 366d94128..cab49da0a 100644 --- a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala @@ -76,7 +76,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { val connectorName = "stored_procedure_vDec2019" //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2020-12-14T15:30:08Z +// ---------- created on 2021-08-19T16:41:22Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -692,7 +692,9 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { azp=Some("string"), email=Some(emailExample.value), emailVerified=Some(emailVerifiedExample.value), - name=Some(userNameExample.value))) + name=Some(userNameExample.value), + userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, + value=valueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -726,7 +728,9 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { azp=Some("string"), email=Some(emailExample.value), emailVerified=Some(emailVerifiedExample.value), - name=Some(userNameExample.value))) + name=Some(userNameExample.value), + userAuthContext=Some(List( BasicUserAuthContext(key=keyExample.value, + value=valueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -1498,7 +1502,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value)) + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true))) ), exampleInboundMessage = ( InBoundGetPhysicalCardsForUser(status=MessageDocsSwaggerDefinitions.inboundStatus, @@ -1670,7 +1677,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), limit=limitExample.value.toInt, offset=offsetExample.value.toInt, fromDate=fromDateExample.value, @@ -1986,7 +1996,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, @@ -2127,7 +2140,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, @@ -2300,7 +2316,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, balance=BigDecimal(balanceExample.value), @@ -3087,7 +3106,20 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { isAccessible=Some(isAccessibleExample.value.toBoolean), locatedAt=Some(locatedAtExample.value), moreInfo=Some(moreInfoExample.value), - hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean))) + hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), + supportedLanguages=Some(supportedLanguagesExample.value.split("[,;]").toList), + services=Some(listExample.value.split("[,;]").toList), + accessibilityFeatures=Some(accessibilityFeaturesExample.value.split("[,;]").toList), + supportedCurrencies=Some(supportedCurrenciesExample.value.split("[,;]").toList), + notes=Some(listExample.value.split("[,;]").toList), + locationCategories=Some(listExample.value.split("[,;]").toList), + minimumWithdrawal=Some("string"), + branchIdentification=Some("string"), + siteIdentification=Some(siteIdentification.value), + siteName=Some("string"), + cashWithdrawalNationalFee=Some(cashWithdrawalNationalFeeExample.value), + cashWithdrawalInternationalFee=Some(cashWithdrawalInternationalFeeExample.value), + balanceInquiryFee=Some(balanceInquiryFeeExample.value))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -3153,7 +3185,20 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { isAccessible=Some(isAccessibleExample.value.toBoolean), locatedAt=Some(locatedAtExample.value), moreInfo=Some(moreInfoExample.value), - hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean)))) + hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), + supportedLanguages=Some(supportedLanguagesExample.value.split("[,;]").toList), + services=Some(listExample.value.split("[,;]").toList), + accessibilityFeatures=Some(accessibilityFeaturesExample.value.split("[,;]").toList), + supportedCurrencies=Some(supportedCurrenciesExample.value.split("[,;]").toList), + notes=Some(listExample.value.split("[,;]").toList), + locationCategories=Some(listExample.value.split("[,;]").toList), + minimumWithdrawal=Some("string"), + branchIdentification=Some("string"), + siteIdentification=Some(siteIdentification.value), + siteName=Some("string"), + cashWithdrawalNationalFee=Some(cashWithdrawalNationalFeeExample.value), + cashWithdrawalInternationalFee=Some(cashWithdrawalInternationalFeeExample.value), + balanceInquiryFee=Some(balanceInquiryFeeExample.value)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -3211,7 +3256,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, balance=BigDecimal(balanceExample.value), @@ -3327,7 +3375,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, balance=BigDecimal(balanceExample.value), @@ -3418,7 +3469,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), viewId=ViewId(viewIdExample.value), fromAccount= BankAccountCommons(accountId=AccountId(accountIdExample.value), accountType=accountTypeExample.value, @@ -4733,7 +4787,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { productAttributeId=productAttributeIdExample.value, name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value)) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -4764,7 +4819,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { productAttributeId=productAttributeIdExample.value, name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value)) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -4796,7 +4852,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { productAttributeId=productAttributeIdExample.value, name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -5024,7 +5081,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { productAttributeId=productAttributeIdExample.value, name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))) ), exampleInboundMessage = ( InBoundCreateAccountAttributes(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -5651,7 +5709,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { productAttributeId=productAttributeIdExample.value, name=nameExample.value, attributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value))))) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -5678,13 +5737,19 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), customerUser= UserCommons(userPrimaryKey=UserPrimaryKey(123), userId=userIdExample.value, idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), providerId=providerIdExample.value, purposeId=purposeIdExample.value, when=toDate(whenExample), @@ -5745,7 +5810,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value)) + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true))) ), exampleInboundMessage = ( InBoundGetMeetings(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -5793,7 +5861,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), meetingId=meetingIdExample.value) ), exampleInboundMessage = ( @@ -6136,7 +6207,10 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { idGivenByProvider="string", provider=providerExample.value, emailAddress=emailAddressExample.value, - name=userNameExample.value), + name=userNameExample.value, + createdByConsentId=Some("string"), + createdByUserInvitationId=Some("string"), + isDeleted=Some(true)), bankId=BankId(bankIdExample.value), message=messageExample.value, fromDepartment=fromDepartmentExample.value, @@ -6298,8 +6372,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2020-12-14T15:30:08Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2021-08-19T16:41:22Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data index 58f4d39e087162721117c1654020381449c46c6f..4e0e332ecef5882e76b19e0f6e7ddd6e3c0c4739 100644 GIT binary patch delta 12901 zcmbVT3wTu3wa(6KCNs%A@|ZjzCLx3*B!mzG2n0wn;SmzZUlgtb=6G*UE zpi~=Q5LoIK1chSNmMTHiRO=&(Z(9wv(p&Kn>SwE1-^FUFaM#}ZoRgCf_1^3E0drpa z?6dY-|N7UzwqJf4_4dcn-H&CYZFaVL+|H0x;dR?LO0Jgb^-k~N_O|s>AQYCgfo^Xg ziF;m8uv#`qA^S#WV1raEZI)W?C3^-Ew^>{P2_MDtt*w%GgA@#f#ScGaFA0SuD=$&+ ztndc6us5WB&lUDmws@sHbYqyA-4oV@TAjlwr5oecqtt4OP2C zVX@jvp)egDRyw^cp)kGtD+o?9s)3zv2(synb}RUl zc6n}xCm6yjR(Ze*m&@1g4b`=}VGmhH65tE`Qx={A!SLenj1A!Y=nD8aJPnS7$3y=M zkz>*7Y)0~9Y|d;XI~zj^_?>}}M+!o9#CWp_PiqVSuSM7*+5BK%#1e>#Tn!bGY2l^C z&=`3`UYt|RLYbTqpLGO$?sgZOszE)1_alqN!nOwj_>uEEuENy>Yt+gy<~C=GAp9i09uNBCpAW}_+mm(|$ZsAx`bcl?@Pl(80bI6mqz0Y| z78+G3sqCb8jwPw&B9N*KI43RJdpZVgu-WlNf3WQ#G(u0(>7gL8fcHj&-d+-9U(!V% zSWOz>Q(FwYedA(Xw6l#x61Aq142#9ZO|Kdr%DW0^-%Jv1P){{d>oOcQZWbwsw1#{Y z@WtV3h^R`3p6k=Wu{#^qrpzH-^zd3zd14@CDZ$B2x+@RN^RI>%)28CgE~a%xaLe5R zmW)n$?w7u7fQuPd>bkZ>hJ}Si(L)HxjJ|+CtLUr>>u}2*$QR3^qQnC_R!(N0g#|)PZe!DJ4y$0_Uj)UUKCc1kriG`!L#mHm#?8sw=q1$UnB<#;C z#}^$~xd1ZLj8K%HKpx?abIqEMVBz@3<{a)o2dJ$eMiyEAY zn*^bIS`G^`eMBg1I%G}CTOpk|?sXsPp1QUaSg&I#yaO#dq7+6z~nzG30mp`LW`$>&(s%#SJf{0naK(EG` z^x4uzOg#b`H!UV9v9{14i-K=DM?*trJefzAtRZnUxf8A^fk{_yWxuu zO5tZWHF6YIV$+z4v}fdXgl9f>!`^Ax@Y1X}429FP0yyD3+G8h?mm|JdgF6fItm+!r zeQj+>>l$xQBZYB}fW!!%coS@!?IvFXNzU2Em}`|3a(Y^Y-wV7op+9m?7U--F`ZQk@ z>GFg+HOCQKJ$}uhB`Eowc4xqCZEWqS*WP?jbst3Io7eeD@)dEPdVLg{B&d^>QiQRm&_9i1yNA18QHaZx7+RuAatvz zqx_7L!M<4&A!be-qGa-%Zpgll14g>KdJ0|`{em~zeQt?^hW)-`x-%%;9;RI{gC+c| zyb7xPSsZ-7tFRzuvaHS0W}j;ev{o*_;K@4pDr~n;$JMHMvViU$N21|ldlE;+6H06~ zO@?iA7s*F&Jv$%H9Lk6OeWn=IwP@3Fq@B|nv+00DrqV|;NU4D_R5|KMRpuy-tBOJa z`I8PSm7vedW9mq4HuSf|BP1<=PqK>GZ~ayLa$}DGnUV6?U@Nu|FjASN)^{2J}_c+C|Wm|F}hhgz( zZQkPV6Om?MJc0IXBDT0VsSU$$nH2CednDM=p9pOyQzu189oh(s@L--8bj*lgyVlzy zoLl`s(i7q$ob4=e2_T~HuOKTep|A*#CJs6f+Y6{;F^Q(tS0P1M*APXzdYxC1^Wm7E zXUbnQVdWeZbfCOf_hVp;^mk|mLA1?*-790!9tT!7%cC-*D)GP*lVvb7$}Wim5jz~; zQ38|v32?d~9s0diFn1>92)jkA{7MZ{ElSgP3mNzSg6I;`!AMOu^u(Lt#jg@@!CyV% zhZU=zf{5ho5{8$&T@OgWmCN0O2gi`ShJFi%^4fKOl?xM8QnlQvxU_-GvX z)c&WT$r4E~EhGjgld90qcSzMDY_aUvt*$N`n%p|qoJX9HAs z7r^Yvde}~r<#n#RzYCqpv#SVa?73 zNUhn_O>kex##fb*;wJd+t|WN1U9A`py*F=W6r2?rjxC+Y(s6;t!RK4j(2tBAZ{Z3Y z{xSmw%mx;qXyTmCXUPTlu(J)XFWZ`nzfa+(_WU~rd=I5V)06RVZXF`&iGi*2!pTka z)M)Y&sihT32uPn8iGjX0mFR54Rh}V^Q%0*6kP@*JT_t@9wtJjp1Yg?9MIVs0w|5Hw?}TGqw>n zcdbCXzuxsAi;Zh zMdOb4?(RqA@eB5J$-gipVAtL%`G}?d5KM>_psmA{6l{l0x6V3o4qj2*HFp2a&~*Du zwB>=@eGEAY>0`CTVo)obgS2)LDdAMOFE2Vy#t<1jD=5pnY-RfBS=qhCh+}DAEHTn; zDMV)xw%2^$DMuo`rIr*z_Z_kD-abaKS?I*>e-1}GwZ9)4HnFJJWpZdAQR-D4l2V4l zMons9i@$o_3Z@Lon8t5bQ2J;0fX{560nrEbaT|n&9DMHHbpT zA5DbBo;p0wij;}R=i)E6TDKnmHAd5%hguN*k3Pg!bk2zl5#dp@;QmJ+kl)5&I$<)0 zsd%{5By!Eutf(N3^!P+l3@x9i0;O1btZfJN1$f|CF6K_N%tu7{*D$q{i9Knb=AoPx z4W1{ga(V&#lPo86J$Vf0LAzb}`G=lqgaz^0P`=41e=JgUdT|knj#o=)RhNSDYjVK& zbc_)hiLTY-lCWLEscqHMb2-W9X5y%;BnzelbAHBf_ZO=&n0}UKAFgB%zF~*N>9`4A z=(EU-&A_!yc&oKk6hBX#v_eK(1}twI#il&?CBKl(`qr~I;#W#1Popq=c3|?4vGxD6 zbn?u~3~0J94(^^}fs9Tp7%0<6z}KHdGc4#^$Dg|&0c6$l3#n^5;ZlW(CG%K5Jx2J- z;K3Ie(w}?rY5aTAT}-W|9C^mV^)K({=(7qfH5QG^Du>5kVLai*SKcMENfL$J+xPo} zED5o7zy9@p`I;VfJeLbmTg?Fdukm@zhqj69K>x;c6Y6A{hCK zIXx98TzJKC3*f{rKXN8NRipVtrgpQ4mW-Z6f zXlY)7&xyzFGHm)iCu9&=yrKN+r2BrOOr2NJ2R;ga$fE((C*v0BjxVzGzSBnRR zHy;*`W!WoUXb_t3jH0`mNmh)>?Q^xWP8{5FGF546u-Z5((uFCPwKr^LlT5N?xs&C@ zadd4CNtjtF1zJ7c`2kKzp!RXIsl7Gi!Eq(*WQ9=1#(5_sOC7F_PV5*n zS|MHxJy)ja;@sk%f+dAaldzarD+~oQU!Y(~^uve|y01 zW3<8zZjC z2b8I5PQCZvX*z@W5;o%$y?Qg*nvfF;8$03$s76<&Z?!0vv&%-{dPpqt+sz2uybsUL zSmRwX0jq1~5^gi>Ihmx>%eEBnj8*2qlyVJ8i^X-orhX-Aoa`x!O?w~KEr1`BG=c{# z_0Z#+NCN4AC7)+=+3&VJsnD}KidQEJr?x_9fbnXE9Mxw}YXjudzuLti+K~E8OR-efT-4dHUC=%cal&ZT| zPL#yhIN%*Im{~TPrpJ)~LUELpFZ#lf6=a2xE89uLHjY8|UH^Fj)5JzAMUpgR&jggYl8W^z~fy6bPW2D$eq)tWUuGBdl zLm7<%+b*W!oc3M3L)4CWx2+=YVzNheb5ZsvS*7@y#<%Z%;4OL~g3QJnXGD@mQHK5^ zlB~jZKCRV}71+AX0>^Pn3R;0HudL1%W)=9Qz)Kz7XT^vX%W9H2Az#s6T+uaz)peqk z4qKmOelIrV_r=1Y7h~c6d6_hGB{4$xFHO`EN1}`uhl&SKOT}39 zK`)VOCTh?oT0FJK+Hw-S{q5nVHtR1C+0Y^^#1q|JbbjQH$8>?i72jg@y#Mu6v|p$@ANc+ zb$c}{KSqzdr%85l9onnHfH_&rFPqGPrygZ*aIZzz1$VO4a=kmxG z5@d`^#&_0t!%A4$0DzS-=g=tFnw9B@qC}WzXaoLb2Z|U?8%Z4WNpF|-_wC9s!+$HXzFOMgau;jlm z9;=DaX_l*XQu2)4Ui*q?4j+Nu^yp|F^s%ZZ{DZnFu6tzjJ` zCQOVe5T}aj?G@rzBf>_|*{bab#-QfMI{knYmin_us$Tx04(uS8(bfWjN?-4m0^%o^ zVOk7Y481G1l6UGg5wNQ%8@lf_(ZY#jn&R|_&Xy+fTZ9m+ekv4yHXc4NH;u5CA}ST3 z(5yy+SQ%#!-pafgPc5xJ?tsTtdV!bFTpWylr;R%Ct3 zwzC9y>i08x&(9!-!s$#u$%hrklTFHoIPon zi}dFeWXqr>ZWSNO_d<2d;CmHp3TzynOa27Qk0KNJJSkbo8<$rNOO7=#36uurkr|lr z9+*ci@%KH>aN8;vxM*JK;fkGdcWDSjFD8%BTNaWX7{KNlvK0rpv4#vp^UOPo`fG8Q zAucjUiyy#j4x-V*u5{CK+(pz@DIQ{N1*9jvf2_qsfZ5l29!X1|jc*C#DY_3K>BG)K zkj+n@tkbSPBdiv-PYg3R*JY97TZM`(oRL===-mR(xI=aI?r$J=ghBf5GQxHvh`gmL zm4Xh&j2dzCuOp?I<~5>}VV(4^K43jZ^JtaC z<3e)i*Kl}b?TOIxMmFzcY3Xqc?0T}E_OB#snTlGxiZpVk5yD==>*K*u6op-)gqV^^ zVrxlPFK#XE38%g5NQLk(wqc_MR~9!K^JQF+*v_sJZYvMop{ibdlUn85xU9N5JA? zHG{H?4&i(_C=ZEpRH13pJfg_ZhcSm@;!Z;=U9*uqfey=SZMyhs;aS6yzaR}Nyg)_q zBDU|4?HP@uKe<{KUr~#0A=k>`{!|OuFQ?-;ICW%l@7`7n3?8ko(k)(6i?5c2-ElPB zNA?bisSNDq zp6XmEzNL}Q(UW!b;2P4IoPhsZg`&mDJLxei)&OZKGY^&N8fju9={3sRmhh$#wko~1 z>sC?zVencts_9^`aZIvkE^$GXBB7eV+C3&UZ6QxbBsd<4nSmLbd7+G$EH}k!cTzIi en#p(2uG)+i`5KWfcFJRN zZmwxgp}F`)Q_=WhW07^I|6ebg9enK#^4JeEwq1>>&QI z-96NpKh^e+)@!Ub-gfl23ccyr9Xg@jDa86gQ1>02JGMwhATb# zI=0Qla|uCp)t>zwQKjAvIrv%U5USOJ7O$zZ66TF`aGq%_ji2qX*nyv2=Nj_o7`xfM zb+>zycg~xI86lClQS%*?P{u4cis{`{IBXv}HE=k|l3CeN4?^u30 z@B2?jk8-nvizJXP_(3G5pVQ)~a(CRRa>iS2Qlk~!?B)NJZu4f*yFI`M4FM4}*#uFT zqYYviTLLQqk8KQFx7HnZ2m6DWf_Fhm-5XLwIgXsHvFU{eWU&E`a$(J@h4 z3c;kc<1wgHA2)M}vx9?!3syf2KrcfEmQIVn`S}{xV&Ro?th^P3{tP9RN9o^C z3UPvTeE(@UK8$d~#Hf_aR+iX$Ts-%%^YC9;XpM}0oaF!TM$|79p9R6#ut|m0(c!W^ zq+0|7aC1zmV$idgv9w?cgpp1S{+^;XBoidtsUV;IFSIS~D)xt&hEk|6_+z^`cUaD@ z3aLwt+XafF7I*JQj!W3hJ>r8n{9#@k{`$96xFg#GgL@3*7*FYuC7tpDe!MdnYumeH z;TWy#vJwpGxs=^i-7_0d^Bo6Ag(vpAQAiu`Ry5r6DDKhxXx4`2CjH9fpwAM7*%ONU4b)(u5!bNnLf7O@QDh?{r&YU=Vbo~$s3rJ z6v8{ok{VI9O?Xg4pN1|r4c8>k zG0&KgXDpEvyNmIoityWza2$2XO`Tq3EH*MAiU{Au=cA{>A#4imgxR6)(kblShZz+V zzmWYel%6;?P%*=ETq-_}mQ+I10F{>vAvQ6qIRxRN?5H{)!i5{>kJCZ9)h)wW{p7#H zIsDJ~1eSU6W;EtZXxr@J^^%mc_{U3WioAQ@4WTOoAXvf%op85}L{Tp5FsCw>ZWtgy z{Bf`vyG|aYJo#q!hP%|{4Q;S&;zT^2IYbsjXNU2pzEc)}8IKtQ@xqiNoEzh9Bp=97CZ%pLi*YC~gU;@Yyt#RdQk{9bTT^ zla0Goz!B;`Bbt2~h9Q`J#vAW!)U)D`^Wv-sa;zYUQ=}^^A7+}??4&SCFXB?VRU|ZB z^wBJwTzry#e~YyhC8lj|DI&CTv0-Z59lRVDqmrUsE^?=l+J>Ff??ow5xqb!mZr9(ITymNTfQcz&jT-RYs8>L{V zECV8|7H~&*-!_B=rf*Ajbbb#P7c=y3^HnvP9bCtni}DJm&%h{z!UC~8|Yl`NCH z03!-yV%$#(NvPk>K*(7Xi9c_@rTFK`j%{2KQp90l8aWu ztMhj~QE+KpgL3ML{d!!o!iCS%?>W+P0CNDQ5$oT4nRDX7n+HT{Z2kLNa@I<1)zy=W z!TCM8B4)>M1GunnxZ*WWoZWVGo$2iY;Who9I8@i{k&nh<2UaLT?6PP7!Bp}2;CYr) zU+XQm?+_~Q3UA=zx_+$P(K-_&e6(#LVqtWQKwHfrkz~R#1z(R?_b3|IWX9stLkfSe z9@3E-d>N9~i~u*CR1$Yv48YI2`eLGGu3%QD)+F9C-|Gtkb-kypT&u(OW=E~NEI^R4l2-5L4l(@lRt`$z<(VvK>=j{NeBb_DXD4{uAO?1aj&I3-nqA4Di2NuJaxYthp*}WO_7}!f3OH}5I(MLy2u}v zK4R7(sWk*Yf4q^;%>OA0pH5)poTS%@@l#G!X$bJ7AGbnQU7w$G<|L9?9S7lgc3LZNceAvChAm(55RL*J*?J$|7;LbX^AXP zJfa5kp;HjUbtbs?c{=I{GRc>`!OTt~elS$@a5|-hKpgn8NIAwtn&SzFq{lECse;Q; zV&NksqF}9bLaj`s+S{d`bS6bD<7}h>{$Jt4rKC$dL8d^ zE1pwOU??h;n?RBu6!V5K(+k)>w-@RBfm@EQ37_fQEhvgb~VrUj@NhWy{r7k$uPq-HCL| z*zSIdK(CaoB{~{h}Q#8$`e>3ib+?#j&s9{og?spPD=yJI5W-kVi`PV zmoloIK;0HE>Xro|B=xVdY;dEIHDKrA7XO%>nBj)3(%~mN6!J>eS{x6{Y1%Sa%IAK+ z4Cb?x+~v^VDM4d0cl1JBdL@v@9BC*KAV2L@E?q{t*`II&+^4|{-?-zo1aAcr#i+cO z%kKDw7+SLvvM7B8q_l*zSRT8htGvL4&XmW&1St?W}REkQ^_W5{p?-r*Vv<;zFRw!$+#%>(9a-_5>NN#Ol zCP5Fz>Bo6dmSY4yeD@^x^Tr9vAR* Date: Fri, 20 Aug 2021 12:56:36 +0200 Subject: [PATCH 049/293] docfix/Add relase notes regarding updated implementations of Akka, Rest and Stored Procedure connectors --- release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release_notes.md b/release_notes.md index 0b00bcd2a..4131790b9 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action +20/08/2021 2ad1a3b0 Updated implementations of Akka, Rest and Stored Procedure connectors via the builder. 18/08/2021 83c3b4fa Added props: webui_favicon_link_url, default is /favicon.ico 18/08/2021 5924c820 Added props: webui_api_documentation_bottom_url, default is https://github.com/OpenBankProject/OBP-API/wiki Added props: webui_privacy_policy_url, default is https://openbankproject.com/privacy-policy From 2567c79a35416df752bf0ed042c6c722517f698a Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 20 Aug 2021 17:09:11 +0200 Subject: [PATCH 050/293] feature/tidying up password validation --- obp-api/src/main/scala/code/api/directlogin.scala | 2 +- obp-api/src/main/scala/code/api/util/APIUtil.scala | 9 +++++---- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 +- .../src/main/scala/code/api/v2_0_0/APIMethods200.scala | 2 +- .../src/main/scala/code/model/dataAccess/AuthUser.scala | 4 ++-- obp-api/src/main/scala/code/sandbox/CreateOBPUsers.scala | 5 ++++- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/directlogin.scala b/obp-api/src/main/scala/code/api/directlogin.scala index 737496148..3dc004a94 100644 --- a/obp-api/src/main/scala/code/api/directlogin.scala +++ b/obp-api/src/main/scala/code/api/directlogin.scala @@ -202,7 +202,7 @@ object DirectLogin extends RestHelper with MdcLoggable { case "username" => checkUsernameString(parameterValue) case "password" => - checkMediumPassword(parameterValue) + validatePasswordOnUsage(parameterValue) case "consumer_key" => checkMediumAlphaNumeric(parameterValue) case "token" => diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 3e7d2c07b..a711afc64 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -643,10 +643,10 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ /** enforce the password. * The rules : - * 1) length is >16 characters without validations + * 1) length is >16 characters without validations but max length <= 512 * 2) or Min 10 characters with mixed numbers + letters + upper+lower case + at least one special character. * */ - def isValidStrongPassword(password: String): Boolean = { + def validatePasswordOnCreation(password: String): Boolean = { /** * (?=.*\d) //should contain at least one digit * (?=.*[a-z]) //should contain at least one lower case @@ -657,7 +657,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val regex = """^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~])([A-Za-z0-9!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~]{10,16})$""".r password match { - case password if (password.length > 16) => true + case password if(validatePasswordOnUsage(password) ==SILENCE_IS_GOLDEN) => true + case password if(password.length > 16 && password.length <= 512) => true case regex(password) => true case _ => false } @@ -693,7 +694,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ /** only A-Z, a-z, 0-9, all allowed characters for password and max length <= 512 */ /** also support space now */ - def checkMediumPassword(value:String): String ={ + def validatePasswordOnUsage(value:String): String ={ val valueLength = value.length val regex = """^([A-Za-z0-9!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~ ]+)$""".r value match { diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 2fd57dfd3..705b03ae9 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -376,7 +376,7 @@ object ErrorMessages { val EntitlementIsSystemRole = "OBP-30206: This entitlement is a System Role. Please set bank_id to empty string." - val InvalidStrongPasswordFormat = "OBP-30207: Invalid Password Format. Your password should EITHER be at least 10 characters long and contain mixed numbers and both upper and lower case letters and at least one special character, OR be longer than 16 characters." + val InvalidStrongPasswordFormat = "OBP-30207: Invalid Password Format. Your password should EITHER be at least 10 characters long and contain mixed numbers and both upper and lower case letters and at least one special character, OR the length should be > 16 and <= 512." val AccountIdAlreadyExists = "OBP-30208: Account_ID already exists at the Bank." diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index 3f3f6f2fa..772aac304 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1477,7 +1477,7 @@ trait APIMethods200 { cc => for { postedData <- tryo {json.extract[CreateUserJson]} ?~! ErrorMessages.InvalidJsonFormat - _ <- tryo(assert(isValidStrongPassword(postedData.password))) ?~! ErrorMessages.InvalidStrongPasswordFormat + _ <- tryo(assert(validatePasswordOnCreation(postedData.password))) ?~! ErrorMessages.InvalidStrongPasswordFormat } yield { if (AuthUser.find(By(AuthUser.username, postedData.username)).isEmpty) { val userCreated = AuthUser.create diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index c223ff8c2..77abe0fae 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -28,7 +28,7 @@ package code.model.dataAccess import code.UserRefreshes.UserRefreshes import code.accountholders.AccountHolders -import code.api.util.APIUtil.{hasAnOAuthHeader, isValidStrongPassword, logger, _} +import code.api.util.APIUtil.{hasAnOAuthHeader, validatePasswordOnCreation, logger, _} import code.api.util.ErrorMessages._ import code.api.util._ import code.api.v4_0_0.dynamic.DynamicEndpointHelper @@ -268,7 +268,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with MdcLoggable { invalidMsg = Helper.i18n("please.enter.your.password") S.error("authuser_password_repeat", Text(Helper.i18n("please.re-enter.your.password"))) case false => - if (isValidStrongPassword(passwordValue)) + if (validatePasswordOnCreation(passwordValue)) invalidPw = false else { invalidPw = true diff --git a/obp-api/src/main/scala/code/sandbox/CreateOBPUsers.scala b/obp-api/src/main/scala/code/sandbox/CreateOBPUsers.scala index a8e8e602f..3b7ffc6a3 100644 --- a/obp-api/src/main/scala/code/sandbox/CreateOBPUsers.scala +++ b/obp-api/src/main/scala/code/sandbox/CreateOBPUsers.scala @@ -1,5 +1,7 @@ package code.sandbox +import code.api.util.APIUtil.validatePasswordOnCreation +import code.api.util.ErrorMessages import code.model.dataAccess.{AuthUser, ResourceUser} import code.users.Users import net.liftweb.common.{Box, Failure, Full} @@ -36,7 +38,8 @@ trait CreateAuthUsers { .validated(true) val validationErrors = authUser.validate - if(!validationErrors.isEmpty) Failure(s"Errors: ${validationErrors.map(_.msg)}") + if (!validatePasswordOnCreation(u.password)) Failure(ErrorMessages.InvalidStrongPasswordFormat) + else if(!validationErrors.isEmpty) Failure(s"Errors: ${validationErrors.map(_.msg)}") else Full(asSaveable(authUser)) } } From b0f964814c43d2798ed85ef9fb33fe5277a4f9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 20 Aug 2021 17:43:56 +0200 Subject: [PATCH 051/293] test/Fix the failed test --- obp-api/src/test/scala/code/api/oauthTest.scala | 12 +++++++++++- .../code/api/v2_1_0/SandboxDataLoadingTest.scala | 10 +++++++--- .../scala/code/api/v4_0_0/PasswordRecoverTest.scala | 10 +++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/obp-api/src/test/scala/code/api/oauthTest.scala b/obp-api/src/test/scala/code/api/oauthTest.scala index 6967a9ccc..b0fbea7d6 100644 --- a/obp-api/src/test/scala/code/api/oauthTest.scala +++ b/obp-api/src/test/scala/code/api/oauthTest.scala @@ -28,13 +28,14 @@ TESOBE (http://www.tesobe.com/) package code.api import java.util.ResourceBundle + import code.api.oauth1a.OauthParams._ import code.api.util.APIUtil.OAuth._ import code.api.util.ErrorMessages._ import code.api.util.{APIUtil, ErrorMessages} import code.consumer.Consumers import code.loginattempts.LoginAttempt -import code.model.dataAccess.AuthUser +import code.model.dataAccess.{AuthUser, ResourceUser} import code.model.{Consumer => OBPConsumer, Token => OBPToken} import code.setup.ServerSetup import code.util.Helper.MdcLoggable @@ -42,6 +43,7 @@ import dispatch.Defaults._ import dispatch._ import net.liftweb.common.{Box, Failure} import net.liftweb.http.LiftRules +import net.liftweb.mapper.By import net.liftweb.util.Helpers._ import org.scalatest._ import org.scalatestplus.selenium._ @@ -56,6 +58,14 @@ case class OAuthResponse( class OAuthTest extends ServerSetup { + override def beforeAll() = { + super.beforeAll() + AuthUser.bulkDelete_!!(By(AuthUser.username, "username with_space")) + ResourceUser.bulkDelete_!!(By(ResourceUser.providerId, "username with_space")) + AuthUser.bulkDelete_!!(By(AuthUser.username, "username with more than 1 space")) + ResourceUser.bulkDelete_!!(By(ResourceUser.providerId, "username with more than 1 space")) + } + def oauthRequest = baseRequest / "oauth" //a url that will be guaranteed to resolve when the oauth redirects us to it diff --git a/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala b/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala index 0b635a942..55c8130f5 100644 --- a/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala +++ b/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala @@ -86,6 +86,8 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Match val user1Import = SandboxUserImport(email = "user1@example.com", password = "TESOBE520berlin123!", user_name = "user.name_1") val user2Import = SandboxUserImport(email = "user2@example.com", password = "TESOBE520berlin123!", user_name = "user.name_2") + val differentUsername = "user_one" + val secondUserName = "user_two" val standardUsers = user1Import :: user2Import :: Nil @@ -102,8 +104,12 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Match //we need to delete the test uses manully here. AuthUser.bulkDelete_!!(By(AuthUser.username, user1Import.user_name)) AuthUser.bulkDelete_!!(By(AuthUser.username, user2Import.user_name)) + AuthUser.bulkDelete_!!(By(AuthUser.username, differentUsername)) + AuthUser.bulkDelete_!!(By(AuthUser.username, secondUserName)) ResourceUser.bulkDelete_!!(By(ResourceUser.name_, user1Import.user_name )) ResourceUser.bulkDelete_!!(By(ResourceUser.name_, user2Import.user_name )) + ResourceUser.bulkDelete_!!(By(ResourceUser.name_, differentUsername )) + ResourceUser.bulkDelete_!!(By(ResourceUser.name_, secondUserName )) Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanCreateSandbox.toString) } @@ -756,11 +762,9 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Match } //emails of the user we will eventually create to show multiple users with different ids are possible - val secondUserName = "user_two" val user1Json = Extraction.decompose(user1Import) - - val differentUsername = "user_one" + differentUsername should not equal(user1Import.user_name) val userWithSameUsernameAsUser1 = user1Json diff --git a/obp-api/src/test/scala/code/api/v4_0_0/PasswordRecoverTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/PasswordRecoverTest.scala index 7ded4e670..e299f5e4a 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/PasswordRecoverTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/PasswordRecoverTest.scala @@ -34,16 +34,24 @@ import com.openbankproject.commons.util.ApiVersion import code.api.util.ErrorMessages._ import code.api.v4_0_0.APIMethods400.Implementations4_0_0 import code.entitlement.Entitlement -import code.model.dataAccess.AuthUser +import code.model.dataAccess.{AuthUser, ResourceUser} import code.users.Users import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.User import net.liftweb.common.Box import net.liftweb.json.Serialization.write +import net.liftweb.mapper.By import org.scalatest.Tag class PasswordRecoverTest extends V400ServerSetupAsync { + override def beforeEach() = { + wipeTestData() + super.beforeEach() + AuthUser.bulkDelete_!!(By(AuthUser.username, postJson.username)) + ResourceUser.bulkDelete_!!(By(ResourceUser.providerId, postJson.username)) + } + /** * Test tags * Example: To run tests with tag "getPermissions": From 29d812e96e947997a7795904cb921a5bb44d395a Mon Sep 17 00:00:00 2001 From: shuang Date: Sun, 22 Aug 2021 13:20:19 +0800 Subject: [PATCH 052/293] add annotation OBPMemoize way, operate cache. --- obp-api/pom.xml | 9 +++- .../main/scala/code/api/cache/Caching.scala | 41 +++++++++++++++++++ obp-commons/pom.xml | 7 +++- pom.xml | 13 +++++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/obp-api/pom.xml b/obp-api/pom.xml index 57e6af0be..ed9eaa037 100644 --- a/obp-api/pom.xml +++ b/obp-api/pom.xml @@ -8,7 +8,7 @@ com.tesobe obp-parent ../pom.xml - 1.9.0 + 1.10.0 obp-api war @@ -476,6 +476,13 @@ iban4j 3.2.1 + + + + com.github.oldbig + macmemo + 0.6-OBP-SNAPSHOT + diff --git a/obp-api/src/main/scala/code/api/cache/Caching.scala b/obp-api/src/main/scala/code/api/cache/Caching.scala index 2b97f409d..288bdf048 100644 --- a/obp-api/src/main/scala/code/api/cache/Caching.scala +++ b/obp-api/src/main/scala/code/api/cache/Caching.scala @@ -6,7 +6,9 @@ import net.liftweb.common.Full import scala.concurrent.Future import scala.concurrent.duration.Duration import scala.language.postfixOps +import com.softwaremill.macmemo.{Cache, MemoCacheBuilder, MemoizeParams} +import scala.reflect.runtime.universe._ object Caching { def memoizeSyncWithProvider[A](cacheKey: Option[String])(ttl: Duration)(f: => A)(implicit m: Manifest[A]): A = { @@ -46,4 +48,43 @@ object Caching { } } + + /** + * the default MemoCacheBuilder for annotation OBPMemoize + * + * e.g: + *{{{ + * import Caching._ + * + * @OBPMemoize(ttl = 2 hours, maxSize = 111) + * def hello(name: String, age: Int): Future[String] = ??? + *}}} + */ + implicit object OBPCacheBuilder extends MemoCacheBuilder { + override def build[V : TypeTag : Manifest](bucketId: String, params: MemoizeParams): Cache[V] = new Cache[V] { + val ttl = params.expiresAfterMillis + var isFuture = implicitly[TypeTag[V]].tpe <:< typeOf[Future[_]] + var fixedReturnType = false + + override def get(key: List[Any], compute: => V): V = { + val cacheKey = bucketId + "_" + key.mkString("_") + if(isFuture) { + val result = memoizeWithProvider(Some(cacheKey))(ttl ){println("call Future method"); compute.asInstanceOf[Future[Any]]} + result.asInstanceOf[V] + } else if(implicitly[TypeTag[V]].tpe =:= typeOf[Any] && !fixedReturnType) { + val result = compute + isFuture = result.isInstanceOf[Future[_]] + fixedReturnType = true + this.get(key, result) + } else { + val result = memoizeSyncWithProvider(Some(cacheKey))(ttl ){println("call common method"); compute} + if(result.isInstanceOf[Future[_]]) { + isFuture = true + } + result + } + } + } + } + } diff --git a/obp-commons/pom.xml b/obp-commons/pom.xml index ac08617c6..9929785bb 100644 --- a/obp-commons/pom.xml +++ b/obp-commons/pom.xml @@ -7,7 +7,7 @@ com.tesobe obp-parent ../pom.xml - 1.9.0 + 1.10.0 obp-commons jar @@ -67,6 +67,11 @@ org.apache.commons commons-lang3 + + com.google.guava + guava + 23.0 + diff --git a/pom.xml b/pom.xml index 3a2c1681e..a2b5e94db 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.tesobe obp-parent - 1.9.0 + 1.10.0 pom Open Bank Project API Parent 2011 @@ -181,6 +181,17 @@ net.alchim31.maven scala-maven-plugin + + + + + org.scalamacros + paradise_${scala.compiler} + 2.1.1 + + + org.apache.maven.plugins From 4ae11a5db0e960eae539a4543778127cef393615 Mon Sep 17 00:00:00 2001 From: shuang Date: Sun, 22 Aug 2021 21:05:15 +0800 Subject: [PATCH 053/293] refactor --- obp-api/src/main/scala/code/api/cache/Caching.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/cache/Caching.scala b/obp-api/src/main/scala/code/api/cache/Caching.scala index 288bdf048..b260e63a7 100644 --- a/obp-api/src/main/scala/code/api/cache/Caching.scala +++ b/obp-api/src/main/scala/code/api/cache/Caching.scala @@ -69,7 +69,7 @@ object Caching { override def get(key: List[Any], compute: => V): V = { val cacheKey = bucketId + "_" + key.mkString("_") if(isFuture) { - val result = memoizeWithProvider(Some(cacheKey))(ttl ){println("call Future method"); compute.asInstanceOf[Future[Any]]} + val result = memoizeWithProvider(Some(cacheKey))(ttl)(compute.asInstanceOf[Future[Any]]) result.asInstanceOf[V] } else if(implicitly[TypeTag[V]].tpe =:= typeOf[Any] && !fixedReturnType) { val result = compute @@ -77,7 +77,7 @@ object Caching { fixedReturnType = true this.get(key, result) } else { - val result = memoizeSyncWithProvider(Some(cacheKey))(ttl ){println("call common method"); compute} + val result = memoizeSyncWithProvider(Some(cacheKey))(ttl)(compute) if(result.isInstanceOf[Future[_]]) { isFuture = true } From c87cdf4a8566c30c0f0be01ea60acd0355d1882a Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 23 Aug 2021 10:27:19 +0200 Subject: [PATCH 054/293] feature/added the missing roles to getResourceDoc endpoints --- .../ResourceDocs1_4_0/ResourceDocsAPIMethods.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 05bec74ad..8fb56da02 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -5,7 +5,7 @@ import code.api.OBPRestHelper import code.api.builder.OBP_APIBuilder import code.api.cache.Caching import code.api.util.APIUtil._ -import code.api.util.ApiRole.canReadResourceDoc +import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc} import code.api.util.ApiTag._ import code.api.util.ExampleValue.endpointMappingRequestBodyExample import code.api.util.{APIUtil, _} @@ -34,7 +34,6 @@ import net.liftweb.json._ import net.liftweb.util.Helpers.tryo import net.liftweb.util.Props import java.util.concurrent.ConcurrentHashMap - import code.api.util.NewStyle.HttpCode import code.util.Helper @@ -468,7 +467,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth emptyObjectJson, exampleResourceDocsJson, UnknownError :: Nil, - List(apiTagDocumentation, apiTagApi) + List(apiTagDocumentation, apiTagApi), + Some(List(canReadResourceDoc)) ) def resourceDocsRequireRole = APIUtil.getPropsAsBoolValue("resource_docs_requires_role", false) @@ -493,7 +493,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth emptyObjectJson, exampleResourceDocsJsonV400, UnknownError :: Nil, - List(apiTagDocumentation, apiTagApi) + List(apiTagDocumentation, apiTagApi), + Some(List(canReadResourceDoc)) ) def getResourceDocsObpV400 : OBPEndpoint = { @@ -564,7 +565,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth emptyObjectJson, exampleResourceDocsJson, UnknownError :: Nil, - List(apiTagDocumentation, apiTagApi) + List(apiTagDocumentation, apiTagApi), + Some(List(canReadDynamicResourceDocsAtOneBank)) ) // Provides resource documents so that API Explorer (or other apps) can display API documentation From 094f8e85e32bbc469f9a21006b8354422842b0a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 24 Aug 2021 14:17:20 +0200 Subject: [PATCH 055/293] feature/Add is_active (boolean) to Product Attribute POST and GET APIs - done --- .../SwaggerDefinitionsJSON.scala | 14 ++++++++++++ .../main/scala/code/api/util/NewStyle.scala | 2 ++ .../scala/code/api/v3_1_0/APIMethods310.scala | 2 ++ .../scala/code/api/v4_0_0/APIMethods400.scala | 20 ++++++++++------- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 21 ++++++++++++++---- .../scala/code/bankconnectors/Connector.scala | 1 + .../bankconnectors/LocalMappedConnector.scala | 3 ++- .../akka/AkkaConnector_vDec2018.scala | 13 ++++++----- .../rest/RestConnector_vMar2019.scala | 13 ++++++----- .../StoredProcedureConnector_vDec2019.scala | 13 ++++++----- .../MappedProductAttributeProvider.scala | 6 +++-- .../productattribute/ProductAttribute.scala | 6 +++-- .../RemotedataProductAttribute.scala | 2 +- .../RemotedataProductAttributeActor.scala | 8 ++++--- .../RestConnector_vMar2019_frozen_meta_data | Bin 112092 -> 112121 bytes .../commons/dto/JsonsTransfer.scala | 3 ++- 16 files changed, 87 insertions(+), 40 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 1b8e0eb82..82d972008 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -3452,6 +3452,12 @@ object SwaggerDefinitionsJSON { name = "OVERDRAFT_START_DATE", `type` = "DATE_WITH_DAY", value = "2012-04-23" + ) + val productAttributeJsonV400 = ProductAttributeJsonV400( + name = "OVERDRAFT_START_DATE", + `type` = "DATE_WITH_DAY", + value = "2012-04-23", + is_active = Some(true) ) val productAttributeResponseJson = ProductAttributeResponseWithoutBankIdJson( product_code = "saving1", @@ -3460,6 +3466,14 @@ object SwaggerDefinitionsJSON { `type` = "DATE_WITH_DAY", value = "2012-04-23" ) + val productAttributeResponseJsonV400 = ProductAttributeResponseWithoutBankIdJsonV400( + product_code = "saving1", + product_attribute_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f", + name = "OVERDRAFT_START_DATE", + `type` = "DATE_WITH_DAY", + value = "2012-04-23", + is_active = Some(true) + ) val accountAttributeJson = AccountAttributeJson( name = "OVERDRAFT_START_DATE", diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index f890b473a..946ce3c04 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1322,6 +1322,7 @@ object NewStyle { name: String, attributType: ProductAttributeType.Value, value: String, + isActive: Option[Boolean], callContext: Option[CallContext] ): OBPReturnType[ProductAttribute] = { Connector.connector.vend.createOrUpdateProductAttribute( @@ -1331,6 +1332,7 @@ object NewStyle { name: String, attributType: ProductAttributeType.Value, value: String, + isActive: Option[Boolean], callContext: Option[CallContext] ) map { i => (connectorEmptyResponse(i._1, callContext), i._2) diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index c1bc9b69e..1c2fb9480 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -2058,6 +2058,7 @@ trait APIMethods310 { postedData.name, productAttributeType, postedData.value, + None, callContext: Option[CallContext] ) } yield { @@ -2154,6 +2155,7 @@ trait APIMethods310 { postedData.name, productAttributeType, postedData.value, + None, callContext: Option[CallContext] ) } yield { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 480548f60..121f4620f 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5487,8 +5487,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - productAttributeJson, - productAttributeResponseJson, + productAttributeJsonV400, + productAttributeResponseJsonV400, List( InvalidJsonFormat, UnknownError @@ -5506,14 +5506,16 @@ trait APIMethods400 { (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) failMsg = s"$InvalidJsonFormat The Json body should be the $ProductAttributeJson " postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.extract[ProductAttributeJson] + json.extract[ProductAttributeJsonV400] } failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + s"${ProductAttributeType.DOUBLE}(12.1234), ${ProductAttributeType.STRING}(TAX_NUMBER), ${ProductAttributeType.INTEGER}(123) and ${ProductAttributeType.DATE_WITH_DAY}(2012-04-23)" productAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { ProductAttributeType.withName(postedData.`type`) } - + _ <- Future(Connector.connector.vend.getProduct(BankId(bankId), ProductCode(productCode))) map { + getFullBoxOrFail(_, callContext, ProductNotFoundByProductCode + " {" + productCode + "}", 400) + } (productAttribute, callContext) <- NewStyle.function.createOrUpdateProductAttribute( BankId(bankId), ProductCode(productCode), @@ -5521,6 +5523,7 @@ trait APIMethods400 { postedData.name, productAttributeType, postedData.value, + postedData.is_active, callContext: Option[CallContext] ) } yield { @@ -5546,8 +5549,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - productAttributeJson, - productAttributeResponseJson, + productAttributeJsonV400, + productAttributeResponseJsonV400, List( UserHasMissingRoles, UnknownError @@ -5563,7 +5566,7 @@ trait APIMethods400 { (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) failMsg = s"$InvalidJsonFormat The Json body should be the $ProductAttributeJson " postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.extract[ProductAttributeJson] + json.extract[ProductAttributeJsonV400] } failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + s"${ProductAttributeType.DOUBLE}(12.1234), ${ProductAttributeType.STRING}(TAX_NUMBER), ${ProductAttributeType.INTEGER}(123) and ${ProductAttributeType.DATE_WITH_DAY}(2012-04-23)" @@ -5578,6 +5581,7 @@ trait APIMethods400 { postedData.name, productAttributeType, postedData.value, + postedData.is_active, callContext: Option[CallContext] ) } yield { @@ -5603,7 +5607,7 @@ trait APIMethods400 { | |""", emptyObjectJson, - productAttributeResponseJson, + productAttributeResponseJsonV400, List( UserHasMissingRoles, UnknownError diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index ac626237c..75f436283 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -649,8 +649,13 @@ case class JsonSchemaV400( case class JsonValidationV400(operation_id: String, json_schema: JsonSchemaV400) // Validation related END - -case class ProductAttributeResponseJson( +case class ProductAttributeJsonV400( + name: String, + `type`: String, + value: String, + is_active: Option[Boolean] + ) +case class ProductAttributeResponseJsonV400( bank_id: String, product_code: String, product_attribute_id: String, @@ -659,6 +664,14 @@ case class ProductAttributeResponseJson( value: String, is_active: Option[Boolean] ) +case class ProductAttributeResponseWithoutBankIdJsonV400( + product_code: String, + product_attribute_id: String, + name: String, + `type`: String, + value: String, + is_active: Option[Boolean] + ) case class IbanCheckerJsonV400( is_valid: Boolean, @@ -1369,8 +1382,8 @@ object JSONFactory400 { } - def createProductAttributeJson(productAttribute: ProductAttribute): ProductAttributeResponseJson = - ProductAttributeResponseJson( + def createProductAttributeJson(productAttribute: ProductAttribute): ProductAttributeResponseJsonV400 = + ProductAttributeResponseJsonV400( bank_id = productAttribute.bankId.value, product_code = productAttribute.productCode.value, product_attribute_id = productAttribute.productAttributeId, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index d61bb6ed7..3ba57d56a 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1989,6 +1989,7 @@ trait Connector extends MdcLoggable { name: String, productAttributeType: ProductAttributeType.Value, value: String, + isActive: Option[Boolean], callContext: Option[CallContext] ): OBPReturnType[Box[ProductAttribute]] = Future{(Failure(setUnimplementedError), callContext)} diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index d75e97bd2..e937e25f3 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -3402,6 +3402,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { name: String, attributType: ProductAttributeType.Value, value: String, + isActive: Option[Boolean], callContext: Option[CallContext] ): OBPReturnType[Box[ProductAttribute]] = ProductAttributeX.productAttributeProvider.vend.createOrUpdateProductAttribute( @@ -3410,7 +3411,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, - value: String) map { + value: String, isActive: Option[Boolean]) map { (_, callContext) } diff --git a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala index d61643811..e75e60657 100644 --- a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala +++ b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala @@ -307,7 +307,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2021-08-19T16:36:57Z +// ---------- created on 2021-08-24T13:21:14Z messageDocs += validateAndCheckIbanNumberDoc def validateAndCheckIbanNumberDoc = MessageDoc( @@ -4609,7 +4609,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { productAttributeId=Some(productAttributeIdExample.value), name=nameExample.value, productAttributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)) ), exampleInboundMessage = ( InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -4625,9 +4626,9 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { + override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean], callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { import com.openbankproject.commons.dto.{InBoundCreateOrUpdateProductAttribute => InBound, OutBoundCreateOrUpdateProductAttribute => OutBound} - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value) + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value, isActive) val response: Future[Box[InBound]] = (southSideActor ? req).mapTo[InBound].recoverWith(recoverFunction).map(Box !! _) response.map(convertToTuple[ProductAttributeCommons](callContext)) } @@ -6204,6 +6205,6 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2021-08-19T16:36:57Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2021-08-24T13:21:14Z +//---------------- dynamic end ---------------------please don't modify this line } diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 2d9a23fe8..28a738c7d 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -95,7 +95,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2021-08-19T16:37:18Z +// ---------- created on 2021-08-24T13:22:01Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -4796,7 +4796,8 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable productAttributeId=Some(productAttributeIdExample.value), name=nameExample.value, productAttributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)) ), exampleInboundMessage = ( InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -4812,9 +4813,9 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { + override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean], callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { import com.openbankproject.commons.dto.{InBoundCreateOrUpdateProductAttribute => InBound, OutBoundCreateOrUpdateProductAttribute => OutBound} - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value) + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value, isActive) val response: Future[Box[InBound]] = sendRequest[InBound](getUrl(callContext, "createOrUpdateProductAttribute"), HttpMethods.POST, req, callContext) response.map(convertToTuple[ProductAttributeCommons](callContext)) } @@ -6391,8 +6392,8 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2021-08-19T16:37:18Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2021-08-24T13:22:01Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala index cab49da0a..41d775ebd 100644 --- a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala @@ -76,7 +76,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { val connectorName = "stored_procedure_vDec2019" //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2021-08-19T16:41:22Z +// ---------- created on 2021-08-24T13:22:36Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -4777,7 +4777,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { productAttributeId=Some(productAttributeIdExample.value), name=nameExample.value, productAttributeType=com.openbankproject.commons.model.enums.ProductAttributeType.example, - value=valueExample.value) + value=valueExample.value, + isActive=Some(isActiveExample.value.toBoolean)) ), exampleInboundMessage = ( InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, @@ -4793,9 +4794,9 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) - override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { + override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, productAttributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean], callContext: Option[CallContext]): OBPReturnType[Box[ProductAttribute]] = { import com.openbankproject.commons.dto.{InBoundCreateOrUpdateProductAttribute => InBound, OutBoundCreateOrUpdateProductAttribute => OutBound} - val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value) + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, productCode, productAttributeId, name, productAttributeType, value, isActive) val response: Future[Box[InBound]] = sendRequest[InBound]("obp_create_or_update_product_attribute", req, callContext) response.map(convertToTuple[ProductAttributeCommons](callContext)) } @@ -6372,8 +6373,8 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { response.map(convertToTuple[Boolean](callContext)) } -// ---------- created on 2021-08-19T16:41:22Z -//---------------- dynamic end ---------------------please don't modify this line +// ---------- created on 2021-08-24T13:22:36Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala b/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala index bd4cb384b..8017b1932 100644 --- a/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala +++ b/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala @@ -8,7 +8,6 @@ import com.openbankproject.commons.model.{BankId, ProductAttribute, ProductCode} import net.liftweb.common.{Box, Empty, Full} import net.liftweb.mapper.{BaseMappedField, MappedBoolean, _} import net.liftweb.util.Helpers.tryo -import com.openbankproject.commons.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -32,7 +31,8 @@ object MappedProductAttributeProvider extends ProductAttributeProvider { productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, - value: String): Future[Box[ProductAttribute]] = { + value: String, + isActive: Option[Boolean]): Future[Box[ProductAttribute]] = { productAttributeId match { case Some(id) => Future { MappedProductAttribute.find(By(MappedProductAttribute.mProductAttributeId, id)) match { @@ -42,6 +42,7 @@ object MappedProductAttributeProvider extends ProductAttributeProvider { .mName(name) .mType(attributType.toString) .mValue(value) + .IsActive(isActive.getOrElse(true)) .saveMe() } case _ => Empty @@ -55,6 +56,7 @@ object MappedProductAttributeProvider extends ProductAttributeProvider { .mName(name) .mType(attributType.toString()) .mValue(value) + .IsActive(isActive.getOrElse(true)) .saveMe() } } diff --git a/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala b/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala index cfdc6c9c9..15286ed11 100644 --- a/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala +++ b/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala @@ -47,7 +47,8 @@ trait ProductAttributeProvider { productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, - value: String): Future[Box[ProductAttribute]] + value: String, + isActive: Option[Boolean]): Future[Box[ProductAttribute]] def deleteProductAttribute(productAttributeId: String): Future[Box[Boolean]] // End of Trait } @@ -62,7 +63,8 @@ class RemotedataProductAttributeCaseClasses { productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, - value: String) + value: String, + isActive: Option[Boolean]) case class deleteProductAttribute(productAttributeId: String) } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala index 99ffc868c..f9f46cd23 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala @@ -19,7 +19,7 @@ object RemotedataProductAttribute extends ObpActorInit with ProductAttributeProv override def getProductAttributeById(productAttributeId: String): Future[Box[ProductAttribute]] = (actor ? cc.getProductAttributeById(productAttributeId)).mapTo[Box[ProductAttribute]] - override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, value: String): Future[Box[ProductAttribute]] = (actor ? cc.createOrUpdateProductAttribute(bankId, productCode, productAttributeId , name , attributType , value )).mapTo[Box[ProductAttribute]] + override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]): Future[Box[ProductAttribute]] = (actor ? cc.createOrUpdateProductAttribute(bankId, productCode, productAttributeId , name , attributType , value, isActive)).mapTo[Box[ProductAttribute]] override def deleteProductAttribute(productAttributeId: String): Future[Box[Boolean]] = (actor ? cc.deleteProductAttribute(productAttributeId)).mapTo[Box[Boolean]] } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala index 5a3d680f4..753cbb693 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala @@ -31,14 +31,16 @@ class RemotedataProductAttributeActor extends Actor with ObpActorHelper with Mdc productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, - value: String) => - logger.debug(s"createOrUpdateProductAttribute(${bankId}, ${productCode}, ${productAttributeId}, ${name}, ${attributType}, ${value})") + value: String, + isActive: Option[Boolean]) => + logger.debug(s"createOrUpdateProductAttribute(${bankId}, ${productCode}, ${productAttributeId}, ${name}, ${attributType}, ${value}, ${isActive})") mapper.createOrUpdateProductAttribute(bankId, productCode, productAttributeId, name, attributType, - value) pipeTo sender + value, + isActive) pipeTo sender case cc.deleteProductAttribute(productAttributeId: String) => logger.debug(s"deleteProductAttribute(${productAttributeId})") diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data index 4e0e332ecef5882e76b19e0f6e7ddd6e3c0c4739..e31fe3c316cf8ae1ca06984e853bbee82cf7338f 100644 GIT binary patch delta 30 ocmV+(0O9}K>jwGj27t5yUZ|6X@;R56r~zD)&gUJs^QZyo3;`|>7XSbN delta 39 xcmV+?0NDTe>jvEG27t5yUZ|G|hXE6lu;&$%uJRF=m#6_;lR)Txw~na+YYc=M5`zE$ diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala index 6f13aa3ce..2a6d29180 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala @@ -378,7 +378,8 @@ case class OutBoundCreateOrUpdateProductAttribute(outboundAdapterCallContext: Ou productAttributeId: Option[String], name: String, productAttributeType: enums.ProductAttributeType.Value, - value: String) extends TopicTrait + value: String, + isActive: Option[Boolean]) extends TopicTrait case class InBoundCreateOrUpdateProductAttribute(inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: ProductAttributeCommons) extends InBoundTrait[ProductAttributeCommons] From 0d50c02b23c9032a13366323f9c3a1a7c9414639 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 25 Aug 2021 11:58:45 +0200 Subject: [PATCH 056/293] feature/OBPv400 added new endpoint getSystemResourceDocsObp --- .../ResourceDocs1_4_0/ResourceDocs140.scala | 21 +- .../ResourceDocsAPIMethods.scala | 47 +++- .../main/scala/code/api/util/ApiRole.scala | 3 + .../ResourceDocs1_4_0/ResourceDocsTest.scala | 260 ++++++++++++++++++ 4 files changed, 319 insertions(+), 12 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index e1dfd2a4c..3890e0ee2 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -11,7 +11,8 @@ object ResourceDocs140 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getResourceDocsSwagger + ImplementationsResourceDocs.getResourceDocsSwagger, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -26,7 +27,8 @@ object ResourceDocs200 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -41,7 +43,8 @@ object ResourceDocs210 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -55,7 +58,8 @@ object ResourceDocs220 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -69,7 +73,8 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -82,7 +87,8 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { @@ -97,7 +103,8 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val routes = List( ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp + ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, + ImplementationsResourceDocs.getSystemResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 8fb56da02..20971728e 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -5,7 +5,7 @@ import code.api.OBPRestHelper import code.api.builder.OBP_APIBuilder import code.api.cache.Caching import code.api.util.APIUtil._ -import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc} +import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc, canReadSystemResourceDoc} import code.api.util.ApiTag._ import code.api.util.ExampleValue.endpointMappingRequestBodyExample import code.api.util.{APIUtil, _} @@ -478,7 +478,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() cc => - getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam, false) + getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam, false, false) } } @@ -501,7 +501,40 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() cc => - getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam, true) + getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam, true, false) + } + } + + localResourceDocs += ResourceDoc( + getSystemResourceDocsObp, + implementedInApiVersion, + nameOf(getSystemResourceDocsObp), + "GET", + "/system-resource-docs/API_VERSION/obp", + "Get System Resource Docs", + getResourceDocsDescription(false), + emptyObjectJson, + exampleResourceDocsJsonV400, + UnknownError :: Nil, + List(apiTagDocumentation, apiTagApi), + Some(List(canReadSystemResourceDoc)) + ) + + def getSystemResourceDocsObp : OBPEndpoint = { + case "system-resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { + val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() + cc => + getApiLevelResourceDocs( + cc,requestedApiVersionString, + tags, + partialFunctions, + languageParam, + Some(ContentParam.STATIC) ,//Note: here it set to default STATIC value. + apiCollectionIdParam, + cacheModifierParam, + true, + true + ) } } @@ -514,7 +547,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth contentParam: Option[ContentParam], apiCollectionIdParam: Option[String], cacheModifierParam: Option[String], - isVersion4OrHigher: Boolean + isVersion4OrHigher: Boolean, + isSystemResource: Boolean, ) = { for { (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { @@ -524,7 +558,10 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth _ <- resourceDocsRequireRole match { case false => Future() case true => // If set resource_docs_requires_role=true, we need check the the roles as well - NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc :: Nil, cc.callContext) + if(isSystemResource) + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadSystemResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadSystemResourceDoc :: Nil, cc.callContext) + else + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc :: Nil, cc.callContext) } requestedApiVersion <- NewStyle.function.tryons(s"$InvalidApiVersionString $requestedApiVersionString", 400, callContext) {ApiVersionUtils.valueOf(requestedApiVersionString)} _ <- Helper.booleanToFuture(s"$ApiVersionNotSupported $requestedApiVersionString", 400, callContext)(versionIsAllowed(requestedApiVersion)) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 27ea919c9..25d2d7c76 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -594,6 +594,9 @@ object ApiRole { case class CanReadResourceDoc(requiresBankId: Boolean = false) extends ApiRole lazy val canReadResourceDoc = CanReadResourceDoc() + case class CanReadSystemResourceDoc(requiresBankId: Boolean = false) extends ApiRole + lazy val canReadSystemResourceDoc = CanReadSystemResourceDoc() + case class CanReadDynamicResourceDocsAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canReadDynamicResourceDocsAtOneBank = CanReadDynamicResourceDocsAtOneBank() diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index cdcbad917..121600189 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -24,6 +24,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with object ApiEndpoint1 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsObp)) object ApiEndpoint2 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsSwagger)) object ApiEndpoint3 extends Tag(nameOf(ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp)) + object ApiEndpoint4 extends Tag(nameOf(ImplementationsResourceDocs.getSystemResourceDocsObp)) override def beforeEach() = { @@ -700,6 +701,265 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } } + + feature(s"test ${ApiEndpoint4.name} ") { + scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv4.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v3.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + org.scalameta.logger.elem(responseGetObp) + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv3.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v3.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv3.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v2.2.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.2.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv2.2.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v2.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.1.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv2.1.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v2.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv2.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.4.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.4.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv1.4.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.3.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.3.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv1.3.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.2.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.2.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv1.2.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + + scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "BGv1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.3" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "BGv1.3" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v3.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -UKv3.1", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "UKv3.1" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(200) + //This should not throw any exceptions + responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props", ApiEndpoint1, VersionOfApi) { + setPropsValues( + "resource_docs_requires_role" -> "true", + ) + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v4.0.0" / "obp").GET + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(401) + responseGetObp.toString contains(UserNotLoggedIn) should be (true) + } + + scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) { + setPropsValues( + "resource_docs_requires_role" -> "true", + ) + val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v4.0.0" / "obp").GET <@ (user1) + val responseGetObp = makeGetRequest(requestGetObp) + And("We should get 200 and the response can be extract to case classes") + val responseDocs = responseGetObp.body.extract[ResourceDocsJson] + responseGetObp.code should equal(403) + responseGetObp.toString contains(UserHasMissingRoles) should be (true) + responseGetObp.toString contains( ApiRole.canReadSystemResourceDoc.toString()) should be (true) + } + + } + //Note: it is tricky to validate the swagger string, I just find this : https://github.com/swagger-api/swagger-parser/issues/718 //So follow it to call the `Validate` method: //https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Validate.java#L46 From 0641fdeee153b113162cb9e74f67440d82b27fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 26 Aug 2021 12:53:38 +0200 Subject: [PATCH 057/293] feature/Add the props user_invitation.mandatory --- .../resources/props/sample.props.template | 2 ++ .../main/scala/bootstrap/liftweb/Boot.scala | 1 + .../code/model/dataAccess/AuthUser.scala | 7 ++-- .../src/main/webapp/user-invitation-info.html | 33 +++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 obp-api/src/main/webapp/user-invitation-info.html diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 7add90410..fc57c88d4 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -1027,6 +1027,8 @@ default_auth_context_update_request_key=CUSTOMER_NUMBER # User Invitation Time To Live # user_invitation.ttl.seconds=86400 +# User Invitation is mandatory in case of onboarding a user +# user_invitation.mandatory=false # User (Developer) Invitation webui_post_user_invitation_submit_button_value=Register as a Developer diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index f94294208..ab3cf72b0 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -495,6 +495,7 @@ class Boot extends MdcLoggable { Menu("Validate OTP", "Validate OTP") / "otp" >> AuthUser.loginFirst, Menu("User Invitation", "User Invitation") / "user-invitation", + Menu("User Invitation Info", "User Invitation Info") / "user-invitation-info", // Menu.i("Metrics") / "metrics", //TODO: allow this page once we can make the account number anonymous in the URL Menu.i("OAuth") / "oauth" / "authorize", //OAuth authorization page Menu.i("Consent") / "consent" >> AuthUser.loginFirst,//OAuth consent page diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 77abe0fae..5f258aea4 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -1372,8 +1372,11 @@ def restoreSomeSessions(): Unit = { val bind = "type=submit" #> signupSubmitButton(signupSubmitButtonValue, testSignup _) bind(signupXhtml(theUser)) } - - innerSignup + + if(APIUtil.getPropsAsBoolValue("user_invitation.mandatory", false)) + S.redirectTo("/user-invitation-info") + else + innerSignup } def scrambleAuthUser(userPrimaryKey: UserPrimaryKey): Box[Boolean] = tryo { diff --git a/obp-api/src/main/webapp/user-invitation-info.html b/obp-api/src/main/webapp/user-invitation-info.html new file mode 100644 index 000000000..8e7d5de6b --- /dev/null +++ b/obp-api/src/main/webapp/user-invitation-info.html @@ -0,0 +1,33 @@ + +
    +
    +

    User invitation info

    +

    Thank you for expressing interest in the API Playground. At this time access to the API Playground is on an invitation basis only. Those invited will be invited to join by email, where you will be able to complete registration.

    +
    +
    + + From 8c9fcd1356d3467807cb1c25de4176be5a25176f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 26 Aug 2021 15:14:33 +0200 Subject: [PATCH 058/293] feature/Add endpoint getProduct v4.0.0 --- .../SwaggerDefinitionsJSON.scala | 16 +++++- .../scala/code/api/v4_0_0/APIMethods400.scala | 54 +++++++++++++++++++ .../code/api/v4_0_0/JSONFactory4.0.0.scala | 43 +++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 82d972008..4c99896ae 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -3536,7 +3536,21 @@ object SwaggerDefinitionsJSON { Some(List(productAttributeResponseJson)) ) val productsJsonV310 = ProductsJsonV310(products = List(productJsonV310)) - + + val productJsonV400 = ProductJsonV400( + bank_id = bankIdExample.value, + code = "product_code", + parent_product_code = "parent", + name = "product name", + category = "category", + family = "family", + super_family = "super family", + more_info_url = "www.example.com/prod1/more-info.html", + details = "Details", + description = "Description", + meta = metaJson, + Some(List(productAttributeResponseJsonV400)) + ) val productCollectionItemJsonV310 = ProductCollectionItemJsonV310(member_product_code = "A") val productCollectionJsonV310 = ProductCollectionJsonV310( diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 121f4620f..6d25a70f2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5629,6 +5629,60 @@ trait APIMethods400 { } } + + val getProductsIsPublic = APIUtil.getPropsAsBoolValue("apiOptions.getProductsIsPublic", true) + + staticResourceDocs += ResourceDoc( + getProduct, + implementedInApiVersion, + "getProduct", + "GET", + "/banks/BANK_ID/products/PRODUCT_CODE", + "Get Bank Product", + s"""Returns information about a financial Product offered by the bank specified by BANK_ID and PRODUCT_CODE including: + | + |* Name + |* Code + |* Parent Product Code + |* Category + |* Family + |* Super Family + |* More info URL + |* Description + |* Terms and Conditions + |* License the data under this endpoint is released under + | + |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, + emptyObjectJson, + productJsonV400, + List( + UserNotLoggedIn, + ProductNotFoundByProductCode, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle) + ) + + lazy val getProduct: OBPEndpoint = { + case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonGet _ => { + cc => { + for { + (_, callContext) <- getProductsIsPublic match { + case false => authenticatedAccess(cc) + case true => anonymousAccess(cc) + } + (_, callContext) <- NewStyle.function.getBank(bankId, callContext) + product <- Future(Connector.connector.vend.getProduct(bankId, productCode)) map { + unboxFullOrFail(_, callContext, ProductNotFoundByProductCode) + } + (productAttributes, callContext) <- NewStyle.function.getProductAttributesByBankAndCode(bankId, productCode, callContext) + } yield { + (JSONFactory400.createProductJson(product, productAttributes), HttpCode.`200`(callContext)) + } + } + } + } + staticResourceDocs += ResourceDoc( createOrUpdateTransactionAttributeDefinition, implementedInApiVersion, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 75f436283..4378a49f1 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -649,6 +649,19 @@ case class JsonSchemaV400( case class JsonValidationV400(operation_id: String, json_schema: JsonSchemaV400) // Validation related END + +case class ProductJsonV400(bank_id: String, + code : String, + parent_product_code : String, + name : String, + category: String, + family : String, + super_family : String, + more_info_url: String, + details: String, + description: String, + meta : MetaJsonV140, + product_attributes: Option[List[ProductAttributeResponseWithoutBankIdJsonV400]]) case class ProductAttributeJsonV400( name: String, `type`: String, @@ -1393,6 +1406,36 @@ object JSONFactory400 { is_active = productAttribute.isActive ) + def createProductAttributesJson(productAttributes: List[ProductAttribute]): List[ProductAttributeResponseWithoutBankIdJsonV400] = { + productAttributes.map( + productAttribute => + ProductAttributeResponseWithoutBankIdJsonV400( + product_code = productAttribute.productCode.value, + product_attribute_id = productAttribute.productAttributeId, + name = productAttribute.name, + `type` = productAttribute.attributeType.toString, + value = productAttribute.value, + is_active = productAttribute.isActive + ) + ) + } + def createProductJson(product: Product, productAttributes: List[ProductAttribute]) : ProductJsonV400 = { + ProductJsonV400( + bank_id = product.bankId.toString, + code = product.code.value, + parent_product_code = product.parentProductCode.value, + name = product.name, + category = product.category, + family = product.family, + super_family = product.superFamily, + more_info_url = product.moreInfoUrl, + details = product.details, + description = product.description, + meta = createMetaJson(product.meta), + product_attributes = Some(createProductAttributesJson(productAttributes)) + ) + } + def createApiCollectionEndpointsJsonV400(apiCollectionEndpoints: List[ApiCollectionEndpointTrait]) = { ApiCollectionEndpointsJson400(apiCollectionEndpoints.map(apiCollectionEndpoint => createApiCollectionEndpointJsonV400(apiCollectionEndpoint))) } From 6e92c926190963bba8619c5068b64303f0b57bfd Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 26 Aug 2021 08:09:06 +0200 Subject: [PATCH 059/293] feature/OBPv4.0.0 add new endpoint getMySpaces and added resource_docs_requires_role to getRoot --- .../SwaggerDefinitionsJSON.scala | 7 ++- .../scala/code/api/v4_0_0/APIMethods400.scala | 36 ++++++++++++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 7 ++- .../scala/code/api/v4_0_0/MySpaceTest.scala | 54 +++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 obp-api/src/test/scala/code/api/v4_0_0/MySpaceTest.scala diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 82d972008..cd49f614c 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -504,7 +504,8 @@ object SwaggerDefinitionsJSON { connector = "String", hosted_by = hostedBy400, hosted_at = hostedAt400, - energy_source = energySource400 + energy_source = energySource400, + resource_docs_requires_role = false ) val apiInfoJSON = APIInfoJSON( version = "String", @@ -2453,6 +2454,10 @@ object SwaggerDefinitionsJSON { tag_name = tagNameExample.value ) + val mySpaces = MySpaces( + bank_ids = List(bankIdExample.value), + ) + val metricsJson = MetricsJson( metrics = List(metricJson) ) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 121f4620f..2d357104a 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2536,8 +2536,9 @@ trait APIMethods400 { val energySource = new EnergySource400(organisationEnergySource, organisationWebsiteEnergySource) val connector = APIUtil.getPropsValue("connector").openOrThrowException("no connector set") + val resourceDocsRequiresRole = APIUtil.getPropsAsBoolValue("resource_docs_requires_role", false) - APIInfoJson400(apiVersion.vDottedApiVersion, apiVersionStatus, gitCommit, connector, hostedBy, hostedAt, energySource) + APIInfoJson400(apiVersion.vDottedApiVersion, apiVersionStatus, gitCommit, connector, hostedBy, hostedAt, energySource, resourceDocsRequiresRole) } @@ -9585,6 +9586,39 @@ trait APIMethods400 { } } } + + staticResourceDocs += ResourceDoc( + getMySpaces, + implementedInApiVersion, + nameOf(getMySpaces), + "GET", + "/my/spaces", + "Get My Spaces", + s"""Get My Spaces.""", + EmptyBody, + mySpaces, + List( + $UserNotLoggedIn, + UnknownError + ), + List(apiTagUser, apiTagNewStyle) + ) + lazy val getMySpaces: OBPEndpoint = { + case "my" :: "spaces" :: Nil JsonGet _ => { + cc => + for { + (Full(u), callContext) <- SS.user + entitlements <- NewStyle.function.getEntitlementsByUserId(u.userId, callContext) + } yield { + ( + MySpaces(entitlements + .filter(_.roleName == canReadDynamicResourceDocsAtOneBank.toString()) + .map(entitlement => entitlement.bankId)), + HttpCode.`200`(callContext) + ) + } + } + } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 75f436283..10e0f4110 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -150,7 +150,8 @@ case class APIInfoJson400( connector : String, hosted_by : HostedBy400, hosted_at : HostedAt400, - energy_source : EnergySource400 + energy_source : EnergySource400, + resource_docs_requires_role: Boolean ) case class HostedBy400( organisation : String, @@ -562,6 +563,10 @@ case class BankLevelEndpointTagResponseJson400( tag_name: String ) +case class MySpaces( + bank_ids: List[String], +) + case class CounterpartyJson400( name: String, description: String, diff --git a/obp-api/src/test/scala/code/api/v4_0_0/MySpaceTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/MySpaceTest.scala new file mode 100644 index 000000000..b0f39dd4e --- /dev/null +++ b/obp-api/src/test/scala/code/api/v4_0_0/MySpaceTest.scala @@ -0,0 +1,54 @@ +package code.api.v4_0_0 + +import com.openbankproject.commons.model.ErrorMessage +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole +import com.openbankproject.commons.util.ApiVersion +import code.api.util.ErrorMessages.UserNotLoggedIn +import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import code.entitlement.Entitlement +import com.github.dwickern.macros.NameOf.nameOf +import net.liftweb.common.Box +import org.scalatest.Tag + +class MySpaceTest extends V400ServerSetup { + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.getMySpaces)) + + + feature(s"test $ApiEndpoint1 version $VersionOfApi") { + scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "my" / "spaces").GET + val response400 = makeGetRequest(request400) + Then("We should get a 401") + response400.code should equal(401) + response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + scenario("We will call the endpoint return empty List", ApiEndpoint1, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "my" / "spaces").GET <@ (user1) + val response400 = makeGetRequest(request400) + Then("We should get a 200") + response400.code should equal(200) + response400.body.extract[MySpaces].bank_ids.length should be (0) + } + scenario("We will call the endpoint return proper List", ApiEndpoint1, VersionOfApi) { + When("We make a request v4.0.0") + Entitlement.entitlement.vend.addEntitlement(testBankId1.value, resourceUser1.userId, ApiRole.CanReadDynamicResourceDocsAtOneBank.toString) + val request400 = (v4_0_0_Request / "my" / "spaces").GET <@ (user1) + val response400 = makeGetRequest(request400) + Then("We should get a 200") + response400.code should equal(200) + response400.body.extract[MySpaces].bank_ids.length should be (1) + } + } + +} From 9f1eb71bb9a36e7ac1ba54160b69d74d111d1a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 27 Aug 2021 16:22:31 +0200 Subject: [PATCH 060/293] docfix/Tweak jsons in case of product attribute version 4.0.0 --- .../ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 4c99896ae..a29729077 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -3466,7 +3466,16 @@ object SwaggerDefinitionsJSON { `type` = "DATE_WITH_DAY", value = "2012-04-23" ) - val productAttributeResponseJsonV400 = ProductAttributeResponseWithoutBankIdJsonV400( + val productAttributeResponseJsonV400 = ProductAttributeResponseJsonV400( + bank_id = bankIdExample.value, + product_code = "saving1", + product_attribute_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f", + name = "OVERDRAFT_START_DATE", + `type` = "DATE_WITH_DAY", + value = "2012-04-23", + is_active = Some(true) + ) + val productAttributeResponseWithoutBankIdJsonV400 = ProductAttributeResponseWithoutBankIdJsonV400( product_code = "saving1", product_attribute_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f", name = "OVERDRAFT_START_DATE", @@ -3549,7 +3558,7 @@ object SwaggerDefinitionsJSON { details = "Details", description = "Description", meta = metaJson, - Some(List(productAttributeResponseJsonV400)) + Some(List(productAttributeResponseWithoutBankIdJsonV400)) ) val productCollectionItemJsonV310 = ProductCollectionItemJsonV310(member_product_code = "A") From 054f30814934e7ec21e79ea0018116c4ec028150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Sun, 29 Aug 2021 19:28:36 +0200 Subject: [PATCH 061/293] feature/Tweak the i18n message user.invitation.is.already.finished --- obp-api/src/main/resources/i18n/lift-core.properties | 3 ++- obp-api/src/main/scala/code/snippet/UserInvitation.scala | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/resources/i18n/lift-core.properties b/obp-api/src/main/resources/i18n/lift-core.properties index 35b1aa61d..78afcf873 100644 --- a/obp-api/src/main/resources/i18n/lift-core.properties +++ b/obp-api/src/main/resources/i18n/lift-core.properties @@ -374,4 +374,5 @@ invalid.username=Invalid Username: \ 4) Usernames MUST NOT contain __ or ._ or ._ or .. \ 5) Usernames MUST NOT end with _ or . -your.username.is.not.unique = Your username is not unique. Please enter a different one. \ No newline at end of file +your.username.is.not.unique = Your username is not unique. Please enter a different one. +user.invitation.is.already.finished = Cannot complete your user invitation. Please check the invitation link. Your invitation could be invalid or completed. \ No newline at end of file diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 27f34b5b8..602296163 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -172,7 +172,7 @@ class UserInvitation extends MdcLoggable { companyVar.set("None") countryVar.set("None") usernameVar.set("None") - S.error("Cannot complete your user invitation. Please check the invitation link. Your invitation could be invalid or completed.") + S.error(Helper.i18n("user.invitation.is.already.finished")) } register } From 4a2971fa960a00cb8a0cb39c03b6eefe6cbbaee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 30 Aug 2021 09:42:27 +0200 Subject: [PATCH 062/293] feature/Stop OBP startup if database is not available --- .../src/main/scala/bootstrap/liftweb/Boot.scala | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index ab3cf72b0..9d0a63de6 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -268,6 +268,17 @@ class Boot extends MdcLoggable { } } } + implicit val formats = CustomJsonFormats.formats + LiftRules.statelessDispatch.prepend { + case _ if tryo(DB.use(DefaultConnectionIdentifier){ conn => conn}.isClosed).isEmpty => + () => + Full( + JsonResponse( + Extraction.decompose(ErrorMessage(code = 500, message = s"${ErrorMessages.DatabaseConnectionClosedError}")), + 500 + ) + ) + } logger.info("Mapper database info: " + Migration.DbFunction.mapperDatabaseInfo()) @@ -571,8 +582,7 @@ class Boot extends MdcLoggable { Mailer.devModeSend.default.set( (m : MimeMessage) => { logger.info("Would have sent email if not in dev mode: " + m.getContent) }) - - implicit val formats = CustomJsonFormats.formats + LiftRules.exceptionHandler.prepend{ case(_, r, e) if DB.use(DefaultConnectionIdentifier){ conn => conn}.isClosed => { logger.error("Exception being returned to browser when processing " + r.uri.toString, e) From e637abac7a42bd8c83b281a830cbece4f9592610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 30 Aug 2021 09:58:58 +0200 Subject: [PATCH 063/293] refactor/Stop OBP startup if database is not available --- obp-api/src/main/scala/bootstrap/liftweb/Boot.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 9d0a63de6..87ed52bef 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -268,9 +268,10 @@ class Boot extends MdcLoggable { } } } + implicit val formats = CustomJsonFormats.formats LiftRules.statelessDispatch.prepend { - case _ if tryo(DB.use(DefaultConnectionIdentifier){ conn => conn}.isClosed).isEmpty => + case _ if !DB.jndiJdbcConnAvailable_? => () => Full( JsonResponse( From 81feebada6ecf5d261b1a60613d479a8a2cec4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 30 Aug 2021 12:34:52 +0200 Subject: [PATCH 064/293] Revert "refactor/Stop OBP startup if database is not available" This reverts commit e637abac --- obp-api/src/main/scala/bootstrap/liftweb/Boot.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 87ed52bef..9d0a63de6 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -268,10 +268,9 @@ class Boot extends MdcLoggable { } } } - implicit val formats = CustomJsonFormats.formats LiftRules.statelessDispatch.prepend { - case _ if !DB.jndiJdbcConnAvailable_? => + case _ if tryo(DB.use(DefaultConnectionIdentifier){ conn => conn}.isClosed).isEmpty => () => Full( JsonResponse( From d750bd895bea602e4db5e04b7e9e2aabb103dee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 30 Aug 2021 13:27:45 +0200 Subject: [PATCH 065/293] feature/Stop OBP startup if database is not available in development mode --- .../main/scala/bootstrap/liftweb/Boot.scala | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 9d0a63de6..a8240aa1d 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -270,14 +270,17 @@ class Boot extends MdcLoggable { } implicit val formats = CustomJsonFormats.formats LiftRules.statelessDispatch.prepend { - case _ if tryo(DB.use(DefaultConnectionIdentifier){ conn => conn}.isClosed).isEmpty => - () => - Full( - JsonResponse( - Extraction.decompose(ErrorMessage(code = 500, message = s"${ErrorMessages.DatabaseConnectionClosedError}")), - 500 - ) - ) + case _ if tryo(DB.use(DefaultConnectionIdentifier){ conn => conn}.isClosed).isEmpty => + Props.mode match { + case Props.RunModes.Development => + () => + Full( + JsonResponse( + Extraction.decompose(ErrorMessage(code = 500, message = s"${ErrorMessages.DatabaseConnectionClosedError}")), + 500 + ) + ) + } } logger.info("Mapper database info: " + Migration.DbFunction.mapperDatabaseInfo()) From 7a537a5b6ed2be5eae45db36ad5ec72d598354ff Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 30 Aug 2021 15:38:44 +0200 Subject: [PATCH 066/293] OBV 400 added the create Product, get Product and get Products --- .../SwaggerDefinitionsJSON.scala | 27 +++ .../main/scala/code/api/util/APIUtil.scala | 19 +- .../scala/code/api/util/ExampleValue.scala | 4 +- .../scala/code/api/v2_2_0/APIMethods220.scala | 1 + .../scala/code/api/v3_1_0/APIMethods310.scala | 19 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 182 +++++++++++++++++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 64 +++++- .../scala/code/bankconnectors/Connector.scala | 1 + .../KafkaMappedConnector_JVMcompatible.scala | 3 +- .../bankconnectors/LocalMappedConnector.scala | 3 + .../akka/AkkaConnector_vDec2018.scala | 5 +- .../rest/RestConnector_vMar2019.scala | 3 + .../StoredProcedureConnector_vDec2019.scala | 3 + .../products/MappedProductsProvider.scala | 2 + .../scala/code/api/v1_4_0/ProductsTest.scala | 7 +- .../scala/code/api/v4_0_0/ProductTest.scala | 156 +++++++++++++++ .../commons/model/CommonModel.scala | 1 + .../commons/model/CommonModelTrait.scala | 1 + 18 files changed, 470 insertions(+), 31 deletions(-) create mode 100644 obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index cd49f614c..0b548d85a 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4334,6 +4334,33 @@ object SwaggerDefinitionsJSON { ) val atmsJsonV400 = AtmsJsonV400(List(atmJsonV400)) + + val productJsonV400 = ProductJsonV400( + bank_id = bankIdExample.value, + code = "product_code", + parent_product_code = "parent", + name = "product name", + more_info_url = moreInfoUrlExample.value, + terms_and_conditions_url = termsAndConditionsUrlExample.value, + details = "Details", + description = "Description", + meta = metaJson, + Some(List(productAttributeResponseJson)) + ) + + val productsJsonV400 = ProductsJsonV400(products = List(productJsonV400)) + + val putProductJsonV400 = PutProductJsonV400( + bank_id = bankIdExample.value, + parent_product_code = "parent", + name = "product name", + more_info_url = moreInfoUrlExample.value, + terms_and_conditions_url = termsAndConditionsUrlExample.value, + details = "Details", + description = "Description", + meta = metaJson + ) + //The common error or success format. //Just some helper format to use in Json diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index a711afc64..97487d270 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -33,7 +33,6 @@ import java.nio.charset.Charset import java.text.{ParsePosition, SimpleDateFormat} import java.util.concurrent.ConcurrentHashMap import java.util.{Calendar, Date, UUID} - import code.UserRefreshes.UserRefreshes import code.accountholders.AccountHolders import code.api.Constant._ @@ -42,6 +41,7 @@ import code.api.builder.OBP_APIBuilder import code.api.oauth1a.Arithmetics import code.api.oauth1a.OauthParams._ import code.api.util.APIUtil.ResourceDoc.{findPathVariableNames, isPathVariable} +import code.api.util.ApiRole.{canCreateProduct, canCreateProductAtAnyBank} import code.api.util.ApiTag.{ResourceDocTag, apiTagBank, apiTagNewStyle} import code.api.util.Glossary.GlossaryItem import code.api.util.JwsUtil.getJwsHeaderValue @@ -4050,4 +4050,21 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ APIUtil.getPropsValue("email_domain_to_entitlement_mappings").map(extractor).getOrElse(Nil) } + + val getProductsIsPublic = APIUtil.getPropsAsBoolValue("apiOptions.getProductsIsPublic", true) + + val createProductEntitlements = canCreateProduct :: canCreateProductAtAnyBank :: Nil + + val createProductEntitlementsRequiredText = UserHasMissingRoles + createProductEntitlements.mkString(" or ") + + val productHiearchyAndCollectionNote = + """ + | + |Product hiearchy vs Product Collections: + | + |* You can define a hierarchy of products - so that a child Product inherits attributes of its parent Product - using the parent_product_code in Product. + | + |* You can define a collection (also known as baskets or buckets) of products using Product Collections. + | + """.stripMargin } diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index fe70fd0a5..2c6e39346 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -1221,8 +1221,8 @@ object ExampleValue { lazy val roleNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("role_name", roleNameExample) - lazy val refundExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) - glossaryItems += makeGlossaryItem("refund", refundExample) + lazy val termsAndConditionsUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + glossaryItems += makeGlossaryItem("terms_and_conditions_url_example", termsAndConditionsUrlExample) lazy val canAddUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_add_url", canAddUrlExample) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 1ab6bd33c..ab31a4e38 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -607,6 +607,7 @@ trait APIMethods220 { family = product.family, superFamily = product.super_family, moreInfoUrl = product.more_info_url, + termsAndConditionsUrl = null, details = product.details, description = product.description, metaLicenceId = product.meta.license.id, diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 1c2fb9480..2fa88b736 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -2430,22 +2430,6 @@ trait APIMethods310 { } } - - val productHiearchyAndCollectionNote = - """ - | - |Product hiearchy vs Product Collections: - | - |* You can define a hierarchy of products - so that a child Product inherits attributes of its parent Product - using the parent_product_code in Product. - | - |* You can define a collection (also known as baskets or buckets) of products using Product Collections. - | - """.stripMargin - - - val createProductEntitlements = canCreateProduct :: canCreateProductAtAnyBank :: Nil - val createProductEntitlementsRequiredText = UserHasMissingRoles + createProductEntitlements.mkString(" or ") - resourceDocs += ResourceDoc( createProduct, implementedInApiVersion, @@ -2511,6 +2495,7 @@ trait APIMethods310 { family = product.family, superFamily = product.super_family, moreInfoUrl = product.more_info_url, + termsAndConditionsUrl = null, details = product.details, description = product.description, metaLicenceId = product.meta.license.id, @@ -2526,8 +2511,6 @@ trait APIMethods310 { } - val getProductsIsPublic = APIUtil.getPropsAsBoolValue("apiOptions.getProductsIsPublic", true) - resourceDocs += ResourceDoc( getProduct, implementedInApiVersion, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 2d357104a..686c1e1ad 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -59,6 +59,7 @@ import code.views.Views import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global +import com.openbankproject.commons.dto.GetProductsParam import com.openbankproject.commons.model.enums.DynamicEntityOperation._ import com.openbankproject.commons.model.enums.{TransactionRequestStatus, _} import com.openbankproject.commons.model.{ListResult, _} @@ -9619,7 +9620,186 @@ trait APIMethods400 { } } } - + + staticResourceDocs += ResourceDoc( + getProducts, + implementedInApiVersion, + "getProducts", + "GET", + "/banks/BANK_ID/products", + "Get Products", + s"""Returns information about the financial products offered by a bank specified by BANK_ID including: + | + |* Name + |* Code + |* Parent Product Code + |* More info URL + |* Terms And Conditions URL + |* Description + |* Terms and Conditions + |* License the data under this endpoint is released under + | + |Can filter with attributes name and values. + |URL params example: /banks/some-bank-id/products?manager=John&count=8 + | + |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, + emptyObjectJson, + productsJsonV310, + List( + UserNotLoggedIn, + BankNotFound, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle) + ) + lazy val getProducts : OBPEndpoint = { + case "banks" :: BankId(bankId) :: "products" :: Nil JsonGet req => { + cc => { + for { + (_, callContext) <- getProductsIsPublic match { + case false => authenticatedAccess(cc) + case true => anonymousAccess(cc) + } + (_, callContext) <- NewStyle.function.getBank(bankId, callContext) + params = req.params.toList.map(kv => GetProductsParam(kv._1, kv._2)) + products <- Future(Connector.connector.vend.getProducts(bankId, params)) map { + unboxFullOrFail(_, callContext, ProductNotFoundByProductCode) + } + } yield { + (JSONFactory400.createProductsJson(products), HttpCode.`200`(callContext)) + } + } + } + } + + staticResourceDocs += ResourceDoc( + createProduct, + implementedInApiVersion, + nameOf(createProduct), + "PUT", + "/banks/BANK_ID/products/PRODUCT_CODE", + "Create Product", + s"""Create or Update Product for the Bank. + | + | + |Typical Super Family values / Asset classes are: + | + |Debt + |Equity + |FX + |Commodity + |Derivative + | + |$productHiearchyAndCollectionNote + | + | + |${authenticationRequiredMessage(true) } + | + | + |""", + putProductJsonV400, + productJsonV400, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canCreateProduct, canCreateProductAtAnyBank)) + ) + lazy val createProduct: OBPEndpoint = { + case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonPut json -> _ => { + cc => + for { + (Full(u), callContext) <- SS.user + _ <- NewStyle.function.hasAtLeastOneEntitlement(failMsg = createProductEntitlementsRequiredText)(bankId.value, u.userId, createProductEntitlements, callContext) + failMsg = s"$InvalidJsonFormat The Json body should be the $PutProductJsonV400 " + product <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[PutProductJsonV400] + } + parentProductCode <- product.parent_product_code.trim.nonEmpty match { + case false => + Future(Empty) + case true => + Future(Connector.connector.vend.getProduct(bankId, ProductCode(product.parent_product_code))) map { + getFullBoxOrFail(_, callContext, ParentProductNotFoundByProductCode + " {" + product.parent_product_code + "}", 400) + } + } + success <- Future(Connector.connector.vend.createOrUpdateProduct( + bankId = bankId.value, + code = productCode.value, + parentProductCode = parentProductCode.map(_.code.value).toOption, + name = product.name, + category = null, + family = null, + superFamily = null, + moreInfoUrl = product.more_info_url, + termsAndConditionsUrl = product.terms_and_conditions_url, + details = product.details, + description = product.description, + metaLicenceId = product.meta.license.id, + metaLicenceName = product.meta.license.name + )) map { + connectorEmptyResponse(_, callContext) + } + } yield { + (JSONFactory400.createProductJson(success), HttpCode.`201`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getProduct, + implementedInApiVersion, + nameOf(getProduct), + "GET", + "/banks/BANK_ID/products/PRODUCT_CODE", + "Get Bank Product", + s"""Returns information about a financial Product offered by the bank specified by BANK_ID and PRODUCT_CODE including: + | + |* Name + |* Code + |* Parent Product Code + |* Category + |* Family + |* Super Family + |* More info URL + |* Description + |* Terms and Conditions + |* License the data under this endpoint is released under + | + |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, + emptyObjectJson, + productJsonV400, + List( + UserNotLoggedIn, + $BankNotFound, + ProductNotFoundByProductCode, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle) + ) + + lazy val getProduct: OBPEndpoint = { + case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonGet _ => { + cc => { + for { + (_, callContext) <- getProductsIsPublic match { + case false => authenticatedAccess(cc) + case true => anonymousAccess(cc) + } + product <- Future(Connector.connector.vend.getProduct(bankId, productCode)) map { + unboxFullOrFail(_, callContext, ProductNotFoundByProductCode) + } + (productAttributes, callContext) <- NewStyle.function.getProductAttributesByBankAndCode(bankId, productCode, callContext) + } yield { + (JSONFactory400.createProductJson(product, productAttributes), HttpCode.`200`(callContext)) + } + } + } + } + } private def createDynamicEndpointMethod(bankId: Option[String], json: JValue, cc: CallContext) = { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 10e0f4110..43410ae72 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -28,7 +28,6 @@ package code.api.v4_0_0 import java.text.SimpleDateFormat import java.util.Date - import code.api.attributedefinition.AttributeDefinition import code.api.util.APIUtil import code.api.util.APIUtil.{DateWithDay, DateWithSeconds, stringOptionOrNull, stringOrNull} @@ -40,8 +39,8 @@ import code.api.v2_1_0.{IbanJson, JSONFactory210, PostCounterpartyBespokeJson, R import code.api.v2_2_0.CounterpartyMetadataJson import code.api.v3_0_0.JSONFactory300._ import code.api.v3_0_0._ -import code.api.v3_1_0.JSONFactory310.createAccountAttributeJson -import code.api.v3_1_0.{AccountAttributeResponseJson, RedisCallLimitJson} +import code.api.v3_1_0.JSONFactory310.{createAccountAttributeJson, createProductAttributesJson} +import code.api.v3_1_0.{AccountAttributeResponseJson, ProductAttributeResponseWithoutBankIdJson, RedisCallLimitJson} import code.apicollection.ApiCollectionTrait import code.apicollectionendpoint.ApiCollectionEndpointTrait import code.atms.Atms.Atm @@ -567,6 +566,31 @@ case class MySpaces( bank_ids: List[String], ) +case class ProductJsonV400( + bank_id: String, + code: String, + parent_product_code: String, + name: String, + more_info_url: String, + terms_and_conditions_url: String, + details: String, + description: String, + meta: MetaJsonV140, + product_attributes: Option[List[ProductAttributeResponseWithoutBankIdJson]] +) + +case class ProductsJsonV400(products: List[ProductJsonV400]) + +case class PutProductJsonV400( + bank_id: String, + parent_product_code: String, + name: String, + more_info_url: String, + terms_and_conditions_url: String, + details: String, + description: String, + meta: MetaJsonV140 +) case class CounterpartyJson400( name: String, description: String, @@ -1516,6 +1540,38 @@ object JSONFactory400 { balanceInquiryFee = Some(atmJsonV400.balance_inquiry_fee) ) } - + + def createProductJson(product: Product) : ProductJsonV400 = { + ProductJsonV400( + bank_id = product.bankId.toString, + code = product.code.value, + parent_product_code = product.parentProductCode.value, + name = product.name, + more_info_url = product.moreInfoUrl, + terms_and_conditions_url = product.moreInfoUrl, + details = product.details, + description = product.description, + meta = createMetaJson(product.meta), + None + ) + } + def createProductsJson(productsList: List[Product]) : ProductsJsonV400 = { + ProductsJsonV400(productsList.map(createProductJson)) + } + + def createProductJson(product: Product, productAttributes: List[ProductAttribute]) : ProductJsonV400 = { + ProductJsonV400( + bank_id = product.bankId.toString, + code = product.code.value, + parent_product_code = product.parentProductCode.value, + name = product.name, + more_info_url = product.moreInfoUrl, + terms_and_conditions_url = product.termsAndConditionsUrl, + details = product.details, + description = product.description, + meta = createMetaJson(product.meta), + product_attributes = Some(createProductAttributesJson(productAttributes)) + ) + } } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 3ba57d56a..22cc525da 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1588,6 +1588,7 @@ trait Connector extends MdcLoggable { family : String, superFamily : String, moreInfoUrl : String, + termsAndConditionsUrl : String, details : String, description : String, metaLicenceId : String, diff --git a/obp-api/src/main/scala/code/bankconnectors/KafkaMappedConnector_JVMcompatible.scala b/obp-api/src/main/scala/code/bankconnectors/KafkaMappedConnector_JVMcompatible.scala index 53bae7500..c1028d651 100644 --- a/obp-api/src/main/scala/code/bankconnectors/KafkaMappedConnector_JVMcompatible.scala +++ b/obp-api/src/main/scala/code/bankconnectors/KafkaMappedConnector_JVMcompatible.scala @@ -1140,11 +1140,12 @@ object KafkaMappedConnector_JVMcompatible extends Connector with KafkaHelper wit family : String, superFamily : String, moreInfoUrl : String, + termsAndConditionsUrl: String, details : String, description : String, metaLicenceId : String, metaLicenceName : String): Box[Product] = { - LocalMappedConnector.createOrUpdateProduct(bankId, code, parentProductCode, name, category, family, superFamily, moreInfoUrl, details, description, metaLicenceId, metaLicenceName) + LocalMappedConnector.createOrUpdateProduct(bankId, code, parentProductCode, name, category, family, superFamily, moreInfoUrl, termsAndConditionsUrl, details, description, metaLicenceId, metaLicenceName) } override def getProduct(bankId: BankId, productCode: ProductCode): Box[Product] = { diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index e937e25f3..05aa3fb03 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2721,6 +2721,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { family: String, superFamily: String, moreInfoUrl: String, + termsAndConditionsUrl: String, details: String, description: String, metaLicenceId: String, @@ -2742,6 +2743,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { .mFamily(family) .mSuperFamily(superFamily) .mMoreInfoUrl(moreInfoUrl) + .mTermsAndConditionsUrl(termsAndConditionsUrl) .mDetails(details) .mDescription(description) .mLicenseId(metaLicenceId) @@ -2759,6 +2761,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { .mFamily(family) .mSuperFamily(superFamily) .mMoreInfoUrl(moreInfoUrl) + .mTermsAndConditionsUrl(termsAndConditionsUrl) .mDetails(details) .mDescription(description) .mLicenseId(metaLicenceId) diff --git a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala index e75e60657..c6cf6583a 100644 --- a/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala +++ b/obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala @@ -2713,6 +2713,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, @@ -2750,6 +2751,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, @@ -5523,7 +5525,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { exampleInboundMessage = ( InBoundGetProductCollectionItemsTree(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List( ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, + data=List(ProductCollectionItemsTree(productCollectionItem= ProductCollectionItemCommons(collectionCode=collectionCodeExample.value, memberProductCode=memberProductCodeExample.value), product= ProductCommons(bankId=BankId(bankIdExample.value), code=ProductCode(productCodeExample.value), @@ -5533,6 +5535,7 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit { family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 28a738c7d..0e9d6b9eb 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -2852,6 +2852,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, @@ -2889,6 +2890,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, @@ -5720,6 +5722,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, diff --git a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala index 41d775ebd..cb349805f 100644 --- a/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/storedprocedure/StoredProcedureConnector_vDec2019.scala @@ -2833,6 +2833,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, @@ -2870,6 +2871,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, @@ -5701,6 +5703,7 @@ trait StoredProcedureConnector_vDec2019 extends Connector with MdcLoggable { family=familyExample.value, superFamily=superFamilyExample.value, moreInfoUrl=moreInfoUrlExample.value, + termsAndConditionsUrl=termsAndConditionsUrlExample.value, details=detailsExample.value, description=descriptionExample.value, meta=Meta( License(id=idExample.value, diff --git a/obp-api/src/main/scala/code/products/MappedProductsProvider.scala b/obp-api/src/main/scala/code/products/MappedProductsProvider.scala index 8c8584d1f..4c3fa601d 100644 --- a/obp-api/src/main/scala/code/products/MappedProductsProvider.scala +++ b/obp-api/src/main/scala/code/products/MappedProductsProvider.scala @@ -39,6 +39,7 @@ class MappedProduct extends Product with LongKeyedMapper[MappedProduct] with IdP object mFamily extends MappedString(this, 50) object mSuperFamily extends MappedString(this, 50) object mMoreInfoUrl extends MappedString(this, 2000) // use URL field? + object mTermsAndConditionsUrl extends MappedString(this, 2000) // use URL field? object mDetails extends MappedString(this, 2000) object mDescription extends MappedString(this, 2000) @@ -57,6 +58,7 @@ class MappedProduct extends Product with LongKeyedMapper[MappedProduct] with IdP override def family : String = mFamily.get override def superFamily : String = mSuperFamily.get override def moreInfoUrl: String = mMoreInfoUrl.get + override def termsAndConditionsUrl: String = mTermsAndConditionsUrl.get override def details: String = mDetails.get override def description: String = mDescription.get diff --git a/obp-api/src/test/scala/code/api/v1_4_0/ProductsTest.scala b/obp-api/src/test/scala/code/api/v1_4_0/ProductsTest.scala index 227c10fa8..f48be12c6 100644 --- a/obp-api/src/test/scala/code/api/v1_4_0/ProductsTest.scala +++ b/obp-api/src/test/scala/code/api/v1_4_0/ProductsTest.scala @@ -21,6 +21,7 @@ class ProductsTest extends ServerSetup with DefaultUsers with V140ServerSetup { family : String, superFamily : String, moreInfoUrl: String, + termsAndConditionsUrl: String, details: String, description: String, meta: Meta) extends Product @@ -40,11 +41,11 @@ class ProductsTest extends ServerSetup with DefaultUsers with V140ServerSetup { ) - val fakeProduct1 = ProductImpl(BankWithLicense, ProductCode("prod1"), ProductCode(""), "name 1", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo1.html", "", "", fakeMeta) - val fakeProduct2 = ProductImpl(BankWithLicense, ProductCode("prod2"), ProductCode(""), "name 2", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo2.html", "", "", fakeMeta) + val fakeProduct1 = ProductImpl(BankWithLicense, ProductCode("prod1"), ProductCode(""), "name 1", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo1.html", "http://www.example.com/termsAndConditionsUrl1.html","", "", fakeMeta) + val fakeProduct2 = ProductImpl(BankWithLicense, ProductCode("prod2"), ProductCode(""), "name 2", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo2.html", "http://www.example.com/termsAndConditionsUrl2.html", "","", fakeMeta) // Should not be returned (no license) - val fakeProduct3 = ProductImpl(BankWithoutLicense, ProductCode("prod3"), ProductCode(""), "name 3", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo3.html", "", "", fakeMetaNoLicense) + val fakeProduct3 = ProductImpl(BankWithoutLicense, ProductCode("prod3"), ProductCode(""), "name 3", "cat 1", "family 1", "super family 1", "http://www.example.com/moreinfo3.html", "http://www.example.com/termsAndConditionsUrl3.html", "","", fakeMetaNoLicense) // This mock provider is returning same branches for the fake banks diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala new file mode 100644 index 000000000..775dbaf08 --- /dev/null +++ b/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala @@ -0,0 +1,156 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH +Osloerstrasse 16/17 +Berlin 13359, Germany + +This product includes software developed at +TESOBE (http://www.tesobe.com/) + */ +package code.api.v4_0_0 + +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import code.api.util.ErrorMessages._ +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole._ +import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import code.entitlement.Entitlement +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.model.ErrorMessage +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write +import org.scalatest.Tag + +import scala.collection.immutable.{List, Nil} + +class ProductTest extends V400ServerSetup { + + override def beforeAll(): Unit = { + super.beforeAll() + } + + override def afterAll(): Unit = { + super.afterAll() + } + + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createProduct)) + object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getProduct)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getProducts)) + + lazy val testBankId = randomBankId + lazy val parentPutProductJsonV400: PutProductJsonV400 = SwaggerDefinitionsJSON.putProductJsonV400.copy(parent_product_code ="") + def createProduct(code: String, json: PutProductJsonV400) = { + When("We try to create a product v4.0.0") + val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / code).PUT <@ (user1) + val response400 = makePutRequest(request400, write(json)) + Then("We should get a 201") + response400.code should equal(201) + val product = response400.body.extract[ProductJsonV400] + product.code shouldBe code + product.parent_product_code shouldBe json.parent_product_code + product.bank_id shouldBe testBankId + product.name shouldBe json.name + product.more_info_url shouldBe json.more_info_url + product.terms_and_conditions_url shouldBe json.terms_and_conditions_url + product.details shouldBe json.details + product.description shouldBe json.description + product + } + + feature("Create Product v4.0.0") { + scenario("We will call the Add endpoint without a user credentials", ApiEndpoint1, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / "CODE").PUT + val response400 = makePutRequest(request400, write(parentPutProductJsonV400)) + Then("We should get a 401") + response400.code should equal(401) + And("error should be " + UserNotLoggedIn) + response400.body.extract[ErrorMessage].message should equal (UserNotLoggedIn) + } + scenario("We will call the Add endpoint without a proper role", ApiEndpoint1, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / "CODE").PUT <@(user1) + val response400 = makePutRequest(request400, write(parentPutProductJsonV400)) + Then("We should get a 403") + response400.code should equal(403) + val createProductEntitlements = canCreateProduct :: canCreateProductAtAnyBank :: Nil + val createProductEntitlementsRequiredText = UserHasMissingRoles + createProductEntitlements.mkString(" or ") + And("error should be " + createProductEntitlementsRequiredText) + response400.body.extract[ErrorMessage].message contains (createProductEntitlementsRequiredText) should be (true) + } + scenario("We will call the Add endpoint with user credentials and role", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, VersionOfApi) { + + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProduct.toString) + + // Create an grandparent + val grandparent: ProductJsonV400 = createProduct(code = "GRANDPARENT_CODE", json = parentPutProductJsonV400) + + // Create an parent + val product: ProductJsonV400 = createProduct(code = "PARENT_CODE", json = parentPutProductJsonV400.copy(parent_product_code = grandparent.code)) + + // Get + val requestGet400 = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.code ).GET <@(user1) + val responseGet400 = makeGetRequest(requestGet400) + Then("We should get a 200") + responseGet400.code should equal(200) + val product1 = responseGet400.body.extract[ProductJsonV400] + + // Create an child + val childPutProductJsonV400 = parentPutProductJsonV400.copy(parent_product_code = product.code) + createProduct(code = "PRODUCT_CODE", json = childPutProductJsonV400) + + // Get + val requestGetAll400 = (v4_0_0_Request / "banks" / product.bank_id / "products").GET <@(user1) + val responseGetAll400 = makeGetRequest(requestGetAll400) + Then("We should get a 200") + responseGetAll400.code should equal(200) + val products: ProductsJsonV400 = responseGetAll400.body.extract[ProductsJsonV400] + products.products.size shouldBe 3 + + } + scenario("Test the getProducts by url parameters", ApiEndpoint3, VersionOfApi) { + + When("We need to first create the products ") + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProduct.toString) + createProduct(code = "PRODUCT_CODE", json = parentPutProductJsonV400) + + + When("we grant the CanCreateProductAttribute role") + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProductAttribute.toString) + + val requestGetAll400 = (v4_0_0_Request / "banks" / testBankId / "products").GET <@(user1) + val responseGetAll400 = makeGetRequest(requestGetAll400) + Then("We should get a 200") + responseGetAll400.code should equal(200) + val products: ProductsJsonV400 = responseGetAll400.body.extract[ProductsJsonV400] + products.products.head.code should be ("PRODUCT_CODE") + + } + } + + +} diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala index cb58573d3..8dceecd5e 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala @@ -369,6 +369,7 @@ case class ProductCommons(bankId: BankId, family : String, superFamily : String, moreInfoUrl: String, + termsAndConditionsUrl: String, details: String, description: String, meta: Meta) extends Product diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala index a53d71265..367d90e75 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala @@ -380,6 +380,7 @@ trait Product { def family : String def superFamily : String def moreInfoUrl: String + def termsAndConditionsUrl: String def details :String def description: String def meta : Meta From 1e71df1b3234f7fe41ad38d67afefe4ab0003c5f Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 30 Aug 2021 16:47:36 +0200 Subject: [PATCH 067/293] test/obpV400 tweaked the tests for get/create products --- .../SwaggerDefinitionsJSON.scala | 1 - .../code/api/v4_0_0/JSONFactory4.0.0.scala | 3 +-- .../scala/code/api/v4_0_0/AccountTest.scala | 6 ++--- .../api/v4_0_0/DeleteProductCascadeTest.scala | 7 +++--- .../code/api/v4_0_0/V400ServerSetup.scala | 24 ++++++++----------- 5 files changed, 17 insertions(+), 24 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 0b548d85a..788ace8dc 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4351,7 +4351,6 @@ object SwaggerDefinitionsJSON { val productsJsonV400 = ProductsJsonV400(products = List(productJsonV400)) val putProductJsonV400 = PutProductJsonV400( - bank_id = bankIdExample.value, parent_product_code = "parent", name = "product name", more_info_url = moreInfoUrlExample.value, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 43410ae72..226547209 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -582,7 +582,6 @@ case class ProductJsonV400( case class ProductsJsonV400(products: List[ProductJsonV400]) case class PutProductJsonV400( - bank_id: String, parent_product_code: String, name: String, more_info_url: String, @@ -1548,7 +1547,7 @@ object JSONFactory400 { parent_product_code = product.parentProductCode.value, name = product.name, more_info_url = product.moreInfoUrl, - terms_and_conditions_url = product.moreInfoUrl, + terms_and_conditions_url = product.termsAndConditionsUrl, details = product.details, description = product.description, meta = createMetaJson(product.meta), diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala index 1e3130c4b..167cec5b3 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala @@ -196,15 +196,15 @@ class AccountTest extends V400ServerSetup { scenario("We will call the endpoint with user credentials", ApiEndpoint3, VersionOfApi) { val testBankId = randomBankId - val parentPostPutProductJsonV310: PostPutProductJsonV310 = SwaggerDefinitionsJSON.postPutProductJsonV310.copy(parent_product_code ="") + val putProductJsonV400: PutProductJsonV400 = SwaggerDefinitionsJSON.putProductJsonV400.copy(parent_product_code ="") val postAccountAttributeJson = accountAttributeJson When("We will first prepare the product") - val product: ProductJsonV310 = + val product: ProductJsonV400 = createProductViaEndpoint( bankId=testBankId, code=APIUtil.generateUUID(), - json=parentPostPutProductJsonV310 + json=putProductJsonV400 ) Then("We will prepare the account attribute") diff --git a/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala index 30ee154ae..42d83793e 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala @@ -60,14 +60,13 @@ class DeleteProductCascadeTest extends V400ServerSetup { scenario("We will call the endpoint with user credentials", ApiEndpoint1, VersionOfApi) { val testBankId = randomBankId - val parentPostPutProductJsonV310: PostPutProductJsonV310 = SwaggerDefinitionsJSON.postPutProductJsonV310.copy(parent_product_code ="") + val putProductJsonV400: PutProductJsonV400 = SwaggerDefinitionsJSON.putProductJsonV400.copy(parent_product_code ="") When("We first prepare the product") - val product: ProductJsonV310 = - createProductViaEndpoint( + val product = createProductViaEndpoint( bankId = testBankId, code = APIUtil.generateUUID(), - json = parentPostPutProductJsonV310 + json = putProductJsonV400 ) val addAccountJson = SwaggerDefinitionsJSON.createAccountRequestJsonV310 diff --git a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala index 88a1851c1..88e00d99c 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala @@ -132,20 +132,18 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { reply.body.extract[ViewJsonV300] } - def createProductViaEndpoint(bankId: String, code: String, json: PostPutProductJsonV310): ProductJsonV310 = { + def createProductViaEndpoint(bankId: String, code: String, json: PutProductJsonV400): ProductJsonV400 = { val entitlement = Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanCreateProduct.toString) - val request310 = (v4_0_0_Request / "banks" / bankId / "products" / code).PUT <@ (user1) - val response310 = makePutRequest(request310, write(json)) - response310.code should equal(201) - val product = response310.body.extract[ProductJsonV310] + val request400 = (v4_0_0_Request / "banks" / bankId / "products" / code).PUT <@ (user1) + val response400 = makePutRequest(request400, write(json)) + response400.code should equal(201) + val product = response400.body.extract[ProductJsonV400] product.code shouldBe code product.parent_product_code shouldBe json.parent_product_code product.bank_id shouldBe bankId product.name shouldBe json.name - product.category shouldBe json.category - product.super_family shouldBe json.super_family - product.family shouldBe json.family product.more_info_url shouldBe json.more_info_url + product.terms_and_conditions_url shouldBe json.terms_and_conditions_url product.details shouldBe json.details product.description shouldBe json.description Entitlement.entitlement.vend.deleteEntitlement(entitlement) @@ -153,22 +151,20 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { } def createAccountAttributeViaEndpoint(bankId: String, accountId: String, name: String, value: String, `type`: String): AccountAttributeResponseJson = { - val postPutProductJsonV310 = PostPutProductJsonV310( + val putProductJsonV400 = PutProductJsonV400( name = "product name", parent_product_code = "", - category = "category", - family = "family", - super_family = "super family", more_info_url = "www.example.com/prod1/more-info.html", + terms_and_conditions_url = "www.example.com/prod1/terms_and_conditions_url.html", details = "Details", description = "Description", meta = SwaggerDefinitionsJSON.metaJson ) - val product: ProductJsonV310 = + val product: ProductJsonV400 = createProductViaEndpoint( bankId=bankId, code=APIUtil.generateUUID(), - json=postPutProductJsonV310 + json=putProductJsonV400 ) val accountAttributeJson = AccountAttributeJson( name = name, From 9a47f989700b73065591e73e591b260d23df3faf Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 30 Aug 2021 17:25:51 +0200 Subject: [PATCH 068/293] test/fixed the failed jenkins tests --- .../RestConnector_vMar2019_frozen_meta_data | Bin 112121 -> 112154 bytes .../commons/dto/JsonsTransfer.scala | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_frozen_meta_data index e31fe3c316cf8ae1ca06984e853bbee82cf7338f..30914d25dd6b8bf4a8bb71884e586237287c2a0a 100644 GIT binary patch delta 47 zcmV+~0MP&W>js+a2CxFl0SuGs6e*J|%hDDVbY*gFb3txoLvL@6CZgW*~Y_s#r F2I}<0Pk2CxFl0SlAr6e*J|%hIzS%=_t-eGHfY diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala index 2a6d29180..5d6d94816 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala @@ -1228,7 +1228,7 @@ case class InBoundCreateOrUpdateAtmLegacy(status: Status, data: AtmTCommons) ext override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext() } -case class OutBoundCreateOrUpdateProduct(bankId: String, code: String, parentProductCode: Option[String], name: String, category: String, family: String, superFamily: String, moreInfoUrl: String, details: String, description: String, metaLicenceId: String, metaLicenceName: String) extends TopicTrait +case class OutBoundCreateOrUpdateProduct(bankId: String, code: String, parentProductCode: Option[String], name: String, category: String, family: String, superFamily: String, moreInfoUrl: String, termsAndConditionsUrl: String, details: String, description: String, metaLicenceId: String, metaLicenceName: String) extends TopicTrait case class InBoundCreateOrUpdateProduct(status: Status, data: ProductCommons) extends InBoundTrait[ProductCommons] { override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext() } From 59fe548077d52bcb361690af5fec9b88cc38a87c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 31 Aug 2021 09:11:35 +0200 Subject: [PATCH 069/293] feature/Redirect in case of invalid ser invitation link --- .../main/resources/i18n/lift-core.properties | 4 ++- .../main/scala/bootstrap/liftweb/Boot.scala | 1 + .../scala/code/snippet/UserInvitation.scala | 4 ++- .../main/webapp/user-invitation-invalid.html | 33 +++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 obp-api/src/main/webapp/user-invitation-invalid.html diff --git a/obp-api/src/main/resources/i18n/lift-core.properties b/obp-api/src/main/resources/i18n/lift-core.properties index 78afcf873..eceed845a 100644 --- a/obp-api/src/main/resources/i18n/lift-core.properties +++ b/obp-api/src/main/resources/i18n/lift-core.properties @@ -375,4 +375,6 @@ invalid.username=Invalid Username: \ 5) Usernames MUST NOT end with _ or . your.username.is.not.unique = Your username is not unique. Please enter a different one. -user.invitation.is.already.finished = Cannot complete your user invitation. Please check the invitation link. Your invitation could be invalid or completed. \ No newline at end of file +# Those 2 messages must have the same output in order to prevent leakage of information +user.invitation.is.already.finished = Looks like the invitation link is invalid. Still need help? Please send us a message using API Playground Support. +your.secret.link.is.not.valid = Looks like the invitation link is invalid. Still need help? Please send us a message using API Playground Support. \ No newline at end of file diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index a8240aa1d..050d9fea8 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -510,6 +510,7 @@ class Boot extends MdcLoggable { Menu("Validate OTP", "Validate OTP") / "otp" >> AuthUser.loginFirst, Menu("User Invitation", "User Invitation") / "user-invitation", Menu("User Invitation Info", "User Invitation Info") / "user-invitation-info", + Menu("User Invitation Invalid", "User Invitation Invalid") / "user-invitation-invalid", // Menu.i("Metrics") / "metrics", //TODO: allow this page once we can make the account number anonymous in the URL Menu.i("OAuth") / "oauth" / "authorize", //OAuth authorization page Menu.i("Consent") / "consent" >> AuthUser.loginFirst,//OAuth consent page diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 602296163..21f9ffb7d 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -166,13 +166,15 @@ class UserInvitation extends MdcLoggable { userInvitation match { case Full(payload) if payload.status == "CREATED" => // All good case _ => + // Clear all data firstNameVar.set("None") lastNameVar.set("None") devEmailVar.set("None") companyVar.set("None") countryVar.set("None") usernameVar.set("None") - S.error(Helper.i18n("user.invitation.is.already.finished")) + // and the redirect + S.redirectTo("/user-invitation-invalid") } register } diff --git a/obp-api/src/main/webapp/user-invitation-invalid.html b/obp-api/src/main/webapp/user-invitation-invalid.html new file mode 100644 index 000000000..94f7b82f4 --- /dev/null +++ b/obp-api/src/main/webapp/user-invitation-invalid.html @@ -0,0 +1,33 @@ + +
    +
    +

    Looks like the invitation link is invalid

    +

    Still need help? Please send us a message using API Playground Support.

    +
    +
    + + From 6d2e0c008451a1c2f43fe21e4db0b7c95e589102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 31 Aug 2021 09:49:13 +0200 Subject: [PATCH 070/293] feature/Change place of the check box marketing-info-label --- obp-api/src/main/webapp/user-invitation.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/webapp/user-invitation.html b/obp-api/src/main/webapp/user-invitation.html index dcc2fccb8..e2c9c78d9 100644 --- a/obp-api/src/main/webapp/user-invitation.html +++ b/obp-api/src/main/webapp/user-invitation.html @@ -74,16 +74,16 @@ Berlin 13359, Germany -
    - - -
    +
    + + +
    From 714e6539abcd369cdeade7320f53c32717c5a6a4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 31 Aug 2021 10:00:31 +0200 Subject: [PATCH 071/293] docfix/added the `space` to glossary --- obp-api/src/main/scala/code/api/util/Glossary.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 4f4e375b0..49b1d527b 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2170,6 +2170,15 @@ object Glossary extends MdcLoggable { | """) + glossaryItems += GlossaryItem( + title = "Space", + description = + s"""Space is actually relevant to one bank and all these bank's dynamic endpoints. + |The developer first creates his own bank and then creates the bank-level dynamic endpoints or entities. + |Then the developer can use the space to organise his new endpoints. + |He can grant the role CanReadDynamicResourceDocsAtOneBank to himself or others. + |Then they can see the new endpoints in API_Explorer under the Space menu.""".stripMargin) + /////////////////////////////////////////////////////////////////// // NOTE! Some glossary items are generated in ExampleValue.scala From e1524330a20f6cc61aaff2570688bd5e1c80c069 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 31 Aug 2021 10:27:07 +0200 Subject: [PATCH 072/293] refactor/rename System Resource to Static Resource --- .../ResourceDocs1_4_0/ResourceDocs140.scala | 14 ++--- .../ResourceDocsAPIMethods.scala | 24 +++++---- .../main/scala/code/api/util/ApiRole.scala | 4 +- .../ResourceDocs1_4_0/ResourceDocsTest.scala | 54 +++++++++---------- 4 files changed, 49 insertions(+), 47 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index 3890e0ee2..dfb177d47 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -12,7 +12,7 @@ object ResourceDocs140 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -28,7 +28,7 @@ object ResourceDocs200 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -44,7 +44,7 @@ object ResourceDocs210 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -59,7 +59,7 @@ object ResourceDocs220 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -74,7 +74,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -88,7 +88,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { @@ -104,7 +104,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getSystemResourceDocsObp + ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 20971728e..af9afb9b6 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -5,7 +5,7 @@ import code.api.OBPRestHelper import code.api.builder.OBP_APIBuilder import code.api.cache.Caching import code.api.util.APIUtil._ -import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc, canReadSystemResourceDoc} +import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc, canReadStaticResourceDoc} import code.api.util.ApiTag._ import code.api.util.ExampleValue.endpointMappingRequestBodyExample import code.api.util.{APIUtil, _} @@ -506,22 +506,22 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } localResourceDocs += ResourceDoc( - getSystemResourceDocsObp, + getStaticResourceDocsObp, implementedInApiVersion, - nameOf(getSystemResourceDocsObp), + nameOf(getStaticResourceDocsObp), "GET", - "/system-resource-docs/API_VERSION/obp", - "Get System Resource Docs", + "/static-resource-docs/API_VERSION/obp", + "Get Static Resource Docs", getResourceDocsDescription(false), emptyObjectJson, exampleResourceDocsJsonV400, UnknownError :: Nil, List(apiTagDocumentation, apiTagApi), - Some(List(canReadSystemResourceDoc)) + Some(List(canReadStaticResourceDoc)) ) - def getSystemResourceDocsObp : OBPEndpoint = { - case "system-resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { + def getStaticResourceDocsObp : OBPEndpoint = { + case "static-resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() cc => getApiLevelResourceDocs( @@ -538,6 +538,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } } + + //API level just mean, this response will be forward to liftweb directly. private def getApiLevelResourceDocs( cc: CallContext, requestedApiVersionString: String, @@ -548,7 +550,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth apiCollectionIdParam: Option[String], cacheModifierParam: Option[String], isVersion4OrHigher: Boolean, - isSystemResource: Boolean, + isStaticResource: Boolean, ) = { for { (u: Box[User], callContext: Option[CallContext]) <- resourceDocsRequireRole match { @@ -558,8 +560,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth _ <- resourceDocsRequireRole match { case false => Future() case true => // If set resource_docs_requires_role=true, we need check the the roles as well - if(isSystemResource) - NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadSystemResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadSystemResourceDoc :: Nil, cc.callContext) + if(isStaticResource) + NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadStaticResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadStaticResourceDoc :: Nil, cc.callContext) else NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc :: Nil, cc.callContext) } diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 25d2d7c76..a744fed8e 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -594,8 +594,8 @@ object ApiRole { case class CanReadResourceDoc(requiresBankId: Boolean = false) extends ApiRole lazy val canReadResourceDoc = CanReadResourceDoc() - case class CanReadSystemResourceDoc(requiresBankId: Boolean = false) extends ApiRole - lazy val canReadSystemResourceDoc = CanReadSystemResourceDoc() + case class CanReadStaticResourceDoc(requiresBankId: Boolean = false) extends ApiRole + lazy val canReadStaticResourceDoc = CanReadStaticResourceDoc() case class CanReadDynamicResourceDocsAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canReadDynamicResourceDocsAtOneBank = CanReadDynamicResourceDocsAtOneBank() diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index 121600189..0a32c05e2 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -24,7 +24,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with object ApiEndpoint1 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsObp)) object ApiEndpoint2 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsSwagger)) object ApiEndpoint3 extends Tag(nameOf(ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp)) - object ApiEndpoint4 extends Tag(nameOf(ImplementationsResourceDocs.getSystemResourceDocsObp)) + object ApiEndpoint4 extends Tag(nameOf(ImplementationsResourceDocs.getStaticResourceDocsObp)) override def beforeEach() = { @@ -704,7 +704,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with feature(s"test ${ApiEndpoint4.name} ") { scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v4.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -714,7 +714,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv4.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv4.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv4.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -724,7 +724,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v3.1.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.1.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -735,7 +735,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv3.1.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv3.1.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -745,7 +745,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v3.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -755,7 +755,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv3.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv3.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -765,7 +765,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v2.2.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.2.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -775,7 +775,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.2.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv2.2.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.2.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -785,7 +785,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v2.1.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.1.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -795,7 +795,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv2.1.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.1.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -805,7 +805,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v2.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -815,7 +815,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv2.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -825,7 +825,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.4.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.4.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") responseGetObp.body.extract[ResourceDocsJson] @@ -833,7 +833,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.4.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv1.4.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.4.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -843,7 +843,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.3.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.3.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -853,7 +853,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.3.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv1.3.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.3.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -863,7 +863,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.2.1" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.2.1" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -873,7 +873,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.2.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "OBPv1.2.1" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.2.1" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -884,7 +884,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "BGv1" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "BGv1" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -894,7 +894,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v1.3" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.3" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -904,7 +904,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "BGv1.3" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "BGv1.3" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -914,7 +914,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v3.1" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.1" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -924,7 +924,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } scenario(s"We will test ${ApiEndpoint1.name} Api -UKv3.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "UKv3.1" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "UKv3.1" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -937,7 +937,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with setPropsValues( "resource_docs_requires_role" -> "true", ) - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v4.0.0" / "obp").GET + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] @@ -949,13 +949,13 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with setPropsValues( "resource_docs_requires_role" -> "true", ) - val requestGetObp = (ResourceDocsV4_0Request / "system-resource-docs" / "v4.0.0" / "obp").GET <@ (user1) + val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET <@ (user1) val responseGetObp = makeGetRequest(requestGetObp) And("We should get 200 and the response can be extract to case classes") val responseDocs = responseGetObp.body.extract[ResourceDocsJson] responseGetObp.code should equal(403) responseGetObp.toString contains(UserHasMissingRoles) should be (true) - responseGetObp.toString contains( ApiRole.canReadSystemResourceDoc.toString()) should be (true) + responseGetObp.toString contains( ApiRole.canReadStaticResourceDoc.toString()) should be (true) } } From 2057c099d817f322c8d6b0b19965df9e5e07dd28 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 31 Aug 2021 12:00:46 +0200 Subject: [PATCH 073/293] feature/commented the getStaticResourceDocsObp endpoint first --- .../ResourceDocs1_4_0/ResourceDocs140.scala | 14 +- .../ResourceDocsAPIMethods.scala | 64 +-- .../ResourceDocs1_4_0/ResourceDocsTest.scala | 518 +++++++++--------- 3 files changed, 298 insertions(+), 298 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index dfb177d47..c9a87013d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -12,7 +12,7 @@ object ResourceDocs140 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -28,7 +28,7 @@ object ResourceDocs200 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -44,7 +44,7 @@ object ResourceDocs210 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -59,7 +59,7 @@ object ResourceDocs220 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -74,7 +74,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix{route}) @@ -88,7 +88,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { @@ -104,7 +104,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, - ImplementationsResourceDocs.getStaticResourceDocsObp +// ImplementationsResourceDocs.getStaticResourceDocsObp ) routes.foreach(route => { oauthServe(apiPrefix { diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index af9afb9b6..94dd1f2ab 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -505,38 +505,38 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } } - localResourceDocs += ResourceDoc( - getStaticResourceDocsObp, - implementedInApiVersion, - nameOf(getStaticResourceDocsObp), - "GET", - "/static-resource-docs/API_VERSION/obp", - "Get Static Resource Docs", - getResourceDocsDescription(false), - emptyObjectJson, - exampleResourceDocsJsonV400, - UnknownError :: Nil, - List(apiTagDocumentation, apiTagApi), - Some(List(canReadStaticResourceDoc)) - ) - - def getStaticResourceDocsObp : OBPEndpoint = { - case "static-resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { - val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() - cc => - getApiLevelResourceDocs( - cc,requestedApiVersionString, - tags, - partialFunctions, - languageParam, - Some(ContentParam.STATIC) ,//Note: here it set to default STATIC value. - apiCollectionIdParam, - cacheModifierParam, - true, - true - ) - } - } +// localResourceDocs += ResourceDoc( +// getStaticResourceDocsObp, +// implementedInApiVersion, +// nameOf(getStaticResourceDocsObp), +// "GET", +// "/static-resource-docs/API_VERSION/obp", +// "Get Static Resource Docs", +// getResourceDocsDescription(false), +// emptyObjectJson, +// exampleResourceDocsJsonV400, +// UnknownError :: Nil, +// List(apiTagDocumentation, apiTagApi), +// Some(List(canReadStaticResourceDoc)) +// ) +// +// def getStaticResourceDocsObp : OBPEndpoint = { +// case "static-resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { +// val (tags, partialFunctions, languageParam, contentParam, apiCollectionIdParam, cacheModifierParam) = ResourceDocsAPIMethodsUtil.getParams() +// cc => +// getApiLevelResourceDocs( +// cc,requestedApiVersionString, +// tags, +// partialFunctions, +// languageParam, +// Some(ContentParam.STATIC) ,//Note: here it set to default STATIC value. +// apiCollectionIdParam, +// cacheModifierParam, +// true, +// true +// ) +// } +// } //API level just mean, this response will be forward to liftweb directly. diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index 0a32c05e2..5d8a92e8e 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -24,7 +24,7 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with object ApiEndpoint1 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsObp)) object ApiEndpoint2 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsSwagger)) object ApiEndpoint3 extends Tag(nameOf(ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp)) - object ApiEndpoint4 extends Tag(nameOf(ImplementationsResourceDocs.getStaticResourceDocsObp)) +// object ApiEndpoint4 extends Tag(nameOf(ImplementationsResourceDocs.getStaticResourceDocsObp)) override def beforeEach() = { @@ -701,264 +701,264 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with } } - - feature(s"test ${ApiEndpoint4.name} ") { - scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv4.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv4.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.1.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - org.scalameta.logger.elem(responseGetObp) - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv3.1.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv3.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.2.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.2.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.2.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.1.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.1.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.1.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.0.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.4.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.4.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.4.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.3.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.3.0", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.3.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.2.1" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.2.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.2.1" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - - scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "BGv1" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.3" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "BGv1.3" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.1" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -UKv3.1", ApiEndpoint1, VersionOfApi) { - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "UKv3.1" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(200) - //This should not throw any exceptions - responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props", ApiEndpoint1, VersionOfApi) { - setPropsValues( - "resource_docs_requires_role" -> "true", - ) - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(401) - responseGetObp.toString contains(UserNotLoggedIn) should be (true) - } - - scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) { - setPropsValues( - "resource_docs_requires_role" -> "true", - ) - val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET <@ (user1) - val responseGetObp = makeGetRequest(requestGetObp) - And("We should get 200 and the response can be extract to case classes") - val responseDocs = responseGetObp.body.extract[ResourceDocsJson] - responseGetObp.code should equal(403) - responseGetObp.toString contains(UserHasMissingRoles) should be (true) - responseGetObp.toString contains( ApiRole.canReadStaticResourceDoc.toString()) should be (true) - } - - } +// +// feature(s"test ${ApiEndpoint4.name} ") { +// scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv4.0.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv4.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.1.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// org.scalameta.logger.elem(responseGetObp) +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.1.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv3.1.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv3.0.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv3.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.2.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.2.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.2.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.1.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.1.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.1.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v2.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv2.0.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv2.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.4.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.4.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.4.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.3.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.3.0", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.3.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.2.1" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv1.2.1", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "OBPv1.2.1" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "BGv1" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v1.3", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v1.3" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -BGv1.3", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "BGv1.3" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v3.1", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v3.1" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -UKv3.1", ApiEndpoint1, VersionOfApi) { +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "UKv3.1" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(200) +// //This should not throw any exceptions +// responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description)) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props", ApiEndpoint1, VersionOfApi) { +// setPropsValues( +// "resource_docs_requires_role" -> "true", +// ) +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(401) +// responseGetObp.toString contains(UserNotLoggedIn) should be (true) +// } +// +// scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) { +// setPropsValues( +// "resource_docs_requires_role" -> "true", +// ) +// val requestGetObp = (ResourceDocsV4_0Request / "static-resource-docs" / "v4.0.0" / "obp").GET <@ (user1) +// val responseGetObp = makeGetRequest(requestGetObp) +// And("We should get 200 and the response can be extract to case classes") +// val responseDocs = responseGetObp.body.extract[ResourceDocsJson] +// responseGetObp.code should equal(403) +// responseGetObp.toString contains(UserHasMissingRoles) should be (true) +// responseGetObp.toString contains( ApiRole.canReadStaticResourceDoc.toString()) should be (true) +// } +// +// } //Note: it is tricky to validate the swagger string, I just find this : https://github.com/swagger-api/swagger-parser/issues/718 //So follow it to call the `Validate` method: From 253bb7831b8a62e7f57daacc7577d5366e2f6703 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 31 Aug 2021 13:51:55 +0200 Subject: [PATCH 074/293] docfix/tweaked the doc for getResourceDocs --- .../ResourceDocsAPIMethods.scala | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 94dd1f2ab..84dff4440 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -433,15 +433,18 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth | | You can filter with api-collection-id, but api-collection-id can not be used with others together. If api-collection-id is used in URL, it will ignore all other parameters. | + | You can easily pass the cache, use different value for cache-modifier, eg: ?cache-modifier= 123 + | |See the Resource Doc endpoint for more information. | |Following are more examples: - |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v3.1.0/obp - |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v3.1.0/obp?tags=Account,Bank - |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v3.1.0/obp?functions=getBanks,bankById - |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v4.0.0/obp?language=zh - |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v4.0.0/obp?content=static,dynamic,all - |${getObpApiRoot}/v3.1.0$endpointBankIdPath/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp?tags=Account,Bank + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp?functions=getBanks,bankById + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp?language=zh + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp?content=static,dynamic,all + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp?api-collection-id=4e866c86-60c3-4268-a221-cb0bbf1ad221 + |${getObpApiRoot}/v4.0.0$endpointBankIdPath/resource-docs/v4.0.0/obp?cache-modifier=3141592653 | |
      |
    • operation_id is concatenation of "v", version and function and should be unique (used for DOM element IDs etc. maybe used to link to source code)
    • From 0b760fb0d41bf16ca0419617051d585de1617e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 1 Sep 2021 13:56:10 +0200 Subject: [PATCH 075/293] feature/Support Azure as the OpenID Connect Identity Provider --- obp-api/src/main/scala/code/api/OAuth2.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/obp-api/src/main/scala/code/api/OAuth2.scala b/obp-api/src/main/scala/code/api/OAuth2.scala index 83f811fe3..0ec4c7129 100644 --- a/obp-api/src/main/scala/code/api/OAuth2.scala +++ b/obp-api/src/main/scala/code/api/OAuth2.scala @@ -76,6 +76,8 @@ object OAuth2Login extends RestHelper with MdcLoggable { Google.applyRules(value, cc) } else if (Yahoo.isIssuer(value)) { Yahoo.applyRules(value, cc) + } else if (Azure.isIssuer(value)) { + Azure.applyRules(value, cc) } else { Hydra.applyRules(value, cc) } @@ -395,6 +397,18 @@ object OAuth2Login extends RestHelper with MdcLoggable { override def wellKnownOpenidConfiguration: URI = new URI("https://login.yahoo.com/.well-known/openid-configuration") override def urlOfJwkSets: Box[String] = checkUrlOfJwkSets(identityProvider = yahoo) def isIssuer(jwt: String): Boolean = isIssuer(jwtToken=jwt, identityProvider = yahoo) + } + + object Azure extends OAuth2Util { + val microsoft = "microsoft" + /** + * OpenID Connect Discovery. + * Yahoo exposes OpenID Connect discovery documents ( https://YOUR_DOMAIN/.well-known/openid-configuration ). + * These can be used to automatically configure applications. + */ + override def wellKnownOpenidConfiguration: URI = new URI("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration") + override def urlOfJwkSets: Box[String] = checkUrlOfJwkSets(identityProvider = microsoft) + def isIssuer(jwt: String): Boolean = isIssuer(jwtToken=jwt, identityProvider = microsoft) } } \ No newline at end of file From 76a8ce7723c89190d605b71f537c6ba4a1833234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 1 Sep 2021 14:56:54 +0200 Subject: [PATCH 076/293] bugfix/Fixed merge issues --- .../SwaggerDefinitionsJSON.scala | 2 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 54 +------------------ .../code/api/v4_0_0/JSONFactory4.0.0.scala | 33 +----------- 3 files changed, 4 insertions(+), 85 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 5b1f831ba..91c8de2f9 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -3551,7 +3551,7 @@ object SwaggerDefinitionsJSON { ) val productsJsonV310 = ProductsJsonV310(products = List(productJsonV310)) - val productJsonV400 = ProductJsonV400( + val productJsonV400b = ProductJsonV400b( bank_id = bankIdExample.value, code = "product_code", parent_product_code = "parent", diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 1b6b1eb0a..7d9c5f0fa 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5631,59 +5631,7 @@ trait APIMethods400 { } } - - val getProductsIsPublic = APIUtil.getPropsAsBoolValue("apiOptions.getProductsIsPublic", true) - - staticResourceDocs += ResourceDoc( - getProduct, - implementedInApiVersion, - "getProduct", - "GET", - "/banks/BANK_ID/products/PRODUCT_CODE", - "Get Bank Product", - s"""Returns information about a financial Product offered by the bank specified by BANK_ID and PRODUCT_CODE including: - | - |* Name - |* Code - |* Parent Product Code - |* Category - |* Family - |* Super Family - |* More info URL - |* Description - |* Terms and Conditions - |* License the data under this endpoint is released under - | - |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, - emptyObjectJson, - productJsonV400, - List( - UserNotLoggedIn, - ProductNotFoundByProductCode, - UnknownError - ), - List(apiTagProduct, apiTagNewStyle) - ) - - lazy val getProduct: OBPEndpoint = { - case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonGet _ => { - cc => { - for { - (_, callContext) <- getProductsIsPublic match { - case false => authenticatedAccess(cc) - case true => anonymousAccess(cc) - } - (_, callContext) <- NewStyle.function.getBank(bankId, callContext) - product <- Future(Connector.connector.vend.getProduct(bankId, productCode)) map { - unboxFullOrFail(_, callContext, ProductNotFoundByProductCode) - } - (productAttributes, callContext) <- NewStyle.function.getProductAttributesByBankAndCode(bankId, productCode, callContext) - } yield { - (JSONFactory400.createProductJson(product, productAttributes), HttpCode.`200`(callContext)) - } - } - } - } + staticResourceDocs += ResourceDoc( createOrUpdateTransactionAttributeDefinition, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 348ecac34..6f8badca6 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -678,7 +678,7 @@ case class JsonValidationV400(operation_id: String, json_schema: JsonSchemaV400) // Validation related END -case class ProductJsonV400(bank_id: String, +case class ProductJsonV400b(bank_id: String, code : String, parent_product_code : String, name : String, @@ -1433,36 +1433,7 @@ object JSONFactory400 { value = productAttribute.value, is_active = productAttribute.isActive ) - - def createProductAttributesJson(productAttributes: List[ProductAttribute]): List[ProductAttributeResponseWithoutBankIdJsonV400] = { - productAttributes.map( - productAttribute => - ProductAttributeResponseWithoutBankIdJsonV400( - product_code = productAttribute.productCode.value, - product_attribute_id = productAttribute.productAttributeId, - name = productAttribute.name, - `type` = productAttribute.attributeType.toString, - value = productAttribute.value, - is_active = productAttribute.isActive - ) - ) - } - def createProductJson(product: Product, productAttributes: List[ProductAttribute]) : ProductJsonV400 = { - ProductJsonV400( - bank_id = product.bankId.toString, - code = product.code.value, - parent_product_code = product.parentProductCode.value, - name = product.name, - category = product.category, - family = product.family, - super_family = product.superFamily, - more_info_url = product.moreInfoUrl, - details = product.details, - description = product.description, - meta = createMetaJson(product.meta), - product_attributes = Some(createProductAttributesJson(productAttributes)) - ) - } + def createApiCollectionEndpointsJsonV400(apiCollectionEndpoints: List[ApiCollectionEndpointTrait]) = { ApiCollectionEndpointsJson400(apiCollectionEndpoints.map(apiCollectionEndpoint => createApiCollectionEndpointJsonV400(apiCollectionEndpoint))) From db8cfaa01420863b1f8ea849f8e57e305b716cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 2 Sep 2021 10:40:13 +0200 Subject: [PATCH 077/293] feature/Azure as the OpenID Connect Identity Provider - add migrtion scripts --- .../code/api/util/migration/Migration.scala | 24 +++++++ .../util/migration/MigrationOfAuthUser.scala | 72 +++++++++++++++++++ .../migration/MigrationOfResourceUser.scala | 51 ++++++++++++- .../code/model/dataAccess/AuthUser.scala | 8 +-- .../code/model/dataAccess/ResourceUser.scala | 2 +- 5 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfAuthUser.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index b8fc85153..660a93130 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -82,6 +82,8 @@ object Migration extends MdcLoggable { deleteDuplicatedRowsInTheTableUserAuthContext() populateTheFieldDeletedAtResourceUser(startedBeforeSchemifier) populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier) + alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier) + alterColumnEmailAtResourceUser(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -259,6 +261,28 @@ object Migration extends MdcLoggable { } } } + private def alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfAuthUser.alterColumnUsernameProviderEmailFirstnameAndLastname(name) + } + } + } + private def alterColumnEmailAtResourceUser(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.alterColumnEmailAtResourceUser(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(alterColumnEmailAtResourceUser(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfResourceUser.alterColumnEmail(name) + } + } + } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfAuthUser.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfAuthUser.scala new file mode 100644 index 000000000..1e584fba3 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfAuthUser.scala @@ -0,0 +1,72 @@ +package code.api.util.migration + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} + +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.model.dataAccess.AuthUser +import net.liftweb.common.Full +import net.liftweb.mapper.{DB, Schemifier} +import net.liftweb.util.DefaultConnectionIdentifier + +object MigrationOfAuthUser { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def alterColumnUsernameProviderEmailFirstnameAndLastname(name: String): Boolean = { + DbFunction.tableExists(AuthUser, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val executedSql = + DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { + APIUtil.getPropsValue("db.driver") match { + case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") => + () => + """ + |ALTER TABLE authuser ALTER COLUMN username varchar(100); + |ALTER TABLE authuser ALTER COLUMN provider varchar(100); + |ALTER TABLE authuser ALTER COLUMN firstname varchar(100); + |ALTER TABLE authuser ALTER COLUMN lastname varchar(100); + |ALTER TABLE authuser ALTER COLUMN email varchar(100); + |""".stripMargin + case _ => + () => + """ + |ALTER TABLE authuser ALTER COLUMN username type varchar(100); + |ALTER TABLE authuser ALTER COLUMN provider type varchar(100); + |ALTER TABLE authuser ALTER COLUMN firstname type varchar(100); + |ALTER TABLE authuser ALTER COLUMN lastname type varchar(100); + |ALTER TABLE authuser ALTER COLUMN email type varchar(100); + |""".stripMargin + } + + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Executed SQL: + |$executedSql + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${AuthUser._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } + +} diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala index 40e798266..ab8cfe176 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfResourceUser.scala @@ -5,10 +5,11 @@ import java.time.{ZoneId, ZonedDateTime} import code.api.util.APIUtil import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.model.Consumer import code.model.dataAccess.ResourceUser -import code.model.{AppType, Consumer} -import net.liftweb.mapper.DB -import net.liftweb.util.{DefaultConnectionIdentifier, Helpers} +import net.liftweb.common.Full +import net.liftweb.mapper.{DB, Schemifier} +import net.liftweb.util.DefaultConnectionIdentifier object MigrationOfResourceUser { @@ -53,4 +54,48 @@ object MigrationOfResourceUser { isSuccessful } } + + def alterColumnEmail(name: String): Boolean = { + DbFunction.tableExists(ResourceUser, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val executedSql = + DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { + APIUtil.getPropsValue("db.driver") match { + case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") => + () => + """ALTER TABLE resourceuser ALTER COLUMN email varchar(100); + |""".stripMargin + case _ => + () => + """ALTER TABLE resourceuser ALTER COLUMN email type varchar(100); + |""".stripMargin + } + + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Executed SQL: + |$executedSql + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${ResourceUser._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } + } diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 5f258aea4..43f140839 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -89,7 +89,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with MdcLoggable { override lazy val firstName = new MyFirstName - protected class MyFirstName extends MappedString(this, 32) { + protected class MyFirstName extends MappedString(this, 100) { def isEmpty(msg: => String)(value: String): List[FieldError] = value match { case null => List(FieldError(this, Text(msg))) // issue 179 @@ -114,7 +114,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with MdcLoggable { override lazy val lastName = new MyLastName - protected class MyLastName extends MappedString(this, 32) { + protected class MyLastName extends MappedString(this, 100) { def isEmpty(msg: => String)(value: String): List[FieldError] = value match { case null => List(FieldError(this, Text(msg))) // issue 179 @@ -160,7 +160,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with MdcLoggable { * The username field for the User. */ lazy val username: userName = new userName() - class userName extends MappedString(this, 64) { + class userName extends MappedString(this, 100) { def isEmpty(msg: => String)(value: String): List[FieldError] = value match { case null => List(FieldError(this, Text(msg))) // issue 179 @@ -309,7 +309,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with MdcLoggable { * The provider field for the User. */ lazy val provider: userProvider = new userProvider() - class userProvider extends MappedString(this, 64) { + class userProvider extends MappedString(this, 100) { override def displayName = S.?("provider") override val fieldId = Some(Text("txtProvider")) } diff --git a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala index 82ed93bfc..6c8d72159 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala @@ -59,7 +59,7 @@ class ResourceUser extends LongKeyedMapper[ResourceUser] with User with ManyToMa object id extends MappedLongIndex(this) object userId_ extends MappedUUID(this) - object email extends MappedEmail(this, 48){ + object email extends MappedEmail(this, 100){ override def required_? = false } object name_ extends MappedString(this, 100){ From a826d9083df509e07fca2d979c5f34241e8eab0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 2 Sep 2021 11:38:19 +0200 Subject: [PATCH 078/293] refactor/Tweak Web UI props names --- obp-api/src/main/resources/props/sample.props.template | 4 ++-- obp-api/src/main/scala/code/snippet/UserInvitation.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index fc57c88d4..d28a83745 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -1032,8 +1032,8 @@ default_auth_context_update_request_key=CUSTOMER_NUMBER # User (Developer) Invitation webui_post_user_invitation_submit_button_value=Register as a Developer -webui_post_user_invitation_privacy_conditions_value=Privacy conditions.. -webui_post_user_invitation_terms_and_conditions_value=Terms and Conditions.. +webui_privacy_policy=Privacy conditions.. +webui_terms_and_conditions=Terms and Conditions.. webui_post_user_invitation_terms_and_conditions_checkbox_value=I agree to the above Developer Terms and Conditions webui_developer_user_invitation_email_html_text=\ diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 21f9ffb7d..59af4bc97 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -58,8 +58,8 @@ class UserInvitation extends MdcLoggable { val ttl = APIUtil.getPropsAsLongValue("user_invitation.ttl.seconds", 86400) val registrationConsumerButtonValue: String = getWebUiPropsValue("webui_post_user_invitation_submit_button_value", "Register as a Developer") - val privacyConditionsValue: String = getWebUiPropsValue("webui_post_user_invitation_privacy_conditions_value", "Privacy conditions..") - val termsAndConditionsValue: String = getWebUiPropsValue("webui_post_user_invitation_terms_and_conditions_value", "Terms and Conditions..") + val privacyConditionsValue: String = getWebUiPropsValue("webui_privacy_policy", "Privacy conditions..") + val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "Terms and Conditions..") val termsAndConditionsCheckboxValue: String = getWebUiPropsValue("webui_post_user_invitation_terms_and_conditions_checkbox_value", "I agree to the above Developer Terms and Conditions") def registerForm: CssSel = { From b2924ad7d9bbfaeaddb5b450baf3e9baf368d237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 2 Sep 2021 11:42:36 +0200 Subject: [PATCH 079/293] docfix/Add relase notes regarding renamed Web UI props --- release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release_notes.md b/release_notes.md index 4131790b9..0460b1794 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,9 @@ ### Most recent changes at top of file ``` Date Commit Action +02/09/2021 a826d908 Renamed Web UI props: + webui_post_user_invitation_privacy_conditions_value => webui_privacy_policy + webui_post_user_invitation_terms_and_conditions_value => webui_terms_and_conditions 20/08/2021 2ad1a3b0 Updated implementations of Akka, Rest and Stored Procedure connectors via the builder. 18/08/2021 83c3b4fa Added props: webui_favicon_link_url, default is /favicon.ico 18/08/2021 5924c820 Added props: webui_api_documentation_bottom_url, default is https://github.com/OpenBankProject/OBP-API/wiki From 76e7a9e4f3e4e1358825cf61a67abfe7b4db8b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 6 Sep 2021 14:27:19 +0200 Subject: [PATCH 080/293] refactor/Tweak User Agreement table in order to store differnet types of agreement text --- .../remotedata/RemotedataUserAgreement.scala | 7 +++-- .../RemotedataUserAgreementActor.scala | 10 +++++-- .../scala/code/snippet/UserInvitation.scala | 10 +++++-- .../main/scala/code/users/UserAgreement.scala | 29 ++++++++++++------- .../code/users/UserAgreementProvider.scala | 12 ++++---- 5 files changed, 44 insertions(+), 24 deletions(-) diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala index eb12787b9..9960f49a7 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala @@ -10,7 +10,10 @@ object RemotedataUserAgreement extends ObpActorInit with UserAgreementProvider { val cc = RemotedataUserAgreementProviderCaseClass - def createOrUpdateUserAgreement(userId: String, summary: String, agreementText: String, acceptMarketingInfo: Boolean): Box[UserAgreement] = getValueFromFuture( - (actor ? cc.createOrUpdateUserAgreement(userId, summary, agreementText, acceptMarketingInfo)).mapTo[Box[UserAgreement]] + def createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] = getValueFromFuture( + (actor ? cc.createOrUpdateUserAgreement(userId, agreementType, agreementText)).mapTo[Box[UserAgreement]] + ) + def createUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] = getValueFromFuture( + (actor ? cc.createOrUpdateUserAgreement(userId, agreementType, agreementText)).mapTo[Box[UserAgreement]] ) } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala index 0e7399898..cac3ddcb7 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala @@ -12,9 +12,13 @@ class RemotedataUserAgreementActor extends Actor with ObpActorHelper with MdcLog def receive: PartialFunction[Any, Unit] = { - case cc.createOrUpdateUserAgreement(userId: String, summary: String, agreementText: String, acceptMarketingInfo: Boolean) => - logger.debug(s"createOrUpdateUserAgreement($userId, $summary, $agreementText, $acceptMarketingInfo)") - sender ! (mapper.createOrUpdateUserAgreement(userId, summary, agreementText, acceptMarketingInfo)) + case cc.createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String) => + logger.debug(s"createOrUpdateUserAgreement($userId, $agreementType, $agreementText)") + sender ! (mapper.createOrUpdateUserAgreement(userId, agreementType, agreementText)) + + case cc.createUserAgreement(userId: String, agreementType: String, agreementText: String) => + logger.debug(s"createUserAgreement($userId, $agreementType, $agreementText)") + sender ! (mapper.createUserAgreement(userId, agreementType, agreementText)) case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 59af4bc97..804341d5b 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -58,8 +58,8 @@ class UserInvitation extends MdcLoggable { val ttl = APIUtil.getPropsAsLongValue("user_invitation.ttl.seconds", 86400) val registrationConsumerButtonValue: String = getWebUiPropsValue("webui_post_user_invitation_submit_button_value", "Register as a Developer") - val privacyConditionsValue: String = getWebUiPropsValue("webui_privacy_policy", "Privacy conditions..") - val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "Terms and Conditions..") + val privacyConditionsValue: String = getWebUiPropsValue("webui_privacy_policy", "Privacy conditions...") + val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "Terms and Conditions...") val termsAndConditionsCheckboxValue: String = getWebUiPropsValue("webui_post_user_invitation_terms_and_conditions_checkbox_value", "I agree to the above Developer Terms and Conditions") def registerForm: CssSel = { @@ -105,7 +105,11 @@ class UserInvitation extends MdcLoggable { createAuthUser(user = u, firstName = firstNameVar.is, lastName = lastNameVar.is, password = "") // Use Agreement table UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( - u.userId, privacyConditionsValue, termsAndConditionsValue, marketingInfoCheckboxVar.is) + u.userId, "privacy_conditions", privacyConditionsValue) + UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( + u.userId, "terms_and_conditions", termsAndConditionsValue) + UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( + u.userId, "accept_marketing_info", marketingInfoCheckboxVar.is.toString) // Set the status of the user invitation to "FINISHED" UserInvitationProvider.userInvitationProvider.vend.updateStatusOfUserInvitation(userInvitation.map(_.userInvitationId).getOrElse(""), "FINISHED") // Set a new password diff --git a/obp-api/src/main/scala/code/users/UserAgreement.scala b/obp-api/src/main/scala/code/users/UserAgreement.scala index b87ee9d43..9dc3439bd 100644 --- a/obp-api/src/main/scala/code/users/UserAgreement.scala +++ b/obp-api/src/main/scala/code/users/UserAgreement.scala @@ -9,29 +9,40 @@ import net.liftweb.common.{Box, Empty, Full} import net.liftweb.mapper._ object MappedUserAgreementProvider extends UserAgreementProvider { - override def createOrUpdateUserAgreement(userId: String, summary: String, agreementText: String, acceptMarketingInfo: Boolean): Box[UserAgreement] = { - UserAgreement.find(By(UserAgreement.UserId, userId)) match { + override def createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] = { + UserAgreement.find( + By(UserAgreement.UserId, userId), + By(UserAgreement.AgreementType, agreementType) + ) match { case Full(existingUser) => Full( existingUser - .Summary(summary) + .AgreementType(agreementType) .AgreementText(agreementText) - .AcceptMarketingInfo(acceptMarketingInfo) .saveMe() ) case Empty => Full( UserAgreement.create .UserId(userId) - .Summary(summary) + .AgreementType(agreementType) .AgreementText(agreementText) - .AcceptMarketingInfo(acceptMarketingInfo) .Date(new Date) .saveMe() ) case everythingElse => everythingElse } } + override def createUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] = { + Full( + UserAgreement.create + .UserId(userId) + .AgreementType(agreementType) + .AgreementText(agreementText) + .Date(new Date) + .saveMe() + ) + } } class UserAgreement extends UserAgreementTrait with LongKeyedMapper[UserAgreement] with IdPK with CreatedUpdated { @@ -42,19 +53,17 @@ class UserAgreement extends UserAgreementTrait with LongKeyedMapper[UserAgreemen } object UserId extends MappedString(this, 255) object Date extends MappedDate(this) - object Summary extends MappedText(this) + object AgreementType extends MappedString(this, 64) object AgreementText extends MappedText(this) object AgreementHash extends MappedString(this, 64) { override def defaultValue: String = HashUtil.Sha256Hash(AgreementText.get) } - object AcceptMarketingInfo extends MappedBoolean(this) override def userInvitationId: String = UserAgreementId.get override def userId: String = UserId.get - override def summary: String = Summary.get + override def agreementType: String = AgreementType.get override def agreementText: String = AgreementText.get override def agreementHash: String = AgreementHash.get - override def acceptMarketingInfo: Boolean = AcceptMarketingInfo.get } object UserAgreement extends UserAgreement with LongKeyedMetaMapper[UserAgreement] { diff --git a/obp-api/src/main/scala/code/users/UserAgreementProvider.scala b/obp-api/src/main/scala/code/users/UserAgreementProvider.scala index 76a077cec..85d57dbb2 100644 --- a/obp-api/src/main/scala/code/users/UserAgreementProvider.scala +++ b/obp-api/src/main/scala/code/users/UserAgreementProvider.scala @@ -1,8 +1,7 @@ package code.users import code.api.util.APIUtil -import code.remotedata.{RemotedataUserAgreement, RemotedataUserInvitation} -import com.openbankproject.commons.model.BankId +import code.remotedata.RemotedataUserAgreement import net.liftweb.common.Box import net.liftweb.util.SimpleInjector @@ -20,11 +19,13 @@ object UserAgreementProvider extends SimpleInjector { } trait UserAgreementProvider { - def createOrUpdateUserAgreement(userId: String, summary: String, agreementText: String, acceptMarketingInfo: Boolean): Box[UserAgreement] + def createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] + def createUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] } class RemotedataUserAgreementProviderCaseClass { - case class createOrUpdateUserAgreement(userId: String, summary: String, agreementText: String, acceptMarketingInfo: Boolean) + case class createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String) + case class createUserAgreement(userId: String, agreementType: String, agreementText: String) } object RemotedataUserAgreementProviderCaseClass extends RemotedataUserAgreementProviderCaseClass @@ -32,8 +33,7 @@ object RemotedataUserAgreementProviderCaseClass extends RemotedataUserAgreementP trait UserAgreementTrait { def userInvitationId: String def userId: String - def summary: String + def agreementType: String def agreementText: String def agreementHash: String - def acceptMarketingInfo: Boolean } \ No newline at end of file From 154e2e08377ef642808831ab4fea7985f38a43e9 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 6 Sep 2021 15:59:25 +0200 Subject: [PATCH 081/293] feature/OBPv400 added the `fees` fields to Product response body -step1 --- .../SwaggerDefinitionsJSON.scala | 52 +++++++++---------- .../scala/code/api/util/ExampleValue.scala | 6 +++ .../scala/code/api/v4_0_0/APIMethods400.scala | 2 +- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 47 +++++++++-------- .../scala/code/api/v4_0_0/AccountTest.scala | 2 +- .../api/v4_0_0/DeleteProductCascadeTest.scala | 4 +- .../scala/code/api/v4_0_0/ProductTest.scala | 11 ++-- .../code/api/v4_0_0/V400ServerSetup.scala | 10 ++-- 8 files changed, 69 insertions(+), 65 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 91c8de2f9..b98e892b9 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -3551,21 +3551,6 @@ object SwaggerDefinitionsJSON { ) val productsJsonV310 = ProductsJsonV310(products = List(productJsonV310)) - val productJsonV400b = ProductJsonV400b( - bank_id = bankIdExample.value, - code = "product_code", - parent_product_code = "parent", - name = "product name", - category = "category", - family = "family", - super_family = "super family", - more_info_url = "www.example.com/prod1/more-info.html", - details = "Details", - description = "Description", - meta = metaJson, - Some(List(productAttributeResponseWithoutBankIdJsonV400)) - ) - val productCollectionItemJsonV310 = ProductCollectionItemJsonV310(member_product_code = "A") val productCollectionJsonV310 = ProductCollectionJsonV310( collection_code = "C", @@ -4358,29 +4343,44 @@ object SwaggerDefinitionsJSON { val atmsJsonV400 = AtmsJsonV400(List(atmJsonV400)) + val feeJsonValue= FeeJsonValue( + currency = currencyExample.value, + amount = amountExample.value, + frequency = frequencyExample.value, + `type` = typeExample.value + ) + + val feeJson = FeeJson( + fee_id = feeIdExample.value, + name = nameExample.value, + isActive = true, + moreInfo = moreInfoExample.value, + value = feeJsonValue + ) + val productJsonV400 = ProductJsonV400( bank_id = bankIdExample.value, - code = "product_code", - parent_product_code = "parent", - name = "product name", + product_code = productCodeExample.value, + parent_product_code = parentProductCodeExample.value, + name = productNameExample.value, more_info_url = moreInfoUrlExample.value, terms_and_conditions_url = termsAndConditionsUrlExample.value, - details = "Details", - description = "Description", + description = descriptionExample.value, meta = metaJson, - Some(List(productAttributeResponseJson)) + attributes = Some(List(productAttributeResponseJson)), + fees = Some(List(feeJson)) ) val productsJsonV400 = ProductsJsonV400(products = List(productJsonV400)) val putProductJsonV400 = PutProductJsonV400( - parent_product_code = "parent", - name = "product name", + parent_product_code = parentProductCodeExample.value, + name = productNameExample.value, more_info_url = moreInfoUrlExample.value, terms_and_conditions_url = termsAndConditionsUrlExample.value, - details = "Details", - description = "Description", - meta = metaJson + description = descriptionExample.value, + meta = metaJson, + fees = Some(List()) ) diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 2c6e39346..265479dd4 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -1365,6 +1365,9 @@ object ExampleValue { lazy val parentProductCodeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("parent_product_code", parentProductCodeExample) + lazy val productNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + glossaryItems += makeGlossaryItem("product_name", productNameExample) + lazy val numberOfCheckbooksExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("number_of_checkbooks", numberOfCheckbooksExample) @@ -1602,6 +1605,9 @@ object ExampleValue { lazy val nameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("name", nameExample) + lazy val feeIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + glossaryItems += makeGlossaryItem("fee_id", nameExample) + lazy val emailAddressExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("email_address", emailAddressExample) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 7d9c5f0fa..b2f32162d 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9738,7 +9738,7 @@ trait APIMethods400 { superFamily = null, moreInfoUrl = product.more_info_url, termsAndConditionsUrl = product.terms_and_conditions_url, - details = product.details, + details = null, description = product.description, metaLicenceId = product.meta.license.id, metaLicenceName = product.meta.license.name diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 6f8badca6..dd372c5a7 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -568,27 +568,41 @@ case class MySpaces( case class ProductJsonV400( bank_id: String, - code: String, + product_code: String, parent_product_code: String, name: String, more_info_url: String, terms_and_conditions_url: String, - details: String, description: String, meta: MetaJsonV140, - product_attributes: Option[List[ProductAttributeResponseWithoutBankIdJson]] + attributes: Option[List[ProductAttributeResponseWithoutBankIdJson]], + fees: Option[List[FeeJson]] ) case class ProductsJsonV400(products: List[ProductJsonV400]) +case class FeeJsonValue( + currency: String, + amount: String, + frequency: String, + `type`: String, +) +case class FeeJson( + fee_id: String, + name: String, + isActive: Boolean, + moreInfo: String, + value:FeeJsonValue, +) + case class PutProductJsonV400( parent_product_code: String, name: String, more_info_url: String, terms_and_conditions_url: String, - details: String, description: String, - meta: MetaJsonV140 + meta: MetaJsonV140, + fees: Option[List[FeeJson]] ) case class CounterpartyJson400( name: String, @@ -677,19 +691,6 @@ case class JsonSchemaV400( case class JsonValidationV400(operation_id: String, json_schema: JsonSchemaV400) // Validation related END - -case class ProductJsonV400b(bank_id: String, - code : String, - parent_product_code : String, - name : String, - category: String, - family : String, - super_family : String, - more_info_url: String, - details: String, - description: String, - meta : MetaJsonV140, - product_attributes: Option[List[ProductAttributeResponseWithoutBankIdJsonV400]]) case class ProductAttributeJsonV400( name: String, `type`: String, @@ -1557,14 +1558,14 @@ object JSONFactory400 { def createProductJson(product: Product) : ProductJsonV400 = { ProductJsonV400( bank_id = product.bankId.toString, - code = product.code.value, + product_code = product.code.value, parent_product_code = product.parentProductCode.value, name = product.name, more_info_url = product.moreInfoUrl, terms_and_conditions_url = product.termsAndConditionsUrl, - details = product.details, description = product.description, meta = createMetaJson(product.meta), + None, None ) } @@ -1575,15 +1576,15 @@ object JSONFactory400 { def createProductJson(product: Product, productAttributes: List[ProductAttribute]) : ProductJsonV400 = { ProductJsonV400( bank_id = product.bankId.toString, - code = product.code.value, + product_code = product.code.value, parent_product_code = product.parentProductCode.value, name = product.name, more_info_url = product.moreInfoUrl, terms_and_conditions_url = product.termsAndConditionsUrl, - details = product.details, description = product.description, meta = createMetaJson(product.meta), - product_attributes = Some(createProductAttributesJson(productAttributes)) + attributes = Some(createProductAttributesJson(productAttributes)), + fees= None ) } } diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala index 167cec5b3..486f546a3 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala @@ -210,7 +210,7 @@ class AccountTest extends V400ServerSetup { Then("We will prepare the account attribute") Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateAccountAttributeAtOneBank.toString) When(s"We make a request $VersionOfApi") - val requestCreate310 = (v4_0_0_Request / "banks" / testBankId / "accounts" / testAccountId0.value / "products" / product.code / "attribute").POST <@(user1) + val requestCreate310 = (v4_0_0_Request / "banks" / testBankId / "accounts" / testAccountId0.value / "products" / product.product_code / "attribute").POST <@(user1) val responseCreate310 = makePostRequest(requestCreate310, write(postAccountAttributeJson)) Then("We should get a 201") responseCreate310.code should equal(201) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala index 42d83793e..500d47c48 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/DeleteProductCascadeTest.scala @@ -70,7 +70,7 @@ class DeleteProductCascadeTest extends V400ServerSetup { ) val addAccountJson = SwaggerDefinitionsJSON.createAccountRequestJsonV310 - .copy(user_id = resourceUser1.userId, balance = AmountOfMoneyJsonV121("EUR","0"), product_code = product.code, + .copy(user_id = resourceUser1.userId, balance = AmountOfMoneyJsonV121("EUR","0"), product_code = product.product_code, account_routings = List(AccountRoutingJsonV121(Random.nextString(10), Random.nextString(10)))) createAccountViaEndpoint(testBankId, addAccountJson, user1) @@ -78,7 +78,7 @@ class DeleteProductCascadeTest extends V400ServerSetup { Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, ApiRole.canDeleteProductCascade.toString) And("We make a request v4.0.0") val request400 = (v4_0_0_Request / "management" / "cascading" / "banks" / testBankId / - "products" / product.code).DELETE <@(user1) + "products" / product.product_code).DELETE <@(user1) Then("We should get a 200") makeDeleteRequest(request400).code should equal(200) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala index 775dbaf08..09f90c680 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/ProductTest.scala @@ -70,13 +70,12 @@ class ProductTest extends V400ServerSetup { Then("We should get a 201") response400.code should equal(201) val product = response400.body.extract[ProductJsonV400] - product.code shouldBe code + product.product_code shouldBe code product.parent_product_code shouldBe json.parent_product_code product.bank_id shouldBe testBankId product.name shouldBe json.name product.more_info_url shouldBe json.more_info_url product.terms_and_conditions_url shouldBe json.terms_and_conditions_url - product.details shouldBe json.details product.description shouldBe json.description product } @@ -110,17 +109,17 @@ class ProductTest extends V400ServerSetup { val grandparent: ProductJsonV400 = createProduct(code = "GRANDPARENT_CODE", json = parentPutProductJsonV400) // Create an parent - val product: ProductJsonV400 = createProduct(code = "PARENT_CODE", json = parentPutProductJsonV400.copy(parent_product_code = grandparent.code)) + val product: ProductJsonV400 = createProduct(code = "PARENT_CODE", json = parentPutProductJsonV400.copy(parent_product_code = grandparent.product_code)) // Get - val requestGet400 = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.code ).GET <@(user1) + val requestGet400 = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code ).GET <@(user1) val responseGet400 = makeGetRequest(requestGet400) Then("We should get a 200") responseGet400.code should equal(200) val product1 = responseGet400.body.extract[ProductJsonV400] // Create an child - val childPutProductJsonV400 = parentPutProductJsonV400.copy(parent_product_code = product.code) + val childPutProductJsonV400 = parentPutProductJsonV400.copy(parent_product_code = product.product_code) createProduct(code = "PRODUCT_CODE", json = childPutProductJsonV400) // Get @@ -147,7 +146,7 @@ class ProductTest extends V400ServerSetup { Then("We should get a 200") responseGetAll400.code should equal(200) val products: ProductsJsonV400 = responseGetAll400.body.extract[ProductsJsonV400] - products.products.head.code should be ("PRODUCT_CODE") + products.products.head.product_code should be ("PRODUCT_CODE") } } diff --git a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala index 88e00d99c..798eef150 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala @@ -138,14 +138,12 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { val response400 = makePutRequest(request400, write(json)) response400.code should equal(201) val product = response400.body.extract[ProductJsonV400] - product.code shouldBe code + product.product_code shouldBe code product.parent_product_code shouldBe json.parent_product_code product.bank_id shouldBe bankId product.name shouldBe json.name product.more_info_url shouldBe json.more_info_url product.terms_and_conditions_url shouldBe json.terms_and_conditions_url - product.details shouldBe json.details - product.description shouldBe json.description Entitlement.entitlement.vend.deleteEntitlement(entitlement) product } @@ -156,9 +154,9 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { parent_product_code = "", more_info_url = "www.example.com/prod1/more-info.html", terms_and_conditions_url = "www.example.com/prod1/terms_and_conditions_url.html", - details = "Details", description = "Description", - meta = SwaggerDefinitionsJSON.metaJson + meta = SwaggerDefinitionsJSON.metaJson, + fees = None ) val product: ProductJsonV400 = createProductViaEndpoint( @@ -173,7 +171,7 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { ) val entitlement = Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanCreateAccountAttributeAtOneBank.toString) val requestCreate310 = (v4_0_0_Request / "banks" / bankId / "accounts" / accountId / - "products" / product.code / "attribute").POST <@(user1) + "products" / product.product_code / "attribute").POST <@(user1) val responseCreate310 = makePostRequest(requestCreate310, write(accountAttributeJson)) Then("We should get a 201") responseCreate310.code should equal(201) From 2924d1a7223b0c40caf422ef370cb8f7ca24a0c0 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Mon, 6 Sep 2021 16:16:31 +0200 Subject: [PATCH 082/293] Updating Space glossary item. Added Dynamic Entity glossary item --- .../main/scala/code/api/util/Glossary.scala | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 49b1d527b..d1d947480 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2173,11 +2173,48 @@ object Glossary extends MdcLoggable { glossaryItems += GlossaryItem( title = "Space", description = - s"""Space is actually relevant to one bank and all these bank's dynamic endpoints. - |The developer first creates his own bank and then creates the bank-level dynamic endpoints or entities. - |Then the developer can use the space to organise his new endpoints. - |He can grant the role CanReadDynamicResourceDocsAtOneBank to himself or others. - |Then they can see the new endpoints in API_Explorer under the Space menu.""".stripMargin) + s"""In OBP, if you have access to a "Space", you have access to a set of Dynamic Endpoints and Dynamic Entities that belong to that Space. +|Internally, Spaces are defined as a "Banks" thus Spaces are synonymous with OBP Banks. +| +|A user can have access to several spaces. The API Explorer shows these under the Spaces menu. +| +|In order to see the documentation for the Dynamic Endpoints and Dynamic Entities, a user may need to have access to the CanReadDynamicResourceDocsAtOneBank Role. +| +|You can create your own Space by creating an OBP Bank. +| +""".stripMargin) + + + glossaryItems += GlossaryItem( + title = "Dynamic Entity", + description = + s"""If you want to create, store and custom data in OBP, you can create "Dynamic Entities". +|You define your Dynamic Entities in JSON. +| +|Fields are typed, have an example value and a (markdown) description. They can also be constrained in size. +| +|You can also create field "references" to other fields in other Entities. These are like foreign keys to other Dynamic or Static (built in) entities. +|In other words, if you create an Entity called X which has a field called A, you can force the values of X.A to match the values of Y.B where Y is another Dynamic Entity or Z.B where Z is a Static (OBP) Entity. +| +|Dynamic Entities can be created at the System level (bank_id is null) - or Bank / Space level (bank_id is not null). You might want to create Bank level Dynamic Entities in order to grant automated roles based on user email domain. +| +|Upon successful creation of a Dynamic Entity, OBP automatically: +| +|*Creates Create, Read, Update and Delete endpoints to operate on the Entity so you can insert, get, modify and delete records. +|*Creates Roles to guard the above endpoints. +| +|Following the creation of a Dynamic Entity you will need to grant yourself or others the appropriate roles before you can insert or get records. +| +|Each Dynamic Entity gets a dynamicEntityId which uniquely identifies it and the userId which identifies the user who created the Entity. +| +|For more information see the endpoints. +| +|The following videos are available: +| +| * [Introduction to Dynamic Entities](https://vimeo.com/426524451) +| * [Features of Dynamic Entities](https://vimeo.com/446465797) +| +""".stripMargin) /////////////////////////////////////////////////////////////////// From 29ac83020ff79690a630dfb728ac4751c4e355f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 6 Sep 2021 16:25:25 +0200 Subject: [PATCH 083/293] feature/Create terms and conditions page --- .../main/scala/bootstrap/liftweb/Boot.scala | 1 + .../src/main/scala/code/snippet/WebUI.scala | 8 ++++- .../src/main/webapp/terms-and-conditions.html | 36 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/main/webapp/terms-and-conditions.html diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 050d9fea8..e055aa889 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -511,6 +511,7 @@ class Boot extends MdcLoggable { Menu("User Invitation", "User Invitation") / "user-invitation", Menu("User Invitation Info", "User Invitation Info") / "user-invitation-info", Menu("User Invitation Invalid", "User Invitation Invalid") / "user-invitation-invalid", + Menu("Terms and Conditions", "Terms and Conditions") / "terms-and-conditions", // Menu.i("Metrics") / "metrics", //TODO: allow this page once we can make the account number anonymous in the URL Menu.i("OAuth") / "oauth" / "authorize", //OAuth authorization page Menu.i("Consent") / "consent" >> AuthUser.loginFirst,//OAuth consent page diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index 2a3b018d9..5be3cf779 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -63,6 +63,8 @@ class WebUI extends MdcLoggable{ } } + + // Cookie Consent button. // Note we don't currently (7th Jan 2017) need to display the cookie consent message due to our limited use of cookies // If a deployment does make more use of cookies we would need to add a No button and we might want to make use of the @@ -198,7 +200,11 @@ class WebUI extends MdcLoggable{ // Terms&Conditions def termsAndConditions: CssSel = { - ".termsAndConditions-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_agree_terms_url", "")) + ".termsAndConditions-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_agree_terms_url", "/terms-and-conditions")) + } + def termsAndConditionsText = { + val webUiPropsValue = getWebUiPropsValue("webui_terms_and_conditions", "") + "#terms-and-conditions-page" #> scala.xml.Unparsed(makeHtml(webUiPropsValue)) } // Points to the documentation. Probably a sandbox specific link is good. diff --git a/obp-api/src/main/webapp/terms-and-conditions.html b/obp-api/src/main/webapp/terms-and-conditions.html new file mode 100644 index 000000000..0c653baf8 --- /dev/null +++ b/obp-api/src/main/webapp/terms-and-conditions.html @@ -0,0 +1,36 @@ + +
      +
      +
      +
      +
      +
      +
      +
      +
      + + From 37f9f2db1e8e67f140a84cbdb7fad1d3eeeeb022 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 6 Sep 2021 23:57:22 +0200 Subject: [PATCH 084/293] refactor/typo --- .../api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 2 +- obp-api/src/main/scala/code/api/util/NewStyle.scala | 4 ++-- .../scala/code/bankconnectors/LocalMappedConnector.scala | 8 ++++---- .../productattribute/MappedProductAttributeProvider.scala | 6 +++--- .../scala/code/productattribute/ProductAttribute.scala | 4 ++-- .../code/remotedata/RemotedataProductAttribute.scala | 2 +- .../code/remotedata/RemotedataProductAttributeActor.scala | 6 +++--- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index b98e892b9..9db31db3d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4380,7 +4380,7 @@ object SwaggerDefinitionsJSON { terms_and_conditions_url = termsAndConditionsUrlExample.value, description = descriptionExample.value, meta = metaJson, - fees = Some(List()) + fees = Some(List(feeJson)) ) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 946ce3c04..7fe6cad8c 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1320,7 +1320,7 @@ object NewStyle { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean], callContext: Option[CallContext] @@ -1330,7 +1330,7 @@ object NewStyle { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean], callContext: Option[CallContext] diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 05aa3fb03..da4c7559f 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -3403,7 +3403,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean], callContext: Option[CallContext] @@ -3413,7 +3413,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]) map { (_, callContext) } @@ -3460,7 +3460,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { productCode: ProductCode, accountAttributeId: Option[String], name: String, - attributType: AccountAttributeType.Value, + attributeType: AccountAttributeType.Value, value: String, callContext: Option[CallContext] ): OBPReturnType[Box[AccountAttribute]] = { @@ -3469,7 +3469,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { productCode: ProductCode, accountAttributeId: Option[String], name: String, - attributType: AccountAttributeType.Value, + attributeType: AccountAttributeType.Value, value: String) map { (_, callContext) } diff --git a/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala b/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala index 8017b1932..531bf98ba 100644 --- a/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala +++ b/obp-api/src/main/scala/code/productattribute/MappedProductAttributeProvider.scala @@ -30,7 +30,7 @@ object MappedProductAttributeProvider extends ProductAttributeProvider { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]): Future[Box[ProductAttribute]] = { productAttributeId match { @@ -40,7 +40,7 @@ object MappedProductAttributeProvider extends ProductAttributeProvider { attribute.mBankId(bankId.value) .mCode(productCode.value) .mName(name) - .mType(attributType.toString) + .mType(attributeType.toString) .mValue(value) .IsActive(isActive.getOrElse(true)) .saveMe() @@ -54,7 +54,7 @@ object MappedProductAttributeProvider extends ProductAttributeProvider { .mBankId(bankId.value) .mCode(productCode.value) .mName(name) - .mType(attributType.toString()) + .mType(attributeType.toString()) .mValue(value) .IsActive(isActive.getOrElse(true)) .saveMe() diff --git a/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala b/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala index 15286ed11..676df827f 100644 --- a/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala +++ b/obp-api/src/main/scala/code/productattribute/ProductAttribute.scala @@ -46,7 +46,7 @@ trait ProductAttributeProvider { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]): Future[Box[ProductAttribute]] def deleteProductAttribute(productAttributeId: String): Future[Box[Boolean]] @@ -62,7 +62,7 @@ class RemotedataProductAttributeCaseClasses { productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]) diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala index f9f46cd23..b96b86404 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttribute.scala @@ -19,7 +19,7 @@ object RemotedataProductAttribute extends ObpActorInit with ProductAttributeProv override def getProductAttributeById(productAttributeId: String): Future[Box[ProductAttribute]] = (actor ? cc.getProductAttributeById(productAttributeId)).mapTo[Box[ProductAttribute]] - override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, attributType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]): Future[Box[ProductAttribute]] = (actor ? cc.createOrUpdateProductAttribute(bankId, productCode, productAttributeId , name , attributType , value, isActive)).mapTo[Box[ProductAttribute]] + override def createOrUpdateProductAttribute(bankId: BankId, productCode: ProductCode, productAttributeId: Option[String], name: String, attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]): Future[Box[ProductAttribute]] = (actor ? cc.createOrUpdateProductAttribute(bankId, productCode, productAttributeId , name , attributeType , value, isActive)).mapTo[Box[ProductAttribute]] override def deleteProductAttribute(productAttributeId: String): Future[Box[Boolean]] = (actor ? cc.deleteProductAttribute(productAttributeId)).mapTo[Box[Boolean]] } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala index 753cbb693..35e178261 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataProductAttributeActor.scala @@ -30,15 +30,15 @@ class RemotedataProductAttributeActor extends Actor with ObpActorHelper with Mdc productCode: ProductCode, productAttributeId: Option[String], name: String, - attributType: ProductAttributeType.Value, + attributeType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]) => - logger.debug(s"createOrUpdateProductAttribute(${bankId}, ${productCode}, ${productAttributeId}, ${name}, ${attributType}, ${value}, ${isActive})") + logger.debug(s"createOrUpdateProductAttribute(${bankId}, ${productCode}, ${productAttributeId}, ${name}, ${attributeType}, ${value}, ${isActive})") mapper.createOrUpdateProductAttribute(bankId, productCode, productAttributeId, name, - attributType, + attributeType, value, isActive) pipeTo sender From f9611b87309a304d3886e929e3033787f46f2695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 7 Sep 2021 10:04:13 +0200 Subject: [PATCH 085/293] feature/Create privacy policy page --- .../main/scala/bootstrap/liftweb/Boot.scala | 1 + .../src/main/scala/code/snippet/WebUI.scala | 6 +++- obp-api/src/main/webapp/privacy-policy.html | 36 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/main/webapp/privacy-policy.html diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index e055aa889..bcad10509 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -512,6 +512,7 @@ class Boot extends MdcLoggable { Menu("User Invitation Info", "User Invitation Info") / "user-invitation-info", Menu("User Invitation Invalid", "User Invitation Invalid") / "user-invitation-invalid", Menu("Terms and Conditions", "Terms and Conditions") / "terms-and-conditions", + Menu("Privacy Policy", "Privacy Policy") / "privacy-policy", // Menu.i("Metrics") / "metrics", //TODO: allow this page once we can make the account number anonymous in the URL Menu.i("OAuth") / "oauth" / "authorize", //OAuth authorization page Menu.i("Consent") / "consent" >> AuthUser.loginFirst,//OAuth consent page diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index 5be3cf779..b5de7c2c9 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -209,7 +209,11 @@ class WebUI extends MdcLoggable{ // Points to the documentation. Probably a sandbox specific link is good. def privacyPolicyLink: CssSel = { - ".privacy-policy-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_privacy_policy_url", "https://openbankproject.com/privacy-policy")) + ".privacy-policy-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_privacy_policy_url", "/privacy-policy")) + } + def privacyPolicyText = { + val webUiPropsValue = getWebUiPropsValue("webui_privacy_policy", "") + "#privacy-policy-page" #> scala.xml.Unparsed(makeHtml(webUiPropsValue)) } def sandboxIntroductionLink: CssSel = { diff --git a/obp-api/src/main/webapp/privacy-policy.html b/obp-api/src/main/webapp/privacy-policy.html new file mode 100644 index 000000000..d831ae849 --- /dev/null +++ b/obp-api/src/main/webapp/privacy-policy.html @@ -0,0 +1,36 @@ + +
      +
      +
      +
      +
      +
      +
      +
      +
      + + From 0f448d2efb9ca4edb2ea470c521494098143310d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 7 Sep 2021 13:32:23 +0200 Subject: [PATCH 086/293] feature/Tweak User Invitation page regarding terms and policy --- .../main/resources/props/sample.props.template | 4 ++-- .../scala/code/snippet/UserInvitation.scala | 6 ++---- .../main/scala/code/snippet/WebUITemplate.scala | 15 +++++++++++++++ obp-api/src/main/webapp/user-invitation.html | 17 ++++++++++++----- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index d28a83745..2b8317b83 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -1032,8 +1032,8 @@ default_auth_context_update_request_key=CUSTOMER_NUMBER # User (Developer) Invitation webui_post_user_invitation_submit_button_value=Register as a Developer -webui_privacy_policy=Privacy conditions.. -webui_terms_and_conditions=Terms and Conditions.. +webui_privacy_policy= +webui_terms_and_conditions= webui_post_user_invitation_terms_and_conditions_checkbox_value=I agree to the above Developer Terms and Conditions webui_developer_user_invitation_email_html_text=\ diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 804341d5b..94b18e002 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -58,8 +58,8 @@ class UserInvitation extends MdcLoggable { val ttl = APIUtil.getPropsAsLongValue("user_invitation.ttl.seconds", 86400) val registrationConsumerButtonValue: String = getWebUiPropsValue("webui_post_user_invitation_submit_button_value", "Register as a Developer") - val privacyConditionsValue: String = getWebUiPropsValue("webui_privacy_policy", "Privacy conditions...") - val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "Terms and Conditions...") + val privacyConditionsValue: String = getWebUiPropsValue("webui_privacy_policy", "") + val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "") val termsAndConditionsCheckboxValue: String = getWebUiPropsValue("webui_post_user_invitation_terms_and_conditions_checkbox_value", "I agree to the above Developer Terms and Conditions") def registerForm: CssSel = { @@ -158,9 +158,7 @@ class UserInvitation extends MdcLoggable { "#companyName" #> SHtml.text(companyVar.is, companyVar(_)) & "#devEmail" #> SHtml.text(devEmailVar, devEmailVar(_)) & "#username" #> SHtml.text(usernameVar, usernameVar(_)) & - "#privacy" #> SHtml.textarea(privacyConditionsValue, privacyConditionsValue => privacyConditionsValue) & "#privacy_checkbox" #> SHtml.checkbox(privacyCheckboxVar, privacyCheckboxVar(_)) & - "#terms" #> SHtml.textarea(termsAndConditionsValue, termsAndConditionsValue => termsAndConditionsValue) & "#terms_checkbox" #> SHtml.checkbox(termsCheckboxVar, termsCheckboxVar(_)) & "#marketing_info_checkbox" #> SHtml.checkbox(marketingInfoCheckboxVar, marketingInfoCheckboxVar(_)) & "type=submit" #> SHtml.submit(s"$registrationConsumerButtonValue", () => submitButtonDefense) diff --git a/obp-api/src/main/scala/code/snippet/WebUITemplate.scala b/obp-api/src/main/scala/code/snippet/WebUITemplate.scala index 98858c9ab..229e146bc 100644 --- a/obp-api/src/main/scala/code/snippet/WebUITemplate.scala +++ b/obp-api/src/main/scala/code/snippet/WebUITemplate.scala @@ -82,4 +82,19 @@ object WebUITemplate { | | |""".stripMargin + + webUIDoc += WebUIDoc( + webUiPropsName = "webui_terms_and_conditions", + defaultValue = "", + typeOfValue = "markdown", + placeholders = List() + ) + + webUIDoc += WebUIDoc( + webUiPropsName = "webui_privacy_policy", + defaultValue = "", + typeOfValue = "markdown", + placeholders = List() + ) + } diff --git a/obp-api/src/main/webapp/user-invitation.html b/obp-api/src/main/webapp/user-invitation.html index e2c9c78d9..29bd87f1d 100644 --- a/obp-api/src/main/webapp/user-invitation.html +++ b/obp-api/src/main/webapp/user-invitation.html @@ -68,18 +68,25 @@ Berlin 13359, Germany +
      - - - +
      + Privacy Policy +
      +
      +
      +
      - - +
      + Terms and Conditions +
      +
      +
      From 2f0995cd160cb2d560b582cdcaa0abe1878da8e2 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 7 Sep 2021 16:28:52 +0200 Subject: [PATCH 087/293] feature/OBPv400 added the `fees` fields to Product response body -step2 --- .../main/scala/bootstrap/liftweb/Boot.scala | 6 +- .../SwaggerDefinitionsJSON.scala | 2 +- .../main/scala/code/api/util/NewStyle.scala | 51 ++++++- .../scala/code/api/v4_0_0/APIMethods400.scala | 18 ++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 49 +++++- .../scala/code/bankconnectors/Connector.scala | 23 ++- .../bankconnectors/LocalMappedConnector.scala | 40 +++++ .../productfee/MappedProductFeeProvider.scala | 140 ++++++++++++++++++ .../code/productfee/ProductAttribute.scala | 76 ++++++++++ .../commons/model/CommonModelTrait.scala | 15 +- 10 files changed, 403 insertions(+), 17 deletions(-) create mode 100644 obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala create mode 100644 obp-api/src/main/scala/code/productfee/ProductAttribute.scala diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 050d9fea8..b6265d8cd 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -29,7 +29,6 @@ package bootstrap.liftweb import java.io.{File, FileInputStream} import java.util.stream.Collectors import java.util.{Locale, TimeZone} - import code.CustomerDependants.MappedCustomerDependant import code.DynamicData.DynamicData import code.DynamicEndpoint.DynamicEndpoint @@ -105,6 +104,7 @@ import code.dynamicMessageDoc.DynamicMessageDoc import code.dynamicResourceDoc.DynamicResourceDoc import code.endpointMapping.EndpointMapping import code.endpointTag.EndpointTag +import code.productfee.MappedProductFee import code.snippet.{OAuthAuthorisation, OAuthWorkedThanks} import code.socialmedia.MappedSocialMedia import code.standingorders.StandingOrder @@ -130,6 +130,7 @@ import code.webuiprops.WebUiProps import com.openbankproject.commons.model.ErrorMessage import com.openbankproject.commons.util.Functions.Implicits._ import com.openbankproject.commons.util.{ApiVersion, Functions} + import javax.mail.{Authenticator, PasswordAuthentication} import javax.mail.internet.MimeMessage import net.liftweb.common._ @@ -945,7 +946,8 @@ object ToSchemify { ConnectorMethod, DynamicResourceDoc, DynamicMessageDoc, - EndpointTag + EndpointTag, + MappedProductFee )++ APIBuilder_Connector.allAPIBuilderModels // start grpc server diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 9db31db3d..5dddb00b7 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4345,7 +4345,7 @@ object SwaggerDefinitionsJSON { val feeJsonValue= FeeJsonValue( currency = currencyExample.value, - amount = amountExample.value, + amount = 10.12, frequency = frequencyExample.value, `type` = typeExample.value ) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 7fe6cad8c..5e3b335ae 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -47,7 +47,7 @@ import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatu import com.openbankproject.commons.model.enums._ import com.openbankproject.commons.model.{AccountApplication, Bank, Customer, CustomerAddress, Product, ProductCollection, ProductCollectionItem, TaxResidence, UserAuthContext, UserAuthContextUpdate, _} import com.tesobe.CacheKeyFromArguments -import net.liftweb.common.{Box, Empty, Full, ParamFailure} +import net.liftweb.common.{Box, Empty, Failure, Full, ParamFailure} import net.liftweb.http.provider.HTTPParam import net.liftweb.json.JsonDSL._ import net.liftweb.json.{JField, JInt, JNothing, JNull, JObject, JString, JValue, _} @@ -62,6 +62,7 @@ import code.validation.{JsonSchemaValidationProvider, JsonValidation} import net.liftweb.http.JsonResponse import net.liftweb.util.Props import code.api.JsonResponseException +import code.api.v4_0_0.FeeJson import code.api.v4_0_0.dynamic.{DynamicEndpointHelper, DynamicEntityInfo} import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod} import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc} @@ -70,6 +71,8 @@ import code.endpointMapping.{EndpointMappingProvider, EndpointMappingT} import code.endpointTag.EndpointTagT import net.liftweb.json +import scala.util.Success + object NewStyle { lazy val endpoints: List[(String, String)] = List( (nameOf(ImplementationsResourceDocs.getResourceDocsObp), ApiVersion.v1_4_0.toString), @@ -1338,6 +1341,52 @@ object NewStyle { i => (connectorEmptyResponse(i._1, callContext), i._2) } } + + def createProductFees( + bankId: BankId, + productCode: ProductCode, + fees: List[FeeJson], + callContext: Option[CallContext] + ): OBPReturnType[List[ProductFee]] = { + val abc: List[Future[ProductFee]] = fees.map( + fee => + Connector.connector.vend.createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId = None, + name = fee.name, + isActive = fee.isActive, + moreInfo = fee.moreInfo, + currency = fee.value.currency, + amount = fee.value.amount, + frequency = fee.value.frequency, + `type` = fee.value.`type`, + callContext: Option[CallContext]) map { + i => (connectorEmptyResponse(i, callContext), callContext) + } + ).map( i =>i.map(_._1)) + + val seq = Future.sequence(abc.map(_.transform(Success(_)))) + + val successes = seq.map(_.collect{case Success(x)=>x}) + + successes.map(success => (success, callContext)) + + } + + def getProductFeesFromProvider( + bankId: BankId, + productCode: ProductCode, + callContext: Option[CallContext] + ): OBPReturnType[List[ProductFee]] = { + Connector.connector.vend.getProductFeesFromProvider( + bankId: BankId, + productCode: ProductCode, + callContext: Option[CallContext] + ) map { + i => (connectorEmptyResponse(i, callContext), callContext) + } + } def getProductAttributesByBankAndCode( bank: BankId, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index b2f32162d..c2d7268b5 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -85,6 +85,7 @@ import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future import scala.jdk.CollectionConverters.collectionAsScalaIterableConverter +import scala.math.BigDecimal import scala.xml.XML trait APIMethods400 { @@ -9646,7 +9647,7 @@ trait APIMethods400 { | |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, emptyObjectJson, - productsJsonV310, + productJsonV400.copy(attributes = None), List( UserNotLoggedIn, BankNotFound, @@ -9745,8 +9746,16 @@ trait APIMethods400 { )) map { connectorEmptyResponse(_, callContext) } + + (productFees, callContext) <- NewStyle.function.createProductFees( + bankId, + productCode, + product.fees.getOrElse(Nil), + callContext + ) + } yield { - (JSONFactory400.createProductJson(success), HttpCode.`201`(callContext)) + (JSONFactory400.createProductWithFeeJson(success, productFees), HttpCode.`201`(callContext)) } } } @@ -9795,8 +9804,11 @@ trait APIMethods400 { unboxFullOrFail(_, callContext, ProductNotFoundByProductCode) } (productAttributes, callContext) <- NewStyle.function.getProductAttributesByBankAndCode(bankId, productCode, callContext) + + (productFees, callContext) <- NewStyle.function.getProductFeesFromProvider(bankId, productCode, callContext) + } yield { - (JSONFactory400.createProductJson(product, productAttributes), HttpCode.`200`(callContext)) + (JSONFactory400.createProductJson(product, productAttributes, productFees), HttpCode.`200`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index dd372c5a7..811b077fb 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -47,16 +47,19 @@ import code.atms.Atms.Atm import code.consent.MappedConsent import code.entitlement.Entitlement import code.model.{Consumer, ModeratedBankAccount, ModeratedBankAccountCore} +import code.productfee.MappedProductFee import code.ratelimiting.RateLimiting import code.standingorders.StandingOrderTrait import code.transactionrequests.TransactionRequests.TransactionChallengeTypes import code.userlocks.UserLocks import code.users.UserInvitation -import com.openbankproject.commons.model.{DirectDebitTrait, _} +import com.openbankproject.commons.model.{DirectDebitTrait, ProductFee, _} import net.liftweb.common.{Box, Full} import net.liftweb.json.JValue +import net.liftweb.mapper.By import scala.collection.immutable.List +import scala.math.BigDecimal import scala.util.Try @@ -583,7 +586,7 @@ case class ProductsJsonV400(products: List[ProductJsonV400]) case class FeeJsonValue( currency: String, - amount: String, + amount: BigDecimal, frequency: String, `type`: String, ) @@ -1555,7 +1558,7 @@ object JSONFactory400 { ) } - def createProductJson(product: Product) : ProductJsonV400 = { + def createProductWithFeeJson(product: Product, productFees:List[ProductFee]) : ProductJsonV400 = { ProductJsonV400( bank_id = product.bankId.toString, product_code = product.code.value, @@ -1566,14 +1569,34 @@ object JSONFactory400 { description = product.description, meta = createMetaJson(product.meta), None, - None + fees = Some(productFees.map(productFee =>FeeJson( + fee_id = productFee.feeId, + name = productFee.name, + isActive = productFee.isActive, + moreInfo = productFee.moreInfo, + value = FeeJsonValue( + currency = productFee.currency, + amount = productFee.amount, + frequency = productFee.frequency, + `type` = productFee.`type` + )))) ) } def createProductsJson(productsList: List[Product]) : ProductsJsonV400 = { - ProductsJsonV400(productsList.map(createProductJson)) - } + ProductsJsonV400(productsList.map( + product =>{ + val productFrees = MappedProductFee.findAll( //TODO move this to connector + By(MappedProductFee.BankId, product.bankId.value), + By(MappedProductFee.ProductCode,product.code.value) + ) + createProductWithFeeJson( + product, + productFrees + ) + } + ))} - def createProductJson(product: Product, productAttributes: List[ProductAttribute]) : ProductJsonV400 = { + def createProductJson(product: Product, productAttributes: List[ProductAttribute], productFees:List[ProductFee]) : ProductJsonV400 = { ProductJsonV400( bank_id = product.bankId.toString, product_code = product.code.value, @@ -1584,7 +1607,17 @@ object JSONFactory400 { description = product.description, meta = createMetaJson(product.meta), attributes = Some(createProductAttributesJson(productAttributes)), - fees= None + fees = Some(productFees.map(productFee =>FeeJson( + fee_id = productFee.feeId, + name = productFee.name, + isActive = productFee.isActive, + moreInfo = productFee.moreInfo, + value = FeeJsonValue( + currency = productFee.currency, + amount = productFee.amount, + frequency = productFee.frequency, + `type` = productFee.`type` + )))) ) } } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 22cc525da..ecbd78731 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -25,6 +25,7 @@ import code.fx.fx.TTL import code.management.ImporterAPI.ImporterTransaction import code.model.dataAccess.{BankAccountRouting, ResourceUser} import code.model.toUserExtended +import code.productfee.ProductFeeX import code.standingorders.StandingOrderTrait import code.transactionrequests.TransactionRequests import code.transactionrequests.TransactionRequests.TransactionRequestTypes._ @@ -1594,8 +1595,28 @@ trait Connector extends MdcLoggable { metaLicenceId : String, metaLicenceName : String ): Box[Product] = Failure(setUnimplementedError) + + def createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String, + callContext: Option[CallContext] + ): Future[Box[ProductFee]]= Future(Failure(setUnimplementedError)) - + def getProductFeesFromProvider( + bankId: BankId, + productCode: ProductCode, + callContext: Option[CallContext] + ): Future[Box[List[ProductFee]]] = Future(Failure(setUnimplementedError)) + + def createOrUpdateFXRate( bankId: String, fromCurrencyCode: String, diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index da4c7559f..ec894f50e 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -53,6 +53,7 @@ import code.productAttributeattribute.MappedProductAttribute import code.productattribute.ProductAttributeX import code.productcollection.ProductCollectionX import code.productcollectionitem.ProductCollectionItems +import code.productfee.ProductFeeX import code.products.MappedProduct import code.standingorders.{StandingOrderTrait, StandingOrders} import code.taxresidence.TaxResidenceX @@ -2712,6 +2713,45 @@ object LocalMappedConnector extends Connector with MdcLoggable { } } + override def createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String, + callContext: Option[CallContext] + ): Future[Box[ProductFee]] = { + ProductFeeX.productFeeProvider.vend.createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String + ) map { + (_, callContext) + } + } + + override def getProductFeesFromProvider( + bankId: BankId, + productCode: ProductCode, + callContext: Option[CallContext] + ): Future[Box[List[ProductFee]]] = { + ProductFeeX.productFeeProvider.vend.getProductFeesFromProvider(bankId: BankId, productCode: ProductCode) map { + (_, callContext) + } + } + override def createOrUpdateProduct(bankId: String, code: String, diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala new file mode 100644 index 000000000..1b2dd4934 --- /dev/null +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -0,0 +1,140 @@ +package code.productfee + +import code.api.util.APIUtil +import code.util.UUIDString +import com.openbankproject.commons.model.{BankId, ProductCode, ProductFee} +import net.liftweb.common.{Box, Empty, Full} +import net.liftweb.mapper.{MappedBoolean, _} +import net.liftweb.util.Helpers.tryo + +import java.math.MathContext +import scala.math.BigDecimal +import com.openbankproject.commons.ExecutionContext.Implicits.global + +import scala.concurrent.Future + +object MappedProductFeeProvider extends ProductFeeProvider { + + override def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFee]]] = + Future { + Box !! MappedProductFee.findAll( + By(MappedProductFee.BankId, bankId.value), + By(MappedProductFee.ProductCode, productCode.value) + ) + } + + override def getProductFeeById(feeId: String): Future[Box[ProductFee]] = Future { + MappedProductFee.find(By(MappedProductFee.FeeId, feeId)) + } + + override def createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String + ): Future[Box[ProductFee]] = { + feeId match { + case Some(id) => Future { + MappedProductFee.find(By(MappedProductFee.FeeId, id)) match { + case Full(productFee) => tryo { + productFee + .BankId(bankId.value) + .ProductCode(productCode.value) + .Name(name) + .IsActive(isActive) + .MoreInfo(moreInfo) + .Currency(currency) + .Amount(amount) + .Frequency(frequency) + .Type(`type`) + .saveMe() + } + case _ => Empty + } + } + case None => Future { + Full { + MappedProductFee + .create + .FeeId(APIUtil.generateUUID) + .BankId(bankId.value) + .ProductCode(productCode.value) + .Name(name) + .IsActive(isActive) + .MoreInfo(moreInfo) + .Currency(currency) + .Amount(amount) + .Frequency(frequency) + .Type(`type`) + .saveMe() + } + } + } + } + + override def deleteProductFee(feeId: String): Future[Box[Boolean]] = Future { + tryo( + MappedProductFee.bulkDelete_!!(By(MappedProductFee.FeeId, feeId)) + ) + } +} + +class MappedProductFee extends ProductFee with LongKeyedMapper[MappedProductFee] with IdPK { + + override def getSingleton = MappedProductFee + + object BankId extends UUIDString(this) + + object ProductCode extends MappedString(this, 50) + + object FeeId extends UUIDString(this) + + object Name extends MappedString(this, 50) + + object IsActive extends MappedBoolean(this) { + override def defaultValue = true + } + + object MoreInfo extends MappedString(this, 255) + + object Currency extends MappedString(this, 50) + + object Amount extends MappedDecimal(this, MathContext.DECIMAL64, 0) + + object Frequency extends MappedString(this, 255) + + object Type extends MappedString(this, 255) + + + override def bankId: BankId = com.openbankproject.commons.model.BankId(BankId.get) + + override def productCode: ProductCode = com.openbankproject.commons.model.ProductCode(ProductCode.get) + + override def feeId: String = FeeId.get + + override def name: String = Name.get + + override def isActive: Boolean = IsActive.get + + override def moreInfo: String = MoreInfo.get + + override def currency: String = Currency.get + + override def amount: BigDecimal = Amount.get + + override def frequency: String = Frequency.get + + override def `type`: String = Type.get + +} + +object MappedProductFee extends MappedProductFee with LongKeyedMetaMapper[MappedProductFee] { + override def dbIndexes = Index(BankId) :: Index(FeeId) :: super.dbIndexes +} + diff --git a/obp-api/src/main/scala/code/productfee/ProductAttribute.scala b/obp-api/src/main/scala/code/productfee/ProductAttribute.scala new file mode 100644 index 000000000..33677f945 --- /dev/null +++ b/obp-api/src/main/scala/code/productfee/ProductAttribute.scala @@ -0,0 +1,76 @@ +package code.productfee + +/* For ProductFee */ + +import code.api.util.APIUtil +import com.openbankproject.commons.model.{BankId, ProductCode, ProductFee} +import net.liftweb.common.{Box, Logger} +import net.liftweb.util.SimpleInjector + +import scala.concurrent.Future +import scala.math.BigDecimal + +object ProductFeeX extends SimpleInjector { + + val productFeeProvider = new Inject(buildOne _) {} + + def buildOne: ProductFeeProvider = MappedProductFeeProvider + + // Helper to get the count out of an option + def countOfProductFee(listOpt: Option[List[ProductFee]]): Int = { + val count = listOpt match { + case Some(list) => list.size + case None => 0 + } + count + } + + +} + +trait ProductFeeProvider { + + private val logger = Logger(classOf[ProductFeeProvider]) + + def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFee]]] + + def getProductFeeById(feeId: String): Future[Box[ProductFee]] + + def createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String + ): Future[Box[ProductFee]] + + def deleteProductFee(feeId: String): Future[Box[Boolean]] +} + +class RemotedataProductFeeCaseClasses { + case class getProductFeesFromProvider(bankId: BankId, productCode: ProductCode) + + case class getProductFeeById(feeId: String) + + case class createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + feeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String + ) + + case class deleteProductFee(feeId: String) +} + +object RemotedataProductFeeCaseClasses extends RemotedataProductFeeCaseClasses diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala index 367d90e75..57aab4d47 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala @@ -28,13 +28,13 @@ TESOBE (http://www.tesobe.com/) package com.openbankproject.commons.model import java.util.Date - import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus import com.openbankproject.commons.model.enums._ import com.openbankproject.commons.util.ReflectUtils import scala.collection.immutable.List +import scala.math.BigDecimal import scala.reflect.runtime.universe /** @@ -261,6 +261,19 @@ trait ProductAttribute { def isActive: Option[Boolean] } +trait ProductFee { + def bankId: BankId + def productCode: ProductCode + def feeId: String + def name: String + def isActive: Boolean + def moreInfo: String + def currency: String + def amount: BigDecimal + def frequency: String + def `type`: String +} + trait ProductCollection { def collectionCode: String From b96bd27a439aa5b44dea1f5cf5b8d8e72b30c1ff Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 09:56:49 +0200 Subject: [PATCH 088/293] feature/OBPv400 added the `fees` fields to Product response body -step3 --- .../SwaggerDefinitionsJSON.scala | 1 - .../scala/code/api/v4_0_0/APIMethods400.scala | 14 ++-------- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 28 ++----------------- .../code/api/v4_0_0/V400ServerSetup.scala | 1 - 4 files changed, 6 insertions(+), 38 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 5dddb00b7..4e25850bf 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4380,7 +4380,6 @@ object SwaggerDefinitionsJSON { terms_and_conditions_url = termsAndConditionsUrlExample.value, description = descriptionExample.value, meta = metaJson, - fees = Some(List(feeJson)) ) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index c2d7268b5..2a35385b2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -9647,7 +9647,7 @@ trait APIMethods400 { | |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, emptyObjectJson, - productJsonV400.copy(attributes = None), + productJsonV400.copy(attributes = None, fees = None), List( UserNotLoggedIn, BankNotFound, @@ -9701,7 +9701,7 @@ trait APIMethods400 { | |""", putProductJsonV400, - productJsonV400, + productJsonV400.copy(attributes = None, fees = None), List( $UserNotLoggedIn, $BankNotFound, @@ -9746,16 +9746,8 @@ trait APIMethods400 { )) map { connectorEmptyResponse(_, callContext) } - - (productFees, callContext) <- NewStyle.function.createProductFees( - bankId, - productCode, - product.fees.getOrElse(Nil), - callContext - ) - } yield { - (JSONFactory400.createProductWithFeeJson(success, productFees), HttpCode.`201`(callContext)) + (JSONFactory400.createProductJson(success), HttpCode.`201`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 811b077fb..e7751dcdd 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -605,7 +605,6 @@ case class PutProductJsonV400( terms_and_conditions_url: String, description: String, meta: MetaJsonV140, - fees: Option[List[FeeJson]] ) case class CounterpartyJson400( name: String, @@ -1558,7 +1557,7 @@ object JSONFactory400 { ) } - def createProductWithFeeJson(product: Product, productFees:List[ProductFee]) : ProductJsonV400 = { + def createProductJson(product: Product) : ProductJsonV400 = { ProductJsonV400( bank_id = product.bankId.toString, product_code = product.code.value, @@ -1569,32 +1568,11 @@ object JSONFactory400 { description = product.description, meta = createMetaJson(product.meta), None, - fees = Some(productFees.map(productFee =>FeeJson( - fee_id = productFee.feeId, - name = productFee.name, - isActive = productFee.isActive, - moreInfo = productFee.moreInfo, - value = FeeJsonValue( - currency = productFee.currency, - amount = productFee.amount, - frequency = productFee.frequency, - `type` = productFee.`type` - )))) + None ) } def createProductsJson(productsList: List[Product]) : ProductsJsonV400 = { - ProductsJsonV400(productsList.map( - product =>{ - val productFrees = MappedProductFee.findAll( //TODO move this to connector - By(MappedProductFee.BankId, product.bankId.value), - By(MappedProductFee.ProductCode,product.code.value) - ) - createProductWithFeeJson( - product, - productFrees - ) - } - ))} + ProductsJsonV400(productsList.map(createProductJson))} def createProductJson(product: Product, productAttributes: List[ProductAttribute], productFees:List[ProductFee]) : ProductJsonV400 = { ProductJsonV400( diff --git a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala index 798eef150..af5529b47 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala @@ -156,7 +156,6 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { terms_and_conditions_url = "www.example.com/prod1/terms_and_conditions_url.html", description = "Description", meta = SwaggerDefinitionsJSON.metaJson, - fees = None ) val product: ProductJsonV400 = createProductViaEndpoint( From 15cd78330150639495bb9c20a94e4a5ebdf82909 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 13:01:32 +0200 Subject: [PATCH 089/293] feature/OBPv400 added CURD Product Fee endpoints -step4 --- .../SwaggerDefinitionsJSON.scala | 27 ++- .../main/scala/code/api/util/ApiRole.scala | 12 ++ .../scala/code/api/util/ErrorMessages.scala | 2 + .../scala/code/api/util/ExampleValue.scala | 4 +- .../main/scala/code/api/util/NewStyle.scala | 67 ++++--- .../scala/code/api/v4_0_0/APIMethods400.scala | 174 +++++++++++++++++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 78 +++++--- .../scala/code/bankconnectors/Connector.scala | 13 +- .../bankconnectors/LocalMappedConnector.scala | 17 +- .../productfee/MappedProductFeeProvider.scala | 22 +-- .../code/productfee/ProductAttribute.scala | 12 +- .../commons/model/CommonModelTrait.scala | 2 +- 12 files changed, 344 insertions(+), 86 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 4e25850bf..e59c4d44a 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4343,21 +4343,34 @@ object SwaggerDefinitionsJSON { val atmsJsonV400 = AtmsJsonV400(List(atmJsonV400)) - val feeJsonValue= FeeJsonValue( + val productFeeValueJsonV400 = ProductFeeValueJsonV400( currency = currencyExample.value, amount = 10.12, frequency = frequencyExample.value, `type` = typeExample.value ) - val feeJson = FeeJson( - fee_id = feeIdExample.value, + val productFeeJsonV400 = ProductFeeJsonV400( + product_fee_id = Some(productFeeIdExample.value), name = nameExample.value, - isActive = true, - moreInfo = moreInfoExample.value, - value = feeJsonValue + is_active = true, + more_info = moreInfoExample.value, + value = productFeeValueJsonV400 ) + val productFeeResponseJsonV400 = ProductFeeResponseJsonV400( + bank_id = bankIdExample.value, + product_code = productCodeExample.value, + product_fee_id = productFeeIdExample.value, + name = nameExample.value, + is_active = true, + more_info = moreInfoExample.value, + value = productFeeValueJsonV400 + ) + + val productFeesResponseJsonV400 = ProductFeesResponseJsonV400(List(productFeeResponseJsonV400)) + + val productJsonV400 = ProductJsonV400( bank_id = bankIdExample.value, product_code = productCodeExample.value, @@ -4368,7 +4381,7 @@ object SwaggerDefinitionsJSON { description = descriptionExample.value, meta = metaJson, attributes = Some(List(productAttributeResponseJson)), - fees = Some(List(feeJson)) + fees = Some(List(productFeeJsonV400)) ) val productsJsonV400 = ProductsJsonV400(products = List(productJsonV400)) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index a744fed8e..795dfc067 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -419,6 +419,18 @@ object ApiRole { case class CanCreateProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateProductAttribute = CanCreateProductAttribute() + case class CanUpdateProductFee(requiresBankId: Boolean = true) extends ApiRole + lazy val canUpdateProductFee = CanUpdateProductFee() + + case class CanGetProductFee(requiresBankId: Boolean = true) extends ApiRole + lazy val canGetProductFee = CanGetProductFee() + + case class CanDeleteProductFee(requiresBankId: Boolean = true) extends ApiRole + lazy val canDeleteProductFee = CanDeleteProductFee() + + case class CanCreateProductFee(requiresBankId: Boolean = true) extends ApiRole + lazy val canCreateProductFee = CanCreateProductFee() + case class CanMaintainProductCollection(requiresBankId: Boolean = true) extends ApiRole lazy val canMaintainProductCollection = CanMaintainProductCollection() diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 705b03ae9..ac8076acb 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -370,6 +370,8 @@ object ErrorMessages { val InvalidAccountRoutings = "OBP-30114: Invalid Account Routings." val AccountRoutingAlreadyExist = "OBP-30115: Account Routing already exist." val InvalidPaymentSystemName = "OBP-30116: Invalid payment system name. The payment system name should only contain 0-9/a-z/A-Z/'-'/'.'/'_', the length should be smaller than 200." + + val ProductFeeNotFoundById = "OBP-30017: Product Fee not found. Please specify a valid value for PRODUCT_FEE_ID." val EntitlementIsBankRole = "OBP-30205: This entitlement is a Bank Role. Please set bank_id to a valid bank id." diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 265479dd4..b82a736a0 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -1605,8 +1605,8 @@ object ExampleValue { lazy val nameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("name", nameExample) - lazy val feeIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) - glossaryItems += makeGlossaryItem("fee_id", nameExample) + lazy val productFeeIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + glossaryItems += makeGlossaryItem("product_fee_id", nameExample) lazy val emailAddressExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("email_address", emailAddressExample) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 5e3b335ae..58c948497 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -62,7 +62,7 @@ import code.validation.{JsonSchemaValidationProvider, JsonValidation} import net.liftweb.http.JsonResponse import net.liftweb.util.Props import code.api.JsonResponseException -import code.api.v4_0_0.FeeJson +import code.api.v4_0_0.ProductFeeJsonV400 import code.api.v4_0_0.dynamic.{DynamicEndpointHelper, DynamicEntityInfo} import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod} import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc} @@ -1342,38 +1342,47 @@ object NewStyle { } } - def createProductFees( + def createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - fees: List[FeeJson], + productFeeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String, callContext: Option[CallContext] - ): OBPReturnType[List[ProductFee]] = { - val abc: List[Future[ProductFee]] = fees.map( - fee => - Connector.connector.vend.createOrUpdateProductFee( - bankId: BankId, - productCode: ProductCode, - feeId = None, - name = fee.name, - isActive = fee.isActive, - moreInfo = fee.moreInfo, - currency = fee.value.currency, - amount = fee.value.amount, - frequency = fee.value.frequency, - `type` = fee.value.`type`, - callContext: Option[CallContext]) map { - i => (connectorEmptyResponse(i, callContext), callContext) - } - ).map( i =>i.map(_._1)) - - val seq = Future.sequence(abc.map(_.transform(Success(_)))) - - val successes = seq.map(_.collect{case Success(x)=>x}) - - successes.map(success => (success, callContext)) - + ): OBPReturnType[ProductFee] = { + Connector.connector.vend.createOrUpdateProductFee( + bankId: BankId, + productCode: ProductCode, + productFeeId: Option[String], + name: String, + isActive: Boolean, + moreInfo: String, + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String, + callContext: Option[CallContext] + ) map { + i => (connectorEmptyResponse(i._1, callContext), i._2) + } } + def getProductFeeById( + productFeeId: String, + callContext: Option[CallContext] + ) : OBPReturnType[ProductFee] = + Connector.connector.vend.getProductFeeById( + productFeeId: String, + callContext: Option[CallContext] + ) map { + i => (unboxFullOrFail(i._1, callContext, ProductFeeNotFoundById + " {" + productFeeId + "}", 404), i._2) + } + def getProductFeesFromProvider( bankId: BankId, productCode: ProductCode, @@ -1384,7 +1393,7 @@ object NewStyle { productCode: ProductCode, callContext: Option[CallContext] ) map { - i => (connectorEmptyResponse(i, callContext), callContext) + i => (connectorEmptyResponse(i._1, callContext), i._2) } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 2a35385b2..580705876 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5632,7 +5632,179 @@ trait APIMethods400 { } } - + staticResourceDocs += ResourceDoc( + createProductFee, + implementedInApiVersion, + nameOf(createProductFee), + "POST", + "/banks/BANK_ID/products/PRODUCT_CODE/fee", + "Create Product Fee", + s"""Create Product Fee + | + |${authenticationRequiredMessage(true)} + | + |""", + productFeeJsonV400.copy(product_fee_id = None), + productFeeResponseJsonV400, + List( + $UserNotLoggedIn, + $BankNotFound, + InvalidJsonFormat, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canCreateProductFee)) + ) + + lazy val createProductFee : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "fee" :: Nil JsonPost json -> _=> { + cc => + for { + postedData <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $ProductFeeJsonV400 " , 400, Some(cc)) { + json.extract[ProductFeeJsonV400] + } + (_, callContext) <- NewStyle.function.getProduct(BankId(bankId), ProductCode(productCode), Some(cc)) + (productFee, callContext) <- NewStyle.function.createOrUpdateProductFee( + BankId(bankId), + ProductCode(productCode), + None, + postedData.name, + postedData.is_active, + postedData.more_info, + postedData.value.currency, + postedData.value.amount, + postedData.value.frequency, + postedData.value.`type`, + callContext: Option[CallContext] + ) + } yield { + (createProductFeeJson(productFee), HttpCode.`201`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + updateProductFee, + implementedInApiVersion, + nameOf(updateProductFee), + "PUT", + "/banks/BANK_ID/products/PRODUCT_CODE/fees/PRODUCT_FEE_ID", + "Update Product Fee", + s""" Update Product Fee. + | + |Update one Product Fee by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + productFeeJsonV400.copy(product_fee_id = None), + productFeeResponseJsonV400, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canUpdateProductFee))) + + lazy val updateProductFee : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "fees" :: productFeeId :: Nil JsonPut json -> _ =>{ + cc => + for { + postedData <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $ProductFeeJsonV400 ", 400, Some(cc)) { + json.extract[ProductFeeJsonV400] + } + (_, callContext) <- NewStyle.function.getProduct(BankId(bankId), ProductCode(productCode), Some(cc)) + (_, callContext) <- NewStyle.function.getProductFeeById(productFeeId, callContext) + (productFee, callContext) <- NewStyle.function.createOrUpdateProductFee( + BankId(bankId), + ProductCode(productCode), + Some(productFeeId), + postedData.name, + postedData.is_active, + postedData.more_info, + postedData.value.currency, + postedData.value.amount, + postedData.value.frequency, + postedData.value.`type`, + callContext: Option[CallContext] + ) + } yield { + (createProductFeeJson(productFee), HttpCode.`201`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getProductFee, + implementedInApiVersion, + nameOf(getProductFee), + "GET", + "/banks/BANK_ID/products/PRODUCT_CODE/fees/PRODUCT_FEE_ID", + "Get Product Fee", + s""" Get Product Fee + | + |Get one product fee by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + productFeeResponseJsonV400, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canGetProductFee))) + + lazy val getProductFee : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "fees" :: productFeeId :: Nil JsonGet _ => { + cc => + for { + (productFee, callContext) <- NewStyle.function.getProductFeeById(productFeeId, Some(cc)) + } yield { + (createProductFeeJson(productFee), HttpCode.`200`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getProductFees, + implementedInApiVersion, + nameOf(getProductFees), + "GET", + "/banks/BANK_ID/products/PRODUCT_CODE/fees", + "Get Product Fees", + s"""Get Product Fees + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + productFeesResponseJsonV400, + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canGetProductFee))) + + lazy val getProductFees : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "fees" :: Nil JsonGet _ => { + cc => + for { + (productFees, callContext) <- NewStyle.function.getProductFeesFromProvider(BankId(bankId), ProductCode(productCode), Some(cc)) + } yield { + (createProductFeesJson(productFees), HttpCode.`200`(callContext)) + } + } + } staticResourceDocs += ResourceDoc( createOrUpdateTransactionAttributeDefinition, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index e7751dcdd..fa0aa9777 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -579,24 +579,12 @@ case class ProductJsonV400( description: String, meta: MetaJsonV140, attributes: Option[List[ProductAttributeResponseWithoutBankIdJson]], - fees: Option[List[FeeJson]] + fees: Option[List[ProductFeeJsonV400]] ) case class ProductsJsonV400(products: List[ProductJsonV400]) -case class FeeJsonValue( - currency: String, - amount: BigDecimal, - frequency: String, - `type`: String, -) -case class FeeJson( - fee_id: String, - name: String, - isActive: Boolean, - moreInfo: String, - value:FeeJsonValue, -) + case class PutProductJsonV400( parent_product_code: String, @@ -717,6 +705,35 @@ case class ProductAttributeResponseWithoutBankIdJsonV400( is_active: Option[Boolean] ) +case class ProductFeeValueJsonV400( + currency: String, + amount: BigDecimal, + frequency: String, + `type`: String, +) + +case class ProductFeeJsonV400( + product_fee_id:Option[String], + name: String, + is_active: Boolean, + more_info: String, + value:ProductFeeValueJsonV400, +) + +case class ProductFeeResponseJsonV400( + bank_id: String, + product_code: String, + product_fee_id: String, + name: String, + is_active: Boolean, + more_info: String, + value:ProductFeeValueJsonV400, +) + +case class ProductFeesResponseJsonV400( + product_fees: List[ProductFeeResponseJsonV400] +) + case class IbanCheckerJsonV400( is_valid: Boolean, details: Option[IbanDetailsJsonV400] @@ -1436,7 +1453,26 @@ object JSONFactory400 { value = productAttribute.value, is_active = productAttribute.isActive ) - + + def createProductFeeJson(productFee: ProductFee): ProductFeeResponseJsonV400 = + ProductFeeResponseJsonV400( + bank_id = productFee.bankId.value, + product_code = productFee.productCode.value, + product_fee_id = productFee.productFeeId, + name = productFee.name, + is_active = productFee.isActive, + more_info = productFee.moreInfo, + value = ProductFeeValueJsonV400( + currency = productFee.currency, + amount = productFee.amount, + frequency= productFee.frequency, + `type`= productFee.`type` + ) + ) + + def createProductFeesJson(productFees: List[ProductFee]): ProductFeesResponseJsonV400 = + ProductFeesResponseJsonV400(productFees.map(createProductFeeJson)) + def createApiCollectionEndpointsJsonV400(apiCollectionEndpoints: List[ApiCollectionEndpointTrait]) = { ApiCollectionEndpointsJson400(apiCollectionEndpoints.map(apiCollectionEndpoint => createApiCollectionEndpointJsonV400(apiCollectionEndpoint))) @@ -1585,12 +1621,12 @@ object JSONFactory400 { description = product.description, meta = createMetaJson(product.meta), attributes = Some(createProductAttributesJson(productAttributes)), - fees = Some(productFees.map(productFee =>FeeJson( - fee_id = productFee.feeId, - name = productFee.name, - isActive = productFee.isActive, - moreInfo = productFee.moreInfo, - value = FeeJsonValue( + fees = Some(productFees.map(productFee =>ProductFeeJsonV400( + product_fee_id= Some(productFee.productFeeId), + name = productFee.name, + is_active = productFee.isActive, + more_info = productFee.moreInfo, + value = ProductFeeValueJsonV400( currency = productFee.currency, amount = productFee.amount, frequency = productFee.frequency, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index ecbd78731..41f6b6b71 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1599,7 +1599,7 @@ trait Connector extends MdcLoggable { def createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - feeId: Option[String], + productFeeId: Option[String], name: String, isActive: Boolean, moreInfo: String, @@ -1608,14 +1608,19 @@ trait Connector extends MdcLoggable { frequency: String, `type`: String, callContext: Option[CallContext] - ): Future[Box[ProductFee]]= Future(Failure(setUnimplementedError)) + ): OBPReturnType[Box[ProductFee]]= Future(Failure(setUnimplementedError)) def getProductFeesFromProvider( bankId: BankId, productCode: ProductCode, callContext: Option[CallContext] - ): Future[Box[List[ProductFee]]] = Future(Failure(setUnimplementedError)) - + ): OBPReturnType[Box[List[ProductFee]]] = Future(Failure(setUnimplementedError)) + + def getProductFeeById( + productFeeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Box[ProductFee]] = Future(Failure(setUnimplementedError)) + def createOrUpdateFXRate( bankId: String, diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index ec894f50e..4449608ef 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2716,7 +2716,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { override def createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - feeId: Option[String], + productFeeId: Option[String], name: String, isActive: Boolean, moreInfo: String, @@ -2725,11 +2725,11 @@ object LocalMappedConnector extends Connector with MdcLoggable { frequency: String, `type`: String, callContext: Option[CallContext] - ): Future[Box[ProductFee]] = { + ): OBPReturnType[Box[ProductFee]] = { ProductFeeX.productFeeProvider.vend.createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - feeId: Option[String], + productFeeId: Option[String], name: String, isActive: Boolean, moreInfo: String, @@ -2746,11 +2746,20 @@ object LocalMappedConnector extends Connector with MdcLoggable { bankId: BankId, productCode: ProductCode, callContext: Option[CallContext] - ): Future[Box[List[ProductFee]]] = { + ): OBPReturnType[Box[List[ProductFee]]] = { ProductFeeX.productFeeProvider.vend.getProductFeesFromProvider(bankId: BankId, productCode: ProductCode) map { (_, callContext) } } + + override def getProductFeeById( + productFeeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Box[ProductFee]] = { + ProductFeeX.productFeeProvider.vend.getProductFeeById(productFeeId) map { + (_, callContext) + } + } override def createOrUpdateProduct(bankId: String, diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala index 1b2dd4934..49a6ba2c3 100644 --- a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -23,14 +23,14 @@ object MappedProductFeeProvider extends ProductFeeProvider { ) } - override def getProductFeeById(feeId: String): Future[Box[ProductFee]] = Future { - MappedProductFee.find(By(MappedProductFee.FeeId, feeId)) + override def getProductFeeById(productFeeId: String): Future[Box[ProductFee]] = Future { + MappedProductFee.find(By(MappedProductFee.ProductFeeId, productFeeId)) } override def createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - feeId: Option[String], + productFeeId: Option[String], name: String, isActive: Boolean, moreInfo: String, @@ -39,9 +39,9 @@ object MappedProductFeeProvider extends ProductFeeProvider { frequency: String, `type`: String ): Future[Box[ProductFee]] = { - feeId match { + productFeeId match { case Some(id) => Future { - MappedProductFee.find(By(MappedProductFee.FeeId, id)) match { + MappedProductFee.find(By(MappedProductFee.ProductFeeId, id)) match { case Full(productFee) => tryo { productFee .BankId(bankId.value) @@ -62,7 +62,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { Full { MappedProductFee .create - .FeeId(APIUtil.generateUUID) + .ProductFeeId(APIUtil.generateUUID) .BankId(bankId.value) .ProductCode(productCode.value) .Name(name) @@ -78,9 +78,9 @@ object MappedProductFeeProvider extends ProductFeeProvider { } } - override def deleteProductFee(feeId: String): Future[Box[Boolean]] = Future { + override def deleteProductFee(productFeeId: String): Future[Box[Boolean]] = Future { tryo( - MappedProductFee.bulkDelete_!!(By(MappedProductFee.FeeId, feeId)) + MappedProductFee.bulkDelete_!!(By(MappedProductFee.ProductFeeId, productFeeId)) ) } } @@ -93,7 +93,7 @@ class MappedProductFee extends ProductFee with LongKeyedMapper[MappedProductFee] object ProductCode extends MappedString(this, 50) - object FeeId extends UUIDString(this) + object ProductFeeId extends UUIDString(this) object Name extends MappedString(this, 50) @@ -116,7 +116,7 @@ class MappedProductFee extends ProductFee with LongKeyedMapper[MappedProductFee] override def productCode: ProductCode = com.openbankproject.commons.model.ProductCode(ProductCode.get) - override def feeId: String = FeeId.get + override def productFeeId: String = ProductFeeId.get override def name: String = Name.get @@ -135,6 +135,6 @@ class MappedProductFee extends ProductFee with LongKeyedMapper[MappedProductFee] } object MappedProductFee extends MappedProductFee with LongKeyedMetaMapper[MappedProductFee] { - override def dbIndexes = Index(BankId) :: Index(FeeId) :: super.dbIndexes + override def dbIndexes = Index(BankId) :: Index(ProductFeeId) :: super.dbIndexes } diff --git a/obp-api/src/main/scala/code/productfee/ProductAttribute.scala b/obp-api/src/main/scala/code/productfee/ProductAttribute.scala index 33677f945..21f180621 100644 --- a/obp-api/src/main/scala/code/productfee/ProductAttribute.scala +++ b/obp-api/src/main/scala/code/productfee/ProductAttribute.scala @@ -34,12 +34,12 @@ trait ProductFeeProvider { def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFee]]] - def getProductFeeById(feeId: String): Future[Box[ProductFee]] + def getProductFeeById(productFeeId: String): Future[Box[ProductFee]] def createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - feeId: Option[String], + productFeeId: Option[String], name: String, isActive: Boolean, moreInfo: String, @@ -49,18 +49,18 @@ trait ProductFeeProvider { `type`: String ): Future[Box[ProductFee]] - def deleteProductFee(feeId: String): Future[Box[Boolean]] + def deleteProductFee(productFeeId: String): Future[Box[Boolean]] } class RemotedataProductFeeCaseClasses { case class getProductFeesFromProvider(bankId: BankId, productCode: ProductCode) - case class getProductFeeById(feeId: String) + case class getProductFeeById(productFeeId: String) case class createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, - feeId: Option[String], + productFeeId: Option[String], name: String, isActive: Boolean, moreInfo: String, @@ -70,7 +70,7 @@ class RemotedataProductFeeCaseClasses { `type`: String ) - case class deleteProductFee(feeId: String) + case class deleteProductFee(productFeeId: String) } object RemotedataProductFeeCaseClasses extends RemotedataProductFeeCaseClasses diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala index 57aab4d47..2cb4237ec 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala @@ -264,7 +264,7 @@ trait ProductAttribute { trait ProductFee { def bankId: BankId def productCode: ProductCode - def feeId: String + def productFeeId: String def name: String def isActive: Boolean def moreInfo: String From 126925ee2c158518004eb410cf62ddebd628c632 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 13:15:23 +0200 Subject: [PATCH 090/293] feature/OBPv400 added CURD Product Fee endpoints -step5 rename ProductFee -> ProductFeeTrait --- obp-api/src/main/scala/code/api/util/NewStyle.scala | 6 +++--- .../main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala | 8 ++++---- .../src/main/scala/code/bankconnectors/Connector.scala | 6 +++--- .../code/bankconnectors/LocalMappedConnector.scala | 6 +++--- .../code/productfee/MappedProductFeeProvider.scala | 10 +++++----- .../{ProductAttribute.scala => ProductFee.scala} | 10 +++++----- .../commons/model/CommonModelTrait.scala | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) rename obp-api/src/main/scala/code/productfee/{ProductAttribute.scala => ProductFee.scala} (90%) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 58c948497..a0cbc9d45 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1354,7 +1354,7 @@ object NewStyle { frequency: String, `type`: String, callContext: Option[CallContext] - ): OBPReturnType[ProductFee] = { + ): OBPReturnType[ProductFeeTrait] = { Connector.connector.vend.createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, @@ -1375,7 +1375,7 @@ object NewStyle { def getProductFeeById( productFeeId: String, callContext: Option[CallContext] - ) : OBPReturnType[ProductFee] = + ) : OBPReturnType[ProductFeeTrait] = Connector.connector.vend.getProductFeeById( productFeeId: String, callContext: Option[CallContext] @@ -1387,7 +1387,7 @@ object NewStyle { bankId: BankId, productCode: ProductCode, callContext: Option[CallContext] - ): OBPReturnType[List[ProductFee]] = { + ): OBPReturnType[List[ProductFeeTrait]] = { Connector.connector.vend.getProductFeesFromProvider( bankId: BankId, productCode: ProductCode, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index fa0aa9777..c53b1cc7b 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -53,7 +53,7 @@ import code.standingorders.StandingOrderTrait import code.transactionrequests.TransactionRequests.TransactionChallengeTypes import code.userlocks.UserLocks import code.users.UserInvitation -import com.openbankproject.commons.model.{DirectDebitTrait, ProductFee, _} +import com.openbankproject.commons.model.{DirectDebitTrait, ProductFeeTrait, _} import net.liftweb.common.{Box, Full} import net.liftweb.json.JValue import net.liftweb.mapper.By @@ -1454,7 +1454,7 @@ object JSONFactory400 { is_active = productAttribute.isActive ) - def createProductFeeJson(productFee: ProductFee): ProductFeeResponseJsonV400 = + def createProductFeeJson(productFee: ProductFeeTrait): ProductFeeResponseJsonV400 = ProductFeeResponseJsonV400( bank_id = productFee.bankId.value, product_code = productFee.productCode.value, @@ -1470,7 +1470,7 @@ object JSONFactory400 { ) ) - def createProductFeesJson(productFees: List[ProductFee]): ProductFeesResponseJsonV400 = + def createProductFeesJson(productFees: List[ProductFeeTrait]): ProductFeesResponseJsonV400 = ProductFeesResponseJsonV400(productFees.map(createProductFeeJson)) @@ -1610,7 +1610,7 @@ object JSONFactory400 { def createProductsJson(productsList: List[Product]) : ProductsJsonV400 = { ProductsJsonV400(productsList.map(createProductJson))} - def createProductJson(product: Product, productAttributes: List[ProductAttribute], productFees:List[ProductFee]) : ProductJsonV400 = { + def createProductJson(product: Product, productAttributes: List[ProductAttribute], productFees:List[ProductFeeTrait]) : ProductJsonV400 = { ProductJsonV400( bank_id = product.bankId.toString, product_code = product.code.value, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 41f6b6b71..fb7d71a99 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1608,18 +1608,18 @@ trait Connector extends MdcLoggable { frequency: String, `type`: String, callContext: Option[CallContext] - ): OBPReturnType[Box[ProductFee]]= Future(Failure(setUnimplementedError)) + ): OBPReturnType[Box[ProductFeeTrait]]= Future(Failure(setUnimplementedError)) def getProductFeesFromProvider( bankId: BankId, productCode: ProductCode, callContext: Option[CallContext] - ): OBPReturnType[Box[List[ProductFee]]] = Future(Failure(setUnimplementedError)) + ): OBPReturnType[Box[List[ProductFeeTrait]]] = Future(Failure(setUnimplementedError)) def getProductFeeById( productFeeId: String, callContext: Option[CallContext] - ): OBPReturnType[Box[ProductFee]] = Future(Failure(setUnimplementedError)) + ): OBPReturnType[Box[ProductFeeTrait]] = Future(Failure(setUnimplementedError)) def createOrUpdateFXRate( diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 4449608ef..47af9d7bb 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2725,7 +2725,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { frequency: String, `type`: String, callContext: Option[CallContext] - ): OBPReturnType[Box[ProductFee]] = { + ): OBPReturnType[Box[ProductFeeTrait]] = { ProductFeeX.productFeeProvider.vend.createOrUpdateProductFee( bankId: BankId, productCode: ProductCode, @@ -2746,7 +2746,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { bankId: BankId, productCode: ProductCode, callContext: Option[CallContext] - ): OBPReturnType[Box[List[ProductFee]]] = { + ): OBPReturnType[Box[List[ProductFeeTrait]]] = { ProductFeeX.productFeeProvider.vend.getProductFeesFromProvider(bankId: BankId, productCode: ProductCode) map { (_, callContext) } @@ -2755,7 +2755,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { override def getProductFeeById( productFeeId: String, callContext: Option[CallContext] - ): OBPReturnType[Box[ProductFee]] = { + ): OBPReturnType[Box[ProductFeeTrait]] = { ProductFeeX.productFeeProvider.vend.getProductFeeById(productFeeId) map { (_, callContext) } diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala index 49a6ba2c3..610e234e2 100644 --- a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -2,7 +2,7 @@ package code.productfee import code.api.util.APIUtil import code.util.UUIDString -import com.openbankproject.commons.model.{BankId, ProductCode, ProductFee} +import com.openbankproject.commons.model.{BankId, ProductCode, ProductFeeTrait} import net.liftweb.common.{Box, Empty, Full} import net.liftweb.mapper.{MappedBoolean, _} import net.liftweb.util.Helpers.tryo @@ -15,7 +15,7 @@ import scala.concurrent.Future object MappedProductFeeProvider extends ProductFeeProvider { - override def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFee]]] = + override def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFeeTrait]]] = Future { Box !! MappedProductFee.findAll( By(MappedProductFee.BankId, bankId.value), @@ -23,7 +23,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { ) } - override def getProductFeeById(productFeeId: String): Future[Box[ProductFee]] = Future { + override def getProductFeeById(productFeeId: String): Future[Box[ProductFeeTrait]] = Future { MappedProductFee.find(By(MappedProductFee.ProductFeeId, productFeeId)) } @@ -38,7 +38,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { amount: BigDecimal, frequency: String, `type`: String - ): Future[Box[ProductFee]] = { + ): Future[Box[ProductFeeTrait]] = { productFeeId match { case Some(id) => Future { MappedProductFee.find(By(MappedProductFee.ProductFeeId, id)) match { @@ -85,7 +85,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { } } -class MappedProductFee extends ProductFee with LongKeyedMapper[MappedProductFee] with IdPK { +class MappedProductFee extends ProductFeeTrait with LongKeyedMapper[MappedProductFee] with IdPK { override def getSingleton = MappedProductFee diff --git a/obp-api/src/main/scala/code/productfee/ProductAttribute.scala b/obp-api/src/main/scala/code/productfee/ProductFee.scala similarity index 90% rename from obp-api/src/main/scala/code/productfee/ProductAttribute.scala rename to obp-api/src/main/scala/code/productfee/ProductFee.scala index 21f180621..85b242a94 100644 --- a/obp-api/src/main/scala/code/productfee/ProductAttribute.scala +++ b/obp-api/src/main/scala/code/productfee/ProductFee.scala @@ -3,7 +3,7 @@ package code.productfee /* For ProductFee */ import code.api.util.APIUtil -import com.openbankproject.commons.model.{BankId, ProductCode, ProductFee} +import com.openbankproject.commons.model.{BankId, ProductCode, ProductFeeTrait} import net.liftweb.common.{Box, Logger} import net.liftweb.util.SimpleInjector @@ -17,7 +17,7 @@ object ProductFeeX extends SimpleInjector { def buildOne: ProductFeeProvider = MappedProductFeeProvider // Helper to get the count out of an option - def countOfProductFee(listOpt: Option[List[ProductFee]]): Int = { + def countOfProductFee(listOpt: Option[List[ProductFeeTrait]]): Int = { val count = listOpt match { case Some(list) => list.size case None => 0 @@ -32,9 +32,9 @@ trait ProductFeeProvider { private val logger = Logger(classOf[ProductFeeProvider]) - def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFee]]] + def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFeeTrait]]] - def getProductFeeById(productFeeId: String): Future[Box[ProductFee]] + def getProductFeeById(productFeeId: String): Future[Box[ProductFeeTrait]] def createOrUpdateProductFee( bankId: BankId, @@ -47,7 +47,7 @@ trait ProductFeeProvider { amount: BigDecimal, frequency: String, `type`: String - ): Future[Box[ProductFee]] + ): Future[Box[ProductFeeTrait]] def deleteProductFee(productFeeId: String): Future[Box[Boolean]] } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala index 2cb4237ec..ec577d4fa 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala @@ -261,7 +261,7 @@ trait ProductAttribute { def isActive: Option[Boolean] } -trait ProductFee { +trait ProductFeeTrait { def bankId: BankId def productCode: ProductCode def productFeeId: String From 1292869a9d104097d08c07cc660eb4d2fd30baed Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 13:17:51 +0200 Subject: [PATCH 091/293] feature/OBPv400 added CURD Product Fee endpoints -step6 rename MappedProductFee -> MappedProduct --- .../main/scala/bootstrap/liftweb/Boot.scala | 4 ++-- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 1 - .../productfee/MappedProductFeeProvider.scala | 20 +++++++++---------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index b6265d8cd..62301282c 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -104,7 +104,7 @@ import code.dynamicMessageDoc.DynamicMessageDoc import code.dynamicResourceDoc.DynamicResourceDoc import code.endpointMapping.EndpointMapping import code.endpointTag.EndpointTag -import code.productfee.MappedProductFee +import code.productfee.ProductFee import code.snippet.{OAuthAuthorisation, OAuthWorkedThanks} import code.socialmedia.MappedSocialMedia import code.standingorders.StandingOrder @@ -947,7 +947,7 @@ object ToSchemify { DynamicResourceDoc, DynamicMessageDoc, EndpointTag, - MappedProductFee + ProductFee )++ APIBuilder_Connector.allAPIBuilderModels // start grpc server diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index c53b1cc7b..81654aa29 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -47,7 +47,6 @@ import code.atms.Atms.Atm import code.consent.MappedConsent import code.entitlement.Entitlement import code.model.{Consumer, ModeratedBankAccount, ModeratedBankAccountCore} -import code.productfee.MappedProductFee import code.ratelimiting.RateLimiting import code.standingorders.StandingOrderTrait import code.transactionrequests.TransactionRequests.TransactionChallengeTypes diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala index 610e234e2..b56c50fbd 100644 --- a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -17,14 +17,14 @@ object MappedProductFeeProvider extends ProductFeeProvider { override def getProductFeesFromProvider(bankId: BankId, productCode: ProductCode): Future[Box[List[ProductFeeTrait]]] = Future { - Box !! MappedProductFee.findAll( - By(MappedProductFee.BankId, bankId.value), - By(MappedProductFee.ProductCode, productCode.value) + Box !! ProductFee.findAll( + By(ProductFee.BankId, bankId.value), + By(ProductFee.ProductCode, productCode.value) ) } override def getProductFeeById(productFeeId: String): Future[Box[ProductFeeTrait]] = Future { - MappedProductFee.find(By(MappedProductFee.ProductFeeId, productFeeId)) + ProductFee.find(By(ProductFee.ProductFeeId, productFeeId)) } override def createOrUpdateProductFee( @@ -41,7 +41,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { ): Future[Box[ProductFeeTrait]] = { productFeeId match { case Some(id) => Future { - MappedProductFee.find(By(MappedProductFee.ProductFeeId, id)) match { + ProductFee.find(By(ProductFee.ProductFeeId, id)) match { case Full(productFee) => tryo { productFee .BankId(bankId.value) @@ -60,7 +60,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { } case None => Future { Full { - MappedProductFee + ProductFee .create .ProductFeeId(APIUtil.generateUUID) .BankId(bankId.value) @@ -80,14 +80,14 @@ object MappedProductFeeProvider extends ProductFeeProvider { override def deleteProductFee(productFeeId: String): Future[Box[Boolean]] = Future { tryo( - MappedProductFee.bulkDelete_!!(By(MappedProductFee.ProductFeeId, productFeeId)) + ProductFee.bulkDelete_!!(By(ProductFee.ProductFeeId, productFeeId)) ) } } -class MappedProductFee extends ProductFeeTrait with LongKeyedMapper[MappedProductFee] with IdPK { +class ProductFee extends ProductFeeTrait with LongKeyedMapper[ProductFee] with IdPK { - override def getSingleton = MappedProductFee + override def getSingleton = ProductFee object BankId extends UUIDString(this) @@ -134,7 +134,7 @@ class MappedProductFee extends ProductFeeTrait with LongKeyedMapper[MappedProduc } -object MappedProductFee extends MappedProductFee with LongKeyedMetaMapper[MappedProductFee] { +object ProductFee extends ProductFee with LongKeyedMetaMapper[ProductFee] { override def dbIndexes = Index(BankId) :: Index(ProductFeeId) :: super.dbIndexes } From aa851d1b889d46250ce6ebd3a0a34b2ebf556402 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 13:56:22 +0200 Subject: [PATCH 092/293] docfix/tweaked the ErrorMessages code --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index ac8076acb..3224f8f7e 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -371,7 +371,7 @@ object ErrorMessages { val AccountRoutingAlreadyExist = "OBP-30115: Account Routing already exist." val InvalidPaymentSystemName = "OBP-30116: Invalid payment system name. The payment system name should only contain 0-9/a-z/A-Z/'-'/'.'/'_', the length should be smaller than 200." - val ProductFeeNotFoundById = "OBP-30017: Product Fee not found. Please specify a valid value for PRODUCT_FEE_ID." + val ProductFeeNotFoundById = "OBP-30117: Product Fee not found. Please specify a valid value for PRODUCT_FEE_ID." val EntitlementIsBankRole = "OBP-30205: This entitlement is a Bank Role. Please set bank_id to a valid bank id." From 49ad104bf1967ced84d2e16498ae7b9d77770cd3 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 15:12:05 +0200 Subject: [PATCH 093/293] feature/OBPv400 added CURD Product Fee endpoints -step7 added the delete product fee --- .../main/scala/code/api/util/NewStyle.scala | 11 ++++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 36 +++++++++++++++++++ .../scala/code/bankconnectors/Connector.scala | 5 +++ .../bankconnectors/LocalMappedConnector.scala | 8 +++++ 4 files changed, 60 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index a0cbc9d45..fbe5cb47d 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1383,6 +1383,17 @@ object NewStyle { i => (unboxFullOrFail(i._1, callContext, ProductFeeNotFoundById + " {" + productFeeId + "}", 404), i._2) } + def deleteProductFee( + productFeeId: String, + callContext: Option[CallContext] + ) : OBPReturnType[Boolean] = + Connector.connector.vend.deleteProductFee( + productFeeId: String, + callContext: Option[CallContext] + ) map { + i => (unboxFullOrFail(i._1, callContext, ProductFeeNotFoundById + " {" + productFeeId + "}", 404), i._2) + } + def getProductFeesFromProvider( bankId: BankId, productCode: ProductCode, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 580705876..692aee6e5 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5805,6 +5805,42 @@ trait APIMethods400 { } } } + staticResourceDocs += ResourceDoc( + deleteProductFee, + implementedInApiVersion, + nameOf(deleteProductFee), + "DELETE", + "/banks/BANK_ID/products/PRODUCT_CODE/fees/PRODUCT_FEE_ID", + "Delete Product Fee", + s"""Delete Product Fee + | + |Delete one product fee by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + BooleanBody(true), + List( + $UserNotLoggedIn, + $BankNotFound, + UserHasMissingRoles, + UnknownError + ), + List(apiTagProduct, apiTagNewStyle), + Some(List(canDeleteProductFee))) + + lazy val deleteProductFee : OBPEndpoint = { + case "banks" :: bankId :: "products" :: productCode:: "fees" :: productFeeId :: Nil JsonDelete _ => { + cc => + for { + (_, callContext) <- NewStyle.function.getProductFeeById(productFeeId, Some(cc)) + (productFee, callContext) <- NewStyle.function.deleteProductFee(productFeeId, Some(cc)) + } yield { + (productFee, HttpCode.`200`(callContext)) + } + } + } staticResourceDocs += ResourceDoc( createOrUpdateTransactionAttributeDefinition, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index fb7d71a99..c3d7ebd58 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1620,6 +1620,11 @@ trait Connector extends MdcLoggable { productFeeId: String, callContext: Option[CallContext] ): OBPReturnType[Box[ProductFeeTrait]] = Future(Failure(setUnimplementedError)) + + def deleteProductFee( + productFeeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Box[Boolean]] = Future(Failure(setUnimplementedError)) def createOrUpdateFXRate( diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 47af9d7bb..513332677 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2761,6 +2761,14 @@ object LocalMappedConnector extends Connector with MdcLoggable { } } + override def deleteProductFee( + productFeeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Box[Boolean]] = { + ProductFeeX.productFeeProvider.vend.deleteProductFee(productFeeId) map { + (_, callContext) + } + } override def createOrUpdateProduct(bankId: String, code: String, From 416ba867450c8d6a27e31c053849091826c1b64b Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 17:19:47 +0200 Subject: [PATCH 094/293] feature/OBPv400 added CURD Product Fee endpoints -step8 deleted the ProductFee in DeleteProductCascade endpoint --- .../src/main/scala/deletion/DeleteProductCascade.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/obp-api/src/main/scala/deletion/DeleteProductCascade.scala b/obp-api/src/main/scala/deletion/DeleteProductCascade.scala index 0432ab8c5..dc68b2b56 100644 --- a/obp-api/src/main/scala/deletion/DeleteProductCascade.scala +++ b/obp-api/src/main/scala/deletion/DeleteProductCascade.scala @@ -6,6 +6,7 @@ import code.api.util.APIUtil.fullBoxOrException import code.api.util.ErrorMessages.CouldNotDeleteCascade import code.model.dataAccess.MappedBankAccount import code.productAttributeattribute.MappedProductAttribute +import code.productfee.ProductFee import code.products.MappedProduct import com.openbankproject.commons.model.{BankId, ProductCode} import deletion.DeletionUtil.databaseAtomicTask @@ -22,6 +23,7 @@ object DeleteProductCascade { deleteProductAttributes(bankId, code) :: deleteProductAttributeDefinitions(bankId, code) :: deleteProduct(bankId, code) :: + deleteProductFee(bankId, code) :: Nil doneTasks.forall(_ == true) } @@ -68,5 +70,11 @@ object DeleteProductCascade { By(MappedProduct.mCode, code.value) ) } + private def deleteProductFee(bankId: BankId, code: ProductCode): Boolean = { + ProductFee.bulkDelete_!!( + By(ProductFee.BankId, bankId.value), + By(ProductFee.ProductCode, code.value) + ) + } } From 0e5c14566a703299e3ed258539ca0116203d9eff Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 8 Sep 2021 18:12:43 +0200 Subject: [PATCH 095/293] feature/OBPv400 added CURD Product Fee endpoints -step9 added the tests --- .../scala/code/api/v4_0_0/APIMethods400.scala | 2 +- .../code/api/v4_0_0/ProductFeeTest.scala | 263 ++++++++++++++++++ 2 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 692aee6e5..d5de640a6 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5837,7 +5837,7 @@ trait APIMethods400 { (_, callContext) <- NewStyle.function.getProductFeeById(productFeeId, Some(cc)) (productFee, callContext) <- NewStyle.function.deleteProductFee(productFeeId, Some(cc)) } yield { - (productFee, HttpCode.`200`(callContext)) + (productFee, HttpCode.`204`(callContext)) } } } diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala new file mode 100644 index 000000000..9c4807ab5 --- /dev/null +++ b/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala @@ -0,0 +1,263 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH +Osloerstrasse 16/17 +Berlin 13359, Germany + +This product includes software developed at +TESOBE (http://www.tesobe.com/) + */ +package code.api.v4_0_0 + +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.productFeeJsonV400 +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole._ +import code.api.util.ErrorMessages.{ProductFeeNotFoundById, UserHasMissingRoles, UserNotLoggedIn} +import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import code.entitlement.Entitlement +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write +import org.scalatest.Tag + +class ProductFeeTest extends V400ServerSetup { + + override def beforeAll(): Unit = { + super.beforeAll() + } + + override def afterAll(): Unit = { + super.afterAll() + } + + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createProductFee)) + object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getProductFee)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getProductFees)) + object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.updateProductFee)) + object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.deleteProductFee)) + + lazy val testBankId = randomBankId + lazy val parentPutProductJsonV400: PutProductJsonV400 = SwaggerDefinitionsJSON.putProductJsonV400.copy(parent_product_code ="") + def createProduct(code: String, json: PutProductJsonV400) = { + When("We try to create a product v4.0.0") + val request400 = (v4_0_0_Request / "banks" / testBankId / "products" / code).PUT <@ (user1) + val response400 = makePutRequest(request400, write(json)) + Then("We should get a 201") + response400.code should equal(201) + val product = response400.body.extract[ProductJsonV400] + product.product_code shouldBe code + product.parent_product_code shouldBe json.parent_product_code + product.bank_id shouldBe testBankId + product.name shouldBe json.name + product.more_info_url shouldBe json.more_info_url + product.terms_and_conditions_url shouldBe json.terms_and_conditions_url + product.description shouldBe json.description + product + } + + feature("Create Product Fee v4.0.0") { + scenario("We will call the Add endpoint with user credentials and role", + ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5) { + + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProduct.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProductFee.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanUpdateProductFee.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanDeleteProductFee.toString) + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanGetProductFee.toString) + + // Create an grandparent + val grandparent: ProductJsonV400 = createProduct(code = "GRANDPARENT_CODE", json = parentPutProductJsonV400) + + // Create an parent + val product: ProductJsonV400 = createProduct(code = "PARENT_CODE", json = parentPutProductJsonV400.copy(parent_product_code = grandparent.product_code)) + + // Get + val requestGet400 = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code ).GET <@(user1) + val responseGet400 = makeGetRequest(requestGet400) + Then("We should get a 200") + responseGet400.code should equal(200) + val product1 = responseGet400.body.extract[ProductJsonV400] + + // Create an child + val childPutProductJsonV400 = parentPutProductJsonV400.copy(parent_product_code = product.product_code) + createProduct(code = "PRODUCT_CODE", json = childPutProductJsonV400) + + // Get + val requestGetAll400 = (v4_0_0_Request / "banks" / product.bank_id / "products").GET <@(user1) + val responseGetAll400 = makeGetRequest(requestGetAll400) + Then("We should get a 200") + responseGetAll400.code should equal(200) + val products: ProductsJsonV400 = responseGetAll400.body.extract[ProductsJsonV400] + products.products.size shouldBe 3 + + // then we createProductFee + val requestCreateProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fee").POST <@(user1) + + val responseCreateProductFee = makePostRequest(requestCreateProductFee, write(productFeeJsonV400)) + + responseCreateProductFee.code should equal(201) + val productFeeCreate1: ProductFeeResponseJsonV400 = responseCreateProductFee.body.extract[ProductFeeResponseJsonV400] + + productFeeCreate1.name should be(productFeeJsonV400.name) + // then we create second Product Fee + val responseCreateProductFee2 = makePostRequest(requestCreateProductFee, write(productFeeJsonV400)) + + responseCreateProductFee2.code should equal(201) + + val productFeeCreate2: ProductFeeResponseJsonV400 = responseCreateProductFee2.body.extract[ProductFeeResponseJsonV400] + productFeeCreate2.name should be(productFeeJsonV400.name) + + // then we getProductFees + val requestGetProductFees = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees").GET <@(user1) + + val responseGetProductFees = makeGetRequest(requestGetProductFees) + responseGetProductFees.code should equal(200) + val productFees: ProductFeesResponseJsonV400 = responseGetProductFees.body.extract[ProductFeesResponseJsonV400] + + productFees.product_fees.length should be (2) + val productFeeId = productFees.product_fees.head.product_fee_id + + // then we getProductFee + val requestGetProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).GET <@(user1) + val responseGetProductFee = makeGetRequest(requestGetProductFee) + responseGetProductFee.code should equal(200) + val productFee: ProductFeeResponseJsonV400 = responseGetProductFee.body.extract[ProductFeeResponseJsonV400] + + productFee should be (productFees.product_fees.head) + + // then we updateProductFee + val requestPutProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).PUT <@(user1) + val updatedName = "test Case 123" + val responsePutProductFee = makePutRequest(requestPutProductFee,write(productFeeJsonV400.copy(name = updatedName)) ) + responsePutProductFee.code should equal(201) + val putProductFee: ProductFeeResponseJsonV400 = responsePutProductFee.body.extract[ProductFeeResponseJsonV400] + putProductFee.name should be (updatedName) + + // then we getProductFee + val responseGetProductFeeUpdated = makeGetRequest(requestGetProductFee) + val productFeeUpdated: ProductFeeResponseJsonV400 = responseGetProductFeeUpdated.body.extract[ProductFeeResponseJsonV400] + + productFeeUpdated.name should be (updatedName) + + // then we deleteProductFee + val requestDeleteProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).DELETE <@(user1) + val responseDeleteProductFee = makeDeleteRequest(requestDeleteProductFee) + responseDeleteProductFee.code should equal(204) + + // then we getProductFee + val responseGetProductFeeAfterDeleted = makeGetRequest(requestGetProductFee) + responseGetProductFeeAfterDeleted.code should equal(404) + responseGetProductFeeAfterDeleted.body.toString contains(ProductFeeNotFoundById) should be (true) + } + + scenario("We will test the error cases", + ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, ApiEndpoint5) { + Entitlement.entitlement.vend.addEntitlement(testBankId, resourceUser1.userId, CanCreateProduct.toString) + // Create an grandparent + val grandparent: ProductJsonV400 = createProduct(code = "GRANDPARENT_CODE", json = parentPutProductJsonV400) + + // Create an parent + val product: ProductJsonV400 = createProduct(code = "PARENT_CODE", json = parentPutProductJsonV400.copy(parent_product_code = grandparent.product_code)) + + // then we createProductFee + val requestCreateProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fee").POST + val responseCreateProductFee = makePostRequest(requestCreateProductFee, write(productFeeJsonV400)) + responseCreateProductFee.code should equal(401) + responseCreateProductFee.body.toString contains(UserNotLoggedIn) should be (true) + + { + val requestCreateProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fee").POST <@(user1) + val responseCreateProductFee = makePostRequest(requestCreateProductFee, write(productFeeJsonV400)) + responseCreateProductFee.code should equal(403) + responseCreateProductFee.body.toString contains(UserHasMissingRoles) should be (true) + responseCreateProductFee.body.toString contains(canCreateProductFee.toString()) should be (true) + } + + + // then we getProductFees + val requestGetProductFees = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees").GET + val responseGetProductFees = makeGetRequest(requestGetProductFees) + responseGetProductFees.code should equal(401) + responseGetProductFees.body.toString contains(UserNotLoggedIn) should be (true) + + { + val requestGetProductFees = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees").GET <@(user1) + val responseGetProductFees = makeGetRequest(requestGetProductFees) + responseGetProductFees.code should equal(403) + responseGetProductFees.body.toString contains(UserHasMissingRoles) should be (true) + responseGetProductFees.body.toString contains(canGetProductFee.toString()) should be (true) + } + + // then we getProductFee + val productFeeId = "xxx" + val requestGetProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).GET + val responseGetProductFee = makeGetRequest(requestGetProductFee) + responseGetProductFee.code should equal(401) + responseGetProductFee.body.toString contains(UserNotLoggedIn) should be (true) + + { + val requestGetProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).GET <@(user1) + val responseGetProductFee = makeGetRequest(requestGetProductFee) + responseGetProductFee.code should equal(403) + responseGetProductFee.body.toString contains(UserHasMissingRoles) should be (true) + responseGetProductFee.body.toString contains(canGetProductFee.toString()) should be (true) + } + + // then we updateProductFee + val requestPutProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).PUT + val updatedName = "test Case 123" + val responsePutProductFee = makePutRequest(requestPutProductFee,write(productFeeJsonV400.copy(name = updatedName)) ) + responsePutProductFee.code should equal(401) + responsePutProductFee.body.toString contains(UserNotLoggedIn) should be (true) + + { + val requestPutProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).PUT <@(user1) + val updatedName = "test Case 123" + val responsePutProductFee = makePutRequest(requestPutProductFee,write(productFeeJsonV400.copy(name = updatedName)) ) + responsePutProductFee.code should equal(403) + responsePutProductFee.body.toString contains(UserHasMissingRoles) should be (true) + responsePutProductFee.body.toString contains(canUpdateProductFee.toString()) should be (true) + } + + // then we deleteProductFee + val requestDeleteProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).DELETE + val responseDeleteProductFee = makeDeleteRequest(requestDeleteProductFee) + responseDeleteProductFee.code should equal(401) + responseDeleteProductFee.body.toString contains(UserNotLoggedIn) should be (true) + + { + val requestDeleteProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).DELETE <@(user1) + val responseDeleteProductFee = makeDeleteRequest(requestDeleteProductFee) + responseDeleteProductFee.code should equal(403) + responseDeleteProductFee.body.toString contains(UserHasMissingRoles) should be (true) + responseDeleteProductFee.body.toString contains(canDeleteProductFee.toString()) should be (true) + } + + } + } +} From 66e024155898e987f791374939fc282b42fa5725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 9 Sep 2021 12:23:22 +0200 Subject: [PATCH 096/293] feature/Add attributes to Bank Model 1 --- .../main/scala/bootstrap/liftweb/Boot.scala | 2 + .../SwaggerDefinitionsJSON.scala | 25 ++- .../main/scala/code/api/util/ApiRole.scala | 6 + .../main/scala/code/api/util/NewStyle.scala | 32 ++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 167 ++++++++++++++++++ .../code/api/v4_0_0/JSONFactory4.0.0.scala | 44 ++++- .../code/bankattribute/BankAttribute.scala | 69 ++++++++ .../MappedBankAttributeProvider.scala | 94 ++++++++++ .../scala/code/bankconnectors/Connector.scala | 14 ++ .../bankconnectors/LocalMappedConnector.scala | 24 +++ .../code/obp/grpc/HelloWorldServer.scala | 2 +- .../code/remotedata/RemotedataActors.scala | 3 +- .../remotedata/RemotedataBankAttribute.scala | 29 +++ .../RemotedataBankAttributeActor.scala | 50 ++++++ .../src/test/resources/frozen_type_meta_data | Bin 90568 -> 90735 bytes .../commons/model/CommonModelTrait.scala | 9 + .../commons/model/enums/Enumerations.scala | 9 + 17 files changed, 572 insertions(+), 7 deletions(-) create mode 100644 obp-api/src/main/scala/code/bankattribute/BankAttribute.scala create mode 100644 obp-api/src/main/scala/code/bankattribute/MappedBankAttributeProvider.scala create mode 100644 obp-api/src/main/scala/code/remotedata/RemotedataBankAttribute.scala create mode 100644 obp-api/src/main/scala/code/remotedata/RemotedataBankAttributeActor.scala diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index bcad10509..20cdfef92 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -100,6 +100,7 @@ import code.scheduler.DatabaseDriverScheduler import code.scope.{MappedScope, MappedUserScope} import code.apicollectionendpoint.ApiCollectionEndpoint import code.apicollection.ApiCollection +import code.bankattribute.BankAttribute import code.connectormethod.ConnectorMethod import code.dynamicMessageDoc.DynamicMessageDoc import code.dynamicResourceDoc.DynamicResourceDoc @@ -888,6 +889,7 @@ object ToSchemify { MappedCustomerAttribute, MappedTransactionAttribute, MappedCardAttribute, + BankAttribute, RateLimiting, MappedCustomerDependant, AttributeDefinition diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 91c8de2f9..f4047c5c2 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -839,7 +839,8 @@ object SwaggerDefinitionsJSON { full_name = "full_name", logo = "logo", website = "www.openbankproject.com", - bank_routings = List(bankRoutingJsonV121) + bank_routings = List(bankRoutingJsonV121), + None ) val banksJSON400 = BanksJson400( @@ -3489,6 +3490,22 @@ object SwaggerDefinitionsJSON { is_active = Some(true) ) + val bankAttributeJsonV400 = BankAttributeJsonV400( + name = "TAX_ID", + `type` = "INTEGER", + value = "12345678", + is_active = Some(true) + ) + val bankAttributeResponseJsonV400 = BankAttributeResponseJsonV400( + bank_id = bankIdExample.value, + bank_attribute_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f", + name = "OVERDRAFT_START_DATE", + `type` = "DATE_WITH_DAY", + value = "2012-04-23", + is_active = Some(true) + ) + + val accountAttributeJson = AccountAttributeJson( name = "OVERDRAFT_START_DATE", `type` = "DATE_WITH_DAY", @@ -4121,9 +4138,15 @@ object SwaggerDefinitionsJSON { val productAttributeDefinitionJsonV400 = templateAttributeDefinitionJsonV400.copy(category = AttributeCategory.Product.toString) + val bankAttributeDefinitionJsonV400 = + templateAttributeDefinitionJsonV400.copy(category = AttributeCategory.Bank.toString) + val productAttributeDefinitionResponseJsonV400 = templateAttributeDefinitionResponseJsonV400.copy(category = AttributeCategory.Product.toString) + val bankAttributeDefinitionResponseJsonV400 = + templateAttributeDefinitionResponseJsonV400.copy(category = AttributeCategory.Bank.toString) + val transactionAttributeDefinitionJsonV400 = templateAttributeDefinitionJsonV400.copy(category = AttributeCategory.Transaction.toString) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index a744fed8e..ae95788ce 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -418,6 +418,9 @@ object ApiRole { case class CanCreateProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateProductAttribute = CanCreateProductAttribute() + + case class CanCreateBankAttribute(requiresBankId: Boolean = true) extends ApiRole + lazy val canCreateBankAttribute = CanCreateBankAttribute() case class CanMaintainProductCollection(requiresBankId: Boolean = true) extends ApiRole lazy val canMaintainProductCollection = CanMaintainProductCollection() @@ -630,6 +633,9 @@ object ApiRole { case class CanCreateProductAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateProductAttributeDefinitionAtOneBank = CanCreateProductAttributeDefinitionAtOneBank() + case class CanCreateBankAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole + lazy val canCreateBankAttributeDefinitionAtOneBank = CanCreateBankAttributeDefinitionAtOneBank() + case class CanCreateTransactionAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateTransactionAttributeDefinitionAtOneBank = CanCreateTransactionAttributeDefinitionAtOneBank() diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 946ce3c04..2c0c97306 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -3,6 +3,7 @@ package code.api.util import java.io import java.util.Date import java.util.UUID.randomUUID + import akka.http.scaladsl.model.HttpMethod import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT} import code.api.APIFailureNewStyle @@ -63,6 +64,7 @@ import net.liftweb.http.JsonResponse import net.liftweb.util.Props import code.api.JsonResponseException import code.api.v4_0_0.dynamic.{DynamicEndpointHelper, DynamicEntityInfo} +import code.bankattribute.BankAttribute import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod} import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc} import code.dynamicResourceDoc.{DynamicResourceDocProvider, JsonDynamicResourceDoc} @@ -1338,7 +1340,37 @@ object NewStyle { i => (connectorEmptyResponse(i._1, callContext), i._2) } } + + def createOrUpdateBankAttribute( + bankId: BankId, + bankAttributeId: Option[String], + name: String, + attributeType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean], + callContext: Option[CallContext] + ): OBPReturnType[BankAttribute] = { + Connector.connector.vend.createOrUpdateBankAttribute( + bankId: BankId, + bankAttributeId: Option[String], + name: String, + attributeType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean], + callContext: Option[CallContext] + ) map { + i => (connectorEmptyResponse(i._1, callContext), i._2) + } + } + def getBankAttributesByBank(bank: BankId,callContext: Option[CallContext]): OBPReturnType[List[BankAttribute]] = { + Connector.connector.vend.getBankAttributesByBank( + bank: BankId, + callContext: Option[CallContext] + ) map { + i => (connectorEmptyResponse(i._1, callContext), i._2) + } + } def getProductAttributesByBankAndCode( bank: BankId, productCode: ProductCode, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 7d9c5f0fa..e89101e4f 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -256,6 +256,38 @@ trait APIMethods400 { } } + + + staticResourceDocs += ResourceDoc( + getBank, + implementedInApiVersion, + nameOf(getBank), + "GET", + "/banks/BANK_ID", + "Get Bank", + """Get the bank specified by BANK_ID + |Returns information about a single bank specified by BANK_ID including: + | + |* Short and full name of bank + |* Logo URL + |* Website""", + emptyObjectJson, + bankJson400, + List(UserNotLoggedIn, UnknownError, BankNotFound), + apiTagBank :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil + ) + + lazy val getBank : OBPEndpoint = { + case "banks" :: BankId(bankId) :: Nil JsonGet _ => { + cc => + for { + (bank, callContext) <- NewStyle.function.getBank(bankId, cc.callContext) + (attributes, callContext) <- NewStyle.function.getBankAttributesByBank(bankId, callContext) + } yield + (JSONFactory400.createBankJSON400(bank, attributes), HttpCode.`200`(callContext)) + } + } + staticResourceDocs += ResourceDoc( ibanChecker, @@ -5633,6 +5665,141 @@ trait APIMethods400 { + staticResourceDocs += ResourceDoc( + createOrUpdateBankAttributeDefinition, + implementedInApiVersion, + nameOf(createOrUpdateBankAttributeDefinition), + "PUT", + "/banks/BANK_ID/attribute-definitions/bank", + "Create or Update Bank Attribute Definition", + s""" Create or Update Bank Attribute Definition + | + |The category field must be ${AttributeCategory.Bank} + | + |The type field must be one of; ${AttributeType.DOUBLE}, ${AttributeType.STRING}, ${AttributeType.INTEGER} and ${AttributeType.DATE_WITH_DAY} + | + |${authenticationRequiredMessage(true)} + | + |""", + bankAttributeDefinitionJsonV400, + bankAttributeDefinitionResponseJsonV400, + List( + $UserNotLoggedIn, + $BankNotFound, + InvalidJsonFormat, + UnknownError + ), + List(apiTagBank, apiTagNewStyle), + Some(List(canCreateBankAttributeDefinitionAtOneBank))) + + lazy val createOrUpdateBankAttributeDefinition : OBPEndpoint = { + case "banks" :: BankId(bankId) :: "attribute-definitions" :: "bank" :: Nil JsonPut json -> _=> { + cc => + val failMsg = s"$InvalidJsonFormat The Json body should be the $AttributeDefinitionJsonV400 " + for { + postedData <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { + json.extract[AttributeDefinitionJsonV400] + } + failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + + s"${AttributeType.DOUBLE}(12.1234), ${AttributeType.STRING}(TAX_NUMBER), ${AttributeType.INTEGER} (123)and ${AttributeType.DATE_WITH_DAY}(2012-04-23)" + attributeType <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { + AttributeType.withName(postedData.`type`) + } + failMsg = s"$InvalidJsonFormat The `Category` field can only accept the following field: " + + s"${AttributeCategory.Bank}" + category <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { + AttributeCategory.withName(postedData.category) + } + (attributeDefinition, callContext) <- createOrUpdateAttributeDefinition( + bankId, + postedData.name, + category, + attributeType, + postedData.description, + postedData.alias, + postedData.can_be_seen_on_views, + postedData.is_active, + cc.callContext + ) + } yield { + (JSONFactory400.createAttributeDefinitionJson(attributeDefinition), HttpCode.`201`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + createBankAttribute, + implementedInApiVersion, + nameOf(createBankAttribute), + "POST", + "/banks/BANK_ID/attribute", + "Create Bank Attribute", + s""" Create Bank Attribute + | + |Typical product attributes might be: + | + |ISIN (for International bonds) + |VKN (for German bonds) + |REDCODE (markit short code for credit derivative) + |LOAN_ID (e.g. used for Anacredit reporting) + | + |ISSUE_DATE (When the bond was issued in the market) + |MATURITY_DATE (End of life time of a product) + |TRADABLE + | + |See [FPML](http://www.fpml.org/) for more examples. + | + | + |The type field must be one of "STRING", "INTEGER", "DOUBLE" or DATE_WITH_DAY" + | + | + | + |${authenticationRequiredMessage(true)} + | + |""", + bankAttributeJsonV400, + bankAttributeResponseJsonV400, + List( + InvalidJsonFormat, + UnknownError + ), + List(apiTagBank, apiTagNewStyle), + Some(List(canCreateBankAttribute)) + ) + + lazy val createBankAttribute : OBPEndpoint = { + case "banks" :: bankId :: "attribute" :: Nil JsonPost json -> _=> { + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId, u.userId, canCreateProductAttribute, callContext) + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) + failMsg = s"$InvalidJsonFormat The Json body should be the $BankAttributeJsonV400 " + postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[BankAttributeJsonV400] + } + failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + + s"${BankAttributeType.DOUBLE}(12.1234), ${BankAttributeType.STRING}(TAX_NUMBER), ${BankAttributeType.INTEGER}(123) and ${BankAttributeType.DATE_WITH_DAY}(2012-04-23)" + bankAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { + BankAttributeType.withName(postedData.`type`) + } + (bankAttribute, callContext) <- NewStyle.function.createOrUpdateBankAttribute( + BankId(bankId), + None, + postedData.name, + bankAttributeType, + postedData.value, + postedData.is_active, + callContext: Option[CallContext] + ) + } yield { + (createBakAttributeJson(bankAttribute), HttpCode.`201`(callContext)) + } + } + } + + + staticResourceDocs += ResourceDoc( createOrUpdateTransactionAttributeDefinition, implementedInApiVersion, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 6f8badca6..292b95677 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -28,6 +28,7 @@ package code.api.v4_0_0 import java.text.SimpleDateFormat import java.util.Date + import code.api.attributedefinition.AttributeDefinition import code.api.util.APIUtil import code.api.util.APIUtil.{DateWithDay, DateWithSeconds, stringOptionOrNull, stringOrNull} @@ -44,6 +45,7 @@ import code.api.v3_1_0.{AccountAttributeResponseJson, ProductAttributeResponseWi import code.apicollection.ApiCollectionTrait import code.apicollectionendpoint.ApiCollectionEndpointTrait import code.atms.Atms.Atm +import code.bankattribute.BankAttribute import code.consent.MappedConsent import code.entitlement.Entitlement import code.model.{Consumer, ModeratedBankAccount, ModeratedBankAccountCore} @@ -95,7 +97,8 @@ case class BankJson400( full_name: String, logo: String, website: String, - bank_routings: List[BankRoutingJsonV121] + bank_routings: List[BankRoutingJsonV121], + attributes: Option[List[BankAttributeBankResponseJsonV400]] ) case class BanksJson400(banks: List[BankJson400]) @@ -714,6 +717,24 @@ case class ProductAttributeResponseWithoutBankIdJsonV400( is_active: Option[Boolean] ) +case class BankAttributeJsonV400( + name: String, + `type`: String, + value: String, + is_active: Option[Boolean]) + +case class BankAttributeResponseJsonV400( + bank_id: String, + bank_attribute_id: String, + name: String, + `type`: String, + value: String, + is_active: Option[Boolean] + ) +case class BankAttributeBankResponseJsonV400(name: String, + value: String) +case class BankAttributesResponseJson(list: List[BankAttributeBankResponseJsonV400]) + case class IbanCheckerJsonV400( is_valid: Boolean, details: Option[IbanDetailsJsonV400] @@ -892,7 +913,7 @@ object JSONFactory400 { } - def createBankJSON400(bank: Bank): BankJson400 = { + def createBankJSON400(bank: Bank, attributes: List[BankAttribute] = Nil): BankJson400 = { val obp = BankRoutingJsonV121("OBP", bank.bankId.value) val bic = BankRoutingJsonV121("BIC", bank.swiftBic) val routings = bank.bankRoutingScheme match { @@ -906,12 +927,18 @@ object JSONFactory400 { stringOrNull(bank.fullName), stringOrNull(bank.logoUrl), stringOrNull(bank.websiteUrl), - routings.filter(a => stringOrNull(a.address) != null) + routings.filter(a => stringOrNull(a.address) != null), + Option( + attributes.filter(_.isActive == Some(true)).map(a => BankAttributeBankResponseJsonV400( + name = a.name, + value = a.value) + ) + ) ) } def createBanksJson(l: List[Bank]): BanksJson400 = { - BanksJson400(l.map(createBankJSON400)) + BanksJson400(l.map(i => createBankJSON400(i, Nil))) } def createUserIdInfoJson(user : User) : UserIdJsonV400 = { @@ -1433,6 +1460,15 @@ object JSONFactory400 { value = productAttribute.value, is_active = productAttribute.isActive ) + def createBakAttributeJson(bankAttribute: BankAttribute): BankAttributeResponseJsonV400 = + BankAttributeResponseJsonV400( + bank_id = bankAttribute.bankId.value, + bank_attribute_id = bankAttribute.bankAttributeId, + name = bankAttribute.name, + `type` = bankAttribute.attributeType.toString, + value = bankAttribute.value, + is_active = bankAttribute.isActive + ) def createApiCollectionEndpointsJsonV400(apiCollectionEndpoints: List[ApiCollectionEndpointTrait]) = { diff --git a/obp-api/src/main/scala/code/bankattribute/BankAttribute.scala b/obp-api/src/main/scala/code/bankattribute/BankAttribute.scala new file mode 100644 index 000000000..e83cc6a89 --- /dev/null +++ b/obp-api/src/main/scala/code/bankattribute/BankAttribute.scala @@ -0,0 +1,69 @@ +package code.bankattribute + +/* For ProductAttribute */ + +import code.api.util.APIUtil +import code.remotedata.RemotedataBankAttribute +import com.openbankproject.commons.model.BankId +import com.openbankproject.commons.model.enums.BankAttributeType +import net.liftweb.common.{Box, Logger} +import net.liftweb.util.SimpleInjector + +import scala.concurrent.Future + +object BankAttributeX extends SimpleInjector { + + val bankAttributeProvider = new Inject(buildOne _) {} + + def buildOne: BankAttributeProviderTrait = + APIUtil.getPropsAsBoolValue("use_akka", false) match { + case false => BankAttributeProvider + case true => RemotedataBankAttribute // We will use Akka as a middleware + } + + // Helper to get the count out of an option + def countOfBankAttribute(listOpt: Option[List[BankAttribute]]): Int = { + val count = listOpt match { + case Some(list) => list.size + case None => 0 + } + count + } + + +} + +trait BankAttributeProviderTrait { + + private val logger = Logger(classOf[BankAttributeProviderTrait]) + + def getBankAttributesFromProvider(bankId: BankId): Future[Box[List[BankAttribute]]] + + def getBankAttributeById(bankAttributeId: String): Future[Box[BankAttribute]] + + def createOrUpdateBankAttribute(bankId : BankId, + bankAttributeId: Option[String], + name: String, + attributType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean]): Future[Box[BankAttribute]] + def deleteBankAttribute(bankAttributeId: String): Future[Box[Boolean]] + // End of Trait +} + +class RemotedataBankAttributeCaseClasses { + case class getBankAttributesFromProvider(bank: BankId) + + case class getBankAttributeById(bankAttributeId: String) + + case class createOrUpdateBankAttribute(bankId : BankId, + bankAttributeId: Option[String], + name: String, + attributType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean]) + + case class deleteBankAttribute(bankAttributeId: String) +} + +object RemotedataBankAttributeCaseClasses extends RemotedataBankAttributeCaseClasses diff --git a/obp-api/src/main/scala/code/bankattribute/MappedBankAttributeProvider.scala b/obp-api/src/main/scala/code/bankattribute/MappedBankAttributeProvider.scala new file mode 100644 index 000000000..51482c050 --- /dev/null +++ b/obp-api/src/main/scala/code/bankattribute/MappedBankAttributeProvider.scala @@ -0,0 +1,94 @@ +package code.bankattribute + +import code.util.{MappedUUID, UUIDString} +import com.openbankproject.commons.ExecutionContext.Implicits.global +import com.openbankproject.commons.model.enums.BankAttributeType +import com.openbankproject.commons.model.{BankAttributeTrait, BankId} +import net.liftweb.common.{Box, Empty, Full} +import net.liftweb.mapper.{MappedBoolean, _} +import net.liftweb.util.Helpers.tryo + +import scala.concurrent.Future + + +object BankAttributeProvider extends BankAttributeProviderTrait { + + override def getBankAttributesFromProvider(bankId: BankId): Future[Box[List[BankAttribute]]] = + Future { + Box !! BankAttribute.findAll( + By(BankAttribute.BankId_, bankId.value) + ) + } + + override def getBankAttributeById(bankAttributeId: String): Future[Box[BankAttribute]] = Future { + BankAttribute.find(By(BankAttribute.BankAttributeId, bankAttributeId)) + } + + override def createOrUpdateBankAttribute(bankId: BankId, + bankAttributeId: Option[String], + name: String, + attributType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean]): Future[Box[BankAttribute]] = { + bankAttributeId match { + case Some(id) => Future { + BankAttribute.find(By(BankAttribute.BankAttributeId, id)) match { + case Full(attribute) => tryo { + attribute.BankId_(bankId.value) + .Name(name) + .Type(attributType.toString) + .Value(value) + .IsActive(isActive.getOrElse(true)) + .saveMe() + } + case _ => Empty + } + } + case None => Future { + Full { + BankAttribute.create + .BankId_(bankId.value) + .Name(name) + .Type(attributType.toString()) + .Value(value) + .IsActive(isActive.getOrElse(true)) + .saveMe() + } + } + } + } + + override def deleteBankAttribute(bankAttributeId: String): Future[Box[Boolean]] = Future { + Some( + BankAttribute.bulkDelete_!!(By(BankAttribute.BankAttributeId, bankAttributeId)) + ) + } +} + +class BankAttribute extends BankAttributeTrait with LongKeyedMapper[BankAttribute] with IdPK { + + override def getSingleton = BankAttribute + + object BankId_ extends UUIDString(this) // combination of this + object BankAttributeId extends MappedUUID(this) + object Name extends MappedString(this, 50) + object Type extends MappedString(this, 50) + object Value extends MappedString(this, 255) + object IsActive extends MappedBoolean(this) { + override def defaultValue = true + } + + + override def bankId: BankId = BankId(BankId_.get) + override def bankAttributeId: String = BankAttributeId.get + override def name: String = Name.get + override def attributeType: BankAttributeType.Value = BankAttributeType.withName(Type.get) + override def value: String = Value.get + override def isActive: Option[Boolean] = if (IsActive.jdbcFriendly(IsActive.calcFieldName) == null) { None } else Some(IsActive.get) + +} + +object BankAttribute extends BankAttribute with LongKeyedMetaMapper[BankAttribute] { + override def dbIndexes = Index(BankId_) :: super.dbIndexes +} + diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 22cc525da..d8c30ff8e 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -2,6 +2,7 @@ package code.bankconnectors import java.util.Date import java.util.UUID.randomUUID + import _root_.akka.http.scaladsl.model.HttpMethod import code.accountholders.{AccountHolders, MapperAccountHolders} import code.api.attributedefinition.AttributeDefinition @@ -13,6 +14,7 @@ import code.api.util._ import code.api.v1_4_0.JSONFactory1_4_0.TransactionRequestAccountJsonV140 import code.api.v2_1_0._ import code.api.{APIFailure, APIFailureNewStyle} +import code.bankattribute.BankAttribute import code.bankconnectors.akka.AkkaConnector_vDec2018 import code.bankconnectors.rest.RestConnector_vMar2019 import code.bankconnectors.storedprocedure.StoredProcedureConnector_vDec2019 @@ -1994,6 +1996,18 @@ trait Connector extends MdcLoggable { callContext: Option[CallContext] ): OBPReturnType[Box[ProductAttribute]] = Future{(Failure(setUnimplementedError), callContext)} + def createOrUpdateBankAttribute(bankId: BankId, + productAttributeId: Option[String], + name: String, + bankAttributeType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean], + callContext: Option[CallContext] + ): OBPReturnType[Box[BankAttribute]] = Future{(Failure(setUnimplementedError), callContext)} + + def getBankAttributesByBank(bank: BankId, callContext: Option[CallContext]): OBPReturnType[Box[List[BankAttribute]]] = + Future{(Failure(setUnimplementedError), callContext)} + def getProductAttributeById( productAttributeId: String, callContext: Option[CallContext] diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 05aa3fb03..c5423bfee 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -2,6 +2,7 @@ package code.bankconnectors import java.util.Date import java.util.UUID.randomUUID + import _root_.akka.http.scaladsl.model.HttpMethod import code.DynamicData.DynamicDataProvider import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT} @@ -21,6 +22,7 @@ import code.api.v1_4_0.JSONFactory1_4_0.TransactionRequestAccountJsonV140 import code.api.v2_1_0._ import code.atms.Atms.Atm import code.atms.MappedAtm +import code.bankattribute.{BankAttribute, BankAttributeX} import code.branches.Branches.Branch import code.branches.MappedBranch import code.cardattribute.CardAttributeX @@ -3416,6 +3418,28 @@ object LocalMappedConnector extends Connector with MdcLoggable { attributType: ProductAttributeType.Value, value: String, isActive: Option[Boolean]) map { (_, callContext) + } + override def createOrUpdateBankAttribute(bankId: BankId, + productAttributeId: Option[String], + name: String, + bankAttributeType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean], + callContext: Option[CallContext] + ): OBPReturnType[Box[BankAttribute]] = + BankAttributeX.bankAttributeProvider.vend.createOrUpdateBankAttribute( + bankId: BankId, + productAttributeId: Option[String], + name: String, + bankAttributeType: BankAttributeType.Value, + value: String, isActive: Option[Boolean]) map { + (_, callContext) + } + + + override def getBankAttributesByBank(bank: BankId, callContext: Option[CallContext]): OBPReturnType[Box[List[BankAttribute]]] = + BankAttributeX.bankAttributeProvider.vend.getBankAttributesFromProvider(bank: BankId) map { + (_, callContext) } override def getProductAttributesByBankAndCode( diff --git a/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala b/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala index 4ce3aa324..5f44b06cf 100644 --- a/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala +++ b/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala @@ -76,7 +76,7 @@ class HelloWorldServer(executionContext: ExecutionContext) { self => val (bankList, _) = it val json40: BanksJson400 = JSONFactory400.createBanksJson(bankList) val grpcBanks: List[BankJson400Grpc] = json40.banks.map(bank => { - val BankJson400(id, short_name, full_name, logo, website, bank_routings) = bank + val BankJson400(id, short_name, full_name, logo, website, bank_routings, None) = bank val bankRoutingGrpcs = bank_routings.map(routings => BankRoutingJsonV121Grpc(routings.scheme, routings.address)) BankJson400Grpc(id, short_name, full_name, logo, website, bankRoutingGrpcs) }) diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataActors.scala b/obp-api/src/main/scala/code/remotedata/RemotedataActors.scala index e41ee0b2a..f56583e8a 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataActors.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataActors.scala @@ -66,7 +66,8 @@ object RemotedataActors extends MdcLoggable { ActorProps[RemotedataUserInvitationActor] -> RemotedataUserInvitation.actorName, ActorProps[RemotedataConsentAuthContextActor] -> RemotedataConsentAuthContext.actorName, ActorProps[RemotedataTransactionRequestAttributeActor] -> RemotedataTransactionRequestAttribute.actorName, - ActorProps[RemotedataUserAgreementActor] -> RemotedataUserAgreement.actorName + ActorProps[RemotedataUserAgreementActor] -> RemotedataUserAgreement.actorName, + ActorProps[RemotedataBankAttributeActor] -> RemotedataBankAttribute.actorName ) actorsRemotedata.foreach { a => logger.info(actorSystem.actorOf(a._1, name = a._2)) } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataBankAttribute.scala b/obp-api/src/main/scala/code/remotedata/RemotedataBankAttribute.scala new file mode 100644 index 000000000..bc3d27c37 --- /dev/null +++ b/obp-api/src/main/scala/code/remotedata/RemotedataBankAttribute.scala @@ -0,0 +1,29 @@ +package code.remotedata + +import akka.pattern.ask +import code.actorsystem.ObpActorInit +import code.bankattribute.{BankAttribute, BankAttributeProviderTrait, RemotedataBankAttributeCaseClasses} +import com.openbankproject.commons.model.BankId +import com.openbankproject.commons.model.enums.BankAttributeType +import net.liftweb.common.Box + +import scala.collection.immutable.List +import scala.concurrent.Future + + +object RemotedataBankAttribute extends ObpActorInit with BankAttributeProviderTrait { + + val cc = RemotedataBankAttributeCaseClasses + + override def getBankAttributesFromProvider(bankId: BankId): Future[Box[List[BankAttribute]]] = + (actor ? cc.getBankAttributesFromProvider(bankId)).mapTo[Box[List[BankAttribute]]] + + override def getBankAttributeById(bankAttributeId: String): Future[Box[BankAttribute]] = + (actor ? cc.getBankAttributeById(bankAttributeId)).mapTo[Box[BankAttribute]] + + override def createOrUpdateBankAttribute(bankId: BankId, bankAttributeId: Option[String], name: String, attributType: BankAttributeType.Value, value: String, isActive: Option[Boolean]): Future[Box[BankAttribute]] = + (actor ? cc.createOrUpdateBankAttribute(bankId, bankAttributeId , name , attributType , value, isActive)).mapTo[Box[BankAttribute]] + + override def deleteBankAttribute(bankAttributeId: String): Future[Box[Boolean]] = + (actor ? cc.deleteBankAttribute(bankAttributeId)).mapTo[Box[Boolean]] +} diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataBankAttributeActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataBankAttributeActor.scala new file mode 100644 index 000000000..51c555040 --- /dev/null +++ b/obp-api/src/main/scala/code/remotedata/RemotedataBankAttributeActor.scala @@ -0,0 +1,50 @@ +package code.remotedata + +import akka.actor.Actor +import akka.pattern.pipe +import code.actorsystem.ObpActorHelper +import code.bankattribute.{BankAttributeProvider, RemotedataBankAttributeCaseClasses} +import code.util.Helper.MdcLoggable +import com.openbankproject.commons.ExecutionContext.Implicits.global +import com.openbankproject.commons.model.BankId +import com.openbankproject.commons.model.enums.BankAttributeType + +class RemotedataBankAttributeActor extends Actor with ObpActorHelper with MdcLoggable { + + val mapper = BankAttributeProvider + val cc = RemotedataBankAttributeCaseClasses + + def receive = { + + case cc.getBankAttributesFromProvider(bankId: BankId) => + logger.debug(s"getBankAttributesFromProvider(${bankId})") + mapper.getBankAttributesFromProvider(bankId) pipeTo sender + + case cc.getBankAttributeById(bankAttributeId: String) => + logger.debug(s"getBankAttributeById(${bankAttributeId})") + mapper.getBankAttributeById(bankAttributeId) pipeTo sender + + case cc.createOrUpdateBankAttribute(bankId: BankId, + productAttributeId: Option[String], + name: String, + attributType: BankAttributeType.Value, + value: String, + isActive: Option[Boolean]) => + logger.debug(s"createOrUpdateBankAttribute(${bankId}, ${productAttributeId}, ${name}, ${attributType}, ${value}, ${isActive})") + mapper.createOrUpdateBankAttribute(bankId, + productAttributeId, + name, + attributType, + value, + isActive) pipeTo sender + + case cc.deleteBankAttribute(bankAttributeId: String) => + logger.debug(s"deleteBankAttribute(${bankAttributeId})") + mapper.deleteBankAttribute(bankAttributeId) pipeTo sender + + case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) + } + +} + + diff --git a/obp-api/src/test/resources/frozen_type_meta_data b/obp-api/src/test/resources/frozen_type_meta_data index f9befedaaebf2d0cfe5e7c1bd8bb04d731aef6b9..15e9497fccb0b6719a8a65406ca389b5325e9299 100644 GIT binary patch delta 165 zcmX?cnDzY;)(tvxj6IVb1H>oS>F`ajbY|q<94q&#n2~+5$D}k-uEdg(qRgbylGNf7 z27CX4lFar4lg$q%MbGqJ>v^aUnw; Date: Thu, 9 Sep 2021 12:50:37 +0200 Subject: [PATCH 097/293] feature/OBPv400 added CURD Product Fee endpoints -step10 tweaked Amount to MappedDecimal(this, MathContext.DECIMAL128, 2) --- .../main/scala/code/productfee/MappedProductFeeProvider.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala index b56c50fbd..00b5f20e1 100644 --- a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -105,7 +105,7 @@ class ProductFee extends ProductFeeTrait with LongKeyedMapper[ProductFee] with I object Currency extends MappedString(this, 50) - object Amount extends MappedDecimal(this, MathContext.DECIMAL64, 0) + object Amount extends MappedDecimal(this, MathContext.DECIMAL128, 2) object Frequency extends MappedString(this, 255) From 5627cff1b9ab521953db22a33365f565a1dcf6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 9 Sep 2021 12:59:38 +0200 Subject: [PATCH 098/293] feature/Add attributes to Bank Model 2 --- .../main/scala/code/api/util/ApiRole.scala | 3 + .../main/scala/code/api/util/NewStyle.scala | 12 ++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 56 ++++++++++++++++++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 2 +- .../scala/code/bankconnectors/Connector.scala | 6 +- .../bankconnectors/LocalMappedConnector.scala | 9 ++- 6 files changed, 83 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index ae95788ce..6b0c74616 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -409,6 +409,9 @@ object ApiRole { case class CanUpdateProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateProductAttribute = CanUpdateProductAttribute() + + case class CanUpdateBankAttribute(requiresBankId: Boolean = true) extends ApiRole + lazy val canUpdateBankAttribute = CanUpdateBankAttribute() case class CanGetProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canGetProductAttribute = CanGetProductAttribute() diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 2c0c97306..e5596a61a 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1397,6 +1397,18 @@ object NewStyle { } } + def getBankAttributeById( + bankAttributeId: String, + callContext: Option[CallContext] + ): OBPReturnType[BankAttribute] = { + Connector.connector.vend.getBankAttributeById( + bankAttributeId: String, + callContext: Option[CallContext] + ) map { + i => (connectorEmptyResponse(i._1, callContext), i._2) + } + } + def deleteProductAttribute( productAttributeId: String, callContext: Option[CallContext] diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index e89101e4f..df7438ffc 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5793,7 +5793,61 @@ trait APIMethods400 { callContext: Option[CallContext] ) } yield { - (createBakAttributeJson(bankAttribute), HttpCode.`201`(callContext)) + (createBankAttributeJson(bankAttribute), HttpCode.`201`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + updateBankAttribute, + implementedInApiVersion, + nameOf(updateBankAttribute), + "PUT", + "/banks/BANK_ID/attributes/BANK_ATTRIBUTE_ID", + "Update Bank Attribute", + s""" Update Bank Attribute. + | + |Update one Bak Attribute by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + bankAttributeJsonV400, + bankAttributeDefinitionJsonV400, + List( + UserHasMissingRoles, + UnknownError + ), + List(apiTagBank, apiTagNewStyle)) + + lazy val updateBankAttribute : OBPEndpoint = { + case "banks" :: bankId :: "attributes" :: bankAttributeId :: Nil JsonPut json -> _ =>{ + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId, u.userId, canUpdateBankAttribute, callContext) + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) + failMsg = s"$InvalidJsonFormat The Json body should be the $BankAttributeJsonV400 " + postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[BankAttributeJsonV400] + } + failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + + s"${BankAttributeType.DOUBLE}(12.1234), ${BankAttributeType.STRING}(TAX_NUMBER), ${BankAttributeType.INTEGER}(123) and ${BankAttributeType.DATE_WITH_DAY}(2012-04-23)" + productAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { + BankAttributeType.withName(postedData.`type`) + } + (_, callContext) <- NewStyle.function.getBankAttributeById(bankAttributeId, callContext) + (bankAttribute, callContext) <- NewStyle.function.createOrUpdateBankAttribute( + BankId(bankId), + Some(bankAttributeId), + postedData.name, + productAttributeType, + postedData.value, + postedData.is_active, + callContext: Option[CallContext] + ) + } yield { + (createBankAttributeJson(bankAttribute), HttpCode.`200`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 292b95677..ce7062689 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -1460,7 +1460,7 @@ object JSONFactory400 { value = productAttribute.value, is_active = productAttribute.isActive ) - def createBakAttributeJson(bankAttribute: BankAttribute): BankAttributeResponseJsonV400 = + def createBankAttributeJson(bankAttribute: BankAttribute): BankAttributeResponseJsonV400 = BankAttributeResponseJsonV400( bank_id = bankAttribute.bankId.value, bank_attribute_id = bankAttribute.bankAttributeId, diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index d8c30ff8e..e6a3468d2 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1997,7 +1997,7 @@ trait Connector extends MdcLoggable { ): OBPReturnType[Box[ProductAttribute]] = Future{(Failure(setUnimplementedError), callContext)} def createOrUpdateBankAttribute(bankId: BankId, - productAttributeId: Option[String], + bankAttributeId: Option[String], name: String, bankAttributeType: BankAttributeType.Value, value: String, @@ -2008,6 +2008,10 @@ trait Connector extends MdcLoggable { def getBankAttributesByBank(bank: BankId, callContext: Option[CallContext]): OBPReturnType[Box[List[BankAttribute]]] = Future{(Failure(setUnimplementedError), callContext)} + def getBankAttributeById(bankAttributeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Box[BankAttribute]] = Future{(Failure(setUnimplementedError), callContext)} + def getProductAttributeById( productAttributeId: String, callContext: Option[CallContext] diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index c5423bfee..967827a94 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -3420,7 +3420,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { (_, callContext) } override def createOrUpdateBankAttribute(bankId: BankId, - productAttributeId: Option[String], + bankAttributeId: Option[String], name: String, bankAttributeType: BankAttributeType.Value, value: String, @@ -3429,7 +3429,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { ): OBPReturnType[Box[BankAttribute]] = BankAttributeX.bankAttributeProvider.vend.createOrUpdateBankAttribute( bankId: BankId, - productAttributeId: Option[String], + bankAttributeId: Option[String], name: String, bankAttributeType: BankAttributeType.Value, value: String, isActive: Option[Boolean]) map { @@ -3451,6 +3451,11 @@ object LocalMappedConnector extends Connector with MdcLoggable { (_, callContext) } + override def getBankAttributeById(bankAttributeId: String, callContext: Option[CallContext]): OBPReturnType[Box[BankAttribute]] = + BankAttributeX.bankAttributeProvider.vend.getBankAttributeById(bankAttributeId: String) map { + (_, callContext) + } + override def getProductAttributeById( productAttributeId: String, callContext: Option[CallContext] From 659522251a41dec507ac59a4633d97f1d6cfe67e Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 9 Sep 2021 13:40:52 +0200 Subject: [PATCH 099/293] feature/added the webui_support_email props --- obp-api/src/main/resources/props/sample.props.template | 3 +++ obp-api/src/main/scala/code/snippet/WebUI.scala | 5 +++++ obp-api/src/main/webapp/index.html | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 2b8317b83..72e4feaf5 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -474,6 +474,9 @@ webui_override_style_sheet = ## Link to agree to Terms & Conditions, shown on signup page webui_agree_terms_url = +## The Support Email, shown in the bottom page +#webui_support_email=contact@openbankproject.com + ## Link to Privacy Policy, shown in the bottom page #webui_privacy_policy_url = diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index b5de7c2c9..a60c57fe9 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -215,6 +215,11 @@ class WebUI extends MdcLoggable{ val webUiPropsValue = getWebUiPropsValue("webui_privacy_policy", "") "#privacy-policy-page" #> scala.xml.Unparsed(makeHtml(webUiPropsValue)) } + def supportEmail = { + val webUiPropsValue = getWebUiPropsValue("webui_support_email", "contact@openbankproject.com") + "#webui-support-email a *" #> scala.xml.Unparsed(webUiPropsValue) & + "#webui-support-email a [href]" #> scala.xml.Unparsed(s"mailto:$webUiPropsValue") + } def sandboxIntroductionLink: CssSel = { val webUiApiDocumentation = getWebUiPropsValue("webui_api_documentation_url",s"${getServerUrl}/introduction") diff --git a/obp-api/src/main/webapp/index.html b/obp-api/src/main/webapp/index.html index 7cda7d1dc..30660d88d 100644 --- a/obp-api/src/main/webapp/index.html +++ b/obp-api/src/main/webapp/index.html @@ -434,7 +434,7 @@ Berlin 13359, Germany
      From 612f1d7a79f521b3fc525b78f7f0e01fbea5524c Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 9 Sep 2021 13:44:32 +0200 Subject: [PATCH 100/293] docfix/added webui_support_email to release_notes.md --- release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release_notes.md b/release_notes.md index 0460b1794..acf52bb2c 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action +09/09/2021 65952225 Added props: webui_support_email, default is contact@openbankproject.com 02/09/2021 a826d908 Renamed Web UI props: webui_post_user_invitation_privacy_conditions_value => webui_privacy_policy webui_post_user_invitation_terms_and_conditions_value => webui_terms_and_conditions From 7b9e0dcc755525f9e3086eb044c9e5264a18c13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 9 Sep 2021 14:33:29 +0200 Subject: [PATCH 101/293] feature/Add attributes to Bank Model 3 --- .../main/scala/code/api/util/ApiRole.scala | 3 ++ .../main/scala/code/api/util/NewStyle.scala | 12 ++++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 37 +++++++++++++++++++ .../scala/code/bankconnectors/Connector.scala | 4 ++ .../bankconnectors/LocalMappedConnector.scala | 6 +++ 5 files changed, 62 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 6b0c74616..06ffe0639 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -418,6 +418,9 @@ object ApiRole { case class CanDeleteProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canDeleteProductAttribute = CanDeleteProductAttribute() + + case class CanDeleteBankAttribute(requiresBankId: Boolean = true) extends ApiRole + lazy val canDeleteBankAttribute = CanDeleteBankAttribute() case class CanCreateProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateProductAttribute = CanCreateProductAttribute() diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index e5596a61a..d55ca832f 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1409,6 +1409,18 @@ object NewStyle { } } + def deleteBankAttribute( + bankAttributeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Boolean] = { + Connector.connector.vend.deleteBankAttribute( + bankAttributeId: String, + callContext: Option[CallContext] + ) map { + i => (connectorEmptyResponse(i._1, callContext), i._2) + } + } + def deleteProductAttribute( productAttributeId: String, callContext: Option[CallContext] diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index df7438ffc..a679f76d4 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5852,6 +5852,43 @@ trait APIMethods400 { } } + + staticResourceDocs += ResourceDoc( + deleteBankAttribute, + implementedInApiVersion, + nameOf(deleteBankAttribute), + "DELETE", + "/banks/BANK_ID/attributes/BANK_ATTRIBUTE_ID", + "Delete Bank Attribute", + s""" Delete Bank Attribute + | + |Delete a Bank Attribute by its id. + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + emptyObjectJson, + List( + UserHasMissingRoles, + BankNotFound, + UnknownError + ), + List(apiTagBank, apiTagNewStyle)) + + lazy val deleteBankAttribute : OBPEndpoint = { + case "banks" :: bankId :: "attributes" :: bankAttributeId :: Nil JsonDelete _=> { + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId, u.userId, canDeleteBankAttribute, callContext) + (_, callContext) <- NewStyle.function.getBank(BankId(bankId), callContext) + (bankAttribute, callContext) <- NewStyle.function.deleteBankAttribute(bankAttributeId, callContext) + } yield { + (Full(bankAttribute), HttpCode.`204`(callContext)) + } + } + } staticResourceDocs += ResourceDoc( diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index e6a3468d2..e8bfc6d10 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -2024,6 +2024,10 @@ trait Connector extends MdcLoggable { ): OBPReturnType[Box[List[ProductAttribute]]] = Future{(Failure(setUnimplementedError), callContext)} + def deleteBankAttribute(bankAttributeId: String, + callContext: Option[CallContext] + ): OBPReturnType[Box[Boolean]] = Future{(Failure(setUnimplementedError), callContext)} + def deleteProductAttribute( productAttributeId: String, callContext: Option[CallContext] diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 967827a94..26562f27b 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -3464,6 +3464,12 @@ object LocalMappedConnector extends Connector with MdcLoggable { (_, callContext) } + override def deleteBankAttribute(bankAttributeId: String, + callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = + BankAttributeX.bankAttributeProvider.vend.deleteBankAttribute(bankAttributeId: String) map { + (_, callContext) + } + override def deleteProductAttribute( productAttributeId: String, callContext: Option[CallContext] From 1609fd52c8263cb832ea036bf14f77652bdfff4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 10 Sep 2021 10:28:04 +0200 Subject: [PATCH 102/293] tests/Add attributes to Bank Model 4 --- .../code/api/v4_0_0/BankAttributeTests.scala | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala diff --git a/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala new file mode 100644 index 000000000..bd9ddbfd8 --- /dev/null +++ b/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala @@ -0,0 +1,107 @@ +package code.api.v4_0_0 + +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole.{CanCreateBankAttribute, CanDeleteBankAttribute, CanUpdateBankAttribute} +import code.api.util.ErrorMessages +import code.api.util.ErrorMessages.UserHasMissingRoles +import code.api.v4_0_0.APIMethods400.Implementations4_0_0 +import code.setup.DefaultUsers +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.model.ErrorMessage +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write +import org.scalatest.Tag + +class BankAttributeTests extends V400ServerSetup with DefaultUsers { + + override def beforeAll() { + super.beforeAll() + } + + override def afterAll() { + super.afterAll() + } + + /** + * Test tags + * Example: To run tests with tag "getPermissions": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createBankAttribute)) + object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.updateBankAttribute)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.deleteBankAttribute)) + + lazy val bankId = randomBankId + + feature(s"Assuring that endpoint $ApiEndpoint1 works as expected - $VersionOfApi") { + scenario(s"We try to consume endpoint $ApiEndpoint1 - Anonymous access", ApiEndpoint1, VersionOfApi) { + When("We make the request") + val requestGet = (v4_0_0_Request / "banks" / bankId / "attribute").POST + val responseGet = makePostRequest(requestGet, write(bankAttributeJsonV400)) + Then("We should get a 401") + And("We should get a message: " + ErrorMessages.UserNotLoggedIn) + responseGet.code should equal(401) + responseGet.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn) + } + scenario(s"We try to consume endpoint $ApiEndpoint1 without proper role - Authorized access", ApiEndpoint1, VersionOfApi) { + When("We make the request") + val requestGet = (v4_0_0_Request / "banks" / bankId / "attribute").POST <@ (user1) + val responseGet = makePostRequest(requestGet, write(bankAttributeJsonV400)) + Then("We should get a 403") + And("We should get a message: " + s"$CanCreateBankAttribute entitlement required") + responseGet.code should equal(403) + responseGet.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanCreateBankAttribute) + } + } + + + feature(s"Assuring that endpoint $ApiEndpoint2 works as expected - $VersionOfApi") { + scenario(s"We try to consume endpoint $ApiEndpoint2 - Anonymous access", ApiEndpoint2, VersionOfApi) { + When("We make the request") + val requestGet = (v4_0_0_Request / "banks" / bankId / "attributes" / "DOES_NOT_MATTER").PUT + val responseGet = makePutRequest(requestGet, write(bankAttributeJsonV400)) + Then("We should get a 401") + And("We should get a message: " + ErrorMessages.UserNotLoggedIn) + responseGet.code should equal(401) + responseGet.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn) + } + scenario(s"We try to consume endpoint $ApiEndpoint2 without proper role - Authorized access", ApiEndpoint2, VersionOfApi) { + When("We make the request") + val requestGet = (v4_0_0_Request / "banks" / bankId / "attributes" / "DOES_NOT_MATTER").PUT <@ (user1) + val responseGet = makePutRequest(requestGet, write(bankAttributeJsonV400)) + Then("We should get a 403") + And("We should get a message: " + s"$CanUpdateBankAttribute entitlement required") + responseGet.code should equal(403) + responseGet.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanUpdateBankAttribute) + } + } + + + + feature(s"Assuring that endpoint $ApiEndpoint3 works as expected - $VersionOfApi") { + scenario(s"We try to consume endpoint $ApiEndpoint3 - Anonymous access", ApiEndpoint3, VersionOfApi) { + When("We make the request") + val request = (v4_0_0_Request / "banks" / bankId / "attributes" / "DOES_NOT_MATTER").DELETE + val response = makeDeleteRequest(request) + Then("We should get a 401") + And("We should get a message: " + ErrorMessages.UserNotLoggedIn) + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn) + } + scenario(s"We try to consume endpoint $ApiEndpoint3 without proper role - Authorized access", ApiEndpoint3, VersionOfApi) { + When("We make the request") + val request = (v4_0_0_Request / "banks" / bankId / "attributes" / "DOES_NOT_MATTER").DELETE <@ (user1) + val response = makeDeleteRequest(request) + Then("We should get a 403") + And("We should get a message: " + s"$CanDeleteBankAttribute entitlement required") + response.code should equal(403) + response.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanDeleteBankAttribute) + } + } + + + } \ No newline at end of file From 096dc720f3a042137efe17b88efcc5e59e9e993a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 10 Sep 2021 12:02:20 +0200 Subject: [PATCH 103/293] feature/Add attributes to Bank Model 5 --- .../main/scala/code/api/util/ApiRole.scala | 3 ++ .../scala/code/api/v4_0_0/APIMethods400.scala | 36 +++++++++++++++++++ .../code/api/v4_0_0/BankAttributeTests.scala | 31 +++++++++++++--- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 06ffe0639..159793374 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -412,6 +412,9 @@ object ApiRole { case class CanUpdateBankAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateBankAttribute = CanUpdateBankAttribute() + + case class CanGetBankAttribute(requiresBankId: Boolean = true) extends ApiRole + lazy val canGetBankAttribute = CanGetBankAttribute() case class CanGetProductAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canGetProductAttribute = CanGetProductAttribute() diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index a679f76d4..1d7d7c987 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5797,6 +5797,42 @@ trait APIMethods400 { } } } + + staticResourceDocs += ResourceDoc( + getBankAttributes, + implementedInApiVersion, + nameOf(getBankAttributes), + "GET", + "/banks/BANK_ID/attributes", + "Get Bank Attributes", + s""" Get Bank Attributes + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + transactionAttributesResponseJson, + List( + $UserNotLoggedIn, + $BankNotFound, + InvalidJsonFormat, + UnknownError + ), + List(apiTagBank, apiTagNewStyle), + Some(List(canGetBankAttribute)) + ) + + lazy val getBankAttributes : OBPEndpoint = { + case "banks" :: BankId(bankId) :: "attributes" :: Nil JsonGet _ => { + cc => + for { + (attributes, callContext) <- NewStyle.function.getBankAttributesByBank(bankId, cc.callContext) + } yield { + (JSONFactory400.createBankAttributesJson(attributes), HttpCode.`200`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( updateBankAttribute, diff --git a/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala index bd9ddbfd8..402f62809 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala @@ -2,7 +2,7 @@ package code.api.v4_0_0 import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil.OAuth._ -import code.api.util.ApiRole.{CanCreateBankAttribute, CanDeleteBankAttribute, CanUpdateBankAttribute} +import code.api.util.ApiRole.{CanCreateBankAttribute, CanDeleteBankAttribute, CanGetBankAttribute, CanUpdateBankAttribute} import code.api.util.ErrorMessages import code.api.util.ErrorMessages.UserHasMissingRoles import code.api.v4_0_0.APIMethods400.Implementations4_0_0 @@ -34,6 +34,7 @@ class BankAttributeTests extends V400ServerSetup with DefaultUsers { object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createBankAttribute)) object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.updateBankAttribute)) object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.deleteBankAttribute)) + object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.getBankAttributes)) lazy val bankId = randomBankId @@ -55,8 +56,8 @@ class BankAttributeTests extends V400ServerSetup with DefaultUsers { And("We should get a message: " + s"$CanCreateBankAttribute entitlement required") responseGet.code should equal(403) responseGet.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanCreateBankAttribute) - } } + } feature(s"Assuring that endpoint $ApiEndpoint2 works as expected - $VersionOfApi") { @@ -77,8 +78,8 @@ class BankAttributeTests extends V400ServerSetup with DefaultUsers { And("We should get a message: " + s"$CanUpdateBankAttribute entitlement required") responseGet.code should equal(403) responseGet.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanUpdateBankAttribute) - } } + } @@ -100,8 +101,30 @@ class BankAttributeTests extends V400ServerSetup with DefaultUsers { And("We should get a message: " + s"$CanDeleteBankAttribute entitlement required") response.code should equal(403) response.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanDeleteBankAttribute) - } } + } + + + feature(s"Assuring that endpoint $ApiEndpoint4 works as expected - $VersionOfApi") { + scenario(s"We try to consume endpoint $ApiEndpoint4 - Anonymous access", ApiEndpoint4, VersionOfApi) { + When("We make the request") + val request = (v4_0_0_Request / "banks" / bankId / "attributes").GET + val response = makeGetRequest(request) + Then("We should get a 401") + And("We should get a message: " + ErrorMessages.UserNotLoggedIn) + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn) + } + scenario(s"We try to consume endpoint $ApiEndpoint4 without proper role - Authorized access", ApiEndpoint4, VersionOfApi) { + When("We make the request") + val request = (v4_0_0_Request / "banks" / bankId / "attributes").GET <@ (user1) + val response = makeGetRequest(request) + Then("We should get a 403") + And("We should get a message: " + s"$CanGetBankAttribute entitlement required") + response.code should equal(403) + response.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanGetBankAttribute) + } + } } \ No newline at end of file From 36a48e560fa20e378130be4e73a80f76583a436c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 10 Sep 2021 12:03:10 +0200 Subject: [PATCH 104/293] feature/Add attributes to Bank Model 5 --- obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index ce7062689..8e7d588e9 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -731,6 +731,7 @@ case class BankAttributeResponseJsonV400( value: String, is_active: Option[Boolean] ) +case class BankAttributesResponseJsonV400(bank_attributes: List[BankAttributeResponseJsonV400]) case class BankAttributeBankResponseJsonV400(name: String, value: String) case class BankAttributesResponseJson(list: List[BankAttributeBankResponseJsonV400]) @@ -1469,7 +1470,8 @@ object JSONFactory400 { value = bankAttribute.value, is_active = bankAttribute.isActive ) - + def createBankAttributesJson(bankAttributes: List[BankAttribute]): BankAttributesResponseJsonV400 = + BankAttributesResponseJsonV400(bankAttributes.map(createBankAttributeJson)) def createApiCollectionEndpointsJsonV400(apiCollectionEndpoints: List[ApiCollectionEndpointTrait]) = { ApiCollectionEndpointsJson400(apiCollectionEndpoints.map(apiCollectionEndpoint => createApiCollectionEndpointJsonV400(apiCollectionEndpoint))) From 472069e0ab0d821fdbb7494e5b7b52c00f81b6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 10 Sep 2021 13:23:29 +0200 Subject: [PATCH 105/293] feature/Add attributes to Bank Model 6 --- .../scala/code/api/v4_0_0/APIMethods400.scala | 37 ++++++++++++++++++- .../code/api/v4_0_0/BankAttributeTests.scala | 22 +++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 1d7d7c987..77eef8e34 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5828,7 +5828,42 @@ trait APIMethods400 { for { (attributes, callContext) <- NewStyle.function.getBankAttributesByBank(bankId, cc.callContext) } yield { - (JSONFactory400.createBankAttributesJson(attributes), HttpCode.`200`(callContext)) + (createBankAttributesJson(attributes), HttpCode.`200`(callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getBankAttribute, + implementedInApiVersion, + nameOf(getBankAttribute), + "GET", + "/banks/BANK_ID/attributes/BANK_ATTRIBUTE_ID", + "Get Bank Attribute By BANK_ATTRIBUTE_ID", + s""" Get Bank Attribute By BANK_ATTRIBUTE_ID + | + |${authenticationRequiredMessage(true)} + | + |""", + emptyObjectJson, + transactionAttributesResponseJson, + List( + $UserNotLoggedIn, + $BankNotFound, + InvalidJsonFormat, + UnknownError + ), + List(apiTagBank, apiTagNewStyle), + Some(List(canGetBankAttribute)) + ) + + lazy val getBankAttribute : OBPEndpoint = { + case "banks" :: BankId(bankId) :: "attributes" :: bankAttributeId :: Nil JsonGet _ => { + cc => + for { + (attribute, callContext) <- NewStyle.function.getBankAttributeById(bankAttributeId, cc.callContext) + } yield { + (createBankAttributeJson(attribute), HttpCode.`200`(callContext)) } } } diff --git a/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala index 402f62809..e5f659a1e 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/BankAttributeTests.scala @@ -35,6 +35,7 @@ class BankAttributeTests extends V400ServerSetup with DefaultUsers { object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.updateBankAttribute)) object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.deleteBankAttribute)) object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.getBankAttributes)) + object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.getBankAttribute)) lazy val bankId = randomBankId @@ -125,6 +126,27 @@ class BankAttributeTests extends V400ServerSetup with DefaultUsers { response.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanGetBankAttribute) } } + + feature(s"Assuring that endpoint $ApiEndpoint5 works as expected - $VersionOfApi") { + scenario(s"We try to consume endpoint $ApiEndpoint4 - Anonymous access", ApiEndpoint5, VersionOfApi) { + When("We make the request") + val request = (v4_0_0_Request / "banks" / bankId / "attributes" / "DOES_NOT_MATTER").GET + val response = makeGetRequest(request) + Then("We should get a 401") + And("We should get a message: " + ErrorMessages.UserNotLoggedIn) + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn) + } + scenario(s"We try to consume endpoint $ApiEndpoint5 without proper role - Authorized access", ApiEndpoint5, VersionOfApi) { + When("We make the request") + val request = (v4_0_0_Request / "banks" / bankId / "attributes" / "DOES_NOT_MATTER").GET <@ (user1) + val response = makeGetRequest(request) + Then("We should get a 403") + And("We should get a message: " + s"$CanGetBankAttribute entitlement required") + response.code should equal(403) + response.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles + CanGetBankAttribute) + } + } } \ No newline at end of file From 6e2182ed62cf244bf168c921cc3b305230240423 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 10 Sep 2021 14:21:13 +0200 Subject: [PATCH 106/293] docfix/added the missing swagger class example --- .../ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 02a8b3acc..5a40b3321 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -15,7 +15,7 @@ import code.api.v3_0_0.JSONFactory300.createBranchJsonV300 import code.api.v3_0_0.custom.JSONFactoryCustom300 import code.api.v3_0_0.{LobbyJsonV330, _} import code.api.v3_1_0.{AccountBalanceV310, AccountsBalancesV310Json, BadLoginStatusJson, ContactDetailsJson, CustomerWithAttributesJsonV310, InviteeJson, ObpApiLoopbackJson, PhysicalCardWithAttributesJsonV310, PutUpdateCustomerEmailJsonV310, _} -import code.api.v4_0_0._ +import code.api.v4_0_0.{BankAttributeBankResponseJsonV400, _} import code.api.v3_1_0.{AccountBalanceV310, AccountsBalancesV310Json, BadLoginStatusJson, ContactDetailsJson, InviteeJson, ObpApiLoopbackJson, PhysicalCardWithAttributesJsonV310, PutUpdateCustomerEmailJsonV310, _} import code.branches.Branches.{Branch, DriveUpString, LobbyString} import code.consent.ConsentStatus @@ -832,7 +832,15 @@ object SwaggerDefinitionsJSON { val banksJSON = BanksJSON( banks = List(bankJSON) ) - + val bankAttributeBankResponseJsonV400 = BankAttributeBankResponseJsonV400( + name = nameExample.value, + value = valueExample.value + ) + + val bankAttributesResponseJson = BankAttributesResponseJson( + list = List(bankAttributeBankResponseJsonV400) + ) + val bankJson400 = BankJson400( id = "gh.29.uk", short_name = "short_name ", @@ -840,7 +848,7 @@ object SwaggerDefinitionsJSON { logo = "logo", website = "www.openbankproject.com", bank_routings = List(bankRoutingJsonV121), - None + attributes = Some(List(bankAttributeBankResponseJsonV400)) ) val banksJSON400 = BanksJson400( From 6ea7e7ba0c22556763262729a2b2395803c675b6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 10 Sep 2021 15:01:13 +0200 Subject: [PATCH 107/293] refactor/use EmptyBody instead of emptyObjectJson --- .../scala/code/api/v4_0_0/APIMethods400.scala | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 026be29cc..e3d297df5 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -118,7 +118,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | """.stripMargin, - emptyObjectJson, + EmptyBody, adapterInfoJsonV300, List($UserNotLoggedIn, UnknownError), List(apiTagApi, apiTagNewStyle), @@ -145,7 +145,7 @@ trait APIMethods400 { | |${authenticationRequiredMessage(true)} """.stripMargin, - emptyObjectJson, + EmptyBody, logoutLinkV400, List($UserNotLoggedIn, UnknownError), List(apiTagUser, apiTagNewStyle)) @@ -240,7 +240,7 @@ trait APIMethods400 { |* Short and full name of bank |* Logo URL |* Website""", - emptyObjectJson, + EmptyBody, banksJSON400, List(UnknownError), apiTagBank :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil @@ -272,7 +272,7 @@ trait APIMethods400 { |* Short and full name of bank |* Logo URL |* Website""", - emptyObjectJson, + EmptyBody, bankJson400, List(UserNotLoggedIn, UnknownError, BankNotFound), apiTagBank :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil @@ -340,7 +340,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, doubleEntryTransactionJson, List( $UserNotLoggedIn, @@ -498,7 +498,7 @@ trait APIMethods400 { |Note: a settlement account is considered as a bank account. |So you can update it and add account attributes to it using the regular account endpoints |""", - emptyObjectJson, + EmptyBody, settlementAccountsJson, List( $UserNotLoggedIn, @@ -1437,7 +1437,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionRequestAttributeResponseJson, List( $UserNotLoggedIn, @@ -1478,7 +1478,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionRequestAttributesResponseJson, List( $UserNotLoggedIn, @@ -1639,7 +1639,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionRequestAttributeDefinitionsResponseJsonV400, List( $UserNotLoggedIn, @@ -1676,7 +1676,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, Full(true), List( $UserNotLoggedIn, @@ -2590,7 +2590,7 @@ trait APIMethods400 { |* Hosted at information |* Energy source information |* Git Commit""", - emptyObjectJson, + EmptyBody, apiInfoJson400, List(UnknownError, "no connector set"), apiTagApi :: apiTagNewStyle :: Nil) @@ -2614,8 +2614,8 @@ trait APIMethods400 { s"""Get the Call Context of the current call. | """.stripMargin, - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List($UserNotLoggedIn, UnknownError), List(apiTagApi, apiTagNewStyle), Some(List(canGetCallContext))) @@ -2638,8 +2638,8 @@ trait APIMethods400 { s"""Verify Request and Sign Response of a current call. | """.stripMargin, - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List($UserNotLoggedIn, UnknownError), List(apiTagApi, apiTagNewStyle), Some(Nil)) @@ -2734,7 +2734,7 @@ trait APIMethods400 { | | """.stripMargin, - emptyObjectJson, + EmptyBody, entitlementJSONs, List($UserNotLoggedIn, UserHasMissingRoles, UnknownError), List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), @@ -2771,7 +2771,7 @@ trait APIMethods400 { s""" | """.stripMargin, - emptyObjectJson, + EmptyBody, entitlementJSONs, List($UserNotLoggedIn, UserHasMissingRoles, UnknownError), List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), @@ -2849,8 +2849,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |Authentication is required as the tag is linked with the user.""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List(NoViewPermission, ViewNotFound, $UserNotLoggedIn, @@ -2890,7 +2890,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |Authentication is required as the tag is linked with the user.""", - emptyObjectJson, + EmptyBody, accountTagsJSON, List( $UserNotLoggedIn, @@ -2944,7 +2944,7 @@ trait APIMethods400 { | | |""".stripMargin, - emptyObjectJson, + EmptyBody, moderatedCoreAccountJsonV400, List($UserNotLoggedIn, $BankAccountNotFound,UnknownError), apiTagAccount :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil @@ -2988,7 +2988,7 @@ trait APIMethods400 { | |Authentication is required if the 'is_public' field in view (VIEW_ID) is not set to `true`. |""".stripMargin, - emptyObjectJson, + EmptyBody, moderatedAccountJSON400, List( $UserNotLoggedIn, @@ -3160,7 +3160,7 @@ trait APIMethods400 { "/banks/BANK_ID/balances", "Get Accounts Balances", """Get the Balances for the Accounts of the current User at one bank.""", - emptyObjectJson, + EmptyBody, accountBalancesV400Json, List($UserNotLoggedIn, $BankNotFound, UnknownError), apiTagAccount :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil @@ -3187,7 +3187,7 @@ trait APIMethods400 { "/banks/BANK_ID/accounts/ACCOUNT_ID/balances", "Get Account Balances", """Get the Balances for one Account of the current User at one bank.""", - emptyObjectJson, + EmptyBody, accountBalanceV400, List($UserNotLoggedIn, $BankNotFound, CannotFindAccountAccess, UnknownError), apiTagAccount :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil @@ -3238,7 +3238,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""".stripMargin, - emptyObjectJson, + EmptyBody, moderatedFirehoseAccountsJsonV400, List($BankNotFound), List(apiTagAccount, apiTagAccountFirehose, apiTagFirehoseData, apiTagNewStyle), @@ -3353,7 +3353,7 @@ trait APIMethods400 { | |${authenticationRequiredMessage(true)} """.stripMargin, - emptyObjectJson, + EmptyBody, userIdJsonV400, List(UserNotLoggedIn, UnknownError), List(apiTagUser, apiTagNewStyle)) @@ -3383,7 +3383,7 @@ trait APIMethods400 { |CanGetAnyUser entitlement is required, | """.stripMargin, - emptyObjectJson, + EmptyBody, usersJsonV200, List(UserNotLoggedIn, UserHasMissingRoles, UserNotFoundById, UnknownError), List(apiTagUser, apiTagNewStyle), @@ -3518,7 +3518,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, userInvitationJsonV400, List( $UserNotLoggedIn, @@ -3553,7 +3553,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, userInvitationJsonV400, List( $UserNotLoggedIn, @@ -3590,8 +3590,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, UserHasMissingRoles, @@ -4232,7 +4232,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, customerAttributesResponseJson, List( $UserNotLoggedIn, @@ -4273,7 +4273,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, customerAttributeResponseJson, List( $UserNotLoggedIn, @@ -4315,7 +4315,7 @@ trait APIMethods400 { | | |""", - emptyObjectJson, + EmptyBody, ListResult( "customers", List(customerWithAttributesJsonV310) @@ -4478,7 +4478,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionAttributesResponseJson, List( $UserNotLoggedIn, @@ -4519,7 +4519,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionAttributeResponseJson, List( $UserNotLoggedIn, @@ -4576,7 +4576,7 @@ trait APIMethods400 { |The customer can proceed with the Transaction by answering the security challenge. | """.stripMargin, - emptyObjectJson, + EmptyBody, transactionRequestWithChargeJSON210, List( $UserNotLoggedIn, @@ -4625,7 +4625,7 @@ trait APIMethods400 { | | """.stripMargin, - emptyObjectJson, + EmptyBody, basicAccountsJSON, List($UserNotLoggedIn, $BankNotFound, UnknownError), List(apiTagAccount, apiTagPrivateData, apiTagPublicData, apiTagNewStyle) @@ -4745,8 +4745,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -5641,7 +5641,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, productAttributeResponseJsonV400, List( UserHasMissingRoles, @@ -5782,7 +5782,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, productFeeResponseJsonV400, List( $UserNotLoggedIn, @@ -5816,7 +5816,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, productFeesResponseJsonV400, List( $UserNotLoggedIn, @@ -5851,7 +5851,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, BooleanBody(true), List( $UserNotLoggedIn, @@ -6019,7 +6019,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionAttributesResponseJson, List( $UserNotLoggedIn, @@ -6054,7 +6054,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionAttributesResponseJson, List( $UserNotLoggedIn, @@ -6147,8 +6147,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( UserHasMissingRoles, BankNotFound, @@ -6311,8 +6311,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6349,8 +6349,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6387,8 +6387,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6425,8 +6425,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6463,8 +6463,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6501,7 +6501,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, productAttributeDefinitionsResponseJsonV400, List( $UserNotLoggedIn, @@ -6538,7 +6538,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, customerAttributeDefinitionsResponseJsonV400, List( $UserNotLoggedIn, @@ -6575,7 +6575,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, accountAttributeDefinitionsResponseJsonV400, List( $UserNotLoggedIn, @@ -6612,7 +6612,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, transactionAttributeDefinitionsResponseJsonV400, List( $UserNotLoggedIn, @@ -6650,7 +6650,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, cardAttributeDefinitionsResponseJsonV400, List( $UserNotLoggedIn, @@ -6687,8 +6687,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6725,7 +6725,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, userCustomerLinksJson, List( $UserNotLoggedIn, @@ -6761,7 +6761,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, + EmptyBody, userCustomerLinksJson, List( $UserNotLoggedIn, @@ -6798,8 +6798,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6836,8 +6836,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -6872,8 +6872,8 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""", - emptyObjectJson, - emptyObjectJson, + EmptyBody, + EmptyBody, List( $UserNotLoggedIn, $BankNotFound, @@ -7267,7 +7267,7 @@ trait APIMethods400 { | |${authenticationRequiredMessage(true)} |""".stripMargin, - emptyObjectJson, + EmptyBody, counterpartiesJson400, List( $UserNotLoggedIn, @@ -7320,7 +7320,7 @@ trait APIMethods400 { | |${authenticationRequiredMessage(true)} |""".stripMargin, - emptyObjectJson, + EmptyBody, counterpartyWithMetadataJson400, List($UserNotLoggedIn, $BankNotFound, $BankAccountNotFound, $UserNoPermissionAccessView, UnknownError), List(apiTagCounterparty, apiTagPSD2PIS, apiTagPsd2, apiTagCounterpartyMetaData, apiTagNewStyle) @@ -7355,7 +7355,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | |""".stripMargin, - emptyObjectJson, + EmptyBody, counterpartyWithMetadataJson400, List( $UserNotLoggedIn, @@ -7525,7 +7525,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | """.stripMargin, - emptyObjectJson, + EmptyBody, consentsJsonV400, List( $UserNotLoggedIn, @@ -7561,7 +7561,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} | """.stripMargin, - emptyObjectJson, + EmptyBody, consentInfosJsonV400, List( $UserNotLoggedIn, @@ -10183,7 +10183,7 @@ trait APIMethods400 { |URL params example: /banks/some-bank-id/products?manager=John&count=8 | |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, - emptyObjectJson, + EmptyBody, productJsonV400.copy(attributes = None, fees = None), List( UserNotLoggedIn, @@ -10310,7 +10310,7 @@ trait APIMethods400 { |* License the data under this endpoint is released under | |${authenticationRequiredMessage(!getProductsIsPublic)}""".stripMargin, - emptyObjectJson, + EmptyBody, productJsonV400, List( UserNotLoggedIn, From c644bd5fcc4500d0eba6acd4836e2e97aa1e4d2c Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 10 Sep 2021 16:10:06 +0200 Subject: [PATCH 108/293] bugfix/tweaked the partialFunctionName filter logic --- .../code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 84dff4440..c75a1ef53 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -1022,7 +1022,7 @@ so the caller must specify any required filtering by catalog explicitly. for { rd <- filteredResources1 partialFunctionName <- pfNames - if rd.partialFunctionName.contains(partialFunctionName) + if rd.partialFunctionName.equals(partialFunctionName) } yield { rd } From aba22ef37661def92ea4fd44961631b6217be23b Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 10 Sep 2021 16:55:38 +0200 Subject: [PATCH 109/293] feature/set public props the getProductFees and getProductFee endpoints --- .../scala/code/api/v4_0_0/APIMethods400.scala | 24 +++++++++++-------- .../code/api/v4_0_0/ProductFeeTest.scala | 23 ++++-------------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index e3d297df5..8283d6434 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5779,24 +5779,26 @@ trait APIMethods400 { | |Get one product fee by its id. | - |${authenticationRequiredMessage(true)} + |${authenticationRequiredMessage(false)} | |""", EmptyBody, productFeeResponseJsonV400, List( - $UserNotLoggedIn, $BankNotFound, - UserHasMissingRoles, UnknownError ), - List(apiTagProduct, apiTagNewStyle), - Some(List(canGetProductFee))) + List(apiTagProduct, apiTagNewStyle) + ) lazy val getProductFee : OBPEndpoint = { case "banks" :: bankId :: "products" :: productCode:: "fees" :: productFeeId :: Nil JsonGet _ => { cc => for { + (_, callContext) <- getProductsIsPublic match { + case false => authenticatedAccess(cc) + case true => anonymousAccess(cc) + } (productFee, callContext) <- NewStyle.function.getProductFeeById(productFeeId, Some(cc)) } yield { (createProductFeeJson(productFee), HttpCode.`200`(callContext)) @@ -5813,24 +5815,26 @@ trait APIMethods400 { "Get Product Fees", s"""Get Product Fees | - |${authenticationRequiredMessage(true)} + |${authenticationRequiredMessage(false)} | |""", EmptyBody, productFeesResponseJsonV400, List( - $UserNotLoggedIn, $BankNotFound, - UserHasMissingRoles, UnknownError ), - List(apiTagProduct, apiTagNewStyle), - Some(List(canGetProductFee))) + List(apiTagProduct, apiTagNewStyle) + ) lazy val getProductFees : OBPEndpoint = { case "banks" :: bankId :: "products" :: productCode:: "fees" :: Nil JsonGet _ => { cc => for { + (_, callContext) <- getProductsIsPublic match { + case false => authenticatedAccess(cc) + case true => anonymousAccess(cc) + } (productFees, callContext) <- NewStyle.function.getProductFeesFromProvider(BankId(bankId), ProductCode(productCode), Some(cc)) } yield { (createProductFeesJson(productFees), HttpCode.`200`(callContext)) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala index 9c4807ab5..1e1780b1b 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/ProductFeeTest.scala @@ -202,32 +202,17 @@ class ProductFeeTest extends V400ServerSetup { // then we getProductFees val requestGetProductFees = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees").GET val responseGetProductFees = makeGetRequest(requestGetProductFees) - responseGetProductFees.code should equal(401) - responseGetProductFees.body.toString contains(UserNotLoggedIn) should be (true) + responseGetProductFees.code should equal(200) - { - val requestGetProductFees = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees").GET <@(user1) - val responseGetProductFees = makeGetRequest(requestGetProductFees) - responseGetProductFees.code should equal(403) - responseGetProductFees.body.toString contains(UserHasMissingRoles) should be (true) - responseGetProductFees.body.toString contains(canGetProductFee.toString()) should be (true) - } // then we getProductFee val productFeeId = "xxx" val requestGetProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).GET val responseGetProductFee = makeGetRequest(requestGetProductFee) - responseGetProductFee.code should equal(401) - responseGetProductFee.body.toString contains(UserNotLoggedIn) should be (true) + responseGetProductFee.code should equal(404) + responseGetProductFee.body.toString contains(ProductFeeNotFoundById) should be (true) - { - val requestGetProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).GET <@(user1) - val responseGetProductFee = makeGetRequest(requestGetProductFee) - responseGetProductFee.code should equal(403) - responseGetProductFee.body.toString contains(UserHasMissingRoles) should be (true) - responseGetProductFee.body.toString contains(canGetProductFee.toString()) should be (true) - } - + // then we updateProductFee val requestPutProductFee = (v4_0_0_Request / "banks" / product.bank_id / "products" / product.product_code / "fees" / productFeeId).PUT val updatedName = "test Case 123" From 9b73c72b17d2b90f12ce3f225674ce63d9d379c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 13 Sep 2021 08:55:26 +0200 Subject: [PATCH 110/293] feature/Support Azure as the OpenID Connect Identity Provider 2 --- obp-api/src/main/scala/code/api/OAuth2.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/obp-api/src/main/scala/code/api/OAuth2.scala b/obp-api/src/main/scala/code/api/OAuth2.scala index 0ec4c7129..f138f5949 100644 --- a/obp-api/src/main/scala/code/api/OAuth2.scala +++ b/obp-api/src/main/scala/code/api/OAuth2.scala @@ -96,6 +96,8 @@ object OAuth2Login extends RestHelper with MdcLoggable { Google.applyRulesFuture(value, cc) } else if (Yahoo.isIssuer(value)) { Yahoo.applyRulesFuture(value, cc) + } else if (Azure.isIssuer(value)) { + Azure.applyRulesFuture(value, cc) } else { Hydra.applyRulesFuture(value, cc) } From 61b131bf124fa39495d6a787c6dbaeec0472e9f6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 13 Sep 2021 11:47:14 +0200 Subject: [PATCH 111/293] bugfix/removed the .main-support-item text value fix --- obp-api/src/main/webapp/media/js/website.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/obp-api/src/main/webapp/media/js/website.js b/obp-api/src/main/webapp/media/js/website.js index 563995aca..a740571c9 100644 --- a/obp-api/src/main/webapp/media/js/website.js +++ b/obp-api/src/main/webapp/media/js/website.js @@ -120,9 +120,6 @@ $(document).ready(function() { $("#small-screen-navbar #small-nav-log-on-button").css("width","63px"); } - $(".main-support-item .support-platform-link").text("chat.openbankproject.com"); - - var htmlTitle = $(document).find("title").text(); if (htmlTitle.indexOf("Get API") > -1){ From 0160cced98353a8e6ef3e1ed05969b45f6cd1545 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 13 Sep 2021 11:52:43 +0200 Subject: [PATCH 112/293] refactor/use rocket.chat instead of slack --- obp-api/src/main/resources/props/sample.props.template | 2 +- obp-api/src/main/scala/code/snippet/WebUI.scala | 2 +- obp-api/src/main/webapp/index.html | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 2b8317b83..98b205430 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -430,7 +430,7 @@ webui_faq_url = https://openbankproject.com/faq/ webui_faq_email = contact@openbankproject.com # Link to support platform -webui_support_platform_url = https://slack.openbankproject.com/ +webui_support_platform_url = https://chat.openbankproject.com # Link to Direct Login glossary on api explorer webui_direct_login_documentation_url = diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index b5de7c2c9..64e96cd6d 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -320,7 +320,7 @@ class WebUI extends MdcLoggable{ // Support platform link def supportPlatformLink: CssSel = { - val supportplatformlink = scala.xml.Unparsed(getWebUiPropsValue("webui_support_platform_url", "https://slack.openbankproject.com/")) + val supportplatformlink = scala.xml.Unparsed(getWebUiPropsValue("webui_support_platform_url", "https://chat.openbankproject.com")) ".support-platform-link a [href]" #> supportplatformlink & ".support-platform-link a *" #> supportplatformlink.toString().replace("https://","").replace("http://", "") } diff --git a/obp-api/src/main/webapp/index.html b/obp-api/src/main/webapp/index.html index 7cda7d1dc..8cb8babfc 100644 --- a/obp-api/src/main/webapp/index.html +++ b/obp-api/src/main/webapp/index.html @@ -407,7 +407,7 @@ Berlin 13359, Germany target="_blank">FAQ, Glossary, join our Slack + class="support-platform-link" data-lift="WebUI.supportPlatformLink" href="" target="_blank">Rocket-Chat channels or email us at contact@openbankproject.com

      @@ -447,9 +447,9 @@ Berlin 13359, Germany
      From e5960cc9e8fe11e9837190b98e13b09f2703a906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 13 Sep 2021 11:59:17 +0200 Subject: [PATCH 113/293] feature/Add props openid_connect.show_tokens --- .../main/resources/props/sample.props.template | 1 + .../src/main/scala/code/api/openidconnect.scala | 8 +++++--- .../scala/code/model/dataAccess/AuthUser.scala | 16 +++++++++++++++- obp-api/src/main/scala/code/snippet/Login.scala | 3 ++- .../code/token/MappedOpenIDConnectToken.scala | 11 ++++++++++- .../code/token/OpenIDConnectTokenProvider.scala | 6 +++++- .../main/webapp/templates-hidden/default.html | 1 + 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 2b8317b83..297248dd5 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -616,6 +616,7 @@ super_admin_user_ids=USER_ID1,USER_ID2, ## Note: The email address used for login must match one ## registered on OBP localy. # openid_connect.enabled=true +# openid_connect.show_tokens=false # First identity provider # openid_connect_1.button_text = Google # openid_connect_1.client_secret=OYdWujJlU7fFOW_NXzPlDI4T diff --git a/obp-api/src/main/scala/code/api/openidconnect.scala b/obp-api/src/main/scala/code/api/openidconnect.scala index 657302e01..2ed85dde2 100644 --- a/obp-api/src/main/scala/code/api/openidconnect.scala +++ b/obp-api/src/main/scala/code/api/openidconnect.scala @@ -115,7 +115,7 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { case Full(authUser) => getOrCreateConsumer(idToken, user.userId) match { case Full(consumer) => - saveAuthorizationToken(tokenType, accessToken, idToken, refreshToken, scope, expiresIn) match { + saveAuthorizationToken(tokenType, accessToken, idToken, refreshToken, scope, expiresIn, authUser.id.get) match { case Full(token) => (200, "OK", Some(authUser)) case _ => (401, ErrorMessages.CouldNotHandleOpenIDConnectData + "1", Some(authUser)) } @@ -272,14 +272,16 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { idToken: String, refreshToken: String, scope: String, - expiresIn: Long): Box[OpenIDConnectToken] = { + expiresIn: Long, + authUserPrimaryKey: Long): Box[OpenIDConnectToken] = { val token = TokensOpenIDConnect.tokens.vend.createToken( tokenType = tokenType, accessToken = accessToken, idToken = idToken, refreshToken = refreshToken, scope = scope, - expiresIn = expiresIn + expiresIn = expiresIn, + authUserPrimaryKey = authUserPrimaryKey ) token match { case Full(_) => // All good diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 43f140839..1a80e72f6 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -28,7 +28,7 @@ package code.model.dataAccess import code.UserRefreshes.UserRefreshes import code.accountholders.AccountHolders -import code.api.util.APIUtil.{hasAnOAuthHeader, validatePasswordOnCreation, logger, _} +import code.api.util.APIUtil.{hasAnOAuthHeader, logger, validatePasswordOnCreation, _} import code.api.util.ErrorMessages._ import code.api.util._ import code.api.v4_0_0.dynamic.DynamicEndpointHelper @@ -37,6 +37,7 @@ import code.bankconnectors.Connector import code.context.UserAuthContextProvider import code.entitlement.Entitlement import code.loginattempts.LoginAttempt +import code.token.TokensOpenIDConnect import code.users.Users import code.util.Helper import code.util.Helper.MdcLoggable @@ -486,11 +487,24 @@ import net.liftweb.util.Helpers._ getCurrentUser match { case Full(user) if user.provider.contains("google") => user.emailAddress case Full(user) if user.provider.contains("yahoo") => user.emailAddress + case Full(user) if user.provider.contains("microsoft") => user.emailAddress case Full(user) => user.name case _ => "" //TODO need more error handling for different user cases } } + def getIDTokenOfCurrentUser(): String = { + if(APIUtil.getPropsAsBoolValue("openid_connect.show_tokens", false)) { + AuthUser.currentUser match { + case Full(authUser) => + TokensOpenIDConnect.tokens.vend.getOpenIDConnectTokenByAuthUser(authUser.id.get).map(_.idToken).getOrElse("") + case _ => "" + } + } else { + "" + } + } + /** * get current user.userId * Note: 1.resourceuser has two ids: id(Long) and userid_(String), diff --git a/obp-api/src/main/scala/code/snippet/Login.scala b/obp-api/src/main/scala/code/snippet/Login.scala index ea0ff50dd..e0f58e64e 100644 --- a/obp-api/src/main/scala/code/snippet/Login.scala +++ b/obp-api/src/main/scala/code/snippet/Login.scala @@ -46,7 +46,8 @@ class Login { ".logout [href]" #> { AuthUser.logoutPath.foldLeft("")(_ + "/" + _) } & - "#loggedIn-username *" #> AuthUser.getCurrentUserUsername + "#loggedIn-username *" #> AuthUser.getCurrentUserUsername & + "#logged-in-id-token *" #> AuthUser.getIDTokenOfCurrentUser } } diff --git a/obp-api/src/main/scala/code/token/MappedOpenIDConnectToken.scala b/obp-api/src/main/scala/code/token/MappedOpenIDConnectToken.scala index cf651db72..dcf1a73eb 100644 --- a/obp-api/src/main/scala/code/token/MappedOpenIDConnectToken.scala +++ b/obp-api/src/main/scala/code/token/MappedOpenIDConnectToken.scala @@ -1,5 +1,7 @@ package code.token +import java.util.Date + import net.liftweb.common.Box import net.liftweb.mapper._ @@ -9,7 +11,8 @@ object MappedOpenIDConnectTokensProvider extends OpenIDConnectTokensProvider { idToken: String, refreshToken: String, scope: String, - expiresIn: Long): Box[OpenIDConnectToken] = Box.tryo { + expiresIn: Long, + authUserPrimaryKey: Long): Box[OpenIDConnectToken] = Box.tryo { OpenIDConnectToken.create .TokenType(tokenType.toString()) .AccessToken(accessToken) @@ -17,8 +20,12 @@ object MappedOpenIDConnectTokensProvider extends OpenIDConnectTokensProvider { .RefreshToken(refreshToken) .Scope(scope) .ExpiresIn(expiresIn) + .AuthUserPrimaryKey(authUserPrimaryKey) .saveMe() } + def getOpenIDConnectTokenByAuthUser(authUserPrimaryKey: Long) = + OpenIDConnectToken.findAll(By(OpenIDConnectToken.AuthUserPrimaryKey, authUserPrimaryKey)) + .sortBy(_.createdAt.get)(Ordering[Date].reverse).headOption } @@ -31,6 +38,7 @@ class OpenIDConnectToken extends OpenIDConnectTokenTrait with LongKeyedMapper[Op object Scope extends MappedString(this, 250) object TokenType extends MappedString(this, 250) object ExpiresIn extends MappedLong(this) + object AuthUserPrimaryKey extends MappedLong(this) override def accessToken: String = AccessToken.get override def idToken: String = IDToken.get @@ -38,6 +46,7 @@ class OpenIDConnectToken extends OpenIDConnectTokenTrait with LongKeyedMapper[Op override def scope: String = Scope.get override def tokenType: String = TokenType.get override def expiresIn: Long = ExpiresIn.get + override def authUserPrimaryKey: Long = AuthUserPrimaryKey.get } diff --git a/obp-api/src/main/scala/code/token/OpenIDConnectTokenProvider.scala b/obp-api/src/main/scala/code/token/OpenIDConnectTokenProvider.scala index efd6bffa3..8b99c7f80 100644 --- a/obp-api/src/main/scala/code/token/OpenIDConnectTokenProvider.scala +++ b/obp-api/src/main/scala/code/token/OpenIDConnectTokenProvider.scala @@ -14,7 +14,10 @@ trait OpenIDConnectTokensProvider { idToken: String, refreshToken: String, scope: String, - expiresIn: Long): Box[OpenIDConnectToken] + expiresIn: Long, + authUserPrimaryKey: Long): Box[OpenIDConnectToken] + + def getOpenIDConnectTokenByAuthUser(authUserPrimaryKey: Long): Box[OpenIDConnectToken] } trait OpenIDConnectTokenTrait { @@ -24,4 +27,5 @@ trait OpenIDConnectTokenTrait { def scope: String def tokenType: String def expiresIn: Long + def authUserPrimaryKey: Long } diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 57103f807..36a23526d 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -133,6 +133,7 @@ Berlin 13359, Germany
    From ff3cf0e935e657a77c9a6e27d966eb2b1bebefc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 13 Sep 2021 15:41:49 +0200 Subject: [PATCH 114/293] feature/Add User Information Page --- .../main/scala/bootstrap/liftweb/Boot.scala | 1 + .../code/model/dataAccess/AuthUser.scala | 2 +- .../scala/code/snippet/UserInformation.scala | 66 +++++++++++++++++++ .../main/webapp/templates-hidden/default.html | 2 +- obp-api/src/main/webapp/user-information.html | 64 ++++++++++++++++++ 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 obp-api/src/main/scala/code/snippet/UserInformation.scala create mode 100644 obp-api/src/main/webapp/user-information.html diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 33830aca6..873ce5fc7 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -510,6 +510,7 @@ class Boot extends MdcLoggable { Menu("Dummy user tokens", "Get Dummy user tokens") / "dummy-user-tokens" >> AuthUser.loginFirst, Menu("Validate OTP", "Validate OTP") / "otp" >> AuthUser.loginFirst, + Menu("User Information", "User Information") / "user-information", Menu("User Invitation", "User Invitation") / "user-invitation", Menu("User Invitation Info", "User Invitation Info") / "user-invitation-info", Menu("User Invitation Invalid", "User Invitation Invalid") / "user-invitation-invalid", diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 1a80e72f6..2bed203ff 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -501,7 +501,7 @@ import net.liftweb.util.Helpers._ case _ => "" } } else { - "" + "This information is not allowed at this instance." } } diff --git a/obp-api/src/main/scala/code/snippet/UserInformation.scala b/obp-api/src/main/scala/code/snippet/UserInformation.scala new file mode 100644 index 000000000..0bec120d0 --- /dev/null +++ b/obp-api/src/main/scala/code/snippet/UserInformation.scala @@ -0,0 +1,66 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH. +Osloer Strasse 16/17 +Berlin 13359, Germany + +This product includes software developed at +TESOBE (http://www.tesobe.com/) + + */ +package code.snippet + +import code.api.util.ErrorMessages.attemptedToOpenAnEmptyBox +import code.model.dataAccess.AuthUser +import code.util.Helper.MdcLoggable +import com.openbankproject.commons.model.User +import net.liftweb.http.{RequestVar, SHtml} +import net.liftweb.util.CssSel +import net.liftweb.util.Helpers._ + +import scala.xml.NodeSeq + +class UserInformation extends MdcLoggable { + + private object idTokenVar extends RequestVar("") + private object providerVar extends RequestVar("") + private object devEmailVar extends RequestVar("") + private object usernameVar extends RequestVar("") + + def show: CssSel = { + if(!AuthUser.loggedIn_?) { + "*" #> NodeSeq.Empty + } else if (AuthUser.getCurrentUser.isEmpty) { + "*" #> NodeSeq.Empty + } else { + val user: User = AuthUser.getCurrentUser.openOrThrowException(attemptedToOpenAnEmptyBox) + usernameVar.set(user.name) + devEmailVar.set(user.emailAddress) + providerVar.set(user.provider) + idTokenVar.set(AuthUser.getIDTokenOfCurrentUser) + "form" #> { + "#user-info-username" #> SHtml.text(usernameVar, usernameVar(_)) & + "#user-info-provider" #> SHtml.text(providerVar.is, providerVar(_)) & + "#user-info-email" #> SHtml.text(devEmailVar, devEmailVar(_)) & + "#user-info-id-token" #> SHtml.text(idTokenVar, idTokenVar(_)) + } & "#register-consumer-success" #> "" + } + } + +} diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 36a23526d..3b6c44109 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -134,7 +134,7 @@ Berlin 13359, Germany
  • diff --git a/obp-api/src/main/webapp/user-information.html b/obp-api/src/main/webapp/user-information.html new file mode 100644 index 000000000..d60122c6d --- /dev/null +++ b/obp-api/src/main/webapp/user-information.html @@ -0,0 +1,64 @@ + +
    +
    +
    +

    User Information

    +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    +
    +
    +
    +
    +
    + + From f20b0316428735cfd992b136806fb30712840152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 14 Sep 2021 07:46:06 +0200 Subject: [PATCH 115/293] refactor/Get rid of unused hidden features --- obp-api/src/main/scala/code/snippet/Login.scala | 3 +-- obp-api/src/main/webapp/templates-hidden/default.html | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/snippet/Login.scala b/obp-api/src/main/scala/code/snippet/Login.scala index e0f58e64e..ea0ff50dd 100644 --- a/obp-api/src/main/scala/code/snippet/Login.scala +++ b/obp-api/src/main/scala/code/snippet/Login.scala @@ -46,8 +46,7 @@ class Login { ".logout [href]" #> { AuthUser.logoutPath.foldLeft("")(_ + "/" + _) } & - "#loggedIn-username *" #> AuthUser.getCurrentUserUsername & - "#logged-in-id-token *" #> AuthUser.getIDTokenOfCurrentUser + "#loggedIn-username *" #> AuthUser.getCurrentUserUsername } } diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 3b6c44109..bc4df9ae9 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -133,7 +133,6 @@ Berlin 13359, Germany From 3a537adf08577ac317fbc9d4ecb26fcf00d61fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 14 Sep 2021 08:59:11 +0200 Subject: [PATCH 116/293] feature/Add migration script to extend coulmns code and parent product code --- .../code/api/util/migration/Migration.scala | 12 ++++ .../util/migration/MigrationOfProduct.scala | 66 +++++++++++++++++++ .../products/MappedProductsProvider.scala | 4 +- 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 660a93130..e2d307817 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -84,6 +84,7 @@ object Migration extends MdcLoggable { populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier) alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier) alterColumnEmailAtResourceUser(startedBeforeSchemifier) + alterColumnCdeAndParentProductCodeAtMappedProduct(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -283,6 +284,17 @@ object Migration extends MdcLoggable { } } } + private def alterColumnCdeAndParentProductCodeAtMappedProduct(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.alterColumnCdeAndParentProductCodeAtMappedProduct(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(alterColumnCdeAndParentProductCodeAtMappedProduct(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfProduct.alterColumnsCodeAndPrentProductCode(name) + } + } + } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala new file mode 100644 index 000000000..f52816949 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala @@ -0,0 +1,66 @@ +package code.api.util.migration + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} + +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.products.MappedProduct +import net.liftweb.common.Full +import net.liftweb.mapper.{DB, Schemifier} +import net.liftweb.util.DefaultConnectionIdentifier + +object MigrationOfProduct { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def alterColumnsCodeAndPrentProductCode(name: String): Boolean = { + DbFunction.tableExists(MappedProduct, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val executedSql = + DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { + APIUtil.getPropsValue("db.driver") match { + case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") => + () => + """ + |ALTER TABLE mappedproduct ALTER COLUMN mcode varchar(100); + |ALTER TABLE mappedproduct ALTER COLUMN mparentproductcode varchar(100); + |""".stripMargin + case _ => + () => + """ + |ALTER TABLE mappedproduct ALTER COLUMN mcode type varchar(100); + |ALTER TABLE mappedproduct ALTER COLUMN mparentproductcode type varchar(100); + |""".stripMargin + } + + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Executed SQL: + |$executedSql + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${MappedProduct._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } + +} diff --git a/obp-api/src/main/scala/code/products/MappedProductsProvider.scala b/obp-api/src/main/scala/code/products/MappedProductsProvider.scala index 4c3fa601d..e8d85d7d7 100644 --- a/obp-api/src/main/scala/code/products/MappedProductsProvider.scala +++ b/obp-api/src/main/scala/code/products/MappedProductsProvider.scala @@ -27,8 +27,8 @@ class MappedProduct extends Product with LongKeyedMapper[MappedProduct] with IdP override def getSingleton = MappedProduct object mBankId extends UUIDString(this) // combination of this - object mCode extends MappedString(this, 50) // and this is unique - object mParentProductCode extends MappedString(this, 50) // and this is unique + object mCode extends MappedString(this, 100) // and this is unique + object mParentProductCode extends MappedString(this, 100) // and this is unique object mName extends MappedString(this, 125) From a9257bd3e3d68cb30a126af10fb9ba6f1969cce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 14 Sep 2021 10:51:18 +0200 Subject: [PATCH 117/293] Revert "feature/Add migration script to extend coulmns code and parent product code" This reverts commit 3a537adf --- .../code/api/util/migration/Migration.scala | 12 ---- .../util/migration/MigrationOfProduct.scala | 66 ------------------- .../products/MappedProductsProvider.scala | 4 +- 3 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index e2d307817..660a93130 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -84,7 +84,6 @@ object Migration extends MdcLoggable { populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier) alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier) alterColumnEmailAtResourceUser(startedBeforeSchemifier) - alterColumnCdeAndParentProductCodeAtMappedProduct(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -284,17 +283,6 @@ object Migration extends MdcLoggable { } } } - private def alterColumnCdeAndParentProductCodeAtMappedProduct(startedBeforeSchemifier: Boolean): Boolean = { - if(startedBeforeSchemifier == true) { - logger.warn(s"Migration.database.alterColumnCdeAndParentProductCodeAtMappedProduct(true) cannot be run before Schemifier.") - true - } else { - val name = nameOf(alterColumnCdeAndParentProductCodeAtMappedProduct(startedBeforeSchemifier)) - runOnce(name) { - MigrationOfProduct.alterColumnsCodeAndPrentProductCode(name) - } - } - } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala deleted file mode 100644 index f52816949..000000000 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfProduct.scala +++ /dev/null @@ -1,66 +0,0 @@ -package code.api.util.migration - -import java.time.format.DateTimeFormatter -import java.time.{ZoneId, ZonedDateTime} - -import code.api.util.APIUtil -import code.api.util.migration.Migration.{DbFunction, saveLog} -import code.products.MappedProduct -import net.liftweb.common.Full -import net.liftweb.mapper.{DB, Schemifier} -import net.liftweb.util.DefaultConnectionIdentifier - -object MigrationOfProduct { - - val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) - val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) - val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") - - def alterColumnsCodeAndPrentProductCode(name: String): Boolean = { - DbFunction.tableExists(MappedProduct, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { - case true => - val startDate = System.currentTimeMillis() - val commitId: String = APIUtil.gitCommit - var isSuccessful = false - - val executedSql = - DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { - APIUtil.getPropsValue("db.driver") match { - case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") => - () => - """ - |ALTER TABLE mappedproduct ALTER COLUMN mcode varchar(100); - |ALTER TABLE mappedproduct ALTER COLUMN mparentproductcode varchar(100); - |""".stripMargin - case _ => - () => - """ - |ALTER TABLE mappedproduct ALTER COLUMN mcode type varchar(100); - |ALTER TABLE mappedproduct ALTER COLUMN mparentproductcode type varchar(100); - |""".stripMargin - } - - } - - val endDate = System.currentTimeMillis() - val comment: String = - s"""Executed SQL: - |$executedSql - |""".stripMargin - isSuccessful = true - saveLog(name, commitId, isSuccessful, startDate, endDate, comment) - isSuccessful - - case false => - val startDate = System.currentTimeMillis() - val commitId: String = APIUtil.gitCommit - val isSuccessful = false - val endDate = System.currentTimeMillis() - val comment: String = - s"""${MappedProduct._dbTableNameLC} table does not exist""".stripMargin - saveLog(name, commitId, isSuccessful, startDate, endDate, comment) - isSuccessful - } - } - -} diff --git a/obp-api/src/main/scala/code/products/MappedProductsProvider.scala b/obp-api/src/main/scala/code/products/MappedProductsProvider.scala index e8d85d7d7..4c3fa601d 100644 --- a/obp-api/src/main/scala/code/products/MappedProductsProvider.scala +++ b/obp-api/src/main/scala/code/products/MappedProductsProvider.scala @@ -27,8 +27,8 @@ class MappedProduct extends Product with LongKeyedMapper[MappedProduct] with IdP override def getSingleton = MappedProduct object mBankId extends UUIDString(this) // combination of this - object mCode extends MappedString(this, 100) // and this is unique - object mParentProductCode extends MappedString(this, 100) // and this is unique + object mCode extends MappedString(this, 50) // and this is unique + object mParentProductCode extends MappedString(this, 50) // and this is unique object mName extends MappedString(this, 125) From a86f8815d4c79209fbc3ce441ff88a6d901c1346 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Sep 2021 10:49:25 +0200 Subject: [PATCH 118/293] feature/Add migration script to extend column name to 100 --- .../code/api/util/migration/Migration.scala | 12 ++++ .../migration/MigrationOfProductFee.scala | 63 +++++++++++++++++++ .../productfee/MappedProductFeeProvider.scala | 2 +- 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfProductFee.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 660a93130..c627f88b8 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -84,6 +84,7 @@ object Migration extends MdcLoggable { populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier) alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier) alterColumnEmailAtResourceUser(startedBeforeSchemifier) + alterColumnNameAtProductFee(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -283,6 +284,17 @@ object Migration extends MdcLoggable { } } } + private def alterColumnNameAtProductFee(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.alterColumnNameAtProductFee(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(alterColumnNameAtProductFee(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfProductFee.alterColumnProductFeeName(name) + } + } + } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfProductFee.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProductFee.scala new file mode 100644 index 000000000..bbd589050 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfProductFee.scala @@ -0,0 +1,63 @@ +package code.api.util.migration + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.productfee.ProductFee +import net.liftweb.common.Full +import net.liftweb.mapper.{DB, Schemifier} +import net.liftweb.util.DefaultConnectionIdentifier + +object MigrationOfProductFee { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def alterColumnProductFeeName(name: String): Boolean = { + DbFunction.tableExists(ProductFee, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val executedSql = + DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { + APIUtil.getPropsValue("db.driver") match { + case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") => + () => + """ + |ALTER TABLE ProductFee ALTER COLUMN name varchar(100); + |""".stripMargin + case _ => + () => + """ + |ALTER TABLE ProductFee ALTER COLUMN name type varchar(100); + |""".stripMargin + } + + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Executed SQL: + |$executedSql + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${ProductFee._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } + +} diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala index 00b5f20e1..0c292eb68 100644 --- a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -95,7 +95,7 @@ class ProductFee extends ProductFeeTrait with LongKeyedMapper[ProductFee] with I object ProductFeeId extends UUIDString(this) - object Name extends MappedString(this, 50) + object Name extends MappedString(this, 100) object IsActive extends MappedBoolean(this) { override def defaultValue = true From ec6beb1788b24bed6cee733f3a5bb2315fa2367d Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Sep 2021 12:15:49 +0200 Subject: [PATCH 119/293] feature/tweaked the error messages for create/update product fee --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 ++ .../scala/code/productfee/MappedProductFeeProvider.scala | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 3224f8f7e..474afa523 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -372,6 +372,8 @@ object ErrorMessages { val InvalidPaymentSystemName = "OBP-30116: Invalid payment system name. The payment system name should only contain 0-9/a-z/A-Z/'-'/'.'/'_', the length should be smaller than 200." val ProductFeeNotFoundById = "OBP-30117: Product Fee not found. Please specify a valid value for PRODUCT_FEE_ID." + val CreateProductFeeError = "OBP-30118: Could not insert the Product Fee." + val UpdateProductFeeError = "OBP-30119: Could not update the Product Fee." val EntitlementIsBankRole = "OBP-30205: This entitlement is a Bank Role. Please set bank_id to a valid bank id." diff --git a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala index 0c292eb68..8c5e01438 100644 --- a/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala +++ b/obp-api/src/main/scala/code/productfee/MappedProductFeeProvider.scala @@ -1,6 +1,7 @@ package code.productfee import code.api.util.APIUtil +import code.api.util.ErrorMessages.{CreateProductFeeError, UpdateProductFeeError} import code.util.UUIDString import com.openbankproject.commons.model.{BankId, ProductCode, ProductFeeTrait} import net.liftweb.common.{Box, Empty, Full} @@ -54,12 +55,12 @@ object MappedProductFeeProvider extends ProductFeeProvider { .Frequency(frequency) .Type(`type`) .saveMe() - } + } ?~! s"$UpdateProductFeeError" case _ => Empty } } case None => Future { - Full { + tryo { ProductFee .create .ProductFeeId(APIUtil.generateUUID) @@ -73,7 +74,7 @@ object MappedProductFeeProvider extends ProductFeeProvider { .Frequency(frequency) .Type(`type`) .saveMe() - } + } ?~! s"$CreateProductFeeError" } } } From e0b384303d48473a182c4b05021a8eb06d4e3292 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Sep 2021 17:13:54 +0200 Subject: [PATCH 120/293] docfix/added the Dynamic Endpoint and Endpoint Mapping to Glossary --- .../main/scala/code/api/util/Glossary.scala | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index d1d947480..d84c42439 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2216,6 +2216,55 @@ object Glossary extends MdcLoggable { | """.stripMargin) + glossaryItems += GlossaryItem( + title = "Dynamic Endpoint", + description = + s""" +|Dynamic Endpoint, you can create dynamic endpoints by the swagger files. +|All the endpoints defined in the swagger file, will be created in OBP sandbox. +|There will be two different modes of these created endpoints. +| +|If the host of swagger is dynamic_entity, then you need link the swagger fields to the dynamic entity fields, +|please check *Endpoint Mapping* endpoints. +| +|If the host of swagger is obp_mock, every dynamic endpoint will return example response of swagger. +|If you need to link the response to external resource, please check * Method Routing* endpoints. +| +| +|Dynamic Endpoint can be created at the System level (bank_id is null) - or Bank / Space level (bank_id is not null). +|You might want to create Bank level Dynamic Entities in order to grant automated roles based on user email domain. +| +|Upon successful creation of a Dynamic Endpoint, OBP automatically: +| +|*Creates Roles to guard the above endpoints. +|*Granted yourself the entitlements to get the access to these endpoints. +| +|The following videos are available: +| +| * [Introduction to Dynamic Endpoints](https://vimeo.com/426235612) +| * [Features of Dynamic Endpoints](https://vimeo.com/444133309) +| +""".stripMargin) + + glossaryItems += GlossaryItem( + title = "Endpoint Mapping", + description = + s""" + |This can be used to map the dynamic entity fields and dynamic endpoint fields. + | + |When you create the dynamic endpoint, and set `host` of swagger to dynamic_entity. + | + |Then you can use these endpoints to map dynamic endpoint response to dynamic entity model. + | + |Check the [Create Endpoint Mapping](/index#OBPv4.0.0-createEndpointMapping) json body, you need to first know the operation_id + | + |and you can prepare the request_mapping and response_mapping objects. + | + |Details better to see the video: + | + | * [Endpoint Mapping -step1-getOne:GetAll](https://vimeo.com/553369108) + |""".stripMargin) + /////////////////////////////////////////////////////////////////// // NOTE! Some glossary items are generated in ExampleValue.scala From 3c7c5ffcf70fa4187718d1ebf97749ea63f3bdba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 15 Sep 2021 18:11:19 +0200 Subject: [PATCH 121/293] feature/Add User Agreements at User's JSON Response v4.0.0 --- .../SwaggerDefinitionsJSON.scala | 15 +++ .../main/scala/code/api/util/APIUtil.scala | 2 +- .../main/scala/code/api/util/NewStyle.scala | 5 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 101 ++++++++++++++++-- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 24 ++++- .../remotedata/RemotedataUserAgreement.scala | 3 + .../RemotedataUserAgreementActor.scala | 4 + .../code/remotedata/RemotedataUsers.scala | 7 +- .../remotedata/RemotedataUsersActor.scala | 4 + .../src/main/scala/code/users/LiftUsers.scala | 34 ++++-- .../main/scala/code/users/UserAgreement.scala | 7 ++ .../code/users/UserAgreementProvider.scala | 5 + obp-api/src/main/scala/code/users/Users.scala | 3 + .../test/scala/code/api/v4_0_0/UserTest.scala | 74 ++++++++++++- 14 files changed, 266 insertions(+), 22 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 5a40b3321..bd7240257 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1701,6 +1701,18 @@ object SwaggerDefinitionsJSON { username = usernameExample.value, entitlements = entitlementJSONs ) + + val userJsonV400 = UserJsonV400( + user_id = ExampleValue.userIdExample.value, + email = ExampleValue.emailExample.value, + provider_id = providerIdValueExample.value, + provider = providerValueExample.value, + username = usernameExample.value, + entitlements = entitlementJSONs, + views = None, + agreements = Some(Nil), + is_deleted = false + ) val userIdJsonV400 = UserIdJsonV400( user_id = ExampleValue.userIdExample.value ) @@ -1965,6 +1977,9 @@ object SwaggerDefinitionsJSON { val usersJsonV200 = UsersJsonV200( users = List(userJsonV200) ) + val usersJsonV400 = UsersJsonV400( + users = List(userJsonV400) + ) val counterpartiesJSON = CounterpartiesJSON( counterparties = List(coreCounterpartyJSON) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 97487d270..ee9975643 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2989,7 +2989,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ throw new Exception(UnknownError) } } - + def unboxFullAndWrapIntoFuture[T](box: Box[T])(implicit m: Manifest[T]) : Future[T] = { Future { unboxFull(fullBoxOrException(box)) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index f2a844196..bc5838b3a 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -36,7 +36,7 @@ import code.apicollection.{ApiCollectionTrait, MappedApiCollectionsProvider} import code.model.dataAccess.{AuthUser, BankAccountRouting} import code.standingorders.StandingOrderTrait import code.usercustomerlinks.UserCustomerLink -import code.users.{UserInvitation, UserInvitationProvider, Users} +import code.users.{UserAgreement, UserAgreementProvider, UserInvitation, UserInvitationProvider, Users} import code.util.Helper import com.openbankproject.commons.util.{ApiVersion, JsonUtils} import code.views.Views @@ -824,6 +824,9 @@ object NewStyle { connectorEmptyResponse(_, callContext) } } + def getAgreementByUserId(userId: String, agreementType: String, callContext: Option[CallContext]): Future[Box[UserAgreement]] = { + Future(UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(userId, agreementType)) + } def getEntitlementsByBankId(bankId: String, callContext: Option[CallContext]): Future[List[Entitlement]] = { Entitlement.entitlement.vend.getEntitlementsByBankId(bankId) map { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 8283d6434..c7096c497 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -41,7 +41,7 @@ import code.endpointMapping.EndpointMappingCommons import code.entitlement.Entitlement import code.metadata.counterparties.{Counterparties, MappedCounterparty} import code.metadata.tags.Tags -import code.model.dataAccess.{AuthUser, BankAccountCreation} +import code.model.dataAccess.{AuthUser, BankAccountCreation, ResourceUser} import code.model.{toUserExtended, _} import code.ratelimiting.RateLimitingDI import code.snippet.{WebUIPlaceholder, WebUITemplate} @@ -51,7 +51,7 @@ import code.transactionrequests.TransactionRequests.TransactionChallengeTypes._ import code.transactionrequests.TransactionRequests.TransactionRequestTypes import code.transactionrequests.TransactionRequests.TransactionRequestTypes.{apply => _, _} import code.userlocks.UserLocksProvider -import code.users.Users +import code.users.{UserAgreement, Users} import code.util.Helper.booleanToFuture import code.util.{Helper, JsonSchemaUtil} import code.validation.JsonValidation @@ -78,9 +78,9 @@ import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To, XHTMLMailB import net.liftweb.util.{Helpers, Mailer, StringHelpers} import org.apache.commons.collections4.CollectionUtils import org.apache.commons.lang3.StringUtils - import java.net.URLEncoder import java.util.{Calendar, Date} + import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future @@ -3384,7 +3384,7 @@ trait APIMethods400 { | """.stripMargin, EmptyBody, - usersJsonV200, + userJsonV400, List(UserNotLoggedIn, UserHasMissingRoles, UserNotFoundById, UnknownError), List(apiTagUser, apiTagNewStyle), Some(List(canGetAnyUser))) @@ -3394,14 +3394,97 @@ trait APIMethods400 { case "users" :: "user_id" :: userId :: Nil JsonGet _ => { cc => for { - (Full(u), callContext) <- authenticatedAccess(cc) - _ <- NewStyle.function.hasEntitlement("", u.userId, ApiRole.canGetAnyUser, callContext) user <- Users.users.vend.getUserByUserIdFuture(userId) map { - x => unboxFullOrFail(x, callContext, s"$UserNotFoundByUserId Current UserId($userId)") + x => unboxFullOrFail(x, cc.callContext, s"$UserNotFoundByUserId Current UserId($userId)") } - entitlements <- NewStyle.function.getEntitlementsByUserId(user.userId, callContext) + entitlements <- NewStyle.function.getEntitlementsByUserId(user.userId, cc.callContext) + acceptMarketingInfo <- NewStyle.function.getAgreementByUserId(user.userId, "accept_marketing_info", cc.callContext) + termsAndConditions <- NewStyle.function.getAgreementByUserId(user.userId, "terms_and_conditions", cc.callContext) + privacyConditions <- NewStyle.function.getAgreementByUserId(user.userId, "privacy_conditions", cc.callContext) } yield { - (JSONFactory400.createUserInfoJSON(user, entitlements), HttpCode.`200`(callContext)) + val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + (JSONFactory400.createUserInfoJSON(user, entitlements, Some(agreements)), HttpCode.`200`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getUserByUsername, + implementedInApiVersion, + nameOf(getUserByUsername), + "GET", + "/users/username/USERNAME", + "Get User by USERNAME", + s"""Get user by USERNAME + | + |${authenticationRequiredMessage(true)} + | + |CanGetAnyUser entitlement is required, + | + """.stripMargin, + emptyObjectJson, + userJsonV400, + List($UserNotLoggedIn, UserHasMissingRoles, UserNotFoundByUsername, UnknownError), + List(apiTagUser, apiTagNewStyle), + Some(List(canGetAnyUser))) + + + lazy val getUserByUsername: OBPEndpoint = { + case "users" :: "username" :: username :: Nil JsonGet _ => { + cc => + for { + user <- Users.users.vend.getUserByUserNameFuture(username) map { + x => unboxFullOrFail(x, cc.callContext, UserNotFoundByUsername, 404) + } + entitlements <- NewStyle.function.getEntitlementsByUserId(user.userId, cc.callContext) + acceptMarketingInfo <- NewStyle.function.getAgreementByUserId(user.userId, "accept_marketing_info", cc.callContext) + termsAndConditions <- NewStyle.function.getAgreementByUserId(user.userId, "terms_and_conditions", cc.callContext) + privacyConditions <- NewStyle.function.getAgreementByUserId(user.userId, "privacy_conditions", cc.callContext) + } yield { + val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + (JSONFactory400.createUserInfoJSON(user, entitlements, Some(agreements)), HttpCode.`200`(cc.callContext)) + } + } + } + + staticResourceDocs += ResourceDoc( + getUsers, + implementedInApiVersion, + nameOf(getUsers), + "GET", + "/users", + "Get all Users", + s"""Get all users + | + |${authenticationRequiredMessage(true)} + | + |CanGetAnyUser entitlement is required, + | + |${urlParametersDocument(false, false)} + |* locked_status (if null ignore) + | + """.stripMargin, + emptyObjectJson, + usersJsonV400, + List( + $UserNotLoggedIn, + UserHasMissingRoles, + UnknownError + ), + List(apiTagUser, apiTagNewStyle), + Some(List(canGetAnyUser))) + + lazy val getUsers: OBPEndpoint = { + case "users" :: Nil JsonGet _ => { + cc => + for { + httpParams <- NewStyle.function.extractHttpParamsFromUrl(cc.url) + obpQueryParams <- createQueriesByHttpParamsFuture(httpParams) map { + x => unboxFullOrFail(x, cc.callContext, InvalidFilterParameterFormat) + } + users <- Users.users.vend.getUsers(obpQueryParams) + } yield { + (JSONFactory400.createUsersJson(users), HttpCode.`200`(cc.callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index a3ad2eace..05713e556 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -35,6 +35,7 @@ import code.api.util.APIUtil.{DateWithDay, DateWithSeconds, stringOptionOrNull, import code.api.v1_2_1.JSONFactory.{createAmountOfMoneyJSON, createOwnersJSON} import code.api.v1_2_1.{BankRoutingJsonV121, JSONFactory, UserJSONV121, ViewJSONV121} import code.api.v1_4_0.JSONFactory1_4_0.{LocationJsonV140, MetaJsonV140, TransactionRequestAccountJsonV140, transformToLocationFromV140, transformToMetaFromV140} +import code.api.v2_0_0.JSONFactory200.UserJsonV200 import code.api.v2_0_0.{EntitlementJSONs, JSONFactory200, TransactionRequestChargeJsonV200} import code.api.v2_1_0.{IbanJson, JSONFactory210, PostCounterpartyBespokeJson, ResourceUserJSON} import code.api.v2_2_0.CounterpartyMetadataJson @@ -48,12 +49,13 @@ import code.atms.Atms.Atm import code.bankattribute.BankAttribute import code.consent.MappedConsent import code.entitlement.Entitlement +import code.model.dataAccess.ResourceUser import code.model.{Consumer, ModeratedBankAccount, ModeratedBankAccountCore} import code.ratelimiting.RateLimiting import code.standingorders.StandingOrderTrait import code.transactionrequests.TransactionRequests.TransactionChallengeTypes import code.userlocks.UserLocks -import code.users.UserInvitation +import code.users.{UserAgreement, UserInvitation} import com.openbankproject.commons.model.{DirectDebitTrait, ProductFeeTrait, _} import net.liftweb.common.{Box, Full} import net.liftweb.json.JValue @@ -887,6 +889,7 @@ case class AtmJsonV400 ( case class AtmsJsonV400(atms : List[AtmJsonV400]) +case class UserAgreementJson(`type`: String, text: String) case class UserJsonV400( user_id: String, email : String, @@ -895,12 +898,14 @@ case class UserJsonV400( username : String, entitlements : EntitlementJSONs, views: Option[ViewsJSON300], + agreements: Option[List[UserAgreementJson]], is_deleted: Boolean ) +case class UsersJsonV400(users: List[UserJsonV400]) object JSONFactory400 { - def createUserInfoJSON(user : User, entitlements: List[Entitlement]) : UserJsonV400 = { + def createUserInfoJSON(user : User, entitlements: List[Entitlement], agreements: Option[List[UserAgreement]]) : UserJsonV400 = { UserJsonV400( user_id = user.userId, email = user.emailAddress, @@ -909,10 +914,25 @@ object JSONFactory400 { provider = stringOrNull(user.provider), entitlements = JSONFactory200.createEntitlementJSONs(entitlements), views = None, + agreements = agreements.map(_.map( i => + UserAgreementJson(`type` = i.agreementType, text = i.agreementText)) + ), is_deleted = user.isDeleted.getOrElse(false) ) } + def createUsersJson(users : List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]) : UsersJsonV400 = { + UsersJsonV400( + users.map(t => + createUserInfoJSON( + t._1, + t._2.getOrElse(Nil), + t._3 + ) + ) + ) + } + def createCallsLimitJson(rateLimiting: RateLimiting) : CallLimitJsonV400 = { CallLimitJsonV400( rateLimiting.fromDate, diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala index 9960f49a7..bc872e22c 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreement.scala @@ -16,4 +16,7 @@ object RemotedataUserAgreement extends ObpActorInit with UserAgreementProvider { def createUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] = getValueFromFuture( (actor ? cc.createOrUpdateUserAgreement(userId, agreementType, agreementText)).mapTo[Box[UserAgreement]] ) + def getUserAgreement(userId: String, agreementType: String): Box[UserAgreement] = getValueFromFuture( + (actor ? cc.getUserAgreement(userId, agreementType)).mapTo[Box[UserAgreement]] + ) } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala index cac3ddcb7..0967f7670 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUserAgreementActor.scala @@ -20,6 +20,10 @@ class RemotedataUserAgreementActor extends Actor with ObpActorHelper with MdcLog logger.debug(s"createUserAgreement($userId, $agreementType, $agreementText)") sender ! (mapper.createUserAgreement(userId, agreementType, agreementText)) + case cc.getUserAgreement(userId: String, agreementType: String) => + logger.debug(s"getUserAgreement($userId, $agreementType)") + sender ! (mapper.getUserAgreement(userId, agreementType)) + case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala index faa3b2a6c..596de4772 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala @@ -5,7 +5,7 @@ import code.actorsystem.ObpActorInit import code.api.util.OBPQueryParam import code.entitlement.Entitlement import code.model.dataAccess.ResourceUser -import code.users.{RemotedataUsersCaseClasses, Users} +import code.users.{RemotedataUsersCaseClasses, UserAgreement, Users} import com.openbankproject.commons.model.{User, UserPrimaryKey} import net.liftweb.common.Box @@ -70,6 +70,11 @@ object RemotedataUsers extends ObpActorInit with Users { val res = (actor ? cc.getAllUsersF(queryParams)) res.mapTo[List[(ResourceUser, Box[List[Entitlement]])]] } + + def getUsers(queryParams: List[OBPQueryParam]): Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] = { + val res = (actor ? cc.getUsers(queryParams)) + res.mapTo[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] + } def createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) : Box[ResourceUser] = getValueFromFuture( (actor ? cc.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, createdByUserInvitationId, company)).mapTo[Box[ResourceUser]] diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala index a088959ed..eab4b368c 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala @@ -78,6 +78,10 @@ class RemotedataUsersActor extends Actor with ObpActorHelper with MdcLoggable { case cc.getAllUsersF(queryParams: List[OBPQueryParam]) => logger.debug(s"getAllUsersF(queryParams: ($queryParams))") mapper.getAllUsersF(queryParams) pipeTo sender + + case cc.getUsers(queryParams: List[OBPQueryParam]) => + logger.debug(s"getUsers(queryParams: ($queryParams))") + mapper.getUsers(queryParams) pipeTo sender case cc.createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) => logger.debug("createResourceUser(" + provider + ", " + providerId.getOrElse("None") + ", " + name.getOrElse("None") + ", " + email.getOrElse("None") + ", " + userId.getOrElse("None") + ", " + createdByUserInvitationId.getOrElse("None") + ", " + company.getOrElse("None") + ")") diff --git a/obp-api/src/main/scala/code/users/LiftUsers.scala b/obp-api/src/main/scala/code/users/LiftUsers.scala index 99c1168e0..4071da280 100644 --- a/obp-api/src/main/scala/code/users/LiftUsers.scala +++ b/obp-api/src/main/scala/code/users/LiftUsers.scala @@ -123,11 +123,21 @@ object LiftUsers extends Users with MdcLoggable{ } override def getAllUsersF(queryParams: List[OBPQueryParam]): Future[List[(ResourceUser, Box[List[Entitlement]])]] = { - + Future { + for { + user <- getUsersCommon(queryParams) + } yield { + (user, Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName))) + } + } + } + + + private def getUsersCommon(queryParams: List[OBPQueryParam]) = { val limit = queryParams.collect { case OBPLimit(value) => MaxRows[ResourceUser](value) }.headOption val offset: Option[StartAt[ResourceUser]] = queryParams.collect { case OBPOffset(value) => StartAt[ResourceUser](value) }.headOption val locked: Option[String] = queryParams.collect { case OBPLockedStatus(value) => value }.headOption - val deleted = queryParams.collect { + val deleted = queryParams.collect { case OBPIsDeleted(value) if value == true => // ?is_deleted=true By(ResourceUser.IsDeleted, true) case OBPIsDeleted(value) if value == false => // ?is_deleted=false @@ -135,13 +145,14 @@ object LiftUsers extends Users with MdcLoggable{ }.headOption.orElse( Some(By(ResourceUser.IsDeleted, false)) // There is no query parameter "is_deleted" ) - + val optionalParams: Seq[QueryParam[ResourceUser]] = Seq(limit.toSeq, offset.toSeq, deleted.toSeq).flatten - + def getAllResourceUsers(): List[ResourceUser] = ResourceUser.findAll(optionalParams: _*) + val showUsers: List[ResourceUser] = locked.map(_.toLowerCase()) match { case Some("active") => - val lockedUsers: immutable.Seq[MappedBadLoginAttempt] = + val lockedUsers: immutable.Seq[MappedBadLoginAttempt] = MappedBadLoginAttempt.findAll( By_>(MappedBadLoginAttempt.mBadAttemptsSinceLastSuccessOrReset, maxBadLoginAttempts.toInt) ) @@ -157,11 +168,20 @@ object LiftUsers extends Users with MdcLoggable{ case _ => getAllResourceUsers() } + showUsers + } + + override def getUsers(queryParams: List[OBPQueryParam]): Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] = { Future { for { - user <- showUsers + user <- getUsersCommon(queryParams) } yield { - (user, Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName))) + val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName)) + val acceptMarketingInfo = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "accept_marketing_info") + val termsAndConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "terms_and_conditions") + val privacyConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "privacy_conditions") + val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + (user, entitlements, Some(agreements)) } } } diff --git a/obp-api/src/main/scala/code/users/UserAgreement.scala b/obp-api/src/main/scala/code/users/UserAgreement.scala index 9dc3439bd..19a643279 100644 --- a/obp-api/src/main/scala/code/users/UserAgreement.scala +++ b/obp-api/src/main/scala/code/users/UserAgreement.scala @@ -43,6 +43,12 @@ object MappedUserAgreementProvider extends UserAgreementProvider { .saveMe() ) } + override def getUserAgreement(userId: String, agreementType: String): Box[UserAgreement] = { + UserAgreement.findAll( + By(UserAgreement.UserId, userId), + By(UserAgreement.AgreementType, agreementType) + ).sortBy(_.Date.get)(Ordering[Date].reverse).headOption + } } class UserAgreement extends UserAgreementTrait with LongKeyedMapper[UserAgreement] with IdPK with CreatedUpdated { @@ -64,6 +70,7 @@ class UserAgreement extends UserAgreementTrait with LongKeyedMapper[UserAgreemen override def agreementType: String = AgreementType.get override def agreementText: String = AgreementText.get override def agreementHash: String = AgreementHash.get + override def date: Date = Date.get } object UserAgreement extends UserAgreement with LongKeyedMetaMapper[UserAgreement] { diff --git a/obp-api/src/main/scala/code/users/UserAgreementProvider.scala b/obp-api/src/main/scala/code/users/UserAgreementProvider.scala index 85d57dbb2..30c9a049e 100644 --- a/obp-api/src/main/scala/code/users/UserAgreementProvider.scala +++ b/obp-api/src/main/scala/code/users/UserAgreementProvider.scala @@ -1,5 +1,7 @@ package code.users +import java.util.Date + import code.api.util.APIUtil import code.remotedata.RemotedataUserAgreement import net.liftweb.common.Box @@ -21,11 +23,13 @@ object UserAgreementProvider extends SimpleInjector { trait UserAgreementProvider { def createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] def createUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] + def getUserAgreement(userId: String, agreementType: String): Box[UserAgreement] } class RemotedataUserAgreementProviderCaseClass { case class createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String) case class createUserAgreement(userId: String, agreementType: String, agreementText: String) + case class getUserAgreement(userId: String, agreementType: String) } object RemotedataUserAgreementProviderCaseClass extends RemotedataUserAgreementProviderCaseClass @@ -36,4 +40,5 @@ trait UserAgreementTrait { def agreementType: String def agreementText: String def agreementHash: String + def date: Date } \ No newline at end of file diff --git a/obp-api/src/main/scala/code/users/Users.scala b/obp-api/src/main/scala/code/users/Users.scala index 771d37a78..a84512374 100644 --- a/obp-api/src/main/scala/code/users/Users.scala +++ b/obp-api/src/main/scala/code/users/Users.scala @@ -51,6 +51,8 @@ trait Users { def getAllUsersF(queryParams: List[OBPQueryParam]) : Future[List[(ResourceUser, Box[List[Entitlement]])]] + def getUsers(queryParams: List[OBPQueryParam]): Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] + def createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) : Box[ResourceUser] def createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) : Box[ResourceUser] @@ -80,6 +82,7 @@ class RemotedataUsersCaseClasses { case class getUserByEmailFuture(email : String) case class getAllUsers() case class getAllUsersF(queryParams: List[OBPQueryParam]) + case class getUsers(queryParams: List[OBPQueryParam]) case class createResourceUser(provider: String, providerId: Option[String],createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) case class createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) case class saveResourceUser(resourceUser: ResourceUser) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala index adbc5274d..10734a17b 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala @@ -1,10 +1,14 @@ package code.api.v4_0_0 +import java.util.UUID + import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole.CanGetAnyUser -import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn, attemptedToOpenAnEmptyBox} import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 import code.entitlement.Entitlement +import code.model.UserX +import code.users.Users import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.ErrorMessage import com.openbankproject.commons.util.ApiVersion @@ -21,6 +25,8 @@ class UserTest extends V400ServerSetup { object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.getCurrentUserId)) object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getUserByUserId)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getUsers)) + object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.getUserByUsername)) feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") { @@ -76,6 +82,72 @@ class UserTest extends V400ServerSetup { response400.body.extract[UserJsonV400].user_id should equal(resourceUser3.userId) } } + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Unauthorized access") { + scenario("We will call the endpoint without user credentials", ApiEndpoint3, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users").GET + val response400 = makeGetRequest(request400) + Then("We should get a 401") + response400.code should equal(401) + response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + feature(s"test $ApiEndpoint3 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials but without a proper entitlement", ApiEndpoint3, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users").GET <@(user1) + val response400 = makeGetRequest(request400) + Then("error should be " + UserHasMissingRoles + CanGetAnyUser) + response400.code should equal(403) + response400.body.extract[ErrorMessage].message should be (UserHasMissingRoles + CanGetAnyUser) + } + } + feature(s"test $ApiEndpoint3 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials and a proper entitlement", ApiEndpoint3, VersionOfApi) { + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users").GET <@(user1) + val response400 = makeGetRequest(request400) + Then("We get successful response") + response400.code should equal(200) + response400.body.extract[UsersJsonV400] + } + } + + feature(s"test $ApiEndpoint4 version $VersionOfApi - Unauthorized access") { + scenario("We will call the endpoint without user credentials", ApiEndpoint4, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users" / "username" / "USERNAME").GET + val response400 = makeGetRequest(request400) + Then("We should get a 401") + response400.code should equal(401) + response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials but without a proper entitlement", ApiEndpoint4, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users" / "username" / "USERNAME").GET <@(user1) + val response400 = makeGetRequest(request400) + Then("error should be " + UserHasMissingRoles + CanGetAnyUser) + response400.code should equal(403) + response400.body.extract[ErrorMessage].message should be (UserHasMissingRoles + CanGetAnyUser) + } + } + feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials and a proper entitlement", ApiEndpoint4, VersionOfApi) { + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) + val user = UserX.createResourceUser(defaultProvider, Some("user.name.1"), None, Some("user.name.1"), None, Some(UUID.randomUUID.toString), None).openOrThrowException(attemptedToOpenAnEmptyBox) + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users" / "username" / user.idGivenByProvider).GET <@(user1) + val response400 = makeGetRequest(request400) + Then("We get successful response") + response400.code should equal(200) + response400.body.extract[UserJsonV400] + Users.users.vend.deleteResourceUser(user.id.get) + } + } } From 536ea172966c1a939266f362ef4fc18e99395a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 15 Sep 2021 18:58:34 +0200 Subject: [PATCH 122/293] feature/Add endpoint getUsersByEmail v4.0.0 --- .../scala/code/api/v4_0_0/APIMethods400.scala | 32 +++++++++++++++++ .../code/remotedata/RemotedataUsers.scala | 3 ++ .../remotedata/RemotedataUsersActor.scala | 4 +++ .../src/main/scala/code/users/LiftUsers.scala | 14 ++++++++ obp-api/src/main/scala/code/users/Users.scala | 2 ++ .../test/scala/code/api/v4_0_0/UserTest.scala | 35 +++++++++++++++++++ 6 files changed, 90 insertions(+) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index c7096c497..3e1136a53 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -3447,6 +3447,38 @@ trait APIMethods400 { } } + + staticResourceDocs += ResourceDoc( + getUsersByEmail, + implementedInApiVersion, + nameOf(getUsersByEmail), + "GET", + "/users/email/EMAIL/terminator", + "Get Users by Email Address", + s"""Get users by email address + | + |${authenticationRequiredMessage(true)} + |CanGetAnyUser entitlement is required, + | + """.stripMargin, + emptyObjectJson, + usersJsonV400, + List($UserNotLoggedIn, UserHasMissingRoles, UserNotFoundByEmail, UnknownError), + List(apiTagUser, apiTagNewStyle), + Some(List(canGetAnyUser))) + + + lazy val getUsersByEmail: OBPEndpoint = { + case "users" :: "email" :: email :: "terminator" :: Nil JsonGet _ => { + cc => + for { + users <- Users.users.vend.getUsersByEmail(email) + } yield { + (JSONFactory400.createUsersJson(users), HttpCode.`200`(cc.callContext)) + } + } + } + staticResourceDocs += ResourceDoc( getUsers, implementedInApiVersion, diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala index 596de4772..50c9eef34 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala @@ -61,6 +61,9 @@ object RemotedataUsers extends ObpActorInit with Users { def getUserByEmailFuture(email : String) : Future[List[(ResourceUser, Box[List[Entitlement]])]] = (actor ? cc.getUserByEmailFuture(email)).mapTo[List[(ResourceUser, Box[List[Entitlement]])]] + + def getUsersByEmail(email : String) : Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] = + (actor ? cc.getUsersByEmail(email)).mapTo[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] def getAllUsers() : Box[List[ResourceUser]] = getValueFromFuture( (actor ? cc.getAllUsers()).mapTo[Box[List[ResourceUser]]] diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala index eab4b368c..696999375 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala @@ -70,6 +70,10 @@ class RemotedataUsersActor extends Actor with ObpActorHelper with MdcLoggable { case cc.getUserByEmailFuture(email: String) => logger.debug("getUserByEmailFuture(" + email +")") sender ! (mapper.getUserByEmailF(email)) + + case cc.getUsersByEmail(email: String) => + logger.debug("getUsersByEmail(" + email +")") + mapper.getUsersByEmail(email) pipeTo sender case cc.getAllUsers() => logger.debug("getAllUsers()") diff --git a/obp-api/src/main/scala/code/users/LiftUsers.scala b/obp-api/src/main/scala/code/users/LiftUsers.scala index 4071da280..f9e610510 100644 --- a/obp-api/src/main/scala/code/users/LiftUsers.scala +++ b/obp-api/src/main/scala/code/users/LiftUsers.scala @@ -111,6 +111,20 @@ object LiftUsers extends Users with MdcLoggable{ (user, Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName))) } } + + override def getUsersByEmail(email: String): Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] = Future { + val users = ResourceUser.findAll(By(ResourceUser.email, email)) + for { + user <- users + } yield { + val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName)) + val acceptMarketingInfo = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "accept_marketing_info") + val termsAndConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "terms_and_conditions") + val privacyConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "privacy_conditions") + val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + (user, entitlements, Some(agreements)) + } + } override def getUserByEmailFuture(email: String): Future[List[(ResourceUser, Box[List[Entitlement]])]] = { Future { diff --git a/obp-api/src/main/scala/code/users/Users.scala b/obp-api/src/main/scala/code/users/Users.scala index a84512374..ef6344eb5 100644 --- a/obp-api/src/main/scala/code/users/Users.scala +++ b/obp-api/src/main/scala/code/users/Users.scala @@ -46,6 +46,7 @@ trait Users { def getUserByEmail(email: String) : Box[List[ResourceUser]] def getUserByEmailFuture(email: String) : Future[List[(ResourceUser, Box[List[Entitlement]])]] + def getUsersByEmail(email: String) : Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] def getAllUsers() : Box[List[ResourceUser]] @@ -80,6 +81,7 @@ class RemotedataUsersCaseClasses { case class getUserByUserNameFuture(userName : String) case class getUserByEmail(email : String) case class getUserByEmailFuture(email : String) + case class getUsersByEmail(email : String) case class getAllUsers() case class getAllUsersF(queryParams: List[OBPQueryParam]) case class getUsers(queryParams: List[OBPQueryParam]) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala index 10734a17b..614563610 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/UserTest.scala @@ -27,6 +27,7 @@ class UserTest extends V400ServerSetup { object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getUserByUserId)) object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getUsers)) object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.getUserByUsername)) + object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.getUsersByEmail)) feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") { @@ -149,5 +150,39 @@ class UserTest extends V400ServerSetup { } } + feature(s"test $ApiEndpoint5 version $VersionOfApi - Unauthorized access") { + scenario("We will call the endpoint without user credentials", ApiEndpoint5, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users" / "email" / "EMAIL" / "terminator").GET + val response400 = makeGetRequest(request400) + Then("We should get a 401") + response400.code should equal(401) + response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + feature(s"test $ApiEndpoint5 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials but without a proper entitlement", ApiEndpoint5, VersionOfApi) { + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users" / "email" / "EMAIL" / "terminator").GET <@(user1) + val response400 = makeGetRequest(request400) + Then("error should be " + UserHasMissingRoles + CanGetAnyUser) + response400.code should equal(403) + response400.body.extract[ErrorMessage].message should be (UserHasMissingRoles + CanGetAnyUser) + } + } + feature(s"test $ApiEndpoint5 version $VersionOfApi - Authorized access") { + scenario("We will call the endpoint with user credentials and a proper entitlement", ApiEndpoint5, VersionOfApi) { + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString) + val user = UserX.createResourceUser(defaultProvider, Some("user.name.1"), None, Some("user.name.1"), Some("test@tesobe.com"), Some(UUID.randomUUID.toString), None).openOrThrowException(attemptedToOpenAnEmptyBox) + When("We make a request v4.0.0") + val request400 = (v4_0_0_Request / "users" / "email" / user.emailAddress / "terminator").GET <@(user1) + val response400 = makeGetRequest(request400) + Then("We get successful response") + response400.code should equal(200) + response400.body.extract[UsersJsonV400] + Users.users.vend.deleteResourceUser(user.id.get) + } + } + } From 93937bac0a246dc3e34d9ddf94519c41224b6208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 16 Sep 2021 09:32:12 +0200 Subject: [PATCH 123/293] refactor/Add User Agreements at User's JSON Response v4.0.0 --- .../src/main/scala/code/users/LiftUsers.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/users/LiftUsers.scala b/obp-api/src/main/scala/code/users/LiftUsers.scala index f9e610510..56a68a496 100644 --- a/obp-api/src/main/scala/code/users/LiftUsers.scala +++ b/obp-api/src/main/scala/code/users/LiftUsers.scala @@ -118,14 +118,19 @@ object LiftUsers extends Users with MdcLoggable{ user <- users } yield { val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName)) - val acceptMarketingInfo = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "accept_marketing_info") - val termsAndConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "terms_and_conditions") - val privacyConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "privacy_conditions") - val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + val agreements = getUserAgreements(user) (user, entitlements, Some(agreements)) } } + private def getUserAgreements(user: ResourceUser) = { + val acceptMarketingInfo = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "accept_marketing_info") + val termsAndConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "terms_and_conditions") + val privacyConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "privacy_conditions") + val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + agreements + } + override def getUserByEmailFuture(email: String): Future[List[(ResourceUser, Box[List[Entitlement]])]] = { Future { getUserByEmailF(email) @@ -191,10 +196,7 @@ object LiftUsers extends Users with MdcLoggable{ user <- getUsersCommon(queryParams) } yield { val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName)) - val acceptMarketingInfo = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "accept_marketing_info") - val termsAndConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "terms_and_conditions") - val privacyConditions = UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(user.userId, "privacy_conditions") - val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList + val agreements = getUserAgreements(user) (user, entitlements, Some(agreements)) } } From 138af5eb85231fc2f75e1c8a180bc3a51df30f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 16 Sep 2021 12:39:49 +0200 Subject: [PATCH 124/293] bugfix/Enforce Auth User validations at user invitation flow --- .../scala/code/snippet/UserInvitation.scala | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 94b18e002..c4c38f61f 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -36,7 +36,7 @@ import code.util.Helper import code.util.Helper.MdcLoggable import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.openbankproject.commons.model.User -import net.liftweb.common.{Box, Full} +import net.liftweb.common.{Box, Empty, Failure, Full} import net.liftweb.http.{RequestVar, S, SHtml} import net.liftweb.util.CssSel import net.liftweb.util.Helpers._ @@ -96,25 +96,30 @@ class UserInvitation extends MdcLoggable { createResourceUser( provider = "OBP-User-Invitation", providerId = Some(usernameVar.is), - name = Some(firstNameVar.is + " " + lastNameVar.is), + name = Some(usernameVar.is), email = Some(email), userInvitationId = userInvitation.map(_.userInvitationId).toOption, company = userInvitation.map(_.company).toOption ).map{ u => // AuthUser table - createAuthUser(user = u, firstName = firstNameVar.is, lastName = lastNameVar.is, password = "") - // Use Agreement table - UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( - u.userId, "privacy_conditions", privacyConditionsValue) - UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( - u.userId, "terms_and_conditions", termsAndConditionsValue) - UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( - u.userId, "accept_marketing_info", marketingInfoCheckboxVar.is.toString) - // Set the status of the user invitation to "FINISHED" - UserInvitationProvider.userInvitationProvider.vend.updateStatusOfUserInvitation(userInvitation.map(_.userInvitationId).getOrElse(""), "FINISHED") - // Set a new password - val resetLink = AuthUser.passwordResetUrl(u.idGivenByProvider, u.emailAddress, u.userId) + "?action=set" - S.redirectTo(resetLink) + createAuthUser(user = u, firstName = firstNameVar.is, lastName = lastNameVar.is, password = "") match { + case Failure(msg,_,_) => + Users.users.vend.deleteResourceUser(u.id.get) + showError(msg) + case _ => + // User Agreement table + UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( + u.userId, "privacy_conditions", privacyConditionsValue) + UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( + u.userId, "terms_and_conditions", termsAndConditionsValue) + UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement( + u.userId, "accept_marketing_info", marketingInfoCheckboxVar.is.toString) + // Set the status of the user invitation to "FINISHED" + UserInvitationProvider.userInvitationProvider.vend.updateStatusOfUserInvitation(userInvitation.map(_.userInvitationId).getOrElse(""), "FINISHED") + // Set a new password + val resetLink = AuthUser.passwordResetUrl(u.idGivenByProvider, u.emailAddress, u.userId) + "?action=set" + S.redirectTo(resetLink) + } } } @@ -181,18 +186,24 @@ class UserInvitation extends MdcLoggable { register } - private def createAuthUser(user: User, firstName: String, lastName: String, password: String): Box[AuthUser] = tryo { + private def createAuthUser(user: User, firstName: String, lastName: String, password: String): Box[AuthUser] = { val newUser = AuthUser.create .firstName(firstName) .lastName(lastName) .email(user.emailAddress) .user(user.userPrimaryKey.value) - .username(user.idGivenByProvider) + .username(user.name) .provider(user.provider) .password(password) .validated(true) - // Save the user - newUser.saveMe() + newUser.validate match { + case Nil => + // Save the user + Full(newUser.saveMe()) + case xs => S.error(xs) + Failure(xs.map(i => i.msg).mkString(";")) + } + } private def createResourceUser(provider: String, From 39b83a8e7a06616a6076ce7407641e0585a17f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 16 Sep 2021 13:31:56 +0200 Subject: [PATCH 125/293] feature/Remove User Agreements at User's JSON Response v4.0.0 except getUserByUserId endpoint --- .../ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 11 +++++++++++ .../main/scala/code/api/v4_0_0/APIMethods400.scala | 8 ++------ obp-api/src/main/scala/code/users/LiftUsers.scala | 8 ++++---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index bd7240257..60e866dad 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1703,6 +1703,17 @@ object SwaggerDefinitionsJSON { ) val userJsonV400 = UserJsonV400( + user_id = ExampleValue.userIdExample.value, + email = ExampleValue.emailExample.value, + provider_id = providerIdValueExample.value, + provider = providerValueExample.value, + username = usernameExample.value, + entitlements = entitlementJSONs, + views = None, + agreements = None, + is_deleted = false + ) + val userJsonWithAgreementsV400 = UserJsonV400( user_id = ExampleValue.userIdExample.value, email = ExampleValue.emailExample.value, provider_id = providerIdValueExample.value, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 3e1136a53..42e71be4b 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -3384,7 +3384,7 @@ trait APIMethods400 { | """.stripMargin, EmptyBody, - userJsonV400, + userJsonWithAgreementsV400, List(UserNotLoggedIn, UserHasMissingRoles, UserNotFoundById, UnknownError), List(apiTagUser, apiTagNewStyle), Some(List(canGetAnyUser))) @@ -3437,12 +3437,8 @@ trait APIMethods400 { x => unboxFullOrFail(x, cc.callContext, UserNotFoundByUsername, 404) } entitlements <- NewStyle.function.getEntitlementsByUserId(user.userId, cc.callContext) - acceptMarketingInfo <- NewStyle.function.getAgreementByUserId(user.userId, "accept_marketing_info", cc.callContext) - termsAndConditions <- NewStyle.function.getAgreementByUserId(user.userId, "terms_and_conditions", cc.callContext) - privacyConditions <- NewStyle.function.getAgreementByUserId(user.userId, "privacy_conditions", cc.callContext) } yield { - val agreements = acceptMarketingInfo.toList ::: termsAndConditions.toList ::: privacyConditions.toList - (JSONFactory400.createUserInfoJSON(user, entitlements, Some(agreements)), HttpCode.`200`(cc.callContext)) + (JSONFactory400.createUserInfoJSON(user, entitlements, None), HttpCode.`200`(cc.callContext)) } } } diff --git a/obp-api/src/main/scala/code/users/LiftUsers.scala b/obp-api/src/main/scala/code/users/LiftUsers.scala index 56a68a496..e8dcf9f45 100644 --- a/obp-api/src/main/scala/code/users/LiftUsers.scala +++ b/obp-api/src/main/scala/code/users/LiftUsers.scala @@ -118,8 +118,8 @@ object LiftUsers extends Users with MdcLoggable{ user <- users } yield { val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName)) - val agreements = getUserAgreements(user) - (user, entitlements, Some(agreements)) + // val agreements = getUserAgreements(user) + (user, entitlements, None) } } @@ -196,8 +196,8 @@ object LiftUsers extends Users with MdcLoggable{ user <- getUsersCommon(queryParams) } yield { val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).map(_.sortWith(_.roleName < _.roleName)) - val agreements = getUserAgreements(user) - (user, entitlements, Some(agreements)) + // val agreements = getUserAgreements(user) + (user, entitlements, None) } } } From 1156efa4d97bbf94765fb6b8fa9421464a03b1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 16 Sep 2021 16:35:38 +0200 Subject: [PATCH 126/293] bugfix/Enforce Auth User validations at user invitation flow 2 --- .../main/scala/code/api/util/SecureRandomUtil.scala | 5 +++++ .../src/main/scala/code/snippet/UserInvitation.scala | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/SecureRandomUtil.scala b/obp-api/src/main/scala/code/api/util/SecureRandomUtil.scala index 095cc9c93..a11b8c2e1 100644 --- a/obp-api/src/main/scala/code/api/util/SecureRandomUtil.scala +++ b/obp-api/src/main/scala/code/api/util/SecureRandomUtil.scala @@ -1,5 +1,6 @@ package code.api.util +import java.math.BigInteger import java.security.SecureRandom /** @@ -15,4 +16,8 @@ object SecureRandomUtil { // Obtains random numbers from the underlying native OS. // No assertions are made as to the blocking nature of generating these numbers. val csprng = SecureRandom.getInstance("NativePRNG") + + def alphanumeric(nrChars: Int = 24): String = { + new BigInteger(nrChars * 5, csprng).toString(32) + } } diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index c4c38f61f..9785fb22a 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -28,7 +28,7 @@ package code.snippet import java.time.{Duration, ZoneId, ZoneOffset, ZonedDateTime} -import code.api.util.APIUtil +import code.api.util.{APIUtil, SecureRandomUtil} import code.model.dataAccess.{AuthUser, ResourceUser} import code.users import code.users.{UserAgreementProvider, UserInvitationProvider, Users} @@ -38,7 +38,7 @@ import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.openbankproject.commons.model.User import net.liftweb.common.{Box, Empty, Failure, Full} import net.liftweb.http.{RequestVar, S, SHtml} -import net.liftweb.util.CssSel +import net.liftweb.util.{CssSel, Helpers} import net.liftweb.util.Helpers._ import scala.collection.immutable.List @@ -102,7 +102,7 @@ class UserInvitation extends MdcLoggable { company = userInvitation.map(_.company).toOption ).map{ u => // AuthUser table - createAuthUser(user = u, firstName = firstNameVar.is, lastName = lastNameVar.is, password = "") match { + createAuthUser(user = u, firstName = firstNameVar.is, lastName = lastNameVar.is) match { case Failure(msg,_,_) => Users.users.vend.deleteResourceUser(u.id.get) showError(msg) @@ -186,7 +186,7 @@ class UserInvitation extends MdcLoggable { register } - private def createAuthUser(user: User, firstName: String, lastName: String, password: String): Box[AuthUser] = { + private def createAuthUser(user: User, firstName: String, lastName: String): Box[AuthUser] = { val newUser = AuthUser.create .firstName(firstName) .lastName(lastName) @@ -194,7 +194,7 @@ class UserInvitation extends MdcLoggable { .user(user.userPrimaryKey.value) .username(user.name) .provider(user.provider) - .password(password) + .password(SecureRandomUtil.alphanumeric(10)) .validated(true) newUser.validate match { case Nil => From a265d5152859e96f2e385888f3f0020cefc52bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 16 Sep 2021 17:05:27 +0200 Subject: [PATCH 127/293] refactor/Add field last_marketing_agreement_signed_date to resourceuser table --- obp-api/src/main/scala/code/api/GatewayLogin.scala | 3 ++- obp-api/src/main/scala/code/api/OAuth2.scala | 3 ++- .../src/main/scala/code/api/openidconnect.scala | 3 ++- .../src/main/scala/code/api/util/ConsentUtil.scala | 3 ++- .../src/main/scala/code/model/BankingData.scala | 1 + obp-api/src/main/scala/code/model/User.scala | 2 +- .../scala/code/model/dataAccess/ResourceUser.scala | 4 ++++ .../scala/code/remotedata/RemotedataUsers.scala | 6 ++++-- .../code/remotedata/RemotedataUsersActor.scala | 8 +++++--- .../main/scala/code/snippet/UserInvitation.scala | 10 +++++++--- obp-api/src/main/scala/code/users/LiftUsers.scala | 12 ++++++++++-- obp-api/src/main/scala/code/users/Users.scala | 14 ++++++++++++-- .../BankAccountCreationListenerTest.scala | 2 +- .../commons/model/CommonModel.scala | 11 ++++++++++- .../openbankproject/commons/model/UserModel.scala | 3 +++ 15 files changed, 66 insertions(+), 19 deletions(-) diff --git a/obp-api/src/main/scala/code/api/GatewayLogin.scala b/obp-api/src/main/scala/code/api/GatewayLogin.scala index aaf83020e..9d2128a18 100755 --- a/obp-api/src/main/scala/code/api/GatewayLogin.scala +++ b/obp-api/src/main/scala/code/api/GatewayLogin.scala @@ -262,7 +262,8 @@ object GatewayLogin extends RestHelper with MdcLoggable { email = None, userId = None, createdByUserInvitationId = None, - company = None + company = None, + lastMarketingAgreementSignedDate = None ) } match { case Full(u) => diff --git a/obp-api/src/main/scala/code/api/OAuth2.scala b/obp-api/src/main/scala/code/api/OAuth2.scala index f138f5949..e77309bac 100644 --- a/obp-api/src/main/scala/code/api/OAuth2.scala +++ b/obp-api/src/main/scala/code/api/OAuth2.scala @@ -287,7 +287,8 @@ object OAuth2Login extends RestHelper with MdcLoggable { email = getClaim(name = "email", idToken = idToken), userId = None, createdByUserInvitationId = None, - company = None + company = None, + lastMarketingAgreementSignedDate = None ) } } diff --git a/obp-api/src/main/scala/code/api/openidconnect.scala b/obp-api/src/main/scala/code/api/openidconnect.scala index 2ed85dde2..6df50fdc2 100644 --- a/obp-api/src/main/scala/code/api/openidconnect.scala +++ b/obp-api/src/main/scala/code/api/openidconnect.scala @@ -186,7 +186,8 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { email = getClaim(name = "email", idToken = idToken), userId = None, createdByUserInvitationId = None, - company = None + company = None, + lastMarketingAgreementSignedDate = None ) } } diff --git a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala index 9cec32129..49ef8d0fb 100644 --- a/obp-api/src/main/scala/code/api/util/ConsentUtil.scala +++ b/obp-api/src/main/scala/code/api/util/ConsentUtil.scala @@ -198,7 +198,8 @@ object Consent { email = email, userId = None, createdByUserInvitationId = None, - company = None + company = None, + lastMarketingAgreementSignedDate = None ) } } diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index 07374a734..f6d0a66b2 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -199,6 +199,7 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable val createdByConsentId = None val createdByUserInvitationId = None val isDeleted = None + val lastMarketingAgreementSignedDate = None }) } else { accountHolders diff --git a/obp-api/src/main/scala/code/model/User.scala b/obp-api/src/main/scala/code/model/User.scala index 316cc2106..aff34e40a 100644 --- a/obp-api/src/main/scala/code/model/User.scala +++ b/obp-api/src/main/scala/code/model/User.scala @@ -131,7 +131,7 @@ object UserX { } def createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], company: Option[String]) = { - Users.users.vend.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, None, company) + Users.users.vend.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, None, company, None) } def createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) = { diff --git a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala index 6c8d72159..30d5d8a20 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala @@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/) */ package code.model.dataAccess +import java.util.Date + import code.api.util.APIUtil import code.util.MappedUUID import com.openbankproject.commons.model.{User, UserPrimaryKey} @@ -81,6 +83,7 @@ class ResourceUser extends LongKeyedMapper[ResourceUser] with User with ManyToMa object IsDeleted extends MappedBoolean(this) { override def defaultValue = false } + object LastMarketingAgreementSignedDate extends MappedDate(this) def emailAddress = { val e = email.get @@ -109,6 +112,7 @@ class ResourceUser extends LongKeyedMapper[ResourceUser] with User with ManyToMa override def createdByConsentId = if(CreatedByConsentId.get == null) None else if (CreatedByConsentId.get.isEmpty) None else Some(CreatedByConsentId.get) //null --> None override def createdByUserInvitationId = if(CreatedByUserInvitationId.get == null) None else if (CreatedByUserInvitationId.get.isEmpty) None else Some(CreatedByUserInvitationId.get) //null --> None override def isDeleted: Option[Boolean] = if(IsDeleted.jdbcFriendly(IsDeleted.calcFieldName) == null) None else Some(IsDeleted.get) // null --> None + override def lastMarketingAgreementSignedDate: Option[Date] = if(IsDeleted.jdbcFriendly(LastMarketingAgreementSignedDate.calcFieldName) == null) None else Some(LastMarketingAgreementSignedDate.get) // null --> None } object ResourceUser extends ResourceUser with LongKeyedMetaMapper[ResourceUser]{ diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala index 50c9eef34..3b28059fb 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUsers.scala @@ -1,5 +1,7 @@ package code.remotedata +import java.util.Date + import akka.pattern.ask import code.actorsystem.ObpActorInit import code.api.util.OBPQueryParam @@ -79,8 +81,8 @@ object RemotedataUsers extends ObpActorInit with Users { res.mapTo[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] } - def createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) : Box[ResourceUser] = getValueFromFuture( - (actor ? cc.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, createdByUserInvitationId, company)).mapTo[Box[ResourceUser]] + def createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String], lastMarketingAgreementSignedDate: Option[Date]) : Box[ResourceUser] = getValueFromFuture( + (actor ? cc.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, createdByUserInvitationId, company, lastMarketingAgreementSignedDate)).mapTo[Box[ResourceUser]] ) def createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) : Box[ResourceUser] = getValueFromFuture( diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala index 696999375..5ed768852 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUsersActor.scala @@ -1,5 +1,7 @@ package code.remotedata +import java.util.Date + import akka.actor.Actor import akka.pattern.pipe import code.actorsystem.ObpActorHelper @@ -87,9 +89,9 @@ class RemotedataUsersActor extends Actor with ObpActorHelper with MdcLoggable { logger.debug(s"getUsers(queryParams: ($queryParams))") mapper.getUsers(queryParams) pipeTo sender - case cc.createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) => - logger.debug("createResourceUser(" + provider + ", " + providerId.getOrElse("None") + ", " + name.getOrElse("None") + ", " + email.getOrElse("None") + ", " + userId.getOrElse("None") + ", " + createdByUserInvitationId.getOrElse("None") + ", " + company.getOrElse("None") + ")") - sender ! (mapper.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, createdByUserInvitationId, company)) + case cc.createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String], lastMarketingAgreementSignedDate: Option[Date]) => + logger.debug("createResourceUser(" + provider + ", " + providerId.getOrElse("None") + ", " + name.getOrElse("None") + ", " + email.getOrElse("None") + ", " + userId.getOrElse("None") + ", " + createdByUserInvitationId.getOrElse("None") + ", " + company.getOrElse("None") + ", " + lastMarketingAgreementSignedDate.getOrElse("None") + ")") + sender ! (mapper.createResourceUser(provider, providerId, createdByConsentId, name, email, userId, createdByUserInvitationId, company, lastMarketingAgreementSignedDate)) case cc.createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) => logger.debug("createUnsavedResourceUser(" + provider + ", " + providerId.getOrElse("None") + ", " + name.getOrElse("None") + ", " + email.getOrElse("None") + ", " + userId.getOrElse("None") + ")") diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 9785fb22a..5cd61f183 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -27,6 +27,7 @@ TESOBE (http://www.tesobe.com/) package code.snippet import java.time.{Duration, ZoneId, ZoneOffset, ZonedDateTime} +import java.util.Date import code.api.util.{APIUtil, SecureRandomUtil} import code.model.dataAccess.{AuthUser, ResourceUser} @@ -99,7 +100,8 @@ class UserInvitation extends MdcLoggable { name = Some(usernameVar.is), email = Some(email), userInvitationId = userInvitation.map(_.userInvitationId).toOption, - company = userInvitation.map(_.company).toOption + company = userInvitation.map(_.company).toOption, + lastMarketingAgreementSignedDate = if(marketingInfoCheckboxVar.is) Some(new Date()) else None ).map{ u => // AuthUser table createAuthUser(user = u, firstName = firstNameVar.is, lastName = lastNameVar.is) match { @@ -211,7 +213,8 @@ class UserInvitation extends MdcLoggable { name: Option[String], email: Option[String], userInvitationId: Option[String], - company: Option[String] + company: Option[String], + lastMarketingAgreementSignedDate: Option[Date], ): Box[ResourceUser] = { Users.users.vend.createResourceUser( provider = provider, @@ -221,7 +224,8 @@ class UserInvitation extends MdcLoggable { email = email, userId = None, createdByUserInvitationId = userInvitationId, - company = company + company = company, + lastMarketingAgreementSignedDate = lastMarketingAgreementSignedDate ) } diff --git a/obp-api/src/main/scala/code/users/LiftUsers.scala b/obp-api/src/main/scala/code/users/LiftUsers.scala index e8dcf9f45..73e759889 100644 --- a/obp-api/src/main/scala/code/users/LiftUsers.scala +++ b/obp-api/src/main/scala/code/users/LiftUsers.scala @@ -1,5 +1,7 @@ package code.users +import java.util.Date + import code.api.util._ import code.entitlement.Entitlement import code.loginattempts.LoginAttempt.maxBadLoginAttempts @@ -60,7 +62,8 @@ object LiftUsers extends Users with MdcLoggable{ email = email, userId = None, createdByUserInvitationId = None, - company = None + company = None, + lastMarketingAgreementSignedDate = None ) (newUser, true) } @@ -210,7 +213,8 @@ object LiftUsers extends Users with MdcLoggable{ email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], - company: Option[String]): Box[ResourceUser] = { + company: Option[String], + lastMarketingAgreementSignedDate: Option[Date]): Box[ResourceUser] = { val ru = ResourceUser.create ru.provider_(provider) providerId match { @@ -241,6 +245,10 @@ object LiftUsers extends Users with MdcLoggable{ case Some(v) => ru.Company(v) case None => } + lastMarketingAgreementSignedDate match { + case Some(v) => ru.LastMarketingAgreementSignedDate(v) + case None => + } Full(ru.saveMe()) } diff --git a/obp-api/src/main/scala/code/users/Users.scala b/obp-api/src/main/scala/code/users/Users.scala index ef6344eb5..d6b446199 100644 --- a/obp-api/src/main/scala/code/users/Users.scala +++ b/obp-api/src/main/scala/code/users/Users.scala @@ -1,5 +1,7 @@ package code.users +import java.util.Date + import code.api.util.{APIUtil, OBPQueryParam} import code.entitlement.Entitlement import code.model.dataAccess.ResourceUser @@ -54,7 +56,15 @@ trait Users { def getUsers(queryParams: List[OBPQueryParam]): Future[List[(ResourceUser, Box[List[Entitlement]], Option[List[UserAgreement]])]] - def createResourceUser(provider: String, providerId: Option[String], createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) : Box[ResourceUser] + def createResourceUser(provider: String, + providerId: Option[String], + createdByConsentId: Option[String], + name: Option[String], + email: Option[String], + userId: Option[String], + createdByUserInvitationId: Option[String], + company: Option[String], + lastMarketingAgreementSignedDate: Option[Date]) : Box[ResourceUser] def createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) : Box[ResourceUser] @@ -85,7 +95,7 @@ class RemotedataUsersCaseClasses { case class getAllUsers() case class getAllUsersF(queryParams: List[OBPQueryParam]) case class getUsers(queryParams: List[OBPQueryParam]) - case class createResourceUser(provider: String, providerId: Option[String],createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String]) + case class createResourceUser(provider: String, providerId: Option[String],createdByConsentId: Option[String], name: Option[String], email: Option[String], userId: Option[String], createdByUserInvitationId: Option[String], company: Option[String], lastMarketingAgreementSignedDate: Option[Date]) case class createUnsavedResourceUser(provider: String, providerId: Option[String], name: Option[String], email: Option[String], userId: Option[String]) case class saveResourceUser(resourceUser: ResourceUser) case class deleteResourceUser(userId: Long) diff --git a/obp-api/src/test/scala/code/bankaccountcreation/BankAccountCreationListenerTest.scala b/obp-api/src/test/scala/code/bankaccountcreation/BankAccountCreationListenerTest.scala index 79aac35ef..580a02a46 100644 --- a/obp-api/src/test/scala/code/bankaccountcreation/BankAccountCreationListenerTest.scala +++ b/obp-api/src/test/scala/code/bankaccountcreation/BankAccountCreationListenerTest.scala @@ -38,7 +38,7 @@ class BankAccountCreationListenerTest extends ServerSetup with DefaultConnectorT //need to create the user for the bank accout creation process to work def getTestUser() = Users.users.vend.getUserByProviderId(userProvider, userId).getOrElse { - Users.users.vend.createResourceUser(userProvider, Some(userId), None, None, None, None, None, None).openOrThrowException(attemptedToOpenAnEmptyBox) + Users.users.vend.createResourceUser(userProvider, Some(userId), None, None, None, None, None, None, None).openOrThrowException(attemptedToOpenAnEmptyBox) } val expectedBankId = "quxbank" diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala index 8dceecd5e..048be111e 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala @@ -802,7 +802,16 @@ case class Transaction( val accountId = thisAccount.accountId } -case class UserCommons(userPrimaryKey : UserPrimaryKey, userId: String,idGivenByProvider: String, provider : String, emailAddress : String, name : String, createdByConsentId: Option[String] = None, createdByUserInvitationId: Option[String] = None, isDeleted: Option[Boolean] = None) extends User +case class UserCommons(userPrimaryKey : UserPrimaryKey, + userId: String, + idGivenByProvider: String, + provider : String, + emailAddress : String, + name : String, + createdByConsentId: Option[String] = None, + createdByUserInvitationId: Option[String] = None, + isDeleted: Option[Boolean] = None, + lastMarketingAgreementSignedDate: Option[Date] = None) extends User case class InternalBasicUser( userId:String, diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/UserModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/UserModel.scala index bf6a26021..4452e3b3d 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/UserModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/UserModel.scala @@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/) package com.openbankproject.commons.model +import java.util.Date + /** * An O-R mapped "User" class that includes first name, last name, password * @@ -66,6 +68,7 @@ trait User { def isOriginalUser = createdByConsentId.isEmpty def isConsentUser = createdByConsentId.nonEmpty def isDeleted: Option[Boolean] + def lastMarketingAgreementSignedDate: Option[Date] } case class UserPrimaryKey(val value : Long) { From ad4bfc125ca5432a5c3104c0245ae2770b6a2e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 16 Sep 2021 17:40:08 +0200 Subject: [PATCH 128/293] feature/Add last_marketing_agreement_signed_date to the users JSON --- .../code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 6 ++++-- .../src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 60e866dad..583196c6f 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1711,7 +1711,8 @@ object SwaggerDefinitionsJSON { entitlements = entitlementJSONs, views = None, agreements = None, - is_deleted = false + is_deleted = false, + last_marketing_agreement_signed_date = Some(DateWithDayExampleObject) ) val userJsonWithAgreementsV400 = UserJsonV400( user_id = ExampleValue.userIdExample.value, @@ -1722,7 +1723,8 @@ object SwaggerDefinitionsJSON { entitlements = entitlementJSONs, views = None, agreements = Some(Nil), - is_deleted = false + is_deleted = false, + last_marketing_agreement_signed_date = Some(DateWithDayExampleObject) ) val userIdJsonV400 = UserIdJsonV400( user_id = ExampleValue.userIdExample.value diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 05713e556..f855ba317 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -899,7 +899,8 @@ case class UserJsonV400( entitlements : EntitlementJSONs, views: Option[ViewsJSON300], agreements: Option[List[UserAgreementJson]], - is_deleted: Boolean + is_deleted: Boolean, + last_marketing_agreement_signed_date: Option[Date] ) case class UsersJsonV400(users: List[UserJsonV400]) @@ -917,7 +918,8 @@ object JSONFactory400 { agreements = agreements.map(_.map( i => UserAgreementJson(`type` = i.agreementType, text = i.agreementText)) ), - is_deleted = user.isDeleted.getOrElse(false) + is_deleted = user.isDeleted.getOrElse(false), + last_marketing_agreement_signed_date = user.lastMarketingAgreementSignedDate ) } From e65cd51d37fd0329b318f2456a81d8e265375173 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 17 Sep 2021 14:26:35 +0200 Subject: [PATCH 129/293] feature/added the new props webui_main_faq_external_link --- .../resources/props/sample.props.template | 5 + .../src/main/scala/code/snippet/WebUI.scala | 16 ++ obp-api/src/main/webapp/index.html | 161 +----------------- obp-api/src/main/webapp/mainFaq.html | 160 +++++++++++++++++ 4 files changed, 182 insertions(+), 160 deletions(-) create mode 100644 obp-api/src/main/webapp/mainFaq.html diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index c5fefe45c..039fc9e93 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -420,6 +420,11 @@ webui_sdks_url = https://github.com/OpenBankProject/OBP-API/wiki/OAuth-Client-SD # then OBP-API can show the content to the HomePage `SDK Showcases`. Please check it over the sandbox homepage first. #webui_featured_sdks_external_link = https://static.openbankproject.com/obp/sdks.html + +# the external html page for the FAQ section. the default link is the obp one. Please following the div to modify it. This link should be anonymous access. +# then OBP-API can show the content to the HomePage `FAQs`. Please check it over the sandbox homepage first. +#webui_main_faq_external_link = /mainFaq.html + # Text about data in FAQ webui_faq_data_text = We use real data and customer profiles which have been anonymized. diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index abcc9b833..165c526df 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -142,7 +142,23 @@ class WebUI extends MdcLoggable{ "#main-showcases *" #> scala.xml.Unparsed(sdksHtmlContent) } + val mainFaqHtmlLink = getWebUiPropsValue("webui_main_faq_external_link","") + + val mainFaqHtmlContent = try{ + if (mainFaqHtmlLink.isEmpty)//If the webui_featured_sdks_external_link is not set, we will read the internal sdks.html file instead. + LiftRules.getResource("/mainFaq.html").map{ url => + Source.fromURL(url, "UTF-8").mkString + }.openOrThrowException("Please check the content of this file: src/main/webapp/mainFaq.html") + else + Source.fromURL(sdksHtmlLink, "UTF-8").mkString + }catch { + case _ : Throwable => "

    SDK Showcases is wrong, please check the props `webui_featured_sdks_external_link`

    " + } + // webui_featured_sdks_external_link props, we can set the sdks here. check the `SDK Showcases` in Homepage, and you can see all the sdks. + def mainFaqHtml: CssSel = { + "#main-faq *" #> scala.xml.Unparsed(mainFaqHtmlContent) + } val brandString = activeBrand match { case Some(v) => s"&brand=$v" diff --git a/obp-api/src/main/webapp/index.html b/obp-api/src/main/webapp/index.html index f3c9fea12..dec65bd91 100644 --- a/obp-api/src/main/webapp/index.html +++ b/obp-api/src/main/webapp/index.html @@ -255,166 +255,7 @@ Berlin 13359, Germany -
    -

    FAQs

    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    - -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    +
    diff --git a/obp-api/src/main/webapp/mainFaq.html b/obp-api/src/main/webapp/mainFaq.html new file mode 100644 index 000000000..97737a6e1 --- /dev/null +++ b/obp-api/src/main/webapp/mainFaq.html @@ -0,0 +1,160 @@ +

    FAQs-xxxxx

    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    From b0ae1ca5c128647044968734ed82b50c802b9ed2 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 17 Sep 2021 14:33:37 +0200 Subject: [PATCH 130/293] docfix/added the webui_main_faq_external_link to release_notes.md --- release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release_notes.md b/release_notes.md index acf52bb2c..3919b7f94 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action +17/09/2021 e65cd51d Added props: webui_main_faq_external_link, default is obp static file: /mainFaq.html 09/09/2021 65952225 Added props: webui_support_email, default is contact@openbankproject.com 02/09/2021 a826d908 Renamed Web UI props: webui_post_user_invitation_privacy_conditions_value => webui_privacy_policy From 7ebb47b55093e3010bc827719411a3f777c8ff74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 20 Sep 2021 09:03:53 +0200 Subject: [PATCH 131/293] bugfix/Use subject instead of given_name for username --- obp-api/src/main/scala/code/api/openidconnect.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/openidconnect.scala b/obp-api/src/main/scala/code/api/openidconnect.scala index 6df50fdc2..a6ef5051a 100644 --- a/obp-api/src/main/scala/code/api/openidconnect.scala +++ b/obp-api/src/main/scala/code/api/openidconnect.scala @@ -182,7 +182,7 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { provider = issuer, providerId = subject, createdByConsentId = None, - name = getClaim(name = "given_name", idToken = idToken).orElse(subject), + name = subject, email = getClaim(name = "email", idToken = idToken), userId = None, createdByUserInvitationId = None, From 282b1af7ce452d7ee03f19f0f162e58dc4db536d Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 20 Sep 2021 11:51:21 +0200 Subject: [PATCH 132/293] factor/tweaked mainFaq.html -> main-faq.html --- obp-api/src/main/resources/props/sample.props.template | 2 +- obp-api/src/main/scala/code/snippet/WebUI.scala | 4 ++-- obp-api/src/main/webapp/{mainFaq.html => main-faq.html} | 2 +- release_notes.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename obp-api/src/main/webapp/{mainFaq.html => main-faq.html} (99%) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 039fc9e93..2cd0951af 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -423,7 +423,7 @@ webui_sdks_url = https://github.com/OpenBankProject/OBP-API/wiki/OAuth-Client-SD # the external html page for the FAQ section. the default link is the obp one. Please following the div to modify it. This link should be anonymous access. # then OBP-API can show the content to the HomePage `FAQs`. Please check it over the sandbox homepage first. -#webui_main_faq_external_link = /mainFaq.html +#webui_main_faq_external_link = /main-faq.html # Text about data in FAQ webui_faq_data_text = We use real data and customer profiles which have been anonymized. diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index 165c526df..df1722300 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -146,9 +146,9 @@ class WebUI extends MdcLoggable{ val mainFaqHtmlContent = try{ if (mainFaqHtmlLink.isEmpty)//If the webui_featured_sdks_external_link is not set, we will read the internal sdks.html file instead. - LiftRules.getResource("/mainFaq.html").map{ url => + LiftRules.getResource("/main-faq.html").map{ url => Source.fromURL(url, "UTF-8").mkString - }.openOrThrowException("Please check the content of this file: src/main/webapp/mainFaq.html") + }.openOrThrowException("Please check the content of this file: src/main/webapp/main-faq.html") else Source.fromURL(sdksHtmlLink, "UTF-8").mkString }catch { diff --git a/obp-api/src/main/webapp/mainFaq.html b/obp-api/src/main/webapp/main-faq.html similarity index 99% rename from obp-api/src/main/webapp/mainFaq.html rename to obp-api/src/main/webapp/main-faq.html index 97737a6e1..769160174 100644 --- a/obp-api/src/main/webapp/mainFaq.html +++ b/obp-api/src/main/webapp/main-faq.html @@ -1,4 +1,4 @@ -

    FAQs-xxxxx

    +

    FAQs

    diff --git a/release_notes.md b/release_notes.md index 3919b7f94..4159cc333 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,7 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action -17/09/2021 e65cd51d Added props: webui_main_faq_external_link, default is obp static file: /mainFaq.html +17/09/2021 e65cd51d Added props: webui_main_faq_external_link, default is obp static file: /main-faq.html 09/09/2021 65952225 Added props: webui_support_email, default is contact@openbankproject.com 02/09/2021 a826d908 Renamed Web UI props: webui_post_user_invitation_privacy_conditions_value => webui_privacy_policy From d2ab9652edf99289ba321d7dbcfaafc3f8ce6f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 20 Sep 2021 11:51:44 +0200 Subject: [PATCH 133/293] feature/Allow an email as a valid username --- obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 2bed203ff..121b96988 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -140,6 +140,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with MdcLoggable { } /** + * Username is a valid email address or the regex below: * Regex to validate a username * * ^(?=.{8,100}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(? String)(e: String) = e match { case null => List(FieldError(this, Text(msg))) case e if e.trim.isEmpty => List(FieldError(this, Text(msg))) + case e if emailRegex.findFirstMatchIn(e).isDefined => Nil // Email is valid username case e if usernameRegex.findFirstMatchIn(e).isDefined => Nil case _ => List(FieldError(this, Text(msg))) } From 85e205e9dfd2b46efcebae4b91c28d20826ec258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 21 Sep 2021 13:31:08 +0200 Subject: [PATCH 134/293] feature/Make OBP API return Bad Request on Duplicate Query Parameters or Header keys --- .../main/scala/code/api/util/APIUtil.scala | 42 +++++++++++++++++++ .../scala/code/api/util/ErrorMessages.scala | 2 + 2 files changed, 44 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index ee9975643..3f7dd48e8 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -3848,6 +3848,40 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } } } + /** + * validate whether current request's query parameters + * @param operationId + * @param callContext + * @return Full(errorResponse) if validate fail + */ + def validateQueryParams(operationId: String, callContext: CallContext): Box[JsonResponse] = { + val queryString: String = if (callContext.url.contains("?")) callContext.url.split("\\?",2)(1) else "" + val queryParams: Array[String] = queryString.split("&").map(_.split("=")(0)) + val queryParamsGrouped: Map[String, Array[String]] = queryParams.groupBy(x => x) + queryParamsGrouped.toList.forall(_._2.size == 1) match { + case true => Empty + case false => + Box.tryo( + createErrorJsonResponse(s"${ErrorMessages.DuplicatedQueryParameters}", 400, callContext.correlationId) + ) + } + } + /** + * validate whether current request's header keys + * @param operationId + * @param callContext + * @return Full(errorResponse) if validate fail + */ + def validateRequestHeadersKeys(operationId: String, callContext: CallContext): Box[JsonResponse] = { + val headerKeysGrouped: Map[String, List[HTTPParam]] = callContext.requestHeaders.groupBy(x => x.name) + headerKeysGrouped.toList.forall(_._2.size == 1) match { + case true => Empty + case false => + Box.tryo( + createErrorJsonResponse(s"${ErrorMessages.DuplicatedHeaderKeys}", 400, callContext.correlationId) + ) + } + } def createErrorJsonResponse(errorMsg: String, errorCode: Int, correlationId: String): JsonResponse = { import net.liftweb.json.JsonDSL._ @@ -3911,6 +3945,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ // validate auth type { case (Some(callContext), operationId) => validateAuthType(operationId, callContext) + }, + // validate query params + { + case (Some(callContext), operationId) => validateQueryParams(operationId, callContext) + }, + // validate request header keys + { + case (Some(callContext), operationId) => validateRequestHeadersKeys(operationId, callContext) } ) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 474afa523..33cc20776 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -58,6 +58,8 @@ object ErrorMessages { val InvalidRequestPayload = "OBP-09014: Incorrect request body Format, it should be a valid json that matches Validation rule." val DynamicDataNotFound = "OBP-09015: Dynamic Data not found. Please specify a valid value." + val DuplicatedQueryParameters = "OBP-09016: Duplicated Query Parameters are not allowed." + val DuplicatedHeaderKeys = "OBP-09017: Duplicated Header Keys are not allowed." // General messages (OBP-10XXX) From 9bc3af947435927f4d6984e3d539e6c83a460f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 22 Sep 2021 07:24:16 +0200 Subject: [PATCH 135/293] refactor/Tweak error messages Duplicated => Duplicate --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 4 ++-- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 3f7dd48e8..32ef1d00e 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -3862,7 +3862,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case true => Empty case false => Box.tryo( - createErrorJsonResponse(s"${ErrorMessages.DuplicatedQueryParameters}", 400, callContext.correlationId) + createErrorJsonResponse(s"${ErrorMessages.DuplicateQueryParameters}", 400, callContext.correlationId) ) } } @@ -3878,7 +3878,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case true => Empty case false => Box.tryo( - createErrorJsonResponse(s"${ErrorMessages.DuplicatedHeaderKeys}", 400, callContext.correlationId) + createErrorJsonResponse(s"${ErrorMessages.DuplicateHeaderKeys}", 400, callContext.correlationId) ) } } diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 33cc20776..aada7e286 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -58,8 +58,8 @@ object ErrorMessages { val InvalidRequestPayload = "OBP-09014: Incorrect request body Format, it should be a valid json that matches Validation rule." val DynamicDataNotFound = "OBP-09015: Dynamic Data not found. Please specify a valid value." - val DuplicatedQueryParameters = "OBP-09016: Duplicated Query Parameters are not allowed." - val DuplicatedHeaderKeys = "OBP-09017: Duplicated Header Keys are not allowed." + val DuplicateQueryParameters = "OBP-09016: Duplicate Query Parameters are not allowed." + val DuplicateHeaderKeys = "OBP-09017: Duplicate Header Keys are not allowed." // General messages (OBP-10XXX) From 09e44eba249954085cd5eba9ac3a31c785725da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 22 Sep 2021 09:34:48 +0200 Subject: [PATCH 136/293] refactor/User Invitation Page --- .../scala/code/snippet/UserInvitation.scala | 6 +- .../src/main/webapp/media/css/data-area.css | 151 ++++++++++++++++++ obp-api/src/main/webapp/media/css/website.css | 2 + obp-api/src/main/webapp/media/js/website.js | 7 + obp-api/src/main/webapp/user-invitation.html | 12 +- 5 files changed, 169 insertions(+), 9 deletions(-) create mode 100644 obp-api/src/main/webapp/media/css/data-area.css diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 5cd61f183..7ff0609e7 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -128,9 +128,9 @@ class UserInvitation extends MdcLoggable { } def showError(usernameError: String) = { - S.error("register-consumer-errors", usernameError) + S.error("data-area-errors", usernameError) register & - "#register-consumer-errors *" #> { + "#data-area-errors *" #> { ".error *" #> List(usernameError).map({ e => ".errorContent *" #> e @@ -170,7 +170,7 @@ class UserInvitation extends MdcLoggable { "#marketing_info_checkbox" #> SHtml.checkbox(marketingInfoCheckboxVar, marketingInfoCheckboxVar(_)) & "type=submit" #> SHtml.submit(s"$registrationConsumerButtonValue", () => submitButtonDefense) } & - "#register-consumer-success" #> "" + "#data-area-success" #> "" } userInvitation match { case Full(payload) if payload.status == "CREATED" => // All good diff --git a/obp-api/src/main/webapp/media/css/data-area.css b/obp-api/src/main/webapp/media/css/data-area.css new file mode 100644 index 000000000..a3cd199ca --- /dev/null +++ b/obp-api/src/main/webapp/media/css/data-area.css @@ -0,0 +1,151 @@ +#data-area { + background-color: #53C4EF; + padding: 20px 10px; + color: white; + margin: 30px 0 90px; +} + +#data-area #data-area-explanation, +#data-area form, +#data-area-errors, +#data-area-success { + max-width: 610px; + margin: 0 auto; + color: #333333; +} +#data-area-errors span{ + color: black; +} +#data-area h1 { + font-family: Roboto-Light; + font-size: 28px; + color: #333333; + letter-spacing: 0; + line-height: 36px; + text-align: left; + margin-bottom: 32px; + font-weight: normal; +} + +#data-area #data-area-explanation p:nth-child(2) { + font-family: Roboto-Light; + font-size: 22px; + color: #333333; + letter-spacing: 0; + line-height: 31px; + margin-bottom: 8px; + font-weight: normal; + text-align: left; +} + +#data-area #data-area-explanation p:last-child{ + margin-top: 8px; + font-family: Roboto-Regular; + font-size: 14px; + color: #333333; + letter-spacing: 0; + line-height: 20px; + margin-bottom: 32px; +} + +#data-area-input form label{ + margin-bottom: 8px; + margin-top: 17px; + font-family: Roboto-Regular; + font-size: 16px; + color: #333333; + line-height: 24px; +} + +#data-area-input form select{ + height: 44px; + border: 1px solid #767676; + -webkit-appearance: none; + -webkit-border-radius: 0px; +} + +#data-area #data-area-explanation { + margin-top: 32px; + margin-bottom: 20px; + color: #333333; + padding: 0 15px; +} + +#data-area textarea { + height: 96px; + border: 1px solid #767676; + border-radius: 0px; +} +#data-area #data-area-errors { + margin-bottom: 20px; +} +#data-area #data-area-success { + margin-top: 30px; +} + +#data-area #data-area-success h1 { + padding-left: 15px; +} + +#data-area #data-area-success #data-area-success-message{ + font-family: Roboto-Light; + font-size: 22px; + color: #333333; + letter-spacing: 0; + line-height: 31px; + padding-left: 15px; +} + + +#data-area #data-area-success p { + font-family: Roboto-Light; + font-size: 22px; + color: #333333; + letter-spacing: 0; + margin-bottom: 44px; + line-height: 31px; + padding-left: 15px; +} + +#data-area-success a{ + text-decoration:underline; +} + + +#data-area-success span, +#data-area-success a{ + font-family: Roboto-Regular; + font-size: 16px; + color: #333333; + line-height: 24px; +} +#data-area #data-area-success .row { + margin-bottom: 20px; +} +#data-area #data-area-success .row div:nth-child(1) { + font-family: Roboto-Medium; + font-size: 16px; + color: #333333; + line-height: 24px; +} +#data-area-input form .btn-danger{ + margin-left: 0; + margin-top: 33px; +} + +#data-area-input #data-area-errors-div{ + margin-top: 8px; +} + +#data-area-input #data-area-errors{ + font-family: Roboto-Regular; + font-size: 14px; + color: #333333; + line-height: 20px; + background-image: url(/media/images/icons/status_error_onlight.svg); + background-repeat:no-repeat; + background-position: left 12px; + background-size: 18px 15.70px; + padding-top: 8px; + padding-left: 26px; +} \ No newline at end of file diff --git a/obp-api/src/main/webapp/media/css/website.css b/obp-api/src/main/webapp/media/css/website.css index 0bd4ea9b1..c4a621bd8 100644 --- a/obp-api/src/main/webapp/media/css/website.css +++ b/obp-api/src/main/webapp/media/css/website.css @@ -8,6 +8,7 @@ @import url(/media/css/main-start.css); @import url(/media/css/authorise.css); @import url(/media/css/register-consumer.css); +@import url(/media/css/data-area.css); @import url(/media/css/signup.css); @import url(/media/css/recover-password.css); @import url(/media/css/main-showcases.css); @@ -284,6 +285,7 @@ header #header-decoration, #signup, #recover-password, #register-consumer, +#data-area , #create-account, .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus, diff --git a/obp-api/src/main/webapp/media/js/website.js b/obp-api/src/main/webapp/media/js/website.js index a740571c9..ac02198c5 100644 --- a/obp-api/src/main/webapp/media/js/website.js +++ b/obp-api/src/main/webapp/media/js/website.js @@ -340,6 +340,13 @@ $(document).ready(function() { } else{ consumerRegistrationAppRequestUriError.parent().addClass('hide'); } + + var dataAreaErrors = $('#data-area-input #data-area-errors'); + if (dataAreaErrors.length > 0 && dataAreaErrors.html().length > 0) { + dataAreaErrors.parent().removeClass('hide'); + } else{ + dataAreaErrors.parent().addClass('hide'); + } { var consumerRegistrationJwksError = $('#register-consumer-input #consumer-registration-app-signing_jwks-error'); diff --git a/obp-api/src/main/webapp/user-invitation.html b/obp-api/src/main/webapp/user-invitation.html index 29bd87f1d..1d8901434 100644 --- a/obp-api/src/main/webapp/user-invitation.html +++ b/obp-api/src/main/webapp/user-invitation.html @@ -23,11 +23,11 @@ Berlin 13359, Germany This product includes software developed at TESOBE (http://www.tesobe.com/) --> -
    +
    -
    -
    +
    +

    Complete your user invitation

    Please complete the information about the user invitation application below.

    All fields are required unless marked as 'optional'

    @@ -94,9 +94,9 @@ Berlin 13359, Germany
    - -
    - + +
    +
    From 071b28a633bc9629e200cbe86b6f62ad9cd9243e Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 15 Oct 2021 12:22:38 +0200 Subject: [PATCH 181/293] docfix/typo --- obp-api/src/main/scala/code/api/util/Glossary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 00a82de98..2bd3a303e 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2287,7 +2287,7 @@ object Glossary extends MdcLoggable { | |To enable Endpoint Mapping for your Dynamic Endpoints, either set the `host` in the swagger file to "dynamic_entity" upon creation of the Dynamic Endpoints - or update the host using the Update Dynamic Endpoint Host endpoints. | - |Once the `host` is thus set, you can the Endpoint Mapping endpoints to map the Dynamic Endpoint fields to Dynamic Entity data. + |Once the `host` is thus set, you can use the Endpoint Mapping endpoints to map the Dynamic Endpoint fields to Dynamic Entity data. | |See the [Create Endpoint Mapping](/index#OBPv4.0.0-createEndpointMapping) JSON body. You will need to know the operation_id in advance and you can prepare the request_mapping and response_mapping objects. You can get the operation ID from the API Explorer or Get Dynamic Endpoints endpoints. | From 3a95a6d6267e7c2e26b189554f92f3c73e099db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 18 Oct 2021 12:07:51 +0200 Subject: [PATCH 182/293] feature/Add link to the Hola app i.e. webui_api_hola_url props --- obp-api/src/main/resources/props/sample.props.template | 3 +++ obp-api/src/main/scala/code/snippet/WebUI.scala | 4 ++++ obp-api/src/main/webapp/index.html | 2 ++ 3 files changed, 9 insertions(+) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 816064d10..c88d5ffa0 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -387,6 +387,9 @@ webui_obp_cli_url = https://github.com/OpenBankProject/OBP-CLI # API Tester URL, change to your instance webui_api_tester_url = https://apitester.openbankproject.com +# API Hola app URL, change to your instance +webui_api_hola_url = # + diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index d225a9a3d..a3581422d 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -193,6 +193,10 @@ class WebUI extends MdcLoggable{ def apiTesterLink: CssSel = { ".api-tester-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_api_tester_url", "")) } + // Link to Hola app + def apiHolaLink: CssSel = { + ".api-hola-link a [href]" #> scala.xml.Unparsed(getWebUiPropsValue("webui_api_hola_url", "#")) + } // Link to API def apiLink: CssSel = { diff --git a/obp-api/src/main/webapp/index.html b/obp-api/src/main/webapp/index.html index dec65bd91..4a5944c90 100644 --- a/obp-api/src/main/webapp/index.html +++ b/obp-api/src/main/webapp/index.html @@ -325,6 +325,8 @@ Berlin 13359, Germany href="">OBP CLI API Tester + Hola
    From c32e8c26084b304fc871ac9444ebe406c1e3ff93 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 18 Oct 2021 13:04:23 +0200 Subject: [PATCH 183/293] feature/added the sort_direction parameter and ORDER BY accountId for fastFirehoseAccounts --- .../main/scala/code/api/v4_0_0/APIMethods400.scala | 11 ++--------- .../code/bankconnectors/LocalMappedConnector.scala | 10 ++++++++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index f28c9fe16..ef83826cc 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -3327,14 +3327,7 @@ trait APIMethods400 { |This endpoint allows bulk access to accounts. | |optional pagination parameters for filter with accounts - |${urlParametersDocument(true, false) - .replace(s""" - | - |* sort_direction=ASC/DESC ==> default value: DESC. - | - |eg2:?limit=100&offset=0&sort_direction=ASC - | - |""". stripMargin,"")} + |${urlParametersDocument(true, false)} | |${authenticationRequiredMessage(true)} | @@ -3355,7 +3348,7 @@ trait APIMethods400 { _ <- Helper.booleanToFuture(failMsg = AccountFirehoseNotAllowedOnThisInstance, cc=cc.callContext) { allowAccountFirehose } - allowedParams = List("limit", "offset") + allowedParams = List("limit", "offset", "sort_direction") httpParams <- NewStyle.function.extractHttpParamsFromUrl(cc.url) obpQueryParams <- NewStyle.function.createObpParams(httpParams, allowedParams, callContext) (firehoseAccounts, callContext) <- NewStyle.function.getBankAccountsWithAttributes(bankId, obpQueryParams, cc.callContext) diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index cf25e3a6a..32d945ecd 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -832,14 +832,20 @@ object LocalMappedConnector extends Connector with MdcLoggable { override def getBankAccountsWithAttributes(bankId: BankId, queryParams: List[OBPQueryParam], callContext: Option[CallContext]): OBPReturnType[Box[List[FastFirehoseAccount]]] = Future{ - val limit = queryParams.collect { case OBPLimit(value) => value }.headOption.getOrElse(1000) + val limit = queryParams.collect { case OBPLimit(value) => value }.headOption.getOrElse(50) val offset = queryParams.collect { case OBPOffset(value) => value }.headOption.getOrElse(0) + val orderBy = queryParams.collect { + case OBPOrdering(_, OBPDescending) => "DESC" + }.headOption.getOrElse("ASC") + + val ordering = if (orderBy =="DESC" ) sqls"DESC" else sqls"ASC" val firehoseAccounts = { scalikeDB readOnly { implicit session => - val sqlResult =sql""" + val sqlResult = sql""" select * from v_fast_firehose_accounts WHERE v_fast_firehose_accounts.bank_id = ${bankId.value} + ORDER BY v_fast_firehose_accounts.account_id $ordering LIMIT $limit OFFSET $offset """.stripMargin From 80ec3716ed2ad084b7e9c888d14e8d8e49aa043c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 19 Oct 2021 07:39:07 +0200 Subject: [PATCH 184/293] feature/3rd party developer consents to collecting personal data 2 --- obp-api/src/main/resources/props/sample.props.template | 4 ++-- obp-api/src/main/scala/code/snippet/UserInvitation.scala | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index c88d5ffa0..8ea3dc84f 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -1083,5 +1083,5 @@ webui_developer_user_invitation_email_html_text=\ \ -# List of cotries where consent to collecting personal data is not mandatory -consent_to_collecting_personal_data_list = Austria, Belgium, Bulgaria, Croatia, Republic of Cyprus, Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden \ No newline at end of file +# List of countries where consent is not required for the collection of personal data +personal_data_collection_consent_country_waiver_list = Austria, Belgium, Bulgaria, Croatia, Republic of Cyprus, Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, England, Scotland, Wales, Northern Ireland \ No newline at end of file diff --git a/obp-api/src/main/scala/code/snippet/UserInvitation.scala b/obp-api/src/main/scala/code/snippet/UserInvitation.scala index 1d8d018ad..5f393d155 100644 --- a/obp-api/src/main/scala/code/snippet/UserInvitation.scala +++ b/obp-api/src/main/scala/code/snippet/UserInvitation.scala @@ -64,7 +64,7 @@ class UserInvitation extends MdcLoggable { val privacyConditionsValue: String = getWebUiPropsValue("webui_privacy_policy", "") val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "") val termsAndConditionsCheckboxValue: String = getWebUiPropsValue("webui_post_user_invitation_terms_and_conditions_checkbox_value", "I agree to the above Developer Terms and Conditions") - val consentExclusionList = getWebUiPropsValue("consent_to_collecting_personal_data_list", "").split(",").toList.map(_.trim) + val personalDataCollectionConsentCountryWaiverList = getWebUiPropsValue("personal_data_collection_consent_country_waiver_list", "").split(",").toList.map(_.trim) def registerForm: CssSel = { @@ -80,7 +80,7 @@ class UserInvitation extends MdcLoggable { countryVar.set(userInvitation.map(_.country).getOrElse("None")) // Propose the username only for the first time. In case an end user manually change it we must not override it. if(usernameVar.isEmpty) usernameVar.set(firstNameVar.is.toLowerCase + "." + lastNameVar.is.toLowerCase()) - if(consentExclusionList.exists(_.toLowerCase == countryVar.is.toLowerCase) == true) { + if(personalDataCollectionConsentCountryWaiverList.exists(_.toLowerCase == countryVar.is.toLowerCase) == true) { consentForCollectingMandatoryCheckboxVar.set(false) } else { consentForCollectingMandatoryCheckboxVar.set(true) @@ -100,7 +100,7 @@ class UserInvitation extends MdcLoggable { else if(Users.users.vend.getUserByUserName(usernameVar.is).isDefined) showErrorsForUsername() else if(privacyCheckboxVar.is == false) showErrorsForPrivacyConditions() else if(termsCheckboxVar.is == false) showErrorsForTermsAndConditions() - else if(consentExclusionList.exists(_.toLowerCase == countryVar.is.toLowerCase) == false && consentForCollectingCheckboxVar.is == false) showErrorsForConsentForCollectingPersonalData() + else if(personalDataCollectionConsentCountryWaiverList.exists(_.toLowerCase == countryVar.is.toLowerCase) == false && consentForCollectingCheckboxVar.is == false) showErrorsForConsentForCollectingPersonalData() else { // Resource User table createResourceUser( From 591a4e768cb966cdb5bcce0f72ad0b14e6c63d90 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 19 Oct 2021 13:19:19 +0200 Subject: [PATCH 185/293] feature/added the addFastFirehoseAccountsMaterializedView --- .../code/api/util/migration/Migration.scala | 13 +++ ...rationOfFastFireHoseMaterializedView.scala | 104 ++++++++++++++++++ .../bankconnectors/LocalMappedConnector.scala | 6 +- 3 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 0e8d582b2..f2d37d31b 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -86,6 +86,7 @@ object Migration extends MdcLoggable { alterColumnEmailAtResourceUser(startedBeforeSchemifier) alterColumnNameAtProductFee(startedBeforeSchemifier) addFastFirehoseAccountsView(startedBeforeSchemifier) + addFastFirehoseAccountsMaterializedView(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -308,6 +309,18 @@ object Migration extends MdcLoggable { } } + private def addFastFirehoseAccountsMaterializedView(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.addfastFirehoseAccountsMaterializedView(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(addFastFirehoseAccountsMaterializedView(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfFastFireHoseMaterializedView.addFastFireHoseMaterializedView(name) + } + } + } + } /** diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala new file mode 100644 index 000000000..9ee9fb6cc --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala @@ -0,0 +1,104 @@ +package code.api.util.migration + +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.productfee.ProductFee +import net.liftweb.mapper.{DB, Schemifier} +import net.liftweb.util.DefaultConnectionIdentifier + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} + +object MigrationOfFastFireHoseMaterializedView { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def addFastFireHoseMaterializedView(name: String): Boolean = { + DbFunction.tableExists(ProductFee, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val executedSql = + DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { + () => + """ + |CREATE MATERIALIZED VIEW mv_fast_firehose_accounts AS select + | mappedbankaccount.theaccountid as account_id, + | mappedbankaccount.bank as bank_id, + | mappedbankaccount.accountlabel as account_label, + | mappedbankaccount.accountnumber as account_number, + | (select + | string_agg( + | 'user_id:' + | || resourceuser.userid_ + | ||',provider:' + | ||resourceuser.provider_ + | ||',user_name:' + | ||resourceuser.name_, + | ',') as owners + | from resourceuser + | where + | resourceuser.id = mapperaccountholders.user_c + | ), + | mappedbankaccount.kind as kind, + | mappedbankaccount.accountcurrency as account_currency , + | mappedbankaccount.accountbalance as account_balance, + | (select + | string_agg( + | 'bank_id:' + | ||bankaccountrouting.bankid + | ||',account_id:' + | ||bankaccountrouting.accountid, + | ',' + | ) as account_routings + | from bankaccountrouting + | where + | bankaccountrouting.accountid = mappedbankaccount.theaccountid + | ), + | (select + | string_agg( + | 'type:' + | || mappedaccountattribute.mtype + | ||',code:' + | ||mappedaccountattribute.mcode + | ||',value:' + | ||mappedaccountattribute.mvalue, + | ',') as account_attributes + | from mappedaccountattribute + | where + | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid + | ) + |from mappedbankaccount + | LEFT JOIN mapperaccountholders + | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); + |CREATE INDEX account_id ON mv_fast_firehose_accounts(account_id); + |CREATE INDEX bank_id ON mv_fast_firehose_accounts(bank_id); + |""".stripMargin + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Executed SQL: + |$executedSql + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${ProductFee._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } + +} \ No newline at end of file diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 32d945ecd..a3721b72f 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -843,9 +843,9 @@ object LocalMappedConnector extends Connector with MdcLoggable { val firehoseAccounts = { scalikeDB readOnly { implicit session => val sqlResult = sql""" - select * from v_fast_firehose_accounts - WHERE v_fast_firehose_accounts.bank_id = ${bankId.value} - ORDER BY v_fast_firehose_accounts.account_id $ordering + select * from mv_fast_firehose_accounts + WHERE mv_fast_firehose_accounts.bank_id = ${bankId.value} + ORDER BY mv_fast_firehose_accounts.account_id $ordering LIMIT $limit OFFSET $offset """.stripMargin From 1b9521b2a3f491ecb0de00f9e54085b6b4ddfb65 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 19 Oct 2021 14:29:45 +0200 Subject: [PATCH 186/293] test/fixed the failed test --- ...rationOfFastFireHoseMaterializedView.scala | 165 ++++++++++++------ 1 file changed, 111 insertions(+), 54 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala index 9ee9fb6cc..8cfa8adf1 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala @@ -3,6 +3,7 @@ package code.api.util.migration import code.api.util.APIUtil import code.api.util.migration.Migration.{DbFunction, saveLog} import code.productfee.ProductFee +import net.liftweb.common.Full import net.liftweb.mapper.{DB, Schemifier} import net.liftweb.util.DefaultConnectionIdentifier @@ -24,60 +25,116 @@ object MigrationOfFastFireHoseMaterializedView { val executedSql = DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { - () => - """ - |CREATE MATERIALIZED VIEW mv_fast_firehose_accounts AS select - | mappedbankaccount.theaccountid as account_id, - | mappedbankaccount.bank as bank_id, - | mappedbankaccount.accountlabel as account_label, - | mappedbankaccount.accountnumber as account_number, - | (select - | string_agg( - | 'user_id:' - | || resourceuser.userid_ - | ||',provider:' - | ||resourceuser.provider_ - | ||',user_name:' - | ||resourceuser.name_, - | ',') as owners - | from resourceuser - | where - | resourceuser.id = mapperaccountholders.user_c - | ), - | mappedbankaccount.kind as kind, - | mappedbankaccount.accountcurrency as account_currency , - | mappedbankaccount.accountbalance as account_balance, - | (select - | string_agg( - | 'bank_id:' - | ||bankaccountrouting.bankid - | ||',account_id:' - | ||bankaccountrouting.accountid, - | ',' - | ) as account_routings - | from bankaccountrouting - | where - | bankaccountrouting.accountid = mappedbankaccount.theaccountid - | ), - | (select - | string_agg( - | 'type:' - | || mappedaccountattribute.mtype - | ||',code:' - | ||mappedaccountattribute.mcode - | ||',value:' - | ||mappedaccountattribute.mvalue, - | ',') as account_attributes - | from mappedaccountattribute - | where - | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid - | ) - |from mappedbankaccount - | LEFT JOIN mapperaccountholders - | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); - |CREATE INDEX account_id ON mv_fast_firehose_accounts(account_id); - |CREATE INDEX bank_id ON mv_fast_firehose_accounts(bank_id); - |""".stripMargin + APIUtil.getPropsValue("db.driver") openOr("org.h2.Driver") match { + case value if value.contains("org.h2.Driver") => + () => //Note: H2 database, do not support the MATERIALIZED view + """ + |CREATE VIEW mv_fast_firehose_accounts AS select + | mappedbankaccount.theaccountid as account_id, + | mappedbankaccount.bank as bank_id, + | mappedbankaccount.accountlabel as account_label, + | mappedbankaccount.accountnumber as account_number, + | (select + | string_agg( + | 'user_id:' + | || resourceuser.userid_ + | ||',provider:' + | ||resourceuser.provider_ + | ||',user_name:' + | ||resourceuser.name_, + | ',') as owners + | from resourceuser + | where + | resourceuser.id = mapperaccountholders.user_c + | ), + | mappedbankaccount.kind as kind, + | mappedbankaccount.accountcurrency as account_currency , + | mappedbankaccount.accountbalance as account_balance, + | (select + | string_agg( + | 'bank_id:' + | ||bankaccountrouting.bankid + | ||',account_id:' + | ||bankaccountrouting.accountid, + | ',' + | ) as account_routings + | from bankaccountrouting + | where + | bankaccountrouting.accountid = mappedbankaccount.theaccountid + | ), + | (select + | string_agg( + | 'type:' + | || mappedaccountattribute.mtype + | ||',code:' + | ||mappedaccountattribute.mcode + | ||',value:' + | ||mappedaccountattribute.mvalue, + | ',') as account_attributes + | from mappedaccountattribute + | where + | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid + | ) + |from mappedbankaccount + | LEFT JOIN mapperaccountholders + | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); + |""".stripMargin + case _ => + () => + """ + |CREATE MATERIALIZED VIEW mv_fast_firehose_accounts AS select + | mappedbankaccount.theaccountid as account_id, + | mappedbankaccount.bank as bank_id, + | mappedbankaccount.accountlabel as account_label, + | mappedbankaccount.accountnumber as account_number, + | (select + | string_agg( + | 'user_id:' + | || resourceuser.userid_ + | ||',provider:' + | ||resourceuser.provider_ + | ||',user_name:' + | ||resourceuser.name_, + | ',') as owners + | from resourceuser + | where + | resourceuser.id = mapperaccountholders.user_c + | ), + | mappedbankaccount.kind as kind, + | mappedbankaccount.accountcurrency as account_currency , + | mappedbankaccount.accountbalance as account_balance, + | (select + | string_agg( + | 'bank_id:' + | ||bankaccountrouting.bankid + | ||',account_id:' + | ||bankaccountrouting.accountid, + | ',' + | ) as account_routings + | from bankaccountrouting + | where + | bankaccountrouting.accountid = mappedbankaccount.theaccountid + | ), + | (select + | string_agg( + | 'type:' + | || mappedaccountattribute.mtype + | ||',code:' + | ||mappedaccountattribute.mcode + | ||',value:' + | ||mappedaccountattribute.mvalue, + | ',') as account_attributes + | from mappedaccountattribute + | where + | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid + | ) + |from mappedbankaccount + | LEFT JOIN mapperaccountholders + | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); + |CREATE INDEX account_id ON mv_fast_firehose_accounts(account_id); + |CREATE INDEX bank_id ON mv_fast_firehose_accounts(bank_id); + |""".stripMargin + } } val endDate = System.currentTimeMillis() From f270ff56997e7d14c25c6203bc21eee50de93a8d Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 20 Oct 2021 10:00:17 +0200 Subject: [PATCH 187/293] refactor/removed the duplicate migration code --- ...rationOfFastFireHoseMaterializedView.scala | 159 ++++++------------ 1 file changed, 53 insertions(+), 106 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala index 8cfa8adf1..8184288b7 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfFastFireHoseMaterializedView.scala @@ -23,117 +23,64 @@ object MigrationOfFastFireHoseMaterializedView { val commitId: String = APIUtil.gitCommit var isSuccessful = false + def migrationSql(isMaterializedView:Boolean) =s""" + |CREATE ${if(isMaterializedView) "MATERIALIZED" else ""} VIEW mv_fast_firehose_accounts AS select + | mappedbankaccount.theaccountid as account_id, + | mappedbankaccount.bank as bank_id, + | mappedbankaccount.accountlabel as account_label, + | mappedbankaccount.accountnumber as account_number, + | (select + | string_agg( + | 'user_id:' + | || resourceuser.userid_ + | ||',provider:' + | ||resourceuser.provider_ + | ||',user_name:' + | ||resourceuser.name_, + | ',') as owners + | from resourceuser + | where + | resourceuser.id = mapperaccountholders.user_c + | ), + | mappedbankaccount.kind as kind, + | mappedbankaccount.accountcurrency as account_currency , + | mappedbankaccount.accountbalance as account_balance, + | (select + | string_agg( + | 'bank_id:' + | ||bankaccountrouting.bankid + | ||',account_id:' + | ||bankaccountrouting.accountid, + | ',' + | ) as account_routings + | from bankaccountrouting + | where + | bankaccountrouting.accountid = mappedbankaccount.theaccountid + | ), + | (select + | string_agg( + | 'type:' + | || mappedaccountattribute.mtype + | ||',code:' + | ||mappedaccountattribute.mcode + | ||',value:' + | ||mappedaccountattribute.mvalue, + | ',') as account_attributes + | from mappedaccountattribute + | where + | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid + | ) + |from mappedbankaccount + | LEFT JOIN mapperaccountholders + | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); + |""".stripMargin val executedSql = DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { APIUtil.getPropsValue("db.driver") openOr("org.h2.Driver") match { case value if value.contains("org.h2.Driver") => - () => //Note: H2 database, do not support the MATERIALIZED view - """ - |CREATE VIEW mv_fast_firehose_accounts AS select - | mappedbankaccount.theaccountid as account_id, - | mappedbankaccount.bank as bank_id, - | mappedbankaccount.accountlabel as account_label, - | mappedbankaccount.accountnumber as account_number, - | (select - | string_agg( - | 'user_id:' - | || resourceuser.userid_ - | ||',provider:' - | ||resourceuser.provider_ - | ||',user_name:' - | ||resourceuser.name_, - | ',') as owners - | from resourceuser - | where - | resourceuser.id = mapperaccountholders.user_c - | ), - | mappedbankaccount.kind as kind, - | mappedbankaccount.accountcurrency as account_currency , - | mappedbankaccount.accountbalance as account_balance, - | (select - | string_agg( - | 'bank_id:' - | ||bankaccountrouting.bankid - | ||',account_id:' - | ||bankaccountrouting.accountid, - | ',' - | ) as account_routings - | from bankaccountrouting - | where - | bankaccountrouting.accountid = mappedbankaccount.theaccountid - | ), - | (select - | string_agg( - | 'type:' - | || mappedaccountattribute.mtype - | ||',code:' - | ||mappedaccountattribute.mcode - | ||',value:' - | ||mappedaccountattribute.mvalue, - | ',') as account_attributes - | from mappedaccountattribute - | where - | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid - | ) - |from mappedbankaccount - | LEFT JOIN mapperaccountholders - | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); - |""".stripMargin + () => migrationSql(false)//Note: H2 database, do not support the MATERIALIZED view case _ => - () => - """ - |CREATE MATERIALIZED VIEW mv_fast_firehose_accounts AS select - | mappedbankaccount.theaccountid as account_id, - | mappedbankaccount.bank as bank_id, - | mappedbankaccount.accountlabel as account_label, - | mappedbankaccount.accountnumber as account_number, - | (select - | string_agg( - | 'user_id:' - | || resourceuser.userid_ - | ||',provider:' - | ||resourceuser.provider_ - | ||',user_name:' - | ||resourceuser.name_, - | ',') as owners - | from resourceuser - | where - | resourceuser.id = mapperaccountholders.user_c - | ), - | mappedbankaccount.kind as kind, - | mappedbankaccount.accountcurrency as account_currency , - | mappedbankaccount.accountbalance as account_balance, - | (select - | string_agg( - | 'bank_id:' - | ||bankaccountrouting.bankid - | ||',account_id:' - | ||bankaccountrouting.accountid, - | ',' - | ) as account_routings - | from bankaccountrouting - | where - | bankaccountrouting.accountid = mappedbankaccount.theaccountid - | ), - | (select - | string_agg( - | 'type:' - | || mappedaccountattribute.mtype - | ||',code:' - | ||mappedaccountattribute.mcode - | ||',value:' - | ||mappedaccountattribute.mvalue, - | ',') as account_attributes - | from mappedaccountattribute - | where - | mappedaccountattribute.maccountid = mappedbankaccount.theaccountid - | ) - |from mappedbankaccount - | LEFT JOIN mapperaccountholders - | ON (mappedbankaccount.bank = mapperaccountholders.accountbankpermalink and mappedbankaccount.theaccountid = mapperaccountholders.accountpermalink); - |CREATE INDEX account_id ON mv_fast_firehose_accounts(account_id); - |CREATE INDEX bank_id ON mv_fast_firehose_accounts(bank_id); - |""".stripMargin + () => migrationSql(true) } } From 8e4dabaf924f61b38db2386f6ee83427761091cf Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 20 Oct 2021 11:01:04 +0200 Subject: [PATCH 188/293] refactor/remove the role error message CreateUserAuthContextError --- obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 2fa88b736..a33571670 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1450,7 +1450,6 @@ trait APIMethods310 { List( UserNotLoggedIn, UserHasMissingRoles, - CreateUserAuthContextError, UnknownError ), List(apiTagUser, apiTagNewStyle), From fb6d8d8be568103f05f6a67f07bae59e2a25d273 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 21 Oct 2021 13:36:48 +0200 Subject: [PATCH 189/293] docfix/tweaked the dynamic entity and endpoint glossary --- obp-api/src/main/scala/code/api/util/Glossary.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 2bd3a303e..7a6ea4f12 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2188,7 +2188,7 @@ object Glossary extends MdcLoggable { glossaryItems += GlossaryItem( - title = "Dynamic Entity", + title = "Dynamic Entity Manage", description = s""" | @@ -2239,7 +2239,7 @@ object Glossary extends MdcLoggable { """.stripMargin) glossaryItems += GlossaryItem( - title = "Dynamic Endpoint", + title = "Dynamic Endpoint Manage", description = s""" | From 170726f6c5f01c4a8e149b9df68289a7bcd5bf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 21 Oct 2021 14:50:02 +0200 Subject: [PATCH 190/293] feature/Add props: openid_connect.response_type, openid_connect.scope and openid_connect.response_mode --- .../resources/props/sample.props.template | 11 ++- .../code/snippet/OpenidConnectInvoke.scala | 71 +++++++++++++++---- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 8ea3dc84f..dba483529 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -628,6 +628,15 @@ super_admin_user_ids=USER_ID1,USER_ID2, ## registered on OBP localy. # openid_connect.enabled=true # openid_connect.show_tokens=false +# Response mode +# possible values: query, fragment, form_post, query.jwt, fragment.jwt, form_post.jwt, jwt +# openid_connect.response_mode=form_post +# Response type +# possible values: "code", "id_token", "code id_token" +# openid_connect.response_type=code +# Scope +# possible values: "openid email profile", "openid email", "openid" +# openid_connect.scope=openid email profile # First identity provider # openid_connect_1.button_text = Google # openid_connect_1.client_secret=OYdWujJlU7fFOW_NXzPlDI4T @@ -642,7 +651,7 @@ super_admin_user_ids=USER_ID1,USER_ID2, # openid_connect_2.button_text = name of 2nd provider # openid_connect_2.client_secret=OYdWujJlU7fFOW_NXzPlDI4T # openid_connect_2.client_id=883773244832-s4hi72j0rble0iiivq1gn09k7vvptdci.apps.googleusercontent.com -# openid_connect_2.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback +# openid_connect_2.callback_url=http://127.0.0.1:8080/auth/openid-connect/callback-2 # openid_connect_2.endpoint.authorization=https://accounts.google.com/o/oauth2/v2/auth # openid_connect_2.endpoint.userinfo=https://openidconnect.googleapis.com/v1/userinfo # openid_connect_2.endpoint.token=https://oauth2.googleapis.com/token diff --git a/obp-api/src/main/scala/code/snippet/OpenidConnectInvoke.scala b/obp-api/src/main/scala/code/snippet/OpenidConnectInvoke.scala index 9429a8088..cd08a06ef 100644 --- a/obp-api/src/main/scala/code/snippet/OpenidConnectInvoke.scala +++ b/obp-api/src/main/scala/code/snippet/OpenidConnectInvoke.scala @@ -3,9 +3,12 @@ package code.snippet import java.net.URI import code.api.OpenIdConnectConfig +import code.api.util.APIUtil +import com.nimbusds.jwt.JWT import com.nimbusds.oauth2.sdk.id.{ClientID, State} -import com.nimbusds.oauth2.sdk.{ResponseType, Scope} -import com.nimbusds.openid.connect.sdk.{AuthenticationRequest, Nonce} +import com.nimbusds.oauth2.sdk.pkce.{CodeChallenge, CodeChallengeMethod} +import com.nimbusds.oauth2.sdk.{ResponseMode, ResponseType, Scope} +import com.nimbusds.openid.connect.sdk.{AuthenticationRequest, Display, Nonce, OIDCClaimsRequest, OIDCScopeValue, Prompt} import net.liftweb.common.{Box, Empty, Full, Loggable} import net.liftweb.http.js.{JsCmd, JsCmds} import net.liftweb.http.{S, SHtml, SessionVar} @@ -36,17 +39,61 @@ object OpenidConnectInvoke extends Loggable { // Generate nonce val nonce = new Nonce() + val responseMode = APIUtil.getPropsValue("openid_connect.response_mode", "form_post") match { + case "query" => ResponseMode.QUERY + case "fragment" => ResponseMode.FRAGMENT + case "form_post" => ResponseMode.FORM_POST + case "query.jwt" => ResponseMode.QUERY_JWT + case "fragment.jwt" => ResponseMode.FRAGMENT_JWT + case "form_post.jwt" => ResponseMode.FORM_POST_JWT + case "jwt" => ResponseMode.JWT + case _ => ResponseMode.FORM_POST + } + val responseType = APIUtil.getPropsValue("openid_connect.response_type", "code") match { + case "code" => new ResponseType("code") + case "id_token" => new ResponseType("id_token") + case "code id_token" => new ResponseType("code", "id_token") + case _ => new ResponseType("code") + } + val scope = APIUtil.getPropsValue("openid_connect.scope", "openid email profile") match { + case "openid email profile" => + val scope: Scope = new Scope(); + scope.add(OIDCScopeValue.OPENID); + scope.add(OIDCScopeValue.EMAIL); + scope.add(OIDCScopeValue.PROFILE); + scope + case "openid email" => + val scope: Scope = new Scope(); + scope.add(OIDCScopeValue.OPENID); + scope.add(OIDCScopeValue.EMAIL); + scope + case "openid" => + val scope: Scope = new Scope(); + scope.add(OIDCScopeValue.OPENID); + scope + case _ => + val scope: Scope = new Scope(); + scope.add(OIDCScopeValue.OPENID); + scope.add(OIDCScopeValue.EMAIL); + scope.add(OIDCScopeValue.PROFILE); + scope + } + // Compose the request (in code flow) - val req = - new AuthenticationRequest( - new URI(OpenIdConnectConfig.get(identityProvider).authorization_endpoint), - new ResponseType("code"), - Scope.parse("openid email profile"), - clientID, - callback, - state, - nonce - ) + val req = new AuthenticationRequest( + new URI(OpenIdConnectConfig.get(identityProvider).authorization_endpoint), + responseType, + responseMode, + scope, + clientID, + callback, + state, + nonce, + null, null, -1, null, null, + null, null, null, null.asInstanceOf[OIDCClaimsRequest], null, + null, null, + null, null, + null, false, null) OpenIDConnectSessionState.set(Full(state)) val accessType = if (OpenIdConnectConfig.get(identityProvider).access_type_offline) "&access_type=offline" else "" val redirectTo = req.toHTTPRequest.getURL() + "?" + req.toHTTPRequest.getQuery() + accessType From 4bb320e0a92aef333b042913d46c29b48fea803c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 25 Oct 2021 13:15:13 +0200 Subject: [PATCH 191/293] feature/Improve modul RSAUtil --- .../main/scala/code/api/util/RSAUtil.scala | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index e8baabb9d..f2c2b55ed 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -2,7 +2,9 @@ package code.api.util import code.api.util.CertificateUtil.{privateKey, publicKey} import code.util.Helper.MdcLoggable +import com.nimbusds.jose.{JWSAlgorithm, JWSHeader, JWSObject, Payload} import javax.crypto.Cipher +import net.liftweb.util.SecurityHelpers object RSAUtil extends MdcLoggable { @@ -16,20 +18,59 @@ object RSAUtil extends MdcLoggable { Base64.encodeBase64String(res) } def decrypt(encrypted: String): String = { - import org.apache.commons.codec.binary.Base64 import javax.crypto.Cipher + import org.apache.commons.codec.binary.Base64 val bytes = Base64.decodeBase64(encrypted) val cipher = Cipher.getInstance(cryptoSystem) cipher.init(Cipher.DECRYPT_MODE, privateKey) new String(cipher.doFinal(bytes), "utf-8") } + def computeHash(input: String): String = SecurityHelpers.hash256(input) + def computeHexHash(input: String): String = { + SecurityHelpers.hexDigest256(input.getBytes("UTF-8")) + } + + def signWithRsa256(payload: String): String = { + // Prepare JWS object with simple string as payload + val jwsObject = new JWSObject( + new JWSHeader.Builder(JWSAlgorithm.RS256).build, + new Payload(payload) + ) + // Compute the RSA signature + jwsObject.sign(CertificateUtil.rsaSigner) + + // To serialize to compact form, produces something like + // eyJhbGciOiJSUzI1NiJ9.SW4gUlNBIHdlIHRydXN0IQ.IRMQENi4nJyp4er2L + // mZq3ivwoAjqa1uUkSBKFIX7ATndFF5ivnt-m8uApHO4kfIFOrW7w2Ezmlg3Qd + // maXlS9DhN0nUk_hGI3amEjkKd0BWYCB8vfUbUv0XGjQip78AI4z1PrFRNidm7 + // -jPDm5Iq0SZnjKjCNS5Q15fokXZc8u0A + val s = jwsObject.serialize + s + } + + def computeXSign(input: String) = { + logger.debug("Input: " + input) + logger.debug("Hash: " + computeHash(input)) + logger.debug("HEX hash: " + computeHexHash(input)) + // Compute JWS token + val jws = signWithRsa256(computeHexHash(input)) + logger.debug("RSA 256 signature: " + jws) + // Get the last i.e. 3rd part of JWS token + val xSign = jws.split('.').toList.last + logger.debug("x-sign: " + xSign) + xSign + } + def main(args: Array[String]): Unit = { val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=f" val res = encrypt(db) println("db.url: " + db) println("encrypt: " + res) println("decrypt: " + decrypt(res)) + + val inputMessage = """hello world\n""" + computeXSign(inputMessage) } } From b6389d1a44fc15ad37e7382e8d8ccb2592cacb92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 25 Oct 2021 19:25:39 +0200 Subject: [PATCH 192/293] feature/Improve modul RSAUtil 2 --- .../main/scala/code/api/util/RSAUtil.scala | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index f2c2b55ed..add1edc25 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -1,7 +1,11 @@ package code.api.util +import java.nio.file.{Files, Paths} + import code.api.util.CertificateUtil.{privateKey, publicKey} import code.util.Helper.MdcLoggable +import com.nimbusds.jose.crypto.RSASSASigner +import com.nimbusds.jose.jwk.JWK import com.nimbusds.jose.{JWSAlgorithm, JWSHeader, JWSObject, Payload} import javax.crypto.Cipher import net.liftweb.util.SecurityHelpers @@ -31,14 +35,16 @@ object RSAUtil extends MdcLoggable { SecurityHelpers.hexDigest256(input.getBytes("UTF-8")) } - def signWithRsa256(payload: String): String = { - // Prepare JWS object with simple string as payload + def signWithRsa256(payload: String, jwk: JWK): String = { + // Prepare JWS object with simple string as a payload val jwsObject = new JWSObject( new JWSHeader.Builder(JWSAlgorithm.RS256).build, new Payload(payload) ) + + val rsaSigner = new RSASSASigner(jwk.toRSAKey) // Compute the RSA signature - jwsObject.sign(CertificateUtil.rsaSigner) + jwsObject.sign(rsaSigner) // To serialize to compact form, produces something like // eyJhbGciOiJSUzI1NiJ9.SW4gUlNBIHdlIHRydXN0IQ.IRMQENi4nJyp4er2L @@ -49,18 +55,28 @@ object RSAUtil extends MdcLoggable { s } - def computeXSign(input: String) = { + def computeXSign(input: String, jwk: JWK) = { logger.debug("Input: " + input) logger.debug("Hash: " + computeHash(input)) logger.debug("HEX hash: " + computeHexHash(input)) // Compute JWS token - val jws = signWithRsa256(computeHexHash(input)) + val jws = signWithRsa256(computeHexHash(input), jwk) logger.debug("RSA 256 signature: " + jws) // Get the last i.e. 3rd part of JWS token val xSign = jws.split('.').toList.last logger.debug("x-sign: " + xSign) xSign } + + def getPrivateKeyFromFile(path: String): JWK = { + val pathOfFile = Paths.get(path) + val pemEncodedRSAPrivateKey = Files.readAllLines(pathOfFile).toArray.toList.mkString("\n") + logger.debug(pemEncodedRSAPrivateKey) + // Parse PEM-encoded key to RSA public / private JWK + val jwk: JWK = JWK.parseFromPEMEncodedObjects(pemEncodedRSAPrivateKey); + logger.debug("Key is private: " + jwk.isPrivate) + jwk + } def main(args: Array[String]): Unit = { val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=f" @@ -69,8 +85,12 @@ object RSAUtil extends MdcLoggable { println("encrypt: " + res) println("decrypt: " + decrypt(res)) - val inputMessage = """hello world\n""" - computeXSign(inputMessage) + val timestamp = "1634805183" + val uri = "https://api.qredo.network/api/v1/p/company" + val body = """{"name":"Tesobe GmbH","city":"Berlin","country":"DE","domain":"tesobe.com","ref":"9827feec-4eae-4e80-bda3-daa7c3b97ad1"}""" + val inputMessage = s"""${timestamp}${uri}${body}""" + val privateKey = getPrivateKeyFromFile("obp-api/src/test/resources/cert/private.pem") + computeXSign(inputMessage, privateKey) } } From 0f9f26616b2004ebc0a65eb74556174b36987bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 26 Oct 2021 11:03:49 +0200 Subject: [PATCH 193/293] feature/Improve modul RSAUtil 3 --- .../src/main/scala/code/api/util/RSAUtil.scala | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index add1edc25..46ce76ae4 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -1,12 +1,13 @@ package code.api.util import java.nio.file.{Files, Paths} +import java.security.Signature import code.api.util.CertificateUtil.{privateKey, publicKey} import code.util.Helper.MdcLoggable import com.nimbusds.jose.crypto.RSASSASigner import com.nimbusds.jose.jwk.JWK -import com.nimbusds.jose.{JWSAlgorithm, JWSHeader, JWSObject, Payload} +import com.nimbusds.jose.{JOSEObjectType, JWSAlgorithm, JWSHeader, JWSObject, Payload} import javax.crypto.Cipher import net.liftweb.util.SecurityHelpers @@ -59,11 +60,14 @@ object RSAUtil extends MdcLoggable { logger.debug("Input: " + input) logger.debug("Hash: " + computeHash(input)) logger.debug("HEX hash: " + computeHexHash(input)) - // Compute JWS token - val jws = signWithRsa256(computeHexHash(input), jwk) - logger.debug("RSA 256 signature: " + jws) - // Get the last i.e. 3rd part of JWS token - val xSign = jws.split('.').toList.last + // Compute the signature + import sun.misc.BASE64Encoder + val data = input.getBytes("UTF8") + val sig = Signature.getInstance("SHA256WithRSA") + sig.initSign(jwk.toRSAKey.toPrivateKey) + sig.update(data) + val signatureBytes = sig.sign + val xSign = new BASE64Encoder().encode(signatureBytes) logger.debug("x-sign: " + xSign) xSign } @@ -91,6 +95,8 @@ object RSAUtil extends MdcLoggable { val inputMessage = s"""${timestamp}${uri}${body}""" val privateKey = getPrivateKeyFromFile("obp-api/src/test/resources/cert/private.pem") computeXSign(inputMessage, privateKey) + + } } From 10a0e4a48c3c80989bf8b8a4ebaeed83b4c2f468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 26 Oct 2021 12:21:16 +0200 Subject: [PATCH 194/293] feature/Improve modul RSAUtil 4 --- obp-api/src/main/scala/code/api/util/RSAUtil.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index 46ce76ae4..777c7f5e0 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -7,9 +7,10 @@ import code.api.util.CertificateUtil.{privateKey, publicKey} import code.util.Helper.MdcLoggable import com.nimbusds.jose.crypto.RSASSASigner import com.nimbusds.jose.jwk.JWK -import com.nimbusds.jose.{JOSEObjectType, JWSAlgorithm, JWSHeader, JWSObject, Payload} +import com.nimbusds.jose.{JWSAlgorithm, JWSHeader, JWSObject, Payload} import javax.crypto.Cipher import net.liftweb.util.SecurityHelpers +import net.liftweb.util.SecurityHelpers.base64EncodeURLSafe object RSAUtil extends MdcLoggable { @@ -61,13 +62,12 @@ object RSAUtil extends MdcLoggable { logger.debug("Hash: " + computeHash(input)) logger.debug("HEX hash: " + computeHexHash(input)) // Compute the signature - import sun.misc.BASE64Encoder val data = input.getBytes("UTF8") val sig = Signature.getInstance("SHA256WithRSA") sig.initSign(jwk.toRSAKey.toPrivateKey) sig.update(data) val signatureBytes = sig.sign - val xSign = new BASE64Encoder().encode(signatureBytes) + val xSign = base64EncodeURLSafe(signatureBytes) logger.debug("x-sign: " + xSign) xSign } From ccefe6dc20051960dd059e1c7c1dfd27812cf375 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 26 Oct 2021 12:35:02 +0200 Subject: [PATCH 195/293] feature/added the timestamp for the RSAUtil test --- obp-api/src/main/scala/code/api/util/RSAUtil.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index 777c7f5e0..db566dff9 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -2,7 +2,6 @@ package code.api.util import java.nio.file.{Files, Paths} import java.security.Signature - import code.api.util.CertificateUtil.{privateKey, publicKey} import code.util.Helper.MdcLoggable import com.nimbusds.jose.crypto.RSASSASigner @@ -11,6 +10,7 @@ import com.nimbusds.jose.{JWSAlgorithm, JWSHeader, JWSObject, Payload} import javax.crypto.Cipher import net.liftweb.util.SecurityHelpers import net.liftweb.util.SecurityHelpers.base64EncodeURLSafe +import java.time.Instant object RSAUtil extends MdcLoggable { @@ -89,12 +89,13 @@ object RSAUtil extends MdcLoggable { println("encrypt: " + res) println("decrypt: " + decrypt(res)) - val timestamp = "1634805183" + val timestamp = Instant.now.getEpochSecond val uri = "https://api.qredo.network/api/v1/p/company" val body = """{"name":"Tesobe GmbH","city":"Berlin","country":"DE","domain":"tesobe.com","ref":"9827feec-4eae-4e80-bda3-daa7c3b97ad1"}""" val inputMessage = s"""${timestamp}${uri}${body}""" val privateKey = getPrivateKeyFromFile("obp-api/src/test/resources/cert/private.pem") computeXSign(inputMessage, privateKey) + logger.debug("timestamp: " + timestamp) } From 19d93bde9b125691aed1875dfe74710d9ded4901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 26 Oct 2021 14:28:44 +0200 Subject: [PATCH 196/293] docfix/Tweak i18n props invalid.username --- obp-api/src/main/resources/i18n/lift-core.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/resources/i18n/lift-core.properties b/obp-api/src/main/resources/i18n/lift-core.properties index eceed845a..d9bc9055e 100644 --- a/obp-api/src/main/resources/i18n/lift-core.properties +++ b/obp-api/src/main/resources/i18n/lift-core.properties @@ -372,7 +372,8 @@ invalid.username=Invalid Username: \ 2) Usernames MUST be between 8 and 100 characters long \ 3) Usernames MUST NOT start with _ or . \ 4) Usernames MUST NOT contain __ or ._ or ._ or .. \ -5) Usernames MUST NOT end with _ or . +5) Usernames MUST NOT end with _ or . \ +6) Any valid email address is allowed as the Username your.username.is.not.unique = Your username is not unique. Please enter a different one. # Those 2 messages must have the same output in order to prevent leakage of information From 764303134a21aa1484f85b0b2055b51f57a4f0fa Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 26 Oct 2021 15:12:32 +0200 Subject: [PATCH 197/293] feature/added the getPrivateKeyFromString method --- obp-api/src/main/scala/code/api/util/RSAUtil.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index db566dff9..f8aefefd8 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -82,6 +82,15 @@ object RSAUtil extends MdcLoggable { jwk } + def getPrivateKeyFromString(privateKeyValue: String): JWK = { + val pemEncodedRSAPrivateKey = privateKeyValue + logger.debug(privateKeyValue) + // Parse PEM-encoded key to RSA public / private JWK + val jwk: JWK = JWK.parseFromPEMEncodedObjects(pemEncodedRSAPrivateKey); + logger.debug("Key is private: " + jwk.isPrivate) + jwk + } + def main(args: Array[String]): Unit = { val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=f" val res = encrypt(db) From fba4a0ffe653fcdf59649790642cb775b5abff6b Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 26 Oct 2021 15:32:41 +0200 Subject: [PATCH 198/293] feature/added the missing headers --- .../rest/RestConnector_vMar2019.scala | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 0e9d6b9eb..7f2146ebd 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -37,6 +37,7 @@ import code.api.cache.Caching import code.api.util.APIUtil.{AdapterImplementation, MessageDoc, OBPReturnType, saveConnectorMetric, _} import code.api.util.ErrorMessages._ import code.api.util.ExampleValue._ +import code.api.util.RSAUtil.{computeXSign, getPrivateKeyFromString} import code.api.util.{APIUtil, CallContext, OBPQueryParam} import code.api.v4_0_0.dynamic.MockResponseHolder import code.bankconnectors._ @@ -63,6 +64,7 @@ import net.liftweb.json.{JValue, _} import net.liftweb.util.Helpers.tryo import org.apache.commons.lang3.StringUtils +import java.time.Instant import scala.collection.immutable.List import scala.collection.mutable.ArrayBuffer import scala.concurrent.duration._ @@ -6522,7 +6524,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable } val jsonToSend = if(jValue == JNothing) "" else compactRender(jValue) - val request = prepareHttpRequest(paramUrl, method, HttpProtocol("HTTP/1.1"), jsonToSend).withHeaders(callContext) + val request = prepareHttpRequest(paramUrl, method, HttpProtocol("HTTP/1.1"), jsonToSend).withHeaders(buildHeaders(paramUrl,jsonToSend,callContext)) logger.debug(s"RestConnector_vMar2019 request is : $request") val responseFuture = makeHttpRequest(request) @@ -6572,15 +6574,31 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable //In RestConnector, we use the headers to propagate the parameters to Adapter. The parameters come from the CallContext.outboundAdapterAuthInfo.userAuthContext //We can set them from UserOauthContext or the http request headers. - private[this] implicit def buildHeaders(callContext: Option[CallContext]): List[HttpHeader] = { + private[this] def buildHeaders( + uri: String, + entityJsonString: String, + callContext: Option[CallContext] + ): List[HttpHeader] = { - val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext]) - val headersFromGeneralContext = generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value)) +// val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext]) +// val headersFromGeneralContext = generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value)) val basicUserAuthContexts: List[BasicUserAuthContext] = callContext.flatMap(_.toOutboundAdapterCallContext.outboundAdapterAuthInfo.flatMap(_.userAuthContext)).getOrElse(List.empty[BasicUserAuthContext]) - val headersFromUserAuthContext = basicUserAuthContexts.map(userAuthContext => RawHeader(userAuthContext.key,userAuthContext.value)) + val headersFromUserAuthContext = basicUserAuthContexts.filterNot(_.key == "private-key").map(userAuthContext =>RawHeader(userAuthContext.key,userAuthContext.value)) + + val timeStamp = Instant.now.getEpochSecond.toString + val inputMessage = s"""${timeStamp}${uri}${entityJsonString}""" + val privateKeyValue = basicUserAuthContexts.find(_.key =="private-key").map(_.value).getOrElse("") + val privateKey = getPrivateKeyFromString(privateKeyValue) + + val xSign = computeXSign(inputMessage, privateKey) + val extraHeaders = List(RawHeader("x-timestamp",timeStamp),RawHeader("x-sign",xSign)) + val headers = headersFromUserAuthContext++extraHeaders + logger.debug(s"x-timestamp: $timeStamp") + logger.debug(s"x-sign: $xSign") + logger.debug(s"obp headers: ${headers}") - headersFromGeneralContext++headersFromUserAuthContext + headers } @@ -6686,7 +6704,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable compactRender(builtJson) case _ => net.liftweb.json.Serialization.write(outBound) } - val request = prepareHttpRequest(url, method, HttpProtocol("HTTP/1.1"), outBoundJson).withHeaders(callContext) + val request = prepareHttpRequest(url, method, HttpProtocol("HTTP/1.1"), outBoundJson).withHeaders(buildHeaders(url, outBoundJson, callContext)) logger.debug(s"RestConnector_vMar2019 request is : $request") val responseFuture = makeHttpRequest(request) responseFuture.map { From 58b6f6b8b6389d112b08af8209975df63edf42b9 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Wed, 27 Oct 2021 17:18:29 +0200 Subject: [PATCH 199/293] /docfix: #authUser.skipEmailValidation=false --- obp-api/src/main/resources/props/sample.props.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 2cd0951af..89cc0181d 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -652,8 +652,8 @@ consumers_enabled_by_default=true # Autocomplete for login form has to be explicitly set autocomplete_at_login_form_enabled=false -# Skip Auth User Email validation (defaults to true) -#authUser.skipEmailValidation=true +# Skip Auth User Email validation (defaults to false as of 29 June 2021) +#authUser.skipEmailValidation=false # If using Kafka but want to get counterparties from OBP, set this to true #get_counterparties_from_OBP_DB=true From 03305d2be18053f066e5bb06e8ae35dc6526534e Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 1 Nov 2021 14:23:53 +0100 Subject: [PATCH 200/293] feature/added rest_connector_http_header_signature props --- .../rest/RestConnector_vMar2019.scala | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 7f2146ebd..9411c2a8c 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -6580,22 +6580,28 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable callContext: Option[CallContext] ): List[HttpHeader] = { -// val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext]) -// val headersFromGeneralContext = generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value)) + val needSignatureHead = APIUtil.getPropsAsBoolValue("rest_connector_http_header_signature", false) + val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext]) + val headersFromGeneralContext = generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value)) val basicUserAuthContexts: List[BasicUserAuthContext] = callContext.flatMap(_.toOutboundAdapterCallContext.outboundAdapterAuthInfo.flatMap(_.userAuthContext)).getOrElse(List.empty[BasicUserAuthContext]) val headersFromUserAuthContext = basicUserAuthContexts.filterNot(_.key == "private-key").map(userAuthContext =>RawHeader(userAuthContext.key,userAuthContext.value)) - + val timeStamp = Instant.now.getEpochSecond.toString - val inputMessage = s"""${timeStamp}${uri}${entityJsonString}""" - val privateKeyValue = basicUserAuthContexts.find(_.key =="private-key").map(_.value).getOrElse("") - val privateKey = getPrivateKeyFromString(privateKeyValue) - - val xSign = computeXSign(inputMessage, privateKey) - val extraHeaders = List(RawHeader("x-timestamp",timeStamp),RawHeader("x-sign",xSign)) - val headers = headersFromUserAuthContext++extraHeaders logger.debug(s"x-timestamp: $timeStamp") - logger.debug(s"x-sign: $xSign") + + val extraHeaders = if(needSignatureHead){ + val inputMessage = s"""${timeStamp}${uri}${entityJsonString}""" + val privateKeyValue = basicUserAuthContexts.find(_.key =="private-key").map(_.value).getOrElse("") + val privateKey = getPrivateKeyFromString(privateKeyValue) + val xSign = computeXSign(inputMessage, privateKey) + logger.debug(s"x-sign: $xSign") + List(RawHeader("x-timestamp",timeStamp),RawHeader("x-sign",xSign)) + } else { + List(RawHeader("x-timestamp",timeStamp)) + } + val headers = headersFromUserAuthContext++extraHeaders++headersFromGeneralContext + logger.debug(s"obp headers: ${headers}") headers From 77039d71d60f5085a07e1717ce829f4813672dc0 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 1 Nov 2021 14:31:31 +0100 Subject: [PATCH 201/293] docfix/added rest_connector_http_header_signature to release_notes.md --- obp-api/src/main/resources/props/sample.props.template | 4 +++- release_notes.md | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index d8898b4bc..e3349524f 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -805,7 +805,9 @@ featured_apis=elasticSearchWarehouseV300 # If Rest Connector do not get the response in the following seconds, it will throw the error message back. # This props can be omitted, the default value is 59. It should be less than Nginx timeout. # rest2019_connector_timeout = 59 - +# If set it to `true`, it will add the signature (SHA256WithRSA) into each the rest connector http calls, and you need to upload the RSA +# private key into the UserAuthContext. +#rest_connector_http_header_signature=false # -- Scopes ----------------------------------------------------- diff --git a/release_notes.md b/release_notes.md index 4159cc333..612c6f8f8 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,6 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action +01/11/2021 03305d2b Added props: rest_connector_http_header_signature, default is false 17/09/2021 e65cd51d Added props: webui_main_faq_external_link, default is obp static file: /main-faq.html 09/09/2021 65952225 Added props: webui_support_email, default is contact@openbankproject.com 02/09/2021 a826d908 Renamed Web UI props: From 374d6e71c2bd89d6a7da0d1e325c1a13e249f740 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 1 Nov 2021 17:10:17 +0100 Subject: [PATCH 202/293] bugfix/fixed the GatewayLogin username issue --- obp-api/src/main/scala/code/api/GatewayLogin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/GatewayLogin.scala b/obp-api/src/main/scala/code/api/GatewayLogin.scala index e8ae2823e..e66c33160 100755 --- a/obp-api/src/main/scala/code/api/GatewayLogin.scala +++ b/obp-api/src/main/scala/code/api/GatewayLogin.scala @@ -482,7 +482,7 @@ object GatewayLogin extends RestHelper with MdcLoggable { val payload = GatewayLogin.parseJwt(parameters) payload match { case Full(payload) => - val username = getFieldFromPayloadJson(payload, "username") + val username = getFieldFromPayloadJson(payload, "login_user_name") logger.debug("username: " + username) Users.users.vend.getUserByProviderId(provider = gateway, idGivenByProvider = username) case _ => From 0893997ae79572ab42eebb2eb83ec639c92e5925 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 1 Nov 2021 17:11:23 +0100 Subject: [PATCH 203/293] feature/added the new login type: DAuthLogin - step1 --- .../resources/props/sample.props.template | 10 + .../src/main/scala/code/api/DAuthLogin.scala | 333 ++++++++++++++++++ .../main/scala/code/api/OBPRestHelper.scala | 43 ++- .../main/scala/code/api/util/APIUtil.scala | 69 +++- .../main/scala/code/api/util/ApiSession.scala | 38 +- .../scala/code/api/util/ErrorMessages.scala | 11 + 6 files changed, 494 insertions(+), 10 deletions(-) create mode 100755 obp-api/src/main/scala/code/api/DAuthLogin.scala diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index e3349524f..28182aa96 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -688,6 +688,16 @@ autocomplete_at_login_form_enabled=false # gateway.token_secret=secret # -------------------------------------- Gateway login -- +# -- DAuth login -------------------------------------- +# Enable/Disable DAuth communication at all +# In case isn't defined default value is false +# allow_dauth_login=false +# Define comma separated list of allowed IP addresses +# dauth.host=127.0.0.1 +# Define secret used to validate JWT token +# jwt.token_secret=secret +# -------------------------------------- DAuth login -- + # Disable akka (Remote storage not possible) use_akka=false diff --git a/obp-api/src/main/scala/code/api/DAuthLogin.scala b/obp-api/src/main/scala/code/api/DAuthLogin.scala new file mode 100755 index 000000000..adf259bc9 --- /dev/null +++ b/obp-api/src/main/scala/code/api/DAuthLogin.scala @@ -0,0 +1,333 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH. +Osloer Strasse 16/17 +Berlin 13359, Germany + + This product includes software developed at + TESOBE (http://www.tesobe.com/) + + */ +package code.api + +import code.api.JSONFactoryDAuth.PayloadOfJwtJSON +import code.api.util._ +import code.consumer.Consumers +import code.model.{Consumer, UserX} +import code.users.Users +import code.util.Helper.MdcLoggable +import com.nimbusds.jwt.JWTClaimsSet +import com.openbankproject.commons.model.{User} +import net.liftweb.common._ +import net.liftweb.http._ +import net.liftweb.http.rest.RestHelper +import net.liftweb.json._ +import net.liftweb.util.Helpers + +import com.openbankproject.commons.ExecutionContext.Implicits.global +import scala.concurrent.Future + +/** + * This object provides the API calls necessary to + * authenticate users using JSON Web Tokens (http://jwt.io). + */ + + +object JSONFactoryDAuth { + //Never update these values inside the case class + case class PayloadOfJwtJSON( + smart_contract_address: String, + network_name: String, + msg_sender: String, + consumer_id: String, + time_stamp: String, + caller_request_id: String + ) + +} + +object DAuthLogin extends RestHelper with MdcLoggable { + + val DAuth = "DAuth" // This value is used for ResourceUser.provider and Consumer.description + + def createJwt(payloadAsJsonString: String) : String = { + val smartContractAddress = getFieldFromPayloadJson(payloadAsJsonString, "smart_contract_address") + val networkName = getFieldFromPayloadJson(payloadAsJsonString, "network_name") + val msgSender = getFieldFromPayloadJson(payloadAsJsonString, "msg_sender") + val consumerId = getFieldFromPayloadJson(payloadAsJsonString, "consumer_id") + val timeStamp = getFieldFromPayloadJson(payloadAsJsonString, "time_stamp") + val callerRequestId = getFieldFromPayloadJson(payloadAsJsonString, "caller_request_id") + + val json = JSONFactoryDAuth.PayloadOfJwtJSON( + smart_contract_address = smartContractAddress, + network_name = networkName, + msg_sender = msgSender, + consumer_id = consumerId, + time_stamp = timeStamp, + caller_request_id = callerRequestId + ) + val jwtPayloadAsJson = compactRender(Extraction.decompose(json)) + val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson) + + APIUtil.getPropsAsBoolValue("jwt.use.ssl", false) match { + case true => + CertificateUtil.encryptJwtWithRsa(jwtClaims) + case false => + CertificateUtil.jwtWithHmacProtection(jwtClaims) + } + } + + def parseJwt(parameters: Map[String, String]): Box[String] = { + val jwt = getToken(parameters) + logger.debug("parseJwt says jwt.toString is: " + jwt.toString) + logger.debug("parseJwt says: validateJwtToken(jwt) is:" + validateJwtToken(jwt)) + validateJwtToken(jwt) match { + case Full(jwtPayload) => + logger.debug("parseJwt says: Full: " + jwtPayload.toString) + Full(compactRender(Extraction.decompose(jwtPayload))) + case _ => + logger.debug("parseJwt says: Not Full(jwtPayload)") + Failure(ErrorMessages.GatewayLoginJwtTokenIsNotValid) + } + } + + def validateJwtToken(token: String): Box[PayloadOfJwtJSON] = { + APIUtil.getPropsAsBoolValue("jwt.use.ssl", false) match { + case true => + logger.debug("validateJwtToken says: verifying jwt token with RSA: " + token) + val claim = CertificateUtil.decryptJwtWithRsa(token) + Box(parse(claim.toString).extractOpt[PayloadOfJwtJSON]) + case false => + logger.debug("validateJwtToken says: verifying jwt token with HmacProtection: " + token) + logger.debug(CertificateUtil.verifywtWithHmacProtection(token).toString) + CertificateUtil.verifywtWithHmacProtection(token) match { + case true => + logger.debug("validateJwtToken says: jwt is verified: " + token) + val claim = CertificateUtil.parseJwtWithHmacProtection(token) + logger.debug("validateJwtToken says: this is claim of verified jwt: " + claim.toString()) + Box(parse(claim.toString).extractOpt[PayloadOfJwtJSON]) + case _ => + logger.debug("validateJwtToken says: could not verify jwt") + Failure(ErrorMessages.GatewayLoginJwtTokenIsNotValid) + } + } + } + + // Check if the request (access token or request token) is valid and return a tuple + def validator(request: Box[Req]) : (Int, String, Map[String,String]) = { + // First we try to extract all parameters from a Request + val parameters: Map[String, String] = getAllParameters(request) + val emptyMap = Map[String, String]() + + parameters.get("error") match { + case Some(m) => { + logger.error("DAuthLogin error message : " + m) + (400, m, emptyMap) + } + case _ => { + // Are all the necessary DAuthLogin parameters present? + val missingParams: Set[String] = missingDAuthLoginParameters(parameters) + missingParams.nonEmpty match { + case true => { + val message = ErrorMessages.DAuthLoginMissingParameters + missingParams.mkString(", ") + logger.error("DAuthLogin error message : " + message) + (400, message, emptyMap) + } + case false => { + logger.debug("DAuthLogin parameters : " + parameters) + (200, "", parameters) + } + } + } + } + } + + def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { + val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + logger.debug("login_user_name: " + username) + for { + tuple <- + Users.users.vend.getUserByProviderId(provider = DAuth, idGivenByProvider = username).or { // Find a user + Users.users.vend.createResourceUser( // Otherwise create a new one + provider = DAuth, + providerId = Some(username), + None, + name = Some(username), + email = None, + userId = None, + createdByUserInvitationId = None, + company = None, + lastMarketingAgreementSignedDate = None + ) + } match { + case Full(u) => + Full((u,callContext)) // Return user + case Empty => + Failure(ErrorMessages.DAuthLoginCannotGetOrCreateUser) + case Failure(msg, t, c) => + Failure(msg, t, c) + case _ => + Failure(ErrorMessages.DAuthLoginUnknownError) + } + } yield { + tuple + } + } + def getOrCreateResourceUserFuture(jwtPayload: String, callContext: Option[CallContext]) : Future[Box[(User, Option[CallContext])]] = { + val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + logger.debug("login_user_name: " + username) + for { + tuple <- + Users.users.vend.getOrCreateUserByProviderIdFuture(provider = DAuth, idGivenByProvider = username, consentId = None, name = None, email = None) map { + case (Full(u), _) => + Full(u, callContext) // Return user + case (Empty, _) => + Failure(ErrorMessages.DAuthLoginCannotGetOrCreateUser) + case (Failure(msg, t, c), _) => + Failure(msg, t, c) + case _ => + Failure(ErrorMessages.DAuthLoginUnknownError) + } + } yield { + tuple + } + } + + def getOrCreateConsumer(jwtPayload: String, u: User) : Box[Consumer] = { + val consumerId = getFieldFromPayloadJson(jwtPayload, "consumer_id") + val consumerName = getFieldFromPayloadJson(jwtPayload, "msg_sender") + logger.debug("app_id: " + consumerId) + logger.debug("app_name: " + consumerName) + Consumers.consumers.vend.getOrCreateConsumer( + consumerId=Some(consumerId), + Some(Helpers.randomString(40).toLowerCase), + Some(Helpers.randomString(40).toLowerCase), + None, + None, + None, + None, + Some(true), + name = Some(consumerName), + appType = None, + description = Some(DAuth), + developerEmail = None, + redirectURL = None, + createdByUserId = Some(u.userId) + ) + } + + // Return a Map containing the DAuthLogin parameter : token -> value + def getAllParameters(request: Box[Req]): Map[String, String] = { + def toMap(parametersList: String) = { + //transform the string "DAuthLogin token="value"" + //to a tuple (DAuthLogin_parameter,Decoded(value)) + def dynamicListExtract(input: String) = { + val DAuthLoginPossibleParameters = + List( + "token" + ) + if (input contains "=") { + val split = input.split("=", 2) + val parameterValue = split(1).replace("\"", "") + //add only OAuth parameters and not empty + if (DAuthLoginPossibleParameters.contains(split(0)) && !parameterValue.isEmpty) + Some(split(0), parameterValue) // return key , value + else + None + } + else + None + } + // We delete the "DAuthLogin" prefix and all the white spaces that may exist in the string + val cleanedParameterList = parametersList.stripPrefix("DAuthLogin").replaceAll("\\s", "") + val params = Map(cleanedParameterList.split(",").flatMap(dynamicListExtract _): _*) + params + } + + request match { + case Full(a) => a.header("Authorization") match { + case Full(header) => { + if (header.contains("DAuthLogin")) + toMap(header) + else + Map("error" -> "Missing DAuthLogin in header!") + } + case _ => Map("error" -> "Missing Authorization header!") + } + case _ => Map("error" -> "Request is incorrect!") + } + } + + // Returns the missing parameters + def missingDAuthLoginParameters(parameters: Map[String, String]): Set[String] = { + ("token" :: List()).toSet diff parameters.keySet + } + + private def getToken(params: Map[String, String]): String = { + logger.debug("getToken params are: " + params.toString()) + val token = params.getOrElse("token", "") + logger.debug("getToken wants to return token: " + token) + token + } + + private def getFieldFromPayloadJson(payloadAsJsonString: String, fieldName: String) = { + val jwtJson = parse(payloadAsJsonString) // Transform Json string to JsonAST + val v = jwtJson.\(fieldName) + v match { + case JNothing => + "" + case _ => + compactRender(v).replace("\"", "") + } + } + + // Try to find errorCode in Json string received from South side and extract to list + // Return list of error codes values + def getErrors(message: String) : List[String] = { + val json = parse(message) removeField { + case JField("backendMessages", _) => true + case _ => false + } + val listOfValues = for { + JArray(objects) <- json + JObject(obj) <- objects + JField("errorCode", JString(fieldName)) <- obj + } yield fieldName + listOfValues + } + + + def getUser : Box[User] = { + val (httpCode, message, parameters) = DAuthLogin.validator(S.request) + httpCode match { + case 200 => + val payload = DAuthLogin.parseJwt(parameters) + payload match { + case Full(payload) => + val username = getFieldFromPayloadJson(payload, "smart_contract_address") + logger.debug("username: " + username) + Users.users.vend.getUserByProviderId(provider = DAuth, idGivenByProvider = username) + case _ => + None + } + case _ => + None + } + } +} diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 2bcf154ab..1def75b97 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -401,7 +401,48 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { case _ => Failure(ErrorMessages.GatewayLoginUnknownError) } - } else { + } + else if (APIUtil.getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(authorization)) { + logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) + APIUtil.getPropsValue("dauth.host") match { + case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature + val s = S + val (httpCode, message, parameters) = DAuthLogin.validator(s.request) + httpCode match { + case 200 => + val payload = DAuthLogin.parseJwt(parameters) + payload match { + case Full(payload) => + val s = S + DAuthLogin.getOrCreateResourceUser(payload: String, Some(cc)) match { + case Full((u, callContext)) => // Authentication is successful + val consumer = DAuthLogin.getOrCreateConsumer(payload, u) + setGatewayResponseHeader(s) {DAuthLogin.createJwt(payload)} + val jwt = DAuthLogin.createJwt(payload) + val callContextUpdated = ApiSession.updateCallContext(DAuthLoginResponseHeader(Some(jwt)), callContext) + fn(callContextUpdated.map( callContext =>callContext.copy(user = Full(u), consumer = consumer)).getOrElse(callContext.getOrElse(cc).copy(user = Full(u), consumer = consumer))) + case Failure(msg, t, c) => Failure(msg, t, c) + case _ => Full(errorJsonResponse(payload, httpCode)) + } + case Failure(msg, t, c) => + Failure(msg, t, c) + case _ => + Failure(ErrorMessages.DAuthLoginUnknownError) + } + case _ => + Failure(message) + } + case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == false) => // All other addresses will be rejected + Failure(ErrorMessages.DAuthLoginWhiteListAddresses) + case Empty => + Failure(ErrorMessages.DAuthLoginHostPropertyMissing) // There is no dauth.host in props file + case Failure(msg, t, c) => + Failure(msg, t, c) + case _ => + Failure(ErrorMessages.DAuthLoginUnknownError) + } + } + else { fn(cc) } } diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 858072ba9..511af54ee 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -180,6 +180,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ def hasAnOAuth2Header(authorization: Box[String]): Boolean = hasHeader("Bearer", authorization) def hasGatewayHeader(authorization: Box[String]) = hasHeader("GatewayLogin", authorization) + + def hasDAuthHeader(authorization: Box[String]) = hasHeader("DAuthLogin", authorization) /** * Helper function which tells us does an "Authorization" request header field has the Type of an authentication scheme @@ -2244,6 +2246,31 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ None } } + /** + * Defines DAuth Custom Response Header. + */ + val DAuthResponseHeaderName = "DAuthLogin" + /** + * Set value of DAuth Custom Response Header. + */ + def setDAuthResponseHeader(s: S)(value: String) = s.setSessionAttribute(DAuthResponseHeaderName, value) + /** + * @return - DAuth Custom Response Header. + */ + def getDAuthResponseHeader() = { + S.getSessionAttribute(DAuthResponseHeaderName) match { + case Full(h) => List((DAuthResponseHeaderName, h)) + case _ => Nil + } + } + def getDAuthLoginJwt(): Option[String] = { + getDAuthResponseHeader() match { + case x :: Nil => + Some(x._2) + case _ => + None + } + } /** * Turn a string of format "FooBar" into snake case "foo_bar" @@ -2708,7 +2735,47 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case _ => Future { (Failure(ErrorMessages.GatewayLoginUnknownError), None) } } - } else if(Option(cc).flatMap(_.user).isDefined) { + } // DAuthLogin Login + else if (getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.authReqHeaderField)) { + logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) + APIUtil.getPropsValue("dauth.host") match { + case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature + val (httpCode, message, parameters) = DAuthLogin.validator(s.request) + httpCode match { + case 200 => + val payload = DAuthLogin.parseJwt(parameters) + payload match { + case Full(payload) => + DAuthLogin.getOrCreateResourceUserFuture(payload: String, Some(cc)) map { + case Full((u,callContext)) => // Authentication is successful + val consumer = DAuthLogin.getOrCreateConsumer(payload, u) + val jwt = DAuthLogin.createJwt(payload) + val callContextUpdated = ApiSession.updateCallContext(DAuthLoginResponseHeader(Some(jwt)), callContext) + (Full(u), callContextUpdated.map(_.copy(consumer=consumer, user = Full(u)))) + case Failure(msg, t, c) => + (Failure(msg, t, c), None) + case _ => + (Failure(payload), None) + } + case Failure(msg, t, c) => + Future { (Failure(msg, t, c), None) } + case _ => + Future { (Failure(ErrorMessages.DAuthLoginUnknownError), None) } + } + case _ => + Future { (Failure(message), None) } + } + case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == false) => // All other addresses will be rejected + Future { (Failure(ErrorMessages.DAuthLoginWhiteListAddresses), None) } + case Empty => + Future { (Failure(ErrorMessages.DAuthLoginHostPropertyMissing), None) } // There is no dauth.host in props file + case Failure(msg, t, c) => + Future { (Failure(msg, t, c), None) } + case _ => + Future { (Failure(ErrorMessages.DAuthLoginUnknownError), None) } + } + } + else if(Option(cc).flatMap(_.user).isDefined) { Future{(cc.user, Some(cc))} } else { diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala index eb84aa7ee..af9e7c08b 100644 --- a/obp-api/src/main/scala/code/api/util/ApiSession.scala +++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala @@ -1,10 +1,11 @@ package code.api.util +import code.api.JSONFactoryDAuth import java.util.{Date, UUID} import code.api.JSONFactoryGateway.PayloadOfJwtJSON import code.api.oauth1a.OauthParams._ import code.api.util.APIUtil._ -import code.api.util.AuthenticationType.{Anonymous, DirectLogin, GatewayLogin, OAuth2_OIDC, OAuth2_OIDC_FAPI} +import code.api.util.AuthenticationType.{Anonymous, DirectLogin, GatewayLogin, DAuthLogin, OAuth2_OIDC, OAuth2_OIDC_FAPI} import code.api.util.ErrorMessages.{BankAccountNotFound, UserNotLoggedIn} import code.api.util.RateLimitingJson.CallLimit import code.context.UserAuthContextProvider @@ -25,6 +26,8 @@ import scala.collection.immutable.List case class CallContext( gatewayLoginRequestPayload: Option[PayloadOfJwtJSON] = None, //Never update these values inside the case class !!! gatewayLoginResponseHeader: Option[String] = None, + dauthLoginRequestPayload: Option[JSONFactoryDAuth.PayloadOfJwtJSON] = None, //Never update these values inside the case class !!! + dauthLoginResponseHeader: Option[String] = None, spelling: Option[String] = None, user: Box[User] = Empty, consumer: Box[Consumer] = Empty, @@ -137,6 +140,8 @@ case class CallContext( def authType: AuthenticationType = { if(hasGatewayHeader(authReqHeaderField)) { GatewayLogin + } else if(hasDAuthHeader(authReqHeaderField)) { // DAuth Login + DAuthLogin } else if(has2021DirectLoginHeader(requestHeaders)) { // Direct Login DirectLogin } else if(hasDirectLoginHeader(authReqHeaderField)) { // Direct Login Deprecated @@ -161,6 +166,7 @@ object AuthenticationType extends OBPEnumeration[AuthenticationType]{ override def toString: String = "OAuth1.0a" } object GatewayLogin extends AuthenticationType + object DAuthLogin extends AuthenticationType object OAuth2_OIDC extends AuthenticationType object OAuth2_OIDC_FAPI extends AuthenticationType object Anonymous extends AuthenticationType @@ -193,9 +199,11 @@ case class CallContextLight(gatewayLoginRequestPayload: Option[PayloadOfJwtJSON] `X-Rate-Limit-Reset` : Long = -1 ) -trait GatewayLoginParam -case class GatewayLoginRequestPayload(jwtPayload: Option[PayloadOfJwtJSON]) extends GatewayLoginParam -case class GatewayLoginResponseHeader(jwt: Option[String]) extends GatewayLoginParam +trait LoginParam +case class GatewayLoginRequestPayload(jwtPayload: Option[PayloadOfJwtJSON]) extends LoginParam +case class GatewayLoginResponseHeader(jwt: Option[String]) extends LoginParam +case class DAuthLoginRequestPayload(jwtPayload: Option[JSONFactoryDAuth.PayloadOfJwtJSON]) extends LoginParam +case class DAuthLoginResponseHeader(jwt: Option[String]) extends LoginParam case class Spelling(spelling: Box[String]) @@ -230,17 +238,17 @@ object ApiSession { def updateCallContext(s: Spelling, cnt: Option[CallContext]): Option[CallContext] = { cnt match { case None => - Some(CallContext(gatewayLoginRequestPayload = None, gatewayLoginResponseHeader = None, spelling = s.spelling)) + Some(CallContext(spelling = s.spelling)) //Some fields default value is NONE. case Some(v) => Some(v.copy(spelling = s.spelling)) } } - def updateCallContext(jwt: GatewayLoginParam, cnt: Option[CallContext]): Option[CallContext] = { + def updateCallContext(jwt: LoginParam, cnt: Option[CallContext]): Option[CallContext] = { jwt match { - case GatewayLoginRequestPayload(None) => + case GatewayLoginRequestPayload(None) | DAuthLoginRequestPayload(None) => cnt - case GatewayLoginResponseHeader(None) => + case GatewayLoginResponseHeader(None) | DAuthLoginResponseHeader(None) => cnt case GatewayLoginRequestPayload(Some(jwtPayload)) => cnt match { @@ -256,6 +264,20 @@ object ApiSession { case None => Some(CallContext(gatewayLoginRequestPayload = None, gatewayLoginResponseHeader = Some(j), spelling = None)) } + case DAuthLoginRequestPayload(Some(jwtPayload)) => + cnt match { + case Some(v) => + Some(v.copy(dauthLoginRequestPayload = Some(jwtPayload))) + case None => + Some(CallContext(dauthLoginRequestPayload = Some(jwtPayload), dauthLoginResponseHeader = None, spelling = None)) + } + case DAuthLoginResponseHeader(Some(j)) => + cnt match { + case Some(v) => + Some(v.copy(dauthLoginResponseHeader = Some(j))) + case None => + Some(CallContext(dauthLoginRequestPayload = None, dauthLoginResponseHeader = Some(j), spelling = None)) + } } } diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index f346ec152..1193a6936 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -182,6 +182,17 @@ object ErrorMessages { val UserIsDeleted = "OBP-20064: The user is deleted!" + val DAuthLoginCannotGetOrCreateUser = "OBP-20065: Cannot get or create user during DAuthLogin process." + val DAuthLoginMissingParameters = "OBP-20066: These DAuthLogin parameters are missing: " + val DAuthLoginUnknownError = "OBP-20067: Unknown Gateway login error." + val DAuthLoginHostPropertyMissing = "OBP-20068: Property gateway.host is not defined." + val DAuthLoginWhiteListAddresses = "OBP-20069: Gateway login can be done only from allowed addresses." + val DAuthLoginJwtTokenIsNotValid = "OBP-20070: The JWT is corrupted/changed during a transport." + val DAuthLoginCannotExtractJwtToken = "OBP-20071: Header, Payload and Signature cannot be extracted from the JWT." + val DAuthLoginNoNeedToCallCbs = "OBP-20072: There is no need to call CBS" + val DAuthLoginCannotFindUser = "OBP-20073: User cannot be found. Please initiate CBS communication in order to create it." + val DAuthLoginCannotGetCbsToken = "OBP-20074: Cannot get the CBSToken response from South side" + val DAuthLoginNoJwtForResponse = "OBP-20075: There is no useful value for JWT." val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " From f84701db9eb0ab6aae23f3087a9cd05b1b119457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 1 Nov 2021 17:15:25 +0100 Subject: [PATCH 204/293] docfix/Add jwt.token_secret=secret as the name for GatawayLoin and DAuthLogin --- obp-api/src/main/resources/props/sample.props.template | 2 +- obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala | 4 ++++ obp-api/src/main/scala/code/api/util/CertificateUtil.scala | 2 +- obp-api/src/main/scala/code/api/util/Glossary.scala | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index d8898b4bc..dd1ffe878 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -685,7 +685,7 @@ autocomplete_at_login_form_enabled=false # Define comma separated list of allowed IP addresses # gateway.host=127.0.0.1 # Define secret used to validate JWT token -# gateway.token_secret=secret +# jwt.token_secret=secret # -------------------------------------- Gateway login -- diff --git a/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala b/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala index 1492be369..f9f96e35f 100644 --- a/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala +++ b/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala @@ -29,6 +29,10 @@ object ApiPropsWithAlias { name="allow_customer_firehose", alias="allow_firehose_views", defaultValue="false") + def jwtTokenSecret = getValueByNameOrAliasAsBoolean( + name="jwt.token_secret", + alias="gateway.token_secret", + defaultValue="Cannot get your at least 256 bit secret") } object HelperFunctions extends MdcLoggable { diff --git a/obp-api/src/main/scala/code/api/util/CertificateUtil.scala b/obp-api/src/main/scala/code/api/util/CertificateUtil.scala index d6cd3bdca..4b3774ac7 100644 --- a/obp-api/src/main/scala/code/api/util/CertificateUtil.scala +++ b/obp-api/src/main/scala/code/api/util/CertificateUtil.scala @@ -25,7 +25,7 @@ object CryptoSystem extends Enumeration { object CertificateUtil extends MdcLoggable { // your-at-least-256-bit-secret - val sharedSecret = APIUtil.getPropsValue("gateway.token_secret", "Cannot get your at least 256 bit secret") + val sharedSecret = ApiPropsWithAlias.jwtTokenSecret lazy val (publicKey: RSAPublicKey, privateKey: RSAPrivateKey) = APIUtil.getPropsAsBoolValue("jwt.use.ssl", false) match { case true => diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 7a6ea4f12..4f4a54e21 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -1844,10 +1844,10 @@ object Glossary extends MdcLoggable { |# Define comma separated list of allowed IP addresses |# gateway.host=127.0.0.1 |# Define secret used to validate JWT token -|# gateway.token_secret=secret +|# jwt.token_secret=secret |# -------------------------------------- Gateway login -- |``` -|Please keep in mind that property gateway.token_secret is used to validate JWT token to check it is not changed or corrupted during transport. +|Please keep in mind that property jwt.token_secret is used to validate JWT token to check it is not changed or corrupted during transport. | |### 2) Create / have access to a JWT | From ca40434443ce97309ce3780cf01f941782cebbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 2 Nov 2021 08:41:39 +0100 Subject: [PATCH 205/293] docfix/Add jwt.token_secret=secret as the name for GatawayLoin and DAuthLogin 2 --- obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala | 2 +- obp-api/src/main/scala/code/api/util/CertificateUtil.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala b/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala index f9f96e35f..2f662a5d5 100644 --- a/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala +++ b/obp-api/src/main/scala/code/api/util/ApiPropsWithAlias.scala @@ -29,7 +29,7 @@ object ApiPropsWithAlias { name="allow_customer_firehose", alias="allow_firehose_views", defaultValue="false") - def jwtTokenSecret = getValueByNameOrAliasAsBoolean( + def jwtTokenSecret = getValueByNameOrAlias( name="jwt.token_secret", alias="gateway.token_secret", defaultValue="Cannot get your at least 256 bit secret") diff --git a/obp-api/src/main/scala/code/api/util/CertificateUtil.scala b/obp-api/src/main/scala/code/api/util/CertificateUtil.scala index 4b3774ac7..1baea2fee 100644 --- a/obp-api/src/main/scala/code/api/util/CertificateUtil.scala +++ b/obp-api/src/main/scala/code/api/util/CertificateUtil.scala @@ -25,7 +25,7 @@ object CryptoSystem extends Enumeration { object CertificateUtil extends MdcLoggable { // your-at-least-256-bit-secret - val sharedSecret = ApiPropsWithAlias.jwtTokenSecret + val sharedSecret: String = ApiPropsWithAlias.jwtTokenSecret lazy val (publicKey: RSAPublicKey, privateKey: RSAPrivateKey) = APIUtil.getPropsAsBoolValue("jwt.use.ssl", false) match { case true => From 691d37c77817ed6a5113a63399be57739d1c2a8a Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 2 Nov 2021 11:48:10 +0100 Subject: [PATCH 206/293] feature/tweaked the error message for InvalidChallengeAnswer --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 1193a6936..a8b878d63 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -503,7 +503,9 @@ object ErrorMessages { val InvalidChargePolicy = "OBP-40013: Invalid Charge Policy. Please specify a valid value for Charge_Policy: SHARED, SENDER or RECEIVER. " val AllowedAttemptsUsedUp = "OBP-40014: Sorry, you've used up your allowed attempts. " val InvalidChallengeType = "OBP-40015: Invalid Challenge Type. Please specify a valid value for CHALLENGE_TYPE, when you create the transaction request." - val InvalidChallengeAnswer = "OBP-40016: Invalid Challenge Answer. Please specify a valid value for answer in Json body. If it is sandbox mode, the answer must be `123`. If it kafka mode, the answer can be got by phone message or other security ways." + val InvalidChallengeAnswer = "OBP-40016: Invalid Challenge Answer. Please specify a valid value for answer in Json body. " + + "If connector = mapped and transactionRequestType_OTP_INSTRUCTION_TRANSPORT = DUMMY and suggested_default_sca_method=DUMMY, the answer must be `123`. " + + "If connector = others, the challenge answer can be got by phone message or other security ways." val InvalidPhoneNumber = "OBP-40017: Invalid Phone Number. Please specify a valid value for PHONE_NUMBER. Eg:+9722398746 " val TransactionRequestsNotEnabled = "OBP-40018: Sorry, Transaction Requests are not enabled in this API instance." val NextChallengePending = s"OBP-40019: Cannot create transaction due to transaction request is in status: ${NEXT_CHALLENGE_PENDING}." From 7950d278293caf30f50530fb892c18daff86950a Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 2 Nov 2021 13:41:07 +0100 Subject: [PATCH 207/293] feature/rename DAuthLogin --> DAuth --- .../resources/props/sample.props.template | 11 ++-- .../main/scala/code/api/OBPRestHelper.scala | 22 +++---- .../api/{DAuthLogin.scala => dauth.scala} | 58 +++++++++---------- .../main/scala/code/api/util/APIUtil.scala | 28 ++++----- .../main/scala/code/api/util/ApiSession.scala | 30 +++++----- .../scala/code/api/util/ErrorMessages.scala | 17 ++---- 6 files changed, 81 insertions(+), 85 deletions(-) rename obp-api/src/main/scala/code/api/{DAuthLogin.scala => dauth.scala} (84%) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 1b03dbb96..54ef0d035 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -678,15 +678,17 @@ autocomplete_at_login_form_enabled=false # control access to customer firehose. # allow_customer_firehose=false +# -- Gateway And DAuth common Setting-------------------------------------- +# Define secret used to validate JWT token +# jwt.token_secret=secretsecretsecretstsecretssssss + # -- Gateway login -------------------------------------- # Enable/Disable Gateway communication at all # In case isn't defined default value is false # allow_gateway_login=false # Define comma separated list of allowed IP addresses # gateway.host=127.0.0.1 -# Define secret used to validate JWT token -# jwt.token_secret=secret -# -------------------------------------- Gateway login -- + # -- DAuth login -------------------------------------- # Enable/Disable DAuth communication at all @@ -694,8 +696,7 @@ autocomplete_at_login_form_enabled=false # allow_dauth_login=false # Define comma separated list of allowed IP addresses # dauth.host=127.0.0.1 -# Define secret used to validate JWT token -# jwt.token_secret=secret + # -------------------------------------- DAuth login -- diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 1def75b97..6475ae593 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -407,19 +407,19 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val s = S - val (httpCode, message, parameters) = DAuthLogin.validator(s.request) + val (httpCode, message, parameters) = DAuth.validator(s.request) httpCode match { case 200 => - val payload = DAuthLogin.parseJwt(parameters) + val payload = DAuth.parseJwt(parameters) payload match { case Full(payload) => val s = S - DAuthLogin.getOrCreateResourceUser(payload: String, Some(cc)) match { + DAuth.getOrCreateResourceUser(payload: String, Some(cc)) match { case Full((u, callContext)) => // Authentication is successful - val consumer = DAuthLogin.getOrCreateConsumer(payload, u) - setGatewayResponseHeader(s) {DAuthLogin.createJwt(payload)} - val jwt = DAuthLogin.createJwt(payload) - val callContextUpdated = ApiSession.updateCallContext(DAuthLoginResponseHeader(Some(jwt)), callContext) + val consumer = DAuth.getOrCreateConsumer(payload, u) + setGatewayResponseHeader(s) {DAuth.createJwt(payload)} + val jwt = DAuth.createJwt(payload) + val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) fn(callContextUpdated.map( callContext =>callContext.copy(user = Full(u), consumer = consumer)).getOrElse(callContext.getOrElse(cc).copy(user = Full(u), consumer = consumer))) case Failure(msg, t, c) => Failure(msg, t, c) case _ => Full(errorJsonResponse(payload, httpCode)) @@ -427,19 +427,19 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { case Failure(msg, t, c) => Failure(msg, t, c) case _ => - Failure(ErrorMessages.DAuthLoginUnknownError) + Failure(ErrorMessages.DAuthUnknownError) } case _ => Failure(message) } case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == false) => // All other addresses will be rejected - Failure(ErrorMessages.DAuthLoginWhiteListAddresses) + Failure(ErrorMessages.DAuthWhiteListAddresses) case Empty => - Failure(ErrorMessages.DAuthLoginHostPropertyMissing) // There is no dauth.host in props file + Failure(ErrorMessages.DAuthHostPropertyMissing) // There is no dauth.host in props file case Failure(msg, t, c) => Failure(msg, t, c) case _ => - Failure(ErrorMessages.DAuthLoginUnknownError) + Failure(ErrorMessages.DAuthUnknownError) } } else { diff --git a/obp-api/src/main/scala/code/api/DAuthLogin.scala b/obp-api/src/main/scala/code/api/dauth.scala similarity index 84% rename from obp-api/src/main/scala/code/api/DAuthLogin.scala rename to obp-api/src/main/scala/code/api/dauth.scala index adf259bc9..7c0cc6898 100755 --- a/obp-api/src/main/scala/code/api/DAuthLogin.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -62,9 +62,9 @@ object JSONFactoryDAuth { } -object DAuthLogin extends RestHelper with MdcLoggable { +object DAuth extends RestHelper with MdcLoggable { - val DAuth = "DAuth" // This value is used for ResourceUser.provider and Consumer.description + val DAuthValue = "DAuth" // This value is used for ResourceUser.provider and Consumer.description def createJwt(payloadAsJsonString: String) : String = { val smartContractAddress = getFieldFromPayloadJson(payloadAsJsonString, "smart_contract_address") @@ -137,20 +137,20 @@ object DAuthLogin extends RestHelper with MdcLoggable { parameters.get("error") match { case Some(m) => { - logger.error("DAuthLogin error message : " + m) + logger.error("DAuth error message : " + m) (400, m, emptyMap) } case _ => { - // Are all the necessary DAuthLogin parameters present? - val missingParams: Set[String] = missingDAuthLoginParameters(parameters) + // Are all the necessary DAuth parameters present? + val missingParams: Set[String] = missingDAuthParameters(parameters) missingParams.nonEmpty match { case true => { - val message = ErrorMessages.DAuthLoginMissingParameters + missingParams.mkString(", ") - logger.error("DAuthLogin error message : " + message) + val message = ErrorMessages.DAuthMissingParameters + missingParams.mkString(", ") + logger.error("DAuth error message : " + message) (400, message, emptyMap) } case false => { - logger.debug("DAuthLogin parameters : " + parameters) + logger.debug("DAuth parameters : " + parameters) (200, "", parameters) } } @@ -163,9 +163,9 @@ object DAuthLogin extends RestHelper with MdcLoggable { logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getUserByProviderId(provider = DAuth, idGivenByProvider = username).or { // Find a user + Users.users.vend.getUserByProviderId(provider = DAuthValue, idGivenByProvider = username).or { // Find a user Users.users.vend.createResourceUser( // Otherwise create a new one - provider = DAuth, + provider = DAuthValue, providerId = Some(username), None, name = Some(username), @@ -179,11 +179,11 @@ object DAuthLogin extends RestHelper with MdcLoggable { case Full(u) => Full((u,callContext)) // Return user case Empty => - Failure(ErrorMessages.DAuthLoginCannotGetOrCreateUser) + Failure(ErrorMessages.DAuthCannotGetOrCreateUser) case Failure(msg, t, c) => Failure(msg, t, c) case _ => - Failure(ErrorMessages.DAuthLoginUnknownError) + Failure(ErrorMessages.DAuthUnknownError) } } yield { tuple @@ -194,15 +194,15 @@ object DAuthLogin extends RestHelper with MdcLoggable { logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getOrCreateUserByProviderIdFuture(provider = DAuth, idGivenByProvider = username, consentId = None, name = None, email = None) map { + Users.users.vend.getOrCreateUserByProviderIdFuture(provider = DAuthValue, idGivenByProvider = username, consentId = None, name = None, email = None) map { case (Full(u), _) => Full(u, callContext) // Return user case (Empty, _) => - Failure(ErrorMessages.DAuthLoginCannotGetOrCreateUser) + Failure(ErrorMessages.DAuthCannotGetOrCreateUser) case (Failure(msg, t, c), _) => Failure(msg, t, c) case _ => - Failure(ErrorMessages.DAuthLoginUnknownError) + Failure(ErrorMessages.DAuthUnknownError) } } yield { tuple @@ -225,20 +225,20 @@ object DAuthLogin extends RestHelper with MdcLoggable { Some(true), name = Some(consumerName), appType = None, - description = Some(DAuth), + description = Some(DAuthValue), developerEmail = None, redirectURL = None, createdByUserId = Some(u.userId) ) } - // Return a Map containing the DAuthLogin parameter : token -> value + // Return a Map containing the DAuth parameter : token -> value def getAllParameters(request: Box[Req]): Map[String, String] = { def toMap(parametersList: String) = { - //transform the string "DAuthLogin token="value"" - //to a tuple (DAuthLogin_parameter,Decoded(value)) + //transform the string "DAuth token="value"" + //to a tuple (DAuth_parameter,Decoded(value)) def dynamicListExtract(input: String) = { - val DAuthLoginPossibleParameters = + val DAuthPossibleParameters = List( "token" ) @@ -246,7 +246,7 @@ object DAuthLogin extends RestHelper with MdcLoggable { val split = input.split("=", 2) val parameterValue = split(1).replace("\"", "") //add only OAuth parameters and not empty - if (DAuthLoginPossibleParameters.contains(split(0)) && !parameterValue.isEmpty) + if (DAuthPossibleParameters.contains(split(0)) && !parameterValue.isEmpty) Some(split(0), parameterValue) // return key , value else None @@ -254,8 +254,8 @@ object DAuthLogin extends RestHelper with MdcLoggable { else None } - // We delete the "DAuthLogin" prefix and all the white spaces that may exist in the string - val cleanedParameterList = parametersList.stripPrefix("DAuthLogin").replaceAll("\\s", "") + // We delete the "DAuth" prefix and all the white spaces that may exist in the string + val cleanedParameterList = parametersList.stripPrefix("DAuth").replaceAll("\\s", "") val params = Map(cleanedParameterList.split(",").flatMap(dynamicListExtract _): _*) params } @@ -263,10 +263,10 @@ object DAuthLogin extends RestHelper with MdcLoggable { request match { case Full(a) => a.header("Authorization") match { case Full(header) => { - if (header.contains("DAuthLogin")) + if (header.contains("DAuth")) toMap(header) else - Map("error" -> "Missing DAuthLogin in header!") + Map("error" -> "Missing DAuth in header!") } case _ => Map("error" -> "Missing Authorization header!") } @@ -275,7 +275,7 @@ object DAuthLogin extends RestHelper with MdcLoggable { } // Returns the missing parameters - def missingDAuthLoginParameters(parameters: Map[String, String]): Set[String] = { + def missingDAuthParameters(parameters: Map[String, String]): Set[String] = { ("token" :: List()).toSet diff parameters.keySet } @@ -314,15 +314,15 @@ object DAuthLogin extends RestHelper with MdcLoggable { def getUser : Box[User] = { - val (httpCode, message, parameters) = DAuthLogin.validator(S.request) + val (httpCode, message, parameters) = DAuth.validator(S.request) httpCode match { case 200 => - val payload = DAuthLogin.parseJwt(parameters) + val payload = DAuth.parseJwt(parameters) payload match { case Full(payload) => val username = getFieldFromPayloadJson(payload, "smart_contract_address") logger.debug("username: " + username) - Users.users.vend.getUserByProviderId(provider = DAuth, idGivenByProvider = username) + Users.users.vend.getUserByProviderId(provider = DAuthValue, idGivenByProvider = username) case _ => None } diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 511af54ee..bf686dc7c 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -181,7 +181,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ def hasGatewayHeader(authorization: Box[String]) = hasHeader("GatewayLogin", authorization) - def hasDAuthHeader(authorization: Box[String]) = hasHeader("DAuthLogin", authorization) + def hasDAuthHeader(authorization: Box[String]) = hasHeader("DAuth", authorization) /** * Helper function which tells us does an "Authorization" request header field has the Type of an authentication scheme @@ -2249,7 +2249,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ /** * Defines DAuth Custom Response Header. */ - val DAuthResponseHeaderName = "DAuthLogin" + val DAuthResponseHeaderName = "DAuth" /** * Set value of DAuth Custom Response Header. */ @@ -2263,7 +2263,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case _ => Nil } } - def getDAuthLoginJwt(): Option[String] = { + def getDAuthJwt(): Option[String] = { getDAuthResponseHeader() match { case x :: Nil => Some(x._2) @@ -2735,22 +2735,22 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case _ => Future { (Failure(ErrorMessages.GatewayLoginUnknownError), None) } } - } // DAuthLogin Login + } // DAuth Login else if (getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.authReqHeaderField)) { logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature - val (httpCode, message, parameters) = DAuthLogin.validator(s.request) + val (httpCode, message, parameters) = DAuth.validator(s.request) httpCode match { case 200 => - val payload = DAuthLogin.parseJwt(parameters) + val payload = DAuth.parseJwt(parameters) payload match { case Full(payload) => - DAuthLogin.getOrCreateResourceUserFuture(payload: String, Some(cc)) map { + DAuth.getOrCreateResourceUserFuture(payload: String, Some(cc)) map { case Full((u,callContext)) => // Authentication is successful - val consumer = DAuthLogin.getOrCreateConsumer(payload, u) - val jwt = DAuthLogin.createJwt(payload) - val callContextUpdated = ApiSession.updateCallContext(DAuthLoginResponseHeader(Some(jwt)), callContext) + val consumer = DAuth.getOrCreateConsumer(payload, u) + val jwt = DAuth.createJwt(payload) + val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) (Full(u), callContextUpdated.map(_.copy(consumer=consumer, user = Full(u)))) case Failure(msg, t, c) => (Failure(msg, t, c), None) @@ -2760,19 +2760,19 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case Failure(msg, t, c) => Future { (Failure(msg, t, c), None) } case _ => - Future { (Failure(ErrorMessages.DAuthLoginUnknownError), None) } + Future { (Failure(ErrorMessages.DAuthUnknownError), None) } } case _ => Future { (Failure(message), None) } } case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == false) => // All other addresses will be rejected - Future { (Failure(ErrorMessages.DAuthLoginWhiteListAddresses), None) } + Future { (Failure(ErrorMessages.DAuthWhiteListAddresses), None) } case Empty => - Future { (Failure(ErrorMessages.DAuthLoginHostPropertyMissing), None) } // There is no dauth.host in props file + Future { (Failure(ErrorMessages.DAuthHostPropertyMissing), None) } // There is no dauth.host in props file case Failure(msg, t, c) => Future { (Failure(msg, t, c), None) } case _ => - Future { (Failure(ErrorMessages.DAuthLoginUnknownError), None) } + Future { (Failure(ErrorMessages.DAuthUnknownError), None) } } } else if(Option(cc).flatMap(_.user).isDefined) { diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala index af9e7c08b..889397845 100644 --- a/obp-api/src/main/scala/code/api/util/ApiSession.scala +++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala @@ -5,7 +5,7 @@ import java.util.{Date, UUID} import code.api.JSONFactoryGateway.PayloadOfJwtJSON import code.api.oauth1a.OauthParams._ import code.api.util.APIUtil._ -import code.api.util.AuthenticationType.{Anonymous, DirectLogin, GatewayLogin, DAuthLogin, OAuth2_OIDC, OAuth2_OIDC_FAPI} +import code.api.util.AuthenticationType.{Anonymous, DirectLogin, GatewayLogin, DAuth, OAuth2_OIDC, OAuth2_OIDC_FAPI} import code.api.util.ErrorMessages.{BankAccountNotFound, UserNotLoggedIn} import code.api.util.RateLimitingJson.CallLimit import code.context.UserAuthContextProvider @@ -26,8 +26,8 @@ import scala.collection.immutable.List case class CallContext( gatewayLoginRequestPayload: Option[PayloadOfJwtJSON] = None, //Never update these values inside the case class !!! gatewayLoginResponseHeader: Option[String] = None, - dauthLoginRequestPayload: Option[JSONFactoryDAuth.PayloadOfJwtJSON] = None, //Never update these values inside the case class !!! - dauthLoginResponseHeader: Option[String] = None, + dauthRequestPayload: Option[JSONFactoryDAuth.PayloadOfJwtJSON] = None, //Never update these values inside the case class !!! + dauthResponseHeader: Option[String] = None, spelling: Option[String] = None, user: Box[User] = Empty, consumer: Box[Consumer] = Empty, @@ -141,7 +141,7 @@ case class CallContext( if(hasGatewayHeader(authReqHeaderField)) { GatewayLogin } else if(hasDAuthHeader(authReqHeaderField)) { // DAuth Login - DAuthLogin + DAuth } else if(has2021DirectLoginHeader(requestHeaders)) { // Direct Login DirectLogin } else if(hasDirectLoginHeader(authReqHeaderField)) { // Direct Login Deprecated @@ -166,7 +166,7 @@ object AuthenticationType extends OBPEnumeration[AuthenticationType]{ override def toString: String = "OAuth1.0a" } object GatewayLogin extends AuthenticationType - object DAuthLogin extends AuthenticationType + object DAuth extends AuthenticationType object OAuth2_OIDC extends AuthenticationType object OAuth2_OIDC_FAPI extends AuthenticationType object Anonymous extends AuthenticationType @@ -202,8 +202,8 @@ case class CallContextLight(gatewayLoginRequestPayload: Option[PayloadOfJwtJSON] trait LoginParam case class GatewayLoginRequestPayload(jwtPayload: Option[PayloadOfJwtJSON]) extends LoginParam case class GatewayLoginResponseHeader(jwt: Option[String]) extends LoginParam -case class DAuthLoginRequestPayload(jwtPayload: Option[JSONFactoryDAuth.PayloadOfJwtJSON]) extends LoginParam -case class DAuthLoginResponseHeader(jwt: Option[String]) extends LoginParam +case class DAuthRequestPayload(jwtPayload: Option[JSONFactoryDAuth.PayloadOfJwtJSON]) extends LoginParam +case class DAuthResponseHeader(jwt: Option[String]) extends LoginParam case class Spelling(spelling: Box[String]) @@ -246,9 +246,9 @@ object ApiSession { def updateCallContext(jwt: LoginParam, cnt: Option[CallContext]): Option[CallContext] = { jwt match { - case GatewayLoginRequestPayload(None) | DAuthLoginRequestPayload(None) => + case GatewayLoginRequestPayload(None) | DAuthRequestPayload(None) => cnt - case GatewayLoginResponseHeader(None) | DAuthLoginResponseHeader(None) => + case GatewayLoginResponseHeader(None) | DAuthResponseHeader(None) => cnt case GatewayLoginRequestPayload(Some(jwtPayload)) => cnt match { @@ -264,19 +264,19 @@ object ApiSession { case None => Some(CallContext(gatewayLoginRequestPayload = None, gatewayLoginResponseHeader = Some(j), spelling = None)) } - case DAuthLoginRequestPayload(Some(jwtPayload)) => + case DAuthRequestPayload(Some(jwtPayload)) => cnt match { case Some(v) => - Some(v.copy(dauthLoginRequestPayload = Some(jwtPayload))) + Some(v.copy(dauthRequestPayload = Some(jwtPayload))) case None => - Some(CallContext(dauthLoginRequestPayload = Some(jwtPayload), dauthLoginResponseHeader = None, spelling = None)) + Some(CallContext(dauthRequestPayload = Some(jwtPayload), dauthResponseHeader = None, spelling = None)) } - case DAuthLoginResponseHeader(Some(j)) => + case DAuthResponseHeader(Some(j)) => cnt match { case Some(v) => - Some(v.copy(dauthLoginResponseHeader = Some(j))) + Some(v.copy(dauthResponseHeader = Some(j))) case None => - Some(CallContext(dauthLoginRequestPayload = None, dauthLoginResponseHeader = Some(j), spelling = None)) + Some(CallContext(dauthRequestPayload = None, dauthResponseHeader = Some(j), spelling = None)) } } } diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index a8b878d63..d7b512dfe 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -182,17 +182,12 @@ object ErrorMessages { val UserIsDeleted = "OBP-20064: The user is deleted!" - val DAuthLoginCannotGetOrCreateUser = "OBP-20065: Cannot get or create user during DAuthLogin process." - val DAuthLoginMissingParameters = "OBP-20066: These DAuthLogin parameters are missing: " - val DAuthLoginUnknownError = "OBP-20067: Unknown Gateway login error." - val DAuthLoginHostPropertyMissing = "OBP-20068: Property gateway.host is not defined." - val DAuthLoginWhiteListAddresses = "OBP-20069: Gateway login can be done only from allowed addresses." - val DAuthLoginJwtTokenIsNotValid = "OBP-20070: The JWT is corrupted/changed during a transport." - val DAuthLoginCannotExtractJwtToken = "OBP-20071: Header, Payload and Signature cannot be extracted from the JWT." - val DAuthLoginNoNeedToCallCbs = "OBP-20072: There is no need to call CBS" - val DAuthLoginCannotFindUser = "OBP-20073: User cannot be found. Please initiate CBS communication in order to create it." - val DAuthLoginCannotGetCbsToken = "OBP-20074: Cannot get the CBSToken response from South side" - val DAuthLoginNoJwtForResponse = "OBP-20075: There is no useful value for JWT." + val DAuthCannotGetOrCreateUser = "OBP-20065: Cannot get or create user during DAuth process." + val DAuthMissingParameters = "OBP-20066: These DAuth parameters are missing: " + val DAuthUnknownError = "OBP-20067: Unknown DAuth login error." + val DAuthHostPropertyMissing = "OBP-20068: Property dauth.host is not defined." + val DAuthWhiteListAddresses = "OBP-20069: DAuth login can be done only from allowed addresses." + val DAuthNoJwtForResponse = "OBP-20070: There is no useful value for JWT." val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " From b6f41d6362625b08507e524490c6e7b2159ef4ec Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 2 Nov 2021 13:59:41 +0100 Subject: [PATCH 208/293] feature/added the new login type: DAuth, added the username there- step2 --- obp-api/src/main/scala/code/api/dauth.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index 7c0cc6898..88c2d6fdd 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -194,7 +194,7 @@ object DAuth extends RestHelper with MdcLoggable { logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getOrCreateUserByProviderIdFuture(provider = DAuthValue, idGivenByProvider = username, consentId = None, name = None, email = None) map { + Users.users.vend.getOrCreateUserByProviderIdFuture(provider = DAuthValue, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map { case (Full(u), _) => Full(u, callContext) // Return user case (Empty, _) => From e393ba09ebbfb2eac4f8cf3761041a6d38bb1441 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 2 Nov 2021 17:05:17 +0100 Subject: [PATCH 209/293] feature/added the new login type: tweaked the provide and username- step3 --- obp-api/src/main/scala/code/api/dauth.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index 88c2d6fdd..a8e98ae81 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -64,7 +64,6 @@ object JSONFactoryDAuth { object DAuth extends RestHelper with MdcLoggable { - val DAuthValue = "DAuth" // This value is used for ResourceUser.provider and Consumer.description def createJwt(payloadAsJsonString: String) : String = { val smartContractAddress = getFieldFromPayloadJson(payloadAsJsonString, "smart_contract_address") @@ -103,7 +102,7 @@ object DAuth extends RestHelper with MdcLoggable { Full(compactRender(Extraction.decompose(jwtPayload))) case _ => logger.debug("parseJwt says: Not Full(jwtPayload)") - Failure(ErrorMessages.GatewayLoginJwtTokenIsNotValid) + Failure(ErrorMessages.DAuthJwtTokenIsNotValid) } } @@ -124,7 +123,7 @@ object DAuth extends RestHelper with MdcLoggable { Box(parse(claim.toString).extractOpt[PayloadOfJwtJSON]) case _ => logger.debug("validateJwtToken says: could not verify jwt") - Failure(ErrorMessages.GatewayLoginJwtTokenIsNotValid) + Failure(ErrorMessages.DAuthJwtTokenIsNotValid) } } } @@ -160,12 +159,13 @@ object DAuth extends RestHelper with MdcLoggable { def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + val provider = getFieldFromPayloadJson(jwtPayload, "network_name") logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getUserByProviderId(provider = DAuthValue, idGivenByProvider = username).or { // Find a user + Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = username).or { // Find a user Users.users.vend.createResourceUser( // Otherwise create a new one - provider = DAuthValue, + provider = provider, providerId = Some(username), None, name = Some(username), @@ -191,10 +191,11 @@ object DAuth extends RestHelper with MdcLoggable { } def getOrCreateResourceUserFuture(jwtPayload: String, callContext: Option[CallContext]) : Future[Box[(User, Option[CallContext])]] = { val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + val provider = getFieldFromPayloadJson(jwtPayload, "network_name") logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getOrCreateUserByProviderIdFuture(provider = DAuthValue, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map { + Users.users.vend.getOrCreateUserByProviderIdFuture(provider = provider, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map { case (Full(u), _) => Full(u, callContext) // Return user case (Empty, _) => @@ -212,6 +213,7 @@ object DAuth extends RestHelper with MdcLoggable { def getOrCreateConsumer(jwtPayload: String, u: User) : Box[Consumer] = { val consumerId = getFieldFromPayloadJson(jwtPayload, "consumer_id") val consumerName = getFieldFromPayloadJson(jwtPayload, "msg_sender") + val DAuthValue = "DAuth" // This value is used for Consumer.description logger.debug("app_id: " + consumerId) logger.debug("app_name: " + consumerName) Consumers.consumers.vend.getOrCreateConsumer( @@ -321,8 +323,9 @@ object DAuth extends RestHelper with MdcLoggable { payload match { case Full(payload) => val username = getFieldFromPayloadJson(payload, "smart_contract_address") + val provider = getFieldFromPayloadJson(payload, "network_name") logger.debug("username: " + username) - Users.users.vend.getUserByProviderId(provider = DAuthValue, idGivenByProvider = username) + Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = username) case _ => None } From 4926e58abeb55aeb3039d972ed57189e6c43a769 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 2 Nov 2021 17:05:40 +0100 Subject: [PATCH 210/293] feature/added the new login type: added the dauth tests- step4 --- .../scala/code/api/util/ErrorMessages.scala | 1 + .../src/test/scala/code/api/dauthTest.scala | 109 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 obp-api/src/test/scala/code/api/dauthTest.scala diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index d7b512dfe..6bc843ad5 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -188,6 +188,7 @@ object ErrorMessages { val DAuthHostPropertyMissing = "OBP-20068: Property dauth.host is not defined." val DAuthWhiteListAddresses = "OBP-20069: DAuth login can be done only from allowed addresses." val DAuthNoJwtForResponse = "OBP-20070: There is no useful value for JWT." + val DAuthJwtTokenIsNotValid = "OBP-20071: The JWT is corrupted/changed during a transport." val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " diff --git a/obp-api/src/test/scala/code/api/dauthTest.scala b/obp-api/src/test/scala/code/api/dauthTest.scala new file mode 100644 index 000000000..e775244d1 --- /dev/null +++ b/obp-api/src/test/scala/code/api/dauthTest.scala @@ -0,0 +1,109 @@ +package code.api + +import code.api.util.APIUtil.OAuth._ +import code.api.util.ErrorMessages +import code.setup.{DefaultUsers, PropsReset, ServerSetup} +import org.scalatest._ + +class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with PropsReset{ + + + setPropsValues("allow_dauth_login" -> "true") + setPropsValues("dauth.host" -> "127.0.0.1") + setPropsValues("jwt.token_secret"->"secretsecretsecretstsecretssssss") + + val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*") + /* Payload data. verified by wrong secret "123" -- show : DAuthJwtTokenIsNotValid + { + "smart_contract_address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "network_name": "ETHEREUM", + "msg_sender": "0xe90980927f1725E7734CE288F8367e1Bb143E90fhku767", + "consumer_id": "0x19255a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", + "time_stamp": "2018-08-20T14:13:40Z", + "caller_request_id": "0Xe876987694328763492876348928736497869273649" +} + */ + val invalidSecretJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfaWQiOiIweDE5MjU1YTRlYzMxZTg5Y2VhNTRkMWYxMjVkYjc1MzZlODc0YWI0YTk2YjRkNGY2NDM4NjY4YjZiYjEwYTZhZGIiLCJ0aW1lX3N0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJjYWxsZXJfcmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.5t1bolx13gCBSyvbTzv_QWP1tFkN0m_Sv727bB1QZuw" + + /* Payload data. verified by correct secret "secretsecretsecretstsecretssssss" + { + "smart_contract_address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F05124", + "network_name": "ETHEREUM", + "msg_sender": "0xe90980927f1725E7734CE288F8367e1Bb143E90fhku767", + "consumer_id": "0x19255a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", + "time_stamp": "2018-08-20T14:13:40Z", + "caller_request_id": "0Xe876987694328763492876348928736497869273649" +} + */ + val jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3Z" + + "TFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhG" + + "ODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfaWQiOiIweDE5MjU1YTRlYzMxZTg5Y2VhNTRkMWYxMjVkYjc1MzZlODc0YWI0YTk2YjRkNGY2" + + "NDM4NjY4YjZiYjEwYTZhZGIiLCJ0aW1lX3N0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJjYWxsZXJfcmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5" + + "NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.us2wjYUwiQHYdmU9JBNEMz8rc8qVGzY6bDNeknC3HMo" + + val invalidJwt = ("Authorization", ("DAuth token=%s").format(invalidSecretJwt)) + val validJwt = ("Authorization", ("DAuth token=%s").format(jwt)) + val missingParameterToken = ("Authorization", ("DAuth wrong_parameter_name=%s").format(jwt)) + + def dauthRequest = baseRequest / "obp" / "v2.0.0" / "users" /"current" <@ (user1) + def dauthNonBlockingRequest = baseRequest / "obp" / "v3.0.0" / "users" / "current" <@ (user1) + + feature("DAuth in a BLOCKING way") { + + scenario("Missing parameter token in a blocking way") { + When("We try to login without parameter token in a Header") + val response = makeGetRequest(dauthRequest, List(missingParameterToken)) + Then("We should get a 400 - Bad Request") + logger.debug("-----------------------------------------") + logger.debug(response) + logger.debug("-----------------------------------------") + response.code should equal(400) + response.toString contains (ErrorMessages.DAuthMissingParameters) should be (true) + + When("We try to login with an invalid JWT") + val responseInvalid = makeGetRequest(dauthRequest, List(invalidJwt)) + Then("We should get a 400 - Bad Request") + logger.debug("-----------------------------------------") + logger.debug("responseInvalid response: "+responseInvalid) + logger.debug("-----------------------------------------") + responseInvalid.code should equal(400) + responseInvalid.toString contains (ErrorMessages.DAuthJwtTokenIsNotValid) should be (true) + + When("We try to login with an valid JWT") + val responseValidJwt = makeGetRequest(dauthRequest, List(validJwt)) + logger.debug("-----------------------------------------") + logger.debug("responseValidJwt response: "+responseValidJwt) + logger.debug("-----------------------------------------") + responseValidJwt.code should equal(200) + + When("We try to login without parameter token in a Header") + val responseNonBlocking = makeGetRequest(dauthNonBlockingRequest, List(missingParameterToken)) + Then("We should get a 400 - Bad Request") + logger.debug("-----------------------------------------") + logger.debug("responseNonBlocking: "+ responseNonBlocking) + logger.debug("-----------------------------------------") + responseNonBlocking.code should equal(401) + responseNonBlocking.toString contains (ErrorMessages.DAuthMissingParameters) should be (true) + + When("We try to login with an invalid JWT") + val responseNonBlockingInvalid = makeGetRequest(dauthNonBlockingRequest, List(invalidJwt)) + Then("We should get a 400 - Bad Request") + logger.debug("-----------------------------------------") + logger.debug("responseNonBlockingInvalid responseNonBlocking: "+responseNonBlockingInvalid) + logger.debug("-----------------------------------------") + responseNonBlockingInvalid.code should equal(401) + responseNonBlockingInvalid.toString contains (ErrorMessages.DAuthJwtTokenIsNotValid) should be (true) + + When("We try to login with an valid JWT") + val responseNonBlockingValidJwt = makeGetRequest(dauthNonBlockingRequest, List(validJwt)) + logger.debug("-----------------------------------------") + logger.debug("responseNonBlockingValidJwt responseNonBlocking: "+responseNonBlockingValidJwt) + logger.debug("-----------------------------------------") + responseValidJwt.code should equal(200) + } + + } + + + +} \ No newline at end of file From c3d4193dec71202d9bf53f99568542c185f840c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 2 Nov 2021 17:06:01 +0100 Subject: [PATCH 211/293] feature/OIDC - Show username in casse email is empty --- obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 121b96988..c0439ec23 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -487,9 +487,9 @@ import net.liftweb.util.Helpers._ */ def getCurrentUserUsername: String = { getCurrentUser match { - case Full(user) if user.provider.contains("google") => user.emailAddress - case Full(user) if user.provider.contains("yahoo") => user.emailAddress - case Full(user) if user.provider.contains("microsoft") => user.emailAddress + case Full(user) if user.provider.contains("google") && !user.emailAddress.isEmpty => user.emailAddress + case Full(user) if user.provider.contains("yahoo") && !user.emailAddress.isEmpty => user.emailAddress + case Full(user) if user.provider.contains("microsoft") && !user.emailAddress.isEmpty => user.emailAddress case Full(user) => user.name case _ => "" //TODO need more error handling for different user cases } From 3a965803b56768d4dad135635bb898fd4ccd01d9 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 2 Nov 2021 17:25:11 +0100 Subject: [PATCH 212/293] feature/added the migration code for UserAuthContext Column KeyAndValue length to 4000 --- .../code/api/util/migration/Migration.scala | 13 ++++ ...igrationOfUserAuthContextFieldLength.scala | 63 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfUserAuthContextFieldLength.scala diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index f2d37d31b..0bc5a7c58 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -87,6 +87,7 @@ object Migration extends MdcLoggable { alterColumnNameAtProductFee(startedBeforeSchemifier) addFastFirehoseAccountsView(startedBeforeSchemifier) addFastFirehoseAccountsMaterializedView(startedBeforeSchemifier) + alterUserAuthContextColumnKeyAndValueLength(startedBeforeSchemifier) } private def dummyScript(): Boolean = { @@ -321,6 +322,18 @@ object Migration extends MdcLoggable { } } + private def alterUserAuthContextColumnKeyAndValueLength(startedBeforeSchemifier: Boolean): Boolean = { + if(startedBeforeSchemifier == true) { + logger.warn(s"Migration.database.alterUserAuthContextColumnKeyAndValueLength(true) cannot be run before Schemifier.") + true + } else { + val name = nameOf(alterUserAuthContextColumnKeyAndValueLength(startedBeforeSchemifier)) + runOnce(name) { + MigrationOfUserAuthContextFieldLength.alterColumnKeyAndValueLength(name) + } + } + } + } /** diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfUserAuthContextFieldLength.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfUserAuthContextFieldLength.scala new file mode 100644 index 000000000..d38aa41a1 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfUserAuthContextFieldLength.scala @@ -0,0 +1,63 @@ +package code.api.util.migration + +import java.time.format.DateTimeFormatter +import java.time.{ZoneId, ZonedDateTime} +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.context.MappedUserAuthContext +import net.liftweb.common.Full +import net.liftweb.mapper.{DB, Schemifier} +import net.liftweb.util.DefaultConnectionIdentifier + +object MigrationOfUserAuthContextFieldLength { + + val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1) + val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'") + + def alterColumnKeyAndValueLength(name: String): Boolean = { + DbFunction.tableExists(MappedUserAuthContext, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + var isSuccessful = false + + val executedSql = + DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) { + APIUtil.getPropsValue("db.driver") match { + case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") => + () => + """ + |ALTER TABLE MappedUserAuthContext ALTER COLUMN mKey varchar(4000); + |ALTER TABLE MappedUserAuthContext ALTER COLUMN mValue varchar(4000); + |""".stripMargin + case _ => + () => + """ + |ALTER TABLE MappedUserAuthContext ALTER COLUMN mKey type varchar(4000); + |ALTER TABLE MappedUserAuthContext ALTER COLUMN mValue type varchar(4000); + |""".stripMargin + } + } + + val endDate = System.currentTimeMillis() + val comment: String = + s"""Executed SQL: + |$executedSql + |""".stripMargin + isSuccessful = true + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""${MappedUserAuthContext._dbTableNameLC} table does not exist""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } +} \ No newline at end of file From 7452cde75e2d17a259c6fefe922a31fb65ed15a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 3 Nov 2021 16:48:57 +0100 Subject: [PATCH 213/293] feature/Add endpoint createHistoricalTransactionAtBank v4.0.0 --- .../SwaggerDefinitionsJSON.scala | 14 +- .../main/scala/code/api/util/ApiRole.scala | 3 + .../scala/code/api/v4_0_0/APIMethods400.scala | 155 ++++++++++++++++++ .../code/api/v4_0_0/JSONFactory4.0.0.scala | 59 ++++++- 4 files changed, 229 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 7fb68a87c..fd0d420d4 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1,6 +1,7 @@ package code.api.ResourceDocs1_4_0 import java.util.Date + import code.api.Constant._ import code.api.Constant import code.api.UKOpenBanking.v2_0_0.JSONFactory_UKOpenBanking_200 @@ -15,7 +16,7 @@ import code.api.v3_0_0.JSONFactory300.createBranchJsonV300 import code.api.v3_0_0.custom.JSONFactoryCustom300 import code.api.v3_0_0.{LobbyJsonV330, _} import code.api.v3_1_0.{AccountBalanceV310, AccountsBalancesV310Json, BadLoginStatusJson, ContactDetailsJson, CustomerWithAttributesJsonV310, InviteeJson, ObpApiLoopbackJson, PhysicalCardWithAttributesJsonV310, PutUpdateCustomerEmailJsonV310, _} -import code.api.v4_0_0.{BankAttributeBankResponseJsonV400, FastFirehoseAccountsJsonV400, _} +import code.api.v4_0_0.{BankAttributeBankResponseJsonV400, FastFirehoseAccountsJsonV400, PostHistoricalTransactionAtBankJson, _} import code.api.v3_1_0.{AccountBalanceV310, AccountsBalancesV310Json, BadLoginStatusJson, ContactDetailsJson, InviteeJson, ObpApiLoopbackJson, PhysicalCardWithAttributesJsonV310, PutUpdateCustomerEmailJsonV310, _} import code.branches.Branches.{Branch, DriveUpString, LobbyString} import code.consent.ConsentStatus @@ -33,6 +34,7 @@ import com.openbankproject.commons.model.{UserAuthContextUpdateStatus, ViewBasic import com.openbankproject.commons.util.{ApiVersion, FieldNameApiVersions, ReflectUtils, RequiredArgs, RequiredInfo} import net.liftweb.json import java.net.URLEncoder + import code.endpointMapping.EndpointMappingCommons import scala.collection.immutable.List @@ -3874,6 +3876,16 @@ object SwaggerDefinitionsJSON { completed= DateWithSecondsExampleString, `type`= SANDBOX_TAN.toString, charge_policy= "SHARED" + ) + val postHistoricalTransactionAtBankJson = PostHistoricalTransactionAtBankJson( + from_account_id = "", + to_account_id = "", + value = amountOfMoneyJsonV121, + description = "this is for work", + posted = DateWithSecondsExampleString, + completed= DateWithSecondsExampleString, + `type`= SANDBOX_TAN.toString, + charge_policy= "SHARED" ) val postHistoricalTransactionResponseJson = PostHistoricalTransactionResponseJson( diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 1becd2472..2dc44a533 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -821,6 +821,9 @@ object ApiRole { case class CanGetBankLevelEndpointTag(requiresBankId: Boolean = true) extends ApiRole lazy val canGetBankLevelEndpointTag = CanGetBankLevelEndpointTag() + case class CanCreateHistoricalTransactionAtBank(requiresBankId: Boolean = true) extends ApiRole + lazy val canCreateHistoricalTransactionAtBank = CanCreateHistoricalTransactionAtBank() + private val dynamicApiRoles = new ConcurrentHashMap[String, ApiRole] private case class DynamicApiRole(role: String, requiresBankId: Boolean = false) extends ApiRole{ diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index ef83826cc..4c61c0ed2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -79,6 +79,7 @@ import net.liftweb.util.{Helpers, Mailer, StringHelpers} import org.apache.commons.collections4.CollectionUtils import org.apache.commons.lang3.StringUtils import java.net.URLEncoder +import java.text.SimpleDateFormat import java.util.{Calendar, Date} import scala.collection.immutable.{List, Nil} @@ -4714,6 +4715,160 @@ trait APIMethods400 { } } + staticResourceDocs += ResourceDoc( + createHistoricalTransactionAtBank, + implementedInApiVersion, + nameOf(createHistoricalTransactionAtBank), + "POST", + "/banks/BANK_ID/management/historical/transactions", + "Create Historical Transactions ", + s""" + |Import the historical transactions. + | + |The fields bank_id, account_id, counterparty_id in the json body are all optional ones. + |It support transfer money from account to account, account to counterparty and counterparty to counterparty + |Both bank_id + account_id and counterparty_id can identify the account, so OBP only need one of them to make the payment. + |So: + |When you need the account to account, just omit counterparty_id field.eg: + |{ + | "from": { + | "bank_id": "gh.29.uk", + | "account_id": "1ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + | }, + | "to": { + | "bank_id": "gh.29.uk", + | "account_id": "2ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + | }, + | "value": { + | "currency": "GBP", + | "amount": "10" + | }, + | "description": "this is for work", + | "posted": "2017-09-19T02:31:05Z", + | "completed": "2017-09-19T02:31:05Z", + | "type": "SANDBOX_TAN", + | "charge_policy": "SHARED" + |} + | + |When you need the counterparty to counterparty, need to omit bank_id and account_id field.eg: + |{ + | "from": { + | "counterparty_id": "f6392b7d-4218-45ea-b9a7-eaa71c0202f9" + | }, + | "to": { + | "counterparty_id": "26392b7d-4218-45ea-b9a7-eaa71c0202f9" + | }, + | "value": { + | "currency": "GBP", + | "amount": "10" + | }, + | "description": "this is for work", + | "posted": "2017-09-19T02:31:05Z", + | "completed": "2017-09-19T02:31:05Z", + | "type": "SANDBOX_TAN", + | "charge_policy": "SHARED" + |} + | + |or, you can counterparty to account + |{ + | "from": { + | "counterparty_id": "f6392b7d-4218-45ea-b9a7-eaa71c0202f9" + | }, + | "to": { + | "bank_id": "gh.29.uk", + | "account_id": "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + | }, + | "value": { + | "currency": "GBP", + | "amount": "10" + | }, + | "description": "this is for work", + | "posted": "2017-09-19T02:31:05Z", + | "completed": "2017-09-19T02:31:05Z", + | "type": "SANDBOX_TAN", + | "charge_policy": "SHARED" + |} + | + |This call is experimental. + """.stripMargin, + postHistoricalTransactionAtBankJson, + postHistoricalTransactionResponseJson, + List( + InvalidJsonFormat, + BankNotFound, + AccountNotFound, + CounterpartyNotFoundByCounterpartyId, + InvalidNumber, + NotPositiveAmount, + InvalidTransactionRequestCurrency, + UnknownError + ), + List(apiTagTransactionRequest, apiTagNewStyle), + Some(List(canCreateHistoricalTransactionAtBank)) + ) + + + lazy val createHistoricalTransactionAtBank : OBPEndpoint = { + case "banks" :: BankId(bankId) :: "management" :: "historical" :: "transactions" :: Nil JsonPost json -> _ => { + cc => + for { + (Full(u), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement(bankId.value, u.userId, ApiRole.canCreateHistoricalTransactionAtBank, callContext) + + // Check the input JSON format, here is just check the common parts of all four types + transDetailsJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $PostHistoricalTransactionJson ", 400, callContext) { + json.extract[PostHistoricalTransactionAtBankJson] + } + (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, AccountId(transDetailsJson.from_account_id), callContext) + (toAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, AccountId(transDetailsJson.to_account_id), callContext) + amountNumber <- NewStyle.function.tryons(s"$InvalidNumber Current input is ${transDetailsJson.value.amount} ", 400, callContext) { + BigDecimal(transDetailsJson.value.amount) + } + _ <- Helper.booleanToFuture(s"${NotPositiveAmount} Current input is: '${amountNumber}'", cc=callContext) { + amountNumber > BigDecimal("0") + } + posted <- NewStyle.function.tryons(s"$InvalidDateFormat Current `posted` field is ${transDetailsJson.posted}. Please use this format ${DateWithSecondsFormat.toPattern}! ", 400, callContext) { + new SimpleDateFormat(DateWithSeconds).parse(transDetailsJson.posted) + } + completed <- NewStyle.function.tryons(s"$InvalidDateFormat Current `completed` field is ${transDetailsJson.completed}. Please use this format ${DateWithSecondsFormat.toPattern}! ", 400, callContext) { + new SimpleDateFormat(DateWithSeconds).parse(transDetailsJson.completed) + } + // Prevent default value for transaction request type (at least). + _ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${transDetailsJson.value.currency}'", cc=callContext) { + isValidCurrencyISOCode(transDetailsJson.value.currency) + } + amountOfMoneyJson = AmountOfMoneyJsonV121(transDetailsJson.value.currency, transDetailsJson.value.amount) + chargePolicy = transDetailsJson.charge_policy + //There is no constraint for the type at the moment + transactionType = transDetailsJson.`type` + (transactionId, callContext) <- NewStyle.function.makeHistoricalPayment( + fromAccount, + toAccount, + posted, + completed, + amountNumber, + transDetailsJson.value.currency, + transDetailsJson.description, + transactionType, + chargePolicy, + callContext + ) + } yield { + (JSONFactory400.createPostHistoricalTransactionResponseJson( + bankId, + transactionId, + fromAccount.accountId, + toAccount.accountId, + value= amountOfMoneyJson, + description = transDetailsJson.description, + posted, + completed, + transactionRequestType = transactionType, + chargePolicy =transDetailsJson.charge_policy), HttpCode.`201`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( getTransactionRequest, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 90ef594fd..0c54094a0 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -42,7 +42,7 @@ import code.api.v2_2_0.CounterpartyMetadataJson import code.api.v3_0_0.JSONFactory300._ import code.api.v3_0_0._ import code.api.v3_1_0.JSONFactory310.{createAccountAttributeJson, createProductAttributesJson} -import code.api.v3_1_0.{AccountAttributeResponseJson, ProductAttributeResponseWithoutBankIdJson, RedisCallLimitJson} +import code.api.v3_1_0.{AccountAttributeResponseJson, PostHistoricalTransactionResponseJson, ProductAttributeResponseWithoutBankIdJson, RedisCallLimitJson} import code.apicollection.ApiCollectionTrait import code.apicollectionendpoint.ApiCollectionEndpointTrait import code.atms.Atms.Atm @@ -128,6 +128,31 @@ case class TransactionRequestWithChargeJSON400( challenges: List[ChallengeJsonV400], charge : TransactionRequestChargeJsonV200 ) +case class PostHistoricalTransactionAtBankJson( + from_account_id: String, + to_account_id: String, + value: AmountOfMoneyJsonV121, + description: String, + posted: String, + completed: String, + `type`: String, + charge_policy: String + ) +case class HistoricalTransactionAccountJsonV400( + bank_id: String, + account_id : String + ) +case class PostHistoricalTransactionResponseJsonV400( + transaction_id: String, + from: HistoricalTransactionAccountJsonV400, + to: HistoricalTransactionAccountJsonV400, + value: AmountOfMoneyJsonV121, + description: String, + posted: Date, + completed: Date, + transaction_request_type: String, + charge_policy: String + ) case class PostResetPasswordUrlJsonV400(username: String, email: String, user_id: String) case class ResetPasswordUrlJsonV400(reset_password_url: String) @@ -1730,5 +1755,37 @@ object JSONFactory400 { )))) ) } + + + + def createPostHistoricalTransactionResponseJson( + bankId: BankId, + transactionId: TransactionId, + fromAccountId: AccountId, + toAccountId: AccountId, + value: AmountOfMoneyJsonV121, + description: String, + posted: Date, + completed: Date, + transactionRequestType: String, + chargePolicy: String + ) : PostHistoricalTransactionResponseJsonV400 = { + PostHistoricalTransactionResponseJsonV400( + transaction_id = transactionId.value, + from = HistoricalTransactionAccountJsonV400(bankId.value, fromAccountId.value), + to = HistoricalTransactionAccountJsonV400(bankId.value, toAccountId.value), + value: AmountOfMoneyJsonV121, + description: String, + posted: Date, + completed: Date, + transaction_request_type = transactionRequestType, + chargePolicy: String + ) + } + + + + + } From 52be51366833fa61eac19037886d4310ef36269e Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 4 Nov 2021 11:51:46 +0100 Subject: [PATCH 214/293] feature/rename allow_dauth_login -> allow_dauth --- obp-api/src/main/resources/props/sample.props.template | 2 +- obp-api/src/main/scala/code/api/OBPRestHelper.scala | 4 ++-- obp-api/src/main/scala/code/api/util/APIUtil.scala | 4 ++-- obp-api/src/test/scala/code/api/dauthTest.scala | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 54ef0d035..0232830a4 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -693,7 +693,7 @@ autocomplete_at_login_form_enabled=false # -- DAuth login -------------------------------------- # Enable/Disable DAuth communication at all # In case isn't defined default value is false -# allow_dauth_login=false +# allow_dauth=false # Define comma separated list of allowed IP addresses # dauth.host=127.0.0.1 diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 6475ae593..475374a55 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -402,8 +402,8 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { Failure(ErrorMessages.GatewayLoginUnknownError) } } - else if (APIUtil.getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(authorization)) { - logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) + else if (APIUtil.getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(authorization)) { + logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val s = S diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index bf686dc7c..05daae483 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2736,8 +2736,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ Future { (Failure(ErrorMessages.GatewayLoginUnknownError), None) } } } // DAuth Login - else if (getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.authReqHeaderField)) { - logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) + else if (getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.authReqHeaderField)) { + logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val (httpCode, message, parameters) = DAuth.validator(s.request) diff --git a/obp-api/src/test/scala/code/api/dauthTest.scala b/obp-api/src/test/scala/code/api/dauthTest.scala index e775244d1..cacd5d30b 100644 --- a/obp-api/src/test/scala/code/api/dauthTest.scala +++ b/obp-api/src/test/scala/code/api/dauthTest.scala @@ -8,7 +8,7 @@ import org.scalatest._ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with PropsReset{ - setPropsValues("allow_dauth_login" -> "true") + setPropsValues("allow_dauth" -> "true") setPropsValues("dauth.host" -> "127.0.0.1") setPropsValues("jwt.token_secret"->"secretsecretsecretstsecretssssss") From 5768a46f0ff7ad956bb4b8c386fe29d7572f7374 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 4 Nov 2021 13:29:06 +0100 Subject: [PATCH 215/293] docfix/added the dauth to Glossary --- .../resources/props/sample.props.template | 6 +- .../main/scala/code/api/OBPRestHelper.scala | 1 - .../main/scala/code/api/util/Glossary.scala | 192 +++++++++++++++++- 3 files changed, 188 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 0232830a4..074f4f42f 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -680,7 +680,7 @@ autocomplete_at_login_form_enabled=false # -- Gateway And DAuth common Setting-------------------------------------- # Define secret used to validate JWT token -# jwt.token_secret=secretsecretsecretstsecretssssss +# jwt.token_secret=your-at-least-256-bit-secret-token # -- Gateway login -------------------------------------- # Enable/Disable Gateway communication at all @@ -690,14 +690,14 @@ autocomplete_at_login_form_enabled=false # gateway.host=127.0.0.1 -# -- DAuth login -------------------------------------- +# -- DAuth -------------------------------------- # Enable/Disable DAuth communication at all # In case isn't defined default value is false # allow_dauth=false # Define comma separated list of allowed IP addresses # dauth.host=127.0.0.1 -# -------------------------------------- DAuth login -- +# -------------------------------------- DAuth-- # Disable akka (Remote storage not possible) diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 475374a55..29900da1f 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -417,7 +417,6 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { DAuth.getOrCreateResourceUser(payload: String, Some(cc)) match { case Full((u, callContext)) => // Authentication is successful val consumer = DAuth.getOrCreateConsumer(payload, u) - setGatewayResponseHeader(s) {DAuth.createJwt(payload)} val jwt = DAuth.createJwt(payload) val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) fn(callContextUpdated.map( callContext =>callContext.copy(user = Full(u), consumer = consumer)).getOrElse(callContext.getOrElse(cc).copy(user = Full(u), consumer = consumer))) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 4f4a54e21..a3663dd02 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -1844,7 +1844,7 @@ object Glossary extends MdcLoggable { |# Define comma separated list of allowed IP addresses |# gateway.host=127.0.0.1 |# Define secret used to validate JWT token -|# jwt.token_secret=secret +|# jwt.token_secret=your-at-least-256-bit-secret-token |# -------------------------------------- Gateway login -- |``` |Please keep in mind that property jwt.token_secret is used to validate JWT token to check it is not changed or corrupted during transport. @@ -1881,15 +1881,15 @@ object Glossary extends MdcLoggable { | base64UrlEncode(header) + "." + | base64UrlEncode(payload), | -|) secret +|) your-at-least-256-bit-secret-token |``` | |Here is the above example token: | |``` |eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. -|AS8D76F7A89S87D6F7A9SD876FA789SD78F6A7S9D78F6AS79DF87A6S7D9F7A6S7D9F78A6SD798F78679D786S789D78F6A7S9D78F6AS79DF876A7S89DF786AS9D87F69AS7D6FN1bWVyIn0. -|KEuvjv3dmwkOhQ3JJ6dIShK8CG_fd2REApOGn1TRmgU +|eyJsb2dpbl91c2VyX25hbWUiOiJ1c2VybmFtZSIsImlzX2ZpcnN0IjpmYWxzZSwiYXBwX2lkIjoiODVhOTY1ZjAtMGQ1NS00ZTBhLThiMWMtNjQ5YzRiMDFjNGZiIiwiYXBwX25hbWUiOiJHV0wiLCJ0aW1lX3N0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJjYnNfdG9rZW4iOiJ5b3VyX3Rva2VuIiwiY2JzX2lkIjoieW91cl9jYnNfaWQiLCJzZXNzaW9uX2lkIjoiMTIzNDU2Nzg5In0. +|bfWGWttEEcftiqrb71mE6Xy1tT_I-gmDPgjzvn6kC_k |``` | | @@ -1924,8 +1924,8 @@ object Glossary extends MdcLoggable { | |``` |curl -v -H 'Authorization: GatewayLogin token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. -|AS8D76F7A89S87D6F7A9SD876FA789SD78F6A7S9D78F6AS79DF87A6S7D9F7A6S7D9F78A6SD798F78679D786S789D78F6A7S9D78F6AS79DF876A7S89DF786AS9D87F69AS7D6FN1bWVyIn0. -|KEuvjv3dmwkOhQ3JJ6dIShK8CG_fd2REApOGn1TRmgU" $getServerUrl/obp/v3.0.0/users/current +|eyJsb2dpbl91c2VyX25hbWUiOiJ1c2VybmFtZSIsImlzX2ZpcnN0IjpmYWxzZSwiYXBwX2lkIjoiODVhOTY1ZjAtMGQ1NS00ZTBhLThiMWMtNjQ5YzRiMDFjNGZiIiwiYXBwX25hbWUiOiJHV0wiLCJ0aW1lX3N0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJjYnNfdG9rZW4iOiJ5b3VyX3Rva2VuIiwiY2JzX2lkIjoieW91cl9jYnNfaWQiLCJzZXNzaW9uX2lkIjoiMTIzNDU2Nzg5In0. +|bfWGWttEEcftiqrb71mE6Xy1tT_I-gmDPgjzvn6kC_k"' $getServerUrl/obp/v3.0.0/users/current |``` | | @@ -1980,7 +1980,7 @@ object Glossary extends MdcLoggable { |} | | -|token = jwt.encode(payload, 'secretsecretsecretstsecretssssss', algorithm='HS256') +|token = jwt.encode(payload, 'your-at-least-256-bit-secret-token', algorithm='HS256').decode("utf-8") |authorization = 'GatewayLogin token="{}"'.format(token) |headers = {'Authorization': authorization} |url = obp_api_host + '/obp/v4.0.0/users/current' @@ -2016,6 +2016,184 @@ object Glossary extends MdcLoggable { """) + val dauthEnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_gateway_login", false)) + {"Note: DAuth is enabled."} else {"Note: *DAuth is NOT enabled on this instance!*"} + + + glossaryItems += GlossaryItem( + title = "DAuth", + description = + s""" + |### Introduction +| +|$dauthEnabledMessage +| +|DAuth Authorisation is made by including a specific header (see step 3 below) in any OBP REST call. +| +|Note: DAuth does *not* require an explicit POST like Direct Login to create the token. +| +|The **Gateway is responsible** for creating a token which is trusted by OBP **absolutely**! +| +|When OBP receives a token via DAuth, OBP creates or gets a user based on the username (smart_contract_address) supplied. +| +|To use DAuth: +| +|### 1) Configure OBP API to accept DAuth. +| +|Set up properties in a props file +| +|``` +|# -- DAuth -------------------------------------- +|# Define secret used to validate JWT token +|# jwt.token_secret=your-at-least-256-bit-secret-token +|# Enable/Disable DAuth communication at all +|# In case isn't defined default value is false +|# allow_dauth=false +|# Define comma separated list of allowed IP addresses +|# dauth.host=127.0.0.1 +|# -------------------------------------- DAuth-- +|``` +|Please keep in mind that property jwt.token_secret is used to validate JWT token to check it is not changed or corrupted during transport. +| +|### 2) Create / have access to a JWT +| +| +| +|HEADER:ALGORITHM & TOKEN TYPE +| +|``` +|{ +| "alg": "HS256", +| "typ": "JWT" +|} +|``` +|PAYLOAD:DATA +| +|``` +|{ +| "smart_contract_address": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", +| "network_name": "ETHEREUM", +| "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", +| "consumer_id": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", +| "time_stamp": "2021-11-04T14:13:40Z", +| "caller_request_id": "0Xe876987694328763492876348928736497869273649" +|} +|``` +|VERIFY SIGNATURE +|``` +|HMACSHA256( +| base64UrlEncode(header) + "." + +| base64UrlEncode(payload), +| +|) your-at-least-256-bit-secret-token +|``` +| +|Here is the above example token: +| +|``` +|eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. +|eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9pZCI6IjB4MTIzNGE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZV9zdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwiY2FsbGVyX3JlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ. +|SbgXzyRNd6uLBYql_fwXi3KAWS8SaKYMHmnVFgbGRiY +|``` +| +| +| +|### 3) Try a REST call using the header +| +| +|Using your favorite http client: +| +| GET $getServerUrl/obp/v3.0.0/users/current +| +|Body +| +| Leave Empty! +| +| +|Headers: +| +| Authorization: DAuth token="your-jwt-from-step-above" +| +|Here is it all together: +| +| GET $getServerUrl/obp/v3.0.0/users/current HTTP/1.1 +| Host: localhost:8080 +| User-Agent: curl/7.47.0 +| Accept: */* +| Authorization: GatewayLogin token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9pZCI6IjB4MTIzNGE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZV9zdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwiY2FsbGVyX3JlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ.SbgXzyRNd6uLBYql_fwXi3KAWS8SaKYMHmnVFgbGRiY" +| +|CURL example +| +|``` +|curl -v -H 'Authorization: DAuth token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9pZCI6IjB4MTIzNGE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZV9zdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwiY2FsbGVyX3JlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ.SbgXzyRNd6uLBYql_fwXi3KAWS8SaKYMHmnVFgbGRiY"' $getServerUrl/obp/v3.0.0/users/current +|``` +| +| +|You should receive a response like: +| +|``` +|{ +| "user_id": "4c4d3175-1e5c-4cfd-9b08-dcdc209d8221", +| "email": "", +| "provider_id": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", +| "provider": "ETHEREUM", +| "username": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", +| "entitlements": { +| "list": [] +| } +|} +|``` +| +|### Example python script +|``` +|import jwt +|from datetime import datetime, timezone +|import requests +| +|env = 'local' +|DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' +| +|obp_api_host = '$getServerUrl' +|payload = { +| "smart_contract_address": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", +| "network_name": "ETHEREUM", +| "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", +| "consumer_id": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", +| "time_stamp": datetime.now(timezone.utc).strftime(DATE_FORMAT), +| "caller_request_id": "0Xe876987694328763492876348928736497869273649" +|} +| +|token = jwt.encode(payload, 'your-at-least-256-bit-secret-token', algorithm='HS256').decode("utf-8") +|authorization = 'DAuth token="{}"'.format(token) +|headers = {'Authorization': authorization} +|url = obp_api_host + '/obp/v4.0.0/users/current' +|req = requests.get(url, headers=headers) +|print(req.text) +|``` +| +|### Under the hood +| +|The file, dauth.scala handles the DAuth, +| +|We: +| +|``` +|-> Check if Props allow_dauth is true +| -> Check if DAuth header exists +| -> Check if getRemoteIpAddress is OK +| -> Look for "token" +| -> parse the JWT token and getOrCreate the user +| -> get the data of the user +|``` +| +|### More information +| +| Parameter names and values are case sensitive. +| Each parameter MUST NOT appear more than once per request. +| + """) + + glossaryItems += GlossaryItem( title = "SCA (Strong Customer Authentication)", From 6131ded99a173146b6c83f8cef89de5c9ed9891d Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 4 Nov 2021 14:02:10 +0100 Subject: [PATCH 216/293] feature/fixed the failed tests --- obp-api/src/test/scala/code/api/dauthTest.scala | 7 +------ obp-api/src/test/scala/code/setup/ServerSetup.scala | 3 +++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/obp-api/src/test/scala/code/api/dauthTest.scala b/obp-api/src/test/scala/code/api/dauthTest.scala index cacd5d30b..3d990fa29 100644 --- a/obp-api/src/test/scala/code/api/dauthTest.scala +++ b/obp-api/src/test/scala/code/api/dauthTest.scala @@ -6,11 +6,6 @@ import code.setup.{DefaultUsers, PropsReset, ServerSetup} import org.scalatest._ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with PropsReset{ - - - setPropsValues("allow_dauth" -> "true") - setPropsValues("dauth.host" -> "127.0.0.1") - setPropsValues("jwt.token_secret"->"secretsecretsecretstsecretssssss") val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*") /* Payload data. verified by wrong secret "123" -- show : DAuthJwtTokenIsNotValid @@ -48,7 +43,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P def dauthRequest = baseRequest / "obp" / "v2.0.0" / "users" /"current" <@ (user1) def dauthNonBlockingRequest = baseRequest / "obp" / "v3.0.0" / "users" / "current" <@ (user1) - feature("DAuth in a BLOCKING way") { + feature("DAuth Testing") { scenario("Missing parameter token in a blocking way") { When("We try to login without parameter token in a Header") diff --git a/obp-api/src/test/scala/code/setup/ServerSetup.scala b/obp-api/src/test/scala/code/setup/ServerSetup.scala index 4dcff76d5..55b45f2a9 100644 --- a/obp-api/src/test/scala/code/setup/ServerSetup.scala +++ b/obp-api/src/test/scala/code/setup/ServerSetup.scala @@ -45,6 +45,9 @@ trait ServerSetup extends FeatureSpec with SendServerRequests setPropsValues("migration_scripts.execute_all" -> "true") setPropsValues("migration_scripts.execute" -> "true") + setPropsValues("allow_dauth" -> "true") + setPropsValues("dauth.host" -> "127.0.0.1") + setPropsValues("jwt.token_secret"->"secretsecretsecretstsecretssssss") val server = TestServer def baseRequest = host(server.host, server.port) From 697c6aef947397fc0ca39ab3d287175ca42b47bc Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 5 Nov 2021 15:41:55 +0100 Subject: [PATCH 217/293] feature/tweaked the DAuth.PayloadOfJwtJSON class --- .../main/scala/code/api/OBPRestHelper.scala | 2 +- obp-api/src/main/scala/code/api/dauth.scala | 51 ++++++------------- .../main/scala/code/api/util/APIUtil.scala | 2 +- .../scala/code/api/util/ErrorMessages.scala | 4 +- .../main/scala/code/api/util/Glossary.scala | 8 +-- .../src/test/scala/code/api/dauthTest.scala | 22 ++++---- .../test/scala/code/setup/ServerSetup.scala | 2 +- 7 files changed, 33 insertions(+), 58 deletions(-) diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 29900da1f..5e169c317 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -416,7 +416,7 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { val s = S DAuth.getOrCreateResourceUser(payload: String, Some(cc)) match { case Full((u, callContext)) => // Authentication is successful - val consumer = DAuth.getOrCreateConsumer(payload, u) + val consumer = DAuth.getConsumerByConsumerKey(payload)//TODO, need to verify the key later. val jwt = DAuth.createJwt(payload) val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) fn(callContextUpdated.map( callContext =>callContext.copy(user = Full(u), consumer = consumer)).getOrElse(callContext.getOrElse(cc).copy(user = Full(u), consumer = consumer))) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index a8e98ae81..6ec0efd00 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -33,13 +33,11 @@ import code.model.{Consumer, UserX} import code.users.Users import code.util.Helper.MdcLoggable import com.nimbusds.jwt.JWTClaimsSet -import com.openbankproject.commons.model.{User} +import com.openbankproject.commons.model.User import net.liftweb.common._ import net.liftweb.http._ import net.liftweb.http.rest.RestHelper import net.liftweb.json._ -import net.liftweb.util.Helpers - import com.openbankproject.commons.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -54,10 +52,10 @@ object JSONFactoryDAuth { case class PayloadOfJwtJSON( smart_contract_address: String, network_name: String, - msg_sender: String, - consumer_id: String, - time_stamp: String, - caller_request_id: String + consumer_key: String, + timestamp: Option[String], + msg_sender: Option[String], + request_id: Option[String] ) } @@ -69,17 +67,17 @@ object DAuth extends RestHelper with MdcLoggable { val smartContractAddress = getFieldFromPayloadJson(payloadAsJsonString, "smart_contract_address") val networkName = getFieldFromPayloadJson(payloadAsJsonString, "network_name") val msgSender = getFieldFromPayloadJson(payloadAsJsonString, "msg_sender") - val consumerId = getFieldFromPayloadJson(payloadAsJsonString, "consumer_id") - val timeStamp = getFieldFromPayloadJson(payloadAsJsonString, "time_stamp") - val callerRequestId = getFieldFromPayloadJson(payloadAsJsonString, "caller_request_id") + val consumerKey = getFieldFromPayloadJson(payloadAsJsonString, "consumer_key") + val timeStamp = getFieldFromPayloadJson(payloadAsJsonString, "timestamp") + val requestId = getFieldFromPayloadJson(payloadAsJsonString, "request_id") val json = JSONFactoryDAuth.PayloadOfJwtJSON( smart_contract_address = smartContractAddress, network_name = networkName, - msg_sender = msgSender, - consumer_id = consumerId, - time_stamp = timeStamp, - caller_request_id = callerRequestId + consumer_key = consumerKey, + msg_sender = Some(msgSender), + timestamp = Some(timeStamp), + request_id = Some(requestId) ) val jwtPayloadAsJson = compactRender(Extraction.decompose(json)) val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson) @@ -210,28 +208,9 @@ object DAuth extends RestHelper with MdcLoggable { } } - def getOrCreateConsumer(jwtPayload: String, u: User) : Box[Consumer] = { - val consumerId = getFieldFromPayloadJson(jwtPayload, "consumer_id") - val consumerName = getFieldFromPayloadJson(jwtPayload, "msg_sender") - val DAuthValue = "DAuth" // This value is used for Consumer.description - logger.debug("app_id: " + consumerId) - logger.debug("app_name: " + consumerName) - Consumers.consumers.vend.getOrCreateConsumer( - consumerId=Some(consumerId), - Some(Helpers.randomString(40).toLowerCase), - Some(Helpers.randomString(40).toLowerCase), - None, - None, - None, - None, - Some(true), - name = Some(consumerName), - appType = None, - description = Some(DAuthValue), - developerEmail = None, - redirectURL = None, - createdByUserId = Some(u.userId) - ) + def getConsumerByConsumerKey(jwtPayload: String) : Box[Consumer] = { + val consumeyKey = getFieldFromPayloadJson(jwtPayload, "consumer_key") + Consumers.consumers.vend.getConsumerByConsumerKey(consumeyKey) } // Return a Map containing the DAuth parameter : token -> value diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 05daae483..025a128ab 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2748,7 +2748,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case Full(payload) => DAuth.getOrCreateResourceUserFuture(payload: String, Some(cc)) map { case Full((u,callContext)) => // Authentication is successful - val consumer = DAuth.getOrCreateConsumer(payload, u) + val consumer = DAuth.getConsumerByConsumerKey(payload) val jwt = DAuth.createJwt(payload) val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) (Full(u), callContextUpdated.map(_.copy(consumer=consumer, user = Full(u)))) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 6bc843ad5..eb645a3ad 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -154,7 +154,7 @@ object ErrorMessages { val GatewayLoginUnknownError = "OBP-20029: Unknown Gateway login error." val GatewayLoginHostPropertyMissing = "OBP-20030: Property gateway.host is not defined." val GatewayLoginWhiteListAddresses = "OBP-20031: Gateway login can be done only from allowed addresses." - val GatewayLoginJwtTokenIsNotValid = "OBP-20040: The JWT is corrupted/changed during a transport." + val GatewayLoginJwtTokenIsNotValid = "OBP-20040: The Gateway login JWT is corrupted/changed during a transport." val GatewayLoginCannotExtractJwtToken = "OBP-20041: Header, Payload and Signature cannot be extracted from the JWT." val GatewayLoginNoNeedToCallCbs = "OBP-20042: There is no need to call CBS" val GatewayLoginCannotFindUser = "OBP-20043: User cannot be found. Please initiate CBS communication in order to create it." @@ -188,7 +188,7 @@ object ErrorMessages { val DAuthHostPropertyMissing = "OBP-20068: Property dauth.host is not defined." val DAuthWhiteListAddresses = "OBP-20069: DAuth login can be done only from allowed addresses." val DAuthNoJwtForResponse = "OBP-20070: There is no useful value for JWT." - val DAuthJwtTokenIsNotValid = "OBP-20071: The JWT is corrupted/changed during a transport." + val DAuthJwtTokenIsNotValid = "OBP-20071: The DAuth JWT is corrupted/changed during a transport." val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index a3663dd02..972ab469c 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2075,8 +2075,8 @@ object Glossary extends MdcLoggable { | "network_name": "ETHEREUM", | "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", | "consumer_id": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", -| "time_stamp": "2021-11-04T14:13:40Z", -| "caller_request_id": "0Xe876987694328763492876348928736497869273649" +| "timestamp": "2021-11-04T14:13:40Z", +| "request_id": "0Xe876987694328763492876348928736497869273649" |} |``` |VERIFY SIGNATURE @@ -2159,8 +2159,8 @@ object Glossary extends MdcLoggable { | "network_name": "ETHEREUM", | "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", | "consumer_id": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", -| "time_stamp": datetime.now(timezone.utc).strftime(DATE_FORMAT), -| "caller_request_id": "0Xe876987694328763492876348928736497869273649" +| "timestamp": datetime.now(timezone.utc).strftime(DATE_FORMAT), +| "request_id": "0Xe876987694328763492876348928736497869273649" |} | |token = jwt.encode(payload, 'your-at-least-256-bit-secret-token', algorithm='HS256').decode("utf-8") diff --git a/obp-api/src/test/scala/code/api/dauthTest.scala b/obp-api/src/test/scala/code/api/dauthTest.scala index 3d990fa29..9e79c0c2f 100644 --- a/obp-api/src/test/scala/code/api/dauthTest.scala +++ b/obp-api/src/test/scala/code/api/dauthTest.scala @@ -13,28 +13,24 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P "smart_contract_address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", "network_name": "ETHEREUM", "msg_sender": "0xe90980927f1725E7734CE288F8367e1Bb143E90fhku767", - "consumer_id": "0x19255a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", - "time_stamp": "2018-08-20T14:13:40Z", - "caller_request_id": "0Xe876987694328763492876348928736497869273649" + "consumer_key": "0x19255a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", + "timestamp": "2018-08-20T14:13:40Z", + "request_id": "0Xe876987694328763492876348928736497869273649" } */ - val invalidSecretJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfaWQiOiIweDE5MjU1YTRlYzMxZTg5Y2VhNTRkMWYxMjVkYjc1MzZlODc0YWI0YTk2YjRkNGY2NDM4NjY4YjZiYjEwYTZhZGIiLCJ0aW1lX3N0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJjYWxsZXJfcmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.5t1bolx13gCBSyvbTzv_QWP1tFkN0m_Sv727bB1QZuw" + val invalidSecretJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfaWQiOiIweDE5MjU1YTRlYzMxZTg5Y2VhNTRkMWYxMjVkYjc1MzZlODc0YWI0YTk2YjRkNGY2NDM4NjY4YjZiYjEwYTZhZGIiLCJ0aW1lc3RhbXAiOiIyMDE4LTA4LTIwVDE0OjEzOjQwWiIsInJlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ.qWI4DXwa8QDGVPJoPCJehkLKHFA2A4_77JHINluc2tc" - /* Payload data. verified by correct secret "secretsecretsecretstsecretssssss" + /* Payload data. verified by correct secret "your-at-least-256-bit-secret-token" { "smart_contract_address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F05124", "network_name": "ETHEREUM", "msg_sender": "0xe90980927f1725E7734CE288F8367e1Bb143E90fhku767", - "consumer_id": "0x19255a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", - "time_stamp": "2018-08-20T14:13:40Z", - "caller_request_id": "0Xe876987694328763492876348928736497869273649" + "consumer_key": "0x19255a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", + "timestamp": "2018-08-20T14:13:40Z", + "request_id": "0Xe876987694328763492876348928736497869273649" } */ - val jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3Z" + - "TFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhG" + - "ODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfaWQiOiIweDE5MjU1YTRlYzMxZTg5Y2VhNTRkMWYxMjVkYjc1MzZlODc0YWI0YTk2YjRkNGY2" + - "NDM4NjY4YjZiYjEwYTZhZGIiLCJ0aW1lX3N0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJjYWxsZXJfcmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5" + - "NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.us2wjYUwiQHYdmU9JBNEMz8rc8qVGzY6bDNeknC3HMo" + val jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyNCIsIm5ldHdvcmtfbmFtZSI6IkVUSEVSRVVNIiwibXNnX3NlbmRlciI6IjB4ZTkwOTgwOTI3ZjE3MjVFNzczNENFMjg4RjgzNjdlMUJiMTQzRTkwZmhrdTc2NyIsImNvbnN1bWVyX2tleSI6IjB4MTkyNTVhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMTgtMDgtMjBUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.Wg2BYYsbWK-MUYToeTUc0GvDwcwnkR6Dh4SV-pMjChk" val invalidJwt = ("Authorization", ("DAuth token=%s").format(invalidSecretJwt)) val validJwt = ("Authorization", ("DAuth token=%s").format(jwt)) diff --git a/obp-api/src/test/scala/code/setup/ServerSetup.scala b/obp-api/src/test/scala/code/setup/ServerSetup.scala index 55b45f2a9..8a26eeefe 100644 --- a/obp-api/src/test/scala/code/setup/ServerSetup.scala +++ b/obp-api/src/test/scala/code/setup/ServerSetup.scala @@ -47,7 +47,7 @@ trait ServerSetup extends FeatureSpec with SendServerRequests setPropsValues("migration_scripts.execute" -> "true") setPropsValues("allow_dauth" -> "true") setPropsValues("dauth.host" -> "127.0.0.1") - setPropsValues("jwt.token_secret"->"secretsecretsecretstsecretssssss") + setPropsValues("jwt.token_secret"->"your-at-least-256-bit-secret-token") val server = TestServer def baseRequest = host(server.host, server.port) From b06077b9c314358306fc17e87293286c671c4bfb Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 5 Nov 2021 17:06:39 +0100 Subject: [PATCH 218/293] feature/tweaked the header format, now support DAuth:xxx --- .../main/scala/code/api/OBPRestHelper.scala | 17 ++- obp-api/src/main/scala/code/api/dauth.scala | 115 +++--------------- .../main/scala/code/api/util/APIUtil.scala | 21 ++-- .../main/scala/code/api/util/ApiSession.scala | 2 +- .../scala/code/api/util/ErrorMessages.scala | 1 + 5 files changed, 40 insertions(+), 116 deletions(-) diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 5e169c317..8456b21f8 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -28,12 +28,11 @@ TESOBE (http://www.tesobe.com/) package code.api import java.net.URLDecoder - import code.api.Constant._ import code.api.OAuthHandshake._ import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi import code.api.util.APIUtil._ -import code.api.util.ErrorMessages.{UserIsDeleted, UsernameHasBeenLocked, attemptedToOpenAnEmptyBox} +import code.api.util.ErrorMessages.{InvalidDAuthHeaderToken, UserIsDeleted, UsernameHasBeenLocked, attemptedToOpenAnEmptyBox} import code.api.util._ import code.api.v3_0_0.APIMethods300 import code.api.v3_1_0.APIMethods310 @@ -402,15 +401,15 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { Failure(ErrorMessages.GatewayLoginUnknownError) } } - else if (APIUtil.getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(authorization)) { + else if (APIUtil.getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.requestHeaders)) { logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val s = S - val (httpCode, message, parameters) = DAuth.validator(s.request) - httpCode match { - case 200 => - val payload = DAuth.parseJwt(parameters) + val dauthToken = DAuth.getDAuthToken(cc.requestHeaders) + dauthToken match { + case Some(token :: _) => + val payload = DAuth.parseJwt(token) payload match { case Full(payload) => val s = S @@ -421,7 +420,7 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) fn(callContextUpdated.map( callContext =>callContext.copy(user = Full(u), consumer = consumer)).getOrElse(callContext.getOrElse(cc).copy(user = Full(u), consumer = consumer))) case Failure(msg, t, c) => Failure(msg, t, c) - case _ => Full(errorJsonResponse(payload, httpCode)) + case _ => Full(errorJsonResponse(payload)) } case Failure(msg, t, c) => Failure(msg, t, c) @@ -429,7 +428,7 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { Failure(ErrorMessages.DAuthUnknownError) } case _ => - Failure(message) + Failure(InvalidDAuthHeaderToken) } case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == false) => // All other addresses will be rejected Failure(ErrorMessages.DAuthWhiteListAddresses) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index 6ec0efd00..f6f29b9f0 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -39,6 +39,9 @@ import net.liftweb.http._ import net.liftweb.http.rest.RestHelper import net.liftweb.json._ import com.openbankproject.commons.ExecutionContext.Implicits.global +import net.liftweb.http.provider.HTTPParam + +import scala.collection.immutable.List import scala.concurrent.Future /** @@ -90,9 +93,8 @@ object DAuth extends RestHelper with MdcLoggable { } } - def parseJwt(parameters: Map[String, String]): Box[String] = { - val jwt = getToken(parameters) - logger.debug("parseJwt says jwt.toString is: " + jwt.toString) + def parseJwt(jwt:String): Box[String] = { + logger.debug("parseJwt says jwt.toString is: " + jwt) logger.debug("parseJwt says: validateJwtToken(jwt) is:" + validateJwtToken(jwt)) validateJwtToken(jwt) match { case Full(jwtPayload) => @@ -127,32 +129,8 @@ object DAuth extends RestHelper with MdcLoggable { } // Check if the request (access token or request token) is valid and return a tuple - def validator(request: Box[Req]) : (Int, String, Map[String,String]) = { - // First we try to extract all parameters from a Request - val parameters: Map[String, String] = getAllParameters(request) - val emptyMap = Map[String, String]() - - parameters.get("error") match { - case Some(m) => { - logger.error("DAuth error message : " + m) - (400, m, emptyMap) - } - case _ => { - // Are all the necessary DAuth parameters present? - val missingParams: Set[String] = missingDAuthParameters(parameters) - missingParams.nonEmpty match { - case true => { - val message = ErrorMessages.DAuthMissingParameters + missingParams.mkString(", ") - logger.error("DAuth error message : " + message) - (400, message, emptyMap) - } - case false => { - logger.debug("DAuth parameters : " + parameters) - (200, "", parameters) - } - } - } - } + def getDAuthToken(requestHeaders: List[HTTPParam]) : Option[List[String]] = { + requestHeaders.find(_.name=="DAuth").map(_.values) } def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { @@ -213,60 +191,6 @@ object DAuth extends RestHelper with MdcLoggable { Consumers.consumers.vend.getConsumerByConsumerKey(consumeyKey) } - // Return a Map containing the DAuth parameter : token -> value - def getAllParameters(request: Box[Req]): Map[String, String] = { - def toMap(parametersList: String) = { - //transform the string "DAuth token="value"" - //to a tuple (DAuth_parameter,Decoded(value)) - def dynamicListExtract(input: String) = { - val DAuthPossibleParameters = - List( - "token" - ) - if (input contains "=") { - val split = input.split("=", 2) - val parameterValue = split(1).replace("\"", "") - //add only OAuth parameters and not empty - if (DAuthPossibleParameters.contains(split(0)) && !parameterValue.isEmpty) - Some(split(0), parameterValue) // return key , value - else - None - } - else - None - } - // We delete the "DAuth" prefix and all the white spaces that may exist in the string - val cleanedParameterList = parametersList.stripPrefix("DAuth").replaceAll("\\s", "") - val params = Map(cleanedParameterList.split(",").flatMap(dynamicListExtract _): _*) - params - } - - request match { - case Full(a) => a.header("Authorization") match { - case Full(header) => { - if (header.contains("DAuth")) - toMap(header) - else - Map("error" -> "Missing DAuth in header!") - } - case _ => Map("error" -> "Missing Authorization header!") - } - case _ => Map("error" -> "Request is incorrect!") - } - } - - // Returns the missing parameters - def missingDAuthParameters(parameters: Map[String, String]): Set[String] = { - ("token" :: List()).toSet diff parameters.keySet - } - - private def getToken(params: Map[String, String]): String = { - logger.debug("getToken params are: " + params.toString()) - val token = params.getOrElse("token", "") - logger.debug("getToken wants to return token: " + token) - token - } - private def getFieldFromPayloadJson(payloadAsJsonString: String, fieldName: String) = { val jwtJson = parse(payloadAsJsonString) // Transform Json string to JsonAST val v = jwtJson.\(fieldName) @@ -277,7 +201,6 @@ object DAuth extends RestHelper with MdcLoggable { compactRender(v).replace("\"", "") } } - // Try to find errorCode in Json string received from South side and extract to list // Return list of error codes values def getErrors(message: String) : List[String] = { @@ -293,22 +216,16 @@ object DAuth extends RestHelper with MdcLoggable { listOfValues } - def getUser : Box[User] = { - val (httpCode, message, parameters) = DAuth.validator(S.request) - httpCode match { - case 200 => - val payload = DAuth.parseJwt(parameters) - payload match { - case Full(payload) => - val username = getFieldFromPayloadJson(payload, "smart_contract_address") - val provider = getFieldFromPayloadJson(payload, "network_name") - logger.debug("username: " + username) - Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = username) - case _ => - None - } - case _ => + val token = S.getRequestHeader("DAuth") + val payload = token.map(DAuth.parseJwt).flatten + payload match { + case Full(payload) => + val username = getFieldFromPayloadJson(payload, "smart_contract_address") + val provider = getFieldFromPayloadJson(payload, "network_name") + logger.debug("username: " + username) + Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = username) + case _ => None } } diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 025a128ab..bda5055a1 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -181,7 +181,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ def hasGatewayHeader(authorization: Box[String]) = hasHeader("GatewayLogin", authorization) - def hasDAuthHeader(authorization: Box[String]) = hasHeader("DAuth", authorization) + /** + * The value `DAuth` is in the KEY + * DAuth:xxxxx + * + * Other types: the `GatewayLogin` is in the VALUE + * Authorization:GatewayLogin token=xxxx + */ + def hasDAuthHeader(requestHeaders: List[HTTPParam]) = requestHeaders.map(_.name).exists(_ =="DAuth") /** * Helper function which tells us does an "Authorization" request header field has the Type of an authentication scheme @@ -2736,14 +2743,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ Future { (Failure(ErrorMessages.GatewayLoginUnknownError), None) } } } // DAuth Login - else if (getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.authReqHeaderField)) { + else if (getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.requestHeaders)) { logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature - val (httpCode, message, parameters) = DAuth.validator(s.request) - httpCode match { - case 200 => - val payload = DAuth.parseJwt(parameters) + val dauthToken = DAuth.getDAuthToken(cc.requestHeaders) + dauthToken match { + case Some(token :: _) => + val payload = DAuth.parseJwt(token) payload match { case Full(payload) => DAuth.getOrCreateResourceUserFuture(payload: String, Some(cc)) map { @@ -2763,7 +2770,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ Future { (Failure(ErrorMessages.DAuthUnknownError), None) } } case _ => - Future { (Failure(message), None) } + Future { (Failure(InvalidDAuthHeaderToken), None) } } case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == false) => // All other addresses will be rejected Future { (Failure(ErrorMessages.DAuthWhiteListAddresses), None) } diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala index 889397845..d6bbce143 100644 --- a/obp-api/src/main/scala/code/api/util/ApiSession.scala +++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala @@ -140,7 +140,7 @@ case class CallContext( def authType: AuthenticationType = { if(hasGatewayHeader(authReqHeaderField)) { GatewayLogin - } else if(hasDAuthHeader(authReqHeaderField)) { // DAuth Login + } else if(requestHeaders.exists(_.name=="DAuth")) { // DAuth Login DAuth } else if(has2021DirectLoginHeader(requestHeaders)) { // Direct Login DirectLogin diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index eb645a3ad..50a057f4b 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -189,6 +189,7 @@ object ErrorMessages { val DAuthWhiteListAddresses = "OBP-20069: DAuth login can be done only from allowed addresses." val DAuthNoJwtForResponse = "OBP-20070: There is no useful value for JWT." val DAuthJwtTokenIsNotValid = "OBP-20071: The DAuth JWT is corrupted/changed during a transport." + val InvalidDAuthHeaderToken = "OBP-20072: DAuth Header value should be one single string." val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " From ce482c132922b55cefde74967b481ae34e2706f5 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 8 Nov 2021 12:50:08 +0100 Subject: [PATCH 219/293] feature/tweaked the payload case class and the header format --- .../main/scala/code/api/OBPRestHelper.scala | 6 ++-- obp-api/src/main/scala/code/api/dauth.scala | 4 +-- .../main/scala/code/api/util/APIUtil.scala | 32 +++---------------- .../main/scala/code/api/util/ApiSession.scala | 2 +- .../main/scala/code/api/util/Glossary.scala | 27 +++++++--------- .../test/scala/code/setup/ServerSetup.scala | 2 +- 6 files changed, 23 insertions(+), 50 deletions(-) diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 8456b21f8..4ec40f92e 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -401,18 +401,16 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { Failure(ErrorMessages.GatewayLoginUnknownError) } } - else if (APIUtil.getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.requestHeaders)) { - logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) + else if (APIUtil.getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.requestHeaders)) { + logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature - val s = S val dauthToken = DAuth.getDAuthToken(cc.requestHeaders) dauthToken match { case Some(token :: _) => val payload = DAuth.parseJwt(token) payload match { case Full(payload) => - val s = S DAuth.getOrCreateResourceUser(payload: String, Some(cc)) match { case Full((u, callContext)) => // Authentication is successful val consumer = DAuth.getConsumerByConsumerKey(payload)//TODO, need to verify the key later. diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index f6f29b9f0..4835b798a 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -130,7 +130,7 @@ object DAuth extends RestHelper with MdcLoggable { // Check if the request (access token or request token) is valid and return a tuple def getDAuthToken(requestHeaders: List[HTTPParam]) : Option[List[String]] = { - requestHeaders.find(_.name=="DAuth").map(_.values) + requestHeaders.find(_.name==APIUtil.DAuthHeaderKey).map(_.values) } def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { @@ -217,7 +217,7 @@ object DAuth extends RestHelper with MdcLoggable { } def getUser : Box[User] = { - val token = S.getRequestHeader("DAuth") + val token = S.getRequestHeader(APIUtil.DAuthHeaderKey) val payload = token.map(DAuth.parseJwt).flatten payload match { case Full(payload) => diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index bda5055a1..d9eea8893 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -188,7 +188,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ * Other types: the `GatewayLogin` is in the VALUE * Authorization:GatewayLogin token=xxxx */ - def hasDAuthHeader(requestHeaders: List[HTTPParam]) = requestHeaders.map(_.name).exists(_ =="DAuth") + def hasDAuthHeader(requestHeaders: List[HTTPParam]) = requestHeaders.map(_.name).exists(_ ==DAuthHeaderKey) /** * Helper function which tells us does an "Authorization" request header field has the Type of an authentication scheme @@ -2256,29 +2256,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ /** * Defines DAuth Custom Response Header. */ - val DAuthResponseHeaderName = "DAuth" - /** - * Set value of DAuth Custom Response Header. - */ - def setDAuthResponseHeader(s: S)(value: String) = s.setSessionAttribute(DAuthResponseHeaderName, value) - /** - * @return - DAuth Custom Response Header. - */ - def getDAuthResponseHeader() = { - S.getSessionAttribute(DAuthResponseHeaderName) match { - case Full(h) => List((DAuthResponseHeaderName, h)) - case _ => Nil - } - } - def getDAuthJwt(): Option[String] = { - getDAuthResponseHeader() match { - case x :: Nil => - Some(x._2) - case _ => - None - } - } - + val DAuthHeaderKey = "DAuth" /** * Turn a string of format "FooBar" into snake case "foo_bar" * @@ -2743,8 +2721,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ Future { (Failure(ErrorMessages.GatewayLoginUnknownError), None) } } } // DAuth Login - else if (getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.requestHeaders)) { - logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) + else if (getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.requestHeaders)) { + logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val dauthToken = DAuth.getDAuthToken(cc.requestHeaders) @@ -2755,7 +2733,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case Full(payload) => DAuth.getOrCreateResourceUserFuture(payload: String, Some(cc)) map { case Full((u,callContext)) => // Authentication is successful - val consumer = DAuth.getConsumerByConsumerKey(payload) + val consumer = DAuth.getConsumerByConsumerKey(payload)//TODO, need to verify the key later. val jwt = DAuth.createJwt(payload) val callContextUpdated = ApiSession.updateCallContext(DAuthResponseHeader(Some(jwt)), callContext) (Full(u), callContextUpdated.map(_.copy(consumer=consumer, user = Full(u)))) diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala index d6bbce143..8f2607e77 100644 --- a/obp-api/src/main/scala/code/api/util/ApiSession.scala +++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala @@ -140,7 +140,7 @@ case class CallContext( def authType: AuthenticationType = { if(hasGatewayHeader(authReqHeaderField)) { GatewayLogin - } else if(requestHeaders.exists(_.name=="DAuth")) { // DAuth Login + } else if(requestHeaders.exists(_.name==DAuthHeaderKey)) { // DAuth Login DAuth } else if(has2021DirectLoginHeader(requestHeaders)) { // Direct Login DirectLogin diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 972ab469c..4699d751b 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2016,12 +2016,12 @@ object Glossary extends MdcLoggable { """) - val dauthEnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_gateway_login", false)) + val dauthEnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_dauth_login", false)) {"Note: DAuth is enabled."} else {"Note: *DAuth is NOT enabled on this instance!*"} glossaryItems += GlossaryItem( - title = "DAuth", + title = APIUtil.DAuthHeaderKey, description = s""" |### Introduction @@ -2032,7 +2032,7 @@ object Glossary extends MdcLoggable { | |Note: DAuth does *not* require an explicit POST like Direct Login to create the token. | -|The **Gateway is responsible** for creating a token which is trusted by OBP **absolutely**! +|The **DAuth is responsible** for creating a token which is trusted by OBP **absolutely**! | |When OBP receives a token via DAuth, OBP creates or gets a user based on the username (smart_contract_address) supplied. | @@ -2048,7 +2048,7 @@ object Glossary extends MdcLoggable { |# jwt.token_secret=your-at-least-256-bit-secret-token |# Enable/Disable DAuth communication at all |# In case isn't defined default value is false -|# allow_dauth=false +|# allow_dauth_login=false |# Define comma separated list of allowed IP addresses |# dauth.host=127.0.0.1 |# -------------------------------------- DAuth-- @@ -2074,7 +2074,7 @@ object Glossary extends MdcLoggable { | "smart_contract_address": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", | "network_name": "ETHEREUM", | "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", -| "consumer_id": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", +| "consumer_key": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", | "timestamp": "2021-11-04T14:13:40Z", | "request_id": "0Xe876987694328763492876348928736497869273649" |} @@ -2091,9 +2091,7 @@ object Glossary extends MdcLoggable { |Here is the above example token: | |``` -|eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. -|eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9pZCI6IjB4MTIzNGE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZV9zdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwiY2FsbGVyX3JlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ. -|SbgXzyRNd6uLBYql_fwXi3KAWS8SaKYMHmnVFgbGRiY +|eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9rZXkiOiIweDEyMzRhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.XSiQxjEVyCouf7zT8MubEKsbOBZuReGVhnt9uck6z6k |``` | | @@ -2120,12 +2118,12 @@ object Glossary extends MdcLoggable { | Host: localhost:8080 | User-Agent: curl/7.47.0 | Accept: */* -| Authorization: GatewayLogin token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9pZCI6IjB4MTIzNGE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZV9zdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwiY2FsbGVyX3JlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ.SbgXzyRNd6uLBYql_fwXi3KAWS8SaKYMHmnVFgbGRiY" +| DAuth: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9rZXkiOiIweDEyMzRhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.XSiQxjEVyCouf7zT8MubEKsbOBZuReGVhnt9uck6z6k | |CURL example | |``` -|curl -v -H 'Authorization: DAuth token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9pZCI6IjB4MTIzNGE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZV9zdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwiY2FsbGVyX3JlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ.SbgXzyRNd6uLBYql_fwXi3KAWS8SaKYMHmnVFgbGRiY"' $getServerUrl/obp/v3.0.0/users/current +|curl -v -H 'DAuth: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9rZXkiOiIweDEyMzRhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.XSiQxjEVyCouf7zT8MubEKsbOBZuReGVhnt9uck6z6k' $getServerUrl/obp/v3.0.0/users/current |``` | | @@ -2157,15 +2155,14 @@ object Glossary extends MdcLoggable { |payload = { | "smart_contract_address": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", | "network_name": "ETHEREUM", -| "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", -| "consumer_id": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", +| "consumer_key": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", | "timestamp": datetime.now(timezone.utc).strftime(DATE_FORMAT), +| "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", | "request_id": "0Xe876987694328763492876348928736497869273649" |} | |token = jwt.encode(payload, 'your-at-least-256-bit-secret-token', algorithm='HS256').decode("utf-8") -|authorization = 'DAuth token="{}"'.format(token) -|headers = {'Authorization': authorization} +|headers = {'DAuth': token} |url = obp_api_host + '/obp/v4.0.0/users/current' |req = requests.get(url, headers=headers) |print(req.text) @@ -2178,7 +2175,7 @@ object Glossary extends MdcLoggable { |We: | |``` -|-> Check if Props allow_dauth is true +|-> Check if Props allow_dauth_login is true | -> Check if DAuth header exists | -> Check if getRemoteIpAddress is OK | -> Look for "token" diff --git a/obp-api/src/test/scala/code/setup/ServerSetup.scala b/obp-api/src/test/scala/code/setup/ServerSetup.scala index 8a26eeefe..ec0546e8b 100644 --- a/obp-api/src/test/scala/code/setup/ServerSetup.scala +++ b/obp-api/src/test/scala/code/setup/ServerSetup.scala @@ -45,7 +45,7 @@ trait ServerSetup extends FeatureSpec with SendServerRequests setPropsValues("migration_scripts.execute_all" -> "true") setPropsValues("migration_scripts.execute" -> "true") - setPropsValues("allow_dauth" -> "true") + setPropsValues("allow_dauth_login" -> "true") setPropsValues("dauth.host" -> "127.0.0.1") setPropsValues("jwt.token_secret"->"your-at-least-256-bit-secret-token") From ac45a044b29324d25113a70ccef31f3d954b8623 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 8 Nov 2021 12:52:24 +0100 Subject: [PATCH 220/293] feature/rename rest_connector_http_header_signature -> rest_connector_sends_x-sign_header --- obp-api/src/main/resources/props/sample.props.template | 6 +++--- .../code/bankconnectors/rest/RestConnector_vMar2019.scala | 2 +- release_notes.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 074f4f42f..dcf17b0f9 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -816,9 +816,9 @@ featured_apis=elasticSearchWarehouseV300 # If Rest Connector do not get the response in the following seconds, it will throw the error message back. # This props can be omitted, the default value is 59. It should be less than Nginx timeout. # rest2019_connector_timeout = 59 -# If set it to `true`, it will add the signature (SHA256WithRSA) into each the rest connector http calls, and you need to upload the RSA -# private key into the UserAuthContext. -#rest_connector_http_header_signature=false +# If set it to `true`, it will add the x-sign (SHA256WithRSA) into each the rest connector http calls, +# and you need to upload the RSA private key into the UserAuthContext. +#rest_connector_sends_x-sign_header=false # -- Scopes ----------------------------------------------------- diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 9411c2a8c..1d9c6dc33 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -6580,7 +6580,7 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable callContext: Option[CallContext] ): List[HttpHeader] = { - val needSignatureHead = APIUtil.getPropsAsBoolValue("rest_connector_http_header_signature", false) + val needSignatureHead = APIUtil.getPropsAsBoolValue("rest_connector_sends_x-sign_header", false) val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext]) val headersFromGeneralContext = generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value)) diff --git a/release_notes.md b/release_notes.md index 612c6f8f8..a8a9ce2dc 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,7 +3,7 @@ ### Most recent changes at top of file ``` Date Commit Action -01/11/2021 03305d2b Added props: rest_connector_http_header_signature, default is false +01/11/2021 03305d2b Added props: rest_connector_sends_x-sign_header, default is false 17/09/2021 e65cd51d Added props: webui_main_faq_external_link, default is obp static file: /main-faq.html 09/09/2021 65952225 Added props: webui_support_email, default is contact@openbankproject.com 02/09/2021 a826d908 Renamed Web UI props: From 4510b0d5c836267b6d22a59f2ca049010df13586 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 8 Nov 2021 13:56:28 +0100 Subject: [PATCH 221/293] feature/fixed the DAuth Test --- .../src/test/scala/code/api/dauthTest.scala | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/obp-api/src/test/scala/code/api/dauthTest.scala b/obp-api/src/test/scala/code/api/dauthTest.scala index 9e79c0c2f..84006f700 100644 --- a/obp-api/src/test/scala/code/api/dauthTest.scala +++ b/obp-api/src/test/scala/code/api/dauthTest.scala @@ -18,7 +18,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P "request_id": "0Xe876987694328763492876348928736497869273649" } */ - val invalidSecretJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfaWQiOiIweDE5MjU1YTRlYzMxZTg5Y2VhNTRkMWYxMjVkYjc1MzZlODc0YWI0YTk2YjRkNGY2NDM4NjY4YjZiYjEwYTZhZGIiLCJ0aW1lc3RhbXAiOiIyMDE4LTA4LTIwVDE0OjEzOjQwWiIsInJlcXVlc3RfaWQiOiIwWGU4NzY5ODc2OTQzMjg3NjM0OTI4NzYzNDg5Mjg3MzY0OTc4NjkyNzM2NDkifQ.qWI4DXwa8QDGVPJoPCJehkLKHFA2A4_77JHINluc2tc" + val invalidSecretJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfa2V5IjoiMHgxOTI1NWE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZXN0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJyZXF1ZXN0X2lkIjoiMFhlODc2OTg3Njk0MzI4NzYzNDkyODc2MzQ4OTI4NzM2NDk3ODY5MjczNjQ5In0.mK4Bx-V3reGe2jWxvQ5NQNSLXZ7AVRTX2fUFLD-2sSs" /* Payload data. verified by correct secret "your-at-least-256-bit-secret-token" { @@ -32,24 +32,16 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P */ val jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyNCIsIm5ldHdvcmtfbmFtZSI6IkVUSEVSRVVNIiwibXNnX3NlbmRlciI6IjB4ZTkwOTgwOTI3ZjE3MjVFNzczNENFMjg4RjgzNjdlMUJiMTQzRTkwZmhrdTc2NyIsImNvbnN1bWVyX2tleSI6IjB4MTkyNTVhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMTgtMDgtMjBUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.Wg2BYYsbWK-MUYToeTUc0GvDwcwnkR6Dh4SV-pMjChk" - val invalidJwt = ("Authorization", ("DAuth token=%s").format(invalidSecretJwt)) - val validJwt = ("Authorization", ("DAuth token=%s").format(jwt)) - val missingParameterToken = ("Authorization", ("DAuth wrong_parameter_name=%s").format(jwt)) + val invalidJwt = ("DAuth", ("%s").format(invalidSecretJwt)) + val validJwt = ("DAuth", ("%s").format(jwt)) - def dauthRequest = baseRequest / "obp" / "v2.0.0" / "users" /"current" <@ (user1) - def dauthNonBlockingRequest = baseRequest / "obp" / "v3.0.0" / "users" / "current" <@ (user1) + def dauthRequest = baseRequest / "obp" / "v2.0.0" / "users" /"current" + def dauthNonBlockingRequest = baseRequest / "obp" / "v3.0.0" / "users" / "current" feature("DAuth Testing") { scenario("Missing parameter token in a blocking way") { When("We try to login without parameter token in a Header") - val response = makeGetRequest(dauthRequest, List(missingParameterToken)) - Then("We should get a 400 - Bad Request") - logger.debug("-----------------------------------------") - logger.debug(response) - logger.debug("-----------------------------------------") - response.code should equal(400) - response.toString contains (ErrorMessages.DAuthMissingParameters) should be (true) When("We try to login with an invalid JWT") val responseInvalid = makeGetRequest(dauthRequest, List(invalidJwt)) @@ -67,15 +59,6 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P logger.debug("-----------------------------------------") responseValidJwt.code should equal(200) - When("We try to login without parameter token in a Header") - val responseNonBlocking = makeGetRequest(dauthNonBlockingRequest, List(missingParameterToken)) - Then("We should get a 400 - Bad Request") - logger.debug("-----------------------------------------") - logger.debug("responseNonBlocking: "+ responseNonBlocking) - logger.debug("-----------------------------------------") - responseNonBlocking.code should equal(401) - responseNonBlocking.toString contains (ErrorMessages.DAuthMissingParameters) should be (true) - When("We try to login with an invalid JWT") val responseNonBlockingInvalid = makeGetRequest(dauthNonBlockingRequest, List(invalidJwt)) Then("We should get a 400 - Bad Request") From e6b2354f67be3bc221022fadc30dcf0e210b13d5 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 8 Nov 2021 17:20:11 +0100 Subject: [PATCH 222/293] refactor/tweaked the names for DAuth --- obp-api/src/main/resources/props/sample.props.template | 4 ++-- obp-api/src/main/scala/code/api/OBPRestHelper.scala | 4 ++-- obp-api/src/main/scala/code/api/util/APIUtil.scala | 4 ++-- obp-api/src/main/scala/code/api/util/Glossary.scala | 6 +++--- obp-api/src/test/scala/code/setup/ServerSetup.scala | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index dcf17b0f9..70f3225da 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -678,7 +678,7 @@ autocomplete_at_login_form_enabled=false # control access to customer firehose. # allow_customer_firehose=false -# -- Gateway And DAuth common Setting-------------------------------------- +# -- Gateway Login And DAuth common settings-------------------------------------- # Define secret used to validate JWT token # jwt.token_secret=your-at-least-256-bit-secret-token @@ -817,7 +817,7 @@ featured_apis=elasticSearchWarehouseV300 # This props can be omitted, the default value is 59. It should be less than Nginx timeout. # rest2019_connector_timeout = 59 # If set it to `true`, it will add the x-sign (SHA256WithRSA) into each the rest connector http calls, -# and you need to upload the RSA private key into the UserAuthContext. +# please add the name of the field for the UserAuthContext and/or link to other documentation.. #rest_connector_sends_x-sign_header=false diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 4ec40f92e..323278334 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -401,8 +401,8 @@ trait OBPRestHelper extends RestHelper with MdcLoggable { Failure(ErrorMessages.GatewayLoginUnknownError) } } - else if (APIUtil.getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.requestHeaders)) { - logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) + else if (APIUtil.getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.requestHeaders)) { + logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val dauthToken = DAuth.getDAuthToken(cc.requestHeaders) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index d9eea8893..e280a306f 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2721,8 +2721,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ Future { (Failure(ErrorMessages.GatewayLoginUnknownError), None) } } } // DAuth Login - else if (getPropsAsBoolValue("allow_dauth_login", false) && hasDAuthHeader(cc.requestHeaders)) { - logger.info("allow_dauth_login-getRemoteIpAddress: " + remoteIpAddress ) + else if (getPropsAsBoolValue("allow_dauth", false) && hasDAuthHeader(cc.requestHeaders)) { + logger.info("allow_dauth-getRemoteIpAddress: " + remoteIpAddress ) APIUtil.getPropsValue("dauth.host") match { case Full(h) if h.split(",").toList.exists(_.equalsIgnoreCase(remoteIpAddress) == true) => // Only addresses from white list can use this feature val dauthToken = DAuth.getDAuthToken(cc.requestHeaders) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 4699d751b..b9bb44450 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2016,7 +2016,7 @@ object Glossary extends MdcLoggable { """) - val dauthEnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_dauth_login", false)) + val dauthEnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_dauth", false)) {"Note: DAuth is enabled."} else {"Note: *DAuth is NOT enabled on this instance!*"} @@ -2048,7 +2048,7 @@ object Glossary extends MdcLoggable { |# jwt.token_secret=your-at-least-256-bit-secret-token |# Enable/Disable DAuth communication at all |# In case isn't defined default value is false -|# allow_dauth_login=false +|# allow_dauth=false |# Define comma separated list of allowed IP addresses |# dauth.host=127.0.0.1 |# -------------------------------------- DAuth-- @@ -2175,7 +2175,7 @@ object Glossary extends MdcLoggable { |We: | |``` -|-> Check if Props allow_dauth_login is true +|-> Check if Props allow_dauth is true | -> Check if DAuth header exists | -> Check if getRemoteIpAddress is OK | -> Look for "token" diff --git a/obp-api/src/test/scala/code/setup/ServerSetup.scala b/obp-api/src/test/scala/code/setup/ServerSetup.scala index ec0546e8b..8a26eeefe 100644 --- a/obp-api/src/test/scala/code/setup/ServerSetup.scala +++ b/obp-api/src/test/scala/code/setup/ServerSetup.scala @@ -45,7 +45,7 @@ trait ServerSetup extends FeatureSpec with SendServerRequests setPropsValues("migration_scripts.execute_all" -> "true") setPropsValues("migration_scripts.execute" -> "true") - setPropsValues("allow_dauth_login" -> "true") + setPropsValues("allow_dauth" -> "true") setPropsValues("dauth.host" -> "127.0.0.1") setPropsValues("jwt.token_secret"->"your-at-least-256-bit-secret-token") From 18508254d81f75162289079c78fe13207717ee0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 9 Nov 2021 20:21:04 +0100 Subject: [PATCH 223/293] feature/DAuth; Add props jwt.public_key_rsa --- .../resources/props/sample.props.template | 13 +++++----- obp-api/src/main/scala/code/api/dauth.scala | 4 ++-- .../main/scala/code/api/util/JwtUtil.scala | 24 ++++++++++++++++++- .../src/test/scala/code/api/dauthTest.scala | 15 ++++++------ .../test/scala/code/setup/ServerSetup.scala | 5 ++++ 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 70f3225da..6ba33300b 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -678,14 +678,12 @@ autocomplete_at_login_form_enabled=false # control access to customer firehose. # allow_customer_firehose=false -# -- Gateway Login And DAuth common settings-------------------------------------- -# Define secret used to validate JWT token -# jwt.token_secret=your-at-least-256-bit-secret-token - # -- Gateway login -------------------------------------- # Enable/Disable Gateway communication at all # In case isn't defined default value is false # allow_gateway_login=false +# Define secret used to validate JWT token +# jwt.token_secret=your-at-least-256-bit-secret-token # Define comma separated list of allowed IP addresses # gateway.host=127.0.0.1 @@ -693,10 +691,11 @@ autocomplete_at_login_form_enabled=false # -- DAuth -------------------------------------- # Enable/Disable DAuth communication at all # In case isn't defined default value is false -# allow_dauth=false +allow_dauth=false +# Define public key used to validate JWT token +jwt.public_key_rsa=path-to-the-pem-file # Define comma separated list of allowed IP addresses -# dauth.host=127.0.0.1 - +dauth.host=127.0.0.1 # -------------------------------------- DAuth-- diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index 4835b798a..b1c8e7fcb 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -114,8 +114,8 @@ object DAuth extends RestHelper with MdcLoggable { Box(parse(claim.toString).extractOpt[PayloadOfJwtJSON]) case false => logger.debug("validateJwtToken says: verifying jwt token with HmacProtection: " + token) - logger.debug(CertificateUtil.verifywtWithHmacProtection(token).toString) - CertificateUtil.verifywtWithHmacProtection(token) match { + logger.debug(JwtUtil.validateJwtWithRsaKey(token).toString) + JwtUtil.validateJwtWithRsaKey(token) match { case true => logger.debug("validateJwtToken says: jwt is verified: " + token) val claim = CertificateUtil.parseJwtWithHmacProtection(token) diff --git a/obp-api/src/main/scala/code/api/util/JwtUtil.scala b/obp-api/src/main/scala/code/api/util/JwtUtil.scala index fa899d189..301d4e707 100644 --- a/obp-api/src/main/scala/code/api/util/JwtUtil.scala +++ b/obp-api/src/main/scala/code/api/util/JwtUtil.scala @@ -1,11 +1,14 @@ package code.api.util -import java.net.URL +import java.net.{URI, URL} +import java.nio.file.{Files, Paths} import java.text.ParseException +import code.api.util.RSAUtil.logger import code.util.Helper.MdcLoggable import com.nimbusds.jose.JWSAlgorithm import com.nimbusds.jose.crypto.{MACVerifier, RSASSAVerifier} +import com.nimbusds.jose.jwk.{JWK, RSAKey} import com.nimbusds.jose.jwk.source.{JWKSource, RemoteJWKSet} import com.nimbusds.jose.proc.{JWSVerificationKeySelector, SecurityContext} import com.nimbusds.jose.util.{DefaultResourceRetriever, JSONObjectUtils} @@ -235,7 +238,26 @@ object JwtUtil extends MdcLoggable { } } + def validateJwtWithRsaKey(jwtString: String): Boolean = { + val relativePath = APIUtil.getPropsValue("jwt.public_key_rsa", "") + val basePath = this.getClass.getResource("/").toString .replaceFirst("target[/\\\\].*$", "") + val filePath = new URI(s"${basePath}/$relativePath").getPath + val publicKey = getPublicRsaKeyFromFile(filePath) + val signedJWT = SignedJWT.parse(jwtString) + val verifier = new RSASSAVerifier(publicKey) + signedJWT.verify(verifier) + } + + def getPublicRsaKeyFromFile(path: String): RSAKey = { + val pathOfFile = Paths.get(path) + val pemEncodedRSAPubliceKey = Files.readAllLines(pathOfFile).toArray.toList.mkString("\n") + logger.debug(pemEncodedRSAPubliceKey) + // Parse PEM-encoded key to RSA public / private JWK + val jwk: JWK = JWK.parseFromPEMEncodedObjects(pemEncodedRSAPubliceKey); + logger.debug(s"Key $path is private: " + jwk.isPrivate) + jwk.toPublicJWK.toRSAKey + } def main(args: Array[String]): Unit = { diff --git a/obp-api/src/test/scala/code/api/dauthTest.scala b/obp-api/src/test/scala/code/api/dauthTest.scala index 84006f700..d00c821aa 100644 --- a/obp-api/src/test/scala/code/api/dauthTest.scala +++ b/obp-api/src/test/scala/code/api/dauthTest.scala @@ -1,6 +1,5 @@ package code.api -import code.api.util.APIUtil.OAuth._ import code.api.util.ErrorMessages import code.setup.{DefaultUsers, PropsReset, ServerSetup} import org.scalatest._ @@ -18,7 +17,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P "request_id": "0Xe876987694328763492876348928736497869273649" } */ - val invalidSecretJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfa2V5IjoiMHgxOTI1NWE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZXN0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJyZXF1ZXN0X2lkIjoiMFhlODc2OTg3Njk0MzI4NzYzNDkyODc2MzQ4OTI4NzM2NDk3ODY5MjczNjQ5In0.mK4Bx-V3reGe2jWxvQ5NQNSLXZ7AVRTX2fUFLD-2sSs" + val wrongPublicKeyJwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfa2V5IjoiMHgxOTI1NWE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZXN0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJyZXF1ZXN0X2lkIjoiMFhlODc2OTg3Njk0MzI4NzYzNDkyODc2MzQ4OTI4NzM2NDk3ODY5MjczNjQ5In0.Wa1aaoHKSWAKcX_tnueVf3PQze-BcPeZ_EfhovxRvv9WIGn86WSShT2x2W_VGfySYJhfYYhpg2N-l-trA2T9jru5u3Mp_yQcSJZ9D1kCg3kmy2AqYp_qbPIakVQthWo1Ys7hkGB6bZHau87BOXv9v4v97LrpRfva5lw62qzdhpN67lTK1hdUc677nsneFdtnA78Ddm6u_ta_KIf_mC0t-lxSfUcuLb7LQgp2biYyYMgVB7dyexPQ7ZSBa2B8ARGXBXo0iOCjvi-Su4IYUomklRwKWYI-waaigaCDd9FZZQyDfjEySQToAG7UO0mPBRQiIVrSumecz1VESlO_c0Bm0w" /* Payload data. verified by correct secret "your-at-least-256-bit-secret-token" { @@ -30,9 +29,9 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P "request_id": "0Xe876987694328763492876348928736497869273649" } */ - val jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyNCIsIm5ldHdvcmtfbmFtZSI6IkVUSEVSRVVNIiwibXNnX3NlbmRlciI6IjB4ZTkwOTgwOTI3ZjE3MjVFNzczNENFMjg4RjgzNjdlMUJiMTQzRTkwZmhrdTc2NyIsImNvbnN1bWVyX2tleSI6IjB4MTkyNTVhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMTgtMDgtMjBUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.Wg2BYYsbWK-MUYToeTUc0GvDwcwnkR6Dh4SV-pMjChk" + val jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyIiwibmV0d29ya19uYW1lIjoiRVRIRVJFVU0iLCJtc2dfc2VuZGVyIjoiMHhlOTA5ODA5MjdmMTcyNUU3NzM0Q0UyODhGODM2N2UxQmIxNDNFOTBmaGt1NzY3IiwiY29uc3VtZXJfa2V5IjoiMHgxOTI1NWE0ZWMzMWU4OWNlYTU0ZDFmMTI1ZGI3NTM2ZTg3NGFiNGE5NmI0ZDRmNjQzODY2OGI2YmIxMGE2YWRiIiwidGltZXN0YW1wIjoiMjAxOC0wOC0yMFQxNDoxMzo0MFoiLCJyZXF1ZXN0X2lkIjoiMFhlODc2OTg3Njk0MzI4NzYzNDkyODc2MzQ4OTI4NzM2NDk3ODY5MjczNjQ5In0.dkAy32AjskvOaQ-gzXEiwU7RslJIawrOPsFsrqAlGHeKr6NyLJPJLYQ6e8_ABK2N-Pw43PiIzefV5QdiGxtWXCuVMRldrdNVC2VdBLVicDVWOmHCLyQ-mFbUvBR3wx8ZsU9nauEchVBsI9UY-_YYYI4yF9DsUazdMoesIjDl-zr68Dzm_ljnxv1wL4fbFpT7wq7MRFQBSy5UTN9o0JxGN_sm9dYeGf-kINQP8-zmJKQM0CRlMegdcBJdonSjlJDib_cKdbyeiSYwWTnqu9pAsOKarY7sX7uIa4A2hVkGY9hkSaGoeQcTxUHFTrJFdEeDm2num2MNLjFul3roAEG0Uw" - val invalidJwt = ("DAuth", ("%s").format(invalidSecretJwt)) + val invalidJwt = ("DAuth", ("%s").format(wrongPublicKeyJwt)) val validJwt = ("DAuth", ("%s").format(jwt)) def dauthRequest = baseRequest / "obp" / "v2.0.0" / "users" /"current" @@ -47,7 +46,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P val responseInvalid = makeGetRequest(dauthRequest, List(invalidJwt)) Then("We should get a 400 - Bad Request") logger.debug("-----------------------------------------") - logger.debug("responseInvalid response: "+responseInvalid) + logger.debug("responseInvalid response: "+ responseInvalid) logger.debug("-----------------------------------------") responseInvalid.code should equal(400) responseInvalid.toString contains (ErrorMessages.DAuthJwtTokenIsNotValid) should be (true) @@ -55,7 +54,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P When("We try to login with an valid JWT") val responseValidJwt = makeGetRequest(dauthRequest, List(validJwt)) logger.debug("-----------------------------------------") - logger.debug("responseValidJwt response: "+responseValidJwt) + logger.debug("responseValidJwt response: " + responseValidJwt) logger.debug("-----------------------------------------") responseValidJwt.code should equal(200) @@ -63,7 +62,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P val responseNonBlockingInvalid = makeGetRequest(dauthNonBlockingRequest, List(invalidJwt)) Then("We should get a 400 - Bad Request") logger.debug("-----------------------------------------") - logger.debug("responseNonBlockingInvalid responseNonBlocking: "+responseNonBlockingInvalid) + logger.debug("responseNonBlockingInvalid responseNonBlocking: " + responseNonBlockingInvalid) logger.debug("-----------------------------------------") responseNonBlockingInvalid.code should equal(401) responseNonBlockingInvalid.toString contains (ErrorMessages.DAuthJwtTokenIsNotValid) should be (true) @@ -71,7 +70,7 @@ class dauthTest extends ServerSetup with BeforeAndAfter with DefaultUsers with P When("We try to login with an valid JWT") val responseNonBlockingValidJwt = makeGetRequest(dauthNonBlockingRequest, List(validJwt)) logger.debug("-----------------------------------------") - logger.debug("responseNonBlockingValidJwt responseNonBlocking: "+responseNonBlockingValidJwt) + logger.debug("responseNonBlockingValidJwt responseNonBlocking: " + responseNonBlockingValidJwt) logger.debug("-----------------------------------------") responseValidJwt.code should equal(200) } diff --git a/obp-api/src/test/scala/code/setup/ServerSetup.scala b/obp-api/src/test/scala/code/setup/ServerSetup.scala index 8a26eeefe..57562d71f 100644 --- a/obp-api/src/test/scala/code/setup/ServerSetup.scala +++ b/obp-api/src/test/scala/code/setup/ServerSetup.scala @@ -27,6 +27,8 @@ TESOBE (http://www.tesobe.com/) package code.setup +import java.net.URI + import _root_.net.liftweb.json.JsonAST.JObject import code.TestServer import code.api.util.APIUtil._ @@ -48,6 +50,9 @@ trait ServerSetup extends FeatureSpec with SendServerRequests setPropsValues("allow_dauth" -> "true") setPropsValues("dauth.host" -> "127.0.0.1") setPropsValues("jwt.token_secret"->"your-at-least-256-bit-secret-token") + val basePath = this.getClass.getResource("/").toString .replaceFirst("target[/\\\\].*$", "") + val filePath = new URI(s"${basePath}/src/test/resources/cert/public_dauth.pem").getPath + setPropsValues("jwt.public_key_rsa" -> filePath) val server = TestServer def baseRequest = host(server.host, server.port) From 606d665bcb0f35d36267645cc92cdeef676c8047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Nov 2021 08:56:24 +0100 Subject: [PATCH 224/293] test/DAuth; Add file public_dauth.pem --- .../src/main/scala/code/api/util/JwtUtil.scala | 2 +- .../src/test/resources/cert/public_dauth.pem | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/test/resources/cert/public_dauth.pem diff --git a/obp-api/src/main/scala/code/api/util/JwtUtil.scala b/obp-api/src/main/scala/code/api/util/JwtUtil.scala index 301d4e707..b82b44cea 100644 --- a/obp-api/src/main/scala/code/api/util/JwtUtil.scala +++ b/obp-api/src/main/scala/code/api/util/JwtUtil.scala @@ -241,7 +241,7 @@ object JwtUtil extends MdcLoggable { def validateJwtWithRsaKey(jwtString: String): Boolean = { val relativePath = APIUtil.getPropsValue("jwt.public_key_rsa", "") val basePath = this.getClass.getResource("/").toString .replaceFirst("target[/\\\\].*$", "") - val filePath = new URI(s"${basePath}/$relativePath").getPath + val filePath = new URI(s"${basePath}$relativePath").getPath val publicKey = getPublicRsaKeyFromFile(filePath) val signedJWT = SignedJWT.parse(jwtString) val verifier = new RSASSAVerifier(publicKey) diff --git a/obp-api/src/test/resources/cert/public_dauth.pem b/obp-api/src/test/resources/cert/public_dauth.pem new file mode 100644 index 000000000..d6562bc8a --- /dev/null +++ b/obp-api/src/test/resources/cert/public_dauth.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICsjCCAZqgAwIBAgIGAX0EbA7DMA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNVBAMM +D2FwcC5leGFtcGxlLmNvbTAeFw0yMTExMDkxMTE4NTBaFw0yMzExMDkxMTE4NTBa +MBoxGDAWBgNVBAMMD2FwcC5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALBf/GQFAiT3c6eeiNbF+G3qHgy5xPOHrgsCr13Vkh2CL5x1 +AoIG7eHSDTZFcIrW7cescf6KEqYSQil5Z64GiwxbaXT3CPZI6wHpc7S0FD89WQVQ +yeJSUr8me0LLOQ5YCmnJ6fn41X4K2PCekJx86vgF4Wbgw5+35Ud9vTxWYVkM247i +O4MdiVR9fd53o9eAOsVJxSJ8ITw41tomqp0h6Wuam9MMuEOIwo48KSMAR+Lx2XmF +9nUIAsxyVFhYibSVT0lnt2OPtm9x/PYEswC0HSM2YNKb31gOyDrGBwrLCDXRArnk +dBSWeK63n85LtK2Th/rf6Qy01aG4e+LFx3f6YI0CAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAonMKkbeqcUOdzqRQ4yE3Did3yM3oxaN2vuB0g4QQ85u++xdGNl5wnl9j +xDzkkvjgO8x1YHsfF0+YoOxF04ObQkZqG8NJUNazPIkRwkEUj5QFQ9YA9uoShaS6 +78w+eXunb6BkPuPsj/nzcB8loUrBgUwfB3NvUx9oCL6snB4iuS7PULtSZ894kXi+ +lyk8C3uuY4o050CQ23LmNtV49yTrzYpE3sLtx3s8u3MxcEEDazvKW9x0o4/Y2sSx +iN7YfI2sF3Jldp2zrlWIoboQMnrJoT5KmKpolRmlR5iEl23fYmzi7Hn+piXrvmS/ +IiACsMLX56d+ggduyvrWnqiWPjvKDA== +-----END CERTIFICATE----- \ No newline at end of file From 895f44f9acd27375a59e58adbeb8934a2f5e36e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Nov 2021 09:23:05 +0100 Subject: [PATCH 225/293] test/Tweak value of the props jwt.public_key_rsa --- obp-api/src/test/scala/code/setup/ServerSetup.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/obp-api/src/test/scala/code/setup/ServerSetup.scala b/obp-api/src/test/scala/code/setup/ServerSetup.scala index 57562d71f..2a77bc0ac 100644 --- a/obp-api/src/test/scala/code/setup/ServerSetup.scala +++ b/obp-api/src/test/scala/code/setup/ServerSetup.scala @@ -50,9 +50,7 @@ trait ServerSetup extends FeatureSpec with SendServerRequests setPropsValues("allow_dauth" -> "true") setPropsValues("dauth.host" -> "127.0.0.1") setPropsValues("jwt.token_secret"->"your-at-least-256-bit-secret-token") - val basePath = this.getClass.getResource("/").toString .replaceFirst("target[/\\\\].*$", "") - val filePath = new URI(s"${basePath}/src/test/resources/cert/public_dauth.pem").getPath - setPropsValues("jwt.public_key_rsa" -> filePath) + setPropsValues("jwt.public_key_rsa" -> "src/test/resources/cert/public_dauth.pem") val server = TestServer def baseRequest = host(server.host, server.port) From ce862ef94bf846ead8843f0aa696a0baaaf618b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Nov 2021 10:52:01 +0100 Subject: [PATCH 226/293] docfix/Tweak documentation at endpoint createHistoricalTransactionAtBank --- .../scala/code/api/v4_0_0/APIMethods400.scala | 49 +------------------ 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 4c61c0ed2..a6a1fba44 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4731,53 +4731,8 @@ trait APIMethods400 { |So: |When you need the account to account, just omit counterparty_id field.eg: |{ - | "from": { - | "bank_id": "gh.29.uk", - | "account_id": "1ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - | }, - | "to": { - | "bank_id": "gh.29.uk", - | "account_id": "2ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - | }, - | "value": { - | "currency": "GBP", - | "amount": "10" - | }, - | "description": "this is for work", - | "posted": "2017-09-19T02:31:05Z", - | "completed": "2017-09-19T02:31:05Z", - | "type": "SANDBOX_TAN", - | "charge_policy": "SHARED" - |} - | - |When you need the counterparty to counterparty, need to omit bank_id and account_id field.eg: - |{ - | "from": { - | "counterparty_id": "f6392b7d-4218-45ea-b9a7-eaa71c0202f9" - | }, - | "to": { - | "counterparty_id": "26392b7d-4218-45ea-b9a7-eaa71c0202f9" - | }, - | "value": { - | "currency": "GBP", - | "amount": "10" - | }, - | "description": "this is for work", - | "posted": "2017-09-19T02:31:05Z", - | "completed": "2017-09-19T02:31:05Z", - | "type": "SANDBOX_TAN", - | "charge_policy": "SHARED" - |} - | - |or, you can counterparty to account - |{ - | "from": { - | "counterparty_id": "f6392b7d-4218-45ea-b9a7-eaa71c0202f9" - | }, - | "to": { - | "bank_id": "gh.29.uk", - | "account_id": "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - | }, + | "from_account_id": "1ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + | "to_account_id": "2ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", | "value": { | "currency": "GBP", | "amount": "10" From 1d02faf4c5b7ef44554673ec61ebf83a7cd7e6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Nov 2021 11:09:15 +0100 Subject: [PATCH 227/293] docfix/Tweak documentation at endpoint createHistoricalTransactionAtBank 2 --- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index a6a1fba44..5b262f84a 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4723,11 +4723,10 @@ trait APIMethods400 { "/banks/BANK_ID/management/historical/transactions", "Create Historical Transactions ", s""" - |Import the historical transactions. + |Create historical transactions at one Bank | - |The fields bank_id, account_id, counterparty_id in the json body are all optional ones. - |It support transfer money from account to account, account to counterparty and counterparty to counterparty - |Both bank_id + account_id and counterparty_id can identify the account, so OBP only need one of them to make the payment. + |Use this endpoint to create transactions between any two accounts at the same bank. + |From account and to account must be at the same bank. |So: |When you need the account to account, just omit counterparty_id field.eg: |{ From 94001269a9aed76ea6b854a794ec32ebc8b2520d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 10 Nov 2021 11:17:12 +0100 Subject: [PATCH 228/293] docfix/Tweak documentation at endpoint createHistoricalTransactionAtBank 3 --- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 5b262f84a..49d4cfc75 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4727,8 +4727,7 @@ trait APIMethods400 { | |Use this endpoint to create transactions between any two accounts at the same bank. |From account and to account must be at the same bank. - |So: - |When you need the account to account, just omit counterparty_id field.eg: + |Example: |{ | "from_account_id": "1ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", | "to_account_id": "2ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", From ed9a2aa1a48a542cc0340fa321ba073042eef396 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 10 Nov 2021 17:13:16 +0100 Subject: [PATCH 229/293] refactor/use the callContext.userId to prepare the headers --- .../code/bankconnectors/rest/RestConnector_vMar2019.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 1d9c6dc33..c412085f6 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -42,6 +42,7 @@ import code.api.util.{APIUtil, CallContext, OBPQueryParam} import code.api.v4_0_0.dynamic.MockResponseHolder import code.bankconnectors._ import code.bankconnectors.vJune2017.AuthInfo +import code.context.UserAuthContextProvider import code.customer.internalMapping.MappedCustomerIdMappingProvider import code.kafka.KafkaHelper import code.model.dataAccess.internalMapping.MappedAccountIdMappingProvider @@ -6581,10 +6582,10 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable ): List[HttpHeader] = { val needSignatureHead = APIUtil.getPropsAsBoolValue("rest_connector_sends_x-sign_header", false) - val generalContext = callContext.flatMap(_.toOutboundAdapterCallContext.generalContext).getOrElse(List.empty[BasicGeneralContext]) + val generalContext = callContext.map(createBasicUserAuthContextJsonFromCallContext(_)).getOrElse(List.empty[BasicGeneralContext]) val headersFromGeneralContext = generalContext.map(generalContext => RawHeader(generalContext.key,generalContext.value)) - val basicUserAuthContexts: List[BasicUserAuthContext] = callContext.flatMap(_.toOutboundAdapterCallContext.outboundAdapterAuthInfo.flatMap(_.userAuthContext)).getOrElse(List.empty[BasicUserAuthContext]) + val basicUserAuthContexts = UserAuthContextProvider.userAuthContextProvider.vend.getUserAuthContextsBox(callContext.map(_.userId).getOrElse("")).getOrElse(List.empty[UserAuthContext]) val headersFromUserAuthContext = basicUserAuthContexts.filterNot(_.key == "private-key").map(userAuthContext =>RawHeader(userAuthContext.key,userAuthContext.value)) val timeStamp = Instant.now.getEpochSecond.toString From f7b50239e0502c22827877f57a552db59b7de522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 11 Nov 2021 07:52:09 +0100 Subject: [PATCH 230/293] docfix/Tweak DAuth glossary documentation --- .../main/scala/code/api/util/Glossary.scala | 35 +++---------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index b9bb44450..10a560b8a 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2045,7 +2045,7 @@ object Glossary extends MdcLoggable { |``` |# -- DAuth -------------------------------------- |# Define secret used to validate JWT token -|# jwt.token_secret=your-at-least-256-bit-secret-token +|# jwt.public_key_rsa=path-to-the-pem-file |# Enable/Disable DAuth communication at all |# In case isn't defined default value is false |# allow_dauth=false @@ -2053,11 +2053,12 @@ object Glossary extends MdcLoggable { |# dauth.host=127.0.0.1 |# -------------------------------------- DAuth-- |``` -|Please keep in mind that property jwt.token_secret is used to validate JWT token to check it is not changed or corrupted during transport. +|Please keep in mind that property jwt.public_key_rsa is used to validate JWT token to check it is not changed or corrupted during transport. | |### 2) Create / have access to a JWT | -| +|The following videos are available: +| * [DAuth in local environment](https://vimeo.com/644315074) | |HEADER:ALGORITHM & TOKEN TYPE | @@ -2110,7 +2111,7 @@ object Glossary extends MdcLoggable { | |Headers: | -| Authorization: DAuth token="your-jwt-from-step-above" +| DAuth: your-jwt-from-step-above | |Here is it all together: | @@ -2142,32 +2143,6 @@ object Glossary extends MdcLoggable { |} |``` | -|### Example python script -|``` -|import jwt -|from datetime import datetime, timezone -|import requests -| -|env = 'local' -|DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' -| -|obp_api_host = '$getServerUrl' -|payload = { -| "smart_contract_address": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", -| "network_name": "ETHEREUM", -| "consumer_key": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", -| "timestamp": datetime.now(timezone.utc).strftime(DATE_FORMAT), -| "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", -| "request_id": "0Xe876987694328763492876348928736497869273649" -|} -| -|token = jwt.encode(payload, 'your-at-least-256-bit-secret-token', algorithm='HS256').decode("utf-8") -|headers = {'DAuth': token} -|url = obp_api_host + '/obp/v4.0.0/users/current' -|req = requests.get(url, headers=headers) -|print(req.text) -|``` -| |### Under the hood | |The file, dauth.scala handles the DAuth, From dce6d78e428572ee228bad3ff62ce5a54456cbfc Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Fri, 12 Nov 2021 10:14:18 +0000 Subject: [PATCH 231/293] Tweaking DAuth glossary item --- .../main/scala/code/api/util/Glossary.scala | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 10a560b8a..e9a9e6b8e 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2024,23 +2024,38 @@ object Glossary extends MdcLoggable { title = APIUtil.DAuthHeaderKey, description = s""" - |### Introduction + |### DAuth Introduction, Setup and Usage +| +| +|DAuth is an experimental authentication mechanism that aims to pin an ethereum or other blockchain Smart Contract to an OBP "User". +| +|In the future, it might be possible to be more specific and pin specific actors (wallets) that are acting within the smart contract, but so far, one smart contract acts on behalf of one User. +| +|Thus, if a smart contract "X" calls the OBP API using the DAuth header, OBP will get or create a user called X and the call will proceed in the context of that User "X". +| +| +|DAuth is invoked by the REST client (caller) including a specific header (see step 3 below) in any OBP REST call. +| +|When OBP receives the DAuth token, it creates or gets a User with a username based on the smart_contract_address and the provider based on the network_name. The combination of username and provider is unique in OBP. +| +|If you are calling OBP-API via an API3 Airnode, the Airnode will take care of constructing the required header. +| +|When OBP detects an DAuth header / token it first checks if the Consumer is allowed to make such a call. OBP will validate the Consumer ip address and signature etc. +| +|Note: The DAuth flow does *not* require an explicit POST like Direct Login to create the token. +| +|Permissions may be assigned to an OBP User at any time, via the UserAuthContext, Views, Entitlements to Roles or Consents. | |$dauthEnabledMessage | -|DAuth Authorisation is made by including a specific header (see step 3 below) in any OBP REST call. +|Note: *The DAuth client is responsible for creating a token which will be trusted by OBP absolutely*! | -|Note: DAuth does *not* require an explicit POST like Direct Login to create the token. -| -|The **DAuth is responsible** for creating a token which is trusted by OBP **absolutely**! -| -|When OBP receives a token via DAuth, OBP creates or gets a user based on the username (smart_contract_address) supplied. | |To use DAuth: | |### 1) Configure OBP API to accept DAuth. | -|Set up properties in a props file +|Set up properties in your props file | |``` |# -- DAuth -------------------------------------- @@ -2073,7 +2088,7 @@ object Glossary extends MdcLoggable { |``` |{ | "smart_contract_address": "0xe123425E7734CE288F8367e1Bb143E90bb3F051224", -| "network_name": "ETHEREUM", +| "network_name": "AIRNODE.TESTNET.ETHEREUM", | "msg_sender": "0xe12340927f1725E7734CE288F8367e1Bb143E90fhku767", | "consumer_key": "0x1234a4ec31e89cea54d1f125db7536e874ab4a96b4d4f6438668b6bb10a6adb", | "timestamp": "2021-11-04T14:13:40Z", @@ -2089,7 +2104,7 @@ object Glossary extends MdcLoggable { |) your-at-least-256-bit-secret-token |``` | -|Here is the above example token: +|Here is an example token: | |``` |eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzbWFydF9jb250cmFjdF9hZGRyZXNzIjoiMHhlMTIzNDI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGJiM0YwNTEyMjQiLCJuZXR3b3JrX25hbWUiOiJFVEhFUkVVTSIsIm1zZ19zZW5kZXIiOiIweGUxMjM0MDkyN2YxNzI1RTc3MzRDRTI4OEY4MzY3ZTFCYjE0M0U5MGZoa3U3NjciLCJjb25zdW1lcl9rZXkiOiIweDEyMzRhNGVjMzFlODljZWE1NGQxZjEyNWRiNzUzNmU4NzRhYjRhOTZiNGQ0ZjY0Mzg2NjhiNmJiMTBhNmFkYiIsInRpbWVzdGFtcCI6IjIwMjEtMTEtMDRUMTQ6MTM6NDBaIiwicmVxdWVzdF9pZCI6IjBYZTg3Njk4NzY5NDMyODc2MzQ5Mjg3NjM0ODkyODczNjQ5Nzg2OTI3MzY0OSJ9.XSiQxjEVyCouf7zT8MubEKsbOBZuReGVhnt9uck6z6k From b72c4dbb4d4b6c064b4bb4ec04385f2ec0c75942 Mon Sep 17 00:00:00 2001 From: tawoe Date: Fri, 12 Nov 2021 15:17:32 +0100 Subject: [PATCH 232/293] docfix / dauth --- obp-api/src/main/scala/code/api/util/Glossary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index e9a9e6b8e..f6eda2e31 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2079,7 +2079,7 @@ object Glossary extends MdcLoggable { | |``` |{ -| "alg": "HS256", +| "alg": "RS256", | "typ": "JWT" |} |``` From ca31087565af830c38543462565a5d40d87bf577 Mon Sep 17 00:00:00 2001 From: tawoe Date: Fri, 12 Nov 2021 17:05:14 +0100 Subject: [PATCH 233/293] docfix / dauth --- obp-api/src/main/scala/code/api/util/Glossary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index f6eda2e31..77d2304be 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2097,7 +2097,7 @@ object Glossary extends MdcLoggable { |``` |VERIFY SIGNATURE |``` -|HMACSHA256( +|RSASHA256( | base64UrlEncode(header) + "." + | base64UrlEncode(payload), | From d93f622203ebf4256c43b3d13ddbe60558f24d85 Mon Sep 17 00:00:00 2001 From: tawoe Date: Fri, 12 Nov 2021 17:07:15 +0100 Subject: [PATCH 234/293] docfix / dauth --- obp-api/src/main/scala/code/api/util/Glossary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 77d2304be..4be54dfca 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2101,7 +2101,7 @@ object Glossary extends MdcLoggable { | base64UrlEncode(header) + "." + | base64UrlEncode(payload), | -|) your-at-least-256-bit-secret-token +|) your-RSA-key-pair |``` | |Here is an example token: From aa300e71259549e722306ee7ff8429730afd32f6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 15 Nov 2021 17:29:03 +0100 Subject: [PATCH 235/293] feature/OBPv400 added new endpoint createUserWithAccountAccess --- .../SwaggerDefinitionsJSON.scala | 5 ++ .../scala/code/api/util/ErrorMessages.scala | 1 + .../main/scala/code/api/util/NewStyle.scala | 18 +++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 77 +++++++++++++++++-- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 1 + 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index fd0d420d4..4d62411bd 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4088,6 +4088,11 @@ object SwaggerDefinitionsJSON { ) val postAccountAccessJsonV400 = PostAccountAccessJsonV400(userIdExample.value, PostViewJsonV400(ExampleValue.viewIdExample.value, true)) + val postCreateUserAccountAccessJsonV400 = PostCreateUserAccountAccessJsonV400( + userIdExample.value, + providerExample.value, + List(PostViewJsonV400(ExampleValue.viewIdExample.value, true)) + ) val revokedJsonV400 = RevokedJsonV400(true) val postRevokeGrantAccountAccessJsonV400 = PostRevokeGrantAccountAccessJsonV400(List("ReadAccountsBasic")) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 50a057f4b..1d3dc1c11 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -192,6 +192,7 @@ object ErrorMessages { val InvalidDAuthHeaderToken = "OBP-20072: DAuth Header value should be one single string." val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " + val CannotGetOrCreateUser = "OBP-20102: Cannot get or create user." // OAuth 2 val ApplicationNotIdentified = "OBP-20200: The application cannot be identified. " diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 72648d7fa..f3ac7659a 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1034,6 +1034,24 @@ object NewStyle { } } + def getOrCreateUser(userId: String, provider: String, callContext: Option[CallContext]): OBPReturnType[User] = { + Future { UserX.findByUserId(userId).or( //first try to find the user by userId + Users.users.vend.createResourceUser( // Otherwise create a new user + provider = provider, + providerId = Some(userId), + None, + name = Some(userId), + email = None, + userId = Some(userId), + createdByUserInvitationId = None, + company = None, + lastMarketingAgreementSignedDate = None + ) + ).map(user =>(user, callContext))} map { + unboxFullOrFail(_, callContext, s"$CannotGetOrCreateUser Current USER_ID($userId) PROVIDER ($provider)", 404) + } + } + def createTransactionRequestv210( u: User, viewId: ViewId, diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 49d4cfc75..1bef54f8b 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4154,14 +4154,8 @@ trait APIMethods400 { } _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, cc.callContext) - view <- postJson.view.is_system match { - case true => NewStyle.function.systemView(ViewId(postJson.view.view_id), callContext) - case false => NewStyle.function.customView(ViewId(postJson.view.view_id), BankIdAccountId(bankId, accountId), callContext) - } - addedView <- postJson.view.is_system match { - case true => NewStyle.function.grantAccessToSystemView(bankId, accountId, view, user, callContext) - case false => NewStyle.function.grantAccessToCustomView(view, user, callContext) - } + view <- checkView(bankId, accountId, postJson.view, callContext) + addedView <- createAccountAccessToUser(bankId, accountId, user, view, callContext) } yield { val viewJson = JSONFactory300.createViewJSON(addedView) (viewJson, HttpCode.`201`(callContext)) @@ -4169,6 +4163,50 @@ trait APIMethods400 { } } + staticResourceDocs += ResourceDoc( + createUserWithAccountAccess, + implementedInApiVersion, + nameOf(createUserWithAccountAccess), + "POST", + "/banks/BANK_ID/accounts/ACCOUNT_ID/user-account-access", + "Create User with Account Access", + s"""This will create the User with user_id and provider if it does not exist . + | + |${authenticationRequiredMessage(true)} and the loggedin user needs to be account holder. + | + |""", + postCreateUserAccountAccessJsonV400, + List(viewJsonV300), + List( + $UserNotLoggedIn, + UserMissOwnerViewOrNotAccountHolder, + InvalidJsonFormat, + SystemViewNotFound, + ViewNotFound, + CannotGrantAccountAccess, + UnknownError + ), + List(apiTagAccountAccess, apiTagView, apiTagAccount, apiTagUser, apiTagOwnerRequired, apiTagNewStyle)) + + lazy val createUserWithAccountAccess : OBPEndpoint = { + //add access for specific user to a specific system view + case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "user-account-access" :: Nil JsonPost json -> _ => { + cc => + val failMsg = s"$InvalidJsonFormat The Json body should be the $PostAccountAccessJsonV400 " + for { + postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { + json.extract[PostCreateUserAccountAccessJsonV400] + } + _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) + (user, callContext) <- NewStyle.function.getOrCreateUser(postJson.user_id, postJson.provider, cc.callContext) + views <- checkViews(bankId, accountId, postJson, callContext) + addedView <- createAccountAccessesToUser(bankId, accountId, user, views, callContext) + } yield { + val viewsJson = addedView.map(JSONFactory300.createViewJSON(_)) + (viewsJson, HttpCode.`201`(callContext)) + } + } + } staticResourceDocs += ResourceDoc( revokeUserAccessToView, @@ -10741,6 +10779,29 @@ trait APIMethods400 { } + private def createAccountAccessToUser(bankId: BankId, accountId: AccountId, user: User, view: View, callContext: Option[CallContext]) = { + view.isSystem match { + case true => NewStyle.function.grantAccessToSystemView(bankId, accountId, view, user, callContext) + case false => NewStyle.function.grantAccessToCustomView(view, user, callContext) + } + } + private def createAccountAccessesToUser(bankId: BankId, accountId: AccountId, user: User, views: List[View], callContext: Option[CallContext]) = { + Future.sequence(views.map(view => + createAccountAccessToUser(bankId: BankId, accountId: AccountId, user: User, view, callContext: Option[CallContext]) + )) + } + + private def checkView(bankId: BankId, accountId: AccountId, postView: PostViewJsonV400, callContext: Option[CallContext]) = { + postView.is_system match { + case true => NewStyle.function.systemView(ViewId(postView.view_id), callContext) + case false => NewStyle.function.customView(ViewId(postView.view_id), BankIdAccountId(bankId, accountId), callContext) + } + } + + private def checkViews(bankId: BankId, accountId: AccountId, postJson: PostCreateUserAccountAccessJsonV400, callContext: Option[CallContext]) = { + Future.sequence(postJson.views.map(view => checkView(bankId: BankId, accountId: AccountId, view: PostViewJsonV400, callContext: Option[CallContext]))) + } + private def createDynamicEndpointMethod(bankId: Option[String], json: JValue, cc: CallContext) = { for { (postedJson, openAPI) <- NewStyle.function.tryons(InvalidJsonFormat, 400, cc.callContext) { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 0c54094a0..1dfa471d5 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -355,6 +355,7 @@ case class StandingOrderJsonV400(standing_order_id: String, active: Boolean) case class PostViewJsonV400(view_id: String, is_system: Boolean) case class PostAccountAccessJsonV400(user_id: String, view: PostViewJsonV400) +case class PostCreateUserAccountAccessJsonV400(user_id: String, provider:String, views: List[PostViewJsonV400]) case class PostRevokeGrantAccountAccessJsonV400(views: List[String]) case class RevokedJsonV400(revoked: Boolean) From 6fc4fc3ada28dddd3865de6d702d0f619e41fd72 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 15 Nov 2021 17:37:21 +0100 Subject: [PATCH 236/293] test/OBPv400 added the tests for createUserWithAccountAccess --- .../scala/code/api/v4_0_0/AccountAccessTest.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala index 285838a8f..6fe224600 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala @@ -28,6 +28,7 @@ class AccountAccessTest extends V400ServerSetup { object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.grantUserAccessToView)) object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.revokeUserAccessToView)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.createUserWithAccountAccess)) lazy val bankId = randomBankId @@ -70,7 +71,7 @@ class AccountAccessTest extends V400ServerSetup { } } - feature(s"test $ApiEndpoint1 and $ApiEndpoint2 version $VersionOfApi - Authorized access") { + feature(s"test $ApiEndpoint1 and $ApiEndpoint2 and $ApiEndpoint3 version $VersionOfApi - Authorized access") { scenario("We will call the endpoint with user credentials", VersionOfApi, ApiEndpoint1, ApiEndpoint2) { val addedEntitlement: Box[Entitlement] = Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, ApiRole.CanCreateAccount.toString) @@ -95,6 +96,17 @@ class AccountAccessTest extends V400ServerSetup { Then("We should get a 201 and check the response body") responseRevoke.code should equal(201) responseRevoke.body.extract[RevokedJsonV400] + + { + val postCreateUserJson = PostCreateUserAccountAccessJsonV400(resourceUser2.userId, resourceUser2.provider, List(PostViewJsonV400(view.id, view.is_system))) + When("We send the request") + val request = (v4_0_0_Request / "banks" / bankId / "accounts" / account.account_id / "user-account-access").POST <@ (user1) + val response = makePostRequest(request, write(postCreateUserJson)) + Then("We should get a 201 and check the response body") + response.code should equal(201) + val views = response.body.extract[List[ViewJsonV300]] + views.length + } } } From c5e20ed8e9fcacc156629519a3d07641b9ac33b1 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 15 Nov 2021 22:54:30 +0100 Subject: [PATCH 237/293] feature/OBPv400 added new endpoint -createUserWithRoles --- .../SwaggerDefinitionsJSON.scala | 5 + .../scala/code/api/v4_0_0/APIMethods400.scala | 128 +++++++++++++++++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 4 +- 3 files changed, 130 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 4d62411bd..0ed1a0c3d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4093,6 +4093,11 @@ object SwaggerDefinitionsJSON { providerExample.value, List(PostViewJsonV400(ExampleValue.viewIdExample.value, true)) ) + val postCreateUserWithRolesJsonV400 = PostCreateUserWithRolesJsonV400( + userIdExample.value, + providerExample.value, + List(createEntitlementJSON) + ) val revokedJsonV400 = RevokedJsonV400(true) val postRevokeGrantAccountAccessJsonV400 = PostRevokeGrantAccountAccessJsonV400(List("ReadAccountsBasic")) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 1bef54f8b..356474df2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -19,7 +19,7 @@ import code.api.v1_2_1.{JSONFactory, PostTransactionTagJSON} import code.api.v1_4_0.JSONFactory1_4_0 import code.api.v1_4_0.JSONFactory1_4_0.TransactionRequestAccountJsonV140 import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0 -import code.api.v2_0_0.{EntitlementJSONs, JSONFactory200} +import code.api.v2_0_0.{CreateEntitlementJSON, EntitlementJSONs, JSONFactory200} import code.api.v2_1_0._ import code.api.v3_0_0.JSONFactory300 import code.api.v3_1_0._ @@ -73,7 +73,7 @@ import net.liftweb.json.JsonDSL._ import net.liftweb.json.Serialization.write import net.liftweb.json.{compactRender, prettyRender, _} import net.liftweb.mapper.By -import net.liftweb.util.Helpers.now +import net.liftweb.util.Helpers.{now, tryo} import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To, XHTMLMailBodyType} import net.liftweb.util.{Helpers, Mailer, StringHelpers} import org.apache.commons.collections4.CollectionUtils @@ -2735,7 +2735,72 @@ trait APIMethods400 { } } } - + staticResourceDocs += ResourceDoc( + createUserWithRoles, + implementedInApiVersion, + nameOf(createUserWithRoles), + "POST", + "/user-entitlements", + "Create User with Roles", + """This will create the User with user_id and provider if it does not exist + | + |Create Entitlement. Grant Role to User. + | + |Entitlements are used to grant System or Bank level roles to Users. (For Account level privileges, see Views) + | + |For a System level Role (.e.g CanGetAnyUser), set bank_id to an empty string i.e. "bank_id":"" + | + |For a Bank level Role (e.g. CanCreateAccount), set bank_id to a valid value e.g. "bank_id":"my-bank-id" + | + |Authentication is required and the user needs to be a Super Admin. Super Admins are listed in the Props file.""", + postCreateUserWithRolesJsonV400, + List(entitlementJSON), + List( + UserNotLoggedIn, + UserNotFoundById, + UserNotSuperAdmin, + InvalidJsonFormat, + IncorrectRoleName, + EntitlementIsBankRole, + EntitlementIsSystemRole, + EntitlementAlreadyExists, + UnknownError + ), + List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), + Some(List(canCreateEntitlementAtOneBank,canCreateEntitlementAtAnyBank))) + + lazy val createUserWithRoles: OBPEndpoint = { + case "user-entitlements" :: Nil JsonPost json -> _ => { + cc => + for { + (Full(loggedInUser), callContext) <- authenticatedAccess(cc) + failMsg = s"$InvalidJsonFormat The Json body should be the $PostCreateUserWithRolesJsonV400 " + postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[PostCreateUserWithRolesJsonV400] + } + _ <- checkRolesBankId(callContext, postedData) + _ <- checkRolesBankIdExsiting(callContext, postedData) + roles <- checkRolesName(callContext, postedData) + (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + + allowedEntitlements = canCreateEntitlementAtAnyBank :: Nil + allowedEntitlementsTxt = UserNotSuperAdmin +" or" + UserHasMissingRoles + canCreateEntitlementAtAnyBank + _ <- + if(isSuperAdmin(loggedInUser.userId)) + Future.successful(Full(Unit)) + else + NewStyle.function.hasAtLeastOneEntitlement(allowedEntitlementsTxt)("", loggedInUser.userId, allowedEntitlements, callContext) + + _ <- checkIfUserHasEntitlements(postedData, callContext) + + addedEntitlements <- addEntitlementsToUser(postedData, callContext) + + } yield { + (addedEntitlements.map(JSONFactory200.createEntitlementJSON(_)), HttpCode.`201`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( getEntitlements, @@ -4175,7 +4240,7 @@ trait APIMethods400 { |${authenticationRequiredMessage(true)} and the loggedin user needs to be account holder. | |""", - postCreateUserAccountAccessJsonV400, + postCreateUserWithRolesJsonV400, List(viewJsonV300), List( $UserNotLoggedIn, @@ -4192,7 +4257,7 @@ trait APIMethods400 { //add access for specific user to a specific system view case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "user-account-access" :: Nil JsonPost json -> _ => { cc => - val failMsg = s"$InvalidJsonFormat The Json body should be the $PostAccountAccessJsonV400 " + val failMsg = s"$InvalidJsonFormat The Json body should be the $PostCreateUserAccountAccessJsonV400 " for { postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostCreateUserAccountAccessJsonV400] @@ -10779,6 +10844,59 @@ trait APIMethods400 { } + private def checkRoleBankIdExsiting(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { + Helper.booleanToFuture(failMsg = s"$BankNotFound Current BANK_ID (${entitlement.bank_id})", cc=callContext) { + entitlement.bank_id.nonEmpty == false || BankX(BankId(entitlement.bank_id), callContext).map(_._1).isEmpty == false + } + } + + private def checkRolesBankIdExsiting(callContext: Option[CallContext], postedData: PostCreateUserWithRolesJsonV400) = { + Future.sequence(postedData.roles.map(checkRoleBankIdExsiting(callContext,_))) + } + + private def addEntitlementToUser(userId:String, entitlement: CreateEntitlementJSON, callContext: Option[CallContext]) = { + Future(Entitlement.entitlement.vend.addEntitlement(entitlement.bank_id, userId, entitlement.role_name)) map { unboxFull(_) } + } + + private def addEntitlementsToUser(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { + Future.sequence(postedData.roles.map(addEntitlementToUser(postedData.user_id, _, callContext))) + } + + private def checkIfUserHasEntitlement(userId:String, entitlement: CreateEntitlementJSON, callContext: Option[CallContext]) = { + Helper.booleanToFuture(failMsg = s"$EntitlementAlreadyExists Current Entitlement (${entitlement.role_name})", cc=callContext) { + hasEntitlement(entitlement.bank_id, userId, valueOf(entitlement.role_name)) == false + } + } + + private def checkIfUserHasEntitlements(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { + Future.sequence(postedData.roles.map(checkIfUserHasEntitlement(postedData.user_id, _, callContext))) + } + + private def checkRoleBankIdRequirement(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { + Helper.booleanToFuture(failMsg = if (ApiRole.valueOf(entitlement.role_name).requiresBankId) EntitlementIsBankRole else EntitlementIsSystemRole, cc = callContext) { + ApiRole.valueOf(entitlement.role_name).requiresBankId == entitlement.bank_id.nonEmpty + } + } + + private def checkRolesBankId(callContext: Option[CallContext], postedData: PostCreateUserWithRolesJsonV400) = { + Future.sequence(postedData.roles.map(checkRoleBankIdRequirement(callContext,_))) + } + + private def checkRoleName(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { + Future{ + tryo { + valueOf(entitlement.role_name) + } + } map { + val msg = IncorrectRoleName + entitlement.role_name + ". Possible roles are " + ApiRole.availableRoles.sorted.mkString(", ") + x => unboxFullOrFail(x, callContext, msg) + } + } + + private def checkRolesName(callContext: Option[CallContext], postJsonBody: PostCreateUserWithRolesJsonV400) = { + Future.sequence(postJsonBody.roles.map(checkRoleName(callContext,_))) + } + private def createAccountAccessToUser(bankId: BankId, accountId: AccountId, user: User, view: View, callContext: Option[CallContext]) = { view.isSystem match { case true => NewStyle.function.grantAccessToSystemView(bankId, accountId, view, user, callContext) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 1dfa471d5..3e59b2237 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -28,7 +28,6 @@ package code.api.v4_0_0 import java.text.SimpleDateFormat import java.util.Date - import code.api.attributedefinition.AttributeDefinition import code.api.util.APIUtil import code.api.util.APIUtil.{DateWithDay, DateWithSeconds, stringOptionOrNull, stringOrNull} @@ -36,7 +35,7 @@ import code.api.v1_2_1.JSONFactory.{createAmountOfMoneyJSON, createOwnersJSON} import code.api.v1_2_1.{BankRoutingJsonV121, JSONFactory, UserJSONV121, ViewJSONV121} import code.api.v1_4_0.JSONFactory1_4_0.{LocationJsonV140, MetaJsonV140, TransactionRequestAccountJsonV140, transformToLocationFromV140, transformToMetaFromV140} import code.api.v2_0_0.JSONFactory200.UserJsonV200 -import code.api.v2_0_0.{EntitlementJSONs, JSONFactory200, TransactionRequestChargeJsonV200} +import code.api.v2_0_0.{CreateEntitlementJSON, EntitlementJSONs, JSONFactory200, TransactionRequestChargeJsonV200} import code.api.v2_1_0.{IbanJson, JSONFactory210, PostCounterpartyBespokeJson, ResourceUserJSON} import code.api.v2_2_0.CounterpartyMetadataJson import code.api.v3_0_0.JSONFactory300._ @@ -356,6 +355,7 @@ case class StandingOrderJsonV400(standing_order_id: String, case class PostViewJsonV400(view_id: String, is_system: Boolean) case class PostAccountAccessJsonV400(user_id: String, view: PostViewJsonV400) case class PostCreateUserAccountAccessJsonV400(user_id: String, provider:String, views: List[PostViewJsonV400]) +case class PostCreateUserWithRolesJsonV400(user_id: String, provider:String, roles: List[CreateEntitlementJSON]) case class PostRevokeGrantAccountAccessJsonV400(views: List[String]) case class RevokedJsonV400(revoked: Boolean) From 11e7a2bd9dce3396993c94851c201292f06b9b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 16 Nov 2021 11:08:41 +0100 Subject: [PATCH 238/293] feature/OpenID Connect; Enable props email_domain_to_space_mappings --- obp-api/src/main/scala/code/api/openidconnect.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/obp-api/src/main/scala/code/api/openidconnect.scala b/obp-api/src/main/scala/code/api/openidconnect.scala index f74d0129d..09f97ad98 100644 --- a/obp-api/src/main/scala/code/api/openidconnect.scala +++ b/obp-api/src/main/scala/code/api/openidconnect.scala @@ -122,6 +122,9 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { case Full(user) => // All good getOrCreateAuthUser(user) match { case Full(authUser) => + // Grant roles according to the props email_domain_to_space_mappings + AuthUser.grantEmailDomainEntitlementsToUser(authUser) + // Consumer getOrCreateConsumer(idToken, user.userId) match { case Full(consumer) => saveAuthorizationToken(tokenType, accessToken, idToken, refreshToken, scope, expiresIn, authUser.id.get) match { From 007c2226d5290a059af7bf07bbc78466da7d08ed Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 16 Nov 2021 13:22:39 +0100 Subject: [PATCH 239/293] test/OBPv400 added tests for createUserWithAccountAccess endpoint --- .../SwaggerDefinitionsJSON.scala | 11 +++++++ .../scala/code/api/v4_0_0/APIMethods400.scala | 6 ++-- .../code/api/v4_0_0/EntitlementTests.scala | 29 ++++++++++++++++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 0ed1a0c3d..ec030e79e 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4493,6 +4493,17 @@ object SwaggerDefinitionsJSON { meta = metaJson, ) + val entitlementJsonV400 = EntitlementJsonV400( + entitlement_id = entitlementIdExample.value, + role_name = roleNameExample.value, + bank_id = bankIdExample.value, + user_id = userIdExample.value, + ) + + val entitlementsJsonV400 = EntitlementsJsonV400( + list = List(entitlementJsonV400) + ) + //The common error or success format. //Just some helper format to use in Json diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 356474df2..7d4e48f37 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2796,7 +2796,7 @@ trait APIMethods400 { addedEntitlements <- addEntitlementsToUser(postedData, callContext) } yield { - (addedEntitlements.map(JSONFactory200.createEntitlementJSON(_)), HttpCode.`201`(callContext)) + (JSONFactory400.createEntitlementJSONs(addedEntitlements), HttpCode.`201`(callContext)) } } } @@ -2814,7 +2814,7 @@ trait APIMethods400 { | """.stripMargin, EmptyBody, - entitlementJSONs, + entitlementsJsonV400, List($UserNotLoggedIn, UserHasMissingRoles, UnknownError), List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), Some(List(canGetEntitlementsForAnyUserAtAnyBank))) @@ -2851,7 +2851,7 @@ trait APIMethods400 { | """.stripMargin, EmptyBody, - entitlementJSONs, + entitlementsJsonV400, List($UserNotLoggedIn, UserHasMissingRoles, UnknownError), List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), Some(List(canGetEntitlementsForOneBank,canGetEntitlementsForAnyBank))) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala index 79bf85e28..6b9b6f8c1 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala @@ -1,15 +1,19 @@ package code.api.v4_0_0 +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import com.openbankproject.commons.model.ErrorMessage -import code.api.util.ApiRole.{CanGetEntitlementsForAnyBank, CanGetEntitlementsForAnyUserAtAnyBank, CanGetEntitlementsForOneBank} +import code.api.util.ApiRole.{CanCreateBranch, CanGetEntitlementsForAnyBank, CanGetEntitlementsForAnyUserAtAnyBank, CanGetEntitlementsForOneBank, CanUpdateBranch} import code.api.util.ErrorMessages.{UserHasMissingRoles, _} import code.api.util.{ApiRole, ErrorMessages} import code.entitlement.Entitlement import code.setup.DefaultUsers import code.api.util.APIUtil.OAuth._ +import code.api.util.ExampleValue.bankIdExample +import code.api.v2_0_0.CreateEntitlementJSON import code.api.v4_0_0.APIMethods400.Implementations4_0_0 import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write import org.scalatest.Tag class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { @@ -32,6 +36,7 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.getEntitlements)) object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getEntitlementsForBank)) + object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.createUserWithRoles)) feature("Assuring that endpoint getEntitlements works as expected - v4.0.0") { @@ -109,6 +114,28 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { r.code should equal(200) } } + + scenario("We try to - createUserWithRoles", ApiEndpoint3, VersionOfApi) { + When("We add required entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanCreateEntitlementAtAnyBank.toString) + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + val entitlements = r.body.extract[EntitlementsJsonV400] + r.code should equal(201) + entitlements.list.length should be (2) + } + } } From b8f39ef5ecc331e2bf479e94cedd7acd6b68a2ca Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 16 Nov 2021 16:08:50 +0100 Subject: [PATCH 240/293] refactor/tweaked checkView -> getViews --- .../main/scala/code/api/v4_0_0/APIMethods400.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 7d4e48f37..a550472ed 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4219,7 +4219,7 @@ trait APIMethods400 { } _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, cc.callContext) - view <- checkView(bankId, accountId, postJson.view, callContext) + view <- getViews(bankId, accountId, postJson.view, callContext) addedView <- createAccountAccessToUser(bankId, accountId, user, view, callContext) } yield { val viewJson = JSONFactory300.createViewJSON(addedView) @@ -4254,7 +4254,6 @@ trait APIMethods400 { List(apiTagAccountAccess, apiTagView, apiTagAccount, apiTagUser, apiTagOwnerRequired, apiTagNewStyle)) lazy val createUserWithAccountAccess : OBPEndpoint = { - //add access for specific user to a specific system view case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "user-account-access" :: Nil JsonPost json -> _ => { cc => val failMsg = s"$InvalidJsonFormat The Json body should be the $PostCreateUserAccountAccessJsonV400 " @@ -4264,7 +4263,7 @@ trait APIMethods400 { } _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) (user, callContext) <- NewStyle.function.getOrCreateUser(postJson.user_id, postJson.provider, cc.callContext) - views <- checkViews(bankId, accountId, postJson, callContext) + views <- getViews(bankId, accountId, postJson, callContext) addedView <- createAccountAccessesToUser(bankId, accountId, user, views, callContext) } yield { val viewsJson = addedView.map(JSONFactory300.createViewJSON(_)) @@ -10909,15 +10908,15 @@ trait APIMethods400 { )) } - private def checkView(bankId: BankId, accountId: AccountId, postView: PostViewJsonV400, callContext: Option[CallContext]) = { + private def getView(bankId: BankId, accountId: AccountId, postView: PostViewJsonV400, callContext: Option[CallContext]) = { postView.is_system match { case true => NewStyle.function.systemView(ViewId(postView.view_id), callContext) case false => NewStyle.function.customView(ViewId(postView.view_id), BankIdAccountId(bankId, accountId), callContext) } } - private def checkViews(bankId: BankId, accountId: AccountId, postJson: PostCreateUserAccountAccessJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postJson.views.map(view => checkView(bankId: BankId, accountId: AccountId, view: PostViewJsonV400, callContext: Option[CallContext]))) + private def getViews(bankId: BankId, accountId: AccountId, postJson: PostCreateUserAccountAccessJsonV400, callContext: Option[CallContext]) = { + Future.sequence(postJson.views.map(view => getView(bankId: BankId, accountId: AccountId, view: PostViewJsonV400, callContext: Option[CallContext]))) } private def createDynamicEndpointMethod(bankId: Option[String], json: JValue, cc: CallContext) = { From 25924c06c71a07fba9b1ebc33f5957a17b0ea610 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 16 Nov 2021 16:45:24 +0100 Subject: [PATCH 241/293] refactor/tweaked the method name checkIfUserHasEntitlements->checkIfUserAlreadyHasEntitlements --- .../scala/code/api/v4_0_0/APIMethods400.scala | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index a550472ed..9126f803f 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2754,7 +2754,7 @@ trait APIMethods400 { | |Authentication is required and the user needs to be a Super Admin. Super Admins are listed in the Props file.""", postCreateUserWithRolesJsonV400, - List(entitlementJSON), + entitlementsJsonV400, List( UserNotLoggedIn, UserNotFoundById, @@ -2778,10 +2778,12 @@ trait APIMethods400 { postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { json.extract[PostCreateUserWithRolesJsonV400] } - _ <- checkRolesBankId(callContext, postedData) + //check the system role bankId is Empty, but bank level role need bankId + _ <- checkRoleBankIdMappings(callContext, postedData) + _ <- checkRolesBankIdExsiting(callContext, postedData) - roles <- checkRolesName(callContext, postedData) - (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + + _ <- checkRolesName(callContext, postedData) allowedEntitlements = canCreateEntitlementAtAnyBank :: Nil allowedEntitlementsTxt = UserNotSuperAdmin +" or" + UserHasMissingRoles + canCreateEntitlementAtAnyBank @@ -2790,8 +2792,10 @@ trait APIMethods400 { Future.successful(Full(Unit)) else NewStyle.function.hasAtLeastOneEntitlement(allowedEntitlementsTxt)("", loggedInUser.userId, allowedEntitlements, callContext) - - _ <- checkIfUserHasEntitlements(postedData, callContext) + + (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + + _ <- checkIfUserAlreadyHasEntitlements(postedData, callContext) addedEntitlements <- addEntitlementsToUser(postedData, callContext) @@ -10861,24 +10865,24 @@ trait APIMethods400 { Future.sequence(postedData.roles.map(addEntitlementToUser(postedData.user_id, _, callContext))) } - private def checkIfUserHasEntitlement(userId:String, entitlement: CreateEntitlementJSON, callContext: Option[CallContext]) = { + private def checkIfUserAlreadyHasEntitlement(userId:String, entitlement: CreateEntitlementJSON, callContext: Option[CallContext]) = { Helper.booleanToFuture(failMsg = s"$EntitlementAlreadyExists Current Entitlement (${entitlement.role_name})", cc=callContext) { hasEntitlement(entitlement.bank_id, userId, valueOf(entitlement.role_name)) == false } } - private def checkIfUserHasEntitlements(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postedData.roles.map(checkIfUserHasEntitlement(postedData.user_id, _, callContext))) + private def checkIfUserAlreadyHasEntitlements(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { + Future.sequence(postedData.roles.map(checkIfUserAlreadyHasEntitlement(postedData.user_id, _, callContext))) } - private def checkRoleBankIdRequirement(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { + private def checkRoleBankIdMapping(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { Helper.booleanToFuture(failMsg = if (ApiRole.valueOf(entitlement.role_name).requiresBankId) EntitlementIsBankRole else EntitlementIsSystemRole, cc = callContext) { ApiRole.valueOf(entitlement.role_name).requiresBankId == entitlement.bank_id.nonEmpty } } - private def checkRolesBankId(callContext: Option[CallContext], postedData: PostCreateUserWithRolesJsonV400) = { - Future.sequence(postedData.roles.map(checkRoleBankIdRequirement(callContext,_))) + private def checkRoleBankIdMappings(callContext: Option[CallContext], postedData: PostCreateUserWithRolesJsonV400) = { + Future.sequence(postedData.roles.map(checkRoleBankIdMapping(callContext,_))) } private def checkRoleName(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { From d6887f38154dd1f64a645059bd90008f2d5a3833 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 16 Nov 2021 16:48:35 +0100 Subject: [PATCH 242/293] feature/remove the UserNotSuperAdmin for createUserWithRoles endpoint --- .../main/scala/code/api/v4_0_0/APIMethods400.scala | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 9126f803f..d5febdcad 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2757,8 +2757,6 @@ trait APIMethods400 { entitlementsJsonV400, List( UserNotLoggedIn, - UserNotFoundById, - UserNotSuperAdmin, InvalidJsonFormat, IncorrectRoleName, EntitlementIsBankRole, @@ -2785,13 +2783,7 @@ trait APIMethods400 { _ <- checkRolesName(callContext, postedData) - allowedEntitlements = canCreateEntitlementAtAnyBank :: Nil - allowedEntitlementsTxt = UserNotSuperAdmin +" or" + UserHasMissingRoles + canCreateEntitlementAtAnyBank - _ <- - if(isSuperAdmin(loggedInUser.userId)) - Future.successful(Full(Unit)) - else - NewStyle.function.hasAtLeastOneEntitlement(allowedEntitlementsTxt)("", loggedInUser.userId, allowedEntitlements, callContext) + _ <- NewStyle.function.hasEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank, cc.callContext) (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) @@ -4223,7 +4215,7 @@ trait APIMethods400 { } _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, cc.callContext) - view <- getViews(bankId, accountId, postJson.view, callContext) + view <- getView(bankId, accountId, postJson.view, callContext) addedView <- createAccountAccessToUser(bankId, accountId, user, view, callContext) } yield { val viewJson = JSONFactory300.createViewJSON(addedView) From cbea7dff0f9ae8fa6e87ee14f546d5e9df0b6b1d Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Nov 2021 12:31:25 +0100 Subject: [PATCH 243/293] feature/added the operationId guard for createMyApiCollectionEndpoint and createMyApiCollectionEndpointById --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 1 + .../src/main/scala/code/api/v4_0_0/APIMethods400.scala | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 1d3dc1c11..ca6d8db0e 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -538,6 +538,7 @@ object ErrorMessages { val DynamicMessageDocNotFound = "OBP-40043: DynamicMessageDoc not found, please specify valid DYNAMIC_MESSAGE_DOC_ID. " val DynamicMessageDocDeleteError = "OBP-40044: DynamicMessageDoc can not be deleted. " val DynamicCodeCompileFail = "OBP-40045: The code to do compile is illegal scala code, compilation failed. " + val InvalidOperationId = "OBP-40046: Invalid operation_id, please specify valid operation_id." // Exceptions (OBP-50XXX) val UnknownError = "OBP-50000: Unknown Error." val FutureTimeoutException = "OBP-50001: Future Timeout Exception." diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index d5febdcad..a1461de30 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8300,6 +8300,10 @@ trait APIMethods400 { postJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $PostApiCollectionEndpointJson400", 400, cc.callContext) { json.extract[PostApiCollectionEndpointJson400] } + _ <- Helper.booleanToFuture(failMsg = s"$InvalidOperationId Current OPERATION_ID(${postJson.operation_id})", cc=Some(cc)) { + (DynamicEntityHelper.doc ++ DynamicEndpointHelper.doc ++ DynamicEndpoints.dynamicResourceDocs ++ OBPAPI4_0_0.allResourceDocs).toList + .find(_.operationId==postJson.operation_id).isDefined + } (apiCollection, callContext) <- NewStyle.function.getApiCollectionByUserIdAndCollectionName(cc.userId, apiCollectionName, Some(cc)) apiCollectionEndpoint <- Future{MappedApiCollectionEndpointsProvider.getApiCollectionEndpointByApiCollectionIdAndOperationId(apiCollection.apiCollectionId, postJson.operation_id)} _ <- Helper.booleanToFuture(failMsg = s"$ApiCollectionEndpointAlreadyExisting Current OPERATION_ID(${postJson.operation_id}) is already in API_COLLECTION_NAME($apiCollectionName) ", cc=callContext) { @@ -8346,6 +8350,10 @@ trait APIMethods400 { postJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $PostApiCollectionEndpointJson400", 400, cc.callContext) { json.extract[PostApiCollectionEndpointJson400] } + _ <- Helper.booleanToFuture(failMsg = s"$InvalidOperationId Current OPERATION_ID(${postJson.operation_id})", cc=Some(cc)) { + (DynamicEntityHelper.doc ++ DynamicEndpointHelper.doc ++ DynamicEndpoints.dynamicResourceDocs ++ OBPAPI4_0_0.allResourceDocs).toList + .find(_.operationId==postJson.operation_id).isDefined + } (apiCollection, callContext) <- NewStyle.function.getApiCollectionById(apiCollectioId, Some(cc)) apiCollectionEndpoint <- Future{MappedApiCollectionEndpointsProvider.getApiCollectionEndpointByApiCollectionIdAndOperationId(apiCollection.apiCollectionId, postJson.operation_id)} _ <- Helper.booleanToFuture(failMsg = s"$ApiCollectionEndpointAlreadyExisting Current OPERATION_ID(${postJson.operation_id}) is already in API_COLLECTION_ID($apiCollectioId) ", cc=callContext) { From b06c9af9800440c43d50e4b2664971ad0c3fb98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 17 Nov 2021 12:36:56 +0100 Subject: [PATCH 244/293] feature/Make RunMTLSWebApp out of the box feature --- obp-api/src/test/scala/RunMTLSWebApp.scala | 9 +++++++- .../code/setup/PropsProgrammatically.scala | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/test/scala/code/setup/PropsProgrammatically.scala diff --git a/obp-api/src/test/scala/RunMTLSWebApp.scala b/obp-api/src/test/scala/RunMTLSWebApp.scala index 1743b8925..93a50ed58 100644 --- a/obp-api/src/test/scala/RunMTLSWebApp.scala +++ b/obp-api/src/test/scala/RunMTLSWebApp.scala @@ -31,6 +31,7 @@ import java.security.cert.X509Certificate import bootstrap.liftweb.Boot import code.api.RequestHeader import code.api.util.APIUtil +import code.setup.PropsProgrammatically import net.liftweb.http.LiftRules import net.liftweb.http.provider.HTTPContext import org.apache.commons.codec.binary.Base64 @@ -39,10 +40,16 @@ import org.eclipse.jetty.util.ssl.SslContextFactory import org.eclipse.jetty.webapp.WebAppContext import sun.security.provider.X509Factory -object RunMTLSWebApp extends App { +object RunMTLSWebApp extends App with PropsProgrammatically { val servletContextPath = "/" //set run mode value to "development", So the value is true of Props.devMode System.setProperty("run.mode", "development") + // Props hostname MUST be set to https protocol. + // Otherwise OAuth1.0a computed signature at OBP-API side cannot match API-Explorer generates + // This automatic adjustment should enable out-of-box feature + APIUtil.getPropsValue("hostname").map{ x => + setPropsValues("hostname"-> x.replaceFirst("http", "https")) + } { val tempHTTPContext = JProxy.newProxyInstance(this.getClass.getClassLoader, Array(classOf[HTTPContext]), diff --git a/obp-api/src/test/scala/code/setup/PropsProgrammatically.scala b/obp-api/src/test/scala/code/setup/PropsProgrammatically.scala new file mode 100644 index 000000000..6eb21025a --- /dev/null +++ b/obp-api/src/test/scala/code/setup/PropsProgrammatically.scala @@ -0,0 +1,23 @@ +package code.setup + +import net.liftweb.util.Props +import org.apache.commons.lang3.reflect.FieldUtils +import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, Suite} + + +/** + * Any unit test that extends this trait, have a chance to set new Props value, + * after each test rollback original Props values + */ +trait PropsProgrammatically { + + private def getLockedProviders = { + FieldUtils.readDeclaredField(Props, "net$liftweb$util$Props$$lockedProviders", true) + .asInstanceOf[List[Map[String, String]]] + } + + def setPropsValues(keyValues: (String, String)*): Unit = { + val newLockedProviders = keyValues.toMap :: getLockedProviders + FieldUtils.writeDeclaredField(Props, "net$liftweb$util$Props$$lockedProviders", newLockedProviders, true) + } +} From 1acacabc548b501a2916aa6a78129dab4d099994 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Wed, 17 Nov 2021 14:11:12 +0100 Subject: [PATCH 245/293] /feature: Added XBT to fallbackExchangeRates --- obp-api/src/main/scala/code/fx/fx.scala | 40 +++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/obp-api/src/main/scala/code/fx/fx.scala b/obp-api/src/main/scala/code/fx/fx.scala index 4db9fd784..e02156040 100644 --- a/obp-api/src/main/scala/code/fx/fx.scala +++ b/obp-api/src/main/scala/code/fx/fx.scala @@ -27,21 +27,32 @@ object fx extends MdcLoggable { // Make this easier //get data from : http://www.xe.com/de/currencyconverter/convert/?Amount=1&From=AUD&To=EUR - val fallbackExchangeRates = { + // Currently There are 14 currencies with 14 mappings etc. + // We don't actually need to store the Same:Same currency (1:1) but it makes editing the map less error prone in terms of data entry! + // So keep the Map balanced. + // If get compile error with type mismatch; + // found : AnyVal + // required: Double + // check the map is complete for all combinations - (We could use getOrElse (1.0) (double) as defaults in calling function but then we risk having missing values below) + // and make sure to sure explicit doubles e.g. 1.0 rather than 1 !! + + + val fallbackExchangeRates: Map[String, Map[String, Double]] = { Map( - "GBP" -> Map("EUR" -> 1.16278, "USD" -> 1.24930, "JPY" -> 141.373, "AED" -> 4.58882, "INR" -> 84.0950, "KRW" -> 1433.92, "XAF" -> 762.826, "JOD" -> 0.936707, "ILS" -> 4.70020, "AUD" -> 1.63992 ,"HKD" -> 10.1468, "MXN" -> 29.2420), - "EUR" -> Map("GBP" -> 0.860011, "USD" -> 1.07428, "JPY" -> 121.567, "AED" -> 3.94594, "INR" -> 72.3136, "KRW" -> 1233.03, "XAF" -> 655.957, "JOD" -> 0.838098, "ILS" -> 4.20494, "AUD" -> 1.49707 ,"HKD" -> 8.88926, "MXN" -> 26.0359), - "USD" -> Map("GBP" -> 0.800446, "EUR" -> 0.930886, "JPY" -> 113.161, "AED" -> 3.67310, "INR" -> 67.3135, "KRW" -> 1147.78, "XAF" -> 610.601, "JOD" -> 0.708659, "ILS" -> 3.55495, "AUD" -> 1.27347 ,"HKD" -> 7.84766, "MXN" -> 21.7480), - "JPY" -> Map("GBP" -> 0.00707350, "EUR" -> 0.00822592, "USD" -> 0.00883695, "AED" -> 0.0324590, "INR" -> 0.594846, "KRW" -> 10.1428, "XAF" -> 5.39585, "JOD" -> 0.00639777, "ILS" -> 0.0320926, "AUD" -> 0.0114819 ,"HKD" -> 0.0709891, "MXN" -> 0.2053), - "AED" -> Map("GBP" -> 0.217921, "EUR" -> 0.253425, "USD" -> 0.272250, "JPY" -> 30.8081, "INR" -> 18.3255, "KRW" -> 312.482, "XAF" -> 166.236, "AED" -> 0.192964, "ILS" -> 0.968033, "AUD" -> 0.346779 ,"HKD" -> 2.13685, "MXN" -> 5.9217), - "INR" -> Map("GBP" -> 0.0118913, "EUR" -> 0.0138287, "USD" -> 0.0148559, "JPY" -> 1.68111, "AED" -> 0.0545671, "KRW" -> 17.0512, "XAF" -> 9.07101, "JOD" -> 0.0110959 , "ILS" -> 0.0556764, "AUD" -> 0.0198319 ,"HKD" -> 0.109972, "MXN" -> 0.2983), - "KRW" -> Map("GBP" -> 0.000697389, "EUR" -> 0.000811008, "USD" -> 0.000871250, "JPY" -> 0.0985917, "AED" -> 0.00320019, "INR" -> 0.0586469, "XAF" -> 0.531986, "JOD" -> 0.000630634, "ILS" -> 0.00316552,"AUD" -> 0.00111694,"HKD" -> 0.00697233, "MXN" -> 0.0183), - "XAF" -> Map("GBP" -> 0.00131092, "EUR" -> 0.00152449, "USD" -> 0.00163773, "JPY" -> 0.185328, "AED" -> 0.00601555, "INR" -> 0.110241, "KRW" -> 1.87975, "JOD" -> 0.00127784, "ILS" -> 0.00641333,"AUD" -> 0.00228226,"HKD" -> 0.0135503, "MXN" -> 0.0396 ), - "JOD" -> Map("GBP" -> 1.06757, "EUR" -> 0.237707, "USD" -> 1.41112, "JPY" -> 156.304, "AED" -> 5.18231, "INR" -> 90.1236, "KRW" -> 1585.68, "XAF" -> 782.572, "ILS" -> 5.02018, "AUD" -> 1.63992 ,"HKD" -> 11.0687, "MXN" -> 30.8336), - "ILS" -> Map("GBP" -> 0.212763, "EUR" -> 1.19318, "USD" -> 0.281298, "JPY" -> 31.1599, "AED" -> 1.03302, "INR" -> 17.9609, "KRW" -> 315.903, "XAF" -> 155.925, "JOD" -> 0.199196, "AUD" -> 0.352661 ,"HKD" -> 2.16985, "MXN" -> 6.4871), - "AUD" -> Map("GBP" -> 0.609788, "EUR" -> 0.667969, "USD" -> 0.785256, "JPY" -> 87.0936, "AED" -> 2.88368, "INR" -> 50.4238, "KRW" -> 895.304, "XAF" -> 438.162, "JOD" -> 0.556152, "ILS" -> 2.83558 ,"HKD" -> 5.61346 , "MXN" -> 16.0826), - "HKD" -> Map("GBP" -> 0.0985443, "EUR" -> 0.112495, "USD" -> 0.127427, "JPY" -> 14.0867, "AED" -> 0.467977, "INR" -> 9.09325, "KRW" -> 143.424, "XAF" -> 73.8049, "JOD" -> 0.0903452, "ILS" -> 0.460862 ,"AUD" -> 0.178137, "MXN" -> 2.8067), - "MXN" -> Map("GBP" -> 0.0341, "EUR" -> 0.0384, "USD" -> 0.0459, "JPY" -> 4.8687, "AED" -> 0.1688, "INR" -> 3.3513, "KRW" -> 54.4512, "XAF" -> 25.1890, "JOD" -> 0.0324, "ILS" -> 0.1541 , "AUD" -> 0.0621, "HKD" -> 0.3562 ) + "GBP" -> Map("GBP" -> 1.0, "EUR" -> 1.16278, "USD" -> 1.24930, "JPY" -> 141.373, "AED" -> 4.58882, "INR" -> 84.0950, "KRW" -> 1433.92, "XAF" -> 762.826, "JOD" -> 0.936707, "ILS" -> 4.70020, "AUD" -> 1.63992, "HKD" -> 10.1468, "MXN" -> 29.2420, "XBT" -> 0.000022756409956), + "EUR" -> Map("GBP" -> 0.860011, "EUR" -> 1.0, "USD" -> 1.07428, "JPY" -> 121.567, "AED" -> 3.94594, "INR" -> 72.3136, "KRW" -> 1233.03, "XAF" -> 655.957, "JOD" -> 0.838098, "ILS" -> 4.20494, "AUD" -> 1.49707, "HKD" -> 8.88926, "MXN" -> 26.0359, "XBT" -> 0.000019087905636), + "USD" -> Map("GBP" -> 0.800446, "EUR" -> 0.930886, "USD" -> 1.0, "JPY" -> 113.161, "AED" -> 3.67310, "INR" -> 67.3135, "KRW" -> 1147.78, "XAF" -> 610.601, "JOD" -> 0.708659, "ILS" -> 3.55495, "AUD" -> 1.27347, "HKD" -> 7.84766, "MXN" -> 21.7480, "XBT" -> 0.0000169154), + "JPY" -> Map("GBP" -> 0.00707350, "EUR" -> 0.00822592, "USD" -> 0.00883695, "JPY" -> 1.0, "AED" -> 0.0324590, "INR" -> 0.594846, "KRW" -> 10.1428, "XAF" -> 5.39585, "JOD" -> 0.00639777, "ILS" -> 0.0320926, "AUD" -> 0.0114819, "HKD" -> 0.0709891, "MXN" -> 0.2053, "XBT" -> 0.000000147171931), + "AED" -> Map("GBP" -> 0.217921, "EUR" -> 0.253425, "USD" -> 0.272250, "JPY" -> 30.8081, "AED" -> 1.0, "INR" -> 18.3255, "KRW" -> 312.482, "XAF" -> 166.236, "JOD" -> 0.1930565, "ILS" -> 0.968033, "AUD" -> 0.346779, "HKD" -> 2.13685, "MXN" -> 5.9217, "XBT" -> 0.000004603349217), + "INR" -> Map("GBP" -> 0.0118913, "EUR" -> 0.0138287, "USD" -> 0.0148559, "JPY" -> 1.68111, "AED" -> 0.0545671, "INR" -> 1.0, "KRW" -> 17.0512, "XAF" -> 9.07101, "JOD" -> 0.0110959, "ILS" -> 0.0556764, "AUD" -> 0.0198319, "HKD" -> 0.109972, "MXN" -> 0.2983, "XBT" -> 0.00000022689396), + "KRW" -> Map("GBP" -> 0.000697389, "EUR" -> 0.000811008, "USD" -> 0.000871250, "JPY" -> 0.0985917, "AED" -> 0.00320019, "INR" -> 0.0586469, "KRW" -> 1.0, "XAF" -> 0.531986, "JOD" -> 0.000630634, "ILS" -> 0.00316552, "AUD" -> 0.00111694,"HKD" -> 0.00697233,"MXN" -> 0.0183, "XBT" -> 0.000000014234725), + "XAF" -> Map("GBP" -> 0.00131092, "EUR" -> 0.00152449, "USD" -> 0.00163773, "JPY" -> 0.185328, "AED" -> 0.00601555, "INR" -> 0.110241, "KRW" -> 1.87975, "XAF" -> 1.0, "JOD" -> 0.00127784, "ILS" -> 0.00641333, "AUD" -> 0.00228226,"HKD" -> 0.0135503, "MXN" -> 0.0396, "XBT" -> 0.000000029074795), + "JOD" -> Map("GBP" -> 1.06757, "EUR" -> 0.237707, "USD" -> 1.41112, "JPY" -> 156.304, "AED" -> 5.18231, "INR" -> 90.1236, "KRW" -> 1585.68, "XAF" -> 782.572, "JOD" -> 1.0, "ILS" -> 5.02018, "AUD" -> 1.63992, "HKD" -> 11.0687, "MXN" -> 30.8336, "XBT" -> 0.000023803244006), + "ILS" -> Map("GBP" -> 0.212763, "EUR" -> 1.19318, "USD" -> 0.281298, "JPY" -> 31.1599, "AED" -> 1.03302, "INR" -> 17.9609, "KRW" -> 315.903, "XAF" -> 155.925, "JOD" -> 0.199196, "ILS" -> 1.0, "AUD" -> 0.352661, "HKD" -> 2.16985, "MXN" -> 6.4871, "XBT" -> 0.000005452272147), + "AUD" -> Map("GBP" -> 0.609788, "EUR" -> 0.667969, "USD" -> 0.785256, "JPY" -> 87.0936, "AED" -> 2.88368, "INR" -> 50.4238, "KRW" -> 895.304, "XAF" -> 438.162, "JOD" -> 0.556152, "ILS" -> 2.83558, "AUD" -> 1.0, "HKD" -> 5.61346, "MXN" -> 16.0826, "XBT" -> 0.000012284055924), + "HKD" -> Map("GBP" -> 0.0985443, "EUR" -> 0.112495, "USD" -> 0.127427, "JPY" -> 14.0867, "AED" -> 0.467977, "INR" -> 9.09325, "KRW" -> 143.424, "XAF" -> 73.8049, "JOD" -> 0.0903452, "ILS" -> 0.460862, "AUD" -> 0.178137, "HKD" -> 1.0, "MXN" -> 2.8067, "XBT" -> 0.000002164242461), + "MXN" -> Map("GBP" -> 0.0341, "EUR" -> 0.0384, "USD" -> 0.0459, "JPY" -> 4.8687, "AED" -> 0.1688, "INR" -> 3.3513, "KRW" -> 54.4512, "XAF" -> 25.1890, "JOD" -> 0.0324, "ILS" -> 0.1541, "AUD" -> 0.0621, "HKD" -> 0.3562, "MXN" -> 1.0, "XBT" -> 0.00000081112586), + "XBT" -> Map("GBP" -> 44188.118, "EUR" -> 52436.431, "USD" -> 59245.918, "JPY" -> 6805170.8, "AED" -> 217414.47, "INR" -> 4407607.74,"KRW" -> 70131575, "XAF" -> 34353824, "JOD" -> 41960.111, "ILS" -> 182981.21, "AUD" -> 81168.603, "HKD" -> 460448.90, "MXN" -> 1230503.30,"XBT" -> 1.0) ) } @@ -104,7 +115,6 @@ object fx extends MdcLoggable { } else { //logger.debug(s"fromAmount is $fromAmount, toCurrency is ${toCurrency}") val rate: Option[Double] = try { - // Get the translated name out of the map Some(fallbackExchangeRates.get(fromCurrency).get(toCurrency)) } catch { From 6836db5fd7300ac42acb4cf64194a88908b8a08b Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Wed, 17 Nov 2021 16:16:11 +0100 Subject: [PATCH 246/293] /feature Adding XBT to isValidCurrencyISOCode --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 3 ++- obp-api/src/main/scala/code/fx/fx.scala | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index e280a306f..971332fb3 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -635,7 +635,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ /** check the currency ISO code from the ISOCurrencyCodes.xml file */ def isValidCurrencyISOCode(currencyCode: String): Boolean = { - val currencyIsoCodeArray = (CurrencyIsoCodeFromXmlFile \"CcyTbl" \ "CcyNtry" \ "Ccy").map(_.text).mkString(" ").split("\\s+") + // Note: We add BTC bitcoin as XBT (the ISO compliant varient) + val currencyIsoCodeArray = (CurrencyIsoCodeFromXmlFile \"CcyTbl" \ "CcyNtry" \ "Ccy").map(_.text).mkString(" ").split("\\s+") :+ "XBT" currencyIsoCodeArray.contains(currencyCode) } diff --git a/obp-api/src/main/scala/code/fx/fx.scala b/obp-api/src/main/scala/code/fx/fx.scala index e02156040..d5935bdfd 100644 --- a/obp-api/src/main/scala/code/fx/fx.scala +++ b/obp-api/src/main/scala/code/fx/fx.scala @@ -36,6 +36,7 @@ object fx extends MdcLoggable { // check the map is complete for all combinations - (We could use getOrElse (1.0) (double) as defaults in calling function but then we risk having missing values below) // and make sure to sure explicit doubles e.g. 1.0 rather than 1 !! + // Note: If you add a non ISO standard currency below, you will also need to add it also to isValidCurrencyISOCode otherwise FX endpoints etc will fail. val fallbackExchangeRates: Map[String, Map[String, Double]] = { Map( From b96db8dcf30812f0d0ebbb4baae316a72deeabf9 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Nov 2021 16:51:26 +0100 Subject: [PATCH 247/293] feature/OBPv400 added deleteMyApiCollectionEndpointByOperationId --- .../scala/code/api/v4_0_0/APIMethods400.scala | 51 ++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index a1461de30..41ef8461a 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2752,7 +2752,7 @@ trait APIMethods400 { | |For a Bank level Role (e.g. CanCreateAccount), set bank_id to a valid value e.g. "bank_id":"my-bank-id" | - |Authentication is required and the user needs to be a Super Admin. Super Admins are listed in the Props file.""", + |""", postCreateUserWithRolesJsonV400, entitlementsJsonV400, List( @@ -8542,16 +8542,53 @@ trait APIMethods400 { } } + staticResourceDocs += ResourceDoc( + deleteMyApiCollectionEndpointByOperationId, + implementedInApiVersion, + nameOf(deleteMyApiCollectionEndpointByOperationId), + "DELETE", + "/my/api-collection-ids/API_COLLECTION_ID/api-collection-endpoints/OPERATION_ID", + "Delete My Api Collection Endpoint By Id", + s"""${Glossary.getGlossaryItem("API Collections")} + | + |Delete Api Collection Endpoint By OPERATION_ID + | + |${authenticationRequiredMessage(true)} + | + |""", + EmptyBody, + Full(true), + List( + $UserNotLoggedIn, + UserNotFoundByUserId, + UnknownError + ), + List(apiTagApiCollection, apiTagNewStyle) + ) + + lazy val deleteMyApiCollectionEndpointByOperationId : OBPEndpoint = { + case "my" :: "api-collection-ids" :: apiCollectionId :: "api-collection-endpoints" :: operationId :: Nil JsonDelete _ => { + cc => + for { + (apiCollection, callContext) <- NewStyle.function.getApiCollectionById(apiCollectionId, Some(cc) ) + (apiCollectionEndpoint, callContext) <- NewStyle.function.getApiCollectionEndpointByApiCollectionIdAndOperationId(apiCollection.apiCollectionId, operationId, callContext) + (deleted, callContext) <- NewStyle.function.deleteApiCollectionEndpointById(apiCollectionEndpoint.apiCollectionEndpointId, callContext) + } yield { + (Full(deleted), HttpCode.`204`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( deleteMyApiCollectionEndpointById, implementedInApiVersion, nameOf(deleteMyApiCollectionEndpointById), "DELETE", - "/my/api-collections-ids/API_COLLECTION_ID/api-collection-endpoints/OPERATION_ID", + "/my/api-collection-ids/API_COLLECTION_ID/api-collection-endpoint-ids/API_COLLECTION_ENDPOINT_ID", "Delete My Api Collection Endpoint By Id", s"""${Glossary.getGlossaryItem("API Collections")} - | - |Delete Api Collection Endpoint By Id + |Delete Api Collection Endpoint + |Delete Api Collection Endpoint By IdDelete Api Collection Endpoint | |${authenticationRequiredMessage(true)} | @@ -8567,18 +8604,18 @@ trait APIMethods400 { ) lazy val deleteMyApiCollectionEndpointById : OBPEndpoint = { - case "my" :: "api-collections-ids" :: apiCollectionId :: "api-collection-endpoints" :: operationId :: Nil JsonDelete _ => { + case "my" :: "api-collection-ids" :: apiCollectionId :: "api-collection-endpoint-ids" :: apiCollectionEndpointId :: Nil JsonDelete _ => { cc => for { (apiCollection, callContext) <- NewStyle.function.getApiCollectionById(apiCollectionId, Some(cc) ) - (apiCollectionEndpoint, callContext) <- NewStyle.function.getApiCollectionEndpointByApiCollectionIdAndOperationId(apiCollection.apiCollectionId, operationId, callContext) + (apiCollectionEndpoint, callContext) <- NewStyle.function.getApiCollectionEndpointById(apiCollectionEndpointId, callContext) (deleted, callContext) <- NewStyle.function.deleteApiCollectionEndpointById(apiCollectionEndpoint.apiCollectionEndpointId, callContext) } yield { (Full(deleted), HttpCode.`204`(callContext)) } } } - + staticResourceDocs += ResourceDoc( createJsonSchemaValidation, implementedInApiVersion, From f55107373e16771522426c0890318eb506e81c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 18 Nov 2021 10:13:13 +0100 Subject: [PATCH 248/293] refactor/Factor out commo code at function getUserAndSessionContextFuture --- .../main/scala/code/api/util/APIUtil.scala | 112 ++++-------------- .../main/scala/code/api/util/ApiAuth.scala | 90 ++++++++++++++ 2 files changed, 112 insertions(+), 90 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/ApiAuth.scala diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index e280a306f..91adeda00 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -45,35 +45,37 @@ import code.api.util.APIUtil.ResourceDoc.{findPathVariableNames, isPathVariable} import code.api.util.ApiRole.{canCreateProduct, canCreateProductAtAnyBank} import code.api.util.ApiTag.{ResourceDocTag, apiTagBank, apiTagNewStyle} import code.api.util.Glossary.GlossaryItem -import code.api.util.JwsUtil.getJwsHeaderValue -import code.api.util.RateLimitingJson.CallLimit import code.api.v1_2.ErrorMessage import code.api.v2_0_0.CreateEntitlementJSON -import code.api.{DirectLogin, _} import code.api.v4_0_0.dynamic.{DynamicEndpointHelper, DynamicEndpoints, DynamicEntityHelper} +import code.api.{DirectLogin, _} import code.authtypevalidation.AuthenticationTypeValidationProvider import code.bankconnectors.Connector import code.consumer.Consumers import code.customer.CustomerX import code.entitlement.Entitlement -import code.loginattempts.LoginAttempt import code.metrics._ import code.model._ import code.model.dataAccess.AuthUser -import code.ratelimiting.{RateLimiting, RateLimitingDI} import code.sanitycheck.SanityCheck import code.scope.Scope import code.usercustomerlinks.UserCustomerLink -import code.util.{Helper, JsonSchemaUtil} import code.util.Helper.{MdcLoggable, SILENCE_IS_GOLDEN} +import code.util.{Helper, JsonSchemaUtil} import code.views.Views import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.alibaba.ttl.internal.javassist.CannotCompileException import com.github.dwickern.macros.NameOf.{nameOf, nameOfType} +import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA import com.openbankproject.commons.model.enums.{PemCertificateRole, StrongCustomerAuthentication} import com.openbankproject.commons.model.{Customer, _} +import com.openbankproject.commons.util.Functions.Implicits._ +import com.openbankproject.commons.util.Functions.Memo +import com.openbankproject.commons.util._ 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.http._ @@ -85,21 +87,14 @@ import net.liftweb.json.JsonAST.{JField, JNothing, JObject, JString, JValue} import net.liftweb.json.JsonParser.ParseException import net.liftweb.json._ import net.liftweb.util.Helpers._ -import net.liftweb.util.{Helpers, LiftFlowOfControlException, Props, StringHelpers, ThreadGlobal} - -import scala.collection.JavaConverters._ -import scala.collection.immutable.{List, Nil} -import scala.collection.mutable.{ArrayBuffer, ListBuffer} -import com.openbankproject.commons.ExecutionContext.Implicits.global -import com.openbankproject.commons.util.{ApiVersion, Functions, JsonAble, ReflectUtils, ScannedApiVersion} -import com.openbankproject.commons.util.Functions.Implicits._ -import com.openbankproject.commons.util.Functions.Memo -import javassist.{ClassPool, LoaderClassPath} -import javassist.expr.{ExprEditor, MethodCall} +import net.liftweb.util._ import org.apache.commons.io.IOUtils import org.apache.commons.lang3.StringUtils +import scala.collection.JavaConverters._ +import scala.collection.immutable.{List, Nil} import scala.collection.mutable +import scala.collection.mutable.{ArrayBuffer, ListBuffer} import scala.concurrent.Future import scala.io.BufferedSource import scala.util.Either @@ -2767,80 +2762,15 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ Future { (Empty, Some(cc)) } } + // COMMON POST AUTHENTICATION CODE GOES BELOW + // Check is it a user deleted or locked - val userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])] = for { - (user: Box[User], cc) <- res - } yield { - user match { - case Full(u) => // There is a user. Check it. - if(u.isDeleted.getOrElse(false)) { - (Failure(UserIsDeleted) , cc) // The user is DELETED. - } else { - LoginAttempt.userIsLocked(u.name) match { - case true => (Failure(UsernameHasBeenLocked),cc) // The user is LOCKED. - case false => (user, cc) // All good - } - } - case _ => // There is no user. Just forward the result. - (user, cc) - } - } + val userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])] = ApiAuth.checkUserIsDeletedOrLocked(res) + // Check Rate Limiting + val resultWithRateLimiting: Future[(Box[User], Option[CallContext])] = ApiAuth.checkRateLimiting(userIsLockedOrDeleted) - - /****************************************************************************************************************** - * This block of code needs to update Call Context with Rate Limiting - * Please note that first source is the table RateLimiting and second is the table Consumer - */ - def getRateLimiting(consumerId: String, version: String, name: String): Future[Box[RateLimiting]] = { - RateLimitingUtil.useConsumerLimits match { - case true => RateLimitingDI.rateLimiting.vend.getByConsumerId(consumerId, version, name, Some(new Date())) - case false => Future(Empty) - } - } - val resultWithRateLimiting: Future[(Box[User], Option[CallContext])] = for { - (user, cc) <- userIsLockedOrDeleted - consumer = cc.flatMap(_.consumer) - version = cc.map(_.implementedInVersion).getOrElse("None") // Calculate apiVersion in case of Rate Limiting - operationId = cc.flatMap(_.operationId) // Unique Identifier of Dynamic Endpoints - // Calculate apiName in case of Rate Limiting - name = cc.flatMap(_.resourceDocument.map(_.partialFunctionName)) // 1st try: function name at resource doc - .orElse(operationId) // 2nd try: In case of Dynamic Endpoint we can only use operationId - .getOrElse("None") // Not found any unique identifier - rateLimiting <- getRateLimiting(consumer.map(_.consumerId.get).getOrElse(""), version, name) - } yield { - val limit: Option[CallLimit] = rateLimiting match { - case Full(rl) => Some(CallLimit( - rl.consumerId, - rl.apiName, - rl.apiVersion, - rl.bankId, - rl.perSecondCallLimit, - rl.perMinuteCallLimit, - rl.perHourCallLimit, - rl.perDayCallLimit, - rl.perWeekCallLimit, - rl.perMonthCallLimit)) - case Empty => - Some(CallLimit( - consumer.map(_.consumerId.get).getOrElse(""), - None, - None, - None, - consumer.map(_.perSecondCallLimit.get).getOrElse(-1), - consumer.map(_.perMinuteCallLimit.get).getOrElse(-1), - consumer.map(_.perHourCallLimit.get).getOrElse(-1), - consumer.map(_.perDayCallLimit.get).getOrElse(-1), - consumer.map(_.perWeekCallLimit.get).getOrElse(-1), - consumer.map(_.perMonthCallLimit.get).getOrElse(-1) - )) - case _ => None - } - (user, cc.map(_.copy(rateLimiting = limit))) - } - /*************************************************************************************************************** */ - - - resultWithRateLimiting map { // Update Call Context + // Update Call Context + resultWithRateLimiting map { x => (x._1, ApiSession.updateCallContext(Spelling(spelling), x._2)) } map { x => (x._1, x._2.map(_.copy(implementedInVersion = implementedInVersion))) @@ -2861,7 +2791,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } } - + + + /** * This Function is used to terminate a Future used in for-comprehension with specific message and code in case that value of Box is not Full. diff --git a/obp-api/src/main/scala/code/api/util/ApiAuth.scala b/obp-api/src/main/scala/code/api/util/ApiAuth.scala new file mode 100644 index 000000000..5acc2bca7 --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/ApiAuth.scala @@ -0,0 +1,90 @@ +package code.api.util + +import java.util.Date + +import code.api.util.ErrorMessages.{UserIsDeleted, UsernameHasBeenLocked} +import code.api.util.RateLimitingJson.CallLimit +import code.loginattempts.LoginAttempt +import code.ratelimiting.{RateLimiting, RateLimitingDI} +import com.openbankproject.commons.model.User +import net.liftweb.common.{Box, Empty, Failure, Full} +import com.openbankproject.commons.ExecutionContext.Implicits.global + +import scala.concurrent.Future + + +object ApiAuth { + def checkUserIsDeletedOrLocked(res: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = { + for { + (user: Box[User], cc) <- res + } yield { + user match { + case Full(u) => // There is a user. Check it. + if (u.isDeleted.getOrElse(false)) { + (Failure(UserIsDeleted), cc) // The user is DELETED. + } else { + LoginAttempt.userIsLocked(u.name) match { + case true => (Failure(UsernameHasBeenLocked), cc) // The user is LOCKED. + case false => (user, cc) // All good + } + } + case _ => // There is no user. Just forward the result. + (user, cc) + } + } + } + + /** + * This block of code needs to update Call Context with Rate Limiting + * Please note that first source is the table RateLimiting and second is the table Consumer + */ + def checkRateLimiting(userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = { + def getRateLimiting(consumerId: String, version: String, name: String): Future[Box[RateLimiting]] = { + RateLimitingUtil.useConsumerLimits match { + case true => RateLimitingDI.rateLimiting.vend.getByConsumerId(consumerId, version, name, Some(new Date())) + case false => Future(Empty) + } + } + for { + (user, cc) <- userIsLockedOrDeleted + consumer = cc.flatMap(_.consumer) + version = cc.map(_.implementedInVersion).getOrElse("None") // Calculate apiVersion in case of Rate Limiting + operationId = cc.flatMap(_.operationId) // Unique Identifier of Dynamic Endpoints + // Calculate apiName in case of Rate Limiting + name = cc.flatMap(_.resourceDocument.map(_.partialFunctionName)) // 1st try: function name at resource doc + .orElse(operationId) // 2nd try: In case of Dynamic Endpoint we can only use operationId + .getOrElse("None") // Not found any unique identifier + rateLimiting <- getRateLimiting(consumer.map(_.consumerId.get).getOrElse(""), version, name) + } yield { + val limit: Option[CallLimit] = rateLimiting match { + case Full(rl) => Some(CallLimit( + rl.consumerId, + rl.apiName, + rl.apiVersion, + rl.bankId, + rl.perSecondCallLimit, + rl.perMinuteCallLimit, + rl.perHourCallLimit, + rl.perDayCallLimit, + rl.perWeekCallLimit, + rl.perMonthCallLimit)) + case Empty => + Some(CallLimit( + consumer.map(_.consumerId.get).getOrElse(""), + None, + None, + None, + consumer.map(_.perSecondCallLimit.get).getOrElse(-1), + consumer.map(_.perMinuteCallLimit.get).getOrElse(-1), + consumer.map(_.perHourCallLimit.get).getOrElse(-1), + consumer.map(_.perDayCallLimit.get).getOrElse(-1), + consumer.map(_.perWeekCallLimit.get).getOrElse(-1), + consumer.map(_.perMonthCallLimit.get).getOrElse(-1) + )) + case _ => None + } + (user, cc.map(_.copy(rateLimiting = limit))) + } + } + +} From e02207069617b818c699f46460f3c4948f00f0e4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 18 Nov 2021 11:49:07 +0100 Subject: [PATCH 249/293] feature/added the guard for createUserWithAccountAccess endpoint --- .../SwaggerDefinitionsJSON.scala | 2 +- .../scala/code/api/util/ErrorMessages.scala | 1 + .../scala/code/api/v4_0_0/APIMethods400.scala | 18 ++++++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index ec030e79e..2712cd229 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4095,7 +4095,7 @@ object SwaggerDefinitionsJSON { ) val postCreateUserWithRolesJsonV400 = PostCreateUserWithRolesJsonV400( userIdExample.value, - providerExample.value, + s"dauth.${providerExample.value}", List(createEntitlementJSON) ) val revokedJsonV400 = RevokedJsonV400(true) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index ca6d8db0e..f1c5d1734 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -193,6 +193,7 @@ object ErrorMessages { val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " val CannotGetOrCreateUser = "OBP-20102: Cannot get or create user." + val InvalidUserProvider = "OBP-20103: Invalid User Provider." // OAuth 2 val ApplicationNotIdentified = "OBP-20200: The application cannot be identified. " diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 41ef8461a..9bd243779 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2778,11 +2778,11 @@ trait APIMethods400 { } //check the system role bankId is Empty, but bank level role need bankId _ <- checkRoleBankIdMappings(callContext, postedData) - + _ <- checkRolesBankIdExsiting(callContext, postedData) - + _ <- checkRolesName(callContext, postedData) - + _ <- NewStyle.function.hasEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank, cc.callContext) (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) @@ -2790,7 +2790,7 @@ trait APIMethods400 { _ <- checkIfUserAlreadyHasEntitlements(postedData, callContext) addedEntitlements <- addEntitlementsToUser(postedData, callContext) - + } yield { (JSONFactory400.createEntitlementJSONs(addedEntitlements), HttpCode.`201`(callContext)) } @@ -4257,6 +4257,16 @@ trait APIMethods400 { postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostCreateUserAccountAccessJsonV400] } + //provider must start with dauth., can not create other provider users. + _ <- Helper.booleanToFuture(s"$InvalidUserProvider The user.provider must be start with 'dauth.'", cc=Some(cc)) { + postJson.provider.startsWith("dauth.") + } + + //user_id set the length for the min length of the userId. eg: 36 + _ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) { + postJson.user_id.length>=36 + } + _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) (user, callContext) <- NewStyle.function.getOrCreateUser(postJson.user_id, postJson.provider, cc.callContext) views <- getViews(bankId, accountId, postJson, callContext) From 374acceede67303f7a63520d7a2db8bf686fe6f4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 19 Nov 2021 00:07:46 +0100 Subject: [PATCH 250/293] feature/OBPv400 add guard for createUserWithRoles --- .../scala/code/api/util/ErrorMessages.scala | 3 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 72 ++++++++++++++----- .../code/api/v4_0_0/AccountAccessTest.scala | 2 +- .../code/api/v4_0_0/EntitlementTests.scala | 56 +++++++++++++++ 4 files changed, 113 insertions(+), 20 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index f1c5d1734..9a8b5dcaf 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -193,7 +193,7 @@ object ErrorMessages { val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " val CannotGetOrCreateUser = "OBP-20102: Cannot get or create user." - val InvalidUserProvider = "OBP-20103: Invalid User Provider." + val InvalidUserProvider = "OBP-20103: Invalid DAuth User Provider." // OAuth 2 val ApplicationNotIdentified = "OBP-20200: The application cannot be identified. " @@ -412,6 +412,7 @@ object ErrorMessages { val EntitlementRequestNotFound = "OBP-30215: EntitlementRequestId not found" val EntitlementAlreadyExists = "OBP-30216: Entitlement already exists for the user." val EntitlementCannotBeDeleted = "OBP-30219: EntitlementId cannot be deleted." + val EntitlementCannotBeGranted = "OBP-30220: Entitlement cannot be granted." val CreateSystemViewError = "OBP-30250: Could not create the system view" val DeleteSystemViewError = "OBP-30251: Could not delete the system view" diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 9bd243779..865aa49e3 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5,7 +5,7 @@ import code.DynamicEndpoint.DynamicEndpointSwagger import code.accountattribute.AccountAttributeX import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil.{fullBoxOrException, _} -import code.api.util.ApiRole._ +import code.api.util.ApiRole.{canCreateEntitlementAtAnyBank, _} import code.api.util.ApiTag._ import code.api.util.ErrorMessages._ import code.api.util.ExampleValue._ @@ -2762,10 +2762,10 @@ trait APIMethods400 { EntitlementIsBankRole, EntitlementIsSystemRole, EntitlementAlreadyExists, + InvalidUserProvider, UnknownError ), - List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), - Some(List(canCreateEntitlementAtOneBank,canCreateEntitlementAtAnyBank))) + List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle)) lazy val createUserWithRoles: OBPEndpoint = { case "user-entitlements" :: Nil JsonPost json -> _ => { @@ -2776,6 +2776,17 @@ trait APIMethods400 { postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { json.extract[PostCreateUserWithRolesJsonV400] } + + //provider must start with dauth., can not create other provider users. + _ <- Helper.booleanToFuture(s"$InvalidUserProvider The user.provider must be start with 'dauth.'", cc=Some(cc)) { + postedData.provider.startsWith("dauth.") + } + + //user_id set the length for the min length of the userId. eg: 36 + _ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) { + postedData.user_id.length>=36 + } + //check the system role bankId is Empty, but bank level role need bankId _ <- checkRoleBankIdMappings(callContext, postedData) @@ -2783,14 +2794,17 @@ trait APIMethods400 { _ <- checkRolesName(callContext, postedData) - _ <- NewStyle.function.hasEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank, cc.callContext) + canCreateEntitlementAtAnyBankRole = Entitlement.entitlement.vend.getEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank.toString()) - (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) - - _ <- checkIfUserAlreadyHasEntitlements(postedData, callContext) + (requestUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + + _ <- if (canCreateEntitlementAtAnyBankRole.isDefined) + checkRequestRolesForTheUser(requestUser.userId, postedData.roles, true, callContext) + else + checkRequestRolesForTheUser(loggedInUser.userId, postedData.roles, false, callContext) addedEntitlements <- addEntitlementsToUser(postedData, callContext) - + } yield { (JSONFactory400.createEntitlementJSONs(addedEntitlements), HttpCode.`201`(callContext)) } @@ -10909,17 +10923,39 @@ trait APIMethods400 { } private def addEntitlementsToUser(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postedData.roles.map(addEntitlementToUser(postedData.user_id, _, callContext))) + Future.sequence(postedData.roles.distinct.map(addEntitlementToUser(postedData.user_id, _, callContext))) } - - private def checkIfUserAlreadyHasEntitlement(userId:String, entitlement: CreateEntitlementJSON, callContext: Option[CallContext]) = { - Helper.booleanToFuture(failMsg = s"$EntitlementAlreadyExists Current Entitlement (${entitlement.role_name})", cc=callContext) { - hasEntitlement(entitlement.bank_id, userId, valueOf(entitlement.role_name)) == false - } - } - - private def checkIfUserAlreadyHasEntitlements(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postedData.roles.map(checkIfUserAlreadyHasEntitlement(postedData.user_id, _, callContext))) + + /** + * this method checks the roles for the userId, + * If isDuplicate = true, (mean the login user has canCreateEntitlementAtAnyBankRole), the userId = requestUserId, + * Here we will grant all the roles to the requestUserId, so first we need to check if the requestUserId already has the roles or not, so + * It will find the duplication ones between requestEntitlements and the userId's already has entitlements.--> throw the duplication error + * If isDuplicate false, (mean the login user does not has canCreateEntitlementAtAnyBankRole), the userId = login user, + * Here we only can grant the roles which the login user has, we need to find the roles which the login user does not have. + * It will find the not existing ones from the userId's already has entitlements by requestEntitlements.--> throw the no existing error + */ + private def checkRequestRolesForTheUser(userId:String, requestEntitlements: List[CreateEntitlementJSON], isDuplicate:Boolean, callContext: Option[CallContext]) = { + //1st: get all the entitlements for the user: + val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) + val rolesAlreadyHas = entitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet + + val rolesFromRequest = requestEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet + + //2rd: find the duplicated ones: + val duplicatedEntitlements = if(isDuplicate) + rolesAlreadyHas.filter(rolesFromRequest) + else + rolesFromRequest.filterNot(rolesAlreadyHas) + + if(duplicatedEntitlements.size >0){ + val errorMessages = if(isDuplicate) + s"$EntitlementAlreadyExists user_id($userId) ${duplicatedEntitlements.mkString(",")}" + else + s"$EntitlementCannotBeGranted user_id($userId). The login user do not have the following roles yet: ${duplicatedEntitlements.mkString(",")}" + Helper.booleanToFuture(errorMessages, cc=callContext) {false} + }else + Future.successful(Full()) } private def checkRoleBankIdMapping(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala index 6fe224600..1dc0f6b1e 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala @@ -98,7 +98,7 @@ class AccountAccessTest extends V400ServerSetup { responseRevoke.body.extract[RevokedJsonV400] { - val postCreateUserJson = PostCreateUserAccountAccessJsonV400(resourceUser2.userId, resourceUser2.provider, List(PostViewJsonV400(view.id, view.is_system))) + val postCreateUserJson = PostCreateUserAccountAccessJsonV400(resourceUser2.userId, "dauth."+resourceUser2.provider, List(PostViewJsonV400(view.id, view.is_system))) When("We send the request") val request = (v4_0_0_Request / "banks" / bankId / "accounts" / account.account_id / "user-account-access").POST <@ (user1) val response = makePostRequest(request, write(postCreateUserJson)) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala index 6b9b6f8c1..f71c62f5c 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala @@ -115,6 +115,62 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { } } + scenario("We try to - createUserWithRoles - not roles, only grant the roles the login user has ", ApiEndpoint3, VersionOfApi) { + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + r.code should equal(400) + r.body.toString contains (EntitlementCannotBeGranted) shouldBe(true) + } + } + + scenario("We try to - createUserWithRoles - short user_id ", ApiEndpoint3, VersionOfApi) { + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(user_id ="xx", roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + r.code should equal(400) + r.body.toString contains (InvalidUserId) shouldBe(true) + } + } + scenario("We try to - createUserWithRoles - wrong user provider ", ApiEndpoint3, VersionOfApi) { + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(provider ="xx", roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + r.code should equal(400) + r.body.toString contains (InvalidUserProvider) shouldBe(true) + } + } + scenario("We try to - createUserWithRoles", ApiEndpoint3, VersionOfApi) { When("We add required entitlement") Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanCreateEntitlementAtAnyBank.toString) From acd490499100077bbf7c0c102671de533360c494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 19 Nov 2021 10:51:17 +0100 Subject: [PATCH 251/293] feature/OpenID Connect; Enable props email_domain_to_space_mappings --- .../src/main/scala/code/api/directlogin.scala | 8 +-- .../main/scala/code/api/openidconnect.scala | 2 + .../code/model/dataAccess/AuthUser.scala | 64 ++++++++++--------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/obp-api/src/main/scala/code/api/directlogin.scala b/obp-api/src/main/scala/code/api/directlogin.scala index 3dc004a94..dd2196953 100644 --- a/obp-api/src/main/scala/code/api/directlogin.scala +++ b/obp-api/src/main/scala/code/api/directlogin.scala @@ -113,12 +113,8 @@ object DirectLogin extends RestHelper with MdcLoggable { try { val resourceUser = UserX.findByResourceUserId(userId).openOrThrowException(s"$InvalidDirectLoginParameters can not find the resourceUser!") val authUser = AuthUser.findUserByUsernameLocally(resourceUser.name).openOrThrowException(s"$InvalidDirectLoginParameters can not find the auth user!") - if(!emailDomainToSpaceMappings.isEmpty){ - AuthUser.grantEntitlementsToUseDynamicEndpointsInSpaces(authUser) - } - if(!emailDomainToEntitlementMappings.isEmpty){ - AuthUser.grantEmailDomainEntitlementsToUser(authUser) - } + AuthUser.grantEntitlementsToUseDynamicEndpointsInSpaces(authUser) + AuthUser.grantEmailDomainEntitlementsToUser(authUser) } catch { case e: Throwable => // error handling, found wrong props value as early as possible. this.logger.error(s"directLogin.grantEntitlementsToUseDynamicEndpointsInSpacesInDirectLogin throw exception, details: $e" ); diff --git a/obp-api/src/main/scala/code/api/openidconnect.scala b/obp-api/src/main/scala/code/api/openidconnect.scala index 09f97ad98..a3b387bec 100644 --- a/obp-api/src/main/scala/code/api/openidconnect.scala +++ b/obp-api/src/main/scala/code/api/openidconnect.scala @@ -124,6 +124,8 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { case Full(authUser) => // Grant roles according to the props email_domain_to_space_mappings AuthUser.grantEmailDomainEntitlementsToUser(authUser) + // Grant roles according to the props email_domain_to_space_mappings + AuthUser.grantEntitlementsToUseDynamicEndpointsInSpaces(authUser) // Consumer getOrCreateConsumer(idToken, user.userId) match { case Full(consumer) => diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index c0439ec23..d888ab655 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -1154,43 +1154,45 @@ def restoreSomeSessions(): Unit = { } def grantEntitlementsToUseDynamicEndpointsInSpaces(user: AuthUser) = { - val createdByProcess = "grantEntitlementsToUseDynamicEndpointsInSpaces" - val userId = user.user.obj.map(_.userId).getOrElse("") + if(emailDomainToSpaceMappings.nonEmpty) { + val createdByProcess = "grantEntitlementsToUseDynamicEndpointsInSpaces" + val userId = user.user.obj.map(_.userId).getOrElse("") - // user's already auto granted entitlements. - val entitlementsGrantedByThisProcess = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) - .map(_.filter(role => role.createdByProcess == createdByProcess)) - .getOrElse(Nil) + // user's already auto granted entitlements. + val entitlementsGrantedByThisProcess = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) + .map(_.filter(role => role.createdByProcess == createdByProcess)) + .getOrElse(Nil) - def alreadyHasEntitlement(role:ApiRole, bankId: String): Boolean = - entitlementsGrantedByThisProcess.exists(entitlement => entitlement.roleName == role.toString() && entitlement.bankId == bankId) + def alreadyHasEntitlement(role:ApiRole, bankId: String): Boolean = + entitlementsGrantedByThisProcess.exists(entitlement => entitlement.roleName == role.toString() && entitlement.bankId == bankId) - //call mySpaces --> get BankIds --> listOfRolesToUseAllDynamicEndpointsAOneBank (at each bank)--> Grant roles (for each role) - val allCurrentDynamicRoleToBankIdPairs: List[(ApiRole, String)] = for { - BankId(bankId) <- mySpaces(user: AuthUser) - role <- DynamicEndpointHelper.listOfRolesToUseAllDynamicEndpointsAOneBank(Some(bankId)) - } yield { - if (!alreadyHasEntitlement(role, bankId)) { - Entitlement.entitlement.vend.addEntitlement(bankId, userId, role.toString, createdByProcess) + //call mySpaces --> get BankIds --> listOfRolesToUseAllDynamicEndpointsAOneBank (at each bank)--> Grant roles (for each role) + val allCurrentDynamicRoleToBankIdPairs: List[(ApiRole, String)] = for { + BankId(bankId) <- mySpaces(user: AuthUser) + role <- DynamicEndpointHelper.listOfRolesToUseAllDynamicEndpointsAOneBank(Some(bankId)) + } yield { + if (!alreadyHasEntitlement(role, bankId)) { + Entitlement.entitlement.vend.addEntitlement(bankId, userId, role.toString, createdByProcess) + } + + role -> bankId } - role -> bankId - } + // if user's auto granted entitlement invalid, delete it. + // invalid happens when some dynamic endpoints are removed, so the entitlements linked to the deleted dynamic endpoints are invalid. + for { + grantedEntitlement <- entitlementsGrantedByThisProcess + grantedEntitlementRoleName = grantedEntitlement.roleName + grantedEntitlementBankId = grantedEntitlement.bankId + } { + val isInValidEntitlement = !allCurrentDynamicRoleToBankIdPairs.exists { roleToBankIdPair => + val(role, roleBankId) = roleToBankIdPair + role.toString() == grantedEntitlementRoleName && roleBankId == grantedEntitlementBankId + } - // if user's auto granted entitlement invalid, delete it. - // invalid happens when some dynamic endpoints are removed, so the entitlements linked to the deleted dynamic endpoints are invalid. - for { - grantedEntitlement <- entitlementsGrantedByThisProcess - grantedEntitlementRoleName = grantedEntitlement.roleName - grantedEntitlementBankId = grantedEntitlement.bankId - } { - val isInValidEntitlement = !allCurrentDynamicRoleToBankIdPairs.exists { roleToBankIdPair => - val(role, roleBankId) = roleToBankIdPair - role.toString() == grantedEntitlementRoleName && roleBankId == grantedEntitlementBankId - } - - if(isInValidEntitlement) { - Entitlement.entitlement.vend.deleteEntitlement(Full(grantedEntitlement)) + if(isInValidEntitlement) { + Entitlement.entitlement.vend.deleteEntitlement(Full(grantedEntitlement)) + } } } } From b1c07e221b77467e56b0cb553e0bbd991387bec0 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 19 Nov 2021 00:07:46 +0100 Subject: [PATCH 252/293] refactor/typo --- .../scala/code/api/util/ErrorMessages.scala | 3 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 76 ++++++++++++++----- .../code/api/v4_0_0/AccountAccessTest.scala | 2 +- .../code/api/v4_0_0/EntitlementTests.scala | 56 ++++++++++++++ 4 files changed, 115 insertions(+), 22 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index f1c5d1734..9a8b5dcaf 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -193,7 +193,7 @@ object ErrorMessages { val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: " val CannotGetOrCreateUser = "OBP-20102: Cannot get or create user." - val InvalidUserProvider = "OBP-20103: Invalid User Provider." + val InvalidUserProvider = "OBP-20103: Invalid DAuth User Provider." // OAuth 2 val ApplicationNotIdentified = "OBP-20200: The application cannot be identified. " @@ -412,6 +412,7 @@ object ErrorMessages { val EntitlementRequestNotFound = "OBP-30215: EntitlementRequestId not found" val EntitlementAlreadyExists = "OBP-30216: Entitlement already exists for the user." val EntitlementCannotBeDeleted = "OBP-30219: EntitlementId cannot be deleted." + val EntitlementCannotBeGranted = "OBP-30220: Entitlement cannot be granted." val CreateSystemViewError = "OBP-30250: Could not create the system view" val DeleteSystemViewError = "OBP-30251: Could not delete the system view" diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 9bd243779..e5bd41011 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5,7 +5,7 @@ import code.DynamicEndpoint.DynamicEndpointSwagger import code.accountattribute.AccountAttributeX import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil.{fullBoxOrException, _} -import code.api.util.ApiRole._ +import code.api.util.ApiRole.{canCreateEntitlementAtAnyBank, _} import code.api.util.ApiTag._ import code.api.util.ErrorMessages._ import code.api.util.ExampleValue._ @@ -2762,10 +2762,10 @@ trait APIMethods400 { EntitlementIsBankRole, EntitlementIsSystemRole, EntitlementAlreadyExists, + InvalidUserProvider, UnknownError ), - List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle), - Some(List(canCreateEntitlementAtOneBank,canCreateEntitlementAtAnyBank))) + List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle)) lazy val createUserWithRoles: OBPEndpoint = { case "user-entitlements" :: Nil JsonPost json -> _ => { @@ -2776,6 +2776,17 @@ trait APIMethods400 { postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { json.extract[PostCreateUserWithRolesJsonV400] } + + //provider must start with dauth., can not create other provider users. + _ <- Helper.booleanToFuture(s"$InvalidUserProvider The user.provider must be start with 'dauth.'", cc=Some(cc)) { + postedData.provider.startsWith("dauth.") + } + + //user_id set the length for the min length of the userId. eg: 36 + _ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) { + postedData.user_id.length>=36 + } + //check the system role bankId is Empty, but bank level role need bankId _ <- checkRoleBankIdMappings(callContext, postedData) @@ -2783,14 +2794,17 @@ trait APIMethods400 { _ <- checkRolesName(callContext, postedData) - _ <- NewStyle.function.hasEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank, cc.callContext) + canCreateEntitlementAtAnyBankRole = Entitlement.entitlement.vend.getEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank.toString()) - (postBodyUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) - - _ <- checkIfUserAlreadyHasEntitlements(postedData, callContext) + (requestUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + + _ <- if (canCreateEntitlementAtAnyBankRole.isDefined) + checkRequestRolesForTheUser(requestUser.userId, postedData.roles, true, callContext) + else + checkRequestRolesForTheUser(loggedInUser.userId, postedData.roles, false, callContext) addedEntitlements <- addEntitlementsToUser(postedData, callContext) - + } yield { (JSONFactory400.createEntitlementJSONs(addedEntitlements), HttpCode.`201`(callContext)) } @@ -8524,7 +8538,7 @@ trait APIMethods400 { s"""${Glossary.getGlossaryItem("API Collections")} | | - |Delete Api Collection Endpoint By Id + |Delete Api Collection Endpoint By OPERATION_ID | |${authenticationRequiredMessage(true)} | @@ -8598,7 +8612,7 @@ trait APIMethods400 { "Delete My Api Collection Endpoint By Id", s"""${Glossary.getGlossaryItem("API Collections")} |Delete Api Collection Endpoint - |Delete Api Collection Endpoint By IdDelete Api Collection Endpoint + |Delete Api Collection Endpoint By Id | |${authenticationRequiredMessage(true)} | @@ -10909,17 +10923,39 @@ trait APIMethods400 { } private def addEntitlementsToUser(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postedData.roles.map(addEntitlementToUser(postedData.user_id, _, callContext))) + Future.sequence(postedData.roles.distinct.map(addEntitlementToUser(postedData.user_id, _, callContext))) } - - private def checkIfUserAlreadyHasEntitlement(userId:String, entitlement: CreateEntitlementJSON, callContext: Option[CallContext]) = { - Helper.booleanToFuture(failMsg = s"$EntitlementAlreadyExists Current Entitlement (${entitlement.role_name})", cc=callContext) { - hasEntitlement(entitlement.bank_id, userId, valueOf(entitlement.role_name)) == false - } - } - - private def checkIfUserAlreadyHasEntitlements(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postedData.roles.map(checkIfUserAlreadyHasEntitlement(postedData.user_id, _, callContext))) + + /** + * this method checks the roles for the userId, + * If isDuplicate = true, (mean the login user has canCreateEntitlementAtAnyBankRole), the userId = requestUserId, + * Here we will grant all the roles to the requestUserId, so first we need to check if the requestUserId already has the roles or not, so + * It will find the duplication ones between requestEntitlements and the userId's already has entitlements.--> throw the duplication error + * If isDuplicate false, (mean the login user does not has canCreateEntitlementAtAnyBankRole), the userId = login user, + * Here we only can grant the roles which the login user has, we need to find the roles which the login user does not have. + * It will find the not existing ones from the userId's already has entitlements by requestEntitlements.--> throw the no existing error + */ + private def checkRequestRolesForTheUser(userId:String, requestEntitlements: List[CreateEntitlementJSON], isDuplicate:Boolean, callContext: Option[CallContext]) = { + //1st: get all the entitlements for the user: + val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) + val rolesAlreadyHas = entitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet + + val rolesFromRequest = requestEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet + + //2rd: find the duplicated ones: + val duplicatedEntitlements = if(isDuplicate) + rolesAlreadyHas.filter(rolesFromRequest) + else + rolesFromRequest.filterNot(rolesAlreadyHas) + + if(duplicatedEntitlements.size >0){ + val errorMessages = if(isDuplicate) + s"$EntitlementAlreadyExists user_id($userId) ${duplicatedEntitlements.mkString(",")}" + else + s"$EntitlementCannotBeGranted user_id($userId). The login user do not have the following roles yet: ${duplicatedEntitlements.mkString(",")}" + Helper.booleanToFuture(errorMessages, cc=callContext) {false} + }else + Future.successful(Full()) } private def checkRoleBankIdMapping(callContext: Option[CallContext], entitlement: CreateEntitlementJSON) = { diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala index 6fe224600..1dc0f6b1e 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala @@ -98,7 +98,7 @@ class AccountAccessTest extends V400ServerSetup { responseRevoke.body.extract[RevokedJsonV400] { - val postCreateUserJson = PostCreateUserAccountAccessJsonV400(resourceUser2.userId, resourceUser2.provider, List(PostViewJsonV400(view.id, view.is_system))) + val postCreateUserJson = PostCreateUserAccountAccessJsonV400(resourceUser2.userId, "dauth."+resourceUser2.provider, List(PostViewJsonV400(view.id, view.is_system))) When("We send the request") val request = (v4_0_0_Request / "banks" / bankId / "accounts" / account.account_id / "user-account-access").POST <@ (user1) val response = makePostRequest(request, write(postCreateUserJson)) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala index 6b9b6f8c1..f71c62f5c 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala @@ -115,6 +115,62 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { } } + scenario("We try to - createUserWithRoles - not roles, only grant the roles the login user has ", ApiEndpoint3, VersionOfApi) { + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + r.code should equal(400) + r.body.toString contains (EntitlementCannotBeGranted) shouldBe(true) + } + } + + scenario("We try to - createUserWithRoles - short user_id ", ApiEndpoint3, VersionOfApi) { + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(user_id ="xx", roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + r.code should equal(400) + r.body.toString contains (InvalidUserId) shouldBe(true) + } + } + scenario("We try to - createUserWithRoles - wrong user provider ", ApiEndpoint3, VersionOfApi) { + And("We make the request") + val createEntitlements = List(CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanCreateBranch.toString() + ), CreateEntitlementJSON( + bank_id = testBankId1.value, + role_name = CanUpdateBranch.toString() + )) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(provider ="xx", roles= createEntitlements) + val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) + val responseGet = makePostRequestAsync(requestGet, write(postJson)) + Then("We should get a 200") + responseGet map { r => + r.code should equal(400) + r.body.toString contains (InvalidUserProvider) shouldBe(true) + } + } + scenario("We try to - createUserWithRoles", ApiEndpoint3, VersionOfApi) { When("We add required entitlement") Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanCreateEntitlementAtAnyBank.toString) From 989b641a85e43c39c990174753a765d53d0fe5e2 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 19 Nov 2021 13:20:45 +0100 Subject: [PATCH 253/293] refactor/separate the checkRequestRolesForTheUser to two methods --- .../scala/code/api/v4_0_0/APIMethods400.scala | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index e5bd41011..6f4c79d56 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2798,11 +2798,16 @@ trait APIMethods400 { (requestUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) - _ <- if (canCreateEntitlementAtAnyBankRole.isDefined) - checkRequestRolesForTheUser(requestUser.userId, postedData.roles, true, callContext) - else - checkRequestRolesForTheUser(loggedInUser.userId, postedData.roles, false, callContext) - + _ <- if (canCreateEntitlementAtAnyBankRole.isDefined) { + //If the loggedIn User has `CanCreateEntitlementAtAnyBankRole` role, then we can grant all the requestRoles to the requestUser. + //But we must check if the requestUser already has the requestRoles or not. + checkIfUserAlreadyHasTheRequestRoles(requestUser.userId, postedData.roles,callContext) + } else { + //If the loggedIn user does not have the `CanCreateEntitlementAtAnyBankRole` role, we can only grant the roles which the loggedIn user have. + //So we need to check if the rqeuestRoles are beyond the current loggedIn user has. + checkIfUserCanGrantTheRequestRoles(loggedInUser.userId, postedData.roles, callContext) + } + addedEntitlements <- addEntitlementsToUser(postedData, callContext) } yield { @@ -10927,32 +10932,45 @@ trait APIMethods400 { } /** - * this method checks the roles for the userId, - * If isDuplicate = true, (mean the login user has canCreateEntitlementAtAnyBankRole), the userId = requestUserId, - * Here we will grant all the roles to the requestUserId, so first we need to check if the requestUserId already has the roles or not, so - * It will find the duplication ones between requestEntitlements and the userId's already has entitlements.--> throw the duplication error - * If isDuplicate false, (mean the login user does not has canCreateEntitlementAtAnyBankRole), the userId = login user, - * Here we only can grant the roles which the login user has, we need to find the roles which the login user does not have. - * It will find the not existing ones from the userId's already has entitlements by requestEntitlements.--> throw the no existing error + * This method will check all the roles the request user already has and the request roles: + * It will find the roles the requestUser already have, then show the error to the developer. + * (We can not grant the same roles to the request user twice) */ - private def checkRequestRolesForTheUser(userId:String, requestEntitlements: List[CreateEntitlementJSON], isDuplicate:Boolean, callContext: Option[CallContext]) = { + private def checkIfUserAlreadyHasTheRequestRoles(requestUserId:String, requestEntitlements: List[CreateEntitlementJSON], callContext: Option[CallContext]) = { //1st: get all the entitlements for the user: - val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) + val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(requestUserId) val rolesAlreadyHas = entitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet val rolesFromRequest = requestEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet //2rd: find the duplicated ones: - val duplicatedEntitlements = if(isDuplicate) - rolesAlreadyHas.filter(rolesFromRequest) - else - rolesFromRequest.filterNot(rolesAlreadyHas) + val duplicatedEntitlements = rolesAlreadyHas.filter(rolesFromRequest) + + //3rd: We can not grant the roles again, so we show the error to the developer. + if(duplicatedEntitlements.size >0){ + val errorMessages = s"$EntitlementAlreadyExists user_id($requestUserId) ${duplicatedEntitlements.mkString(",")}" + Helper.booleanToFuture(errorMessages, cc=callContext) {false} + }else + Future.successful(Full()) + } + + /** + * This method will check all the roles the loggedIn user already has and the request roles: + * It will find the not existing roles from the loggedIn user --> we will show the error to the developer + * (We can only grant the roles which the loggedIn User has to the requestUser) + */ + private def checkIfUserCanGrantTheRequestRoles(loggedInUserId:String, requestEntitlements: List[CreateEntitlementJSON], callContext: Option[CallContext]) = { + //1st: get all the entitlements for the user: + val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(loggedInUserId) + val rolesAlreadyHas = entitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet + + val rolesFromRequest = requestEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet + + //2rd: find the roles which the loggedIn user does not have, + val duplicatedEntitlements = rolesFromRequest.filterNot(rolesAlreadyHas) if(duplicatedEntitlements.size >0){ - val errorMessages = if(isDuplicate) - s"$EntitlementAlreadyExists user_id($userId) ${duplicatedEntitlements.mkString(",")}" - else - s"$EntitlementCannotBeGranted user_id($userId). The login user do not have the following roles yet: ${duplicatedEntitlements.mkString(",")}" + val errorMessages = s"$EntitlementCannotBeGranted user_id($loggedInUserId). The login user do not have the following roles yet: ${duplicatedEntitlements.mkString(",")}" Helper.booleanToFuture(errorMessages, cc=callContext) {false} }else Future.successful(Full()) From f0eced7ec6e419ccd55b414d2e9dbe622d4d4770 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 19 Nov 2021 15:04:40 +0100 Subject: [PATCH 254/293] refactor/rename the methods and variables --- .../scala/code/api/util/ExampleValue.scala | 2 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index c8b5aa220..ae76c49ab 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -2061,7 +2061,7 @@ object ExampleValue { lazy val indexExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("index", indexExample) - lazy val descriptionExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val descriptionExample = ConnectorField("This is used for customer x!","The human readable description here.") glossaryItems += makeGlossaryItem("description", descriptionExample) lazy val dynamicResourceDocdescriptionExample = ConnectorField("Create one User", "the description for this endpoint") diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 6f4c79d56..3746044c2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2796,16 +2796,16 @@ trait APIMethods400 { canCreateEntitlementAtAnyBankRole = Entitlement.entitlement.vend.getEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank.toString()) - (requestUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + (targetUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) _ <- if (canCreateEntitlementAtAnyBankRole.isDefined) { //If the loggedIn User has `CanCreateEntitlementAtAnyBankRole` role, then we can grant all the requestRoles to the requestUser. //But we must check if the requestUser already has the requestRoles or not. - checkIfUserAlreadyHasTheRequestRoles(requestUser.userId, postedData.roles,callContext) + assertTargetUserLacksRoles(targetUser.userId, postedData.roles,callContext) } else { //If the loggedIn user does not have the `CanCreateEntitlementAtAnyBankRole` role, we can only grant the roles which the loggedIn user have. - //So we need to check if the rqeuestRoles are beyond the current loggedIn user has. - checkIfUserCanGrantTheRequestRoles(loggedInUser.userId, postedData.roles, callContext) + //So we need to check if the requestRoles are beyond the current loggedIn user has. + assertUserCanGrantRoles(loggedInUser.userId, postedData.roles, callContext) } addedEntitlements <- addEntitlementsToUser(postedData, callContext) @@ -10936,19 +10936,19 @@ trait APIMethods400 { * It will find the roles the requestUser already have, then show the error to the developer. * (We can not grant the same roles to the request user twice) */ - private def checkIfUserAlreadyHasTheRequestRoles(requestUserId:String, requestEntitlements: List[CreateEntitlementJSON], callContext: Option[CallContext]) = { + private def assertTargetUserLacksRoles(userId:String, requestedEntitlements: List[CreateEntitlementJSON], callContext: Option[CallContext]) = { //1st: get all the entitlements for the user: - val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(requestUserId) - val rolesAlreadyHas = entitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet + val userEntitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) + val userRoles = userEntitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet - val rolesFromRequest = requestEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet + val targetRoles = requestedEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet //2rd: find the duplicated ones: - val duplicatedEntitlements = rolesAlreadyHas.filter(rolesFromRequest) + val duplicatedRoles = userRoles.filter(targetRoles) //3rd: We can not grant the roles again, so we show the error to the developer. - if(duplicatedEntitlements.size >0){ - val errorMessages = s"$EntitlementAlreadyExists user_id($requestUserId) ${duplicatedEntitlements.mkString(",")}" + if(duplicatedRoles.size >0){ + val errorMessages = s"$EntitlementAlreadyExists user_id($userId) ${duplicatedRoles.mkString(",")}" Helper.booleanToFuture(errorMessages, cc=callContext) {false} }else Future.successful(Full()) @@ -10959,18 +10959,18 @@ trait APIMethods400 { * It will find the not existing roles from the loggedIn user --> we will show the error to the developer * (We can only grant the roles which the loggedIn User has to the requestUser) */ - private def checkIfUserCanGrantTheRequestRoles(loggedInUserId:String, requestEntitlements: List[CreateEntitlementJSON], callContext: Option[CallContext]) = { + private def assertUserCanGrantRoles(userId:String, requestedEntitlements: List[CreateEntitlementJSON], callContext: Option[CallContext]) = { //1st: get all the entitlements for the user: - val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(loggedInUserId) - val rolesAlreadyHas = entitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet + val userEntitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(userId) + val userRoles = userEntitlements.map(_.map(entitlement => (entitlement.roleName, entitlement.bankId))).getOrElse(List.empty[(String,String)]).toSet - val rolesFromRequest = requestEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet + val targetRoles = requestedEntitlements.map(entitlement => (entitlement.role_name, entitlement.bank_id)).toSet //2rd: find the roles which the loggedIn user does not have, - val duplicatedEntitlements = rolesFromRequest.filterNot(rolesAlreadyHas) + val roleLacking = targetRoles.filterNot(userRoles) - if(duplicatedEntitlements.size >0){ - val errorMessages = s"$EntitlementCannotBeGranted user_id($loggedInUserId). The login user do not have the following roles yet: ${duplicatedEntitlements.mkString(",")}" + if(roleLacking.size >0){ + val errorMessages = s"$EntitlementCannotBeGranted user_id($userId). The login user does not have the following roles: ${roleLacking.mkString(",")}" Helper.booleanToFuture(errorMessages, cc=callContext) {false} }else Future.successful(Full()) From 9990ca7cb47e113e302a264262ec48f2bea5ccdf Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Fri, 19 Nov 2021 21:00:50 +0100 Subject: [PATCH 255/293] /docfix Added DAuth tag, enhanced DAuth related endpoints --- .../src/main/scala/code/api/util/ApiTag.scala | 2 + .../main/scala/code/api/util/Glossary.scala | 2 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 45 +++++++++++++++---- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiTag.scala b/obp-api/src/main/scala/code/api/util/ApiTag.scala index d03c323a9..14d135ac3 100644 --- a/obp-api/src/main/scala/code/api/util/ApiTag.scala +++ b/obp-api/src/main/scala/code/api/util/ApiTag.scala @@ -77,6 +77,8 @@ object ApiTag { val apiTagDynamicResourceDoc = ResourceDocTag("Dynamic-Resource-Doc") val apiTagDynamicMessageDoc = ResourceDocTag("Dynamic-Message-Doc") + val apiTagDAuth = ResourceDocTag("DAuth") + val apiTagDynamic = ResourceDocTag("Dynamic") val apiTagDynamicEntity = ResourceDocTag("Dynamic-Entity") val apiTagManageDynamicEntity = ResourceDocTag("Dynamic-Entity-Manage") diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 4be54dfca..978af487b 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -2040,7 +2040,7 @@ object Glossary extends MdcLoggable { | |If you are calling OBP-API via an API3 Airnode, the Airnode will take care of constructing the required header. | -|When OBP detects an DAuth header / token it first checks if the Consumer is allowed to make such a call. OBP will validate the Consumer ip address and signature etc. +|When OBP detects a DAuth header / token it first checks if the Consumer is allowed to make such a call. OBP will validate the Consumer ip address and signature etc. | |Note: The DAuth flow does *not* require an explicit POST like Direct Login to create the token. | diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 3746044c2..89508b07d 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -82,6 +82,8 @@ import java.net.URLEncoder import java.text.SimpleDateFormat import java.util.{Calendar, Date} +import code.api.util.Glossary.getGlossaryItem + import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future @@ -2741,17 +2743,34 @@ trait APIMethods400 { nameOf(createUserWithRoles), "POST", "/user-entitlements", - "Create User with Roles", - """This will create the User with user_id and provider if it does not exist + "Create (DAuth) User with Roles", + s""" + |This endpoint is used as part of the DAuth solution to grant Entitlements for Roles to a smart contract on the blockchain. | - |Create Entitlement. Grant Role to User. + |Put the smart contract address in user_id + | + |For provider use "dauth" + | + |This endpoint will create the User with user_id and provider if the User does not already exist. + | + |Then it will create Entitlements i.e. grant Roles to the User. | |Entitlements are used to grant System or Bank level roles to Users. (For Account level privileges, see Views) | + |i.e. Entitlements are used to create / consume system or bank level resources where as views / account access are used to consume / create customer level resources. + | |For a System level Role (.e.g CanGetAnyUser), set bank_id to an empty string i.e. "bank_id":"" | |For a Bank level Role (e.g. CanCreateAccount), set bank_id to a valid value e.g. "bank_id":"my-bank-id" | + |Note: The Roles actually granted will depend on the Roles that the calling user has. + | + |If you try to grant Entitlements to a user that already exist (duplicate entitilements) you will get an error. + | + |For information about DAuth see below: + | + |${getGlossaryItem("DAuth")} + | |""", postCreateUserWithRolesJsonV400, entitlementsJsonV400, @@ -2765,7 +2784,7 @@ trait APIMethods400 { InvalidUserProvider, UnknownError ), - List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle)) + List(apiTagRole, apiTagEntitlement, apiTagUser, apiTagNewStyle, apiTagDAuth)) lazy val createUserWithRoles: OBPEndpoint = { case "user-entitlements" :: Nil JsonPost json -> _ => { @@ -4249,10 +4268,20 @@ trait APIMethods400 { nameOf(createUserWithAccountAccess), "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/user-account-access", - "Create User with Account Access", - s"""This will create the User with user_id and provider if it does not exist . + "Create (DAuth) User with Account Access", + s"""This endpoint is used as part of the DAuth solution to grant access to account and transaction data to a smart contract on the blockchain. | - |${authenticationRequiredMessage(true)} and the loggedin user needs to be account holder. + |Put the smart contract address in user_id + | + |For provider use "dauth" + | + |This endpoint will create the (DAuth) User with user_id and provider if the User does not already exist. + | + |${authenticationRequiredMessage(true)} and the logged in user needs to be account holder. + | + |For information about DAuth see below: + | + |${getGlossaryItem("DAuth")} | |""", postCreateUserWithRolesJsonV400, @@ -4266,7 +4295,7 @@ trait APIMethods400 { CannotGrantAccountAccess, UnknownError ), - List(apiTagAccountAccess, apiTagView, apiTagAccount, apiTagUser, apiTagOwnerRequired, apiTagNewStyle)) + List(apiTagAccountAccess, apiTagView, apiTagAccount, apiTagUser, apiTagOwnerRequired, apiTagDAuth, apiTagNewStyle)) lazy val createUserWithAccountAccess : OBPEndpoint = { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "user-account-access" :: Nil JsonPost json -> _ => { From c2b4ea66013b57b489ccc4640f48a02b2a704972 Mon Sep 17 00:00:00 2001 From: hongwei Date: Sat, 20 Nov 2021 11:49:57 +0100 Subject: [PATCH 256/293] feature/added the `dauth.` to all the Dauth provider --- obp-api/src/main/scala/code/api/dauth.scala | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index b1c8e7fcb..f4f0d9b88 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -136,12 +136,13 @@ object DAuth extends RestHelper with MdcLoggable { def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") val provider = getFieldFromPayloadJson(jwtPayload, "network_name") + val providerHardCodePrefixDauth = "dauth."+provider logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = username).or { // Find a user + Users.users.vend.getUserByProviderId(provider = providerHardCodePrefixDauth, idGivenByProvider = username).or { // Find a user Users.users.vend.createResourceUser( // Otherwise create a new one - provider = provider, + provider = providerHardCodePrefixDauth, providerId = Some(username), None, name = Some(username), @@ -168,10 +169,11 @@ object DAuth extends RestHelper with MdcLoggable { def getOrCreateResourceUserFuture(jwtPayload: String, callContext: Option[CallContext]) : Future[Box[(User, Option[CallContext])]] = { val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") val provider = getFieldFromPayloadJson(jwtPayload, "network_name") + val providerHardCodePrefixDauth = "dauth."+provider logger.debug("login_user_name: " + username) for { tuple <- - Users.users.vend.getOrCreateUserByProviderIdFuture(provider = provider, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map { + Users.users.vend.getOrCreateUserByProviderIdFuture(provider = providerHardCodePrefixDauth, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map { case (Full(u), _) => Full(u, callContext) // Return user case (Empty, _) => @@ -223,8 +225,9 @@ object DAuth extends RestHelper with MdcLoggable { case Full(payload) => val username = getFieldFromPayloadJson(payload, "smart_contract_address") val provider = getFieldFromPayloadJson(payload, "network_name") + val providerHardCodePrefixDauth = "dauth."+provider logger.debug("username: " + username) - Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = username) + Users.users.vend.getUserByProviderId(provider = providerHardCodePrefixDauth, idGivenByProvider = username) case _ => None } From ab979f837d5b755c61a8eff2fe8df394a711d52a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 23 Nov 2021 12:21:07 +0100 Subject: [PATCH 257/293] fature/Tweak endpoint createMyApiCollection v4.0.0 --- .../code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 2 +- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 2 +- obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 2712cd229..412182782 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4265,7 +4265,7 @@ object SwaggerDefinitionsJSON { charge = transactionRequestChargeJsonV200 ) - val postApiCollectionJson400 = PostApiCollectionJson400(apiCollectionNameExample.value, true, descriptionExample.value) + val postApiCollectionJson400 = PostApiCollectionJson400(apiCollectionNameExample.value, true, Some(descriptionExample.value)) val apiCollectionJson400 = ApiCollectionJson400(apiCollectionIdExample.value, userIdExample.value, apiCollectionNameExample.value, true, descriptionExample.value) val apiCollectionsJson400 = ApiCollectionsJson400(List(apiCollectionJson400)) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 89508b07d..190a6e612 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8087,7 +8087,7 @@ trait APIMethods400 { cc.userId, postJson.api_collection_name, postJson.is_sharable, - postJson.description, + postJson.description.getOrElse(""), Some(cc) ) } yield { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 3e59b2237..ae3685578 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -691,7 +691,7 @@ case class ApiCollectionsJson400 ( case class PostApiCollectionJson400( api_collection_name: String, is_sharable: Boolean, - description: String + description: Option[String] ) case class ApiCollectionEndpointJson400 ( From 0c00bee4a553d4b2a6ee90a7ef58029e775d4866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 23 Nov 2021 14:18:14 +0100 Subject: [PATCH 258/293] refactor/Rename ApiAuth to AfterApiAuth --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 4 ++-- .../scala/code/api/util/{ApiAuth.scala => AfterApiAuth.scala} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename obp-api/src/main/scala/code/api/util/{ApiAuth.scala => AfterApiAuth.scala} (99%) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index d7af26f6a..e47be8c25 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2766,9 +2766,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ // COMMON POST AUTHENTICATION CODE GOES BELOW // Check is it a user deleted or locked - val userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])] = ApiAuth.checkUserIsDeletedOrLocked(res) + val userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])] = AfterApiAuth.checkUserIsDeletedOrLocked(res) // Check Rate Limiting - val resultWithRateLimiting: Future[(Box[User], Option[CallContext])] = ApiAuth.checkRateLimiting(userIsLockedOrDeleted) + val resultWithRateLimiting: Future[(Box[User], Option[CallContext])] = AfterApiAuth.checkRateLimiting(userIsLockedOrDeleted) // Update Call Context resultWithRateLimiting map { diff --git a/obp-api/src/main/scala/code/api/util/ApiAuth.scala b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala similarity index 99% rename from obp-api/src/main/scala/code/api/util/ApiAuth.scala rename to obp-api/src/main/scala/code/api/util/AfterApiAuth.scala index 5acc2bca7..50cba999c 100644 --- a/obp-api/src/main/scala/code/api/util/ApiAuth.scala +++ b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala @@ -13,7 +13,7 @@ import com.openbankproject.commons.ExecutionContext.Implicits.global import scala.concurrent.Future -object ApiAuth { +object AfterApiAuth { def checkUserIsDeletedOrLocked(res: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = { for { (user: Box[User], cc) <- res From 84ccd9eb3dfead9de7b70c46e53cb5f92ae4fcc2 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 23 Nov 2021 20:49:16 +0100 Subject: [PATCH 259/293] feature/remove the space for the buildOperationId method --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index e47be8c25..a51b727fc 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1666,7 +1666,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } def buildOperationId(apiVersion: ScannedApiVersion, partialFunctionName: String) = - s"${apiVersion.fullyQualifiedVersion}-$partialFunctionName" + s"${apiVersion.fullyQualifiedVersion}-$partialFunctionName".trim //This is correct: OBPv3.0.0-getCoreAccountById //This is OBPv4_0_0-dynamicEntity_deleteFooBar33 From 9abda6462d14f555c68ff872c7c4e229ab1e56e3 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 24 Nov 2021 12:08:19 +0100 Subject: [PATCH 260/293] docfix/tweaked the document for description field --- obp-api/src/main/scala/code/api/util/ExampleValue.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index ae76c49ab..6fb6cf34f 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -2,9 +2,10 @@ package code.api.util import code.api.util.APIUtil.parseDate -import code.api.util.ErrorMessages.{InvalidJsonFormat, UserHasMissingRoles, UserNotLoggedIn, UnknownError} +import code.api.util.ErrorMessages.{InvalidJsonFormat, UnknownError, UserHasMissingRoles, UserNotLoggedIn} import net.liftweb.json.JsonDSL._ import code.api.util.Glossary.{glossaryItems, makeGlossaryItem} +import code.apicollection.ApiCollection import code.dynamicEntity.{DynamicEntityDefinition, DynamicEntityFooBar, DynamicEntityFullBarFields, DynamicEntityIntTypeExample, DynamicEntityStringTypeExample} import com.openbankproject.commons.model.enums.{CustomerAttributeType, DynamicEntityFieldType} import com.openbankproject.commons.util.ReflectUtils @@ -2061,7 +2062,7 @@ object ExampleValue { lazy val indexExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("index", indexExample) - lazy val descriptionExample = ConnectorField("This is used for customer x!","The human readable description here.") + lazy val descriptionExample = ConnectorField(s"This an optional field. Maximum length is ${ApiCollection.Description.maxLen}. It can be any characters here.","The human readable description here.") glossaryItems += makeGlossaryItem("description", descriptionExample) lazy val dynamicResourceDocdescriptionExample = ConnectorField("Create one User", "the description for this endpoint") From 10acb96ead361d024ee0fdd62dbe45ea98a86eab Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 24 Nov 2021 12:09:13 +0100 Subject: [PATCH 261/293] refactor/typo --- .../code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 2 +- obp-api/src/main/scala/code/api/util/ExampleValue.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 412182782..0ff28d9b8 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4285,7 +4285,7 @@ object SwaggerDefinitionsJSON { requestVerb = requestVerbExample.value, requestUrl = requestUrlExample.value, summary = dynamicResourceDocSummaryExample.value, - description = dynamicResourceDocdescriptionExample.value, + description = dynamicResourceDocDescriptionExample.value, exampleRequestBody = Option(json.parse(exampleRequestBodyExample.value)), successResponseBody = Option(json.parse(successResponseBodyExample.value)), errorResponseBodies = errorResponseBodiesExample.value, diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 6fb6cf34f..3f1ca6743 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -2065,8 +2065,8 @@ object ExampleValue { lazy val descriptionExample = ConnectorField(s"This an optional field. Maximum length is ${ApiCollection.Description.maxLen}. It can be any characters here.","The human readable description here.") glossaryItems += makeGlossaryItem("description", descriptionExample) - lazy val dynamicResourceDocdescriptionExample = ConnectorField("Create one User", "the description for this endpoint") - glossaryItems += makeGlossaryItem("DynamicResourceDoc.description", dynamicResourceDocdescriptionExample) + lazy val dynamicResourceDocDescriptionExample = ConnectorField("Create one User", "the description for this endpoint") + glossaryItems += makeGlossaryItem("DynamicResourceDoc.description", dynamicResourceDocDescriptionExample) lazy val canDeleteCommentExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("can_delete_comment", canDeleteCommentExample) From 7ba30cff511cf5fc7ccb69bb0fceeb9bd4b38e53 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 24 Nov 2021 14:16:21 +0100 Subject: [PATCH 262/293] feature/added the CanCreateEntitlementAtOneBank role when createBank --- .../main/scala/code/api/v2_2_0/APIMethods220.scala | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index ab31a4e38..09ba46f1e 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -1,7 +1,6 @@ package code.api.v2_2_0 import java.util.Date - import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil._ import code.api.util.ApiRole.{canCreateBranch, _} @@ -14,6 +13,7 @@ import code.api.v2_1_0._ import code.api.v2_2_0.JSONFactory220.transformV220ToBranch import code.bankconnectors._ import code.consumer.Consumers +import code.entitlement.Entitlement import code.fx.{MappedFXRate, fx} import code.metadata.counterparties.{Counterparties, MappedCounterparty} import code.metrics.ConnectorMetricsProvider @@ -455,6 +455,16 @@ trait APIMethods220 { bank.bank_routing.scheme, bank.bank_routing.address ) + entitlements <- Entitlement.entitlement.vend.getEntitlementsByUserId(u.userId) + + entitlementsByBank = entitlements.filter(_.bankId==bank.id) + _ <- entitlementsByBank.filter(_.roleName == CanCreateEntitlementAtOneBank.toString()).size > 0 match { + case true => + // Already has entitlement + Full() + case false => + Full(Entitlement.entitlement.vend.addEntitlement(bank.id, u.userId, CanCreateEntitlementAtOneBank.toString())) + } } yield { val json = JSONFactory220.createBankJSON(success) createdJsonResponse(Extraction.decompose(json)) From 476f6157a958a129f20bd3961fe7c862f66abc73 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 24 Nov 2021 15:26:29 +0100 Subject: [PATCH 263/293] feature/added the missing roles for the CreateBank endpoint --- obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala | 7 +++++++ obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 09ba46f1e..8e4969bbe 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -465,6 +465,13 @@ trait APIMethods220 { case false => Full(Entitlement.entitlement.vend.addEntitlement(bank.id, u.userId, CanCreateEntitlementAtOneBank.toString())) } + _ <- entitlementsByBank.filter(_.roleName == CanReadDynamicResourceDocsAtOneBank.toString()).size > 0 match { + case true => + // Already has entitlement + Full() + case false => + Full(Entitlement.entitlement.vend.addEntitlement(bank.id, u.userId, CanReadDynamicResourceDocsAtOneBank.toString())) + } } yield { val json = JSONFactory220.createBankJSON(success) createdJsonResponse(Extraction.decompose(json)) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 190a6e612..a074d7c89 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -3947,6 +3947,13 @@ trait APIMethods400 { case false => Future(Entitlement.entitlement.vend.addEntitlement(bank.id, cc.userId, CanCreateEntitlementAtOneBank.toString())) } + _ <- entitlementsByBank.filter(_.roleName == CanReadDynamicResourceDocsAtOneBank.toString()).size > 0 match { + case true => + // Already has entitlement + Future() + case false => + Future(Entitlement.entitlement.vend.addEntitlement(bank.id, cc.userId, CanReadDynamicResourceDocsAtOneBank.toString())) + } } yield { (JSONFactory400.createBankJSON400(success), HttpCode.`201`(callContext)) } From 984709e8909ffeee4248b44dd1922d78fe04b10c Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 24 Nov 2021 16:09:32 +0100 Subject: [PATCH 264/293] docfix/tweaked the docs for transaction meta --- .../scala/code/api/v1_2_1/APIMethods121.scala | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 3e45426b8..2e5adbe69 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -2401,7 +2401,7 @@ trait APIMethods121 { "getTransactionNarrative", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/narrative", - "Get narrative", + "Get a Transaction Narrative", """Returns the account owner description of the transaction [moderated](#1_2_1-getViewsForBankAccount) by the view. | |Authentication via OAuth is required if the view is not public.""", @@ -2437,7 +2437,7 @@ trait APIMethods121 { "addTransactionNarrative", "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/narrative", - "Add narrative", + "Add a Transaction Narrative", s"""Creates a description of the transaction TRANSACTION_ID. | |Note: Unlike other items of metadata, there is only one "narrative" per transaction accross all views. @@ -2481,7 +2481,7 @@ trait APIMethods121 { "updateTransactionNarrative", "PUT", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/narrative", - "Update narrative", + "Update a Transaction Narrative", """Updates the description of the transaction TRANSACTION_ID. | |Authentication via OAuth is required if the view is not public.""", @@ -2519,7 +2519,7 @@ trait APIMethods121 { "deleteTransactionNarrative", "DELETE", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/narrative", - "Delete narrative", + "Delete a Transaction Narrative", """Deletes the description of the transaction TRANSACTION_ID. | |Authentication via OAuth is required if the view is not public.""", @@ -2556,7 +2556,7 @@ trait APIMethods121 { "getCommentsForViewOnTransaction", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/comments", - "Get comments", + "Get Transaction Comments", """Returns the transaction TRANSACTION_ID comments made on a [view](#1_2_1-getViewsForBankAccount) (VIEW_ID). | |Authentication via OAuth is required if the view is not public.""", @@ -2593,7 +2593,7 @@ trait APIMethods121 { "addCommentForViewOnTransaction", "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/comments", - "Add comment", + "Add a Transaction Comment", """Posts a comment about a transaction TRANSACTION_ID on a [view](#1_2_1-getViewsForBankAccount) VIEW_ID. | |${authenticationRequiredMessage(false)} @@ -2639,7 +2639,7 @@ trait APIMethods121 { "deleteCommentForViewOnTransaction", "DELETE", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/comments/COMMENT_ID", - "Delete comment", + "Delete a Transaction Comment", """Delete the comment COMMENT_ID about the transaction TRANSACTION_ID made on [view](#1_2_1-getViewsForBankAccount). | |Authentication via OAuth is required. The user must either have owner privileges for this account, or must be the user that posted the comment.""", @@ -2677,7 +2677,7 @@ trait APIMethods121 { "getTagsForViewOnTransaction", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/tags", - "Get tags", + "Get Transaction Tags", """Returns the transaction TRANSACTION_ID tags made on a [view](#1_2_1-getViewsForBankAccount) (VIEW_ID). Authentication via OAuth is required if the view is not public.""", emptyObjectJson, @@ -2713,7 +2713,7 @@ trait APIMethods121 { "addTagForViewOnTransaction", "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/tags", - "Add a tag", + "Add a Transaction Tag", s"""Posts a tag about a transaction TRANSACTION_ID on a [view](#1_2_1-getViewsForBankAccount) VIEW_ID. | |${authenticationRequiredMessage(true)} @@ -2759,7 +2759,7 @@ trait APIMethods121 { "deleteTagForViewOnTransaction", "DELETE", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/tags/TAG_ID", - "Delete a tag", + "Delete a Transaction Tag", """Deletes the tag TAG_ID about the transaction TRANSACTION_ID made on [view](#1_2_1-getViewsForBankAccount). |Authentication via OAuth is required. The user must either have owner privileges for this account, |or must be the user that posted the tag. @@ -2796,7 +2796,7 @@ trait APIMethods121 { "getImagesForViewOnTransaction", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/images", - "Get images", + "Get Transaction Images", """Returns the transaction TRANSACTION_ID images made on a [view](#1_2_1-getViewsForBankAccount) (VIEW_ID). Authentication via OAuth is required if the view is not public.""", emptyObjectJson, @@ -2832,7 +2832,7 @@ trait APIMethods121 { "addImageForViewOnTransaction", "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/images", - "Add an image", + "Add a Transaction Image", s"""Posts an image about a transaction TRANSACTION_ID on a [view](#1_2_1-getViewsForBankAccount) VIEW_ID. | |${authenticationRequiredMessage(true) } @@ -2878,7 +2878,7 @@ trait APIMethods121 { "deleteImageForViewOnTransaction", "DELETE", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/images/IMAGE_ID", - "Delete an image", + "Delete a Transaction Image", """Deletes the image IMAGE_ID about the transaction TRANSACTION_ID made on [view](#1_2_1-getViewsForBankAccount). | |Authentication via OAuth is required. The user must either have owner privileges for this account, or must be the user that posted the image.""", @@ -2919,7 +2919,7 @@ trait APIMethods121 { "getWhereTagForViewOnTransaction", "GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/where", - "Get where tag", + "Get a Transaction where Tag", """Returns the "where" Geo tag added to the transaction TRANSACTION_ID made on a [view](#1_2_1-getViewsForBankAccount) (VIEW_ID). |It represents the location where the transaction has been initiated. | @@ -2956,7 +2956,7 @@ trait APIMethods121 { "addWhereTagForViewOnTransaction", "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/where", - "Add where tag", + "Add a Transaction where Tag", s"""Creates a "where" Geo tag on a transaction TRANSACTION_ID in a [view](#1_2_1-getViewsForBankAccount). | |${authenticationRequiredMessage(true)} @@ -3002,7 +3002,7 @@ trait APIMethods121 { "updateWhereTagForViewOnTransaction", "PUT", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/where", - "Update where tag", + "Update a Transaction where Tag", s"""Updates the "where" Geo tag on a transaction TRANSACTION_ID in a [view](#1_2_1-getViewsForBankAccount). | |${authenticationRequiredMessage(true)} @@ -3048,7 +3048,7 @@ trait APIMethods121 { "deleteWhereTagForViewOnTransaction", "DELETE", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions/TRANSACTION_ID/metadata/where", - "Delete where tag", + "Delete a Transaction Tag", s"""Deletes the where tag of the transaction TRANSACTION_ID made on [view](#1_2_1-getViewsForBankAccount). | |${authenticationRequiredMessage(true)} From f637f48095dd0766ce4b7a24506c7bc4c6332215 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 11:42:03 +0100 Subject: [PATCH 265/293] bugfix/Unexpected missing generic font family --- .../webapp/media/css/api-documentation-content.css | 6 +++--- obp-api/src/main/webapp/media/css/authorise.css | 12 ++++++------ .../src/main/webapp/media/css/cookies-consent.css | 6 +++--- obp-api/src/main/webapp/media/css/data-area.css | 8 ++++---- obp-api/src/main/webapp/media/css/fonts.css | 2 +- obp-api/src/main/webapp/media/css/footer.css | 2 +- obp-api/src/main/webapp/media/css/get-started.css | 6 +++--- obp-api/src/main/webapp/media/css/main-apis.css | 4 ++-- obp-api/src/main/webapp/media/css/main-faq.css | 6 +++--- obp-api/src/main/webapp/media/css/main-showcases.css | 4 ++-- obp-api/src/main/webapp/media/css/main-start.css | 2 +- obp-api/src/main/webapp/media/css/main-support.css | 2 +- obp-api/src/main/webapp/media/css/nav.css | 8 ++++---- obp-api/src/main/webapp/media/css/obp-toastr.css | 2 +- .../src/main/webapp/media/css/recover-password.css | 2 +- .../src/main/webapp/media/css/register-consumer.css | 8 ++++---- obp-api/src/main/webapp/media/css/signup.css | 12 ++++++------ obp-api/src/main/webapp/media/css/website.css | 12 ++++++------ 18 files changed, 52 insertions(+), 52 deletions(-) diff --git a/obp-api/src/main/webapp/media/css/api-documentation-content.css b/obp-api/src/main/webapp/media/css/api-documentation-content.css index 0f87dab5a..1c0dffa6e 100644 --- a/obp-api/src/main/webapp/media/css/api-documentation-content.css +++ b/obp-api/src/main/webapp/media/css/api-documentation-content.css @@ -48,7 +48,7 @@ font-size: 16px; line-height: 24px; font-weight:normal; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; /*paragraph-height: 12px*/ } @@ -58,12 +58,12 @@ line-height: 24px; font-weight:normal; margin: 8px 0; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; /*paragraph-height: 12px*/ } .container #api_documentation_content a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/authorise.css b/obp-api/src/main/webapp/media/css/authorise.css index 60a886e0a..714ac67e4 100644 --- a/obp-api/src/main/webapp/media/css/authorise.css +++ b/obp-api/src/main/webapp/media/css/authorise.css @@ -18,7 +18,7 @@ #login-form-password{ margin-bottom: 8px; margin-top: 32px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -31,7 +31,7 @@ float: right; height: 44px; width: 92px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; text-align: center; line-height: 24px; @@ -73,7 +73,7 @@ } #authorise #authorise-recover-password a, #authorise #oauth-authorise-recover-password a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; letter-spacing: 0; @@ -84,7 +84,7 @@ #authorise .login-or { margin-top: 30px; float: left; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 18px; color: #929292; letter-spacing: 0; @@ -110,7 +110,7 @@ } #authorise #thanks-detail{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -142,7 +142,7 @@ #authorise #login-form-username-error, #authorise #login-form-password-error{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; line-height: 20px; diff --git a/obp-api/src/main/webapp/media/css/cookies-consent.css b/obp-api/src/main/webapp/media/css/cookies-consent.css index 6ce328364..5a865c0af 100644 --- a/obp-api/src/main/webapp/media/css/cookies-consent.css +++ b/obp-api/src/main/webapp/media/css/cookies-consent.css @@ -1,6 +1,6 @@ #cookies-consent { background: #252525; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; display:none; text-align: center; @@ -17,7 +17,7 @@ position: absolute; left: 100px; top: 32px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; line-height: 24px; @@ -30,7 +30,7 @@ position: absolute; left: 100px; top: 80px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; text-align: center; diff --git a/obp-api/src/main/webapp/media/css/data-area.css b/obp-api/src/main/webapp/media/css/data-area.css index a3cd199ca..82a0dc0cc 100644 --- a/obp-api/src/main/webapp/media/css/data-area.css +++ b/obp-api/src/main/webapp/media/css/data-area.css @@ -40,7 +40,7 @@ #data-area #data-area-explanation p:last-child{ margin-top: 8px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; letter-spacing: 0; @@ -51,7 +51,7 @@ #data-area-input form label{ margin-bottom: 8px; margin-top: 17px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -114,7 +114,7 @@ #data-area-success span, #data-area-success a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -138,7 +138,7 @@ } #data-area-input #data-area-errors{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; line-height: 20px; diff --git a/obp-api/src/main/webapp/media/css/fonts.css b/obp-api/src/main/webapp/media/css/fonts.css index d95c71b25..3120bb343 100644 --- a/obp-api/src/main/webapp/media/css/fonts.css +++ b/obp-api/src/main/webapp/media/css/fonts.css @@ -11,7 +11,7 @@ } @font-face { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; src: url(../font/Roboto-Regular.ttf); } diff --git a/obp-api/src/main/webapp/media/css/footer.css b/obp-api/src/main/webapp/media/css/footer.css index f6069c310..738c9cb51 100644 --- a/obp-api/src/main/webapp/media/css/footer.css +++ b/obp-api/src/main/webapp/media/css/footer.css @@ -9,7 +9,7 @@ footer a,span, footer a:hover, footer a:focus, span:hover { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #FFFFFF; letter-spacing: 0; diff --git a/obp-api/src/main/webapp/media/css/get-started.css b/obp-api/src/main/webapp/media/css/get-started.css index 45ab63d64..3e22c1ee7 100644 --- a/obp-api/src/main/webapp/media/css/get-started.css +++ b/obp-api/src/main/webapp/media/css/get-started.css @@ -28,13 +28,13 @@ margin-bottom: 17px; } #main-get-started .main-get-started-text p{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; } #main-get-started .main-get-started-text p a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -64,7 +64,7 @@ } #main-get-started .btn-primary a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; text-align: center; diff --git a/obp-api/src/main/webapp/media/css/main-apis.css b/obp-api/src/main/webapp/media/css/main-apis.css index 1270314f6..db29c59f4 100644 --- a/obp-api/src/main/webapp/media/css/main-apis.css +++ b/obp-api/src/main/webapp/media/css/main-apis.css @@ -30,7 +30,7 @@ margin-left: 7.2px; } #main-apis .main-apis-text p{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -59,7 +59,7 @@ background-color: #EDEDED; } #main-apis .btn-secondary a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; text-align: center; diff --git a/obp-api/src/main/webapp/media/css/main-faq.css b/obp-api/src/main/webapp/media/css/main-faq.css index cb07ec399..b2651a37b 100644 --- a/obp-api/src/main/webapp/media/css/main-faq.css +++ b/obp-api/src/main/webapp/media/css/main-faq.css @@ -17,7 +17,7 @@ } #main-faq h3 { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -44,7 +44,7 @@ #main-faq div a{ margin-top: 10px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -57,7 +57,7 @@ padding: 0; border: 1px solid transparent; background-color: #FFFFFF; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/main-showcases.css b/obp-api/src/main/webapp/media/css/main-showcases.css index 06e5122c6..27b4fa9cc 100644 --- a/obp-api/src/main/webapp/media/css/main-showcases.css +++ b/obp-api/src/main/webapp/media/css/main-showcases.css @@ -16,7 +16,7 @@ display: inline-block; margin: 30px 40px; width: 300px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; } @@ -24,7 +24,7 @@ #main-showcases p { color: white; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; line-height: 24px; } diff --git a/obp-api/src/main/webapp/media/css/main-start.css b/obp-api/src/main/webapp/media/css/main-start.css index 474ff9ea2..37ab3844c 100644 --- a/obp-api/src/main/webapp/media/css/main-start.css +++ b/obp-api/src/main/webapp/media/css/main-start.css @@ -28,7 +28,7 @@ padding: 64px 0; } #main-start #main-start_building .btn-default a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; text-align: center; diff --git a/obp-api/src/main/webapp/media/css/main-support.css b/obp-api/src/main/webapp/media/css/main-support.css index 39b2b4b9e..8652c2db5 100644 --- a/obp-api/src/main/webapp/media/css/main-support.css +++ b/obp-api/src/main/webapp/media/css/main-support.css @@ -14,7 +14,7 @@ margin-bottom: 9px ; } .main-support-item a { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/nav.css b/obp-api/src/main/webapp/media/css/nav.css index 420a0707e..c06a92139 100644 --- a/obp-api/src/main/webapp/media/css/nav.css +++ b/obp-api/src/main/webapp/media/css/nav.css @@ -53,7 +53,7 @@ nav .navbar-collapse.collapse { margin-right: 0; } .navbar-default .navbar-right .navitem p #register-link { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -79,7 +79,7 @@ nav .navbar-collapse.collapse { .navbar-default .navbar-right .navbar-btn #loggedIn-username { margin-right: 24px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -130,7 +130,7 @@ nav .navbar-collapse.collapse { } #small-screen-navbar #small-nav-log-on-button .login{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 12px; color: #FFFFFF; letter-spacing: 0; @@ -157,7 +157,7 @@ nav .navbar-collapse.collapse { .sidebar a { text-decoration: none; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/obp-toastr.css b/obp-api/src/main/webapp/media/css/obp-toastr.css index e167758ef..0b2769033 100644 --- a/obp-api/src/main/webapp/media/css/obp-toastr.css +++ b/obp-api/src/main/webapp/media/css/obp-toastr.css @@ -43,7 +43,7 @@ } #toast-container .toast-message { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/recover-password.css b/obp-api/src/main/webapp/media/css/recover-password.css index bf24d8a7f..9fc17b968 100644 --- a/obp-api/src/main/webapp/media/css/recover-password.css +++ b/obp-api/src/main/webapp/media/css/recover-password.css @@ -23,7 +23,7 @@ border: 0; height: 44px; width: 92px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; text-align: center; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/register-consumer.css b/obp-api/src/main/webapp/media/css/register-consumer.css index c4f5dafa4..7268d9ef1 100644 --- a/obp-api/src/main/webapp/media/css/register-consumer.css +++ b/obp-api/src/main/webapp/media/css/register-consumer.css @@ -40,7 +40,7 @@ #register-consumer #register-consumer-explanation p:last-child{ margin-top: 8px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; letter-spacing: 0; @@ -51,7 +51,7 @@ #register-consumer-input form label{ margin-bottom: 8px; margin-top: 17px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -114,7 +114,7 @@ #register-consumer-success span, #register-consumer-success a{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -144,7 +144,7 @@ #register-consumer-input #consumer-registration-app-description-error, #register-consumer-input #consumer-registration-app-developer-error, #register-consumer-input #register-consumer-errors{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; line-height: 20px; diff --git a/obp-api/src/main/webapp/media/css/signup.css b/obp-api/src/main/webapp/media/css/signup.css index 35f2bb396..60db8b229 100644 --- a/obp-api/src/main/webapp/media/css/signup.css +++ b/obp-api/src/main/webapp/media/css/signup.css @@ -19,7 +19,7 @@ } #signup form span{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -32,7 +32,7 @@ #signup form #repeat-password{ margin-top: 32px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -43,7 +43,7 @@ } #signup form label{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -138,7 +138,7 @@ font-size: 16px; } #signup-agree-terms #signup-agree-terms-content { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; letter-spacing: 0; @@ -151,7 +151,7 @@ #signup #signup-submit input { color: #FFF; background-color: #53C4EF; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; text-align: center; @@ -223,7 +223,7 @@ margin-bottom: 0px; } #signup-legal-notice{ - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 14px; color: #333333; letter-spacing: 0; diff --git a/obp-api/src/main/webapp/media/css/website.css b/obp-api/src/main/webapp/media/css/website.css index c4a621bd8..989894a8a 100644 --- a/obp-api/src/main/webapp/media/css/website.css +++ b/obp-api/src/main/webapp/media/css/website.css @@ -31,7 +31,7 @@ body { } a { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; color: #333333; text-decoration: none; } @@ -133,7 +133,7 @@ header #lift__noticesContainer__ { } .btn-danger { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #FFFFFF; text-align: center; @@ -164,7 +164,7 @@ header #lift__noticesContainer__ { padding-bottom: 11px; padding-left: 20px; padding-right: 20px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; text-align: center; @@ -213,7 +213,7 @@ input[type="text"]{ } .select2-results__option { padding: 6px; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -224,7 +224,7 @@ input[type="text"]{ } .select2-container--default .select2-selection--single .select2-selection__rendered { - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -428,7 +428,7 @@ input{ #confirm-user-auth-context-update-request-div #otp-value-error .error{ color: black; background-color: white; - font-family: Roboto-Regular; + font-family: Roboto-Regular,sans-serif; font-size: 16px; color: #333333; line-height: 24px; From 237a090e37adf6d48a576f9d9c72a37ff196df5d Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 11:53:44 +0100 Subject: [PATCH 266/293] bugfix/Unexpected missing generic font family - step2 --- .../src/main/webapp/media/css/authorise.css | 4 +-- .../src/main/webapp/media/css/data-area.css | 10 +++---- obp-api/src/main/webapp/media/css/fonts.css | 4 +-- .../src/main/webapp/media/css/main-faq.css | 2 +- obp-api/src/main/webapp/media/css/nav.css | 2 +- .../src/main/webapp/media/css/obp-toastr.css | 2 +- .../webapp/media/css/recover-password.css | 2 +- .../webapp/media/css/register-consumer.css | 12 ++++---- obp-api/src/main/webapp/media/css/reset.css | 2 +- .../src/main/webapp/media/css/responsive.css | 28 +++++++++---------- obp-api/src/main/webapp/media/css/signup.css | 2 +- 11 files changed, 35 insertions(+), 35 deletions(-) diff --git a/obp-api/src/main/webapp/media/css/authorise.css b/obp-api/src/main/webapp/media/css/authorise.css index 714ac67e4..28fe6ef16 100644 --- a/obp-api/src/main/webapp/media/css/authorise.css +++ b/obp-api/src/main/webapp/media/css/authorise.css @@ -5,7 +5,7 @@ } #authorise h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; line-height: 36px; @@ -102,7 +102,7 @@ color: red; } #authorise #thanks-h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; letter-spacing: 0; diff --git a/obp-api/src/main/webapp/media/css/data-area.css b/obp-api/src/main/webapp/media/css/data-area.css index 82a0dc0cc..e729672e7 100644 --- a/obp-api/src/main/webapp/media/css/data-area.css +++ b/obp-api/src/main/webapp/media/css/data-area.css @@ -17,7 +17,7 @@ color: black; } #data-area h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; letter-spacing: 0; @@ -28,7 +28,7 @@ } #data-area #data-area-explanation p:nth-child(2) { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 22px; color: #333333; letter-spacing: 0; @@ -88,7 +88,7 @@ } #data-area #data-area-success #data-area-success-message{ - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 22px; color: #333333; letter-spacing: 0; @@ -98,7 +98,7 @@ #data-area #data-area-success p { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 22px; color: #333333; letter-spacing: 0; @@ -123,7 +123,7 @@ margin-bottom: 20px; } #data-area #data-area-success .row div:nth-child(1) { - font-family: Roboto-Medium; + font-family: Roboto-Medium,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/fonts.css b/obp-api/src/main/webapp/media/css/fonts.css index 3120bb343..3d35bb34a 100644 --- a/obp-api/src/main/webapp/media/css/fonts.css +++ b/obp-api/src/main/webapp/media/css/fonts.css @@ -1,12 +1,12 @@ /*https://fonts.google.com/specimen/Roboto?selection.family=Roboto&sidebar.open=true*/ /*We use the Roboto font as the OBP default font*/ @font-face { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; src: url(../font/Roboto-Light.ttf); } @font-face { - font-family: Roboto-Medium; + font-family: Roboto-Medium,sans-serif; src: url(../font/Roboto-Medium.ttf); } diff --git a/obp-api/src/main/webapp/media/css/main-faq.css b/obp-api/src/main/webapp/media/css/main-faq.css index b2651a37b..5a07aa450 100644 --- a/obp-api/src/main/webapp/media/css/main-faq.css +++ b/obp-api/src/main/webapp/media/css/main-faq.css @@ -35,7 +35,7 @@ } #main-faq p, #main-faq ol{ margin-top: 18px; - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/nav.css b/obp-api/src/main/webapp/media/css/nav.css index c06a92139..435129e14 100644 --- a/obp-api/src/main/webapp/media/css/nav.css +++ b/obp-api/src/main/webapp/media/css/nav.css @@ -25,7 +25,7 @@ nav .navbar-collapse.collapse { } .navbar-default .navbar-nav > li > a { background-color: white; - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 18px; color: #333333; line-height: 31px; diff --git a/obp-api/src/main/webapp/media/css/obp-toastr.css b/obp-api/src/main/webapp/media/css/obp-toastr.css index 0b2769033..79f73a5db 100644 --- a/obp-api/src/main/webapp/media/css/obp-toastr.css +++ b/obp-api/src/main/webapp/media/css/obp-toastr.css @@ -26,7 +26,7 @@ #toast-container .toast-title { float: left; font-weight: bold; - font-family: Roboto-Medium; + font-family: Roboto-Medium,sans-serif; font-size: 16px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/recover-password.css b/obp-api/src/main/webapp/media/css/recover-password.css index 9fc17b968..1c37005d7 100644 --- a/obp-api/src/main/webapp/media/css/recover-password.css +++ b/obp-api/src/main/webapp/media/css/recover-password.css @@ -1,6 +1,6 @@ #recover-password h1 { margin-top: 52px; - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 35px; color: #333333; text-align: center; diff --git a/obp-api/src/main/webapp/media/css/register-consumer.css b/obp-api/src/main/webapp/media/css/register-consumer.css index 7268d9ef1..476560036 100644 --- a/obp-api/src/main/webapp/media/css/register-consumer.css +++ b/obp-api/src/main/webapp/media/css/register-consumer.css @@ -17,7 +17,7 @@ color: black; } #register-consumer h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; letter-spacing: 0; @@ -28,7 +28,7 @@ } #register-consumer #register-consumer-explanation p:nth-child(2) { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 22px; color: #333333; letter-spacing: 0; @@ -88,7 +88,7 @@ } #register-consumer #register-consumer-success #register-consumer-success-message{ - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 22px; color: #333333; letter-spacing: 0; @@ -98,7 +98,7 @@ #register-consumer #register-consumer-success p { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 22px; color: #333333; letter-spacing: 0; @@ -123,7 +123,7 @@ margin-bottom: 20px; } #register-consumer #register-consumer-success .row div:nth-child(1) { - font-family: Roboto-Medium; + font-family: Roboto-Medium,sans-serif; font-size: 16px; color: #333333; line-height: 24px; @@ -157,7 +157,7 @@ } #dummy-user-tokens .col-xs-12:last-child{ - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 20px; color: #333333; line-height: 24px; diff --git a/obp-api/src/main/webapp/media/css/reset.css b/obp-api/src/main/webapp/media/css/reset.css index 1fb79bec2..805a1106a 100644 --- a/obp-api/src/main/webapp/media/css/reset.css +++ b/obp-api/src/main/webapp/media/css/reset.css @@ -22,7 +22,7 @@ time, mark, audio, video { font: inherit; font-size: 100%; vertical-align: baseline; - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, diff --git a/obp-api/src/main/webapp/media/css/responsive.css b/obp-api/src/main/webapp/media/css/responsive.css index 9d5037105..bd94bc6cc 100644 --- a/obp-api/src/main/webapp/media/css/responsive.css +++ b/obp-api/src/main/webapp/media/css/responsive.css @@ -55,7 +55,7 @@ display: block; } h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 33px; line-height: 40px; color: #333333; @@ -64,21 +64,21 @@ } h2 { font-size: 28px; - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; line-height: 36px; color: #333333; font-weight: lighter; text-align: center; } h3 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 23px; color: #333333; line-height: 30px; font-weight: lighter; } h4 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 19px; color: #333333; line-height: 27px; @@ -204,7 +204,7 @@ @media only screen and (min-width: 760px) and (max-width: 959px) { h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 33px; line-height: 40px; color: #333333; @@ -213,21 +213,21 @@ } h2 { font-size: 28px; - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; line-height: 36px; color: #333333; font-weight: lighter; text-align: center; } h3 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 23px; color: #333333; line-height: 15px; font-weight: lighter; } h4 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 19px; color: #333333; line-height: 27px; @@ -319,7 +319,7 @@ @media only screen and (min-width: 960px) and (max-width: 1279px) { h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 44px; color: #333333; letter-spacing: 0; @@ -327,7 +327,7 @@ } h2 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 35px; color: #333333; text-align: center; @@ -335,7 +335,7 @@ } h3 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; line-height: 36px; @@ -387,7 +387,7 @@ @media only screen and (min-width: 1280px) { h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 44px; color: #333333; letter-spacing: 0; @@ -395,7 +395,7 @@ } h2 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 35px; color: #333333; text-align: center; @@ -403,7 +403,7 @@ } h3 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; line-height: 36px; diff --git a/obp-api/src/main/webapp/media/css/signup.css b/obp-api/src/main/webapp/media/css/signup.css index 60db8b229..91d6e5bdb 100644 --- a/obp-api/src/main/webapp/media/css/signup.css +++ b/obp-api/src/main/webapp/media/css/signup.css @@ -10,7 +10,7 @@ } #signup form h1 { - font-family: Roboto-Light; + font-family: Roboto-Light,sans-serif; font-size: 28px; color: #333333; letter-spacing: 0; From 9fc8ce894f4094dd9bb5d848dbca376fd6252ca0 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 13:57:01 +0100 Subject: [PATCH 267/293] bugfix/Correct one of the identical sub-expressions on both sides this operator --- obp-api/src/main/scala/code/atms/Atms.scala | 2 +- .../vJune2017/KafkaMappedConnector_vJune2017.scala | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/atms/Atms.scala b/obp-api/src/main/scala/code/atms/Atms.scala index 8c5f6ac4a..dede15ea6 100644 --- a/obp-api/src/main/scala/code/atms/Atms.scala +++ b/obp-api/src/main/scala/code/atms/Atms.scala @@ -92,7 +92,7 @@ trait AtmsProvider { getAtmsFromProvider(bankId,queryParams) match { case Some(atms) => { val atmsWithLicense = for { - branch <- atms if branch.meta.license.name.size > 3 && branch.meta.license.name.size > 3 + branch <- atms if branch.meta.license.name.size > 3 } yield branch Option(atmsWithLicense) } diff --git a/obp-api/src/main/scala/code/bankconnectors/vJune2017/KafkaMappedConnector_vJune2017.scala b/obp-api/src/main/scala/code/bankconnectors/vJune2017/KafkaMappedConnector_vJune2017.scala index 76ccbec7a..7a2cba025 100644 --- a/obp-api/src/main/scala/code/bankconnectors/vJune2017/KafkaMappedConnector_vJune2017.scala +++ b/obp-api/src/main/scala/code/bankconnectors/vJune2017/KafkaMappedConnector_vJune2017.scala @@ -1037,8 +1037,6 @@ trait KafkaMappedConnector_vJune2017 extends Connector with KafkaHelper with Mdc } yield { (transaction,callContext) } - case Full((data,status,callContext)) if (status.errorCode!="") => - Failure("INTERNAL-"+ status.errorCode+". + CoreBank-Status:"+ status.backendMessages) case Empty => Failure(ErrorMessages.InvalidConnectorResponse, Empty, Empty) case Failure(msg, e, c) => From 0bcdf6f88f1a470a184dd0047da5ffd8b34c3b19 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:00:58 +0100 Subject: [PATCH 268/293] refactor/comment the unused code --- .../examplething/MappedThingProvider.scala | 104 +++++------ .../main/scala/code/examplething/Thing.scala | 164 +++++++++--------- 2 files changed, 134 insertions(+), 134 deletions(-) diff --git a/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala b/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala index e4d9e7d68..53e1d0d7c 100644 --- a/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala +++ b/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala @@ -1,52 +1,52 @@ -package code.examplething - - -import code.util.UUIDString -import com.openbankproject.commons.model.BankId -import net.liftweb.common.Box -import net.liftweb.mapper._ - - - -object MappedThingProvider extends ThingProvider { - - override protected def getThingFromProvider(thingId: ThingId): Option[Thing] = - MappedThing.find(By(MappedThing.thingId_, thingId.value)) - - override protected def getThingsFromProvider(bankId: BankId): Option[List[Thing]] = { - Some(MappedThing.findAll(By(MappedThing.bankId_, bankId.value))) - } -} - -class MappedThing extends Thing with LongKeyedMapper[MappedThing] with IdPK { - - override def getSingleton = MappedThing - - object bankId_ extends UUIDString(this) - object name_ extends MappedString(this, 255) - - object thingId_ extends MappedString(this, 30) - - object fooSomething_ extends MappedString(this, 255) - object barSomething_ extends MappedString(this, 255) - - override def thingId: ThingId = ThingId(thingId_.get) - override def something: String = name_.get - - - override def foo: Foo = new Foo { - override def fooSomething: String = fooSomething_.get - } - - override def bar: Bar = new Bar { - override def barSomething: String = barSomething_.get - } - - -} - - -object MappedThing extends MappedThing with LongKeyedMetaMapper[MappedThing] { - override def dbIndexes = UniqueIndex(bankId_, thingId_) :: Index(bankId_) :: super.dbIndexes -} - +//package code.examplething +// +// +//import code.util.UUIDString +//import com.openbankproject.commons.model.BankId +//import net.liftweb.common.Box +//import net.liftweb.mapper._ +// +// +// +//object MappedThingProvider extends ThingProvider { +// +// override protected def getThingFromProvider(thingId: ThingId): Option[Thing] = +// MappedThing.find(By(MappedThing.thingId_, thingId.value)) +// +// override protected def getThingsFromProvider(bankId: BankId): Option[List[Thing]] = { +// Some(MappedThing.findAll(By(MappedThing.bankId_, bankId.value))) +// } +//} +// +//class MappedThing extends Thing with LongKeyedMapper[MappedThing] with IdPK { +// +// override def getSingleton = MappedThing +// +// object bankId_ extends UUIDString(this) +// object name_ extends MappedString(this, 255) +// +// object thingId_ extends MappedString(this, 30) +// +// object fooSomething_ extends MappedString(this, 255) +// object barSomething_ extends MappedString(this, 255) +// +// override def thingId: ThingId = ThingId(thingId_.get) +// override def something: String = name_.get +// +// +// override def foo: Foo = new Foo { +// override def fooSomething: String = fooSomething_.get +// } +// +// override def bar: Bar = new Bar { +// override def barSomething: String = barSomething_.get +// } +// +// +//} +// +// +//object MappedThing extends MappedThing with LongKeyedMetaMapper[MappedThing] { +// override def dbIndexes = UniqueIndex(bankId_, thingId_) :: Index(bankId_) :: super.dbIndexes +//} +// diff --git a/obp-api/src/main/scala/code/examplething/Thing.scala b/obp-api/src/main/scala/code/examplething/Thing.scala index 870928099..64800baa9 100644 --- a/obp-api/src/main/scala/code/examplething/Thing.scala +++ b/obp-api/src/main/scala/code/examplething/Thing.scala @@ -1,82 +1,82 @@ -package code.examplething - - -// Need to import these one by one because in same package! -import code.api.util.APIUtil -import com.openbankproject.commons.model.BankId -import net.liftweb.common.Logger -import net.liftweb.util.SimpleInjector - -object Thing extends SimpleInjector { - - val thingProvider = new Inject(buildOne _) {} - // def buildOne: ThingProvider = MappedThingProvider - - - // This determines the provider we use - def buildOne: ThingProvider = - APIUtil.getPropsValue("provider.thing").openOr("mapped") match { - case "mapped" => MappedThingProvider - case _ => MappedThingProvider - } - -} - -case class ThingId(value : String) - -trait Thing { - def thingId : ThingId - def something : String - def foo : Foo - def bar : Bar -} - -trait Foo { - def fooSomething : String -} - -trait Bar { - def barSomething : String -} - - -/* -A trait that defines interfaces to Thing -i.e. a ThingProvider should provide these: - */ - -trait ThingProvider { - - private val logger = Logger(classOf[ThingProvider]) - - - /* - Common logic for returning or changing Things - Datasource implementation details are in Thing provider - */ - final def getThings(bankId : BankId) : Option[List[Thing]] = { - getThingsFromProvider(bankId) match { - case Some(things) => { - - val certainThings = for { - thing <- things // if thing.meta.license.name.size > 3 - } yield thing - Option(certainThings) - } - case None => None - } - } - - /* - Return one Thing - */ - final def getThing(thingId : ThingId) : Option[Thing] = { - // Could do something here - getThingFromProvider(thingId) //.filter... - } - - protected def getThingFromProvider(thingId : ThingId) : Option[Thing] - protected def getThingsFromProvider(bank : BankId) : Option[List[Thing]] - -} - +//package code.examplething +// +// +//// Need to import these one by one because in same package! +//import code.api.util.APIUtil +//import com.openbankproject.commons.model.BankId +//import net.liftweb.common.Logger +//import net.liftweb.util.SimpleInjector +// +//object Thing extends SimpleInjector { +// +// val thingProvider = new Inject(buildOne _) {} +// // def buildOne: ThingProvider = MappedThingProvider +// +// +// // This determines the provider we use +// def buildOne: ThingProvider = +// APIUtil.getPropsValue("provider.thing").openOr("mapped") match { +// case "mapped" => MappedThingProvider +// case _ => MappedThingProvider +// } +// +//} +// +//case class ThingId(value : String) +// +//trait Thing { +// def thingId : ThingId +// def something : String +// def foo : Foo +// def bar : Bar +//} +// +//trait Foo { +// def fooSomething : String +//} +// +//trait Bar { +// def barSomething : String +//} +// +// +///* +//A trait that defines interfaces to Thing +//i.e. a ThingProvider should provide these: +// */ +// +//trait ThingProvider { +// +// private val logger = Logger(classOf[ThingProvider]) +// +// +// /* +// Common logic for returning or changing Things +// Datasource implementation details are in Thing provider +// */ +// final def getThings(bankId : BankId) : Option[List[Thing]] = { +// getThingsFromProvider(bankId) match { +// case Some(things) => { +// +// val certainThings = for { +// thing <- things // if thing.meta.license.name.size > 3 +// } yield thing +// Option(certainThings) +// } +// case None => None +// } +// } +// +// /* +// Return one Thing +// */ +// final def getThing(thingId : ThingId) : Option[Thing] = { +// // Could do something here +// getThingFromProvider(thingId) //.filter... +// } +// +// protected def getThingFromProvider(thingId : ThingId) : Option[Thing] +// protected def getThingsFromProvider(bank : BankId) : Option[List[Thing]] +// +//} +// From 5cd42d022f36580fe49b944bac53c9b2e5ceaf8d Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:01:57 +0100 Subject: [PATCH 269/293] feature/Correct one of the identical sub-expressions on both sides this operator --- obp-api/src/main/scala/code/products/Products.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/products/Products.scala b/obp-api/src/main/scala/code/products/Products.scala index e902f8f1d..cef006aa2 100644 --- a/obp-api/src/main/scala/code/products/Products.scala +++ b/obp-api/src/main/scala/code/products/Products.scala @@ -43,7 +43,7 @@ trait ProductsProvider { case Some(products) => { val productsWithLicense = for { // Only return products that have a license set unless its for an admin view - product <- products if (adminView || (product.meta.license.name.size > 3 && product.meta.license.name.size > 3)) + product <- products if (adminView || (product.meta.license.name.size > 3)) } yield product Option(productsWithLicense) } From 9337ad1cb84253fe4b085b1abf64164b71d88c2e Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:06:27 +0100 Subject: [PATCH 270/293] refactor/commented YearlyCharge code --- .../MappedYearlyChargeProvider.scala | 152 +++++++++--------- .../yearlycustomercharges/YearlyCharge.scala | 142 ++++++++-------- 2 files changed, 147 insertions(+), 147 deletions(-) diff --git a/obp-api/src/main/scala/code/yearlycustomercharges/MappedYearlyChargeProvider.scala b/obp-api/src/main/scala/code/yearlycustomercharges/MappedYearlyChargeProvider.scala index 8e47ba47c..592d9997d 100644 --- a/obp-api/src/main/scala/code/yearlycustomercharges/MappedYearlyChargeProvider.scala +++ b/obp-api/src/main/scala/code/yearlycustomercharges/MappedYearlyChargeProvider.scala @@ -1,76 +1,76 @@ -package code.yearlycustomercharges - -import code.util.UUIDString -import com.openbankproject.commons.model.{BankId, CustomerId} -import net.liftweb.common.Box -import net.liftweb.mapper._ - - - -object MappedYearlyChargeProvider extends YearlyChargeProvider { - -// override protected def getYearlyChargeFromProvider(thingId: YearlyChargeId): Option[YearlyCharge] = -// MappedYearlyCharge.find(By(MappedYearlyCharge.thingId_, thingId.value)) - - override protected def getYearlyChargesFromProvider(bankId: BankId, customerId: CustomerId, year: Int): Option[List[YearlyCharge]] = { - Some(MappedYearlyCharge.findAll(By(MappedYearlyCharge.bankId_, bankId.value), By(MappedYearlyCharge.customerId_, customerId.value))) - } -} - -class MappedYearlyCharge extends YearlyCharge with LongKeyedMapper[MappedYearlyCharge] with IdPK { - - override def getSingleton = MappedYearlyCharge - - object bankId_ extends UUIDString(this) - object customerId_ extends UUIDString(this) - - object year_ extends MappedInt(this) - - - - //override def yearlyChargeId: YearlyChargeId = YearlyChargeId(id.get) - override def year: Int = year_.get - - - // override def getSingleton = MappedYearlyCustomerCharge - // - // WIP - // object mCustomerNumber extends MappedString(this,123) - // - // object mYear extends MappedInt(this) - // - // object mCategoryId extends UUIDString(this) - // object mForcastIndictor extends MappedString(this,123) - // object mTypeId extends MappedString(this,123) - // object mNatureId extends UUIDString(this) - // - // - // object mCharge_Currency extends MappedString(this,3) - // object mCharge_Amount extends MappedString(this,32) - // - // object mUpdateDate extends MappedDateTime(this) - // - // - // //override def bankId: String = mBankId.get - // override def customerId: String = mCustomerId.get // id.toString - // override def customerNumber: String = mCustomerNumber.get - // override def year: Integer = mYear.get - // - // override def categoryId: String = mCategoryId.get - // override def forcastIndictor: String = mForcastIndictor.get - // override def typeId: String = mTypeId.get - // override def natureId : String = mNatureId.get - // - // override def charge: AmountOfMoney = AmountOfMoney(mCharge_Currency.get, mCharge_Amount.get) - // override def updateDate : Date = mUpdateDate.get - - - - -} - - -object MappedYearlyCharge extends MappedYearlyCharge with LongKeyedMetaMapper[MappedYearlyCharge] { - override def dbIndexes = UniqueIndex(bankId_, customerId_, year_) :: Index(bankId_) :: super.dbIndexes -} - +//package code.yearlycustomercharges +// +//import code.util.UUIDString +//import com.openbankproject.commons.model.{BankId, CustomerId} +//import net.liftweb.common.Box +//import net.liftweb.mapper._ +// +// +// +//object MappedYearlyChargeProvider extends YearlyChargeProvider { +// +//// override protected def getYearlyChargeFromProvider(thingId: YearlyChargeId): Option[YearlyCharge] = +//// MappedYearlyCharge.find(By(MappedYearlyCharge.thingId_, thingId.value)) +// +// override protected def getYearlyChargesFromProvider(bankId: BankId, customerId: CustomerId, year: Int): Option[List[YearlyCharge]] = { +// Some(MappedYearlyCharge.findAll(By(MappedYearlyCharge.bankId_, bankId.value), By(MappedYearlyCharge.customerId_, customerId.value))) +// } +//} +// +//class MappedYearlyCharge extends YearlyCharge with LongKeyedMapper[MappedYearlyCharge] with IdPK { +// +// override def getSingleton = MappedYearlyCharge +// +// object bankId_ extends UUIDString(this) +// object customerId_ extends UUIDString(this) +// +// object year_ extends MappedInt(this) +// +// +// +// //override def yearlyChargeId: YearlyChargeId = YearlyChargeId(id.get) +// override def year: Int = year_.get +// +// +// // override def getSingleton = MappedYearlyCustomerCharge +// // +// // WIP +// // object mCustomerNumber extends MappedString(this,123) +// // +// // object mYear extends MappedInt(this) +// // +// // object mCategoryId extends UUIDString(this) +// // object mForcastIndictor extends MappedString(this,123) +// // object mTypeId extends MappedString(this,123) +// // object mNatureId extends UUIDString(this) +// // +// // +// // object mCharge_Currency extends MappedString(this,3) +// // object mCharge_Amount extends MappedString(this,32) +// // +// // object mUpdateDate extends MappedDateTime(this) +// // +// // +// // //override def bankId: String = mBankId.get +// // override def customerId: String = mCustomerId.get // id.toString +// // override def customerNumber: String = mCustomerNumber.get +// // override def year: Integer = mYear.get +// // +// // override def categoryId: String = mCategoryId.get +// // override def forcastIndictor: String = mForcastIndictor.get +// // override def typeId: String = mTypeId.get +// // override def natureId : String = mNatureId.get +// // +// // override def charge: AmountOfMoney = AmountOfMoney(mCharge_Currency.get, mCharge_Amount.get) +// // override def updateDate : Date = mUpdateDate.get +// +// +// +// +//} +// +// +//object MappedYearlyCharge extends MappedYearlyCharge with LongKeyedMetaMapper[MappedYearlyCharge] { +// override def dbIndexes = UniqueIndex(bankId_, customerId_, year_) :: Index(bankId_) :: super.dbIndexes +//} +// diff --git a/obp-api/src/main/scala/code/yearlycustomercharges/YearlyCharge.scala b/obp-api/src/main/scala/code/yearlycustomercharges/YearlyCharge.scala index 986b81e42..92d55fe54 100644 --- a/obp-api/src/main/scala/code/yearlycustomercharges/YearlyCharge.scala +++ b/obp-api/src/main/scala/code/yearlycustomercharges/YearlyCharge.scala @@ -1,71 +1,71 @@ -package code.yearlycustomercharges - -import code.api.util.APIUtil -import com.openbankproject.commons.model.{BankId, CustomerId} -import net.liftweb.common.Logger -import net.liftweb.util.SimpleInjector - -object YearlyCharge extends SimpleInjector { - - val yearlyChargeProvider = new Inject(buildOne _) {} - - - // This determines the provider we use - def buildOne: YearlyChargeProvider = - APIUtil.getPropsValue("provider.thing").openOr("mapped") match { - case "mapped" => MappedYearlyChargeProvider - case _ => MappedYearlyChargeProvider - } - -} - -case class YearlyChargeId(value : String) - -// WIP -trait YearlyCharge { - def year : Int - - // def customerNumber : String - // - // - // def categoryId : String - // def forcastIndictor : String - // def typeId : String - // def natureId : String - // def charge : AmountOfMoney - // def updateDate : Date - - - -} - - - - -trait YearlyChargeProvider { - - private val logger = Logger(classOf[YearlyChargeProvider]) - - - /* - Common logic for returning or changing Things - Datasource implementation details are in Thing provider - */ - final def getYearlyCharges(bankId : BankId, customerId: CustomerId, year: Int) : Option[List[YearlyCharge]] = { - getYearlyChargesFromProvider(bankId, customerId, year) match { - case Some(things) => { - - val certainThings = for { - thing <- things // if filter etc. if need be - } yield thing - Option(certainThings) - } - case None => None - } - } - - - protected def getYearlyChargesFromProvider(bank : BankId, customerId: CustomerId, year: Int) : Option[List[YearlyCharge]] - -} - +//package code.yearlycustomercharges +// +//import code.api.util.APIUtil +//import com.openbankproject.commons.model.{BankId, CustomerId} +//import net.liftweb.common.Logger +//import net.liftweb.util.SimpleInjector +// +//object YearlyCharge extends SimpleInjector { +// +// val yearlyChargeProvider = new Inject(buildOne _) {} +// +// +// // This determines the provider we use +// def buildOne: YearlyChargeProvider = +// APIUtil.getPropsValue("provider.thing").openOr("mapped") match { +// case "mapped" => MappedYearlyChargeProvider +// case _ => MappedYearlyChargeProvider +// } +// +//} +// +//case class YearlyChargeId(value : String) +// +//// WIP +//trait YearlyCharge { +// def year : Int +// +// // def customerNumber : String +// // +// // +// // def categoryId : String +// // def forcastIndictor : String +// // def typeId : String +// // def natureId : String +// // def charge : AmountOfMoney +// // def updateDate : Date +// +// +// +//} +// +// +// +// +//trait YearlyChargeProvider { +// +// private val logger = Logger(classOf[YearlyChargeProvider]) +// +// +// /* +// Common logic for returning or changing Things +// Datasource implementation details are in Thing provider +// */ +// final def getYearlyCharges(bankId : BankId, customerId: CustomerId, year: Int) : Option[List[YearlyCharge]] = { +// getYearlyChargesFromProvider(bankId, customerId, year) match { +// case Some(things) => { +// +// val certainThings = for { +// thing <- things // if filter etc. if need be +// } yield thing +// Option(certainThings) +// } +// case None => None +// } +// } +// +// +// protected def getYearlyChargesFromProvider(bank : BankId, customerId: CustomerId, year: Int) : Option[List[YearlyCharge]] +// +//} +// From 70b684275dc61d05bb34d72f4920855602ec8834 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:07:33 +0100 Subject: [PATCH 271/293] refactor/Unexpected duplicate "height" --- obp-api/src/main/webapp/media/css/recover-password.css | 1 - obp-api/src/main/webapp/media/css/signup.css | 1 - 2 files changed, 2 deletions(-) diff --git a/obp-api/src/main/webapp/media/css/recover-password.css b/obp-api/src/main/webapp/media/css/recover-password.css index 1c37005d7..d3ba071c8 100644 --- a/obp-api/src/main/webapp/media/css/recover-password.css +++ b/obp-api/src/main/webapp/media/css/recover-password.css @@ -50,7 +50,6 @@ margin-top: 20px; display: block; width: 100%; - height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; diff --git a/obp-api/src/main/webapp/media/css/signup.css b/obp-api/src/main/webapp/media/css/signup.css index 91d6e5bdb..9ecba169b 100644 --- a/obp-api/src/main/webapp/media/css/signup.css +++ b/obp-api/src/main/webapp/media/css/signup.css @@ -149,7 +149,6 @@ } #signup #signup-submit input { - color: #FFF; background-color: #53C4EF; font-family: Roboto-Regular,sans-serif; font-size: 16px; From b2a898078971dfcd4cb0b0ee804a6f983b9ffecf Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:09:31 +0100 Subject: [PATCH 272/293] bugfix/Unexpected missing generic font family --- obp-api/src/main/webapp/media/css/website.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/webapp/media/css/website.css b/obp-api/src/main/webapp/media/css/website.css index 989894a8a..7ab7b0fcc 100644 --- a/obp-api/src/main/webapp/media/css/website.css +++ b/obp-api/src/main/webapp/media/css/website.css @@ -19,7 +19,7 @@ @import url(/media/css/fonts.css); html { - font-family: "Roboto-Regular"; + font-family: Roboto-Regular,sans-serif; height: 100% } From 76af23c2cb72ff9f7d2dbe3fc2429fe7ab73186a Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:12:58 +0100 Subject: [PATCH 273/293] refactor/fixed the bugs for sonarcloud --- obp-api/src/main/webapp/media/css/website.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/obp-api/src/main/webapp/media/css/website.css b/obp-api/src/main/webapp/media/css/website.css index 7ab7b0fcc..8eace0157 100644 --- a/obp-api/src/main/webapp/media/css/website.css +++ b/obp-api/src/main/webapp/media/css/website.css @@ -165,7 +165,6 @@ header #lift__noticesContainer__ { padding-left: 20px; padding-right: 20px; font-family: Roboto-Regular,sans-serif; - font-size: 16px; color: #333333; text-align: center; line-height: 24px; @@ -275,7 +274,7 @@ input[type="text"]{ } body { - font-family: "Roboto-Light"; + font-family: Roboto-Light,sans-serif; } header #header-decoration, @@ -300,7 +299,6 @@ header #header-decoration, min-width: 43%; padding: 6%; padding-top: 6%; - padding-right: 6%; padding-bottom: 6%; padding-left: 6%; padding-right: 10%; @@ -426,7 +424,6 @@ input{ #add-user-auth-context-update-request-div #identifier-error .error, #confirm-user-auth-context-update-request-div #otp-value-error .error{ - color: black; background-color: white; font-family: Roboto-Regular,sans-serif; font-size: 16px; From a59214296eb1c77410e54c6ac74e25d35c0ca56a Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:26:12 +0100 Subject: [PATCH 274/293] bugfix/fixed the bugs of sonarcloud --- obp-api/src/main/webapp/consumer-registration.html | 2 +- obp-api/src/main/webapp/templates-hidden/default.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/webapp/consumer-registration.html b/obp-api/src/main/webapp/consumer-registration.html index 0bdd9878a..d9e61aea1 100644 --- a/obp-api/src/main/webapp/consumer-registration.html +++ b/obp-api/src/main/webapp/consumer-registration.html @@ -137,7 +137,7 @@ Berlin 13359, Germany
    - Content of jwks_uri. jwks_uri and jwks should not both have value at the same time. + Content of jwks_uri. jwks_uri and jwks should not both have value at the same time. Reference 10.1.1. Rotation of Asymmetric Signing Keys
    diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index bc4df9ae9..0865cdbe1 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -70,7 +70,7 @@ Berlin 13359, Germany
    - +
    From ede56cbb3a66ca755fdafad56e424c092f4d3d81 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 14:55:18 +0100 Subject: [PATCH 275/293] bugfix/fixed the major bug of sonarcloud --- obp-api/src/main/webapp/plain.html | 2 ++ obp-api/src/main/webapp/templates-hidden/default.html | 4 +++- obp-api/src/test/scala/RunMTLSWebApp.scala | 2 +- obp-api/src/test/scala/RunWebApp.scala | 2 +- .../scala/com/openbankproject/commons/util/ReflectUtils.scala | 4 ++-- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/webapp/plain.html b/obp-api/src/main/webapp/plain.html index 657cec28b..9394bb840 100644 --- a/obp-api/src/main/webapp/plain.html +++ b/obp-api/src/main/webapp/plain.html @@ -1,3 +1,5 @@ + + Example HTML diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 0865cdbe1..cf34d6536 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -72,7 +72,9 @@ Berlin 13359, Germany
    - + +
    +
    left logo image diff --git a/obp-api/src/test/scala/RunMTLSWebApp.scala b/obp-api/src/test/scala/RunMTLSWebApp.scala index 93a50ed58..edc181489 100644 --- a/obp-api/src/test/scala/RunMTLSWebApp.scala +++ b/obp-api/src/test/scala/RunMTLSWebApp.scala @@ -58,7 +58,7 @@ object RunMTLSWebApp extends App with PropsProgrammatically { servletContextPath } else { throw new IllegalAccessException(s"Should not call this object method except 'path' method, current call method name is: ${method.getName}") - ??? // should not call other method. +// ??? // should not call other method. } }).asInstanceOf[HTTPContext] LiftRules.setContext(tempHTTPContext) diff --git a/obp-api/src/test/scala/RunWebApp.scala b/obp-api/src/test/scala/RunWebApp.scala index 791c1ceb3..7f2484a77 100644 --- a/obp-api/src/test/scala/RunWebApp.scala +++ b/obp-api/src/test/scala/RunWebApp.scala @@ -51,7 +51,7 @@ object RunWebApp extends App { servletContextPath } else { throw new IllegalAccessException(s"Should not call this object method except 'path' method, current call method name is: ${method.getName}") - ??? // should not call other method. +// ??? // should not call other method. } }).asInstanceOf[HTTPContext] LiftRules.setContext(tempHTTPContext) diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala b/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala index bda7df656..dc32cad3f 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/util/ReflectUtils.scala @@ -45,7 +45,7 @@ object ReflectUtils { def isFieldOrCallByPath(term: ru.TermSymbol) = { term.name.decodedName.toString.trim == fieldName && - (term.isVal || term.isVal || term.isLazy || (term.isMethod && term.asMethod.paramLists.isEmpty)) + (term.isVal || term.isLazy || (term.isMethod && term.asMethod.paramLists.isEmpty)) } val fields: Iterable[ru.TermSymbol] = tp.members.collect({ @@ -495,7 +495,7 @@ object ReflectUtils { def findMethod(obj: Any, methodName: String)(predicate: Map[String, ru.Type] => Boolean): Option[MethodSymbol] = findMethod(getType(obj), methodName)(predicate) def findMethodByArgs(tp: ru.Type, methodName: String, args: Any*): Option[ru.MethodSymbol] = findMethod(tp, methodName) { nameToType => - args.size == args.size && nameToType.values.zip(args).forall(it => isTypeOf(it._1, it._2)) + nameToType.values.zip(args).forall(it => isTypeOf(it._1, it._2)) } def findMethodByArgs(obj: Any, methodName: String, args: Any*): Option[ru.MethodSymbol] = findMethodByArgs(getType(obj), methodName, args:_*) From cf0aef73a5e7d5b4c2c97890e5233a6f0def8a9e Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 15:08:24 +0100 Subject: [PATCH 276/293] bugfix/Add "lang" and/or "xml:lang" attributes to this "" element --- obp-api/src/main/webapp/plain.html | 1 - .../openbankproject/commons/util/RequiredFieldValidation.scala | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/obp-api/src/main/webapp/plain.html b/obp-api/src/main/webapp/plain.html index 9394bb840..8f1567748 100644 --- a/obp-api/src/main/webapp/plain.html +++ b/obp-api/src/main/webapp/plain.html @@ -1,6 +1,5 @@ - Example HTML

    I am some Example HTML

    diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala b/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala index 5d20bae5b..f531c9aaa 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/util/RequiredFieldValidation.scala @@ -300,7 +300,7 @@ object RequiredFieldValidation { def getAnnotations(tp: Type): Iterable[RequiredArgs] = { def isField(symbol: TermSymbol): Boolean = - symbol.isVal || symbol.isVal || symbol.isLazy || (symbol.isMethod && symbol.asMethod.paramLists.isEmpty) + symbol.isVal || symbol.isLazy || (symbol.isMethod && symbol.asMethod.paramLists.isEmpty) // constructor's parameters and fields val members: Iterable[Symbol] = From 1763e0d11502f7c0704b09135932e23232aba558 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 15:36:28 +0100 Subject: [PATCH 277/293] feature/use select2.min.js instead of select2.js --- obp-api/src/main/webapp/media/js/select2.js | 6153 ----------------- .../src/main/webapp/media/js/select2.min.js | 1 + .../main/webapp/templates-hidden/default.html | 2 +- 3 files changed, 2 insertions(+), 6154 deletions(-) delete mode 100644 obp-api/src/main/webapp/media/js/select2.js create mode 100644 obp-api/src/main/webapp/media/js/select2.min.js diff --git a/obp-api/src/main/webapp/media/js/select2.js b/obp-api/src/main/webapp/media/js/select2.js deleted file mode 100644 index 7e1eabc58..000000000 --- a/obp-api/src/main/webapp/media/js/select2.js +++ /dev/null @@ -1,6153 +0,0 @@ -/*! - * Select2 4.1.0-beta.1 - * https://select2.github.io - * - * Released under the MIT license - * https://github.com/select2/select2/blob/master/LICENSE.md - */ -;(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['jquery'], factory); - } else if (typeof module === 'object' && module.exports) { - // Node/CommonJS - module.exports = function (root, jQuery) { - if (jQuery === undefined) { - // require('jQuery') returns a factory that requires window to - // build a jQuery instance, we normalize how we use modules - // that require this pattern but the window provided is a noop - // if it's defined (how jquery works) - if (typeof window !== 'undefined') { - jQuery = require('jquery'); - } - else { - jQuery = require('jquery')(root); - } - } - factory(jQuery); - return jQuery; - }; - } else { - // Browser globals - factory(jQuery); - } -} (function (jQuery) { - // This is needed so we can catch the AMD loader configuration and use it - // The inner file should be wrapped (by `banner.start.js`) in a function that - // returns the AMD loader references. - var S2 =(function () { - // Restore the Select2 AMD loader so it can be used - // Needed mostly in the language files, where the loader is not inserted - if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) { - var S2 = jQuery.fn.select2.amd; - } - var S2;(function () { if (!S2 || !S2.requirejs) { - if (!S2) { S2 = {}; } else { require = S2; } - /** - * @license almond 0.3.3 Copyright jQuery Foundation and other contributors. - * Released under MIT license, http://github.com/requirejs/almond/LICENSE - */ -//Going sloppy to avoid 'use strict' string cost, but strict practices should -//be followed. - /*global setTimeout: false */ - - var requirejs, require, define; - (function (undef) { - var main, req, makeMap, handlers, - defined = {}, - waiting = {}, - config = {}, - defining = {}, - hasOwn = Object.prototype.hasOwnProperty, - aps = [].slice, - jsSuffixRegExp = /\.js$/; - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop); - } - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @returns {String} normalized name - */ - function normalize(name, baseName) { - var nameParts, nameSegment, mapValue, foundMap, lastIndex, - foundI, foundStarMap, starI, i, j, part, normalizedBaseParts, - baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = (map && map['*']) || {}; - - //Adjust any relative paths. - if (name) { - name = name.split('/'); - lastIndex = name.length - 1; - - // If wanting node ID compatibility, strip .js from end - // of IDs. Have to do this here, and not in nameToUrl - // because node allows either .js or non .js to map - // to same file. - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - - // Starts with a '.' so need the baseName - if (name[0].charAt(0) === '.' && baseParts) { - //Convert baseName to array, and lop off the last part, - //so that . matches that 'directory' and not name of the baseName's - //module. For instance, baseName of 'one/two/three', maps to - //'one/two/three.js', but we want the directory, 'one/two' for - //this normalization. - normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); - name = normalizedBaseParts.concat(name); - } - - //start trimDots - for (i = 0; i < name.length; i++) { - part = name[i]; - if (part === '.') { - name.splice(i, 1); - i -= 1; - } else if (part === '..') { - // If at the start, or previous value is still .., - // keep them so that when converted to a path it may - // still work when converted to a path, even though - // as an ID it is less than ideal. In larger point - // releases, may be better to just kick out an error. - if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') { - - } else if (i > 0) { - name.splice(i - 1, 2); - i -= 2; - } - } - } - //end trimDots - - name = name.join('/'); - } - - //Apply map config if available. - if ((baseParts || starMap) && map) { - nameParts = name.split('/'); - - for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join("/"); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = map[baseParts.slice(0, j).join('/')]; - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = mapValue[nameSegment]; - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break; - } - } - } - } - - if (foundMap) { - break; - } - - //Check for a star map match, but just hold on to it, - //if there is a shorter segment match later in a matching - //config, then favor over this star map. - if (!foundStarMap && starMap && starMap[nameSegment]) { - foundStarMap = starMap[nameSegment]; - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } - } - - return name; - } - - function makeRequire(relName, forceSync) { - return function () { - //A version of a require function that passes a moduleName - //value for items that may need to - //look up paths relative to the moduleName - var args = aps.call(arguments, 0); - - //If first arg is not require('string'), and there is only - //one arg, it is the array form without a callback. Insert - //a null so that the following concat is correct. - if (typeof args[0] !== 'string' && args.length === 1) { - args.push(null); - } - return req.apply(undef, args.concat([relName, forceSync])); - }; - } - - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName); - }; - } - - function makeLoad(depName) { - return function (value) { - defined[depName] = value; - }; - } - - function callDep(name) { - if (hasProp(waiting, name)) { - var args = waiting[name]; - delete waiting[name]; - defining[name] = true; - main.apply(undef, args); - } - - if (!hasProp(defined, name) && !hasProp(defining, name)) { - throw new Error('No ' + name); - } - return defined[name]; - } - - //Turns a plugin!resource to [plugin, resource] - //with the plugin being undefined if the name - //did not have a plugin prefix. - function splitPrefix(name) { - var prefix, - index = name ? name.indexOf('!') : -1; - if (index > -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); - } - return [prefix, name]; - } - - //Creates a parts array for a relName where first part is plugin ID, - //second part is resource ID. Assumes relName has already been normalized. - function makeRelParts(relName) { - return relName ? splitPrefix(relName) : []; - } - - /** - * Makes a name map, normalizing the name, and using a plugin - * for normalization if necessary. Grabs a ref to plugin - * too, as an optimization. - */ - makeMap = function (name, relParts) { - var plugin, - parts = splitPrefix(name), - prefix = parts[0], - relResourceName = relParts[1]; - - name = parts[1]; - - if (prefix) { - prefix = normalize(prefix, relResourceName); - plugin = callDep(prefix); - } - - //Normalize according - if (prefix) { - if (plugin && plugin.normalize) { - name = plugin.normalize(name, makeNormalize(relResourceName)); - } else { - name = normalize(name, relResourceName); - } - } else { - name = normalize(name, relResourceName); - parts = splitPrefix(name); - prefix = parts[0]; - name = parts[1]; - if (prefix) { - plugin = callDep(prefix); - } - } - - //Using ridiculous property names for space reasons - return { - f: prefix ? prefix + '!' + name : name, //fullName - n: name, - pr: prefix, - p: plugin - }; - }; - - function makeConfig(name) { - return function () { - return (config && config.config && config.config[name]) || {}; - }; - } - - handlers = { - require: function (name) { - return makeRequire(name); - }, - exports: function (name) { - var e = defined[name]; - if (typeof e !== 'undefined') { - return e; - } else { - return (defined[name] = {}); - } - }, - module: function (name) { - return { - id: name, - uri: '', - exports: defined[name], - config: makeConfig(name) - }; - } - }; - - main = function (name, deps, callback, relName) { - var cjsModule, depName, ret, map, i, relParts, - args = [], - callbackType = typeof callback, - usingExports; - - //Use name if no relName - relName = relName || name; - relParts = makeRelParts(relName); - - //Call the callback to define the module, if necessary. - if (callbackType === 'undefined' || callbackType === 'function') { - //Pull out the defined dependencies and pass the ordered - //values to the callback. - //Default to [require, exports, module] if no deps - deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; - for (i = 0; i < deps.length; i += 1) { - map = makeMap(deps[i], relParts); - depName = map.f; - - //Fast path CommonJS standard dependencies. - if (depName === "require") { - args[i] = handlers.require(name); - } else if (depName === "exports") { - //CommonJS module spec 1.1 - args[i] = handlers.exports(name); - usingExports = true; - } else if (depName === "module") { - //CommonJS module spec 1.1 - cjsModule = args[i] = handlers.module(name); - } else if (hasProp(defined, depName) || - hasProp(waiting, depName) || - hasProp(defining, depName)) { - args[i] = callDep(depName); - } else if (map.p) { - map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); - args[i] = defined[depName]; - } else { - throw new Error(name + ' missing ' + depName); - } - } - - ret = callback ? callback.apply(defined[name], args) : undefined; - - if (name) { - //If setting exports via "module" is in play, - //favor that over return value and exports. After that, - //favor a non-undefined return value over exports use. - if (cjsModule && cjsModule.exports !== undef && - cjsModule.exports !== defined[name]) { - defined[name] = cjsModule.exports; - } else if (ret !== undef || !usingExports) { - //Use the return value from the function. - defined[name] = ret; - } - } - } else if (name) { - //May just be an object definition for the module. Only - //worry about defining if have a module name. - defined[name] = callback; - } - }; - - requirejs = require = req = function (deps, callback, relName, forceSync, alt) { - if (typeof deps === "string") { - if (handlers[deps]) { - //callback in this case is really relName - return handlers[deps](callback); - } - //Just return the module wanted. In this scenario, the - //deps arg is the module name, and second arg (if passed) - //is just the relName. - //Normalize module name, if it contains . or .. - return callDep(makeMap(deps, makeRelParts(callback)).f); - } else if (!deps.splice) { - //deps is a config object, not an array. - config = deps; - if (config.deps) { - req(config.deps, config.callback); - } - if (!callback) { - return; - } - - if (callback.splice) { - //callback is an array, which means it is a dependency list. - //Adjust args if there are dependencies - deps = callback; - callback = relName; - relName = null; - } else { - deps = undef; - } - } - - //Support require(['a']) - callback = callback || function () {}; - - //If relName is a function, it is an errback handler, - //so remove it. - if (typeof relName === 'function') { - relName = forceSync; - forceSync = alt; - } - - //Simulate async callback; - if (forceSync) { - main(undef, deps, callback, relName); - } else { - //Using a non-zero value because of concern for what old browsers - //do, and latest browsers "upgrade" to 4 if lower value is used: - //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: - //If want a value immediately, use require('id') instead -- something - //that works in almond on the global level, but not guaranteed and - //unlikely to work in other AMD implementations. - setTimeout(function () { - main(undef, deps, callback, relName); - }, 4); - } - - return req; - }; - - /** - * Just drops the config on the floor, but returns req in case - * the config return value is used. - */ - req.config = function (cfg) { - return req(cfg); - }; - - /** - * Expose module registry for debugging and tooling - */ - requirejs._defined = defined; - - define = function (name, deps, callback) { - if (typeof name !== 'string') { - throw new Error('See almond README: incorrect module build, no module name'); - } - - //This module may not have dependencies - if (!deps.splice) { - //deps is not an array, so probably means - //an object literal or factory function for - //the value. Adjust args. - callback = deps; - deps = []; - } - - if (!hasProp(defined, name) && !hasProp(waiting, name)) { - waiting[name] = [name, deps, callback]; - } - }; - - define.amd = { - jQuery: true - }; - }()); - - S2.requirejs = requirejs;S2.require = require;S2.define = define; - } - }()); - S2.define("almond", function(){}); - - /* global jQuery:false, $:false */ - S2.define('jquery',[],function () { - var _$ = jQuery || $; - - if (_$ == null && console && console.error) { - console.error( - 'Select2: An instance of jQuery or a jQuery-compatible library was not ' + - 'found. Make sure that you are including jQuery before Select2 on your ' + - 'web page.' - ); - } - - return _$; - }); - - S2.define('select2/utils',[ - 'jquery' - ], function ($) { - var Utils = {}; - - Utils.Extend = function (ChildClass, SuperClass) { - var __hasProp = {}.hasOwnProperty; - - function BaseConstructor () { - this.constructor = ChildClass; - } - - for (var key in SuperClass) { - if (__hasProp.call(SuperClass, key)) { - ChildClass[key] = SuperClass[key]; - } - } - - BaseConstructor.prototype = SuperClass.prototype; - ChildClass.prototype = new BaseConstructor(); - ChildClass.__super__ = SuperClass.prototype; - - return ChildClass; - }; - - function getMethods (theClass) { - var proto = theClass.prototype; - - var methods = []; - - for (var methodName in proto) { - var m = proto[methodName]; - - if (typeof m !== 'function') { - continue; - } - - if (methodName === 'constructor') { - continue; - } - - methods.push(methodName); - } - - return methods; - } - - Utils.Decorate = function (SuperClass, DecoratorClass) { - var decoratedMethods = getMethods(DecoratorClass); - var superMethods = getMethods(SuperClass); - - function DecoratedClass () { - var unshift = Array.prototype.unshift; - - var argCount = DecoratorClass.prototype.constructor.length; - - var calledConstructor = SuperClass.prototype.constructor; - - if (argCount > 0) { - unshift.call(arguments, SuperClass.prototype.constructor); - - calledConstructor = DecoratorClass.prototype.constructor; - } - - calledConstructor.apply(this, arguments); - } - - DecoratorClass.displayName = SuperClass.displayName; - - function ctr () { - this.constructor = DecoratedClass; - } - - DecoratedClass.prototype = new ctr(); - - for (var m = 0; m < superMethods.length; m++) { - var superMethod = superMethods[m]; - - DecoratedClass.prototype[superMethod] = - SuperClass.prototype[superMethod]; - } - - var calledMethod = function (methodName) { - // Stub out the original method if it's not decorating an actual method - var originalMethod = function () {}; - - if (methodName in DecoratedClass.prototype) { - originalMethod = DecoratedClass.prototype[methodName]; - } - - var decoratedMethod = DecoratorClass.prototype[methodName]; - - return function () { - var unshift = Array.prototype.unshift; - - unshift.call(arguments, originalMethod); - - return decoratedMethod.apply(this, arguments); - }; - }; - - for (var d = 0; d < decoratedMethods.length; d++) { - var decoratedMethod = decoratedMethods[d]; - - DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod); - } - - return DecoratedClass; - }; - - var Observable = function () { - this.listeners = {}; - }; - - Observable.prototype.on = function (event, callback) { - this.listeners = this.listeners || {}; - - if (event in this.listeners) { - this.listeners[event].push(callback); - } else { - this.listeners[event] = [callback]; - } - }; - - Observable.prototype.trigger = function (event) { - var slice = Array.prototype.slice; - var params = slice.call(arguments, 1); - - this.listeners = this.listeners || {}; - - // Params should always come in as an array - if (params == null) { - params = []; - } - - // If there are no arguments to the event, use a temporary object - if (params.length === 0) { - params.push({}); - } - - // Set the `_type` of the first object to the event - params[0]._type = event; - - if (event in this.listeners) { - this.invoke(this.listeners[event], slice.call(arguments, 1)); - } - - if ('*' in this.listeners) { - this.invoke(this.listeners['*'], arguments); - } - }; - - Observable.prototype.invoke = function (listeners, params) { - for (var i = 0, len = listeners.length; i < len; i++) { - listeners[i].apply(this, params); - } - }; - - Utils.Observable = Observable; - - Utils.generateChars = function (length) { - var chars = ''; - - for (var i = 0; i < length; i++) { - var randomChar = Math.floor(Math.random() * 36); - chars += randomChar.toString(36); - } - - return chars; - }; - - Utils.bind = function (func, context) { - return function () { - func.apply(context, arguments); - }; - }; - - Utils._convertData = function (data) { - for (var originalKey in data) { - var keys = originalKey.split('-'); - - var dataLevel = data; - - if (keys.length === 1) { - continue; - } - - for (var k = 0; k < keys.length; k++) { - var key = keys[k]; - - // Lowercase the first letter - // By default, dash-separated becomes camelCase - key = key.substring(0, 1).toLowerCase() + key.substring(1); - - if (!(key in dataLevel)) { - dataLevel[key] = {}; - } - - if (k == keys.length - 1) { - dataLevel[key] = data[originalKey]; - } - - dataLevel = dataLevel[key]; - } - - delete data[originalKey]; - } - - return data; - }; - - Utils.hasScroll = function (index, el) { - // Adapted from the function created by @ShadowScripter - // and adapted by @BillBarry on the Stack Exchange Code Review website. - // The original code can be found at - // http://codereview.stackexchange.com/q/13338 - // and was designed to be used with the Sizzle selector engine. - - var $el = $(el); - var overflowX = el.style.overflowX; - var overflowY = el.style.overflowY; - - //Check both x and y declarations - if (overflowX === overflowY && - (overflowY === 'hidden' || overflowY === 'visible')) { - return false; - } - - if (overflowX === 'scroll' || overflowY === 'scroll') { - return true; - } - - return ($el.innerHeight() < el.scrollHeight || - $el.innerWidth() < el.scrollWidth); - }; - - Utils.escapeMarkup = function (markup) { - var replaceMap = { - '\\': '\', - '&': '&', - '<': '<', - '>': '>', - '"': '"', - '\'': ''', - '/': '/' - }; - - // Do not try to escape the markup if it's not a string - if (typeof markup !== 'string') { - return markup; - } - - return String(markup).replace(/[&<>"'\/\\]/g, function (match) { - return replaceMap[match]; - }); - }; - - // Cache objects in Utils.__cache instead of $.data (see #4346) - Utils.__cache = {}; - - var id = 0; - Utils.GetUniqueElementId = function (element) { - // Get a unique element Id. If element has no id, - // creates a new unique number, stores it in the id - // attribute and returns the new id with a prefix. - // If an id already exists, it simply returns it with a prefix. - - var select2Id = element.getAttribute('data-select2-id'); - - if (select2Id != null) { - return select2Id; - } - - // If element has id, use it. - if (element.id) { - select2Id = 'select2-data-' + element.id; - } else { - select2Id = 'select2-data-' + (++id).toString() + - '-' + Utils.generateChars(4); - } - - element.setAttribute('data-select2-id', select2Id); - - return select2Id; - }; - - Utils.StoreData = function (element, name, value) { - // Stores an item in the cache for a specified element. - // name is the cache key. - var id = Utils.GetUniqueElementId(element); - if (!Utils.__cache[id]) { - Utils.__cache[id] = {}; - } - - Utils.__cache[id][name] = value; - }; - - Utils.GetData = function (element, name) { - // Retrieves a value from the cache by its key (name) - // name is optional. If no name specified, return - // all cache items for the specified element. - // and for a specified element. - var id = Utils.GetUniqueElementId(element); - if (name) { - if (Utils.__cache[id]) { - if (Utils.__cache[id][name] != null) { - return Utils.__cache[id][name]; - } - return $(element).data(name); // Fallback to HTML5 data attribs. - } - return $(element).data(name); // Fallback to HTML5 data attribs. - } else { - return Utils.__cache[id]; - } - }; - - Utils.RemoveData = function (element) { - // Removes all cached items for a specified element. - var id = Utils.GetUniqueElementId(element); - if (Utils.__cache[id] != null) { - delete Utils.__cache[id]; - } - - element.removeAttribute('data-select2-id'); - }; - - Utils.copyNonInternalCssClasses = function (dest, src) { - var classes; - - var destinationClasses = dest.getAttribute('class').trim().split(/\s+/); - - destinationClasses = destinationClasses.filter(function (clazz) { - // Save all Select2 classes - return clazz.indexOf('select2-') === 0; - }); - - var sourceClasses = src.getAttribute('class').trim().split(/\s+/); - - sourceClasses = sourceClasses.filter(function (clazz) { - // Only copy non-Select2 classes - return clazz.indexOf('select2-') !== 0; - }); - - var replacements = destinationClasses.concat(sourceClasses); - - dest.setAttribute('class', replacements.join(' ')); - }; - - return Utils; - }); - - S2.define('select2/results',[ - 'jquery', - './utils' - ], function ($, Utils) { - function Results ($element, options, dataAdapter) { - this.$element = $element; - this.data = dataAdapter; - this.options = options; - - Results.__super__.constructor.call(this); - } - - Utils.Extend(Results, Utils.Observable); - - Results.prototype.render = function () { - var $results = $( - '
      ' - ); - - if (this.options.get('multiple')) { - $results.attr('aria-multiselectable', 'true'); - } - - this.$results = $results; - - return $results; - }; - - Results.prototype.clear = function () { - this.$results.empty(); - }; - - Results.prototype.displayMessage = function (params) { - var escapeMarkup = this.options.get('escapeMarkup'); - - this.clear(); - this.hideLoading(); - - var $message = $( - '' - ); - - var message = this.options.get('translations').get(params.message); - - $message.append( - escapeMarkup( - message(params.args) - ) - ); - - $message[0].className += ' select2-results__message'; - - this.$results.append($message); - }; - - Results.prototype.hideMessages = function () { - this.$results.find('.select2-results__message').remove(); - }; - - Results.prototype.append = function (data) { - this.hideLoading(); - - var $options = []; - - if (data.results == null || data.results.length === 0) { - if (this.$results.children().length === 0) { - this.trigger('results:message', { - message: 'noResults' - }); - } - - return; - } - - data.results = this.sort(data.results); - - for (var d = 0; d < data.results.length; d++) { - var item = data.results[d]; - - var $option = this.option(item); - - $options.push($option); - } - - this.$results.append($options); - }; - - Results.prototype.position = function ($results, $dropdown) { - var $resultsContainer = $dropdown.find('.select2-results'); - $resultsContainer.append($results); - }; - - Results.prototype.sort = function (data) { - var sorter = this.options.get('sorter'); - - return sorter(data); - }; - - Results.prototype.highlightFirstItem = function () { - var $options = this.$results - .find('.select2-results__option--selectable'); - - var $selected = $options.filter('.select2-results__option--selected'); - - // Check if there are any selected options - if ($selected.length > 0) { - // If there are selected options, highlight the first - $selected.first().trigger('mouseenter'); - } else { - // If there are no selected options, highlight the first option - // in the dropdown - $options.first().trigger('mouseenter'); - } - - this.ensureHighlightVisible(); - }; - - Results.prototype.setClasses = function () { - var self = this; - - this.data.current(function (selected) { - var selectedIds = selected.map(function (s) { - return s.id.toString(); - }); - - var $options = self.$results - .find('.select2-results__option--selectable'); - - $options.each(function () { - var $option = $(this); - - var item = Utils.GetData(this, 'data'); - - // id needs to be converted to a string when comparing - var id = '' + item.id; - - if ((item.element != null && item.element.selected) || - (item.element == null && selectedIds.indexOf(id) > -1)) { - this.classList.add('select2-results__option--selected'); - $option.attr('aria-selected', 'true'); - } else { - this.classList.remove('select2-results__option--selected'); - $option.attr('aria-selected', 'false'); - } - }); - - }); - }; - - Results.prototype.showLoading = function (params) { - this.hideLoading(); - - var loadingMore = this.options.get('translations').get('searching'); - - var loading = { - disabled: true, - loading: true, - text: loadingMore(params) - }; - var $loading = this.option(loading); - $loading.className += ' loading-results'; - - this.$results.prepend($loading); - }; - - Results.prototype.hideLoading = function () { - this.$results.find('.loading-results').remove(); - }; - - Results.prototype.option = function (data) { - var option = document.createElement('li'); - option.classList.add('select2-results__option'); - option.classList.add('select2-results__option--selectable'); - - var attrs = { - 'role': 'option' - }; - - var matches = window.Element.prototype.matches || - window.Element.prototype.msMatchesSelector || - window.Element.prototype.webkitMatchesSelector; - - if ((data.element != null && matches.call(data.element, ':disabled')) || - (data.element == null && data.disabled)) { - attrs['aria-disabled'] = 'true'; - - option.classList.remove('select2-results__option--selectable'); - option.classList.add('select2-results__option--disabled'); - } - - if (data.id == null) { - option.classList.remove('select2-results__option--selectable'); - } - - if (data._resultId != null) { - option.id = data._resultId; - } - - if (data.title) { - option.title = data.title; - } - - if (data.children) { - attrs.role = 'group'; - attrs['aria-label'] = data.text; - - option.classList.remove('select2-results__option--selectable'); - option.classList.add('select2-results__option--group'); - } - - for (var attr in attrs) { - var val = attrs[attr]; - - option.setAttribute(attr, val); - } - - if (data.children) { - var $option = $(option); - - var label = document.createElement('strong'); - label.className = 'select2-results__group'; - - this.template(data, label); - - var $children = []; - - for (var c = 0; c < data.children.length; c++) { - var child = data.children[c]; - - var $child = this.option(child); - - $children.push($child); - } - - var $childrenContainer = $('
        ', { - 'class': 'select2-results__options select2-results__options--nested' - }); - - $childrenContainer.append($children); - - $option.append(label); - $option.append($childrenContainer); - } else { - this.template(data, option); - } - - Utils.StoreData(option, 'data', data); - - return option; - }; - - Results.prototype.bind = function (container, $container) { - var self = this; - - var id = container.id + '-results'; - - this.$results.attr('id', id); - - container.on('results:all', function (params) { - self.clear(); - self.append(params.data); - - if (container.isOpen()) { - self.setClasses(); - self.highlightFirstItem(); - } - }); - - container.on('results:append', function (params) { - self.append(params.data); - - if (container.isOpen()) { - self.setClasses(); - } - }); - - container.on('query', function (params) { - self.hideMessages(); - self.showLoading(params); - }); - - container.on('select', function () { - if (!container.isOpen()) { - return; - } - - self.setClasses(); - - if (self.options.get('scrollAfterSelect')) { - self.highlightFirstItem(); - } - }); - - container.on('unselect', function () { - if (!container.isOpen()) { - return; - } - - self.setClasses(); - - if (self.options.get('scrollAfterSelect')) { - self.highlightFirstItem(); - } - }); - - container.on('open', function () { - // When the dropdown is open, aria-expended="true" - self.$results.attr('aria-expanded', 'true'); - self.$results.attr('aria-hidden', 'false'); - - self.setClasses(); - self.ensureHighlightVisible(); - }); - - container.on('close', function () { - // When the dropdown is closed, aria-expended="false" - self.$results.attr('aria-expanded', 'false'); - self.$results.attr('aria-hidden', 'true'); - self.$results.removeAttr('aria-activedescendant'); - }); - - container.on('results:toggle', function () { - var $highlighted = self.getHighlightedResults(); - - if ($highlighted.length === 0) { - return; - } - - $highlighted.trigger('mouseup'); - }); - - container.on('results:select', function () { - var $highlighted = self.getHighlightedResults(); - - if ($highlighted.length === 0) { - return; - } - - var data = Utils.GetData($highlighted[0], 'data'); - - if ($highlighted.hasClass('select2-results__option--selected')) { - self.trigger('close', {}); - } else { - self.trigger('select', { - data: data - }); - } - }); - - container.on('results:previous', function () { - var $highlighted = self.getHighlightedResults(); - - var $options = self.$results.find('.select2-results__option--selectable'); - - var currentIndex = $options.index($highlighted); - - // If we are already at the top, don't move further - // If no options, currentIndex will be -1 - if (currentIndex <= 0) { - return; - } - - var nextIndex = currentIndex - 1; - - // If none are highlighted, highlight the first - if ($highlighted.length === 0) { - nextIndex = 0; - } - - var $next = $options.eq(nextIndex); - - $next.trigger('mouseenter'); - - var currentOffset = self.$results.offset().top; - var nextTop = $next.offset().top; - var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset); - - if (nextIndex === 0) { - self.$results.scrollTop(0); - } else if (nextTop - currentOffset < 0) { - self.$results.scrollTop(nextOffset); - } - }); - - container.on('results:next', function () { - var $highlighted = self.getHighlightedResults(); - - var $options = self.$results.find('.select2-results__option--selectable'); - - var currentIndex = $options.index($highlighted); - - var nextIndex = currentIndex + 1; - - // If we are at the last option, stay there - if (nextIndex >= $options.length) { - return; - } - - var $next = $options.eq(nextIndex); - - $next.trigger('mouseenter'); - - var currentOffset = self.$results.offset().top + - self.$results.outerHeight(false); - var nextBottom = $next.offset().top + $next.outerHeight(false); - var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset; - - if (nextIndex === 0) { - self.$results.scrollTop(0); - } else if (nextBottom > currentOffset) { - self.$results.scrollTop(nextOffset); - } - }); - - container.on('results:focus', function (params) { - params.element[0].classList.add('select2-results__option--highlighted'); - params.element[0].setAttribute('aria-selected', 'true'); - }); - - container.on('results:message', function (params) { - self.displayMessage(params); - }); - - if ($.fn.mousewheel) { - this.$results.on('mousewheel', function (e) { - var top = self.$results.scrollTop(); - - var bottom = self.$results.get(0).scrollHeight - top + e.deltaY; - - var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0; - var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height(); - - if (isAtTop) { - self.$results.scrollTop(0); - - e.preventDefault(); - e.stopPropagation(); - } else if (isAtBottom) { - self.$results.scrollTop( - self.$results.get(0).scrollHeight - self.$results.height() - ); - - e.preventDefault(); - e.stopPropagation(); - } - }); - } - - this.$results.on('mouseup', '.select2-results__option--selectable', - function (evt) { - var $this = $(this); - - var data = Utils.GetData(this, 'data'); - - if ($this.hasClass('select2-results__option--selected')) { - if (self.options.get('multiple')) { - self.trigger('unselect', { - originalEvent: evt, - data: data - }); - } else { - self.trigger('close', {}); - } - - return; - } - - self.trigger('select', { - originalEvent: evt, - data: data - }); - }); - - this.$results.on('mouseenter', '.select2-results__option--selectable', - function (evt) { - var data = Utils.GetData(this, 'data'); - - self.getHighlightedResults() - .removeClass('select2-results__option--highlighted') - .attr('aria-selected', 'false'); - - self.trigger('results:focus', { - data: data, - element: $(this) - }); - }); - }; - - Results.prototype.getHighlightedResults = function () { - var $highlighted = this.$results - .find('.select2-results__option--highlighted'); - - return $highlighted; - }; - - Results.prototype.destroy = function () { - this.$results.remove(); - }; - - Results.prototype.ensureHighlightVisible = function () { - var $highlighted = this.getHighlightedResults(); - - if ($highlighted.length === 0) { - return; - } - - var $options = this.$results.find('.select2-results__option--selectable'); - - var currentIndex = $options.index($highlighted); - - var currentOffset = this.$results.offset().top; - var nextTop = $highlighted.offset().top; - var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset); - - var offsetDelta = nextTop - currentOffset; - nextOffset -= $highlighted.outerHeight(false) * 2; - - if (currentIndex <= 2) { - this.$results.scrollTop(0); - } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) { - this.$results.scrollTop(nextOffset); - } - }; - - Results.prototype.template = function (result, container) { - var template = this.options.get('templateResult'); - var escapeMarkup = this.options.get('escapeMarkup'); - - var content = template(result, container); - - if (content == null) { - container.style.display = 'none'; - } else if (typeof content === 'string') { - container.innerHTML = escapeMarkup(content); - } else { - $(container).append(content); - } - }; - - return Results; - }); - - S2.define('select2/keys',[ - - ], function () { - var KEYS = { - BACKSPACE: 8, - TAB: 9, - ENTER: 13, - SHIFT: 16, - CTRL: 17, - ALT: 18, - ESC: 27, - SPACE: 32, - PAGE_UP: 33, - PAGE_DOWN: 34, - END: 35, - HOME: 36, - LEFT: 37, - UP: 38, - RIGHT: 39, - DOWN: 40, - DELETE: 46 - }; - - return KEYS; - }); - - S2.define('select2/selection/base',[ - 'jquery', - '../utils', - '../keys' - ], function ($, Utils, KEYS) { - function BaseSelection ($element, options) { - this.$element = $element; - this.options = options; - - BaseSelection.__super__.constructor.call(this); - } - - Utils.Extend(BaseSelection, Utils.Observable); - - BaseSelection.prototype.render = function () { - var $selection = $( - '' - ); - - this._tabindex = 0; - - if (Utils.GetData(this.$element[0], 'old-tabindex') != null) { - this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex'); - } else if (this.$element.attr('tabindex') != null) { - this._tabindex = this.$element.attr('tabindex'); - } - - $selection.attr('title', this.$element.attr('title')); - $selection.attr('tabindex', this._tabindex); - $selection.attr('aria-disabled', 'false'); - - this.$selection = $selection; - - return $selection; - }; - - BaseSelection.prototype.bind = function (container, $container) { - var self = this; - - var resultsId = container.id + '-results'; - - this.container = container; - - this.$selection.on('focus', function (evt) { - self.trigger('focus', evt); - }); - - this.$selection.on('blur', function (evt) { - self._handleBlur(evt); - }); - - this.$selection.on('keydown', function (evt) { - self.trigger('keypress', evt); - - if (evt.which === KEYS.SPACE) { - evt.preventDefault(); - } - }); - - container.on('results:focus', function (params) { - self.$selection.attr('aria-activedescendant', params.data._resultId); - }); - - container.on('selection:update', function (params) { - self.update(params.data); - }); - - container.on('open', function () { - // When the dropdown is open, aria-expanded="true" - self.$selection.attr('aria-expanded', 'true'); - self.$selection.attr('aria-owns', resultsId); - - self._attachCloseHandler(container); - }); - - container.on('close', function () { - // When the dropdown is closed, aria-expanded="false" - self.$selection.attr('aria-expanded', 'false'); - self.$selection.removeAttr('aria-activedescendant'); - self.$selection.removeAttr('aria-owns'); - - self.$selection.trigger('focus'); - - self._detachCloseHandler(container); - }); - - container.on('enable', function () { - self.$selection.attr('tabindex', self._tabindex); - self.$selection.attr('aria-disabled', 'false'); - }); - - container.on('disable', function () { - self.$selection.attr('tabindex', '-1'); - self.$selection.attr('aria-disabled', 'true'); - }); - }; - - BaseSelection.prototype._handleBlur = function (evt) { - var self = this; - - // This needs to be delayed as the active element is the body when the tab - // key is pressed, possibly along with others. - window.setTimeout(function () { - // Don't trigger `blur` if the focus is still in the selection - if ( - (document.activeElement == self.$selection[0]) || - ($.contains(self.$selection[0], document.activeElement)) - ) { - return; - } - - self.trigger('blur', evt); - }, 1); - }; - - BaseSelection.prototype._attachCloseHandler = function (container) { - - $(document.body).on('mousedown.select2.' + container.id, function (e) { - var $target = $(e.target); - - var $select = $target.closest('.select2'); - - var $all = $('.select2.select2-container--open'); - - $all.each(function () { - if (this == $select[0]) { - return; - } - - var $element = Utils.GetData(this, 'element'); - - $element.select2('close'); - }); - }); - }; - - BaseSelection.prototype._detachCloseHandler = function (container) { - $(document.body).off('mousedown.select2.' + container.id); - }; - - BaseSelection.prototype.position = function ($selection, $container) { - var $selectionContainer = $container.find('.selection'); - $selectionContainer.append($selection); - }; - - BaseSelection.prototype.destroy = function () { - this._detachCloseHandler(this.container); - }; - - BaseSelection.prototype.update = function (data) { - throw new Error('The `update` method must be defined in child classes.'); - }; - - /** - * Helper method to abstract the "enabled" (not "disabled") state of this - * object. - * - * @return {true} if the instance is not disabled. - * @return {false} if the instance is disabled. - */ - BaseSelection.prototype.isEnabled = function () { - return !this.isDisabled(); - }; - - /** - * Helper method to abstract the "disabled" state of this object. - * - * @return {true} if the disabled option is true. - * @return {false} if the disabled option is false. - */ - BaseSelection.prototype.isDisabled = function () { - return this.options.get('disabled'); - }; - - return BaseSelection; - }); - - S2.define('select2/selection/single',[ - 'jquery', - './base', - '../utils', - '../keys' - ], function ($, BaseSelection, Utils, KEYS) { - function SingleSelection () { - SingleSelection.__super__.constructor.apply(this, arguments); - } - - Utils.Extend(SingleSelection, BaseSelection); - - SingleSelection.prototype.render = function () { - var $selection = SingleSelection.__super__.render.call(this); - - $selection.addClass('select2-selection--single'); - - $selection.html( - '' + - '' + - '' + - '' - ); - - return $selection; - }; - - SingleSelection.prototype.bind = function (container, $container) { - var self = this; - - SingleSelection.__super__.bind.apply(this, arguments); - - var id = container.id + '-container'; - var first_click_datetime = new Date(); - - this.$selection.find('.select2-selection__rendered') - .attr('id', id) - .attr('role', 'textbox') - .attr('aria-readonly', 'true'); - this.$selection.attr('aria-labelledby', id); - - this.$selection.on('mousedown', function (evt) { - var second_click_datetime = new Date(); - //We add a time guard to make sure this button can only be clicked once in 200ms - if (second_click_datetime > first_click_datetime){ - // Only respond to left clicks - if (evt.which !== 1) { - return; - } - self.trigger('toggle', { - originalEvent: evt - }); - //set the first click time to 200 ms later. - first_click_datetime=second_click_datetime.setMilliseconds(second_click_datetime.getMilliseconds() + 200); - } - }); - - this.$selection.on('focus', function (evt) { - // User focuses on the container - }); - - this.$selection.on('blur', function (evt) { - // User exits the container - }); - - container.on('focus', function (evt) { - if (!container.isOpen()) { - self.$selection.trigger('focus'); - } - }); - }; - - SingleSelection.prototype.clear = function () { - var $rendered = this.$selection.find('.select2-selection__rendered'); - $rendered.empty(); - $rendered.removeAttr('title'); // clear tooltip on empty - }; - - SingleSelection.prototype.display = function (data, container) { - var template = this.options.get('templateSelection'); - var escapeMarkup = this.options.get('escapeMarkup'); - - return escapeMarkup(template(data, container)); - }; - - SingleSelection.prototype.selectionContainer = function () { - return $(''); - }; - - SingleSelection.prototype.update = function (data) { - if (data.length === 0) { - this.clear(); - return; - } - - var selection = data[0]; - - var $rendered = this.$selection.find('.select2-selection__rendered'); - var formatted = this.display(selection, $rendered); - - $rendered.empty().append(formatted); - - var title = selection.title || selection.text; - - if (title) { - $rendered.attr('title', title); - } else { - $rendered.removeAttr('title'); - } - }; - - return SingleSelection; - }); - - S2.define('select2/selection/multiple',[ - 'jquery', - './base', - '../utils' - ], function ($, BaseSelection, Utils) { - function MultipleSelection ($element, options) { - MultipleSelection.__super__.constructor.apply(this, arguments); - } - - Utils.Extend(MultipleSelection, BaseSelection); - - MultipleSelection.prototype.render = function () { - var $selection = MultipleSelection.__super__.render.call(this); - - $selection[0].classList.add('select2-selection--multiple'); - - $selection.html( - '
          ' - ); - - return $selection; - }; - - MultipleSelection.prototype.bind = function (container, $container) { - var self = this; - - MultipleSelection.__super__.bind.apply(this, arguments); - - var id = container.id + '-container'; - this.$selection.find('.select2-selection__rendered').attr('id', id); - - this.$selection.on('click', function (evt) { - self.trigger('toggle', { - originalEvent: evt - }); - }); - - this.$selection.on( - 'click', - '.select2-selection__choice__remove', - function (evt) { - // Ignore the event if it is disabled - if (self.isDisabled()) { - return; - } - - var $remove = $(this); - var $selection = $remove.parent(); - - var data = Utils.GetData($selection[0], 'data'); - - self.trigger('unselect', { - originalEvent: evt, - data: data - }); - } - ); - - this.$selection.on( - 'keydown', - '.select2-selection__choice__remove', - function (evt) { - // Ignore the event if it is disabled - if (self.isDisabled()) { - return; - } - - evt.stopPropagation(); - } - ); - }; - - MultipleSelection.prototype.clear = function () { - var $rendered = this.$selection.find('.select2-selection__rendered'); - $rendered.empty(); - $rendered.removeAttr('title'); - }; - - MultipleSelection.prototype.display = function (data, container) { - var template = this.options.get('templateSelection'); - var escapeMarkup = this.options.get('escapeMarkup'); - - return escapeMarkup(template(data, container)); - }; - - MultipleSelection.prototype.selectionContainer = function () { - var $container = $( - '
        • ' + - '' + - '' + - '
        • ' - ); - - return $container; - }; - - MultipleSelection.prototype.update = function (data) { - this.clear(); - - if (data.length === 0) { - return; - } - - var $selections = []; - - var selectionIdPrefix = this.$selection.find('.select2-selection__rendered') - .attr('id') + '-choice-'; - - for (var d = 0; d < data.length; d++) { - var selection = data[d]; - - var $selection = this.selectionContainer(); - var formatted = this.display(selection, $selection); - - var selectionId = selectionIdPrefix + Utils.generateChars(4) + '-'; - - if (selection.id) { - selectionId += selection.id; - } else { - selectionId += Utils.generateChars(4); - } - - $selection.find('.select2-selection__choice__display') - .append(formatted) - .attr('id', selectionId); - - var title = selection.title || selection.text; - - if (title) { - $selection.attr('title', title); - } - - var removeItem = this.options.get('translations').get('removeItem'); - - var $remove = $selection.find('.select2-selection__choice__remove'); - - $remove.attr('title', removeItem()); - $remove.attr('aria-label', removeItem()); - $remove.attr('aria-describedby', selectionId); - - Utils.StoreData($selection[0], 'data', selection); - - $selections.push($selection); - } - - var $rendered = this.$selection.find('.select2-selection__rendered'); - - $rendered.append($selections); - }; - - return MultipleSelection; - }); - - S2.define('select2/selection/placeholder',[ - - ], function () { - function Placeholder (decorated, $element, options) { - this.placeholder = this.normalizePlaceholder(options.get('placeholder')); - - decorated.call(this, $element, options); - } - - Placeholder.prototype.normalizePlaceholder = function (_, placeholder) { - if (typeof placeholder === 'string') { - placeholder = { - id: '', - text: placeholder - }; - } - - return placeholder; - }; - - Placeholder.prototype.createPlaceholder = function (decorated, placeholder) { - var $placeholder = this.selectionContainer(); - - $placeholder.html(this.display(placeholder)); - $placeholder[0].classList.add('select2-selection__placeholder'); - $placeholder[0].classList.remove('select2-selection__choice'); - - return $placeholder; - }; - - Placeholder.prototype.update = function (decorated, data) { - var singlePlaceholder = ( - data.length == 1 && data[0].id != this.placeholder.id - ); - var multipleSelections = data.length > 1; - - if (multipleSelections || singlePlaceholder) { - return decorated.call(this, data); - } - - this.clear(); - - var $placeholder = this.createPlaceholder(this.placeholder); - - this.$selection.find('.select2-selection__rendered').append($placeholder); - }; - - return Placeholder; - }); - - S2.define('select2/selection/allowClear',[ - 'jquery', - '../keys', - '../utils' - ], function ($, KEYS, Utils) { - function AllowClear () { } - - AllowClear.prototype.bind = function (decorated, container, $container) { - var self = this; - - decorated.call(this, container, $container); - - if (this.placeholder == null) { - if (this.options.get('debug') && window.console && console.error) { - console.error( - 'Select2: The `allowClear` option should be used in combination ' + - 'with the `placeholder` option.' - ); - } - } - - this.$selection.on('mousedown', '.select2-selection__clear', - function (evt) { - self._handleClear(evt); - }); - - container.on('keypress', function (evt) { - self._handleKeyboardClear(evt, container); - }); - }; - - AllowClear.prototype._handleClear = function (_, evt) { - // Ignore the event if it is disabled - if (this.isDisabled()) { - return; - } - - var $clear = this.$selection.find('.select2-selection__clear'); - - // Ignore the event if nothing has been selected - if ($clear.length === 0) { - return; - } - - evt.stopPropagation(); - - var data = Utils.GetData($clear[0], 'data'); - - var previousVal = this.$element.val(); - this.$element.val(this.placeholder.id); - - var unselectData = { - data: data - }; - this.trigger('clear', unselectData); - if (unselectData.prevented) { - this.$element.val(previousVal); - return; - } - - for (var d = 0; d < data.length; d++) { - unselectData = { - data: data[d] - }; - - // Trigger the `unselect` event, so people can prevent it from being - // cleared. - this.trigger('unselect', unselectData); - - // If the event was prevented, don't clear it out. - if (unselectData.prevented) { - this.$element.val(previousVal); - return; - } - } - - this.$element.trigger('input').trigger('change'); - - this.trigger('toggle', {}); - }; - - AllowClear.prototype._handleKeyboardClear = function (_, evt, container) { - if (container.isOpen()) { - return; - } - - if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) { - this._handleClear(evt); - } - }; - - AllowClear.prototype.update = function (decorated, data) { - decorated.call(this, data); - - this.$selection.find('.select2-selection__clear').remove(); - - if (this.$selection.find('.select2-selection__placeholder').length > 0 || - data.length === 0) { - return; - } - - var selectionId = this.$selection.find('.select2-selection__rendered') - .attr('id'); - - var removeAll = this.options.get('translations').get('removeAllItems'); - - var $remove = $( - '' - ); - $remove.attr('title', removeAll()); - $remove.attr('aria-label', removeAll()); - $remove.attr('aria-describedby', selectionId); - Utils.StoreData($remove[0], 'data', data); - - this.$selection.prepend($remove); - }; - - return AllowClear; - }); - - S2.define('select2/selection/search',[ - 'jquery', - '../utils', - '../keys' - ], function ($, Utils, KEYS) { - function Search (decorated, $element, options) { - decorated.call(this, $element, options); - } - - Search.prototype.render = function (decorated) { - var $search = $( - '' + - '' + - '' - ); - - this.$searchContainer = $search; - this.$search = $search.find('input'); - - this.$search.prop('autocomplete', this.options.get('autocomplete')); - - var $rendered = decorated.call(this); - - this._transferTabIndex(); - $rendered.append(this.$searchContainer); - - return $rendered; - }; - - Search.prototype.bind = function (decorated, container, $container) { - var self = this; - - var resultsId = container.id + '-results'; - var selectionId = container.id + '-container'; - - decorated.call(this, container, $container); - - self.$search.attr('aria-describedby', selectionId); - - container.on('open', function () { - self.$search.attr('aria-controls', resultsId); - self.$search.trigger('focus'); - }); - - container.on('close', function () { - self.$search.val(''); - self.resizeSearch(); - self.$search.removeAttr('aria-controls'); - self.$search.removeAttr('aria-activedescendant'); - self.$search.trigger('focus'); - }); - - container.on('enable', function () { - self.$search.prop('disabled', false); - - self._transferTabIndex(); - }); - - container.on('disable', function () { - self.$search.prop('disabled', true); - }); - - container.on('focus', function (evt) { - self.$search.trigger('focus'); - }); - - container.on('results:focus', function (params) { - if (params.data._resultId) { - self.$search.attr('aria-activedescendant', params.data._resultId); - } else { - self.$search.removeAttr('aria-activedescendant'); - } - }); - - this.$selection.on('focusin', '.select2-search--inline', function (evt) { - self.trigger('focus', evt); - }); - - this.$selection.on('focusout', '.select2-search--inline', function (evt) { - self._handleBlur(evt); - }); - - this.$selection.on('keydown', '.select2-search--inline', function (evt) { - evt.stopPropagation(); - - self.trigger('keypress', evt); - - self._keyUpPrevented = evt.isDefaultPrevented(); - - var key = evt.which; - - if (key === KEYS.BACKSPACE && self.$search.val() === '') { - var $previousChoice = self.$selection - .find('.select2-selection__choice').last(); - - if ($previousChoice.length > 0) { - var item = Utils.GetData($previousChoice[0], 'data'); - - self.searchRemoveChoice(item); - - evt.preventDefault(); - } - } - }); - - this.$selection.on('click', '.select2-search--inline', function (evt) { - if (self.$search.val()) { - evt.stopPropagation(); - } - }); - - // Try to detect the IE version should the `documentMode` property that - // is stored on the document. This is only implemented in IE and is - // slightly cleaner than doing a user agent check. - // This property is not available in Edge, but Edge also doesn't have - // this bug. - var msie = document.documentMode; - var disableInputEvents = msie && msie <= 11; - - // Workaround for browsers which do not support the `input` event - // This will prevent double-triggering of events for browsers which support - // both the `keyup` and `input` events. - this.$selection.on( - 'input.searchcheck', - '.select2-search--inline', - function (evt) { - // IE will trigger the `input` event when a placeholder is used on a - // search box. To get around this issue, we are forced to ignore all - // `input` events in IE and keep using `keyup`. - if (disableInputEvents) { - self.$selection.off('input.search input.searchcheck'); - return; - } - - // Unbind the duplicated `keyup` event - self.$selection.off('keyup.search'); - } - ); - - this.$selection.on( - 'keyup.search input.search', - '.select2-search--inline', - function (evt) { - // IE will trigger the `input` event when a placeholder is used on a - // search box. To get around this issue, we are forced to ignore all - // `input` events in IE and keep using `keyup`. - if (disableInputEvents && evt.type === 'input') { - self.$selection.off('input.search input.searchcheck'); - return; - } - - var key = evt.which; - - // We can freely ignore events from modifier keys - if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) { - return; - } - - // Tabbing will be handled during the `keydown` phase - if (key == KEYS.TAB) { - return; - } - - self.handleSearch(evt); - } - ); - }; - - /** - * This method will transfer the tabindex attribute from the rendered - * selection to the search box. This allows for the search box to be used as - * the primary focus instead of the selection container. - * - * @private - */ - Search.prototype._transferTabIndex = function (decorated) { - this.$search.attr('tabindex', this.$selection.attr('tabindex')); - this.$selection.attr('tabindex', '-1'); - }; - - Search.prototype.createPlaceholder = function (decorated, placeholder) { - this.$search.attr('placeholder', placeholder.text); - }; - - Search.prototype.update = function (decorated, data) { - var searchHadFocus = this.$search[0] == document.activeElement; - - this.$search.attr('placeholder', ''); - - decorated.call(this, data); - - this.resizeSearch(); - if (searchHadFocus) { - this.$search.trigger('focus'); - } - }; - - Search.prototype.handleSearch = function () { - this.resizeSearch(); - - if (!this._keyUpPrevented) { - var input = this.$search.val(); - - this.trigger('query', { - term: input - }); - } - - this._keyUpPrevented = false; - }; - - Search.prototype.searchRemoveChoice = function (decorated, item) { - this.trigger('unselect', { - data: item - }); - - this.$search.val(item.text); - this.handleSearch(); - }; - - Search.prototype.resizeSearch = function () { - this.$search.css('width', '25px'); - - var width = '100%'; - - if (this.$search.attr('placeholder') === '') { - var minimumWidth = this.$search.val().length + 1; - - width = (minimumWidth * 0.75) + 'em'; - } - - this.$search.css('width', width); - }; - - return Search; - }); - - S2.define('select2/selection/selectionCss',[ - '../utils' - ], function (Utils) { - function SelectionCSS () { } - - SelectionCSS.prototype.render = function (decorated) { - var $selection = decorated.call(this); - - var selectionCssClass = this.options.get('selectionCssClass') || ''; - - if (selectionCssClass.indexOf(':all:') !== -1) { - selectionCssClass = selectionCssClass.replace(':all:', ''); - - Utils.copyNonInternalCssClasses($selection[0], this.$element[0]); - } - - $selection.addClass(selectionCssClass); - - return $selection; - }; - - return SelectionCSS; - }); - - S2.define('select2/selection/eventRelay',[ - 'jquery' - ], function ($) { - function EventRelay () { } - - EventRelay.prototype.bind = function (decorated, container, $container) { - var self = this; - var relayEvents = [ - 'open', 'opening', - 'close', 'closing', - 'select', 'selecting', - 'unselect', 'unselecting', - 'clear', 'clearing' - ]; - - var preventableEvents = [ - 'opening', 'closing', 'selecting', 'unselecting', 'clearing' - ]; - - decorated.call(this, container, $container); - - container.on('*', function (name, params) { - // Ignore events that should not be relayed - if (relayEvents.indexOf(name) === -1) { - return; - } - - // The parameters should always be an object - params = params || {}; - - // Generate the jQuery event for the Select2 event - var evt = $.Event('select2:' + name, { - params: params - }); - - self.$element.trigger(evt); - - // Only handle preventable events if it was one - if (preventableEvents.indexOf(name) === -1) { - return; - } - - params.prevented = evt.isDefaultPrevented(); - }); - }; - - return EventRelay; - }); - - S2.define('select2/translation',[ - 'jquery', - 'require' - ], function ($, require) { - function Translation (dict) { - this.dict = dict || {}; - } - - Translation.prototype.all = function () { - return this.dict; - }; - - Translation.prototype.get = function (key) { - return this.dict[key]; - }; - - Translation.prototype.extend = function (translation) { - this.dict = $.extend({}, translation.all(), this.dict); - }; - - // Static functions - - Translation._cache = {}; - - Translation.loadPath = function (path) { - if (!(path in Translation._cache)) { - var translations = require(path); - - Translation._cache[path] = translations; - } - - return new Translation(Translation._cache[path]); - }; - - return Translation; - }); - - S2.define('select2/diacritics',[ - - ], function () { - var diacritics = { - '\u24B6': 'A', - '\uFF21': 'A', - '\u00C0': 'A', - '\u00C1': 'A', - '\u00C2': 'A', - '\u1EA6': 'A', - '\u1EA4': 'A', - '\u1EAA': 'A', - '\u1EA8': 'A', - '\u00C3': 'A', - '\u0100': 'A', - '\u0102': 'A', - '\u1EB0': 'A', - '\u1EAE': 'A', - '\u1EB4': 'A', - '\u1EB2': 'A', - '\u0226': 'A', - '\u01E0': 'A', - '\u00C4': 'A', - '\u01DE': 'A', - '\u1EA2': 'A', - '\u00C5': 'A', - '\u01FA': 'A', - '\u01CD': 'A', - '\u0200': 'A', - '\u0202': 'A', - '\u1EA0': 'A', - '\u1EAC': 'A', - '\u1EB6': 'A', - '\u1E00': 'A', - '\u0104': 'A', - '\u023A': 'A', - '\u2C6F': 'A', - '\uA732': 'AA', - '\u00C6': 'AE', - '\u01FC': 'AE', - '\u01E2': 'AE', - '\uA734': 'AO', - '\uA736': 'AU', - '\uA738': 'AV', - '\uA73A': 'AV', - '\uA73C': 'AY', - '\u24B7': 'B', - '\uFF22': 'B', - '\u1E02': 'B', - '\u1E04': 'B', - '\u1E06': 'B', - '\u0243': 'B', - '\u0182': 'B', - '\u0181': 'B', - '\u24B8': 'C', - '\uFF23': 'C', - '\u0106': 'C', - '\u0108': 'C', - '\u010A': 'C', - '\u010C': 'C', - '\u00C7': 'C', - '\u1E08': 'C', - '\u0187': 'C', - '\u023B': 'C', - '\uA73E': 'C', - '\u24B9': 'D', - '\uFF24': 'D', - '\u1E0A': 'D', - '\u010E': 'D', - '\u1E0C': 'D', - '\u1E10': 'D', - '\u1E12': 'D', - '\u1E0E': 'D', - '\u0110': 'D', - '\u018B': 'D', - '\u018A': 'D', - '\u0189': 'D', - '\uA779': 'D', - '\u01F1': 'DZ', - '\u01C4': 'DZ', - '\u01F2': 'Dz', - '\u01C5': 'Dz', - '\u24BA': 'E', - '\uFF25': 'E', - '\u00C8': 'E', - '\u00C9': 'E', - '\u00CA': 'E', - '\u1EC0': 'E', - '\u1EBE': 'E', - '\u1EC4': 'E', - '\u1EC2': 'E', - '\u1EBC': 'E', - '\u0112': 'E', - '\u1E14': 'E', - '\u1E16': 'E', - '\u0114': 'E', - '\u0116': 'E', - '\u00CB': 'E', - '\u1EBA': 'E', - '\u011A': 'E', - '\u0204': 'E', - '\u0206': 'E', - '\u1EB8': 'E', - '\u1EC6': 'E', - '\u0228': 'E', - '\u1E1C': 'E', - '\u0118': 'E', - '\u1E18': 'E', - '\u1E1A': 'E', - '\u0190': 'E', - '\u018E': 'E', - '\u24BB': 'F', - '\uFF26': 'F', - '\u1E1E': 'F', - '\u0191': 'F', - '\uA77B': 'F', - '\u24BC': 'G', - '\uFF27': 'G', - '\u01F4': 'G', - '\u011C': 'G', - '\u1E20': 'G', - '\u011E': 'G', - '\u0120': 'G', - '\u01E6': 'G', - '\u0122': 'G', - '\u01E4': 'G', - '\u0193': 'G', - '\uA7A0': 'G', - '\uA77D': 'G', - '\uA77E': 'G', - '\u24BD': 'H', - '\uFF28': 'H', - '\u0124': 'H', - '\u1E22': 'H', - '\u1E26': 'H', - '\u021E': 'H', - '\u1E24': 'H', - '\u1E28': 'H', - '\u1E2A': 'H', - '\u0126': 'H', - '\u2C67': 'H', - '\u2C75': 'H', - '\uA78D': 'H', - '\u24BE': 'I', - '\uFF29': 'I', - '\u00CC': 'I', - '\u00CD': 'I', - '\u00CE': 'I', - '\u0128': 'I', - '\u012A': 'I', - '\u012C': 'I', - '\u0130': 'I', - '\u00CF': 'I', - '\u1E2E': 'I', - '\u1EC8': 'I', - '\u01CF': 'I', - '\u0208': 'I', - '\u020A': 'I', - '\u1ECA': 'I', - '\u012E': 'I', - '\u1E2C': 'I', - '\u0197': 'I', - '\u24BF': 'J', - '\uFF2A': 'J', - '\u0134': 'J', - '\u0248': 'J', - '\u24C0': 'K', - '\uFF2B': 'K', - '\u1E30': 'K', - '\u01E8': 'K', - '\u1E32': 'K', - '\u0136': 'K', - '\u1E34': 'K', - '\u0198': 'K', - '\u2C69': 'K', - '\uA740': 'K', - '\uA742': 'K', - '\uA744': 'K', - '\uA7A2': 'K', - '\u24C1': 'L', - '\uFF2C': 'L', - '\u013F': 'L', - '\u0139': 'L', - '\u013D': 'L', - '\u1E36': 'L', - '\u1E38': 'L', - '\u013B': 'L', - '\u1E3C': 'L', - '\u1E3A': 'L', - '\u0141': 'L', - '\u023D': 'L', - '\u2C62': 'L', - '\u2C60': 'L', - '\uA748': 'L', - '\uA746': 'L', - '\uA780': 'L', - '\u01C7': 'LJ', - '\u01C8': 'Lj', - '\u24C2': 'M', - '\uFF2D': 'M', - '\u1E3E': 'M', - '\u1E40': 'M', - '\u1E42': 'M', - '\u2C6E': 'M', - '\u019C': 'M', - '\u24C3': 'N', - '\uFF2E': 'N', - '\u01F8': 'N', - '\u0143': 'N', - '\u00D1': 'N', - '\u1E44': 'N', - '\u0147': 'N', - '\u1E46': 'N', - '\u0145': 'N', - '\u1E4A': 'N', - '\u1E48': 'N', - '\u0220': 'N', - '\u019D': 'N', - '\uA790': 'N', - '\uA7A4': 'N', - '\u01CA': 'NJ', - '\u01CB': 'Nj', - '\u24C4': 'O', - '\uFF2F': 'O', - '\u00D2': 'O', - '\u00D3': 'O', - '\u00D4': 'O', - '\u1ED2': 'O', - '\u1ED0': 'O', - '\u1ED6': 'O', - '\u1ED4': 'O', - '\u00D5': 'O', - '\u1E4C': 'O', - '\u022C': 'O', - '\u1E4E': 'O', - '\u014C': 'O', - '\u1E50': 'O', - '\u1E52': 'O', - '\u014E': 'O', - '\u022E': 'O', - '\u0230': 'O', - '\u00D6': 'O', - '\u022A': 'O', - '\u1ECE': 'O', - '\u0150': 'O', - '\u01D1': 'O', - '\u020C': 'O', - '\u020E': 'O', - '\u01A0': 'O', - '\u1EDC': 'O', - '\u1EDA': 'O', - '\u1EE0': 'O', - '\u1EDE': 'O', - '\u1EE2': 'O', - '\u1ECC': 'O', - '\u1ED8': 'O', - '\u01EA': 'O', - '\u01EC': 'O', - '\u00D8': 'O', - '\u01FE': 'O', - '\u0186': 'O', - '\u019F': 'O', - '\uA74A': 'O', - '\uA74C': 'O', - '\u0152': 'OE', - '\u01A2': 'OI', - '\uA74E': 'OO', - '\u0222': 'OU', - '\u24C5': 'P', - '\uFF30': 'P', - '\u1E54': 'P', - '\u1E56': 'P', - '\u01A4': 'P', - '\u2C63': 'P', - '\uA750': 'P', - '\uA752': 'P', - '\uA754': 'P', - '\u24C6': 'Q', - '\uFF31': 'Q', - '\uA756': 'Q', - '\uA758': 'Q', - '\u024A': 'Q', - '\u24C7': 'R', - '\uFF32': 'R', - '\u0154': 'R', - '\u1E58': 'R', - '\u0158': 'R', - '\u0210': 'R', - '\u0212': 'R', - '\u1E5A': 'R', - '\u1E5C': 'R', - '\u0156': 'R', - '\u1E5E': 'R', - '\u024C': 'R', - '\u2C64': 'R', - '\uA75A': 'R', - '\uA7A6': 'R', - '\uA782': 'R', - '\u24C8': 'S', - '\uFF33': 'S', - '\u1E9E': 'S', - '\u015A': 'S', - '\u1E64': 'S', - '\u015C': 'S', - '\u1E60': 'S', - '\u0160': 'S', - '\u1E66': 'S', - '\u1E62': 'S', - '\u1E68': 'S', - '\u0218': 'S', - '\u015E': 'S', - '\u2C7E': 'S', - '\uA7A8': 'S', - '\uA784': 'S', - '\u24C9': 'T', - '\uFF34': 'T', - '\u1E6A': 'T', - '\u0164': 'T', - '\u1E6C': 'T', - '\u021A': 'T', - '\u0162': 'T', - '\u1E70': 'T', - '\u1E6E': 'T', - '\u0166': 'T', - '\u01AC': 'T', - '\u01AE': 'T', - '\u023E': 'T', - '\uA786': 'T', - '\uA728': 'TZ', - '\u24CA': 'U', - '\uFF35': 'U', - '\u00D9': 'U', - '\u00DA': 'U', - '\u00DB': 'U', - '\u0168': 'U', - '\u1E78': 'U', - '\u016A': 'U', - '\u1E7A': 'U', - '\u016C': 'U', - '\u00DC': 'U', - '\u01DB': 'U', - '\u01D7': 'U', - '\u01D5': 'U', - '\u01D9': 'U', - '\u1EE6': 'U', - '\u016E': 'U', - '\u0170': 'U', - '\u01D3': 'U', - '\u0214': 'U', - '\u0216': 'U', - '\u01AF': 'U', - '\u1EEA': 'U', - '\u1EE8': 'U', - '\u1EEE': 'U', - '\u1EEC': 'U', - '\u1EF0': 'U', - '\u1EE4': 'U', - '\u1E72': 'U', - '\u0172': 'U', - '\u1E76': 'U', - '\u1E74': 'U', - '\u0244': 'U', - '\u24CB': 'V', - '\uFF36': 'V', - '\u1E7C': 'V', - '\u1E7E': 'V', - '\u01B2': 'V', - '\uA75E': 'V', - '\u0245': 'V', - '\uA760': 'VY', - '\u24CC': 'W', - '\uFF37': 'W', - '\u1E80': 'W', - '\u1E82': 'W', - '\u0174': 'W', - '\u1E86': 'W', - '\u1E84': 'W', - '\u1E88': 'W', - '\u2C72': 'W', - '\u24CD': 'X', - '\uFF38': 'X', - '\u1E8A': 'X', - '\u1E8C': 'X', - '\u24CE': 'Y', - '\uFF39': 'Y', - '\u1EF2': 'Y', - '\u00DD': 'Y', - '\u0176': 'Y', - '\u1EF8': 'Y', - '\u0232': 'Y', - '\u1E8E': 'Y', - '\u0178': 'Y', - '\u1EF6': 'Y', - '\u1EF4': 'Y', - '\u01B3': 'Y', - '\u024E': 'Y', - '\u1EFE': 'Y', - '\u24CF': 'Z', - '\uFF3A': 'Z', - '\u0179': 'Z', - '\u1E90': 'Z', - '\u017B': 'Z', - '\u017D': 'Z', - '\u1E92': 'Z', - '\u1E94': 'Z', - '\u01B5': 'Z', - '\u0224': 'Z', - '\u2C7F': 'Z', - '\u2C6B': 'Z', - '\uA762': 'Z', - '\u24D0': 'a', - '\uFF41': 'a', - '\u1E9A': 'a', - '\u00E0': 'a', - '\u00E1': 'a', - '\u00E2': 'a', - '\u1EA7': 'a', - '\u1EA5': 'a', - '\u1EAB': 'a', - '\u1EA9': 'a', - '\u00E3': 'a', - '\u0101': 'a', - '\u0103': 'a', - '\u1EB1': 'a', - '\u1EAF': 'a', - '\u1EB5': 'a', - '\u1EB3': 'a', - '\u0227': 'a', - '\u01E1': 'a', - '\u00E4': 'a', - '\u01DF': 'a', - '\u1EA3': 'a', - '\u00E5': 'a', - '\u01FB': 'a', - '\u01CE': 'a', - '\u0201': 'a', - '\u0203': 'a', - '\u1EA1': 'a', - '\u1EAD': 'a', - '\u1EB7': 'a', - '\u1E01': 'a', - '\u0105': 'a', - '\u2C65': 'a', - '\u0250': 'a', - '\uA733': 'aa', - '\u00E6': 'ae', - '\u01FD': 'ae', - '\u01E3': 'ae', - '\uA735': 'ao', - '\uA737': 'au', - '\uA739': 'av', - '\uA73B': 'av', - '\uA73D': 'ay', - '\u24D1': 'b', - '\uFF42': 'b', - '\u1E03': 'b', - '\u1E05': 'b', - '\u1E07': 'b', - '\u0180': 'b', - '\u0183': 'b', - '\u0253': 'b', - '\u24D2': 'c', - '\uFF43': 'c', - '\u0107': 'c', - '\u0109': 'c', - '\u010B': 'c', - '\u010D': 'c', - '\u00E7': 'c', - '\u1E09': 'c', - '\u0188': 'c', - '\u023C': 'c', - '\uA73F': 'c', - '\u2184': 'c', - '\u24D3': 'd', - '\uFF44': 'd', - '\u1E0B': 'd', - '\u010F': 'd', - '\u1E0D': 'd', - '\u1E11': 'd', - '\u1E13': 'd', - '\u1E0F': 'd', - '\u0111': 'd', - '\u018C': 'd', - '\u0256': 'd', - '\u0257': 'd', - '\uA77A': 'd', - '\u01F3': 'dz', - '\u01C6': 'dz', - '\u24D4': 'e', - '\uFF45': 'e', - '\u00E8': 'e', - '\u00E9': 'e', - '\u00EA': 'e', - '\u1EC1': 'e', - '\u1EBF': 'e', - '\u1EC5': 'e', - '\u1EC3': 'e', - '\u1EBD': 'e', - '\u0113': 'e', - '\u1E15': 'e', - '\u1E17': 'e', - '\u0115': 'e', - '\u0117': 'e', - '\u00EB': 'e', - '\u1EBB': 'e', - '\u011B': 'e', - '\u0205': 'e', - '\u0207': 'e', - '\u1EB9': 'e', - '\u1EC7': 'e', - '\u0229': 'e', - '\u1E1D': 'e', - '\u0119': 'e', - '\u1E19': 'e', - '\u1E1B': 'e', - '\u0247': 'e', - '\u025B': 'e', - '\u01DD': 'e', - '\u24D5': 'f', - '\uFF46': 'f', - '\u1E1F': 'f', - '\u0192': 'f', - '\uA77C': 'f', - '\u24D6': 'g', - '\uFF47': 'g', - '\u01F5': 'g', - '\u011D': 'g', - '\u1E21': 'g', - '\u011F': 'g', - '\u0121': 'g', - '\u01E7': 'g', - '\u0123': 'g', - '\u01E5': 'g', - '\u0260': 'g', - '\uA7A1': 'g', - '\u1D79': 'g', - '\uA77F': 'g', - '\u24D7': 'h', - '\uFF48': 'h', - '\u0125': 'h', - '\u1E23': 'h', - '\u1E27': 'h', - '\u021F': 'h', - '\u1E25': 'h', - '\u1E29': 'h', - '\u1E2B': 'h', - '\u1E96': 'h', - '\u0127': 'h', - '\u2C68': 'h', - '\u2C76': 'h', - '\u0265': 'h', - '\u0195': 'hv', - '\u24D8': 'i', - '\uFF49': 'i', - '\u00EC': 'i', - '\u00ED': 'i', - '\u00EE': 'i', - '\u0129': 'i', - '\u012B': 'i', - '\u012D': 'i', - '\u00EF': 'i', - '\u1E2F': 'i', - '\u1EC9': 'i', - '\u01D0': 'i', - '\u0209': 'i', - '\u020B': 'i', - '\u1ECB': 'i', - '\u012F': 'i', - '\u1E2D': 'i', - '\u0268': 'i', - '\u0131': 'i', - '\u24D9': 'j', - '\uFF4A': 'j', - '\u0135': 'j', - '\u01F0': 'j', - '\u0249': 'j', - '\u24DA': 'k', - '\uFF4B': 'k', - '\u1E31': 'k', - '\u01E9': 'k', - '\u1E33': 'k', - '\u0137': 'k', - '\u1E35': 'k', - '\u0199': 'k', - '\u2C6A': 'k', - '\uA741': 'k', - '\uA743': 'k', - '\uA745': 'k', - '\uA7A3': 'k', - '\u24DB': 'l', - '\uFF4C': 'l', - '\u0140': 'l', - '\u013A': 'l', - '\u013E': 'l', - '\u1E37': 'l', - '\u1E39': 'l', - '\u013C': 'l', - '\u1E3D': 'l', - '\u1E3B': 'l', - '\u017F': 'l', - '\u0142': 'l', - '\u019A': 'l', - '\u026B': 'l', - '\u2C61': 'l', - '\uA749': 'l', - '\uA781': 'l', - '\uA747': 'l', - '\u01C9': 'lj', - '\u24DC': 'm', - '\uFF4D': 'm', - '\u1E3F': 'm', - '\u1E41': 'm', - '\u1E43': 'm', - '\u0271': 'm', - '\u026F': 'm', - '\u24DD': 'n', - '\uFF4E': 'n', - '\u01F9': 'n', - '\u0144': 'n', - '\u00F1': 'n', - '\u1E45': 'n', - '\u0148': 'n', - '\u1E47': 'n', - '\u0146': 'n', - '\u1E4B': 'n', - '\u1E49': 'n', - '\u019E': 'n', - '\u0272': 'n', - '\u0149': 'n', - '\uA791': 'n', - '\uA7A5': 'n', - '\u01CC': 'nj', - '\u24DE': 'o', - '\uFF4F': 'o', - '\u00F2': 'o', - '\u00F3': 'o', - '\u00F4': 'o', - '\u1ED3': 'o', - '\u1ED1': 'o', - '\u1ED7': 'o', - '\u1ED5': 'o', - '\u00F5': 'o', - '\u1E4D': 'o', - '\u022D': 'o', - '\u1E4F': 'o', - '\u014D': 'o', - '\u1E51': 'o', - '\u1E53': 'o', - '\u014F': 'o', - '\u022F': 'o', - '\u0231': 'o', - '\u00F6': 'o', - '\u022B': 'o', - '\u1ECF': 'o', - '\u0151': 'o', - '\u01D2': 'o', - '\u020D': 'o', - '\u020F': 'o', - '\u01A1': 'o', - '\u1EDD': 'o', - '\u1EDB': 'o', - '\u1EE1': 'o', - '\u1EDF': 'o', - '\u1EE3': 'o', - '\u1ECD': 'o', - '\u1ED9': 'o', - '\u01EB': 'o', - '\u01ED': 'o', - '\u00F8': 'o', - '\u01FF': 'o', - '\u0254': 'o', - '\uA74B': 'o', - '\uA74D': 'o', - '\u0275': 'o', - '\u0153': 'oe', - '\u01A3': 'oi', - '\u0223': 'ou', - '\uA74F': 'oo', - '\u24DF': 'p', - '\uFF50': 'p', - '\u1E55': 'p', - '\u1E57': 'p', - '\u01A5': 'p', - '\u1D7D': 'p', - '\uA751': 'p', - '\uA753': 'p', - '\uA755': 'p', - '\u24E0': 'q', - '\uFF51': 'q', - '\u024B': 'q', - '\uA757': 'q', - '\uA759': 'q', - '\u24E1': 'r', - '\uFF52': 'r', - '\u0155': 'r', - '\u1E59': 'r', - '\u0159': 'r', - '\u0211': 'r', - '\u0213': 'r', - '\u1E5B': 'r', - '\u1E5D': 'r', - '\u0157': 'r', - '\u1E5F': 'r', - '\u024D': 'r', - '\u027D': 'r', - '\uA75B': 'r', - '\uA7A7': 'r', - '\uA783': 'r', - '\u24E2': 's', - '\uFF53': 's', - '\u00DF': 's', - '\u015B': 's', - '\u1E65': 's', - '\u015D': 's', - '\u1E61': 's', - '\u0161': 's', - '\u1E67': 's', - '\u1E63': 's', - '\u1E69': 's', - '\u0219': 's', - '\u015F': 's', - '\u023F': 's', - '\uA7A9': 's', - '\uA785': 's', - '\u1E9B': 's', - '\u24E3': 't', - '\uFF54': 't', - '\u1E6B': 't', - '\u1E97': 't', - '\u0165': 't', - '\u1E6D': 't', - '\u021B': 't', - '\u0163': 't', - '\u1E71': 't', - '\u1E6F': 't', - '\u0167': 't', - '\u01AD': 't', - '\u0288': 't', - '\u2C66': 't', - '\uA787': 't', - '\uA729': 'tz', - '\u24E4': 'u', - '\uFF55': 'u', - '\u00F9': 'u', - '\u00FA': 'u', - '\u00FB': 'u', - '\u0169': 'u', - '\u1E79': 'u', - '\u016B': 'u', - '\u1E7B': 'u', - '\u016D': 'u', - '\u00FC': 'u', - '\u01DC': 'u', - '\u01D8': 'u', - '\u01D6': 'u', - '\u01DA': 'u', - '\u1EE7': 'u', - '\u016F': 'u', - '\u0171': 'u', - '\u01D4': 'u', - '\u0215': 'u', - '\u0217': 'u', - '\u01B0': 'u', - '\u1EEB': 'u', - '\u1EE9': 'u', - '\u1EEF': 'u', - '\u1EED': 'u', - '\u1EF1': 'u', - '\u1EE5': 'u', - '\u1E73': 'u', - '\u0173': 'u', - '\u1E77': 'u', - '\u1E75': 'u', - '\u0289': 'u', - '\u24E5': 'v', - '\uFF56': 'v', - '\u1E7D': 'v', - '\u1E7F': 'v', - '\u028B': 'v', - '\uA75F': 'v', - '\u028C': 'v', - '\uA761': 'vy', - '\u24E6': 'w', - '\uFF57': 'w', - '\u1E81': 'w', - '\u1E83': 'w', - '\u0175': 'w', - '\u1E87': 'w', - '\u1E85': 'w', - '\u1E98': 'w', - '\u1E89': 'w', - '\u2C73': 'w', - '\u24E7': 'x', - '\uFF58': 'x', - '\u1E8B': 'x', - '\u1E8D': 'x', - '\u24E8': 'y', - '\uFF59': 'y', - '\u1EF3': 'y', - '\u00FD': 'y', - '\u0177': 'y', - '\u1EF9': 'y', - '\u0233': 'y', - '\u1E8F': 'y', - '\u00FF': 'y', - '\u1EF7': 'y', - '\u1E99': 'y', - '\u1EF5': 'y', - '\u01B4': 'y', - '\u024F': 'y', - '\u1EFF': 'y', - '\u24E9': 'z', - '\uFF5A': 'z', - '\u017A': 'z', - '\u1E91': 'z', - '\u017C': 'z', - '\u017E': 'z', - '\u1E93': 'z', - '\u1E95': 'z', - '\u01B6': 'z', - '\u0225': 'z', - '\u0240': 'z', - '\u2C6C': 'z', - '\uA763': 'z', - '\u0386': '\u0391', - '\u0388': '\u0395', - '\u0389': '\u0397', - '\u038A': '\u0399', - '\u03AA': '\u0399', - '\u038C': '\u039F', - '\u038E': '\u03A5', - '\u03AB': '\u03A5', - '\u038F': '\u03A9', - '\u03AC': '\u03B1', - '\u03AD': '\u03B5', - '\u03AE': '\u03B7', - '\u03AF': '\u03B9', - '\u03CA': '\u03B9', - '\u0390': '\u03B9', - '\u03CC': '\u03BF', - '\u03CD': '\u03C5', - '\u03CB': '\u03C5', - '\u03B0': '\u03C5', - '\u03CE': '\u03C9', - '\u03C2': '\u03C3', - '\u2019': '\'' - }; - - return diacritics; - }); - - S2.define('select2/data/base',[ - '../utils' - ], function (Utils) { - function BaseAdapter ($element, options) { - BaseAdapter.__super__.constructor.call(this); - } - - Utils.Extend(BaseAdapter, Utils.Observable); - - BaseAdapter.prototype.current = function (callback) { - throw new Error('The `current` method must be defined in child classes.'); - }; - - BaseAdapter.prototype.query = function (params, callback) { - throw new Error('The `query` method must be defined in child classes.'); - }; - - BaseAdapter.prototype.bind = function (container, $container) { - // Can be implemented in subclasses - }; - - BaseAdapter.prototype.destroy = function () { - // Can be implemented in subclasses - }; - - BaseAdapter.prototype.generateResultId = function (container, data) { - var id = container.id + '-result-'; - - id += Utils.generateChars(4); - - if (data.id != null) { - id += '-' + data.id.toString(); - } else { - id += '-' + Utils.generateChars(4); - } - return id; - }; - - return BaseAdapter; - }); - - S2.define('select2/data/select',[ - './base', - '../utils', - 'jquery' - ], function (BaseAdapter, Utils, $) { - function SelectAdapter ($element, options) { - this.$element = $element; - this.options = options; - - SelectAdapter.__super__.constructor.call(this); - } - - Utils.Extend(SelectAdapter, BaseAdapter); - - SelectAdapter.prototype.current = function (callback) { - var self = this; - - var data = Array.prototype.map.call( - this.$element[0].querySelectorAll(':checked'), - function (selectedElement) { - return self.item($(selectedElement)); - } - ); - - callback(data); - }; - - SelectAdapter.prototype.select = function (data) { - var self = this; - - data.selected = true; - - // If data.element is a DOM node, use it instead - if ( - data.element != null && data.element.tagName.toLowerCase() === 'option' - ) { - data.element.selected = true; - - this.$element.trigger('input').trigger('change'); - - return; - } - - if (this.$element.prop('multiple')) { - this.current(function (currentData) { - var val = []; - - data = [data]; - data.push.apply(data, currentData); - - for (var d = 0; d < data.length; d++) { - var id = data[d].id; - - if (val.indexOf(id) === -1) { - val.push(id); - } - } - - self.$element.val(val); - self.$element.trigger('input').trigger('change'); - }); - } else { - var val = data.id; - - this.$element.val(val); - this.$element.trigger('input').trigger('change'); - } - }; - - SelectAdapter.prototype.unselect = function (data) { - var self = this; - - if (!this.$element.prop('multiple')) { - return; - } - - data.selected = false; - - if ( - data.element != null && - data.element.tagName.toLowerCase() === 'option' - ) { - data.element.selected = false; - - this.$element.trigger('input').trigger('change'); - - return; - } - - this.current(function (currentData) { - var val = []; - - for (var d = 0; d < currentData.length; d++) { - var id = currentData[d].id; - - if (id !== data.id && val.indexOf(id) === -1) { - val.push(id); - } - } - - self.$element.val(val); - - self.$element.trigger('input').trigger('change'); - }); - }; - - SelectAdapter.prototype.bind = function (container, $container) { - var self = this; - - this.container = container; - - container.on('select', function (params) { - self.select(params.data); - }); - - container.on('unselect', function (params) { - self.unselect(params.data); - }); - }; - - SelectAdapter.prototype.destroy = function () { - // Remove anything added to child elements - this.$element.find('*').each(function () { - // Remove any custom data set by Select2 - Utils.RemoveData(this); - }); - }; - - SelectAdapter.prototype.query = function (params, callback) { - var data = []; - var self = this; - - var $options = this.$element.children(); - - $options.each(function () { - if ( - this.tagName.toLowerCase() !== 'option' && - this.tagName.toLowerCase() !== 'optgroup' - ) { - return; - } - - var $option = $(this); - - var option = self.item($option); - - var matches = self.matches(params, option); - - if (matches !== null) { - data.push(matches); - } - }); - - callback({ - results: data - }); - }; - - SelectAdapter.prototype.addOptions = function ($options) { - this.$element.append($options); - }; - - SelectAdapter.prototype.option = function (data) { - var option; - - if (data.children) { - option = document.createElement('optgroup'); - option.label = data.text; - } else { - option = document.createElement('option'); - - if (option.textContent !== undefined) { - option.textContent = data.text; - } else { - option.innerText = data.text; - } - } - - if (data.id !== undefined) { - option.value = data.id; - } - - if (data.disabled) { - option.disabled = true; - } - - if (data.selected) { - option.selected = true; - } - - if (data.title) { - option.title = data.title; - } - - var normalizedData = this._normalizeItem(data); - normalizedData.element = option; - - // Override the option's data with the combined data - Utils.StoreData(option, 'data', normalizedData); - - return $(option); - }; - - SelectAdapter.prototype.item = function ($option) { - var data = {}; - - data = Utils.GetData($option[0], 'data'); - - if (data != null) { - return data; - } - - var option = $option[0]; - - if (option.tagName.toLowerCase() === 'option') { - data = { - id: $option.val(), - text: $option.text(), - disabled: $option.prop('disabled'), - selected: $option.prop('selected'), - title: $option.prop('title') - }; - } else if (option.tagName.toLowerCase() === 'optgroup') { - data = { - text: $option.prop('label'), - children: [], - title: $option.prop('title') - }; - - var $children = $option.children('option'); - var children = []; - - for (var c = 0; c < $children.length; c++) { - var $child = $($children[c]); - - var child = this.item($child); - - children.push(child); - } - - data.children = children; - } - - data = this._normalizeItem(data); - data.element = $option[0]; - - Utils.StoreData($option[0], 'data', data); - - return data; - }; - - SelectAdapter.prototype._normalizeItem = function (item) { - if (item !== Object(item)) { - item = { - id: item, - text: item - }; - } - - item = $.extend({}, { - text: '' - }, item); - - var defaults = { - selected: false, - disabled: false - }; - - if (item.id != null) { - item.id = item.id.toString(); - } - - if (item.text != null) { - item.text = item.text.toString(); - } - - if (item._resultId == null && item.id && this.container != null) { - item._resultId = this.generateResultId(this.container, item); - } - - return $.extend({}, defaults, item); - }; - - SelectAdapter.prototype.matches = function (params, data) { - var matcher = this.options.get('matcher'); - - return matcher(params, data); - }; - - return SelectAdapter; - }); - - S2.define('select2/data/array',[ - './select', - '../utils', - 'jquery' - ], function (SelectAdapter, Utils, $) { - function ArrayAdapter ($element, options) { - this._dataToConvert = options.get('data') || []; - - ArrayAdapter.__super__.constructor.call(this, $element, options); - } - - Utils.Extend(ArrayAdapter, SelectAdapter); - - ArrayAdapter.prototype.bind = function (container, $container) { - ArrayAdapter.__super__.bind.call(this, container, $container); - - this.addOptions(this.convertToOptions(this._dataToConvert)); - }; - - ArrayAdapter.prototype.select = function (data) { - var $option = this.$element.find('option').filter(function (i, elm) { - return elm.value == data.id.toString(); - }); - - if ($option.length === 0) { - $option = this.option(data); - - this.addOptions($option); - } - - ArrayAdapter.__super__.select.call(this, data); - }; - - ArrayAdapter.prototype.convertToOptions = function (data) { - var self = this; - - var $existing = this.$element.find('option'); - var existingIds = $existing.map(function () { - return self.item($(this)).id; - }).get(); - - var $options = []; - - // Filter out all items except for the one passed in the argument - function onlyItem (item) { - return function () { - return $(this).val() == item.id; - }; - } - - for (var d = 0; d < data.length; d++) { - var item = this._normalizeItem(data[d]); - - // Skip items which were pre-loaded, only merge the data - if (existingIds.indexOf(item.id) >= 0) { - var $existingOption = $existing.filter(onlyItem(item)); - - var existingData = this.item($existingOption); - var newData = $.extend(true, {}, item, existingData); - - var $newOption = this.option(newData); - - $existingOption.replaceWith($newOption); - - continue; - } - - var $option = this.option(item); - - if (item.children) { - var $children = this.convertToOptions(item.children); - - $option.append($children); - } - - $options.push($option); - } - - return $options; - }; - - return ArrayAdapter; - }); - - S2.define('select2/data/ajax',[ - './array', - '../utils', - 'jquery' - ], function (ArrayAdapter, Utils, $) { - function AjaxAdapter ($element, options) { - this.ajaxOptions = this._applyDefaults(options.get('ajax')); - - if (this.ajaxOptions.processResults != null) { - this.processResults = this.ajaxOptions.processResults; - } - - AjaxAdapter.__super__.constructor.call(this, $element, options); - } - - Utils.Extend(AjaxAdapter, ArrayAdapter); - - AjaxAdapter.prototype._applyDefaults = function (options) { - var defaults = { - data: function (params) { - return $.extend({}, params, { - q: params.term - }); - }, - transport: function (params, success, failure) { - var $request = $.ajax(params); - - $request.then(success); - $request.fail(failure); - - return $request; - } - }; - - return $.extend({}, defaults, options, true); - }; - - AjaxAdapter.prototype.processResults = function (results) { - return results; - }; - - AjaxAdapter.prototype.query = function (params, callback) { - var matches = []; - var self = this; - - if (this._request != null) { - // JSONP requests cannot always be aborted - if ($.isFunction(this._request.abort)) { - this._request.abort(); - } - - this._request = null; - } - - var options = $.extend({ - type: 'GET' - }, this.ajaxOptions); - - if (typeof options.url === 'function') { - options.url = options.url.call(this.$element, params); - } - - if (typeof options.data === 'function') { - options.data = options.data.call(this.$element, params); - } - - function request () { - var $request = options.transport(options, function (data) { - var results = self.processResults(data, params); - - if (self.options.get('debug') && window.console && console.error) { - // Check to make sure that the response included a `results` key. - if (!results || !results.results || !Array.isArray(results.results)) { - console.error( - 'Select2: The AJAX results did not return an array in the ' + - '`results` key of the response.' - ); - } - } - - callback(results); - }, function () { - // Attempt to detect if a request was aborted - // Only works if the transport exposes a status property - if ('status' in $request && - ($request.status === 0 || $request.status === '0')) { - return; - } - - self.trigger('results:message', { - message: 'errorLoading' - }); - }); - - self._request = $request; - } - - if (this.ajaxOptions.delay && params.term != null) { - if (this._queryTimeout) { - window.clearTimeout(this._queryTimeout); - } - - this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); - } else { - request(); - } - }; - - return AjaxAdapter; - }); - - S2.define('select2/data/tags',[ - 'jquery' - ], function ($) { - function Tags (decorated, $element, options) { - var tags = options.get('tags'); - - var createTag = options.get('createTag'); - - if (createTag !== undefined) { - this.createTag = createTag; - } - - var insertTag = options.get('insertTag'); - - if (insertTag !== undefined) { - this.insertTag = insertTag; - } - - decorated.call(this, $element, options); - - if (Array.isArray(tags)) { - for (var t = 0; t < tags.length; t++) { - var tag = tags[t]; - var item = this._normalizeItem(tag); - - var $option = this.option(item); - - this.$element.append($option); - } - } - } - - Tags.prototype.query = function (decorated, params, callback) { - var self = this; - - this._removeOldTags(); - - if (params.term == null || params.page != null) { - decorated.call(this, params, callback); - return; - } - - function wrapper (obj, child) { - var data = obj.results; - - for (var i = 0; i < data.length; i++) { - var option = data[i]; - - var checkChildren = ( - option.children != null && - !wrapper({ - results: option.children - }, true) - ); - - var optionText = (option.text || '').toUpperCase(); - var paramsTerm = (params.term || '').toUpperCase(); - - var checkText = optionText === paramsTerm; - - if (checkText || checkChildren) { - if (child) { - return false; - } - - obj.data = data; - callback(obj); - - return; - } - } - - if (child) { - return true; - } - - var tag = self.createTag(params); - - if (tag != null) { - var $option = self.option(tag); - $option.attr('data-select2-tag', true); - - self.addOptions([$option]); - - self.insertTag(data, tag); - } - - obj.results = data; - - callback(obj); - } - - decorated.call(this, params, wrapper); - }; - - Tags.prototype.createTag = function (decorated, params) { - if (params.term == null) { - return null; - } - - var term = params.term.trim(); - - if (term === '') { - return null; - } - - return { - id: term, - text: term - }; - }; - - Tags.prototype.insertTag = function (_, data, tag) { - data.unshift(tag); - }; - - Tags.prototype._removeOldTags = function (_) { - var $options = this.$element.find('option[data-select2-tag]'); - - $options.each(function () { - if (this.selected) { - return; - } - - $(this).remove(); - }); - }; - - return Tags; - }); - - S2.define('select2/data/tokenizer',[ - 'jquery' - ], function ($) { - function Tokenizer (decorated, $element, options) { - var tokenizer = options.get('tokenizer'); - - if (tokenizer !== undefined) { - this.tokenizer = tokenizer; - } - - decorated.call(this, $element, options); - } - - Tokenizer.prototype.bind = function (decorated, container, $container) { - decorated.call(this, container, $container); - - this.$search = container.dropdown.$search || container.selection.$search || - $container.find('.select2-search__field'); - }; - - Tokenizer.prototype.query = function (decorated, params, callback) { - var self = this; - - function createAndSelect (data) { - // Normalize the data object so we can use it for checks - var item = self._normalizeItem(data); - - // Check if the data object already exists as a tag - // Select it if it doesn't - var $existingOptions = self.$element.find('option').filter(function () { - return $(this).val() === item.id; - }); - - // If an existing option wasn't found for it, create the option - if (!$existingOptions.length) { - var $option = self.option(item); - $option.attr('data-select2-tag', true); - - self._removeOldTags(); - self.addOptions([$option]); - } - - // Select the item, now that we know there is an option for it - select(item); - } - - function select (data) { - self.trigger('select', { - data: data - }); - } - - params.term = params.term || ''; - - var tokenData = this.tokenizer(params, this.options, createAndSelect); - - if (tokenData.term !== params.term) { - // Replace the search term if we have the search box - if (this.$search.length) { - this.$search.val(tokenData.term); - this.$search.trigger('focus'); - } - - params.term = tokenData.term; - } - - decorated.call(this, params, callback); - }; - - Tokenizer.prototype.tokenizer = function (_, params, options, callback) { - var separators = options.get('tokenSeparators') || []; - var term = params.term; - var i = 0; - - var createTag = this.createTag || function (params) { - return { - id: params.term, - text: params.term - }; - }; - - while (i < term.length) { - var termChar = term[i]; - - if (separators.indexOf(termChar) === -1) { - i++; - - continue; - } - - var part = term.substr(0, i); - var partParams = $.extend({}, params, { - term: part - }); - - var data = createTag(partParams); - - if (data == null) { - i++; - continue; - } - - callback(data); - - // Reset the term to not include the tokenized portion - term = term.substr(i + 1) || ''; - i = 0; - } - - return { - term: term - }; - }; - - return Tokenizer; - }); - - S2.define('select2/data/minimumInputLength',[ - - ], function () { - function MinimumInputLength (decorated, $e, options) { - this.minimumInputLength = options.get('minimumInputLength'); - - decorated.call(this, $e, options); - } - - MinimumInputLength.prototype.query = function (decorated, params, callback) { - params.term = params.term || ''; - - if (params.term.length < this.minimumInputLength) { - this.trigger('results:message', { - message: 'inputTooShort', - args: { - minimum: this.minimumInputLength, - input: params.term, - params: params - } - }); - - return; - } - - decorated.call(this, params, callback); - }; - - return MinimumInputLength; - }); - - S2.define('select2/data/maximumInputLength',[ - - ], function () { - function MaximumInputLength (decorated, $e, options) { - this.maximumInputLength = options.get('maximumInputLength'); - - decorated.call(this, $e, options); - } - - MaximumInputLength.prototype.query = function (decorated, params, callback) { - params.term = params.term || ''; - - if (this.maximumInputLength > 0 && - params.term.length > this.maximumInputLength) { - this.trigger('results:message', { - message: 'inputTooLong', - args: { - maximum: this.maximumInputLength, - input: params.term, - params: params - } - }); - - return; - } - - decorated.call(this, params, callback); - }; - - return MaximumInputLength; - }); - - S2.define('select2/data/maximumSelectionLength',[ - - ], function (){ - function MaximumSelectionLength (decorated, $e, options) { - this.maximumSelectionLength = options.get('maximumSelectionLength'); - - decorated.call(this, $e, options); - } - - MaximumSelectionLength.prototype.bind = - function (decorated, container, $container) { - var self = this; - - decorated.call(this, container, $container); - - container.on('select', function () { - self._checkIfMaximumSelected(); - }); - }; - - MaximumSelectionLength.prototype.query = - function (decorated, params, callback) { - var self = this; - - this._checkIfMaximumSelected(function () { - decorated.call(self, params, callback); - }); - }; - - MaximumSelectionLength.prototype._checkIfMaximumSelected = - function (_, successCallback) { - var self = this; - - this.current(function (currentData) { - var count = currentData != null ? currentData.length : 0; - if (self.maximumSelectionLength > 0 && - count >= self.maximumSelectionLength) { - self.trigger('results:message', { - message: 'maximumSelected', - args: { - maximum: self.maximumSelectionLength - } - }); - return; - } - - if (successCallback) { - successCallback(); - } - }); - }; - - return MaximumSelectionLength; - }); - - S2.define('select2/dropdown',[ - 'jquery', - './utils' - ], function ($, Utils) { - function Dropdown ($element, options) { - this.$element = $element; - this.options = options; - - Dropdown.__super__.constructor.call(this); - } - - Utils.Extend(Dropdown, Utils.Observable); - - Dropdown.prototype.render = function () { - var $dropdown = $( - '' + - '' + - '' - ); - - $dropdown.attr('dir', this.options.get('dir')); - - this.$dropdown = $dropdown; - - return $dropdown; - }; - - Dropdown.prototype.bind = function () { - // Should be implemented in subclasses - }; - - Dropdown.prototype.position = function ($dropdown, $container) { - // Should be implemented in subclasses - }; - - Dropdown.prototype.destroy = function () { - // Remove the dropdown from the DOM - this.$dropdown.remove(); - }; - - return Dropdown; - }); - - S2.define('select2/dropdown/search',[ - 'jquery' - ], function ($) { - function Search () { } - - Search.prototype.render = function (decorated) { - var $rendered = decorated.call(this); - - var $search = $( - '' + - '' + - '' - ); - - this.$searchContainer = $search; - this.$search = $search.find('input'); - - this.$search.prop('autocomplete', this.options.get('autocomplete')); - - $rendered.prepend($search); - - return $rendered; - }; - - Search.prototype.bind = function (decorated, container, $container) { - var self = this; - - var resultsId = container.id + '-results'; - - decorated.call(this, container, $container); - - this.$search.on('keydown', function (evt) { - self.trigger('keypress', evt); - - self._keyUpPrevented = evt.isDefaultPrevented(); - }); - - // Workaround for browsers which do not support the `input` event - // This will prevent double-triggering of events for browsers which support - // both the `keyup` and `input` events. - this.$search.on('input', function (evt) { - // Unbind the duplicated `keyup` event - $(this).off('keyup'); - }); - - this.$search.on('keyup input', function (evt) { - self.handleSearch(evt); - }); - - container.on('open', function () { - self.$search.attr('tabindex', 0); - self.$search.attr('aria-controls', resultsId); - - self.$search.trigger('focus'); - - window.setTimeout(function () { - self.$search.trigger('focus'); - }, 0); - }); - - container.on('close', function () { - self.$search.attr('tabindex', -1); - self.$search.removeAttr('aria-controls'); - self.$search.removeAttr('aria-activedescendant'); - - self.$search.val(''); - self.$search.trigger('blur'); - }); - - container.on('focus', function () { - if (!container.isOpen()) { - self.$search.trigger('focus'); - } - }); - - container.on('results:all', function (params) { - if (params.query.term == null || params.query.term === '') { - var showSearch = self.showSearch(params); - - if (showSearch) { - self.$searchContainer[0].classList.remove('select2-search--hide'); - } else { - self.$searchContainer[0].classList.add('select2-search--hide'); - } - } - }); - - container.on('results:focus', function (params) { - if (params.data._resultId) { - self.$search.attr('aria-activedescendant', params.data._resultId); - } else { - self.$search.removeAttr('aria-activedescendant'); - } - }); - }; - - Search.prototype.handleSearch = function (evt) { - if (!this._keyUpPrevented) { - var input = this.$search.val(); - - this.trigger('query', { - term: input - }); - } - - this._keyUpPrevented = false; - }; - - Search.prototype.showSearch = function (_, params) { - return true; - }; - - return Search; - }); - - S2.define('select2/dropdown/hidePlaceholder',[ - - ], function () { - function HidePlaceholder (decorated, $element, options, dataAdapter) { - this.placeholder = this.normalizePlaceholder(options.get('placeholder')); - - decorated.call(this, $element, options, dataAdapter); - } - - HidePlaceholder.prototype.append = function (decorated, data) { - data.results = this.removePlaceholder(data.results); - - decorated.call(this, data); - }; - - HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) { - if (typeof placeholder === 'string') { - placeholder = { - id: '', - text: placeholder - }; - } - - return placeholder; - }; - - HidePlaceholder.prototype.removePlaceholder = function (_, data) { - var modifiedData = data.slice(0); - - for (var d = data.length - 1; d >= 0; d--) { - var item = data[d]; - - if (this.placeholder.id === item.id) { - modifiedData.splice(d, 1); - } - } - - return modifiedData; - }; - - return HidePlaceholder; - }); - - S2.define('select2/dropdown/infiniteScroll',[ - 'jquery' - ], function ($) { - function InfiniteScroll (decorated, $element, options, dataAdapter) { - this.lastParams = {}; - - decorated.call(this, $element, options, dataAdapter); - - this.$loadingMore = this.createLoadingMore(); - this.loading = false; - } - - InfiniteScroll.prototype.append = function (decorated, data) { - this.$loadingMore.remove(); - this.loading = false; - - decorated.call(this, data); - - if (this.showLoadingMore(data)) { - this.$results.append(this.$loadingMore); - this.loadMoreIfNeeded(); - } - }; - - InfiniteScroll.prototype.bind = function (decorated, container, $container) { - var self = this; - - decorated.call(this, container, $container); - - container.on('query', function (params) { - self.lastParams = params; - self.loading = true; - }); - - container.on('query:append', function (params) { - self.lastParams = params; - self.loading = true; - }); - - this.$results.on('scroll', this.loadMoreIfNeeded.bind(this)); - }; - - InfiniteScroll.prototype.loadMoreIfNeeded = function () { - var isLoadMoreVisible = $.contains( - document.documentElement, - this.$loadingMore[0] - ); - - if (this.loading || !isLoadMoreVisible) { - return; - } - - var currentOffset = this.$results.offset().top + - this.$results.outerHeight(false); - var loadingMoreOffset = this.$loadingMore.offset().top + - this.$loadingMore.outerHeight(false); - - if (currentOffset + 50 >= loadingMoreOffset) { - this.loadMore(); - } - }; - - InfiniteScroll.prototype.loadMore = function () { - this.loading = true; - - var params = $.extend({}, {page: 1}, this.lastParams); - - params.page++; - - this.trigger('query:append', params); - }; - - InfiniteScroll.prototype.showLoadingMore = function (_, data) { - return data.pagination && data.pagination.more; - }; - - InfiniteScroll.prototype.createLoadingMore = function () { - var $option = $( - '
        • ' - ); - - var message = this.options.get('translations').get('loadingMore'); - - $option.html(message(this.lastParams)); - - return $option; - }; - - return InfiniteScroll; - }); - - S2.define('select2/dropdown/attachBody',[ - 'jquery', - '../utils' - ], function ($, Utils) { - function AttachBody (decorated, $element, options) { - this.$dropdownParent = $(options.get('dropdownParent') || document.body); - - decorated.call(this, $element, options); - } - - AttachBody.prototype.bind = function (decorated, container, $container) { - var self = this; - - decorated.call(this, container, $container); - - container.on('open', function () { - self._showDropdown(); - self._attachPositioningHandler(container); - - // Must bind after the results handlers to ensure correct sizing - self._bindContainerResultHandlers(container); - }); - - container.on('close', function () { - self._hideDropdown(); - self._detachPositioningHandler(container); - }); - - this.$dropdownContainer.on('mousedown', function (evt) { - evt.stopPropagation(); - }); - }; - - AttachBody.prototype.destroy = function (decorated) { - decorated.call(this); - - this.$dropdownContainer.remove(); - }; - - AttachBody.prototype.position = function (decorated, $dropdown, $container) { - // Clone all of the container classes - $dropdown.attr('class', $container.attr('class')); - - $dropdown[0].classList.remove('select2'); - $dropdown[0].classList.add('select2-container--open'); - - $dropdown.css({ - position: 'absolute', - top: -999999 - }); - - this.$container = $container; - }; - - AttachBody.prototype.render = function (decorated) { - var $container = $(''); - - var $dropdown = decorated.call(this); - $container.append($dropdown); - - this.$dropdownContainer = $container; - - return $container; - }; - - AttachBody.prototype._hideDropdown = function (decorated) { - this.$dropdownContainer.detach(); - }; - - AttachBody.prototype._bindContainerResultHandlers = - function (decorated, container) { - - // These should only be bound once - if (this._containerResultsHandlersBound) { - return; - } - - var self = this; - - container.on('results:all', function () { - self._positionDropdown(); - self._resizeDropdown(); - }); - - container.on('results:append', function () { - self._positionDropdown(); - self._resizeDropdown(); - }); - - container.on('results:message', function () { - self._positionDropdown(); - self._resizeDropdown(); - }); - - container.on('select', function () { - self._positionDropdown(); - self._resizeDropdown(); - }); - - container.on('unselect', function () { - self._positionDropdown(); - self._resizeDropdown(); - }); - - this._containerResultsHandlersBound = true; - }; - - AttachBody.prototype._attachPositioningHandler = - function (decorated, container) { - var self = this; - - var scrollEvent = 'scroll.select2.' + container.id; - var resizeEvent = 'resize.select2.' + container.id; - var orientationEvent = 'orientationchange.select2.' + container.id; - - var $watchers = this.$container.parents().filter(Utils.hasScroll); - $watchers.each(function () { - Utils.StoreData(this, 'select2-scroll-position', { - x: $(this).scrollLeft(), - y: $(this).scrollTop() - }); - }); - - $watchers.on(scrollEvent, function (ev) { - var position = Utils.GetData(this, 'select2-scroll-position'); - $(this).scrollTop(position.y); - }); - - $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, - function (e) { - self._positionDropdown(); - self._resizeDropdown(); - }); - }; - - AttachBody.prototype._detachPositioningHandler = - function (decorated, container) { - var scrollEvent = 'scroll.select2.' + container.id; - var resizeEvent = 'resize.select2.' + container.id; - var orientationEvent = 'orientationchange.select2.' + container.id; - - var $watchers = this.$container.parents().filter(Utils.hasScroll); - $watchers.off(scrollEvent); - - $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent); - }; - - AttachBody.prototype._positionDropdown = function () { - var $window = $(window); - - var isCurrentlyAbove = this.$dropdown[0].classList - .contains('select2-dropdown--above'); - var isCurrentlyBelow = this.$dropdown[0].classList - .contains('select2-dropdown--below'); - - var newDirection = null; - - var offset = this.$container.offset(); - - offset.bottom = offset.top + this.$container.outerHeight(false); - - var container = { - height: this.$container.outerHeight(false) - }; - - container.top = offset.top; - container.bottom = offset.top + container.height; - - var dropdown = { - height: this.$dropdown.outerHeight(false) - }; - - var viewport = { - top: $window.scrollTop(), - bottom: $window.scrollTop() + $window.height() - }; - - var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); - var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); - - var css = { - left: offset.left, - top: container.bottom - }; - - // Determine what the parent element is to use for calculating the offset - var $offsetParent = this.$dropdownParent; - - // For statically positioned elements, we need to get the element - // that is determining the offset - if ($offsetParent.css('position') === 'static') { - $offsetParent = $offsetParent.offsetParent(); - } - - var parentOffset = { - top: 0, - left: 0 - }; - - if ( - $.contains(document.body, $offsetParent[0]) || - $offsetParent[0].isConnected - ) { - parentOffset = $offsetParent.offset(); - } - - css.top -= parentOffset.top; - css.left -= parentOffset.left; - - if (!isCurrentlyAbove && !isCurrentlyBelow) { - newDirection = 'below'; - } - - if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { - newDirection = 'above'; - } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { - newDirection = 'below'; - } - - if (newDirection == 'above' || - (isCurrentlyAbove && newDirection !== 'below')) { - css.top = container.top - parentOffset.top - dropdown.height; - } - - if (newDirection != null) { - this.$dropdown[0].classList.remove('select2-dropdown--below'); - this.$dropdown[0].classList.remove('select2-dropdown--above'); - this.$dropdown[0].classList.add('select2-dropdown--' + newDirection); - - this.$container[0].classList.remove('select2-container--below'); - this.$container[0].classList.remove('select2-container--above'); - this.$container[0].classList.add('select2-container--' + newDirection); - } - - this.$dropdownContainer.css(css); - }; - - AttachBody.prototype._resizeDropdown = function () { - var css = { - width: this.$container.outerWidth(false) + 'px' - }; - - if (this.options.get('dropdownAutoWidth')) { - css.minWidth = css.width; - css.position = 'relative'; - css.width = 'auto'; - } - - this.$dropdown.css(css); - }; - - AttachBody.prototype._showDropdown = function (decorated) { - this.$dropdownContainer.appendTo(this.$dropdownParent); - - this._positionDropdown(); - this._resizeDropdown(); - }; - - return AttachBody; - }); - - S2.define('select2/dropdown/minimumResultsForSearch',[ - - ], function () { - function countResults (data) { - var count = 0; - - for (var d = 0; d < data.length; d++) { - var item = data[d]; - - if (item.children) { - count += countResults(item.children); - } else { - count++; - } - } - - return count; - } - - function MinimumResultsForSearch (decorated, $element, options, dataAdapter) { - this.minimumResultsForSearch = options.get('minimumResultsForSearch'); - - if (this.minimumResultsForSearch < 0) { - this.minimumResultsForSearch = Infinity; - } - - decorated.call(this, $element, options, dataAdapter); - } - - MinimumResultsForSearch.prototype.showSearch = function (decorated, params) { - if (countResults(params.data.results) < this.minimumResultsForSearch) { - return false; - } - - return decorated.call(this, params); - }; - - return MinimumResultsForSearch; - }); - - S2.define('select2/dropdown/selectOnClose',[ - '../utils' - ], function (Utils) { - function SelectOnClose () { } - - SelectOnClose.prototype.bind = function (decorated, container, $container) { - var self = this; - - decorated.call(this, container, $container); - - container.on('close', function (params) { - self._handleSelectOnClose(params); - }); - }; - - SelectOnClose.prototype._handleSelectOnClose = function (_, params) { - if (params && params.originalSelect2Event != null) { - var event = params.originalSelect2Event; - - // Don't select an item if the close event was triggered from a select or - // unselect event - if (event._type === 'select' || event._type === 'unselect') { - return; - } - } - - var $highlightedResults = this.getHighlightedResults(); - - // Only select highlighted results - if ($highlightedResults.length < 1) { - return; - } - - var data = Utils.GetData($highlightedResults[0], 'data'); - - // Don't re-select already selected resulte - if ( - (data.element != null && data.element.selected) || - (data.element == null && data.selected) - ) { - return; - } - - this.trigger('select', { - data: data - }); - }; - - return SelectOnClose; - }); - - S2.define('select2/dropdown/closeOnSelect',[ - - ], function () { - function CloseOnSelect () { } - - CloseOnSelect.prototype.bind = function (decorated, container, $container) { - var self = this; - - decorated.call(this, container, $container); - - container.on('select', function (evt) { - self._selectTriggered(evt); - }); - - container.on('unselect', function (evt) { - self._selectTriggered(evt); - }); - }; - - CloseOnSelect.prototype._selectTriggered = function (_, evt) { - var originalEvent = evt.originalEvent; - - // Don't close if the control key is being held - if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) { - return; - } - - this.trigger('close', { - originalEvent: originalEvent, - originalSelect2Event: evt - }); - }; - - return CloseOnSelect; - }); - - S2.define('select2/dropdown/dropdownCss',[ - '../utils' - ], function (Utils) { - function DropdownCSS () { } - - DropdownCSS.prototype.render = function (decorated) { - var $dropdown = decorated.call(this); - - var dropdownCssClass = this.options.get('dropdownCssClass') || ''; - - if (dropdownCssClass.indexOf(':all:') !== -1) { - dropdownCssClass = dropdownCssClass.replace(':all:', ''); - - Utils.copyNonInternalCssClasses($dropdown[0], this.$element[0]); - } - - $dropdown.addClass(dropdownCssClass); - - return $dropdown; - }; - - return DropdownCSS; - }); - - S2.define('select2/i18n/en',[],function () { - // English - return { - errorLoading: function () { - return 'The results could not be loaded.'; - }, - inputTooLong: function (args) { - var overChars = args.input.length - args.maximum; - - var message = 'Please delete ' + overChars + ' character'; - - if (overChars != 1) { - message += 's'; - } - - return message; - }, - inputTooShort: function (args) { - var remainingChars = args.minimum - args.input.length; - - var message = 'Please enter ' + remainingChars + ' or more characters'; - - return message; - }, - loadingMore: function () { - return 'Loading more results…'; - }, - maximumSelected: function (args) { - var message = 'You can only select ' + args.maximum + ' item'; - - if (args.maximum != 1) { - message += 's'; - } - - return message; - }, - noResults: function () { - return 'No results found'; - }, - searching: function () { - return 'Searching…'; - }, - removeAllItems: function () { - return 'Remove all items'; - }, - removeItem: function () { - return 'Remove item'; - } - }; - }); - - S2.define('select2/defaults',[ - 'jquery', - - './results', - - './selection/single', - './selection/multiple', - './selection/placeholder', - './selection/allowClear', - './selection/search', - './selection/selectionCss', - './selection/eventRelay', - - './utils', - './translation', - './diacritics', - - './data/select', - './data/array', - './data/ajax', - './data/tags', - './data/tokenizer', - './data/minimumInputLength', - './data/maximumInputLength', - './data/maximumSelectionLength', - - './dropdown', - './dropdown/search', - './dropdown/hidePlaceholder', - './dropdown/infiniteScroll', - './dropdown/attachBody', - './dropdown/minimumResultsForSearch', - './dropdown/selectOnClose', - './dropdown/closeOnSelect', - './dropdown/dropdownCss', - - './i18n/en' - ], function ($, - - ResultsList, - - SingleSelection, MultipleSelection, Placeholder, AllowClear, - SelectionSearch, SelectionCSS, EventRelay, - - Utils, Translation, DIACRITICS, - - SelectData, ArrayData, AjaxData, Tags, Tokenizer, - MinimumInputLength, MaximumInputLength, MaximumSelectionLength, - - Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, - AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, - DropdownCSS, - - EnglishTranslation) { - function Defaults () { - this.reset(); - } - - Defaults.prototype.apply = function (options) { - options = $.extend(true, {}, this.defaults, options); - - if (options.dataAdapter == null) { - if (options.ajax != null) { - options.dataAdapter = AjaxData; - } else if (options.data != null) { - options.dataAdapter = ArrayData; - } else { - options.dataAdapter = SelectData; - } - - if (options.minimumInputLength > 0) { - options.dataAdapter = Utils.Decorate( - options.dataAdapter, - MinimumInputLength - ); - } - - if (options.maximumInputLength > 0) { - options.dataAdapter = Utils.Decorate( - options.dataAdapter, - MaximumInputLength - ); - } - - if (options.maximumSelectionLength > 0) { - options.dataAdapter = Utils.Decorate( - options.dataAdapter, - MaximumSelectionLength - ); - } - - if (options.tags) { - options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); - } - - if (options.tokenSeparators != null || options.tokenizer != null) { - options.dataAdapter = Utils.Decorate( - options.dataAdapter, - Tokenizer - ); - } - } - - if (options.resultsAdapter == null) { - options.resultsAdapter = ResultsList; - - if (options.ajax != null) { - options.resultsAdapter = Utils.Decorate( - options.resultsAdapter, - InfiniteScroll - ); - } - - if (options.placeholder != null) { - options.resultsAdapter = Utils.Decorate( - options.resultsAdapter, - HidePlaceholder - ); - } - - if (options.selectOnClose) { - options.resultsAdapter = Utils.Decorate( - options.resultsAdapter, - SelectOnClose - ); - } - } - - if (options.dropdownAdapter == null) { - if (options.multiple) { - options.dropdownAdapter = Dropdown; - } else { - var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch); - - options.dropdownAdapter = SearchableDropdown; - } - - if (options.minimumResultsForSearch !== 0) { - options.dropdownAdapter = Utils.Decorate( - options.dropdownAdapter, - MinimumResultsForSearch - ); - } - - if (options.closeOnSelect) { - options.dropdownAdapter = Utils.Decorate( - options.dropdownAdapter, - CloseOnSelect - ); - } - - if (options.dropdownCssClass != null) { - options.dropdownAdapter = Utils.Decorate( - options.dropdownAdapter, - DropdownCSS - ); - } - - options.dropdownAdapter = Utils.Decorate( - options.dropdownAdapter, - AttachBody - ); - } - - if (options.selectionAdapter == null) { - if (options.multiple) { - options.selectionAdapter = MultipleSelection; - } else { - options.selectionAdapter = SingleSelection; - } - - // Add the placeholder mixin if a placeholder was specified - if (options.placeholder != null) { - options.selectionAdapter = Utils.Decorate( - options.selectionAdapter, - Placeholder - ); - } - - if (options.allowClear) { - options.selectionAdapter = Utils.Decorate( - options.selectionAdapter, - AllowClear - ); - } - - if (options.multiple) { - options.selectionAdapter = Utils.Decorate( - options.selectionAdapter, - SelectionSearch - ); - } - - if (options.selectionCssClass != null) { - options.selectionAdapter = Utils.Decorate( - options.selectionAdapter, - SelectionCSS - ); - } - - options.selectionAdapter = Utils.Decorate( - options.selectionAdapter, - EventRelay - ); - } - - // If the defaults were not previously applied from an element, it is - // possible for the language option to have not been resolved - options.language = this._resolveLanguage(options.language); - - // Always fall back to English since it will always be complete - options.language.push('en'); - - var uniqueLanguages = []; - - for (var l = 0; l < options.language.length; l++) { - var language = options.language[l]; - - if (uniqueLanguages.indexOf(language) === -1) { - uniqueLanguages.push(language); - } - } - - options.language = uniqueLanguages; - - options.translations = this._processTranslations( - options.language, - options.debug - ); - - return options; - }; - - Defaults.prototype.reset = function () { - function stripDiacritics (text) { - // Used 'uni range + named function' from http://jsperf.com/diacritics/18 - function match(a) { - return DIACRITICS[a] || a; - } - - return text.replace(/[^\u0000-\u007E]/g, match); - } - - function matcher (params, data) { - // Always return the object if there is nothing to compare - if (params.term == null || params.term.trim() === '') { - return data; - } - - // Do a recursive check for options with children - if (data.children && data.children.length > 0) { - // Clone the data object if there are children - // This is required as we modify the object to remove any non-matches - var match = $.extend(true, {}, data); - - // Check each child of the option - for (var c = data.children.length - 1; c >= 0; c--) { - var child = data.children[c]; - - var matches = matcher(params, child); - - // If there wasn't a match, remove the object in the array - if (matches == null) { - match.children.splice(c, 1); - } - } - - // If any children matched, return the new object - if (match.children.length > 0) { - return match; - } - - // If there were no matching children, check just the plain object - return matcher(params, match); - } - - var original = stripDiacritics(data.text).toUpperCase(); - var term = stripDiacritics(params.term).toUpperCase(); - - // Check if the text contains the term - if (original.indexOf(term) > -1) { - return data; - } - - // If it doesn't contain the term, don't return anything - return null; - } - - this.defaults = { - amdLanguageBase: './i18n/', - autocomplete: 'off', - closeOnSelect: true, - debug: false, - dropdownAutoWidth: false, - escapeMarkup: Utils.escapeMarkup, - language: {}, - matcher: matcher, - minimumInputLength: 0, - maximumInputLength: 0, - maximumSelectionLength: 0, - minimumResultsForSearch: 0, - selectOnClose: false, - scrollAfterSelect: false, - sorter: function (data) { - return data; - }, - templateResult: function (result) { - return result.text; - }, - templateSelection: function (selection) { - return selection.text; - }, - theme: 'default', - width: 'resolve' - }; - }; - - Defaults.prototype.applyFromElement = function (options, $element) { - var optionLanguage = options.language; - var defaultLanguage = this.defaults.language; - var elementLanguage = $element.prop('lang'); - var parentLanguage = $element.closest('[lang]').prop('lang'); - - var languages = Array.prototype.concat.call( - this._resolveLanguage(elementLanguage), - this._resolveLanguage(optionLanguage), - this._resolveLanguage(defaultLanguage), - this._resolveLanguage(parentLanguage) - ); - - options.language = languages; - - return options; - }; - - Defaults.prototype._resolveLanguage = function (language) { - if (!language) { - return []; - } - - if ($.isEmptyObject(language)) { - return []; - } - - if ($.isPlainObject(language)) { - return [language]; - } - - var languages; - - if (!Array.isArray(language)) { - languages = [language]; - } else { - languages = language; - } - - var resolvedLanguages = []; - - for (var l = 0; l < languages.length; l++) { - resolvedLanguages.push(languages[l]); - - if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) { - // Extract the region information if it is included - var languageParts = languages[l].split('-'); - var baseLanguage = languageParts[0]; - - resolvedLanguages.push(baseLanguage); - } - } - - return resolvedLanguages; - }; - - Defaults.prototype._processTranslations = function (languages, debug) { - var translations = new Translation(); - - for (var l = 0; l < languages.length; l++) { - var languageData = new Translation(); - - var language = languages[l]; - - if (typeof language === 'string') { - try { - // Try to load it with the original name - languageData = Translation.loadPath(language); - } catch (e) { - try { - // If we couldn't load it, check if it wasn't the full path - language = this.defaults.amdLanguageBase + language; - languageData = Translation.loadPath(language); - } catch (ex) { - // The translation could not be loaded at all. Sometimes this is - // because of a configuration problem, other times this can be - // because of how Select2 helps load all possible translation files - if (debug && window.console && console.warn) { - console.warn( - 'Select2: The language file for "' + language + '" could ' + - 'not be automatically loaded. A fallback will be used instead.' - ); - } - } - } - } else if ($.isPlainObject(language)) { - languageData = new Translation(language); - } else { - languageData = language; - } - - translations.extend(languageData); - } - - return translations; - }; - - Defaults.prototype.set = function (key, value) { - var camelKey = $.camelCase(key); - - var data = {}; - data[camelKey] = value; - - var convertedData = Utils._convertData(data); - - $.extend(true, this.defaults, convertedData); - }; - - var defaults = new Defaults(); - - return defaults; - }); - - S2.define('select2/options',[ - 'jquery', - './defaults', - './utils' - ], function ($, Defaults, Utils) { - function Options (options, $element) { - this.options = options; - - if ($element != null) { - this.fromElement($element); - } - - if ($element != null) { - this.options = Defaults.applyFromElement(this.options, $element); - } - - this.options = Defaults.apply(this.options); - } - - Options.prototype.fromElement = function ($e) { - var excludedData = ['select2']; - - if (this.options.multiple == null) { - this.options.multiple = $e.prop('multiple'); - } - - if (this.options.disabled == null) { - this.options.disabled = $e.prop('disabled'); - } - - if (this.options.autocomplete == null && $e.prop('autocomplete')) { - this.options.autocomplete = $e.prop('autocomplete'); - } - - if (this.options.dir == null) { - if ($e.prop('dir')) { - this.options.dir = $e.prop('dir'); - } else if ($e.closest('[dir]').prop('dir')) { - this.options.dir = $e.closest('[dir]').prop('dir'); - } else { - this.options.dir = 'ltr'; - } - } - - $e.prop('disabled', this.options.disabled); - $e.prop('multiple', this.options.multiple); - - if (Utils.GetData($e[0], 'select2Tags')) { - if (this.options.debug && window.console && console.warn) { - console.warn( - 'Select2: The `data-select2-tags` attribute has been changed to ' + - 'use the `data-data` and `data-tags="true"` attributes and will be ' + - 'removed in future versions of Select2.' - ); - } - - Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags')); - Utils.StoreData($e[0], 'tags', true); - } - - if (Utils.GetData($e[0], 'ajaxUrl')) { - if (this.options.debug && window.console && console.warn) { - console.warn( - 'Select2: The `data-ajax-url` attribute has been changed to ' + - '`data-ajax--url` and support for the old attribute will be removed' + - ' in future versions of Select2.' - ); - } - - $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl')); - Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl')); - } - - var dataset = {}; - - function upperCaseLetter(_, letter) { - return letter.toUpperCase(); - } - - // Pre-load all of the attributes which are prefixed with `data-` - for (var attr = 0; attr < $e[0].attributes.length; attr++) { - var attributeName = $e[0].attributes[attr].name; - var prefix = 'data-'; - - if (attributeName.substr(0, prefix.length) == prefix) { - // Get the contents of the attribute after `data-` - var dataName = attributeName.substring(prefix.length); - - // Get the data contents from the consistent source - // This is more than likely the jQuery data helper - var dataValue = Utils.GetData($e[0], dataName); - - // camelCase the attribute name to match the spec - var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter); - - // Store the data attribute contents into the dataset since - dataset[camelDataName] = dataValue; - } - } - - // Prefer the element's `dataset` attribute if it exists - // jQuery 1.x does not correctly handle data attributes with multiple dashes - if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { - dataset = $.extend(true, {}, $e[0].dataset, dataset); - } - - // Prefer our internal data cache if it exists - var data = $.extend(true, {}, Utils.GetData($e[0]), dataset); - - data = Utils._convertData(data); - - for (var key in data) { - if (excludedData.indexOf(key) > -1) { - continue; - } - - if ($.isPlainObject(this.options[key])) { - $.extend(this.options[key], data[key]); - } else { - this.options[key] = data[key]; - } - } - - return this; - }; - - Options.prototype.get = function (key) { - return this.options[key]; - }; - - Options.prototype.set = function (key, val) { - this.options[key] = val; - }; - - return Options; - }); - - S2.define('select2/core',[ - 'jquery', - './options', - './utils', - './keys' - ], function ($, Options, Utils, KEYS) { - var Select2 = function ($element, options) { - if (Utils.GetData($element[0], 'select2') != null) { - Utils.GetData($element[0], 'select2').destroy(); - } - - this.$element = $element; - - this.id = this._generateId($element); - - options = options || {}; - - this.options = new Options(options, $element); - - Select2.__super__.constructor.call(this); - - // Set up the tabindex - - var tabindex = $element.attr('tabindex') || 0; - Utils.StoreData($element[0], 'old-tabindex', tabindex); - $element.attr('tabindex', '-1'); - - // Set up containers and adapters - - var DataAdapter = this.options.get('dataAdapter'); - this.dataAdapter = new DataAdapter($element, this.options); - - var $container = this.render(); - - this._placeContainer($container); - - var SelectionAdapter = this.options.get('selectionAdapter'); - this.selection = new SelectionAdapter($element, this.options); - this.$selection = this.selection.render(); - - this.selection.position(this.$selection, $container); - - var DropdownAdapter = this.options.get('dropdownAdapter'); - this.dropdown = new DropdownAdapter($element, this.options); - this.$dropdown = this.dropdown.render(); - - this.dropdown.position(this.$dropdown, $container); - - var ResultsAdapter = this.options.get('resultsAdapter'); - this.results = new ResultsAdapter($element, this.options, this.dataAdapter); - this.$results = this.results.render(); - - this.results.position(this.$results, this.$dropdown); - - // Bind events - - var self = this; - - // Bind the container to all of the adapters - this._bindAdapters(); - - // Register any DOM event handlers - this._registerDomEvents(); - - // Register any internal event handlers - this._registerDataEvents(); - this._registerSelectionEvents(); - this._registerDropdownEvents(); - this._registerResultsEvents(); - this._registerEvents(); - - // Set the initial state - this.dataAdapter.current(function (initialData) { - self.trigger('selection:update', { - data: initialData - }); - }); - - // Hide the original select - $element[0].classList.add('select2-hidden-accessible'); - $element.attr('aria-hidden', 'true'); - - // Synchronize any monitored attributes - this._syncAttributes(); - - Utils.StoreData($element[0], 'select2', this); - - // Ensure backwards compatibility with $element.data('select2'). - $element.data('select2', this); - }; - - Utils.Extend(Select2, Utils.Observable); - - Select2.prototype._generateId = function ($element) { - var id = ''; - - if ($element.attr('id') != null) { - id = $element.attr('id'); - } else if ($element.attr('name') != null) { - id = $element.attr('name') + '-' + Utils.generateChars(2); - } else { - id = Utils.generateChars(4); - } - - id = id.replace(/(:|\.|\[|\]|,)/g, ''); - id = 'select2-' + id; - - return id; - }; - - Select2.prototype._placeContainer = function ($container) { - $container.insertAfter(this.$element); - - var width = this._resolveWidth(this.$element, this.options.get('width')); - - if (width != null) { - $container.css('width', width); - } - }; - - Select2.prototype._resolveWidth = function ($element, method) { - var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; - - if (method == 'resolve') { - var styleWidth = this._resolveWidth($element, 'style'); - - if (styleWidth != null) { - return styleWidth; - } - - return this._resolveWidth($element, 'element'); - } - - if (method == 'element') { - var elementWidth = $element.outerWidth(false); - - if (elementWidth <= 0) { - return 'auto'; - } - - return elementWidth + 'px'; - } - - if (method == 'style') { - var style = $element.attr('style'); - - if (typeof(style) !== 'string') { - return null; - } - - var attrs = style.split(';'); - - for (var i = 0, l = attrs.length; i < l; i = i + 1) { - var attr = attrs[i].replace(/\s/g, ''); - var matches = attr.match(WIDTH); - - if (matches !== null && matches.length >= 1) { - return matches[1]; - } - } - - return null; - } - - if (method == 'computedstyle') { - var computedStyle = window.getComputedStyle($element[0]); - - return computedStyle.width; - } - - return method; - }; - - Select2.prototype._bindAdapters = function () { - this.dataAdapter.bind(this, this.$container); - this.selection.bind(this, this.$container); - - this.dropdown.bind(this, this.$container); - this.results.bind(this, this.$container); - }; - - Select2.prototype._registerDomEvents = function () { - var self = this; - - this.$element.on('change.select2', function () { - self.dataAdapter.current(function (data) { - self.trigger('selection:update', { - data: data - }); - }); - }); - - this.$element.on('focus.select2', function (evt) { - self.trigger('focus', evt); - }); - - this._syncA = Utils.bind(this._syncAttributes, this); - this._syncS = Utils.bind(this._syncSubtree, this); - - this._observer = new window.MutationObserver(function (mutations) { - self._syncA(); - self._syncS(mutations); - }); - this._observer.observe(this.$element[0], { - attributes: true, - childList: true, - subtree: false - }); - }; - - Select2.prototype._registerDataEvents = function () { - var self = this; - - this.dataAdapter.on('*', function (name, params) { - self.trigger(name, params); - }); - }; - - Select2.prototype._registerSelectionEvents = function () { - var self = this; - var nonRelayEvents = ['toggle', 'focus']; - - this.selection.on('toggle', function () { - self.toggleDropdown(); - }); - - this.selection.on('focus', function (params) { - self.focus(params); - }); - - this.selection.on('*', function (name, params) { - if (nonRelayEvents.indexOf(name) !== -1) { - return; - } - - self.trigger(name, params); - }); - }; - - Select2.prototype._registerDropdownEvents = function () { - var self = this; - - this.dropdown.on('*', function (name, params) { - self.trigger(name, params); - }); - }; - - Select2.prototype._registerResultsEvents = function () { - var self = this; - - this.results.on('*', function (name, params) { - self.trigger(name, params); - }); - }; - - Select2.prototype._registerEvents = function () { - var self = this; - - this.on('open', function () { - self.$container[0].classList.add('select2-container--open'); - }); - - this.on('close', function () { - self.$container[0].classList.remove('select2-container--open'); - }); - - this.on('enable', function () { - self.$container[0].classList.remove('select2-container--disabled'); - }); - - this.on('disable', function () { - self.$container[0].classList.add('select2-container--disabled'); - }); - - this.on('blur', function () { - self.$container[0].classList.remove('select2-container--focus'); - }); - - this.on('query', function (params) { - if (!self.isOpen()) { - self.trigger('open', {}); - } - - this.dataAdapter.query(params, function (data) { - self.trigger('results:all', { - data: data, - query: params - }); - }); - }); - - this.on('query:append', function (params) { - this.dataAdapter.query(params, function (data) { - self.trigger('results:append', { - data: data, - query: params - }); - }); - }); - - this.on('keypress', function (evt) { - var key = evt.which; - - if (self.isOpen()) { - if (key === KEYS.ESC || key === KEYS.TAB || - (key === KEYS.UP && evt.altKey)) { - self.close(evt); - - evt.preventDefault(); - } else if (key === KEYS.ENTER) { - self.trigger('results:select', {}); - - evt.preventDefault(); - } else if ((key === KEYS.SPACE && evt.ctrlKey)) { - self.trigger('results:toggle', {}); - - evt.preventDefault(); - } else if (key === KEYS.UP) { - self.trigger('results:previous', {}); - - evt.preventDefault(); - } else if (key === KEYS.DOWN) { - self.trigger('results:next', {}); - - evt.preventDefault(); - } - } else { - if (key === KEYS.ENTER || key === KEYS.SPACE || - (key === KEYS.DOWN && evt.altKey)) { - self.open(); - - evt.preventDefault(); - } - } - }); - }; - - Select2.prototype._syncAttributes = function () { - this.options.set('disabled', this.$element.prop('disabled')); - - if (this.isDisabled()) { - if (this.isOpen()) { - this.close(); - } - - this.trigger('disable', {}); - } else { - this.trigger('enable', {}); - } - }; - - Select2.prototype._isChangeMutation = function (mutations) { - var self = this; - - if (mutations.addedNodes && mutations.addedNodes.length > 0) { - for (var n = 0; n < mutations.addedNodes.length; n++) { - var node = mutations.addedNodes[n]; - - if (node.selected) { - return true; - } - } - } else if (mutations.removedNodes && mutations.removedNodes.length > 0) { - return true; - } else if (Array.isArray(mutations)) { - return mutations.some(function (mutation) { - return self._isChangeMutation(mutation); - }); - } - - return false; - }; - - Select2.prototype._syncSubtree = function (mutations) { - var changed = this._isChangeMutation(mutations); - var self = this; - - // Only re-pull the data if we think there is a change - if (changed) { - this.dataAdapter.current(function (currentData) { - self.trigger('selection:update', { - data: currentData - }); - }); - } - }; - - /** - * Override the trigger method to automatically trigger pre-events when - * there are events that can be prevented. - */ - Select2.prototype.trigger = function (name, args) { - var actualTrigger = Select2.__super__.trigger; - var preTriggerMap = { - 'open': 'opening', - 'close': 'closing', - 'select': 'selecting', - 'unselect': 'unselecting', - 'clear': 'clearing' - }; - - if (args === undefined) { - args = {}; - } - - if (name in preTriggerMap) { - var preTriggerName = preTriggerMap[name]; - var preTriggerArgs = { - prevented: false, - name: name, - args: args - }; - - actualTrigger.call(this, preTriggerName, preTriggerArgs); - - if (preTriggerArgs.prevented) { - args.prevented = true; - - return; - } - } - - actualTrigger.call(this, name, args); - }; - - Select2.prototype.toggleDropdown = function () { - if (this.isDisabled()) { - return; - } - - if (this.isOpen()) { - this.close(); - } else { - this.open(); - } - }; - - Select2.prototype.open = function () { - if (this.isOpen()) { - return; - } - - if (this.isDisabled()) { - return; - } - - this.trigger('query', {}); - }; - - Select2.prototype.close = function (evt) { - if (!this.isOpen()) { - return; - } - - this.trigger('close', { originalEvent : evt }); - }; - - /** - * Helper method to abstract the "enabled" (not "disabled") state of this - * object. - * - * @return {true} if the instance is not disabled. - * @return {false} if the instance is disabled. - */ - Select2.prototype.isEnabled = function () { - return !this.isDisabled(); - }; - - /** - * Helper method to abstract the "disabled" state of this object. - * - * @return {true} if the disabled option is true. - * @return {false} if the disabled option is false. - */ - Select2.prototype.isDisabled = function () { - return this.options.get('disabled'); - }; - - Select2.prototype.isOpen = function () { - return this.$container[0].classList.contains('select2-container--open'); - }; - - Select2.prototype.hasFocus = function () { - return this.$container[0].classList.contains('select2-container--focus'); - }; - - Select2.prototype.focus = function (data) { - // No need to re-trigger focus events if we are already focused - if (this.hasFocus()) { - return; - } - - this.$container[0].classList.add('select2-container--focus'); - this.trigger('focus', {}); - }; - - Select2.prototype.enable = function (args) { - if (this.options.get('debug') && window.console && console.warn) { - console.warn( - 'Select2: The `select2("enable")` method has been deprecated and will' + - ' be removed in later Select2 versions. Use $element.prop("disabled")' + - ' instead.' - ); - } - - if (args == null || args.length === 0) { - args = [true]; - } - - var disabled = !args[0]; - - this.$element.prop('disabled', disabled); - }; - - Select2.prototype.data = function () { - if (this.options.get('debug') && - arguments.length > 0 && window.console && console.warn) { - console.warn( - 'Select2: Data can no longer be set using `select2("data")`. You ' + - 'should consider setting the value instead using `$element.val()`.' - ); - } - - var data = []; - - this.dataAdapter.current(function (currentData) { - data = currentData; - }); - - return data; - }; - - Select2.prototype.val = function (args) { - if (this.options.get('debug') && window.console && console.warn) { - console.warn( - 'Select2: The `select2("val")` method has been deprecated and will be' + - ' removed in later Select2 versions. Use $element.val() instead.' - ); - } - - if (args == null || args.length === 0) { - return this.$element.val(); - } - - var newVal = args[0]; - - if (Array.isArray(newVal)) { - newVal = newVal.map(function (obj) { - return obj.toString(); - }); - } - - this.$element.val(newVal).trigger('input').trigger('change'); - }; - - Select2.prototype.destroy = function () { - this.$container.remove(); - - this._observer.disconnect(); - this._observer = null; - - this._syncA = null; - this._syncS = null; - - this.$element.off('.select2'); - this.$element.attr('tabindex', - Utils.GetData(this.$element[0], 'old-tabindex')); - - this.$element[0].classList.remove('select2-hidden-accessible'); - this.$element.attr('aria-hidden', 'false'); - Utils.RemoveData(this.$element[0]); - this.$element.removeData('select2'); - - this.dataAdapter.destroy(); - this.selection.destroy(); - this.dropdown.destroy(); - this.results.destroy(); - - this.dataAdapter = null; - this.selection = null; - this.dropdown = null; - this.results = null; - }; - - Select2.prototype.render = function () { - var $container = $( - '' + - '' + - '' + - '' - ); - - $container.attr('dir', this.options.get('dir')); - - this.$container = $container; - - this.$container[0].classList - .add('select2-container--' + this.options.get('theme')); - - Utils.StoreData($container[0], 'element', this.$element); - - return $container; - }; - - return Select2; - }); - - S2.define('jquery-mousewheel',[ - 'jquery' - ], function ($) { - // Used to shim jQuery.mousewheel for non-full builds. - return $; - }); - - S2.define('jquery.select2',[ - 'jquery', - 'jquery-mousewheel', - - './select2/core', - './select2/defaults', - './select2/utils' - ], function ($, _, Select2, Defaults, Utils) { - if ($.fn.select2 == null) { - // All methods that should return the element - var thisMethods = ['open', 'close', 'destroy']; - - $.fn.select2 = function (options) { - options = options || {}; - - if (typeof options === 'object') { - this.each(function () { - var instanceOptions = $.extend(true, {}, options); - - var instance = new Select2($(this), instanceOptions); - }); - - return this; - } else if (typeof options === 'string') { - var ret; - var args = Array.prototype.slice.call(arguments, 1); - - this.each(function () { - var instance = Utils.GetData(this, 'select2'); - - if (instance == null && window.console && console.error) { - console.error( - 'The select2(\'' + options + '\') method was called on an ' + - 'element that is not using Select2.' - ); - } - - ret = instance[options].apply(instance, args); - }); - - // Check if we should be returning `this` - if (thisMethods.indexOf(options) > -1) { - return this; - } - - return ret; - } else { - throw new Error('Invalid arguments for Select2: ' + options); - } - }; - } - - if ($.fn.select2.defaults == null) { - $.fn.select2.defaults = Defaults; - } - - return Select2; - }); - - // Return the AMD loader configuration so it can be used outside of this file - return { - define: S2.define, - require: S2.require - }; - }()); - - // Autoload the jQuery bindings - // We know that all of the modules exist above this, so we're safe - var select2 = S2.require('jquery.select2'); - - // Hold the AMD module references on the jQuery function that was just loaded - // This allows Select2 to use the internal loader outside of this file, such - // as in the language files. - jQuery.fn.select2.amd = S2; - - // Return the Select2 instance for anyone who is importing it. - return select2; -})); diff --git a/obp-api/src/main/webapp/media/js/select2.min.js b/obp-api/src/main/webapp/media/js/select2.min.js new file mode 100644 index 000000000..fd88a10fe --- /dev/null +++ b/obp-api/src/main/webapp/media/js/select2.min.js @@ -0,0 +1 @@ +;(function(factory){if(typeof define==='function'&&define.amd){define(['jquery'],factory)}else if(typeof module==='object'&&module.exports){module.exports=function(root,jQuery){if(jQuery===undefined){if(typeof window!=='undefined'){jQuery=require('jquery')}else{jQuery=require('jquery')(root)}}factory(jQuery);return jQuery}}else{factory(jQuery)}}(function(jQuery){var S2=(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd){var S2=jQuery.fn.select2.amd}var S2;(function(){if(!S2||!S2.requirejs){if(!S2){S2={}}else{require=S2}var requirejs,require,define;(function(undef){var main,req,makeMap,handlers,defined={},waiting={},config={},defining={},hasOwn=Object.prototype.hasOwnProperty,aps=[].slice,jsSuffixRegExp=/\.js$/;function hasProp(obj,prop){return hasOwn.call(obj,prop)}function normalize(name,baseName){var nameParts,nameSegment,mapValue,foundMap,lastIndex,foundI,foundStarMap,starI,i,j,part,normalizedBaseParts,baseParts=baseName&&baseName.split("/"),map=config.map,starMap=(map&&map['*'])||{};if(name){name=name.split('/');lastIndex=name.length-1;if(config.nodeIdCompat&&jsSuffixRegExp.test(name[lastIndex])){name[lastIndex]=name[lastIndex].replace(jsSuffixRegExp,'')}if(name[0].charAt(0)==='.'&&baseParts){normalizedBaseParts=baseParts.slice(0,baseParts.length-1);name=normalizedBaseParts.concat(name)}for(i=0;i0){name.splice(i-1,2);i-=2}}}name=name.join('/')}if((baseParts||starMap)&&map){nameParts=name.split('/');for(i=nameParts.length;i>0;i-=1){nameSegment=nameParts.slice(0,i).join("/");if(baseParts){for(j=baseParts.length;j>0;j-=1){mapValue=map[baseParts.slice(0,j).join('/')];if(mapValue){mapValue=mapValue[nameSegment];if(mapValue){foundMap=mapValue;foundI=i;break}}}}if(foundMap){break}if(!foundStarMap&&starMap&&starMap[nameSegment]){foundStarMap=starMap[nameSegment];starI=i}}if(!foundMap&&foundStarMap){foundMap=foundStarMap;foundI=starI}if(foundMap){nameParts.splice(0,foundI,foundMap);name=nameParts.join('/')}}return name}function makeRequire(relName,forceSync){return function(){var args=aps.call(arguments,0);if(typeof args[0]!=='string'&&args.length===1){args.push(null)}return req.apply(undef,args.concat([relName,forceSync]))}}function makeNormalize(relName){return function(name){return normalize(name,relName)}}function makeLoad(depName){return function(value){defined[depName]=value}}function callDep(name){if(hasProp(waiting,name)){var args=waiting[name];delete waiting[name];defining[name]=true;main.apply(undef,args)}if(!hasProp(defined,name)&&!hasProp(defining,name)){throw new Error('No '+name);}return defined[name]}function splitPrefix(name){var prefix,index=name?name.indexOf('!'):-1;if(index>-1){prefix=name.substring(0,index);name=name.substring(index+1,name.length)}return[prefix,name]}function makeRelParts(relName){return relName?splitPrefix(relName):[]}makeMap=function(name,relParts){var plugin,parts=splitPrefix(name),prefix=parts[0],relResourceName=relParts[1];name=parts[1];if(prefix){prefix=normalize(prefix,relResourceName);plugin=callDep(prefix)}if(prefix){if(plugin&&plugin.normalize){name=plugin.normalize(name,makeNormalize(relResourceName))}else{name=normalize(name,relResourceName)}}else{name=normalize(name,relResourceName);parts=splitPrefix(name);prefix=parts[0];name=parts[1];if(prefix){plugin=callDep(prefix)}}return{f:prefix?prefix+'!'+name:name,n:name,pr:prefix,p:plugin}};function makeConfig(name){return function(){return(config&&config.config&&config.config[name])||{}}}handlers={require:function(name){return makeRequire(name)},exports:function(name){var e=defined[name];if(typeof e!=='undefined'){return e}else{return(defined[name]={})}},module:function(name){return{id:name,uri:'',exports:defined[name],config:makeConfig(name)}}};main=function(name,deps,callback,relName){var cjsModule,depName,ret,map,i,relParts,args=[],callbackType=typeof callback,usingExports;relName=relName||name;relParts=makeRelParts(relName);if(callbackType==='undefined'||callbackType==='function'){deps=!deps.length&&callback.length?['require','exports','module']:deps;for(i=0;i0){unshift.call(arguments,SuperClass.prototype.constructor);calledConstructor=DecoratorClass.prototype.constructor}calledConstructor.apply(this,arguments)}DecoratorClass.displayName=SuperClass.displayName;function ctr(){this.constructor=DecoratedClass}DecoratedClass.prototype=new ctr();for(var m=0;m':'>','"':'"','\'':''','/':'/'};if(typeof markup!=='string'){return markup}return String(markup).replace(/[&<>"'\/\\]/g,function(match){return replaceMap[match]})};Utils.appendMany=function($element,$nodes){if($.fn.jquery.substr(0,3)==='1.7'){var $jqNodes=$();$.map($nodes,function(node){$jqNodes=$jqNodes.add(node)});$nodes=$jqNodes}$element.append($nodes)};Utils.__cache={};var id=0;Utils.GetUniqueElementId=function(element){var select2Id=element.getAttribute('data-select2-id');if(select2Id==null){if(element.id){select2Id=element.id;element.setAttribute('data-select2-id',select2Id)}else{element.setAttribute('data-select2-id',++id);select2Id=id.toString()}}return select2Id};Utils.StoreData=function(element,name,value){var id=Utils.GetUniqueElementId(element);if(!Utils.__cache[id]){Utils.__cache[id]={}}Utils.__cache[id][name]=value};Utils.GetData=function(element,name){var id=Utils.GetUniqueElementId(element);if(name){if(Utils.__cache[id]){if(Utils.__cache[id][name]!=null){return Utils.__cache[id][name]}return $(element).data(name)}return $(element).data(name)}else{return Utils.__cache[id]}};Utils.RemoveData=function(element){var id=Utils.GetUniqueElementId(element);if(Utils.__cache[id]!=null){delete Utils.__cache[id]}element.removeAttribute('data-select2-id')};return Utils});S2.define('select2/results',['jquery','./utils'],function($,Utils){function Results($element,options,dataAdapter){this.$element=$element;this.data=dataAdapter;this.options=options;Results.__super__.constructor.call(this)}Utils.Extend(Results,Utils.Observable);Results.prototype.render=function(){var $results=$('
            ');if(this.options.get('multiple')){$results.attr('aria-multiselectable','true')}this.$results=$results;return $results};Results.prototype.clear=function(){this.$results.empty()};Results.prototype.displayMessage=function(params){var escapeMarkup=this.options.get('escapeMarkup');this.clear();this.hideLoading();var $message=$('');var message=this.options.get('translations').get(params.message);$message.append(escapeMarkup(message(params.args)));$message[0].className+=' select2-results__message';this.$results.append($message)};Results.prototype.hideMessages=function(){this.$results.find('.select2-results__message').remove()};Results.prototype.append=function(data){this.hideLoading();var $options=[];if(data.results==null||data.results.length===0){if(this.$results.children().length===0){this.trigger('results:message',{message:'noResults'})}return}data.results=this.sort(data.results);for(var d=0;d0){$selected.first().trigger('mouseenter')}else{$options.first().trigger('mouseenter')}this.ensureHighlightVisible()};Results.prototype.setClasses=function(){var self=this;this.data.current(function(selected){var selectedIds=$.map(selected,function(s){return s.id.toString()});var $options=self.$results.find('.select2-results__option[aria-selected]');$options.each(function(){var $option=$(this);var item=Utils.GetData(this,'data');var id=''+item.id;if((item.element!=null&&item.element.selected)||(item.element==null&&$.inArray(id,selectedIds)>-1)){$option.attr('aria-selected','true')}else{$option.attr('aria-selected','false')}})})};Results.prototype.showLoading=function(params){this.hideLoading();var loadingMore=this.options.get('translations').get('searching');var loading={disabled:true,loading:true,text:loadingMore(params)};var $loading=this.option(loading);$loading.className+=' loading-results';this.$results.prepend($loading)};Results.prototype.hideLoading=function(){this.$results.find('.loading-results').remove()};Results.prototype.option=function(data){var option=document.createElement('li');option.className='select2-results__option';var attrs={'role':'option','aria-selected':'false'};var matches=window.Element.prototype.matches||window.Element.prototype.msMatchesSelector||window.Element.prototype.webkitMatchesSelector;if((data.element!=null&&matches.call(data.element,':disabled'))||(data.element==null&&data.disabled)){delete attrs['aria-selected'];attrs['aria-disabled']='true'}if(data.id==null){delete attrs['aria-selected']}if(data._resultId!=null){option.id=data._resultId}if(data.title){option.title=data.title}if(data.children){attrs.role='group';attrs['aria-label']=data.text;delete attrs['aria-selected']}for(var attr in attrs){var val=attrs[attr];option.setAttribute(attr,val)}if(data.children){var $option=$(option);var label=document.createElement('strong');label.className='select2-results__group';var $label=$(label);this.template(data,label);var $children=[];for(var c=0;c',{'class':'select2-results__options select2-results__options--nested'});$childrenContainer.append($children);$option.append(label);$option.append($childrenContainer)}else{this.template(data,option)}Utils.StoreData(option,'data',data);return option};Results.prototype.bind=function(container,$container){var self=this;var id=container.id+'-results';this.$results.attr('id',id);container.on('results:all',function(params){self.clear();self.append(params.data);if(container.isOpen()){self.setClasses();self.highlightFirstItem()}});container.on('results:append',function(params){self.append(params.data);if(container.isOpen()){self.setClasses()}});container.on('query',function(params){self.hideMessages();self.showLoading(params)});container.on('select',function(){if(!container.isOpen()){return}self.setClasses();if(self.options.get('scrollAfterSelect')){self.highlightFirstItem()}});container.on('unselect',function(){if(!container.isOpen()){return}self.setClasses();if(self.options.get('scrollAfterSelect')){self.highlightFirstItem()}});container.on('open',function(){self.$results.attr('aria-expanded','true');self.$results.attr('aria-hidden','false');self.setClasses();self.ensureHighlightVisible()});container.on('close',function(){self.$results.attr('aria-expanded','false');self.$results.attr('aria-hidden','true');self.$results.removeAttr('aria-activedescendant')});container.on('results:toggle',function(){var $highlighted=self.getHighlightedResults();if($highlighted.length===0){return}$highlighted.trigger('mouseup')});container.on('results:select',function(){var $highlighted=self.getHighlightedResults();if($highlighted.length===0){return}var data=Utils.GetData($highlighted[0],'data');if($highlighted.attr('aria-selected')=='true'){self.trigger('close',{})}else{self.trigger('select',{data:data})}});container.on('results:previous',function(){var $highlighted=self.getHighlightedResults();var $options=self.$results.find('[aria-selected]');var currentIndex=$options.index($highlighted);if(currentIndex<=0){return}var nextIndex=currentIndex-1;if($highlighted.length===0){nextIndex=0}var $next=$options.eq(nextIndex);$next.trigger('mouseenter');var currentOffset=self.$results.offset().top;var nextTop=$next.offset().top;var nextOffset=self.$results.scrollTop()+(nextTop-currentOffset);if(nextIndex===0){self.$results.scrollTop(0)}else if(nextTop-currentOffset<0){self.$results.scrollTop(nextOffset)}});container.on('results:next',function(){var $highlighted=self.getHighlightedResults();var $options=self.$results.find('[aria-selected]');var currentIndex=$options.index($highlighted);var nextIndex=currentIndex+1;if(nextIndex>=$options.length){return}var $next=$options.eq(nextIndex);$next.trigger('mouseenter');var currentOffset=self.$results.offset().top+self.$results.outerHeight(false);var nextBottom=$next.offset().top+$next.outerHeight(false);var nextOffset=self.$results.scrollTop()+nextBottom-currentOffset;if(nextIndex===0){self.$results.scrollTop(0)}else if(nextBottom>currentOffset){self.$results.scrollTop(nextOffset)}});container.on('results:focus',function(params){params.element.addClass('select2-results__option--highlighted')});container.on('results:message',function(params){self.displayMessage(params)});if($.fn.mousewheel){this.$results.on('mousewheel',function(e){var top=self.$results.scrollTop();var bottom=self.$results.get(0).scrollHeight-top+e.deltaY;var isAtTop=e.deltaY>0&&top-e.deltaY<=0;var isAtBottom=e.deltaY<0&&bottom<=self.$results.height();if(isAtTop){self.$results.scrollTop(0);e.preventDefault();e.stopPropagation()}else if(isAtBottom){self.$results.scrollTop(self.$results.get(0).scrollHeight-self.$results.height());e.preventDefault();e.stopPropagation()}})}this.$results.on('mouseup','.select2-results__option[aria-selected]',function(evt){var $this=$(this);var data=Utils.GetData(this,'data');if($this.attr('aria-selected')==='true'){if(self.options.get('multiple')){self.trigger('unselect',{originalEvent:evt,data:data})}else{self.trigger('close',{})}return}self.trigger('select',{originalEvent:evt,data:data})});this.$results.on('mouseenter','.select2-results__option[aria-selected]',function(evt){var data=Utils.GetData(this,'data');self.getHighlightedResults().removeClass('select2-results__option--highlighted');self.trigger('results:focus',{data:data,element:$(this)})})};Results.prototype.getHighlightedResults=function(){var $highlighted=this.$results.find('.select2-results__option--highlighted');return $highlighted};Results.prototype.destroy=function(){this.$results.remove()};Results.prototype.ensureHighlightVisible=function(){var $highlighted=this.getHighlightedResults();if($highlighted.length===0){return}var $options=this.$results.find('[aria-selected]');var currentIndex=$options.index($highlighted);var currentOffset=this.$results.offset().top;var nextTop=$highlighted.offset().top;var nextOffset=this.$results.scrollTop()+(nextTop-currentOffset);var offsetDelta=nextTop-currentOffset;nextOffset-=$highlighted.outerHeight(false)*2;if(currentIndex<=2){this.$results.scrollTop(0)}else if(offsetDelta>this.$results.outerHeight()||offsetDelta<0){this.$results.scrollTop(nextOffset)}};Results.prototype.template=function(result,container){var template=this.options.get('templateResult');var escapeMarkup=this.options.get('escapeMarkup');var content=template(result,container);if(content==null){container.style.display='none'}else if(typeof content==='string'){container.innerHTML=escapeMarkup(content)}else{$(container).append(content)}};return Results});S2.define('select2/keys',[],function(){var KEYS={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46};return KEYS});S2.define('select2/selection/base',['jquery','../utils','../keys'],function($,Utils,KEYS){function BaseSelection($element,options){this.$element=$element;this.options=options;BaseSelection.__super__.constructor.call(this)}Utils.Extend(BaseSelection,Utils.Observable);BaseSelection.prototype.render=function(){var $selection=$('');this._tabindex=0;if(Utils.GetData(this.$element[0],'old-tabindex')!=null){this._tabindex=Utils.GetData(this.$element[0],'old-tabindex')}else if(this.$element.attr('tabindex')!=null){this._tabindex=this.$element.attr('tabindex')}$selection.attr('title',this.$element.attr('title'));$selection.attr('tabindex',this._tabindex);$selection.attr('aria-disabled','false');this.$selection=$selection;return $selection};BaseSelection.prototype.bind=function(container,$container){var self=this;var resultsId=container.id+'-results';this.container=container;this.$selection.on('focus',function(evt){self.trigger('focus',evt)});this.$selection.on('blur',function(evt){self._handleBlur(evt)});this.$selection.on('keydown',function(evt){self.trigger('keypress',evt);if(evt.which===KEYS.SPACE){evt.preventDefault()}});container.on('results:focus',function(params){self.$selection.attr('aria-activedescendant',params.data._resultId)});container.on('selection:update',function(params){self.update(params.data)});container.on('open',function(){self.$selection.attr('aria-expanded','true');self.$selection.attr('aria-owns',resultsId);self._attachCloseHandler(container)});container.on('close',function(){self.$selection.attr('aria-expanded','false');self.$selection.removeAttr('aria-activedescendant');self.$selection.removeAttr('aria-owns');self.$selection.trigger('focus');self._detachCloseHandler(container)});container.on('enable',function(){self.$selection.attr('tabindex',self._tabindex);self.$selection.attr('aria-disabled','false')});container.on('disable',function(){self.$selection.attr('tabindex','-1');self.$selection.attr('aria-disabled','true')})};BaseSelection.prototype._handleBlur=function(evt){var self=this;window.setTimeout(function(){if((document.activeElement==self.$selection[0])||($.contains(self.$selection[0],document.activeElement))){return}self.trigger('blur',evt)},1)};BaseSelection.prototype._attachCloseHandler=function(container){$(document.body).on('mousedown.select2.'+container.id,function(e){var $target=$(e.target);var $select=$target.closest('.select2');var $all=$('.select2.select2-container--open');$all.each(function(){if(this==$select[0]){return}var $element=Utils.GetData(this,'element');$element.select2('close')})})};BaseSelection.prototype._detachCloseHandler=function(container){$(document.body).off('mousedown.select2.'+container.id)};BaseSelection.prototype.position=function($selection,$container){var $selectionContainer=$container.find('.selection');$selectionContainer.append($selection)};BaseSelection.prototype.destroy=function(){this._detachCloseHandler(this.container)};BaseSelection.prototype.update=function(data){throw new Error('The `update` method must be defined in child classes.');};BaseSelection.prototype.isEnabled=function(){return!this.isDisabled()};BaseSelection.prototype.isDisabled=function(){return this.options.get('disabled')};return BaseSelection});S2.define('select2/selection/single',['jquery','./base','../utils','../keys'],function($,BaseSelection,Utils,KEYS){function SingleSelection(){SingleSelection.__super__.constructor.apply(this,arguments)}Utils.Extend(SingleSelection,BaseSelection);SingleSelection.prototype.render=function(){var $selection=SingleSelection.__super__.render.call(this);$selection.addClass('select2-selection--single');$selection.html(''+''+''+'');return $selection};SingleSelection.prototype.bind=function(container,$container){var self=this;SingleSelection.__super__.bind.apply(this,arguments);var id=container.id+'-container';this.$selection.find('.select2-selection__rendered').attr('id',id).attr('role','textbox').attr('aria-readonly','true');this.$selection.attr('aria-labelledby',id);this.$selection.on('mousedown',function(evt){if(evt.which!==1){return}self.trigger('toggle',{originalEvent:evt})});this.$selection.on('focus',function(evt){});this.$selection.on('blur',function(evt){});container.on('focus',function(evt){if(!container.isOpen()){self.$selection.trigger('focus')}})};SingleSelection.prototype.clear=function(){var $rendered=this.$selection.find('.select2-selection__rendered');$rendered.empty();$rendered.removeAttr('title')};SingleSelection.prototype.display=function(data,container){var template=this.options.get('templateSelection');var escapeMarkup=this.options.get('escapeMarkup');return escapeMarkup(template(data,container))};SingleSelection.prototype.selectionContainer=function(){return $('')};SingleSelection.prototype.update=function(data){if(data.length===0){this.clear();return}var selection=data[0];var $rendered=this.$selection.find('.select2-selection__rendered');var formatted=this.display(selection,$rendered);$rendered.empty().append(formatted);var title=selection.title||selection.text;if(title){$rendered.attr('title',title)}else{$rendered.removeAttr('title')}};return SingleSelection});S2.define('select2/selection/multiple',['jquery','./base','../utils'],function($,BaseSelection,Utils){function MultipleSelection($element,options){MultipleSelection.__super__.constructor.apply(this,arguments)}Utils.Extend(MultipleSelection,BaseSelection);MultipleSelection.prototype.render=function(){var $selection=MultipleSelection.__super__.render.call(this);$selection.addClass('select2-selection--multiple');$selection.html('
              ');return $selection};MultipleSelection.prototype.bind=function(container,$container){var self=this;MultipleSelection.__super__.bind.apply(this,arguments);this.$selection.on('click',function(evt){self.trigger('toggle',{originalEvent:evt})});this.$selection.on('click','.select2-selection__choice__remove',function(evt){if(self.isDisabled()){return}var $remove=$(this);var $selection=$remove.parent();var data=Utils.GetData($selection[0],'data');self.trigger('unselect',{originalEvent:evt,data:data})})};MultipleSelection.prototype.clear=function(){var $rendered=this.$selection.find('.select2-selection__rendered');$rendered.empty();$rendered.removeAttr('title')};MultipleSelection.prototype.display=function(data,container){var template=this.options.get('templateSelection');var escapeMarkup=this.options.get('escapeMarkup');return escapeMarkup(template(data,container))};MultipleSelection.prototype.selectionContainer=function(){var $container=$('
            • '+''+'×'+''+'
            • ');return $container};MultipleSelection.prototype.update=function(data){this.clear();if(data.length===0){return}var $selections=[];for(var d=0;d1;if(multipleSelections||singlePlaceholder){return decorated.call(this,data)}this.clear();var $placeholder=this.createPlaceholder(this.placeholder);this.$selection.find('.select2-selection__rendered').append($placeholder)};return Placeholder});S2.define('select2/selection/allowClear',['jquery','../keys','../utils'],function($,KEYS,Utils){function AllowClear(){}AllowClear.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);if(this.placeholder==null){if(this.options.get('debug')&&window.console&&console.error){console.error('Select2: The `allowClear` option should be used in combination '+'with the `placeholder` option.')}}this.$selection.on('mousedown','.select2-selection__clear',function(evt){self._handleClear(evt)});container.on('keypress',function(evt){self._handleKeyboardClear(evt,container)})};AllowClear.prototype._handleClear=function(_,evt){if(this.isDisabled()){return}var $clear=this.$selection.find('.select2-selection__clear');if($clear.length===0){return}evt.stopPropagation();var data=Utils.GetData($clear[0],'data');var previousVal=this.$element.val();this.$element.val(this.placeholder.id);var unselectData={data:data};this.trigger('clear',unselectData);if(unselectData.prevented){this.$element.val(previousVal);return}for(var d=0;d0||data.length===0){return}var removeAll=this.options.get('translations').get('removeAllItems');var $remove=$(''+'×'+'');Utils.StoreData($remove[0],'data',data);this.$selection.find('.select2-selection__rendered').prepend($remove)};return AllowClear});S2.define('select2/selection/search',['jquery','../utils','../keys'],function($,Utils,KEYS){function Search(decorated,$element,options){decorated.call(this,$element,options)}Search.prototype.render=function(decorated){var $search=$('');this.$searchContainer=$search;this.$search=$search.find('input');var $rendered=decorated.call(this);this._transferTabIndex();return $rendered};Search.prototype.bind=function(decorated,container,$container){var self=this;var resultsId=container.id+'-results';decorated.call(this,container,$container);container.on('open',function(){self.$search.attr('aria-controls',resultsId);self.$search.trigger('focus')});container.on('close',function(){self.$search.val('');self.$search.removeAttr('aria-controls');self.$search.removeAttr('aria-activedescendant');self.$search.trigger('focus')});container.on('enable',function(){self.$search.prop('disabled',false);self._transferTabIndex()});container.on('disable',function(){self.$search.prop('disabled',true)});container.on('focus',function(evt){self.$search.trigger('focus')});container.on('results:focus',function(params){if(params.data._resultId){self.$search.attr('aria-activedescendant',params.data._resultId)}else{self.$search.removeAttr('aria-activedescendant')}});this.$selection.on('focusin','.select2-search--inline',function(evt){self.trigger('focus',evt)});this.$selection.on('focusout','.select2-search--inline',function(evt){self._handleBlur(evt)});this.$selection.on('keydown','.select2-search--inline',function(evt){evt.stopPropagation();self.trigger('keypress',evt);self._keyUpPrevented=evt.isDefaultPrevented();var key=evt.which;if(key===KEYS.BACKSPACE&&self.$search.val()===''){var $previousChoice=self.$searchContainer.prev('.select2-selection__choice');if($previousChoice.length>0){var item=Utils.GetData($previousChoice[0],'data');self.searchRemoveChoice(item);evt.preventDefault()}}});this.$selection.on('click','.select2-search--inline',function(evt){if(self.$search.val()){evt.stopPropagation()}});var msie=document.documentMode;var disableInputEvents=msie&&msie<=11;this.$selection.on('input.searchcheck','.select2-search--inline',function(evt){if(disableInputEvents){self.$selection.off('input.search input.searchcheck');return}self.$selection.off('keyup.search')});this.$selection.on('keyup.search input.search','.select2-search--inline',function(evt){if(disableInputEvents&&evt.type==='input'){self.$selection.off('input.search input.searchcheck');return}var key=evt.which;if(key==KEYS.SHIFT||key==KEYS.CTRL||key==KEYS.ALT){return}if(key==KEYS.TAB){return}self.handleSearch(evt)})};Search.prototype._transferTabIndex=function(decorated){this.$search.attr('tabindex',this.$selection.attr('tabindex'));this.$selection.attr('tabindex','-1')};Search.prototype.createPlaceholder=function(decorated,placeholder){this.$search.attr('placeholder',placeholder.text)};Search.prototype.update=function(decorated,data){var searchHadFocus=this.$search[0]==document.activeElement;this.$search.attr('placeholder','');decorated.call(this,data);this.$selection.find('.select2-selection__rendered').append(this.$searchContainer);this.resizeSearch();if(searchHadFocus){this.$search.trigger('focus')}};Search.prototype.handleSearch=function(){this.resizeSearch();if(!this._keyUpPrevented){var input=this.$search.val();this.trigger('query',{term:input})}this._keyUpPrevented=false};Search.prototype.searchRemoveChoice=function(decorated,item){this.trigger('unselect',{data:item});this.$search.val(item.text);this.handleSearch()};Search.prototype.resizeSearch=function(){this.$search.css('width','25px');var width='';if(this.$search.attr('placeholder')!==''){width=this.$selection.find('.select2-selection__rendered').width()}else{var minimumWidth=this.$search.val().length+1;width=(minimumWidth*0.75)+'em'}this.$search.css('width',width)};return Search});S2.define('select2/selection/eventRelay',['jquery'],function($){function EventRelay(){}EventRelay.prototype.bind=function(decorated,container,$container){var self=this;var relayEvents=['open','opening','close','closing','select','selecting','unselect','unselecting','clear','clearing'];var preventableEvents=['opening','closing','selecting','unselecting','clearing'];decorated.call(this,container,$container);container.on('*',function(name,params){if($.inArray(name,relayEvents)===-1){return}params=params||{};var evt=$.Event('select2:'+name,{params:params});self.$element.trigger(evt);if($.inArray(name,preventableEvents)===-1){return}params.prevented=evt.isDefaultPrevented()})};return EventRelay});S2.define('select2/translation',['jquery','require'],function($,require){function Translation(dict){this.dict=dict||{}}Translation.prototype.all=function(){return this.dict};Translation.prototype.get=function(key){return this.dict[key]};Translation.prototype.extend=function(translation){this.dict=$.extend({},translation.all(),this.dict)};Translation._cache={};Translation.loadPath=function(path){if(!(path in Translation._cache)){var translations=require(path);Translation._cache[path]=translations}return new Translation(Translation._cache[path])};return Translation});S2.define('select2/diacritics',[],function(){var diacritics={'\u24B6':'A','\uFF21':'A','\u00C0':'A','\u00C1':'A','\u00C2':'A','\u1EA6':'A','\u1EA4':'A','\u1EAA':'A','\u1EA8':'A','\u00C3':'A','\u0100':'A','\u0102':'A','\u1EB0':'A','\u1EAE':'A','\u1EB4':'A','\u1EB2':'A','\u0226':'A','\u01E0':'A','\u00C4':'A','\u01DE':'A','\u1EA2':'A','\u00C5':'A','\u01FA':'A','\u01CD':'A','\u0200':'A','\u0202':'A','\u1EA0':'A','\u1EAC':'A','\u1EB6':'A','\u1E00':'A','\u0104':'A','\u023A':'A','\u2C6F':'A','\uA732':'AA','\u00C6':'AE','\u01FC':'AE','\u01E2':'AE','\uA734':'AO','\uA736':'AU','\uA738':'AV','\uA73A':'AV','\uA73C':'AY','\u24B7':'B','\uFF22':'B','\u1E02':'B','\u1E04':'B','\u1E06':'B','\u0243':'B','\u0182':'B','\u0181':'B','\u24B8':'C','\uFF23':'C','\u0106':'C','\u0108':'C','\u010A':'C','\u010C':'C','\u00C7':'C','\u1E08':'C','\u0187':'C','\u023B':'C','\uA73E':'C','\u24B9':'D','\uFF24':'D','\u1E0A':'D','\u010E':'D','\u1E0C':'D','\u1E10':'D','\u1E12':'D','\u1E0E':'D','\u0110':'D','\u018B':'D','\u018A':'D','\u0189':'D','\uA779':'D','\u01F1':'DZ','\u01C4':'DZ','\u01F2':'Dz','\u01C5':'Dz','\u24BA':'E','\uFF25':'E','\u00C8':'E','\u00C9':'E','\u00CA':'E','\u1EC0':'E','\u1EBE':'E','\u1EC4':'E','\u1EC2':'E','\u1EBC':'E','\u0112':'E','\u1E14':'E','\u1E16':'E','\u0114':'E','\u0116':'E','\u00CB':'E','\u1EBA':'E','\u011A':'E','\u0204':'E','\u0206':'E','\u1EB8':'E','\u1EC6':'E','\u0228':'E','\u1E1C':'E','\u0118':'E','\u1E18':'E','\u1E1A':'E','\u0190':'E','\u018E':'E','\u24BB':'F','\uFF26':'F','\u1E1E':'F','\u0191':'F','\uA77B':'F','\u24BC':'G','\uFF27':'G','\u01F4':'G','\u011C':'G','\u1E20':'G','\u011E':'G','\u0120':'G','\u01E6':'G','\u0122':'G','\u01E4':'G','\u0193':'G','\uA7A0':'G','\uA77D':'G','\uA77E':'G','\u24BD':'H','\uFF28':'H','\u0124':'H','\u1E22':'H','\u1E26':'H','\u021E':'H','\u1E24':'H','\u1E28':'H','\u1E2A':'H','\u0126':'H','\u2C67':'H','\u2C75':'H','\uA78D':'H','\u24BE':'I','\uFF29':'I','\u00CC':'I','\u00CD':'I','\u00CE':'I','\u0128':'I','\u012A':'I','\u012C':'I','\u0130':'I','\u00CF':'I','\u1E2E':'I','\u1EC8':'I','\u01CF':'I','\u0208':'I','\u020A':'I','\u1ECA':'I','\u012E':'I','\u1E2C':'I','\u0197':'I','\u24BF':'J','\uFF2A':'J','\u0134':'J','\u0248':'J','\u24C0':'K','\uFF2B':'K','\u1E30':'K','\u01E8':'K','\u1E32':'K','\u0136':'K','\u1E34':'K','\u0198':'K','\u2C69':'K','\uA740':'K','\uA742':'K','\uA744':'K','\uA7A2':'K','\u24C1':'L','\uFF2C':'L','\u013F':'L','\u0139':'L','\u013D':'L','\u1E36':'L','\u1E38':'L','\u013B':'L','\u1E3C':'L','\u1E3A':'L','\u0141':'L','\u023D':'L','\u2C62':'L','\u2C60':'L','\uA748':'L','\uA746':'L','\uA780':'L','\u01C7':'LJ','\u01C8':'Lj','\u24C2':'M','\uFF2D':'M','\u1E3E':'M','\u1E40':'M','\u1E42':'M','\u2C6E':'M','\u019C':'M','\u24C3':'N','\uFF2E':'N','\u01F8':'N','\u0143':'N','\u00D1':'N','\u1E44':'N','\u0147':'N','\u1E46':'N','\u0145':'N','\u1E4A':'N','\u1E48':'N','\u0220':'N','\u019D':'N','\uA790':'N','\uA7A4':'N','\u01CA':'NJ','\u01CB':'Nj','\u24C4':'O','\uFF2F':'O','\u00D2':'O','\u00D3':'O','\u00D4':'O','\u1ED2':'O','\u1ED0':'O','\u1ED6':'O','\u1ED4':'O','\u00D5':'O','\u1E4C':'O','\u022C':'O','\u1E4E':'O','\u014C':'O','\u1E50':'O','\u1E52':'O','\u014E':'O','\u022E':'O','\u0230':'O','\u00D6':'O','\u022A':'O','\u1ECE':'O','\u0150':'O','\u01D1':'O','\u020C':'O','\u020E':'O','\u01A0':'O','\u1EDC':'O','\u1EDA':'O','\u1EE0':'O','\u1EDE':'O','\u1EE2':'O','\u1ECC':'O','\u1ED8':'O','\u01EA':'O','\u01EC':'O','\u00D8':'O','\u01FE':'O','\u0186':'O','\u019F':'O','\uA74A':'O','\uA74C':'O','\u0152':'OE','\u01A2':'OI','\uA74E':'OO','\u0222':'OU','\u24C5':'P','\uFF30':'P','\u1E54':'P','\u1E56':'P','\u01A4':'P','\u2C63':'P','\uA750':'P','\uA752':'P','\uA754':'P','\u24C6':'Q','\uFF31':'Q','\uA756':'Q','\uA758':'Q','\u024A':'Q','\u24C7':'R','\uFF32':'R','\u0154':'R','\u1E58':'R','\u0158':'R','\u0210':'R','\u0212':'R','\u1E5A':'R','\u1E5C':'R','\u0156':'R','\u1E5E':'R','\u024C':'R','\u2C64':'R','\uA75A':'R','\uA7A6':'R','\uA782':'R','\u24C8':'S','\uFF33':'S','\u1E9E':'S','\u015A':'S','\u1E64':'S','\u015C':'S','\u1E60':'S','\u0160':'S','\u1E66':'S','\u1E62':'S','\u1E68':'S','\u0218':'S','\u015E':'S','\u2C7E':'S','\uA7A8':'S','\uA784':'S','\u24C9':'T','\uFF34':'T','\u1E6A':'T','\u0164':'T','\u1E6C':'T','\u021A':'T','\u0162':'T','\u1E70':'T','\u1E6E':'T','\u0166':'T','\u01AC':'T','\u01AE':'T','\u023E':'T','\uA786':'T','\uA728':'TZ','\u24CA':'U','\uFF35':'U','\u00D9':'U','\u00DA':'U','\u00DB':'U','\u0168':'U','\u1E78':'U','\u016A':'U','\u1E7A':'U','\u016C':'U','\u00DC':'U','\u01DB':'U','\u01D7':'U','\u01D5':'U','\u01D9':'U','\u1EE6':'U','\u016E':'U','\u0170':'U','\u01D3':'U','\u0214':'U','\u0216':'U','\u01AF':'U','\u1EEA':'U','\u1EE8':'U','\u1EEE':'U','\u1EEC':'U','\u1EF0':'U','\u1EE4':'U','\u1E72':'U','\u0172':'U','\u1E76':'U','\u1E74':'U','\u0244':'U','\u24CB':'V','\uFF36':'V','\u1E7C':'V','\u1E7E':'V','\u01B2':'V','\uA75E':'V','\u0245':'V','\uA760':'VY','\u24CC':'W','\uFF37':'W','\u1E80':'W','\u1E82':'W','\u0174':'W','\u1E86':'W','\u1E84':'W','\u1E88':'W','\u2C72':'W','\u24CD':'X','\uFF38':'X','\u1E8A':'X','\u1E8C':'X','\u24CE':'Y','\uFF39':'Y','\u1EF2':'Y','\u00DD':'Y','\u0176':'Y','\u1EF8':'Y','\u0232':'Y','\u1E8E':'Y','\u0178':'Y','\u1EF6':'Y','\u1EF4':'Y','\u01B3':'Y','\u024E':'Y','\u1EFE':'Y','\u24CF':'Z','\uFF3A':'Z','\u0179':'Z','\u1E90':'Z','\u017B':'Z','\u017D':'Z','\u1E92':'Z','\u1E94':'Z','\u01B5':'Z','\u0224':'Z','\u2C7F':'Z','\u2C6B':'Z','\uA762':'Z','\u24D0':'a','\uFF41':'a','\u1E9A':'a','\u00E0':'a','\u00E1':'a','\u00E2':'a','\u1EA7':'a','\u1EA5':'a','\u1EAB':'a','\u1EA9':'a','\u00E3':'a','\u0101':'a','\u0103':'a','\u1EB1':'a','\u1EAF':'a','\u1EB5':'a','\u1EB3':'a','\u0227':'a','\u01E1':'a','\u00E4':'a','\u01DF':'a','\u1EA3':'a','\u00E5':'a','\u01FB':'a','\u01CE':'a','\u0201':'a','\u0203':'a','\u1EA1':'a','\u1EAD':'a','\u1EB7':'a','\u1E01':'a','\u0105':'a','\u2C65':'a','\u0250':'a','\uA733':'aa','\u00E6':'ae','\u01FD':'ae','\u01E3':'ae','\uA735':'ao','\uA737':'au','\uA739':'av','\uA73B':'av','\uA73D':'ay','\u24D1':'b','\uFF42':'b','\u1E03':'b','\u1E05':'b','\u1E07':'b','\u0180':'b','\u0183':'b','\u0253':'b','\u24D2':'c','\uFF43':'c','\u0107':'c','\u0109':'c','\u010B':'c','\u010D':'c','\u00E7':'c','\u1E09':'c','\u0188':'c','\u023C':'c','\uA73F':'c','\u2184':'c','\u24D3':'d','\uFF44':'d','\u1E0B':'d','\u010F':'d','\u1E0D':'d','\u1E11':'d','\u1E13':'d','\u1E0F':'d','\u0111':'d','\u018C':'d','\u0256':'d','\u0257':'d','\uA77A':'d','\u01F3':'dz','\u01C6':'dz','\u24D4':'e','\uFF45':'e','\u00E8':'e','\u00E9':'e','\u00EA':'e','\u1EC1':'e','\u1EBF':'e','\u1EC5':'e','\u1EC3':'e','\u1EBD':'e','\u0113':'e','\u1E15':'e','\u1E17':'e','\u0115':'e','\u0117':'e','\u00EB':'e','\u1EBB':'e','\u011B':'e','\u0205':'e','\u0207':'e','\u1EB9':'e','\u1EC7':'e','\u0229':'e','\u1E1D':'e','\u0119':'e','\u1E19':'e','\u1E1B':'e','\u0247':'e','\u025B':'e','\u01DD':'e','\u24D5':'f','\uFF46':'f','\u1E1F':'f','\u0192':'f','\uA77C':'f','\u24D6':'g','\uFF47':'g','\u01F5':'g','\u011D':'g','\u1E21':'g','\u011F':'g','\u0121':'g','\u01E7':'g','\u0123':'g','\u01E5':'g','\u0260':'g','\uA7A1':'g','\u1D79':'g','\uA77F':'g','\u24D7':'h','\uFF48':'h','\u0125':'h','\u1E23':'h','\u1E27':'h','\u021F':'h','\u1E25':'h','\u1E29':'h','\u1E2B':'h','\u1E96':'h','\u0127':'h','\u2C68':'h','\u2C76':'h','\u0265':'h','\u0195':'hv','\u24D8':'i','\uFF49':'i','\u00EC':'i','\u00ED':'i','\u00EE':'i','\u0129':'i','\u012B':'i','\u012D':'i','\u00EF':'i','\u1E2F':'i','\u1EC9':'i','\u01D0':'i','\u0209':'i','\u020B':'i','\u1ECB':'i','\u012F':'i','\u1E2D':'i','\u0268':'i','\u0131':'i','\u24D9':'j','\uFF4A':'j','\u0135':'j','\u01F0':'j','\u0249':'j','\u24DA':'k','\uFF4B':'k','\u1E31':'k','\u01E9':'k','\u1E33':'k','\u0137':'k','\u1E35':'k','\u0199':'k','\u2C6A':'k','\uA741':'k','\uA743':'k','\uA745':'k','\uA7A3':'k','\u24DB':'l','\uFF4C':'l','\u0140':'l','\u013A':'l','\u013E':'l','\u1E37':'l','\u1E39':'l','\u013C':'l','\u1E3D':'l','\u1E3B':'l','\u017F':'l','\u0142':'l','\u019A':'l','\u026B':'l','\u2C61':'l','\uA749':'l','\uA781':'l','\uA747':'l','\u01C9':'lj','\u24DC':'m','\uFF4D':'m','\u1E3F':'m','\u1E41':'m','\u1E43':'m','\u0271':'m','\u026F':'m','\u24DD':'n','\uFF4E':'n','\u01F9':'n','\u0144':'n','\u00F1':'n','\u1E45':'n','\u0148':'n','\u1E47':'n','\u0146':'n','\u1E4B':'n','\u1E49':'n','\u019E':'n','\u0272':'n','\u0149':'n','\uA791':'n','\uA7A5':'n','\u01CC':'nj','\u24DE':'o','\uFF4F':'o','\u00F2':'o','\u00F3':'o','\u00F4':'o','\u1ED3':'o','\u1ED1':'o','\u1ED7':'o','\u1ED5':'o','\u00F5':'o','\u1E4D':'o','\u022D':'o','\u1E4F':'o','\u014D':'o','\u1E51':'o','\u1E53':'o','\u014F':'o','\u022F':'o','\u0231':'o','\u00F6':'o','\u022B':'o','\u1ECF':'o','\u0151':'o','\u01D2':'o','\u020D':'o','\u020F':'o','\u01A1':'o','\u1EDD':'o','\u1EDB':'o','\u1EE1':'o','\u1EDF':'o','\u1EE3':'o','\u1ECD':'o','\u1ED9':'o','\u01EB':'o','\u01ED':'o','\u00F8':'o','\u01FF':'o','\u0254':'o','\uA74B':'o','\uA74D':'o','\u0275':'o','\u0153':'oe','\u01A3':'oi','\u0223':'ou','\uA74F':'oo','\u24DF':'p','\uFF50':'p','\u1E55':'p','\u1E57':'p','\u01A5':'p','\u1D7D':'p','\uA751':'p','\uA753':'p','\uA755':'p','\u24E0':'q','\uFF51':'q','\u024B':'q','\uA757':'q','\uA759':'q','\u24E1':'r','\uFF52':'r','\u0155':'r','\u1E59':'r','\u0159':'r','\u0211':'r','\u0213':'r','\u1E5B':'r','\u1E5D':'r','\u0157':'r','\u1E5F':'r','\u024D':'r','\u027D':'r','\uA75B':'r','\uA7A7':'r','\uA783':'r','\u24E2':'s','\uFF53':'s','\u00DF':'s','\u015B':'s','\u1E65':'s','\u015D':'s','\u1E61':'s','\u0161':'s','\u1E67':'s','\u1E63':'s','\u1E69':'s','\u0219':'s','\u015F':'s','\u023F':'s','\uA7A9':'s','\uA785':'s','\u1E9B':'s','\u24E3':'t','\uFF54':'t','\u1E6B':'t','\u1E97':'t','\u0165':'t','\u1E6D':'t','\u021B':'t','\u0163':'t','\u1E71':'t','\u1E6F':'t','\u0167':'t','\u01AD':'t','\u0288':'t','\u2C66':'t','\uA787':'t','\uA729':'tz','\u24E4':'u','\uFF55':'u','\u00F9':'u','\u00FA':'u','\u00FB':'u','\u0169':'u','\u1E79':'u','\u016B':'u','\u1E7B':'u','\u016D':'u','\u00FC':'u','\u01DC':'u','\u01D8':'u','\u01D6':'u','\u01DA':'u','\u1EE7':'u','\u016F':'u','\u0171':'u','\u01D4':'u','\u0215':'u','\u0217':'u','\u01B0':'u','\u1EEB':'u','\u1EE9':'u','\u1EEF':'u','\u1EED':'u','\u1EF1':'u','\u1EE5':'u','\u1E73':'u','\u0173':'u','\u1E77':'u','\u1E75':'u','\u0289':'u','\u24E5':'v','\uFF56':'v','\u1E7D':'v','\u1E7F':'v','\u028B':'v','\uA75F':'v','\u028C':'v','\uA761':'vy','\u24E6':'w','\uFF57':'w','\u1E81':'w','\u1E83':'w','\u0175':'w','\u1E87':'w','\u1E85':'w','\u1E98':'w','\u1E89':'w','\u2C73':'w','\u24E7':'x','\uFF58':'x','\u1E8B':'x','\u1E8D':'x','\u24E8':'y','\uFF59':'y','\u1EF3':'y','\u00FD':'y','\u0177':'y','\u1EF9':'y','\u0233':'y','\u1E8F':'y','\u00FF':'y','\u1EF7':'y','\u1E99':'y','\u1EF5':'y','\u01B4':'y','\u024F':'y','\u1EFF':'y','\u24E9':'z','\uFF5A':'z','\u017A':'z','\u1E91':'z','\u017C':'z','\u017E':'z','\u1E93':'z','\u1E95':'z','\u01B6':'z','\u0225':'z','\u0240':'z','\u2C6C':'z','\uA763':'z','\u0386':'\u0391','\u0388':'\u0395','\u0389':'\u0397','\u038A':'\u0399','\u03AA':'\u0399','\u038C':'\u039F','\u038E':'\u03A5','\u03AB':'\u03A5','\u038F':'\u03A9','\u03AC':'\u03B1','\u03AD':'\u03B5','\u03AE':'\u03B7','\u03AF':'\u03B9','\u03CA':'\u03B9','\u0390':'\u03B9','\u03CC':'\u03BF','\u03CD':'\u03C5','\u03CB':'\u03C5','\u03B0':'\u03C5','\u03CE':'\u03C9','\u03C2':'\u03C3','\u2019':'\''};return diacritics});S2.define('select2/data/base',['../utils'],function(Utils){function BaseAdapter($element,options){BaseAdapter.__super__.constructor.call(this)}Utils.Extend(BaseAdapter,Utils.Observable);BaseAdapter.prototype.current=function(callback){throw new Error('The `current` method must be defined in child classes.');};BaseAdapter.prototype.query=function(params,callback){throw new Error('The `query` method must be defined in child classes.');};BaseAdapter.prototype.bind=function(container,$container){};BaseAdapter.prototype.destroy=function(){};BaseAdapter.prototype.generateResultId=function(container,data){var id=container.id+'-result-';id+=Utils.generateChars(4);if(data.id!=null){id+='-'+data.id.toString()}else{id+='-'+Utils.generateChars(4)}return id};return BaseAdapter});S2.define('select2/data/select',['./base','../utils','jquery'],function(BaseAdapter,Utils,$){function SelectAdapter($element,options){this.$element=$element;this.options=options;SelectAdapter.__super__.constructor.call(this)}Utils.Extend(SelectAdapter,BaseAdapter);SelectAdapter.prototype.current=function(callback){var data=[];var self=this;this.$element.find(':selected').each(function(){var $option=$(this);var option=self.item($option);data.push(option)});callback(data)};SelectAdapter.prototype.select=function(data){var self=this;data.selected=true;if($(data.element).is('option')){data.element.selected=true;this.$element.trigger('input').trigger('change');return}if(this.$element.prop('multiple')){this.current(function(currentData){var val=[];data=[data];data.push.apply(data,currentData);for(var d=0;d=0){var $existingOption=$existing.filter(onlyItem(item));var existingData=this.item($existingOption);var newData=$.extend(true,{},item,existingData);var $newOption=this.option(newData);$existingOption.replaceWith($newOption);continue}var $option=this.option(item);if(item.children){var $children=this.convertToOptions(item.children);Utils.appendMany($option,$children)}$options.push($option)}return $options};return ArrayAdapter});S2.define('select2/data/ajax',['./array','../utils','jquery'],function(ArrayAdapter,Utils,$){function AjaxAdapter($element,options){this.ajaxOptions=this._applyDefaults(options.get('ajax'));if(this.ajaxOptions.processResults!=null){this.processResults=this.ajaxOptions.processResults}AjaxAdapter.__super__.constructor.call(this,$element,options)}Utils.Extend(AjaxAdapter,ArrayAdapter);AjaxAdapter.prototype._applyDefaults=function(options){var defaults={data:function(params){return $.extend({},params,{q:params.term})},transport:function(params,success,failure){var $request=$.ajax(params);$request.then(success);$request.fail(failure);return $request}};return $.extend({},defaults,options,true)};AjaxAdapter.prototype.processResults=function(results){return results};AjaxAdapter.prototype.query=function(params,callback){var matches=[];var self=this;if(this._request!=null){if($.isFunction(this._request.abort)){this._request.abort()}this._request=null}var options=$.extend({type:'GET'},this.ajaxOptions);if(typeof options.url==='function'){options.url=options.url.call(this.$element,params)}if(typeof options.data==='function'){options.data=options.data.call(this.$element,params)}function request(){var $request=options.transport(options,function(data){var results=self.processResults(data,params);if(self.options.get('debug')&&window.console&&console.error){if(!results||!results.results||!$.isArray(results.results)){console.error('Select2: The AJAX results did not return an array in the '+'`results` key of the response.')}}callback(results)},function(){if('status'in $request&&($request.status===0||$request.status==='0')){return}self.trigger('results:message',{message:'errorLoading'})});self._request=$request}if(this.ajaxOptions.delay&¶ms.term!=null){if(this._queryTimeout){window.clearTimeout(this._queryTimeout)}this._queryTimeout=window.setTimeout(request,this.ajaxOptions.delay)}else{request()}};return AjaxAdapter});S2.define('select2/data/tags',['jquery'],function($){function Tags(decorated,$element,options){var tags=options.get('tags');var createTag=options.get('createTag');if(createTag!==undefined){this.createTag=createTag}var insertTag=options.get('insertTag');if(insertTag!==undefined){this.insertTag=insertTag}decorated.call(this,$element,options);if($.isArray(tags)){for(var t=0;t0&¶ms.term.length>this.maximumInputLength){this.trigger('results:message',{message:'inputTooLong',args:{maximum:this.maximumInputLength,input:params.term,params:params}});return}decorated.call(this,params,callback)};return MaximumInputLength});S2.define('select2/data/maximumSelectionLength',[],function(){function MaximumSelectionLength(decorated,$e,options){this.maximumSelectionLength=options.get('maximumSelectionLength');decorated.call(this,$e,options)}MaximumSelectionLength.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on('select',function(){self._checkIfMaximumSelected()})};MaximumSelectionLength.prototype.query=function(decorated,params,callback){var self=this;this._checkIfMaximumSelected(function(){decorated.call(self,params,callback)})};MaximumSelectionLength.prototype._checkIfMaximumSelected=function(_,successCallback){var self=this;this.current(function(currentData){var count=currentData!=null?currentData.length:0;if(self.maximumSelectionLength>0&&count>=self.maximumSelectionLength){self.trigger('results:message',{message:'maximumSelected',args:{maximum:self.maximumSelectionLength}});return}if(successCallback){successCallback()}})};return MaximumSelectionLength});S2.define('select2/dropdown',['jquery','./utils'],function($,Utils){function Dropdown($element,options){this.$element=$element;this.options=options;Dropdown.__super__.constructor.call(this)}Utils.Extend(Dropdown,Utils.Observable);Dropdown.prototype.render=function(){var $dropdown=$(''+''+'');$dropdown.attr('dir',this.options.get('dir'));this.$dropdown=$dropdown;return $dropdown};Dropdown.prototype.bind=function(){};Dropdown.prototype.position=function($dropdown,$container){};Dropdown.prototype.destroy=function(){this.$dropdown.remove()};return Dropdown});S2.define('select2/dropdown/search',['jquery','../utils'],function($,Utils){function Search(){}Search.prototype.render=function(decorated){var $rendered=decorated.call(this);var $search=$(''+''+'');this.$searchContainer=$search;this.$search=$search.find('input');$rendered.prepend($search);return $rendered};Search.prototype.bind=function(decorated,container,$container){var self=this;var resultsId=container.id+'-results';decorated.call(this,container,$container);this.$search.on('keydown',function(evt){self.trigger('keypress',evt);self._keyUpPrevented=evt.isDefaultPrevented()});this.$search.on('input',function(evt){$(this).off('keyup')});this.$search.on('keyup input',function(evt){self.handleSearch(evt)});container.on('open',function(){self.$search.attr('tabindex',0);self.$search.attr('aria-controls',resultsId);self.$search.trigger('focus');window.setTimeout(function(){self.$search.trigger('focus')},0)});container.on('close',function(){self.$search.attr('tabindex',-1);self.$search.removeAttr('aria-controls');self.$search.removeAttr('aria-activedescendant');self.$search.val('');self.$search.trigger('blur')});container.on('focus',function(){if(!container.isOpen()){self.$search.trigger('focus')}});container.on('results:all',function(params){if(params.query.term==null||params.query.term===''){var showSearch=self.showSearch(params);if(showSearch){self.$searchContainer.removeClass('select2-search--hide')}else{self.$searchContainer.addClass('select2-search--hide')}}});container.on('results:focus',function(params){if(params.data._resultId){self.$search.attr('aria-activedescendant',params.data._resultId)}else{self.$search.removeAttr('aria-activedescendant')}})};Search.prototype.handleSearch=function(evt){if(!this._keyUpPrevented){var input=this.$search.val();this.trigger('query',{term:input})}this._keyUpPrevented=false};Search.prototype.showSearch=function(_,params){return true};return Search});S2.define('select2/dropdown/hidePlaceholder',[],function(){function HidePlaceholder(decorated,$element,options,dataAdapter){this.placeholder=this.normalizePlaceholder(options.get('placeholder'));decorated.call(this,$element,options,dataAdapter)}HidePlaceholder.prototype.append=function(decorated,data){data.results=this.removePlaceholder(data.results);decorated.call(this,data)};HidePlaceholder.prototype.normalizePlaceholder=function(_,placeholder){if(typeof placeholder==='string'){placeholder={id:'',text:placeholder}}return placeholder};HidePlaceholder.prototype.removePlaceholder=function(_,data){var modifiedData=data.slice(0);for(var d=data.length-1;d>=0;d--){var item=data[d];if(this.placeholder.id===item.id){modifiedData.splice(d,1)}}return modifiedData};return HidePlaceholder});S2.define('select2/dropdown/infiniteScroll',['jquery'],function($){function InfiniteScroll(decorated,$element,options,dataAdapter){this.lastParams={};decorated.call(this,$element,options,dataAdapter);this.$loadingMore=this.createLoadingMore();this.loading=false}InfiniteScroll.prototype.append=function(decorated,data){this.$loadingMore.remove();this.loading=false;decorated.call(this,data);if(this.showLoadingMore(data)){this.$results.append(this.$loadingMore);this.loadMoreIfNeeded()}};InfiniteScroll.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on('query',function(params){self.lastParams=params;self.loading=true});container.on('query:append',function(params){self.lastParams=params;self.loading=true});this.$results.on('scroll',this.loadMoreIfNeeded.bind(this))};InfiniteScroll.prototype.loadMoreIfNeeded=function(){var isLoadMoreVisible=$.contains(document.documentElement,this.$loadingMore[0]);if(this.loading||!isLoadMoreVisible){return}var currentOffset=this.$results.offset().top+this.$results.outerHeight(false);var loadingMoreOffset=this.$loadingMore.offset().top+this.$loadingMore.outerHeight(false);if(currentOffset+50>=loadingMoreOffset){this.loadMore()}};InfiniteScroll.prototype.loadMore=function(){this.loading=true;var params=$.extend({},{page:1},this.lastParams);params.page++;this.trigger('query:append',params)};InfiniteScroll.prototype.showLoadingMore=function(_,data){return data.pagination&&data.pagination.more};InfiniteScroll.prototype.createLoadingMore=function(){var $option=$('
            • ');var message=this.options.get('translations').get('loadingMore');$option.html(message(this.lastParams));return $option};return InfiniteScroll});S2.define('select2/dropdown/attachBody',['jquery','../utils'],function($,Utils){function AttachBody(decorated,$element,options){this.$dropdownParent=$(options.get('dropdownParent')||document.body);decorated.call(this,$element,options)}AttachBody.prototype.bind=function(decorated,container,$container){var self=this;decorated.call(this,container,$container);container.on('open',function(){self._showDropdown();self._attachPositioningHandler(container);self._bindContainerResultHandlers(container)});container.on('close',function(){self._hideDropdown();self._detachPositioningHandler(container)});this.$dropdownContainer.on('mousedown',function(evt){evt.stopPropagation()})};AttachBody.prototype.destroy=function(decorated){decorated.call(this);this.$dropdownContainer.remove()};AttachBody.prototype.position=function(decorated,$dropdown,$container){$dropdown.attr('class',$container.attr('class'));$dropdown.removeClass('select2');$dropdown.addClass('select2-container--open');$dropdown.css({position:'absolute',top:-999999});this.$container=$container};AttachBody.prototype.render=function(decorated){var $container=$('');var $dropdown=decorated.call(this);$container.append($dropdown);this.$dropdownContainer=$container;return $container};AttachBody.prototype._hideDropdown=function(decorated){this.$dropdownContainer.detach()};AttachBody.prototype._bindContainerResultHandlers=function(decorated,container){if(this._containerResultsHandlersBound){return}var self=this;container.on('results:all',function(){self._positionDropdown();self._resizeDropdown()});container.on('results:append',function(){self._positionDropdown();self._resizeDropdown()});container.on('results:message',function(){self._positionDropdown();self._resizeDropdown()});container.on('select',function(){self._positionDropdown();self._resizeDropdown()});container.on('unselect',function(){self._positionDropdown();self._resizeDropdown()});this._containerResultsHandlersBound=true};AttachBody.prototype._attachPositioningHandler=function(decorated,container){var self=this;var scrollEvent='scroll.select2.'+container.id;var resizeEvent='resize.select2.'+container.id;var orientationEvent='orientationchange.select2.'+container.id;var $watchers=this.$container.parents().filter(Utils.hasScroll);$watchers.each(function(){Utils.StoreData(this,'select2-scroll-position',{x:$(this).scrollLeft(),y:$(this).scrollTop()})});$watchers.on(scrollEvent,function(ev){var position=Utils.GetData(this,'select2-scroll-position');$(this).scrollTop(position.y)});$(window).on(scrollEvent+' '+resizeEvent+' '+orientationEvent,function(e){self._positionDropdown();self._resizeDropdown()})};AttachBody.prototype._detachPositioningHandler=function(decorated,container){var scrollEvent='scroll.select2.'+container.id;var resizeEvent='resize.select2.'+container.id;var orientationEvent='orientationchange.select2.'+container.id;var $watchers=this.$container.parents().filter(Utils.hasScroll);$watchers.off(scrollEvent);$(window).off(scrollEvent+' '+resizeEvent+' '+orientationEvent)};AttachBody.prototype._positionDropdown=function(){var $window=$(window);var isCurrentlyAbove=this.$dropdown.hasClass('select2-dropdown--above');var isCurrentlyBelow=this.$dropdown.hasClass('select2-dropdown--below');var newDirection=null;var offset=this.$container.offset();offset.bottom=offset.top+this.$container.outerHeight(false);var container={height:this.$container.outerHeight(false)};container.top=offset.top;container.bottom=offset.top+container.height;var dropdown={height:this.$dropdown.outerHeight(false)};var viewport={top:$window.scrollTop(),bottom:$window.scrollTop()+$window.height()};var enoughRoomAbove=viewport.top<(offset.top-dropdown.height);var enoughRoomBelow=viewport.bottom>(offset.bottom+dropdown.height);var css={left:offset.left,top:container.bottom};var $offsetParent=this.$dropdownParent;if($offsetParent.css('position')==='static'){$offsetParent=$offsetParent.offsetParent()}var parentOffset={top:0,left:0};if($.contains(document.body,$offsetParent[0])||$offsetParent[0].isConnected){parentOffset=$offsetParent.offset()}css.top-=parentOffset.top;css.left-=parentOffset.left;if(!isCurrentlyAbove&&!isCurrentlyBelow){newDirection='below'}if(!enoughRoomBelow&&enoughRoomAbove&&!isCurrentlyAbove){newDirection='above'}else if(!enoughRoomAbove&&enoughRoomBelow&&isCurrentlyAbove){newDirection='below'}if(newDirection=='above'||(isCurrentlyAbove&&newDirection!=='below')){css.top=container.top-parentOffset.top-dropdown.height}if(newDirection!=null){this.$dropdown.removeClass('select2-dropdown--below select2-dropdown--above').addClass('select2-dropdown--'+newDirection);this.$container.removeClass('select2-container--below select2-container--above').addClass('select2-container--'+newDirection)}this.$dropdownContainer.css(css)};AttachBody.prototype._resizeDropdown=function(){var css={width:this.$container.outerWidth(false)+'px'};if(this.options.get('dropdownAutoWidth')){css.minWidth=css.width;css.position='relative';css.width='auto'}this.$dropdown.css(css)};AttachBody.prototype._showDropdown=function(decorated){this.$dropdownContainer.appendTo(this.$dropdownParent);this._positionDropdown();this._resizeDropdown()};return AttachBody});S2.define('select2/dropdown/minimumResultsForSearch',[],function(){function countResults(data){var count=0;for(var d=0;d0){options.dataAdapter=Utils.Decorate(options.dataAdapter,MinimumInputLength)}if(options.maximumInputLength>0){options.dataAdapter=Utils.Decorate(options.dataAdapter,MaximumInputLength)}if(options.maximumSelectionLength>0){options.dataAdapter=Utils.Decorate(options.dataAdapter,MaximumSelectionLength)}if(options.tags){options.dataAdapter=Utils.Decorate(options.dataAdapter,Tags)}if(options.tokenSeparators!=null||options.tokenizer!=null){options.dataAdapter=Utils.Decorate(options.dataAdapter,Tokenizer)}if(options.query!=null){var Query=require(options.amdBase+'compat/query');options.dataAdapter=Utils.Decorate(options.dataAdapter,Query)}if(options.initSelection!=null){var InitSelection=require(options.amdBase+'compat/initSelection');options.dataAdapter=Utils.Decorate(options.dataAdapter,InitSelection)}}if(options.resultsAdapter==null){options.resultsAdapter=ResultsList;if(options.ajax!=null){options.resultsAdapter=Utils.Decorate(options.resultsAdapter,InfiniteScroll)}if(options.placeholder!=null){options.resultsAdapter=Utils.Decorate(options.resultsAdapter,HidePlaceholder)}if(options.selectOnClose){options.resultsAdapter=Utils.Decorate(options.resultsAdapter,SelectOnClose)}}if(options.dropdownAdapter==null){if(options.multiple){options.dropdownAdapter=Dropdown}else{var SearchableDropdown=Utils.Decorate(Dropdown,DropdownSearch);options.dropdownAdapter=SearchableDropdown}if(options.minimumResultsForSearch!==0){options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,MinimumResultsForSearch)}if(options.closeOnSelect){options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,CloseOnSelect)}if(options.dropdownCssClass!=null||options.dropdownCss!=null||options.adaptDropdownCssClass!=null){var DropdownCSS=require(options.amdBase+'compat/dropdownCss');options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,DropdownCSS)}options.dropdownAdapter=Utils.Decorate(options.dropdownAdapter,AttachBody)}if(options.selectionAdapter==null){if(options.multiple){options.selectionAdapter=MultipleSelection}else{options.selectionAdapter=SingleSelection}if(options.placeholder!=null){options.selectionAdapter=Utils.Decorate(options.selectionAdapter,Placeholder)}if(options.allowClear){options.selectionAdapter=Utils.Decorate(options.selectionAdapter,AllowClear)}if(options.multiple){options.selectionAdapter=Utils.Decorate(options.selectionAdapter,SelectionSearch)}if(options.containerCssClass!=null||options.containerCss!=null||options.adaptContainerCssClass!=null){var ContainerCSS=require(options.amdBase+'compat/containerCss');options.selectionAdapter=Utils.Decorate(options.selectionAdapter,ContainerCSS)}options.selectionAdapter=Utils.Decorate(options.selectionAdapter,EventRelay)}options.language=this._resolveLanguage(options.language);options.language.push('en');var uniqueLanguages=[];for(var l=0;l0){var match=$.extend(true,{},data);for(var c=data.children.length-1;c>=0;c--){var child=data.children[c];var matches=matcher(params,child);if(matches==null){match.children.splice(c,1)}}if(match.children.length>0){return match}return matcher(params,match)}var original=stripDiacritics(data.text).toUpperCase();var term=stripDiacritics(params.term).toUpperCase();if(original.indexOf(term)>-1){return data}return null}this.defaults={amdBase:'./',amdLanguageBase:'./i18n/',closeOnSelect:true,debug:false,dropdownAutoWidth:false,escapeMarkup:Utils.escapeMarkup,language:{},matcher:matcher,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:false,scrollAfterSelect:false,sorter:function(data){return data},templateResult:function(result){return result.text},templateSelection:function(selection){return selection.text},theme:'default',width:'resolve'}};Defaults.prototype.applyFromElement=function(options,$element){var optionLanguage=options.language;var defaultLanguage=this.defaults.language;var elementLanguage=$element.prop('lang');var parentLanguage=$element.closest('[lang]').prop('lang');var languages=Array.prototype.concat.call(this._resolveLanguage(elementLanguage),this._resolveLanguage(optionLanguage),this._resolveLanguage(defaultLanguage),this._resolveLanguage(parentLanguage));options.language=languages;return options};Defaults.prototype._resolveLanguage=function(language){if(!language){return[]}if($.isEmptyObject(language)){return[]}if($.isPlainObject(language)){return[language]}var languages;if(!$.isArray(language)){languages=[language]}else{languages=language}var resolvedLanguages=[];for(var l=0;l0){var languageParts=languages[l].split('-');var baseLanguage=languageParts[0];resolvedLanguages.push(baseLanguage)}}return resolvedLanguages};Defaults.prototype._processTranslations=function(languages,debug){var translations=new Translation();for(var l=0;l-1){continue}if($.isPlainObject(this.options[key])){$.extend(this.options[key],data[key])}else{this.options[key]=data[key]}}return this};Options.prototype.get=function(key){return this.options[key]};Options.prototype.set=function(key,val){this.options[key]=val};return Options});S2.define('select2/core',['jquery','./options','./utils','./keys'],function($,Options,Utils,KEYS){var Select2=function($element,options){if(Utils.GetData($element[0],'select2')!=null){Utils.GetData($element[0],'select2').destroy()}this.$element=$element;this.id=this._generateId($element);options=options||{};this.options=new Options(options,$element);Select2.__super__.constructor.call(this);var tabindex=$element.attr('tabindex')||0;Utils.StoreData($element[0],'old-tabindex',tabindex);$element.attr('tabindex','-1');var DataAdapter=this.options.get('dataAdapter');this.dataAdapter=new DataAdapter($element,this.options);var $container=this.render();this._placeContainer($container);var SelectionAdapter=this.options.get('selectionAdapter');this.selection=new SelectionAdapter($element,this.options);this.$selection=this.selection.render();this.selection.position(this.$selection,$container);var DropdownAdapter=this.options.get('dropdownAdapter');this.dropdown=new DropdownAdapter($element,this.options);this.$dropdown=this.dropdown.render();this.dropdown.position(this.$dropdown,$container);var ResultsAdapter=this.options.get('resultsAdapter');this.results=new ResultsAdapter($element,this.options,this.dataAdapter);this.$results=this.results.render();this.results.position(this.$results,this.$dropdown);var self=this;this._bindAdapters();this._registerDomEvents();this._registerDataEvents();this._registerSelectionEvents();this._registerDropdownEvents();this._registerResultsEvents();this._registerEvents();this.dataAdapter.current(function(initialData){self.trigger('selection:update',{data:initialData})});$element.addClass('select2-hidden-accessible');$element.attr('aria-hidden','true');this._syncAttributes();Utils.StoreData($element[0],'select2',this);$element.data('select2',this)};Utils.Extend(Select2,Utils.Observable);Select2.prototype._generateId=function($element){var id='';if($element.attr('id')!=null){id=$element.attr('id')}else if($element.attr('name')!=null){id=$element.attr('name')+'-'+Utils.generateChars(2)}else{id=Utils.generateChars(4)}id=id.replace(/(:|\.|\[|\]|,)/g,'');id='select2-'+id;return id};Select2.prototype._placeContainer=function($container){$container.insertAfter(this.$element);var width=this._resolveWidth(this.$element,this.options.get('width'));if(width!=null){$container.css('width',width)}};Select2.prototype._resolveWidth=function($element,method){var WIDTH=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if(method=='resolve'){var styleWidth=this._resolveWidth($element,'style');if(styleWidth!=null){return styleWidth}return this._resolveWidth($element,'element')}if(method=='element'){var elementWidth=$element.outerWidth(false);if(elementWidth<=0){return'auto'}return elementWidth+'px'}if(method=='style'){var style=$element.attr('style');if(typeof(style)!=='string'){return null}var attrs=style.split(';');for(var i=0,l=attrs.length;i=1){return matches[1]}}return null}if(method=='computedstyle'){var computedStyle=window.getComputedStyle($element[0]);return computedStyle.width}return method};Select2.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container);this.selection.bind(this,this.$container);this.dropdown.bind(this,this.$container);this.results.bind(this,this.$container)};Select2.prototype._registerDomEvents=function(){var self=this;this.$element.on('change.select2',function(){self.dataAdapter.current(function(data){self.trigger('selection:update',{data:data})})});this.$element.on('focus.select2',function(evt){self.trigger('focus',evt)});this._syncA=Utils.bind(this._syncAttributes,this);this._syncS=Utils.bind(this._syncSubtree,this);if(this.$element[0].attachEvent){this.$element[0].attachEvent('onpropertychange',this._syncA)}var observer=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;if(observer!=null){this._observer=new observer(function(mutations){self._syncA();self._syncS(null,mutations)});this._observer.observe(this.$element[0],{attributes:true,childList:true,subtree:false})}else if(this.$element[0].addEventListener){this.$element[0].addEventListener('DOMAttrModified',self._syncA,false);this.$element[0].addEventListener('DOMNodeInserted',self._syncS,false);this.$element[0].addEventListener('DOMNodeRemoved',self._syncS,false)}};Select2.prototype._registerDataEvents=function(){var self=this;this.dataAdapter.on('*',function(name,params){self.trigger(name,params)})};Select2.prototype._registerSelectionEvents=function(){var self=this;var nonRelayEvents=['toggle','focus'];this.selection.on('toggle',function(){self.toggleDropdown()});this.selection.on('focus',function(params){self.focus(params)});this.selection.on('*',function(name,params){if($.inArray(name,nonRelayEvents)!==-1){return}self.trigger(name,params)})};Select2.prototype._registerDropdownEvents=function(){var self=this;this.dropdown.on('*',function(name,params){self.trigger(name,params)})};Select2.prototype._registerResultsEvents=function(){var self=this;this.results.on('*',function(name,params){self.trigger(name,params)})};Select2.prototype._registerEvents=function(){var self=this;this.on('open',function(){self.$container.addClass('select2-container--open')});this.on('close',function(){self.$container.removeClass('select2-container--open')});this.on('enable',function(){self.$container.removeClass('select2-container--disabled')});this.on('disable',function(){self.$container.addClass('select2-container--disabled')});this.on('blur',function(){self.$container.removeClass('select2-container--focus')});this.on('query',function(params){if(!self.isOpen()){self.trigger('open',{})}this.dataAdapter.query(params,function(data){self.trigger('results:all',{data:data,query:params})})});this.on('query:append',function(params){this.dataAdapter.query(params,function(data){self.trigger('results:append',{data:data,query:params})})});this.on('keypress',function(evt){var key=evt.which;if(self.isOpen()){if(key===KEYS.ESC||key===KEYS.TAB||(key===KEYS.UP&&evt.altKey)){self.close(evt);evt.preventDefault()}else if(key===KEYS.ENTER){self.trigger('results:select',{});evt.preventDefault()}else if((key===KEYS.SPACE&&evt.ctrlKey)){self.trigger('results:toggle',{});evt.preventDefault()}else if(key===KEYS.UP){self.trigger('results:previous',{});evt.preventDefault()}else if(key===KEYS.DOWN){self.trigger('results:next',{});evt.preventDefault()}}else{if(key===KEYS.ENTER||key===KEYS.SPACE||(key===KEYS.DOWN&&evt.altKey)){self.open();evt.preventDefault()}}})};Select2.prototype._syncAttributes=function(){this.options.set('disabled',this.$element.prop('disabled'));if(this.isDisabled()){if(this.isOpen()){this.close()}this.trigger('disable',{})}else{this.trigger('enable',{})}};Select2.prototype._isChangeMutation=function(evt,mutations){var changed=false;var self=this;if(evt&&evt.target&&(evt.target.nodeName!=='OPTION'&&evt.target.nodeName!=='OPTGROUP')){return}if(!mutations){changed=true}else if(mutations.addedNodes&&mutations.addedNodes.length>0){for(var n=0;n0){changed=true}else if($.isArray(mutations)){$.each(mutations,function(evt,mutation){if(self._isChangeMutation(evt,mutation)){changed=true;return false}})}return changed};Select2.prototype._syncSubtree=function(evt,mutations){var changed=this._isChangeMutation(evt,mutations);var self=this;if(changed){this.dataAdapter.current(function(currentData){self.trigger('selection:update',{data:currentData})})}};Select2.prototype.trigger=function(name,args){var actualTrigger=Select2.__super__.trigger;var preTriggerMap={'open':'opening','close':'closing','select':'selecting','unselect':'unselecting','clear':'clearing'};if(args===undefined){args={}}if(name in preTriggerMap){var preTriggerName=preTriggerMap[name];var preTriggerArgs={prevented:false,name:name,args:args};actualTrigger.call(this,preTriggerName,preTriggerArgs);if(preTriggerArgs.prevented){args.prevented=true;return}}actualTrigger.call(this,name,args)};Select2.prototype.toggleDropdown=function(){if(this.isDisabled()){return}if(this.isOpen()){this.close()}else{this.open()}};Select2.prototype.open=function(){if(this.isOpen()){return}if(this.isDisabled()){return}this.trigger('query',{})};Select2.prototype.close=function(evt){if(!this.isOpen()){return}this.trigger('close',{originalEvent:evt})};Select2.prototype.isEnabled=function(){return!this.isDisabled()};Select2.prototype.isDisabled=function(){return this.options.get('disabled')};Select2.prototype.isOpen=function(){return this.$container.hasClass('select2-container--open')};Select2.prototype.hasFocus=function(){return this.$container.hasClass('select2-container--focus')};Select2.prototype.focus=function(data){if(this.hasFocus()){return}this.$container.addClass('select2-container--focus');this.trigger('focus',{})};Select2.prototype.enable=function(args){if(this.options.get('debug')&&window.console&&console.warn){console.warn('Select2: The `select2("enable")` method has been deprecated and will'+' be removed in later Select2 versions. Use $element.prop("disabled")'+' instead.')}if(args==null||args.length===0){args=[true]}var disabled=!args[0];this.$element.prop('disabled',disabled)};Select2.prototype.data=function(){if(this.options.get('debug')&&arguments.length>0&&window.console&&console.warn){console.warn('Select2: Data can no longer be set using `select2("data")`. You '+'should consider setting the value instead using `$element.val()`.')}var data=[];this.dataAdapter.current(function(currentData){data=currentData});return data};Select2.prototype.val=function(args){if(this.options.get('debug')&&window.console&&console.warn){console.warn('Select2: The `select2("val")` method has been deprecated and will be'+' removed in later Select2 versions. Use $element.val() instead.')}if(args==null||args.length===0){return this.$element.val()}var newVal=args[0];if($.isArray(newVal)){newVal=$.map(newVal,function(obj){return obj.toString()})}this.$element.val(newVal).trigger('input').trigger('change')};Select2.prototype.destroy=function(){this.$container.remove();if(this.$element[0].detachEvent){this.$element[0].detachEvent('onpropertychange',this._syncA)}if(this._observer!=null){this._observer.disconnect();this._observer=null}else if(this.$element[0].removeEventListener){this.$element[0].removeEventListener('DOMAttrModified',this._syncA,false);this.$element[0].removeEventListener('DOMNodeInserted',this._syncS,false);this.$element[0].removeEventListener('DOMNodeRemoved',this._syncS,false)}this._syncA=null;this._syncS=null;this.$element.off('.select2');this.$element.attr('tabindex',Utils.GetData(this.$element[0],'old-tabindex'));this.$element.removeClass('select2-hidden-accessible');this.$element.attr('aria-hidden','false');Utils.RemoveData(this.$element[0]);this.$element.removeData('select2');this.dataAdapter.destroy();this.selection.destroy();this.dropdown.destroy();this.results.destroy();this.dataAdapter=null;this.selection=null;this.dropdown=null;this.results=null};Select2.prototype.render=function(){var $container=$(''+''+''+'');$container.attr('dir',this.options.get('dir'));this.$container=$container;this.$container.addClass('select2-container--'+this.options.get('theme'));Utils.StoreData($container[0],'element',this.$element);return $container};return Select2});S2.define('jquery-mousewheel',['jquery'],function($){return $});S2.define('jquery.select2',['jquery','jquery-mousewheel','./select2/core','./select2/defaults','./select2/utils'],function($,_,Select2,Defaults,Utils){if($.fn.select2==null){var thisMethods=['open','close','destroy'];$.fn.select2=function(options){options=options||{};if(typeof options==='object'){this.each(function(){var instanceOptions=$.extend(true,{},options);var instance=new Select2($(this),instanceOptions)});return this}else if(typeof options==='string'){var ret;var args=Array.prototype.slice.call(arguments,1);this.each(function(){var instance=Utils.GetData(this,'select2');if(instance==null&&window.console&&console.error){console.error('The select2(\''+options+'\') method was called on an '+'element that is not using Select2.')}ret=instance[options].apply(instance,args)});if($.inArray(options,thisMethods)>-1){return this}return ret}else{throw new Error('Invalid arguments for Select2: '+options);}}}if($.fn.select2.defaults==null){$.fn.select2.defaults=Defaults}return Select2});return{define:S2.define,require:S2.require}}());var select2=S2.require('jquery.select2');jQuery.fn.select2.amd=S2;return select2})); \ No newline at end of file diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index cf34d6536..1384cb02c 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -47,7 +47,7 @@ Berlin 13359, Germany - + From 9b597c4d205dde2efaf00e8d37d42b4f438c02b5 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 16:02:56 +0100 Subject: [PATCH 278/293] refactor/uncomment the MappedThing code. --- .../examplething/MappedThingProvider.scala | 104 +++++------ .../main/scala/code/examplething/Thing.scala | 165 +++++++++--------- .../scala/code/util/MappedClassNameTest.scala | 1 - 3 files changed, 135 insertions(+), 135 deletions(-) diff --git a/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala b/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala index 53e1d0d7c..e4d9e7d68 100644 --- a/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala +++ b/obp-api/src/main/scala/code/examplething/MappedThingProvider.scala @@ -1,52 +1,52 @@ -//package code.examplething -// -// -//import code.util.UUIDString -//import com.openbankproject.commons.model.BankId -//import net.liftweb.common.Box -//import net.liftweb.mapper._ -// -// -// -//object MappedThingProvider extends ThingProvider { -// -// override protected def getThingFromProvider(thingId: ThingId): Option[Thing] = -// MappedThing.find(By(MappedThing.thingId_, thingId.value)) -// -// override protected def getThingsFromProvider(bankId: BankId): Option[List[Thing]] = { -// Some(MappedThing.findAll(By(MappedThing.bankId_, bankId.value))) -// } -//} -// -//class MappedThing extends Thing with LongKeyedMapper[MappedThing] with IdPK { -// -// override def getSingleton = MappedThing -// -// object bankId_ extends UUIDString(this) -// object name_ extends MappedString(this, 255) -// -// object thingId_ extends MappedString(this, 30) -// -// object fooSomething_ extends MappedString(this, 255) -// object barSomething_ extends MappedString(this, 255) -// -// override def thingId: ThingId = ThingId(thingId_.get) -// override def something: String = name_.get -// -// -// override def foo: Foo = new Foo { -// override def fooSomething: String = fooSomething_.get -// } -// -// override def bar: Bar = new Bar { -// override def barSomething: String = barSomething_.get -// } -// -// -//} -// -// -//object MappedThing extends MappedThing with LongKeyedMetaMapper[MappedThing] { -// override def dbIndexes = UniqueIndex(bankId_, thingId_) :: Index(bankId_) :: super.dbIndexes -//} -// +package code.examplething + + +import code.util.UUIDString +import com.openbankproject.commons.model.BankId +import net.liftweb.common.Box +import net.liftweb.mapper._ + + + +object MappedThingProvider extends ThingProvider { + + override protected def getThingFromProvider(thingId: ThingId): Option[Thing] = + MappedThing.find(By(MappedThing.thingId_, thingId.value)) + + override protected def getThingsFromProvider(bankId: BankId): Option[List[Thing]] = { + Some(MappedThing.findAll(By(MappedThing.bankId_, bankId.value))) + } +} + +class MappedThing extends Thing with LongKeyedMapper[MappedThing] with IdPK { + + override def getSingleton = MappedThing + + object bankId_ extends UUIDString(this) + object name_ extends MappedString(this, 255) + + object thingId_ extends MappedString(this, 30) + + object fooSomething_ extends MappedString(this, 255) + object barSomething_ extends MappedString(this, 255) + + override def thingId: ThingId = ThingId(thingId_.get) + override def something: String = name_.get + + + override def foo: Foo = new Foo { + override def fooSomething: String = fooSomething_.get + } + + override def bar: Bar = new Bar { + override def barSomething: String = barSomething_.get + } + + +} + + +object MappedThing extends MappedThing with LongKeyedMetaMapper[MappedThing] { + override def dbIndexes = UniqueIndex(bankId_, thingId_) :: Index(bankId_) :: super.dbIndexes +} + diff --git a/obp-api/src/main/scala/code/examplething/Thing.scala b/obp-api/src/main/scala/code/examplething/Thing.scala index 64800baa9..8f87154d1 100644 --- a/obp-api/src/main/scala/code/examplething/Thing.scala +++ b/obp-api/src/main/scala/code/examplething/Thing.scala @@ -1,82 +1,83 @@ -//package code.examplething -// -// -//// Need to import these one by one because in same package! -//import code.api.util.APIUtil -//import com.openbankproject.commons.model.BankId -//import net.liftweb.common.Logger -//import net.liftweb.util.SimpleInjector -// -//object Thing extends SimpleInjector { -// -// val thingProvider = new Inject(buildOne _) {} -// // def buildOne: ThingProvider = MappedThingProvider -// -// -// // This determines the provider we use -// def buildOne: ThingProvider = -// APIUtil.getPropsValue("provider.thing").openOr("mapped") match { -// case "mapped" => MappedThingProvider -// case _ => MappedThingProvider -// } -// -//} -// -//case class ThingId(value : String) -// -//trait Thing { -// def thingId : ThingId -// def something : String -// def foo : Foo -// def bar : Bar -//} -// -//trait Foo { -// def fooSomething : String -//} -// -//trait Bar { -// def barSomething : String -//} -// -// -///* -//A trait that defines interfaces to Thing -//i.e. a ThingProvider should provide these: -// */ -// -//trait ThingProvider { -// -// private val logger = Logger(classOf[ThingProvider]) -// -// -// /* -// Common logic for returning or changing Things -// Datasource implementation details are in Thing provider -// */ -// final def getThings(bankId : BankId) : Option[List[Thing]] = { -// getThingsFromProvider(bankId) match { -// case Some(things) => { -// -// val certainThings = for { -// thing <- things // if thing.meta.license.name.size > 3 -// } yield thing -// Option(certainThings) -// } -// case None => None -// } -// } -// -// /* -// Return one Thing -// */ -// final def getThing(thingId : ThingId) : Option[Thing] = { -// // Could do something here -// getThingFromProvider(thingId) //.filter... -// } -// -// protected def getThingFromProvider(thingId : ThingId) : Option[Thing] -// protected def getThingsFromProvider(bank : BankId) : Option[List[Thing]] -// -//} -// +package code.examplething + + +// Need to import these one by one because in same package! +import code.api.util.APIUtil +import com.openbankproject.commons.model.BankId +import net.liftweb.common.Logger +import net.liftweb.util.SimpleInjector + +object Thing extends SimpleInjector { + + val thingProvider = new Inject(buildOne _) {} + // def buildOne: ThingProvider = MappedThingProvider + + + // This determines the provider we use + def buildOne: ThingProvider = + APIUtil.getPropsValue("provider.thing").openOr("mapped") match { + //If you set props `provider.thing`, you can set to different providers + //case "mapped" => MappedThingProvider + case _ => MappedThingProvider + } + +} + +case class ThingId(value : String) + +trait Thing { + def thingId : ThingId + def something : String + def foo : Foo + def bar : Bar +} + +trait Foo { + def fooSomething : String +} + +trait Bar { + def barSomething : String +} + + +/* +A trait that defines interfaces to Thing +i.e. a ThingProvider should provide these: + */ + +trait ThingProvider { + + private val logger = Logger(classOf[ThingProvider]) + + + /* + Common logic for returning or changing Things + Datasource implementation details are in Thing provider + */ + final def getThings(bankId : BankId) : Option[List[Thing]] = { + getThingsFromProvider(bankId) match { + case Some(things) => { + + val certainThings = for { + thing <- things // if thing.meta.license.name.size > 3 + } yield thing + Option(certainThings) + } + case None => None + } + } + + /* + Return one Thing + */ + final def getThing(thingId : ThingId) : Option[Thing] = { + // Could do something here + getThingFromProvider(thingId) //.filter... + } + + protected def getThingFromProvider(thingId : ThingId) : Option[Thing] + protected def getThingsFromProvider(bank : BankId) : Option[List[Thing]] + +} + diff --git a/obp-api/src/test/scala/code/util/MappedClassNameTest.scala b/obp-api/src/test/scala/code/util/MappedClassNameTest.scala index fa0179e06..b047b6455 100644 --- a/obp-api/src/test/scala/code/util/MappedClassNameTest.scala +++ b/obp-api/src/test/scala/code/util/MappedClassNameTest.scala @@ -26,7 +26,6 @@ class MappedClassNameTest extends FeatureSpec { val oldMappedTypeNames = Set("code.transactionrequests.MappedTransactionRequest", "code.methodrouting.MethodRouting", "code.metadata.tags.MappedTag", - "code.yearlycustomercharges.MappedYearlyCharge", "code.model.Token", "code.transaction.MappedTransaction", "code.metadata.comments.MappedComment", From 1afcd5e4da9cd30f422f9d24c960ef2674cf29b6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 25 Nov 2021 16:11:11 +0100 Subject: [PATCH 279/293] bugfix/Remove this conditional structure or edit its code blocks so that they're not all the same --- .../main/scala/code/examplething/Thing.scala | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/obp-api/src/main/scala/code/examplething/Thing.scala b/obp-api/src/main/scala/code/examplething/Thing.scala index 8f87154d1..fda82f985 100644 --- a/obp-api/src/main/scala/code/examplething/Thing.scala +++ b/obp-api/src/main/scala/code/examplething/Thing.scala @@ -10,16 +10,15 @@ import net.liftweb.util.SimpleInjector object Thing extends SimpleInjector { val thingProvider = new Inject(buildOne _) {} - // def buildOne: ThingProvider = MappedThingProvider + def buildOne: ThingProvider = MappedThingProvider - - // This determines the provider we use - def buildOne: ThingProvider = - APIUtil.getPropsValue("provider.thing").openOr("mapped") match { - //If you set props `provider.thing`, you can set to different providers - //case "mapped" => MappedThingProvider - case _ => MappedThingProvider - } + //If you set props `provider.thing`, you can set to different providers +// // This determines the provider we use +// def buildOne: ThingProvider = +// APIUtil.getPropsValue("provider.thing").openOr("mapped") match { +// case "mapped" => MappedThingProvider +// case _ => MappedThingProvider +// } } From aae36ed0fb5f93f0e89ba0b83c74975f96065c65 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Nov 2021 12:23:18 +0100 Subject: [PATCH 280/293] bugfix/Make sure not using rel="noopener" is safe here. --- obp-api/src/main/webapp/consumer-registration.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/webapp/consumer-registration.html b/obp-api/src/main/webapp/consumer-registration.html index d9e61aea1..68641846d 100644 --- a/obp-api/src/main/webapp/consumer-registration.html +++ b/obp-api/src/main/webapp/consumer-registration.html @@ -104,8 +104,8 @@ Berlin 13359, Germany
              The signing algorithm name of request object and client_assertion. - Reference 6.1. Passing a Request Object by Value - and 9. Client Authentication + Reference 6.1. Passing a Request Object by Value + and 9. Client Authentication
              @@ -125,7 +125,7 @@ Berlin 13359, Germany
              @@ -138,7 +138,7 @@ Berlin 13359, Germany
              Content of jwks_uri. jwks_uri and jwks should not both have value at the same time. - Reference 10.1.1. Rotation of Asymmetric Signing Keys + Reference 10.1.1. Rotation of Asymmetric Signing Keys
              @@ -217,7 +217,7 @@ Berlin 13359, Germany
              Dummy Users' Direct Login Tokens
              - +
              Direct Login Endpoint
              From c97e2bb471b5bf93926d4eed766e39f76d37af1f Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Nov 2021 12:38:17 +0100 Subject: [PATCH 281/293] bugfix/"password" detected here, make sure this is not a hard-coded credential. --- .../main/scala/code/api/util/HashUtil.scala | 7 ++++--- .../main/scala/code/api/util/RSAUtil.scala | 3 ++- .../test/scala/code/api/DirectLoginTest.scala | 21 ++++++++++--------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/HashUtil.scala b/obp-api/src/main/scala/code/api/util/HashUtil.scala index f272994e8..878f95f1a 100644 --- a/obp-api/src/main/scala/code/api/util/HashUtil.scala +++ b/obp-api/src/main/scala/code/api/util/HashUtil.scala @@ -14,9 +14,10 @@ object HashUtil { def main(args: Array[String]): Unit = { // You can verify hash with command line tool in linux, unix: // $ echo -n "123" | openssl dgst -sha256 - val password = "123" - val hashedPassword = Sha256Hash(password) - println("Password: " + password) + + val passwordTest = "123" + val hashedPassword = Sha256Hash(passwordTest) + println("Password: " + passwordTest) println("Hashed password: " + hashedPassword) } } diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index f8aefefd8..248ec372b 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -92,7 +92,8 @@ object RSAUtil extends MdcLoggable { } def main(args: Array[String]): Unit = { - val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=f" + val PASSWORD_TEST = """G!y"k9GHD$D""" + val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=%s".format(PASSWORD_TEST) val res = encrypt(db) println("db.url: " + db) println("encrypt: " + res) diff --git a/obp-api/src/test/scala/code/api/DirectLoginTest.scala b/obp-api/src/test/scala/code/api/DirectLoginTest.scala index 270dc3091..54cd69006 100644 --- a/obp-api/src/test/scala/code/api/DirectLoginTest.scala +++ b/obp-api/src/test/scala/code/api/DirectLoginTest.scala @@ -38,7 +38,8 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val SECRET = randomString(40).toLowerCase val EMAIL = randomString(10).toLowerCase + "@example.com" val USERNAME = "username with spaces" - val PASSWORD = """G!y"k9GHD$D""" + val PASSWORD_NO_EXISTING = "notExistingPassword" + val PASSWORD_TEST = """G!y"k9GHD$D""" val KEY_DISABLED = randomString(40).toLowerCase val SECRET_DISABLED = randomString(40).toLowerCase @@ -51,7 +52,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(USERNAME). - password(PASSWORD). + password(PASSWORD_TEST). validated(true). firstName(randomString(10)). lastName(randomString(10)). @@ -78,22 +79,22 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*") val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"notExistingUser\", " + - "password=\"notExistingPassword\", consumer_key=%s").format(KEY)) + "password=%s, consumer_key=%s").format(PASSWORD_NO_EXISTING, KEY)) val invalidUsernamePasswordCharaterHeader = ("Authorization", ("DirectLogin username=\" a#s \", " + - "password=\"no-good-password\", consumer_key=%s").format(KEY)) + "password=%s, consumer_key=%s").format(PASSWORD_NO_EXISTING, KEY)) val validUsernameInvalidPasswordHeader = ("Authorization", ("DirectLogin username=%s," + - "password=\"notExistingPassword\", consumer_key=%s").format(USERNAME, KEY)) + "password=%s, consumer_key=%s").format(USERNAME, PASSWORD_NO_EXISTING, KEY)) val invalidConsumerKeyHeader = ("Authorization", ("DirectLogin username=%s, " + - "password=%s, consumer_key=%s").format(USERNAME, PASSWORD, "invalid")) + "password=%s, consumer_key=%s").format(USERNAME, PASSWORD_TEST, "invalid")) val validDeprecatedHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". - format(USERNAME, PASSWORD, KEY)) + format(USERNAME, PASSWORD_TEST, KEY)) val validHeader = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(USERNAME, PASSWORD, KEY)) + format(USERNAME, PASSWORD_TEST, KEY)) val disabledConsumerValidHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". format(USERNAME_DISABLED, PASSWORD_DISABLED, KEY_DISABLED)) @@ -342,7 +343,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { scenario("Login with correct everything but the user is locked", ApiEndpoint1, ApiEndpoint2) { lazy val username = "firstname.lastname" lazy val header = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(username, PASSWORD, KEY)) + format(username, PASSWORD_TEST, KEY)) // Delete the user AuthUser.findUserByUsernameLocally(username).map(_.delete_!()) @@ -350,7 +351,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(username). - password(PASSWORD). + password(PASSWORD_TEST). validated(true). firstName(randomString(10)). lastName(randomString(10)). From 544d8d64fc143b9cdeb1f4a375af1e9f841084ab Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Nov 2021 13:42:39 +0100 Subject: [PATCH 282/293] refactor/rename passwordTest --> plainText --- obp-api/src/main/scala/code/api/util/HashUtil.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/HashUtil.scala b/obp-api/src/main/scala/code/api/util/HashUtil.scala index 878f95f1a..bd8b5836e 100644 --- a/obp-api/src/main/scala/code/api/util/HashUtil.scala +++ b/obp-api/src/main/scala/code/api/util/HashUtil.scala @@ -15,9 +15,9 @@ object HashUtil { // You can verify hash with command line tool in linux, unix: // $ echo -n "123" | openssl dgst -sha256 - val passwordTest = "123" - val hashedPassword = Sha256Hash(passwordTest) - println("Password: " + passwordTest) - println("Hashed password: " + hashedPassword) + val plainText = "123" + val hashedText = Sha256Hash(plainText) + println("Password: " + plainText) + println("Hashed password: " + hashedText) } } From 1d4d47293e7972771615f973dd8cc8de18b1c426 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Nov 2021 13:46:13 +0100 Subject: [PATCH 283/293] bugfix/"password" detected here, make sure this is not a hard-coded credential. --- .../main/scala/code/api/util/RSAUtil.scala | 4 ++-- .../test/scala/code/api/DirectLoginTest.scala | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/RSAUtil.scala b/obp-api/src/main/scala/code/api/util/RSAUtil.scala index 248ec372b..c3d6d6276 100644 --- a/obp-api/src/main/scala/code/api/util/RSAUtil.scala +++ b/obp-api/src/main/scala/code/api/util/RSAUtil.scala @@ -92,8 +92,8 @@ object RSAUtil extends MdcLoggable { } def main(args: Array[String]): Unit = { - val PASSWORD_TEST = """G!y"k9GHD$D""" - val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=%s".format(PASSWORD_TEST) + val randomString = """G!y"k9GHD$D""" + val db = "jdbc:postgresql://localhost:5432/obp_mapped?user=obp&password=%s".format(randomString) val res = encrypt(db) println("db.url: " + db) println("encrypt: " + res) diff --git a/obp-api/src/test/scala/code/api/DirectLoginTest.scala b/obp-api/src/test/scala/code/api/DirectLoginTest.scala index 54cd69006..459379ad7 100644 --- a/obp-api/src/test/scala/code/api/DirectLoginTest.scala +++ b/obp-api/src/test/scala/code/api/DirectLoginTest.scala @@ -38,8 +38,9 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val SECRET = randomString(40).toLowerCase val EMAIL = randomString(10).toLowerCase + "@example.com" val USERNAME = "username with spaces" - val PASSWORD_NO_EXISTING = "notExistingPassword" - val PASSWORD_TEST = """G!y"k9GHD$D""" + //sonarcloud: "password" detected here, make sure this is not a hard-coded credential. + val Passwd_NO_EXISTING = "notExistingPassword" + val Passwd_String = """G!y"k9GHD$D""" val KEY_DISABLED = randomString(40).toLowerCase val SECRET_DISABLED = randomString(40).toLowerCase @@ -52,7 +53,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(USERNAME). - password(PASSWORD_TEST). + password(Passwd_String). validated(true). firstName(randomString(10)). lastName(randomString(10)). @@ -79,22 +80,22 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*") val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"notExistingUser\", " + - "password=%s, consumer_key=%s").format(PASSWORD_NO_EXISTING, KEY)) + "password=%s, consumer_key=%s").format(Passwd_NO_EXISTING, KEY)) val invalidUsernamePasswordCharaterHeader = ("Authorization", ("DirectLogin username=\" a#s \", " + - "password=%s, consumer_key=%s").format(PASSWORD_NO_EXISTING, KEY)) + "password=%s, consumer_key=%s").format(Passwd_NO_EXISTING, KEY)) val validUsernameInvalidPasswordHeader = ("Authorization", ("DirectLogin username=%s," + - "password=%s, consumer_key=%s").format(USERNAME, PASSWORD_NO_EXISTING, KEY)) + "password=%s, consumer_key=%s").format(USERNAME, Passwd_NO_EXISTING, KEY)) val invalidConsumerKeyHeader = ("Authorization", ("DirectLogin username=%s, " + - "password=%s, consumer_key=%s").format(USERNAME, PASSWORD_TEST, "invalid")) + "password=%s, consumer_key=%s").format(USERNAME, Passwd_String, "invalid")) val validDeprecatedHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". - format(USERNAME, PASSWORD_TEST, KEY)) + format(USERNAME, Passwd_String, KEY)) val validHeader = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(USERNAME, PASSWORD_TEST, KEY)) + format(USERNAME, Passwd_String, KEY)) val disabledConsumerValidHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". format(USERNAME_DISABLED, PASSWORD_DISABLED, KEY_DISABLED)) @@ -343,7 +344,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { scenario("Login with correct everything but the user is locked", ApiEndpoint1, ApiEndpoint2) { lazy val username = "firstname.lastname" lazy val header = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(username, PASSWORD_TEST, KEY)) + format(username, Passwd_String, KEY)) // Delete the user AuthUser.findUserByUsernameLocally(username).map(_.delete_!()) @@ -351,7 +352,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(username). - password(PASSWORD_TEST). + password(Passwd_String). validated(true). firstName(randomString(10)). lastName(randomString(10)). From aa874ebbfe595c085463620228b4c58646d43f86 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Nov 2021 13:55:00 +0100 Subject: [PATCH 284/293] bugfix/"password" detected here, make sure this is not a hard-coded credential. -step2 --- .../test/scala/code/api/DirectLoginTest.scala | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/obp-api/src/test/scala/code/api/DirectLoginTest.scala b/obp-api/src/test/scala/code/api/DirectLoginTest.scala index 459379ad7..046afb9e0 100644 --- a/obp-api/src/test/scala/code/api/DirectLoginTest.scala +++ b/obp-api/src/test/scala/code/api/DirectLoginTest.scala @@ -38,9 +38,9 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val SECRET = randomString(40).toLowerCase val EMAIL = randomString(10).toLowerCase + "@example.com" val USERNAME = "username with spaces" - //sonarcloud: "password" detected here, make sure this is not a hard-coded credential. - val Passwd_NO_EXISTING = "notExistingPassword" - val Passwd_String = """G!y"k9GHD$D""" + //these are password, but sonarcloud: "password" detected here, make sure this is not a hard-coded credential. + val NO_EXISTING_PD = "notExistingPassword" + val VALID_PD = """G!y"k9GHD$D""" val KEY_DISABLED = randomString(40).toLowerCase val SECRET_DISABLED = randomString(40).toLowerCase @@ -53,7 +53,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(USERNAME). - password(Passwd_String). + password(VALID_PD). validated(true). firstName(randomString(10)). lastName(randomString(10)). @@ -80,22 +80,22 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*") val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"notExistingUser\", " + - "password=%s, consumer_key=%s").format(Passwd_NO_EXISTING, KEY)) + "password=%s, consumer_key=%s").format(NO_EXISTING_PD, KEY)) val invalidUsernamePasswordCharaterHeader = ("Authorization", ("DirectLogin username=\" a#s \", " + - "password=%s, consumer_key=%s").format(Passwd_NO_EXISTING, KEY)) + "password=%s, consumer_key=%s").format(NO_EXISTING_PD, KEY)) val validUsernameInvalidPasswordHeader = ("Authorization", ("DirectLogin username=%s," + - "password=%s, consumer_key=%s").format(USERNAME, Passwd_NO_EXISTING, KEY)) + "password=%s, consumer_key=%s").format(USERNAME, NO_EXISTING_PD, KEY)) val invalidConsumerKeyHeader = ("Authorization", ("DirectLogin username=%s, " + - "password=%s, consumer_key=%s").format(USERNAME, Passwd_String, "invalid")) + "password=%s, consumer_key=%s").format(USERNAME, VALID_PD, "invalid")) val validDeprecatedHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". - format(USERNAME, Passwd_String, KEY)) + format(USERNAME, VALID_PD, KEY)) val validHeader = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(USERNAME, Passwd_String, KEY)) + format(USERNAME, VALID_PD, KEY)) val disabledConsumerValidHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". format(USERNAME_DISABLED, PASSWORD_DISABLED, KEY_DISABLED)) @@ -344,7 +344,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { scenario("Login with correct everything but the user is locked", ApiEndpoint1, ApiEndpoint2) { lazy val username = "firstname.lastname" lazy val header = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(username, Passwd_String, KEY)) + format(username, VALID_PD, KEY)) // Delete the user AuthUser.findUserByUsernameLocally(username).map(_.delete_!()) @@ -352,7 +352,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(username). - password(Passwd_String). + password(VALID_PD). validated(true). firstName(randomString(10)). lastName(randomString(10)). From d377427ebf21055a1cfb2d82eaec63f0954d292a Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 26 Nov 2021 16:21:40 +0100 Subject: [PATCH 285/293] refactor/rename PD->PW --- .../test/scala/code/api/DirectLoginTest.scala | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/obp-api/src/test/scala/code/api/DirectLoginTest.scala b/obp-api/src/test/scala/code/api/DirectLoginTest.scala index 046afb9e0..2824a6f80 100644 --- a/obp-api/src/test/scala/code/api/DirectLoginTest.scala +++ b/obp-api/src/test/scala/code/api/DirectLoginTest.scala @@ -39,8 +39,8 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val EMAIL = randomString(10).toLowerCase + "@example.com" val USERNAME = "username with spaces" //these are password, but sonarcloud: "password" detected here, make sure this is not a hard-coded credential. - val NO_EXISTING_PD = "notExistingPassword" - val VALID_PD = """G!y"k9GHD$D""" + val NO_EXISTING_PW = "notExistingPassword" + val VALID_PW = """G!y"k9GHD$D""" val KEY_DISABLED = randomString(40).toLowerCase val SECRET_DISABLED = randomString(40).toLowerCase @@ -53,7 +53,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(USERNAME). - password(VALID_PD). + password(VALID_PW). validated(true). firstName(randomString(10)). lastName(randomString(10)). @@ -80,22 +80,22 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*") val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"notExistingUser\", " + - "password=%s, consumer_key=%s").format(NO_EXISTING_PD, KEY)) + "password=%s, consumer_key=%s").format(NO_EXISTING_PW, KEY)) val invalidUsernamePasswordCharaterHeader = ("Authorization", ("DirectLogin username=\" a#s \", " + - "password=%s, consumer_key=%s").format(NO_EXISTING_PD, KEY)) + "password=%s, consumer_key=%s").format(NO_EXISTING_PW, KEY)) val validUsernameInvalidPasswordHeader = ("Authorization", ("DirectLogin username=%s," + - "password=%s, consumer_key=%s").format(USERNAME, NO_EXISTING_PD, KEY)) + "password=%s, consumer_key=%s").format(USERNAME, NO_EXISTING_PW, KEY)) val invalidConsumerKeyHeader = ("Authorization", ("DirectLogin username=%s, " + - "password=%s, consumer_key=%s").format(USERNAME, VALID_PD, "invalid")) + "password=%s, consumer_key=%s").format(USERNAME, VALID_PW, "invalid")) val validDeprecatedHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". - format(USERNAME, VALID_PD, KEY)) + format(USERNAME, VALID_PW, KEY)) val validHeader = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(USERNAME, VALID_PD, KEY)) + format(USERNAME, VALID_PW, KEY)) val disabledConsumerValidHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s". format(USERNAME_DISABLED, PASSWORD_DISABLED, KEY_DISABLED)) @@ -344,7 +344,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { scenario("Login with correct everything but the user is locked", ApiEndpoint1, ApiEndpoint2) { lazy val username = "firstname.lastname" lazy val header = ("DirectLogin", "username=%s, password=%s, consumer_key=%s". - format(username, VALID_PD, KEY)) + format(username, VALID_PW, KEY)) // Delete the user AuthUser.findUserByUsernameLocally(username).map(_.delete_!()) @@ -352,7 +352,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter { AuthUser.create. email(EMAIL). username(username). - password(VALID_PD). + password(VALID_PW). validated(true). firstName(randomString(10)). lastName(randomString(10)). From 36ceb558863516a90218d825683281d14d3be53f Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 29 Nov 2021 21:02:42 +0100 Subject: [PATCH 286/293] docfix/tweaked the document for createUserWithAccountAccess --- .../code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 4 ++-- obp-api/src/main/scala/code/api/util/ExampleValue.scala | 6 +++--- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 0ff28d9b8..89432bb1d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4090,8 +4090,8 @@ object SwaggerDefinitionsJSON { val postAccountAccessJsonV400 = PostAccountAccessJsonV400(userIdExample.value, PostViewJsonV400(ExampleValue.viewIdExample.value, true)) val postCreateUserAccountAccessJsonV400 = PostCreateUserAccountAccessJsonV400( userIdExample.value, - providerExample.value, - List(PostViewJsonV400(ExampleValue.viewIdExample.value, true)) + s"dauth.${providerExample.value}", + List(PostViewJsonV400(viewIdExample.value, isSystemExample.value.toBoolean)) ) val postCreateUserWithRolesJsonV400 = PostCreateUserWithRolesJsonV400( userIdExample.value, diff --git a/obp-api/src/main/scala/code/api/util/ExampleValue.scala b/obp-api/src/main/scala/code/api/util/ExampleValue.scala index 3f1ca6743..fb7044526 100644 --- a/obp-api/src/main/scala/code/api/util/ExampleValue.scala +++ b/obp-api/src/main/scala/code/api/util/ExampleValue.scala @@ -1201,8 +1201,8 @@ object ExampleValue { lazy val productAttributeIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("product_attribute_id", productAttributeIdExample) - lazy val isSystemExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) - glossaryItems += makeGlossaryItem("is_system", isSystemExample) + lazy val isSystemExample = ConnectorField("true", "If the view is the system level, then it is true") + glossaryItems += makeGlossaryItem("view.is_system", isSystemExample) lazy val detailsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("details", detailsExample) @@ -1309,7 +1309,7 @@ object ExampleValue { lazy val webUiPropsIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) glossaryItems += makeGlossaryItem("web_ui_props_id", webUiPropsIdExample) - lazy val providerExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) + lazy val providerExample = ConnectorField("ETHEREUM","the provider name ") glossaryItems += makeGlossaryItem("provider", providerExample) lazy val canSeePhysicalLocationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index a074d7c89..712d89897 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4291,7 +4291,7 @@ trait APIMethods400 { |${getGlossaryItem("DAuth")} | |""", - postCreateUserWithRolesJsonV400, + postCreateUserAccountAccessJsonV400, List(viewJsonV300), List( $UserNotLoggedIn, From 34feb6929e6282de6873e71998b05121bf65427c Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 2 Dec 2021 13:31:13 +0100 Subject: [PATCH 287/293] feature/fixed the user bug for DAuth --- obp-api/src/main/scala/code/api/dauth.scala | 40 ++++++------------- .../main/scala/code/api/util/NewStyle.scala | 14 +------ obp-api/src/main/scala/code/model/User.scala | 16 ++++++++ 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index f4f0d9b88..0bd61d5c5 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -134,25 +134,12 @@ object DAuth extends RestHelper with MdcLoggable { } def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { - val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") - val provider = getFieldFromPayloadJson(jwtPayload, "network_name") - val providerHardCodePrefixDauth = "dauth."+provider - logger.debug("login_user_name: " + username) + val userId = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + val provider = "dauth."+getFieldFromPayloadJson(jwtPayload, "network_name") + logger.debug("login_user_id: " + userId) for { - tuple <- - Users.users.vend.getUserByProviderId(provider = providerHardCodePrefixDauth, idGivenByProvider = username).or { // Find a user - Users.users.vend.createResourceUser( // Otherwise create a new one - provider = providerHardCodePrefixDauth, - providerId = Some(username), - None, - name = Some(username), - email = None, - userId = None, - createdByUserInvitationId = None, - company = None, - lastMarketingAgreementSignedDate = None - ) - } match { + tuple <- + UserX.getOrCreateDauthResourceUser(userId, provider) match { case Full(u) => Full((u,callContext)) // Return user case Empty => @@ -167,18 +154,17 @@ object DAuth extends RestHelper with MdcLoggable { } } def getOrCreateResourceUserFuture(jwtPayload: String, callContext: Option[CallContext]) : Future[Box[(User, Option[CallContext])]] = { - val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") - val provider = getFieldFromPayloadJson(jwtPayload, "network_name") - val providerHardCodePrefixDauth = "dauth."+provider - logger.debug("login_user_name: " + username) + val userId = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + val provider = "dauth."+ getFieldFromPayloadJson(jwtPayload, "network_name") + logger.debug("login_user_Id: " + userId) + for { - tuple <- - Users.users.vend.getOrCreateUserByProviderIdFuture(provider = providerHardCodePrefixDauth, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map { - case (Full(u), _) => + tuple <- Future { UserX.getOrCreateDauthResourceUser(userId, provider)} map { + case (Full(u)) => Full(u, callContext) // Return user - case (Empty, _) => + case (Empty) => Failure(ErrorMessages.DAuthCannotGetOrCreateUser) - case (Failure(msg, t, c), _) => + case (Failure(msg, t, c)) => Failure(msg, t, c) case _ => Failure(ErrorMessages.DAuthUnknownError) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index f3ac7659a..1d86cc720 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1035,19 +1035,7 @@ object NewStyle { } def getOrCreateUser(userId: String, provider: String, callContext: Option[CallContext]): OBPReturnType[User] = { - Future { UserX.findByUserId(userId).or( //first try to find the user by userId - Users.users.vend.createResourceUser( // Otherwise create a new user - provider = provider, - providerId = Some(userId), - None, - name = Some(userId), - email = None, - userId = Some(userId), - createdByUserInvitationId = None, - company = None, - lastMarketingAgreementSignedDate = None - ) - ).map(user =>(user, callContext))} map { + Future { UserX.getOrCreateDauthResourceUser(userId, provider).map(user =>(user, callContext))} map { unboxFullOrFail(_, callContext, s"$CannotGetOrCreateUser Current USER_ID($userId) PROVIDER ($provider)", 404) } } diff --git a/obp-api/src/main/scala/code/model/User.scala b/obp-api/src/main/scala/code/model/User.scala index aff34e40a..8abb2e891 100644 --- a/obp-api/src/main/scala/code/model/User.scala +++ b/obp-api/src/main/scala/code/model/User.scala @@ -141,6 +141,22 @@ object UserX { def saveResourceUser(ru: ResourceUser) = { Users.users.vend.saveResourceUser(ru) } + + def getOrCreateDauthResourceUser(userId: String, provider: String) = { + findByUserId(userId).or( //first try to find the user by userId + Users.users.vend.createResourceUser( // Otherwise create a new user + provider = provider, + providerId = Some(userId), + None, + name = Some(userId), + email = None, + userId = Some(userId), + createdByUserInvitationId = None, + company = None, + lastMarketingAgreementSignedDate = None + ) + ) + } //def bulkDeleteAllResourceUsers(): Box[Boolean] = { // Users.users.vend.bulkDeleteAllResourceUsers() From 2e450dc2148d3d650275a31e918c0128c977de9f Mon Sep 17 00:00:00 2001 From: hongwei Date: Sat, 4 Dec 2021 06:56:02 +0100 Subject: [PATCH 288/293] feature/DAuth: use combination of username + provider --- .../SwaggerDefinitionsJSON.scala | 2 +- obp-api/src/main/scala/code/api/dauth.scala | 12 ++++----- .../main/scala/code/api/util/NewStyle.scala | 6 ++--- .../scala/code/api/v4_0_0/APIMethods400.scala | 26 ++++++------------- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 4 +-- obp-api/src/main/scala/code/model/User.scala | 10 +++---- .../code/api/v4_0_0/EntitlementTests.scala | 2 +- 7 files changed, 26 insertions(+), 36 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 89432bb1d..d8be99d70 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4089,7 +4089,7 @@ object SwaggerDefinitionsJSON { val postAccountAccessJsonV400 = PostAccountAccessJsonV400(userIdExample.value, PostViewJsonV400(ExampleValue.viewIdExample.value, true)) val postCreateUserAccountAccessJsonV400 = PostCreateUserAccountAccessJsonV400( - userIdExample.value, + usernameExample.value, s"dauth.${providerExample.value}", List(PostViewJsonV400(viewIdExample.value, isSystemExample.value.toBoolean)) ) diff --git a/obp-api/src/main/scala/code/api/dauth.scala b/obp-api/src/main/scala/code/api/dauth.scala index 0bd61d5c5..e23240428 100755 --- a/obp-api/src/main/scala/code/api/dauth.scala +++ b/obp-api/src/main/scala/code/api/dauth.scala @@ -134,12 +134,12 @@ object DAuth extends RestHelper with MdcLoggable { } def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = { - val userId = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + val userName = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") val provider = "dauth."+getFieldFromPayloadJson(jwtPayload, "network_name") - logger.debug("login_user_id: " + userId) + logger.debug("login_user_name: " + userName) for { tuple <- - UserX.getOrCreateDauthResourceUser(userId, provider) match { + UserX.getOrCreateDauthResourceUser(userName, provider) match { case Full(u) => Full((u,callContext)) // Return user case Empty => @@ -154,12 +154,12 @@ object DAuth extends RestHelper with MdcLoggable { } } def getOrCreateResourceUserFuture(jwtPayload: String, callContext: Option[CallContext]) : Future[Box[(User, Option[CallContext])]] = { - val userId = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") + val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address") val provider = "dauth."+ getFieldFromPayloadJson(jwtPayload, "network_name") - logger.debug("login_user_Id: " + userId) + logger.debug("login_user_name: " + username) for { - tuple <- Future { UserX.getOrCreateDauthResourceUser(userId, provider)} map { + tuple <- Future { UserX.getOrCreateDauthResourceUser(username, provider)} map { case (Full(u)) => Full(u, callContext) // Return user case (Empty) => diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 1d86cc720..8603ff1de 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1034,9 +1034,9 @@ object NewStyle { } } - def getOrCreateUser(userId: String, provider: String, callContext: Option[CallContext]): OBPReturnType[User] = { - Future { UserX.getOrCreateDauthResourceUser(userId, provider).map(user =>(user, callContext))} map { - unboxFullOrFail(_, callContext, s"$CannotGetOrCreateUser Current USER_ID($userId) PROVIDER ($provider)", 404) + def getOrCreateResourceUser(username: String, provider: String, callContext: Option[CallContext]): OBPReturnType[User] = { + Future { UserX.getOrCreateDauthResourceUser(username, provider).map(user =>(user, callContext))} map { + unboxFullOrFail(_, callContext, s"$CannotGetOrCreateUser Current USERName($username) PROVIDER ($provider)", 404) } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 712d89897..ad59eba42 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2747,7 +2747,7 @@ trait APIMethods400 { s""" |This endpoint is used as part of the DAuth solution to grant Entitlements for Roles to a smart contract on the blockchain. | - |Put the smart contract address in user_id + |Put the smart contract address in username | |For provider use "dauth" | @@ -2801,11 +2801,6 @@ trait APIMethods400 { postedData.provider.startsWith("dauth.") } - //user_id set the length for the min length of the userId. eg: 36 - _ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) { - postedData.user_id.length>=36 - } - //check the system role bankId is Empty, but bank level role need bankId _ <- checkRoleBankIdMappings(callContext, postedData) @@ -2815,7 +2810,7 @@ trait APIMethods400 { canCreateEntitlementAtAnyBankRole = Entitlement.entitlement.vend.getEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank.toString()) - (targetUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext) + (targetUser, callContext) <- NewStyle.function.getOrCreateResourceUser(postedData.username, postedData.provider, callContext) _ <- if (canCreateEntitlementAtAnyBankRole.isDefined) { //If the loggedIn User has `CanCreateEntitlementAtAnyBankRole` role, then we can grant all the requestRoles to the requestUser. @@ -2827,7 +2822,7 @@ trait APIMethods400 { assertUserCanGrantRoles(loggedInUser.userId, postedData.roles, callContext) } - addedEntitlements <- addEntitlementsToUser(postedData, callContext) + addedEntitlements <- addEntitlementsToUser(targetUser.userId, postedData, callContext) } yield { (JSONFactory400.createEntitlementJSONs(addedEntitlements), HttpCode.`201`(callContext)) @@ -4278,7 +4273,7 @@ trait APIMethods400 { "Create (DAuth) User with Account Access", s"""This endpoint is used as part of the DAuth solution to grant access to account and transaction data to a smart contract on the blockchain. | - |Put the smart contract address in user_id + |Put the smart contract address in username | |For provider use "dauth" | @@ -4317,15 +4312,10 @@ trait APIMethods400 { postJson.provider.startsWith("dauth.") } - //user_id set the length for the min length of the userId. eg: 36 - _ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) { - postJson.user_id.length>=36 - } - _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) - (user, callContext) <- NewStyle.function.getOrCreateUser(postJson.user_id, postJson.provider, cc.callContext) + (targetUser, callContext) <- NewStyle.function.getOrCreateResourceUser(postJson.username, postJson.provider, cc.callContext) views <- getViews(bankId, accountId, postJson, callContext) - addedView <- createAccountAccessesToUser(bankId, accountId, user, views, callContext) + addedView <- createAccountAccessesToUser(bankId, accountId, targetUser, views, callContext) } yield { val viewsJson = addedView.map(JSONFactory300.createViewJSON(_)) (viewsJson, HttpCode.`201`(callContext)) @@ -10963,8 +10953,8 @@ trait APIMethods400 { Future(Entitlement.entitlement.vend.addEntitlement(entitlement.bank_id, userId, entitlement.role_name)) map { unboxFull(_) } } - private def addEntitlementsToUser(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { - Future.sequence(postedData.roles.distinct.map(addEntitlementToUser(postedData.user_id, _, callContext))) + private def addEntitlementsToUser(userId:String, postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = { + Future.sequence(postedData.roles.distinct.map(addEntitlementToUser(userId, _, callContext))) } /** diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index ae3685578..957f5898c 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -354,8 +354,8 @@ case class StandingOrderJsonV400(standing_order_id: String, active: Boolean) case class PostViewJsonV400(view_id: String, is_system: Boolean) case class PostAccountAccessJsonV400(user_id: String, view: PostViewJsonV400) -case class PostCreateUserAccountAccessJsonV400(user_id: String, provider:String, views: List[PostViewJsonV400]) -case class PostCreateUserWithRolesJsonV400(user_id: String, provider:String, roles: List[CreateEntitlementJSON]) +case class PostCreateUserAccountAccessJsonV400(username: String, provider:String, views: List[PostViewJsonV400]) +case class PostCreateUserWithRolesJsonV400(username: String, provider:String, roles: List[CreateEntitlementJSON]) case class PostRevokeGrantAccountAccessJsonV400(views: List[String]) case class RevokedJsonV400(revoked: Boolean) diff --git a/obp-api/src/main/scala/code/model/User.scala b/obp-api/src/main/scala/code/model/User.scala index 8abb2e891..0e9e82c19 100644 --- a/obp-api/src/main/scala/code/model/User.scala +++ b/obp-api/src/main/scala/code/model/User.scala @@ -142,15 +142,15 @@ object UserX { Users.users.vend.saveResourceUser(ru) } - def getOrCreateDauthResourceUser(userId: String, provider: String) = { - findByUserId(userId).or( //first try to find the user by userId + def getOrCreateDauthResourceUser(username: String, provider: String) = { + findByUserName(username).or( //first try to find the user by userId Users.users.vend.createResourceUser( // Otherwise create a new user provider = provider, - providerId = Some(userId), + providerId = Some(username), None, - name = Some(userId), + name = Some(username), email = None, - userId = Some(userId), + userId = None, createdByUserInvitationId = None, company = None, lastMarketingAgreementSignedDate = None diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala index f71c62f5c..8116b0f28 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala @@ -143,7 +143,7 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { bank_id = testBankId1.value, role_name = CanUpdateBranch.toString() )) - val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(user_id ="xx", roles= createEntitlements) + val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(username ="xx", roles= createEntitlements) val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) val responseGet = makePostRequestAsync(requestGet, write(postJson)) Then("We should get a 200") From 37702994f7efdeaa5f5f06d720c2c86c2470c5a9 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Sun, 5 Dec 2021 09:22:48 -0600 Subject: [PATCH 289/293] tweaking v_resource_user id -> numeric_resource_user_id --- obp-api/src/main/scripts/sql/cre_views.sql | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scripts/sql/cre_views.sql b/obp-api/src/main/scripts/sql/cre_views.sql index 82dcc1c46..16cdd14ef 100644 --- a/obp-api/src/main/scripts/sql/cre_views.sql +++ b/obp-api/src/main/scripts/sql/cre_views.sql @@ -1,6 +1,14 @@ drop view v_resource_user cascade; -create or replace view v_resource_user as select userid_ resource_user_id, name_ username, email, id numeric_resource_user_id, provider_ provider, providerid provider_id from resourceuser; +create or replace view v_resource_user as +select +userid_ resource_user_id, +name_ username, +email, +id numeric_resource_user_id, +provider_ provider, +providerid provider_id +from resourceuser; drop view v_auth_user cascade; create view v_auth_user as From 0aba1c677e26a53d84d3f1fc49c8b975a19c9d2c Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Sun, 5 Dec 2021 09:41:17 -0600 Subject: [PATCH 290/293] /docfix tiny change to DAuth related endpoints documentation --- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index ad59eba42..28507dcdb 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2751,7 +2751,7 @@ trait APIMethods400 { | |For provider use "dauth" | - |This endpoint will create the User with user_id and provider if the User does not already exist. + |This endpoint will create the User with username and provider if the User does not already exist. | |Then it will create Entitlements i.e. grant Roles to the User. | @@ -4277,7 +4277,7 @@ trait APIMethods400 { | |For provider use "dauth" | - |This endpoint will create the (DAuth) User with user_id and provider if the User does not already exist. + |This endpoint will create the (DAuth) User with username and provider if the User does not already exist. | |${authenticationRequiredMessage(true)} and the logged in user needs to be account holder. | From 7bfae3727904f071ce0b2530ce13f6cf59202c38 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 6 Dec 2021 09:19:44 +0100 Subject: [PATCH 291/293] bugfix/remove the userId test for createUserWithRoles endpoint --- .../SwaggerDefinitionsJSON.scala | 2 +- .../code/api/v4_0_0/EntitlementTests.scala | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index d8be99d70..3b091f85d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4094,7 +4094,7 @@ object SwaggerDefinitionsJSON { List(PostViewJsonV400(viewIdExample.value, isSystemExample.value.toBoolean)) ) val postCreateUserWithRolesJsonV400 = PostCreateUserWithRolesJsonV400( - userIdExample.value, + usernameExample.value, s"dauth.${providerExample.value}", List(createEntitlementJSON) ) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala index 8116b0f28..b007fa04f 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EntitlementTests.scala @@ -134,24 +134,6 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers { } } - scenario("We try to - createUserWithRoles - short user_id ", ApiEndpoint3, VersionOfApi) { - And("We make the request") - val createEntitlements = List(CreateEntitlementJSON( - bank_id = testBankId1.value, - role_name = CanCreateBranch.toString() - ), CreateEntitlementJSON( - bank_id = testBankId1.value, - role_name = CanUpdateBranch.toString() - )) - val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(username ="xx", roles= createEntitlements) - val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1) - val responseGet = makePostRequestAsync(requestGet, write(postJson)) - Then("We should get a 200") - responseGet map { r => - r.code should equal(400) - r.body.toString contains (InvalidUserId) shouldBe(true) - } - } scenario("We try to - createUserWithRoles - wrong user provider ", ApiEndpoint3, VersionOfApi) { And("We make the request") val createEntitlements = List(CreateEntitlementJSON( From ca5b7caf45b46b8852ddf70c4e0993785b2556d9 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Tue, 7 Dec 2021 17:28:48 -0600 Subject: [PATCH 292/293] Tweaking 404 message --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 9a8b5dcaf..36078c94c 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -89,8 +89,8 @@ object ErrorMessages { val InvalidInBoundMapping = "OBP-10032: Incorrect inBoundMapping Format, it should be a json structure." val invalidIban = "OBP-10033: Invalid IBAN." val InvalidUrlParameters = "OBP-10034: Invalid URL parameters." - val InvalidUri = "OBP-10404: Request Not Found. The server has not found anything matching the Request-URI.Check your URL and the headers. " + - "NOTE: when it is POST or PUT api, the Content-Type must be `application/json`. OBP only support the json format body." + val InvalidUri = "OBP-10404: 404 Not Found. The server could not find the requested URI. Please double check your URL, headers and body. " + + "Note: When you are making a POST or PUT request, the Content-Type header MUST be `application/json`. Note: OBP only supports JSON formatted bodies." val ResourceDoesNotExist = "OBP-10405: Resource does not exist." val InvalidJsonValue = "OBP-10035: Incorrect json value." From a4a37a9d27d157b1b67df68b260927df9546dbf4 Mon Sep 17 00:00:00 2001 From: Simon Redfern Date: Sat, 11 Dec 2021 18:16:07 +0100 Subject: [PATCH 293/293] Bumping log4j.version to address CVE-2021-44228 (Log4Shell LogJam) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a2b5e94db..072bd1809 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ 1.8.2 3.4.1 9.4.12.v20180830 - 2.6.2 + 2.15.0 2016.11-RC6-SNAPSHOT UTF-8