Merge pull request #2669 from hongwei1/feature/addedTechnolegyField

Feature/added technolegy field
This commit is contained in:
Simon Redfern 2026-01-30 12:21:25 +01:00 committed by GitHub
commit 2f2401ed1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 687 additions and 370 deletions

View File

@ -17,11 +17,18 @@ ThisBuild / semanticdbVersion := "4.13.9"
// Fix dependency conflicts
ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always
ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-java8-compat" % VersionScheme.Always
lazy val liftVersion = "3.5.0"
lazy val akkaVersion = "2.5.32"
lazy val jettyVersion = "9.4.50.v20221201"
lazy val avroVersion = "1.8.2"
lazy val pekkoVersion = "1.4.0"
lazy val pekkoHttpVersion = "1.3.0"
lazy val http4sVersion = "0.23.30"
lazy val catsEffectVersion = "3.5.7"
lazy val ip4sVersion = "3.7.0"
lazy val jakartaMailVersion = "2.0.1"
lazy val commonSettings = Seq(
resolvers ++= Seq(
@ -42,8 +49,8 @@ lazy val obpCommons = (project in file("obp-commons"))
"net.liftweb" %% "lift-util" % liftVersion,
"net.liftweb" %% "lift-mapper" % liftVersion,
"org.scala-lang" % "scala-reflect" % "2.12.20",
"org.scalatest" %% "scalatest" % "3.2.15" % Test,
"org.scalactic" %% "scalactic" % "3.2.15",
"org.scalatest" %% "scalatest" % "3.0.9" % Test,
"org.scalactic" %% "scalactic" % "3.0.9",
"net.liftweb" %% "lift-json" % liftVersion,
"com.alibaba" % "transmittable-thread-local" % "2.11.5",
"org.apache.commons" % "commons-lang3" % "3.12.0",
@ -95,6 +102,20 @@ lazy val obpApi = (project in file("obp-api"))
"com.typesafe.akka" %% "akka-remote" % akkaVersion,
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion,
"com.typesafe.akka" %% "akka-http-core" % "10.1.6",
// Pekko (ActorSystem + Pekko HTTP used by OBP runtime components)
"org.apache.pekko" %% "pekko-actor" % pekkoVersion,
"org.apache.pekko" %% "pekko-remote" % pekkoVersion,
"org.apache.pekko" %% "pekko-slf4j" % pekkoVersion,
"org.apache.pekko" %% "pekko-stream" % pekkoVersion,
"org.apache.pekko" %% "pekko-http" % pekkoHttpVersion,
// http4s (v7.0.0 experimental stack)
"org.typelevel" %% "cats-effect" % catsEffectVersion,
"com.comcast" %% "ip4s-core" % ip4sVersion,
"org.http4s" %% "http4s-core" % http4sVersion,
"org.http4s" %% "http4s-dsl" % http4sVersion,
"org.http4s" %% "http4s-ember-server" % http4sVersion,
// Avro
"com.sksamuel.avro4s" %% "avro4s-core" % avroVersion,
@ -164,6 +185,9 @@ lazy val obpApi = (project in file("obp-api"))
// RabbitMQ
"com.rabbitmq" % "amqp-client" % "5.22.0",
"net.liftmodules" %% "amqp_3.1" % "1.5.0",
// Blockchain (Ethereum raw transaction decoding)
"org.web3j" % "core" % "4.14.0",
// Elasticsearch
"org.elasticsearch" % "elasticsearch" % "8.14.0",
@ -175,6 +199,7 @@ lazy val obpApi = (project in file("obp-api"))
// Utilities
"cglib" % "cglib" % "3.3.0",
"com.sun.activation" % "jakarta.activation" % "1.2.2",
"com.sun.mail" % "jakarta.mail" % jakartaMailVersion,
"com.nulab-inc" % "zxcvbn" % "1.9.0",
// Testing - temporarily disabled due to version incompatibility
@ -192,7 +217,7 @@ lazy val obpApi = (project in file("obp-api"))
// Test dependencies
"junit" % "junit" % "4.13.2" % Test,
"org.scalatest" %% "scalatest" % "3.2.15" % Test,
"org.scalatest" %% "scalatest" % "3.0.9" % Test,
"org.seleniumhq.selenium" % "htmlunit-driver" % "2.36.0" % Test,
"org.testcontainers" % "rabbitmq" % "1.20.3" % Test
)

View File

@ -35,7 +35,7 @@ import code.api.OBPRestHelper
import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints}
import code.api.util.ScannedApis
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.util.{ApiVersionStatus, ScannedApiVersion}
import com.openbankproject.commons.util.{ApiVersion, ApiVersionStatus}
import scala.collection.mutable.ArrayBuffer
@ -47,7 +47,7 @@ This file defines which endpoints from all the versions are available in v1
*/
object ApiCollector extends OBPRestHelper with MdcLoggable with ScannedApis {
//please modify these three parameter if it is not correct.
override val apiVersion = ScannedApiVersion("cds-au", "AU", "v1.0.0")
override val apiVersion = ApiVersion.auOpenBankingV100
val versionStatus = ApiVersionStatus.DRAFT.toString
private[this] val endpoints =

View File

@ -35,7 +35,7 @@ import code.api.OBPRestHelper
import code.api.util.APIUtil.{OBPEndpoint, ResourceDoc, getAllowedEndpoints}
import code.api.util.{ScannedApis}
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.util.{ApiVersionStatus, ScannedApiVersion}
import com.openbankproject.commons.util.{ApiVersion, ApiVersionStatus}
import scala.collection.mutable.ArrayBuffer
@ -45,7 +45,7 @@ import scala.collection.mutable.ArrayBuffer
This file defines which endpoints from all the versions are available in v1
*/
object ApiCollector extends OBPRestHelper with MdcLoggable with ScannedApis {
override val apiVersion = ScannedApiVersion("BAHRAIN-OBF", "BAHRAIN-OBF", "v1.0.0")
override val apiVersion = ApiVersion.bahrainObfV100
val versionStatus = ApiVersionStatus.DRAFT.toString
private[this] val endpoints =

View File

@ -149,6 +149,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md
object ResourceDocs600 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable {
val version: ApiVersion = ApiVersion.v6_0_0
val versionStatus = ApiVersionStatus.BLEEDING_EDGE.toString
override def includeTechnologyInResponse: Boolean = true
val routes: Seq[OBPEndpoint] = List(
ImplementationsResourceDocs.getResourceDocsObpV400,
ImplementationsResourceDocs.getResourceDocsSwagger,
@ -206,7 +207,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md
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, isVersion4OrHigher, locale)
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, locale, includeTechnology = includeTechnologyInResponse)
resourceDocsJson.resource_docs
case _ =>
contentParam match {
@ -247,4 +248,4 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md
}
}
}
}

View File

@ -65,6 +65,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
// We add previous APIMethods so we have access to the Resource Docs
self: OBPRestHelper =>
def includeTechnologyInResponse: Boolean = false
val ImplementationsResourceDocs = new Object() {
val localResourceDocs = ArrayBuffer[ResourceDoc]()
@ -346,7 +348,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
// Filter
val rdFiltered = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, resourceDocTags, partialFunctionNames)
// Format the data as json
JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isVersion4OrHigher, locale)
JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isVersion4OrHigher, locale, includeTechnology = includeTechnologyInResponse)
}
}
@ -500,7 +502,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
NewStyle.function.tryons(s"$UnknownError Can not prepare OBP resource docs.", 500, callContext) {
val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId)
val resourceDocs = ResourceDoc.getResourceDocs(operationIds)
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, locale)
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, locale, includeTechnology = includeTechnologyInResponse)
val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson))
resourceDocsJsonJValue.map(successJsonResponse(_))
}
@ -709,7 +711,7 @@ 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, isVersion4OrHigher, locale)
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, locale, includeTechnology = includeTechnologyInResponse)
resourceDocsJson.resource_docs
case _ =>
contentParam match {
@ -903,7 +905,7 @@ 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, isVersion4OrHigher, locale)
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, locale, includeTechnology = includeTechnologyInResponse)
resourceDocsJson.resource_docs
case _ =>
contentParam match {
@ -1257,4 +1259,3 @@ so the caller must specify any required filtering by catalog explicitly.
}

View File

@ -1796,7 +1796,8 @@ object SwaggerDefinitionsJSON {
lazy val implementedByJson = ImplementedByJson(
version = "1_4_0",
function = "getBranches"
function = "getBranches",
technology = None
)
// Used to describe the OBP API calls for documentation and API discovery purposes
lazy val canCreateCustomerSwagger = CanCreateCustomer()
@ -4018,7 +4019,7 @@ object SwaggerDefinitionsJSON {
lazy val topApiJson = TopApiJson(
count = 7076,
Implemented_by_partial_function = "getBanks",
implemented_in_version = "v1.2.1"
implemented_in_version = ApiVersion.v1_2_1.toString
)
lazy val topApisJson = TopApisJson(List(topApiJson))
@ -4129,7 +4130,7 @@ object SwaggerDefinitionsJSON {
lazy val callLimitPostJsonV600 = CallLimitPostJsonV600(
from_date = DateWithDayExampleObject,
to_date = DateWithDayExampleObject,
api_version = Some("v6.0.0"),
api_version = Some(ApiVersion.v6_0_0.toString),
api_name = Some("getConsumerCallLimits"),
bank_id = None,
per_second_call_limit = "100",
@ -4144,7 +4145,7 @@ object SwaggerDefinitionsJSON {
rate_limiting_id = "80e1e0b2-d8bf-4f85-a579-e69ef36e3305",
from_date = DateWithDayExampleObject,
to_date = DateWithDayExampleObject,
api_version = Some("v6.0.0"),
api_version = Some(ApiVersion.v6_0_0.toString),
api_name = Some("getConsumerCallLimits"),
bank_id = None,
per_second_call_limit = "100",
@ -5128,7 +5129,7 @@ object SwaggerDefinitionsJSON {
user_id = userIdExample.value,
allowed_attempts =3,
challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString,
link = "/obp/v4.0.0/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transaction-request-types/TRANSACTION_REQUEST_TYPE/transaction-requests/TRANSACTION_REQUEST_ID/challenge"
link = s"/obp/${ApiVersion.v4_0_0}/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transaction-request-types/TRANSACTION_REQUEST_TYPE/transaction-requests/TRANSACTION_REQUEST_ID/challenge"
)
lazy val transactionRequestWithChargeJSON400 = TransactionRequestWithChargeJSON400(
id = "4050046c-63b3-4868-8a22-14b4181d33a6",

View File

@ -654,6 +654,11 @@ object Constant extends MdcLoggable {
CAN_GRANT_ACCESS_TO_VIEWS,
CAN_REVOKE_ACCESS_TO_VIEWS,
)
final val TECHNOLOGY_LIFTWEB = "liftweb"
final val TECHNOLOGY_HTTP4S = "http4s"
}

View File

@ -1,10 +1,9 @@
package code.api.util.http4s
import cats.effect._
import code.api.APIFailureNewStyle
import code.api.util.ErrorMessages._
import code.api.util.CallContext
import net.liftweb.common.{Failure => LiftFailure}
import net.liftweb.json.{JInt, JString, parseOpt}
import net.liftweb.json.compactRender
import net.liftweb.json.JsonDSL._
import org.http4s._
@ -30,6 +29,8 @@ object ErrorResponseConverter {
implicit val formats: Formats = CustomJsonFormats.formats
private val jsonContentType: `Content-Type` = `Content-Type`(MediaType.application.json)
private val internalFieldsFailCode = "failCode"
private val internalFieldsFailMsg = "failMsg"
/**
* OBP standard error response format.
@ -51,39 +52,20 @@ object ErrorResponseConverter {
* Convert any error to http4s Response[IO].
*/
def toHttp4sResponse(error: Throwable, callContext: CallContext): IO[Response[IO]] = {
error match {
case e: APIFailureNewStyle => apiFailureToResponse(e, callContext)
case _ => unknownErrorToResponse(error, callContext)
parseApiFailureFromExceptionMessage(error).map { failure =>
createErrorResponse(failure.code, failure.message, callContext)
}.getOrElse {
unknownErrorToResponse(error, callContext)
}
}
/**
* Convert APIFailureNewStyle to http4s Response.
* Uses failCode as HTTP status and failMsg as error message.
*/
def apiFailureToResponse(failure: APIFailureNewStyle, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(failure.failCode, failure.failMsg)
val status = org.http4s.Status.fromInt(failure.failCode).getOrElse(org.http4s.Status.BadRequest)
IO.pure(
Response[IO](status)
.withEntity(toJsonString(errorJson))
.withContentType(jsonContentType)
.putHeaders(org.http4s.Header.Raw(CIString("Correlation-Id"), callContext.correlationId))
)
}
/**
* Convert Lift Box Failure to http4s Response.
* Returns 400 Bad Request with failure message.
*/
def boxFailureToResponse(failure: LiftFailure, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(400, failure.msg)
IO.pure(
Response[IO](org.http4s.Status.BadRequest)
.withEntity(toJsonString(errorJson))
.withContentType(jsonContentType)
.putHeaders(org.http4s.Header.Raw(CIString("Correlation-Id"), callContext.correlationId))
)
private def parseApiFailureFromExceptionMessage(error: Throwable): Option[OBPErrorResponse] = {
Option(error.getMessage).flatMap(parseOpt).flatMap { json =>
(json \ internalFieldsFailCode, json \ internalFieldsFailMsg) match {
case (JInt(code), JString(message)) => Some(OBPErrorResponse(code.toInt, message))
case _ => None
}
}
}
/**
@ -91,7 +73,7 @@ object ErrorResponseConverter {
* Returns 500 Internal Server Error.
*/
def unknownErrorToResponse(e: Throwable, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(500, s"$UnknownError: ${e.getMessage}")
val errorJson = OBPErrorResponse(500, UnknownError)
IO.pure(
Response[IO](org.http4s.Status.InternalServerError)
.withEntity(toJsonString(errorJson))

View File

@ -106,9 +106,14 @@ object Http4sRequestAttributes {
def executeAndRespond[A](req: Request[IO])(f: CallContext => Future[A])(implicit formats: Formats): IO[Response[IO]] = {
implicit val cc: CallContext = req.callContext
for {
result <- IO.fromFuture(IO(f(cc)))
jsonString = prettyRender(Extraction.decompose(result))
response <- Ok(jsonString)
attempted <- IO.fromFuture(IO(f(cc))).attempt
response <- attempted match {
case Right(result) =>
val jsonString = prettyRender(Extraction.decompose(result))
Ok(jsonString)
case Left(error) =>
ErrorResponseConverter.toHttp4sResponse(error, cc)
}
} yield response
}

View File

@ -10,6 +10,7 @@ import code.api.util.newstyle.ViewNewStyle
import code.api.util.{APIUtil, ApiRole, CallContext, NewStyle}
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.model._
import com.openbankproject.commons.util.ApiShortVersions
import com.github.dwickern.macros.NameOf.nameOf
import net.liftweb.common.{Box, Empty, Full}
import org.http4s._
@ -86,7 +87,7 @@ object ResourceDocMiddleware extends MdcLoggable {
def apply(resourceDocs: ArrayBuffer[ResourceDoc]): HttpRoutes[IO] => HttpRoutes[IO] = { routes =>
Kleisli[HttpF, Request[IO], Response[IO]] { req: Request[IO] =>
// Build initial CallContext from request
OptionT.liftF(Http4sCallContextBuilder.fromRequest(req, "v7.0.0")).flatMap { cc =>
OptionT.liftF(Http4sCallContextBuilder.fromRequest(req, ApiShortVersions.`v7.0.0`.toString)).flatMap { cc =>
ResourceDocMatcher.findResourceDoc(req.method.name, req.uri.path, resourceDocs) match {
case Some(resourceDoc) =>
val ccWithDoc = ResourceDocMatcher.attachToCallContext(cc, resourceDoc)

View File

@ -3,6 +3,7 @@ package code.api.v1_4_0
import code.api.Constant.{CREATE_LOCALISED_RESOURCE_DOC_JSON_TTL, LOCALISED_RESOURCE_DOC_PREFIX}
import code.api.berlin.group.v1_3.JvalueCaseClass
import code.api.cache.Caching
import code.api.Constant
import java.util.Date
import code.api.util.APIUtil.{EmptyBody, PrimaryDataBody, ResourceDoc}
import code.api.util.ApiTag.ResourceDocTag
@ -328,7 +329,8 @@ object JSONFactory1_4_0 extends MdcLoggable{
// Used to describe where an API call is implemented
case class ImplementedByJson (
version : String, // Short hand for the version e.g. "1_4_0" means Implementations1_4_0
function : String // The val / partial function that implements the call e.g. "getBranches"
function : String, // The val / partial function that implements the call e.g. "getBranches"
technology: Option[String] = None
)
case class ResourceDocMeta(
@ -525,11 +527,12 @@ object JSONFactory1_4_0 extends MdcLoggable{
locale: Option[String],// this will be in the cacheKey
resourceDocUpdatedTags: ResourceDoc,
isVersion4OrHigher:Boolean,// this will be in the cacheKey
includeTechnology: Boolean, // this will be in the cacheKey
urlParametersI18n:String ,
jsonRequestBodyFieldsI18n:String,
jsonResponseBodyFieldsI18n:String
): ResourceDocJson = {
val cacheKey = LOCALISED_RESOURCE_DOC_PREFIX + s"operationId:${operationId}-locale:$locale- isVersion4OrHigher:$isVersion4OrHigher".intern()
val cacheKey = LOCALISED_RESOURCE_DOC_PREFIX + s"operationId:${operationId}-locale:$locale- isVersion4OrHigher:$isVersion4OrHigher- includeTechnology:$includeTechnology".intern()
Caching.memoizeSyncWithImMemory(Some(cacheKey))(CREATE_LOCALISED_RESOURCE_DOC_JSON_TTL.seconds) {
val fieldsDescription =
if (resourceDocUpdatedTags.tags.toString.contains("Dynamic-Entity")
@ -564,6 +567,13 @@ object JSONFactory1_4_0 extends MdcLoggable{
val summary = resourceDocUpdatedTags.summary.replaceFirst("""\.(\s*)$""", "$1") // remove the ending dot in summary
val translatedSummary = I18NUtil.ResourceDocTranslation.translate(I18NResourceDocField.SUMMARY, resourceDocUpdatedTags.operationId, locale, summary)
val technology =
if (includeTechnology) {
Some(if (resourceDocUpdatedTags.http4sPartialFunction.isDefined) Constant.TECHNOLOGY_HTTP4S else Constant.TECHNOLOGY_LIFTWEB)
} else {
None
}
val resourceDoc = ResourceDocJson(
operation_id = resourceDocUpdatedTags.operationId,
request_verb = resourceDocUpdatedTags.requestVerb,
@ -575,7 +585,11 @@ object JSONFactory1_4_0 extends MdcLoggable{
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
implemented_by = ImplementedByJson(
version = resourceDocUpdatedTags.implementedInApiVersion.fullyQualifiedVersion,
function = resourceDocUpdatedTags.partialFunctionName,
technology = technology
), // was resourceDocUpdatedTags.implementedInApiVersion.noV
tags = resourceDocUpdatedTags.tags.map(i => i.tag),
typed_request_body = createTypedBody(resourceDocUpdatedTags.exampleRequestBody),
typed_success_response_body = createTypedBody(resourceDocUpdatedTags.successResponseBody),
@ -592,7 +606,7 @@ object JSONFactory1_4_0 extends MdcLoggable{
}}
def createLocalisedResourceDocJson(rd: ResourceDoc, isVersion4OrHigher:Boolean, locale: Option[String], urlParametersI18n:String ,jsonRequestBodyFieldsI18n:String, jsonResponseBodyFieldsI18n:String) : ResourceDocJson = {
def createLocalisedResourceDocJson(rd: ResourceDoc, isVersion4OrHigher:Boolean, locale: Option[String], includeTechnology: Boolean, urlParametersI18n:String ,jsonRequestBodyFieldsI18n:String, jsonResponseBodyFieldsI18n:String) : ResourceDocJson = {
// We MUST recompute all resource doc values due to translation via Web UI props --> now need to wait $CREATE_LOCALISED_RESOURCE_DOC_JSON_TTL seconds
val userDefinedEndpointTags = getAllEndpointTagsBox(rd.operationId).map(endpointTag =>ResourceDocTag(endpointTag.tagName))
val resourceDocWithUserDefinedEndpointTags: ResourceDoc = rd.copy(tags = userDefinedEndpointTags++ rd.tags)
@ -602,6 +616,7 @@ object JSONFactory1_4_0 extends MdcLoggable{
locale: Option[String],
resourceDocWithUserDefinedEndpointTags,
isVersion4OrHigher: Boolean,
includeTechnology: Boolean,
urlParametersI18n: String,
jsonRequestBodyFieldsI18n: String,
jsonResponseBodyFieldsI18n: String
@ -609,7 +624,7 @@ object JSONFactory1_4_0 extends MdcLoggable{
}
def createResourceDocsJson(resourceDocList: List[ResourceDoc], isVersion4OrHigher:Boolean, locale: Option[String]) : ResourceDocsJson = {
def createResourceDocsJson(resourceDocList: List[ResourceDoc], isVersion4OrHigher:Boolean, locale: Option[String], includeTechnology: Boolean = false) : ResourceDocsJson = {
val urlParametersI18n = I18NUtil.ResourceDocTranslation.translate(
I18NResourceDocField.URL_PARAMETERS,
"resourceDocUrlParametersString_i180n",
@ -632,11 +647,11 @@ object JSONFactory1_4_0 extends MdcLoggable{
if(isVersion4OrHigher){
ResourceDocsJson(
resourceDocList.map(createLocalisedResourceDocJson(_,isVersion4OrHigher, locale, urlParametersI18n, jsonRequestBodyFields, jsonResponseBodyFields)),
resourceDocList.map(createLocalisedResourceDocJson(_,isVersion4OrHigher, locale, includeTechnology, urlParametersI18n, jsonRequestBodyFields, jsonResponseBodyFields)),
meta=Some(ResourceDocMeta(new Date(), resourceDocList.length))
)
} else {
ResourceDocsJson(resourceDocList.map(createLocalisedResourceDocJson(_,false, locale, urlParametersI18n, jsonRequestBodyFields, jsonResponseBodyFields)))
ResourceDocsJson(resourceDocList.map(createLocalisedResourceDocJson(_,false, locale, includeTechnology, urlParametersI18n, jsonRequestBodyFields, jsonResponseBodyFields)))
}
}

View File

@ -1283,7 +1283,7 @@ object JSONFactory400 {
).mkString("")
val otpViaApiPath = Constant.HostName + List(
"/obp/v4.0.0/banks/",
s"/obp/${ApiVersion.v4_0_0}/banks/",
stringOrNull(tr.from.bank_id),
"/accounts/",
stringOrNull(tr.from.account_id),
@ -2072,4 +2072,3 @@ object JSONFactory400 {
}
}
}

View File

@ -2037,18 +2037,18 @@ trait APIMethods600 {
ListResult(
"scanned_api_versions",
List(
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v1.2.1", fully_qualified_version = "OBPv1.2.1", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v1.3.0", fully_qualified_version = "OBPv1.3.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v1.4.0", fully_qualified_version = "OBPv1.4.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v2.0.0", fully_qualified_version = "OBPv2.0.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v2.1.0", fully_qualified_version = "OBPv2.1.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v2.2.0", fully_qualified_version = "OBPv2.2.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v3.0.0", fully_qualified_version = "OBPv3.0.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v3.1.0", fully_qualified_version = "OBPv3.1.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v4.0.0", fully_qualified_version = "OBPv4.0.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v5.0.0", fully_qualified_version = "OBPv5.0.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v5.1.0", fully_qualified_version = "OBPv5.1.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = "v6.0.0", fully_qualified_version = "OBPv6.0.0", is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v1_2_1.toString, fully_qualified_version = ApiVersion.v1_2_1.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v1_3_0.toString, fully_qualified_version = ApiVersion.v1_3_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v1_4_0.toString, fully_qualified_version = ApiVersion.v1_4_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v2_0_0.toString, fully_qualified_version = ApiVersion.v2_0_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v2_1_0.toString, fully_qualified_version = ApiVersion.v2_1_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v2_2_0.toString, fully_qualified_version = ApiVersion.v2_2_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v3_0_0.toString, fully_qualified_version = ApiVersion.v3_0_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v3_1_0.toString, fully_qualified_version = ApiVersion.v3_1_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v4_0_0.toString, fully_qualified_version = ApiVersion.v4_0_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v5_0_0.toString, fully_qualified_version = ApiVersion.v5_0_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v5_1_0.toString, fully_qualified_version = ApiVersion.v5_1_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "obp", api_standard = "OBP", api_short_version = ApiVersion.v6_0_0.toString, fully_qualified_version = ApiVersion.v6_0_0.fullyQualifiedVersion, is_active = true),
ScannedApiVersionJsonV600(url_prefix = "berlin-group", api_standard = "BG", api_short_version = "v1.3", fully_qualified_version = "BGv1.3", is_active = false)
)
),
@ -4526,7 +4526,7 @@ trait APIMethods600 {
lazy val getWebUiProp: OBPEndpoint = {
case "webui-props" :: webUiPropName :: Nil JsonGet req => {
cc => implicit val ec = EndpointContext(Some(cc))
logger.info(s"========== GET /obp/v6.0.0/webui-props/$webUiPropName (SINGLE PROP) called ==========")
logger.info(s"========== GET /obp/${ApiVersion.v6_0_0}/webui-props/$webUiPropName (SINGLE PROP) called ==========")
val active = ObpS.param("active").getOrElse("false")
for {
invalidMsg <- Future(s"""$InvalidFilterParameterFormat `active` must be a boolean, but current `active` value is: ${active} """)
@ -4628,7 +4628,7 @@ trait APIMethods600 {
case "webui-props":: Nil JsonGet req => {
cc => implicit val ec = EndpointContext(Some(cc))
val what = ObpS.param("what").getOrElse("active")
logger.info(s"========== GET /obp/v6.0.0/webui-props (ALL PROPS) called with what=$what ==========")
logger.info(s"========== GET /obp/${ApiVersion.v6_0_0}/webui-props (ALL PROPS) called with what=$what ==========")
for {
callContext <- Future.successful(cc.callContext)
_ <- NewStyle.function.tryons(s"""$InvalidFilterParameterFormat `what` must be one of: active, database, config. Current value: $what""", 400, callContext) {
@ -4654,11 +4654,11 @@ trait APIMethods600 {
explicitWebUiPropsWithSource ++ configPropsNotInDatabase
}
} yield {
logger.info(s"========== GET /obp/v6.0.0/webui-props returning ${result.size} records ==========")
logger.info(s"========== GET /obp/${ApiVersion.v6_0_0}/webui-props returning ${result.size} records ==========")
result.foreach { prop =>
logger.info(s" - name: ${prop.name}, value: ${prop.value}, webUiPropsId: ${prop.webUiPropsId}")
}
logger.info(s"========== END GET /obp/v6.0.0/webui-props ==========")
logger.info(s"========== END GET /obp/${ApiVersion.v6_0_0}/webui-props ==========")
(ListResult("webui_props", result), HttpCode.`200`(callContext))
}
}
@ -7220,11 +7220,11 @@ trait APIMethods600 {
schema = net.liftweb.json.parse("""{"description": "User preferences", "required": ["theme"], "properties": {"theme": {"type": "string"}, "language": {"type": "string"}}}""").asInstanceOf[net.liftweb.json.JsonAST.JObject],
_links = Some(DynamicEntityLinksJsonV600(
related = List(
RelatedLinkJsonV600("list", "/obp/v6.0.0/my/customer_preferences", "GET"),
RelatedLinkJsonV600("create", "/obp/v6.0.0/my/customer_preferences", "POST"),
RelatedLinkJsonV600("read", "/obp/v6.0.0/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "GET"),
RelatedLinkJsonV600("update", "/obp/v6.0.0/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "PUT"),
RelatedLinkJsonV600("delete", "/obp/v6.0.0/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "DELETE")
RelatedLinkJsonV600("list", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences", "GET"),
RelatedLinkJsonV600("create", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences", "POST"),
RelatedLinkJsonV600("read", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "GET"),
RelatedLinkJsonV600("update", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "PUT"),
RelatedLinkJsonV600("delete", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "DELETE")
)
))
)
@ -7284,11 +7284,11 @@ trait APIMethods600 {
schema = net.liftweb.json.parse("""{"description": "User preferences", "required": ["theme"], "properties": {"theme": {"type": "string"}, "language": {"type": "string"}}}""").asInstanceOf[net.liftweb.json.JsonAST.JObject],
_links = Some(DynamicEntityLinksJsonV600(
related = List(
RelatedLinkJsonV600("list", "/obp/v6.0.0/my/customer_preferences", "GET"),
RelatedLinkJsonV600("create", "/obp/v6.0.0/my/customer_preferences", "POST"),
RelatedLinkJsonV600("read", "/obp/v6.0.0/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "GET"),
RelatedLinkJsonV600("update", "/obp/v6.0.0/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "PUT"),
RelatedLinkJsonV600("delete", "/obp/v6.0.0/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "DELETE")
RelatedLinkJsonV600("list", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences", "GET"),
RelatedLinkJsonV600("create", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences", "POST"),
RelatedLinkJsonV600("read", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "GET"),
RelatedLinkJsonV600("update", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "PUT"),
RelatedLinkJsonV600("delete", s"/obp/${ApiVersion.v6_0_0}/my/customer_preferences/CUSTOMER_PREFERENCES_ID", "DELETE")
)
))
)

View File

@ -40,6 +40,7 @@ import com.openbankproject.commons.model.{
CustomerAttribute,
_
}
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.common.Box
import java.util.Date
@ -1540,8 +1541,8 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable {
val entityName = entity.entityName
val idPlaceholder = StringHelpers.snakify(entityName + "Id").toUpperCase()
val baseUrl = entity.bankId match {
case Some(bankId) => s"/obp/v6.0.0/banks/$bankId/my/$entityName"
case None => s"/obp/v6.0.0/my/$entityName"
case Some(bankId) => s"/obp/${ApiVersion.v6_0_0}/banks/$bankId/my/$entityName"
case None => s"/obp/${ApiVersion.v6_0_0}/my/$entityName"
}
val links = DynamicEntityLinksJsonV600(

View File

@ -9,7 +9,7 @@ import code.api.util.APIUtil.{EmptyBody, _}
import code.api.util.ApiRole.canGetCardsForBank
import code.api.util.ApiTag._
import code.api.util.ErrorMessages._
import code.api.util.http4s.{Http4sRequestAttributes, ResourceDocMiddleware}
import code.api.util.http4s.{ErrorResponseConverter, Http4sRequestAttributes, ResourceDocMiddleware}
import code.api.util.http4s.Http4sRequestAttributes.{RequestOps, EndpointHelpers}
import code.api.util.{ApiVersionUtils, CallContext, CustomJsonFormats, NewStyle}
import code.api.v1_3_0.JSONFactory1_3_0
@ -26,6 +26,7 @@ import org.http4s.dsl.io._
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.Future
import scala.language.{higherKinds, implicitConversions}
import code.util.Helper
object Http4s700 {
@ -201,25 +202,39 @@ object Http4s700 {
val getResourceDocsObpV700: HttpRoutes[IO] = HttpRoutes.of[IO] {
case req @ GET -> `prefixPath` / "resource-docs" / requestedApiVersionString / "obp" =>
implicit val cc: CallContext = req.callContext
val queryParams = req.uri.query.multiParams
val tags = queryParams
.get("tags")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).map(ResourceDocTag(_)).toList)
val functions = queryParams
.get("functions")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).toList)
val localeParam = queryParams
.get("locale")
.flatMap(_.headOption)
.orElse(queryParams.get("language").flatMap(_.headOption))
.map(_.trim)
.filter(_.nonEmpty)
EndpointHelpers.executeAndRespond(req) { _ =>
val queryParams = req.uri.query.multiParams
val tags = queryParams
.get("tags")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).map(ResourceDocTag(_)).toList)
val functions = queryParams
.get("functions")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).toList)
val localeParam = queryParams
.get("locale")
.flatMap(_.headOption)
.orElse(queryParams.get("language").flatMap(_.headOption))
.map(_.trim)
.filter(_.nonEmpty)
for {
requestedApiVersion <- Future(ApiVersionUtils.valueOf(requestedApiVersionString))
resourceDocs = ResourceDocs140.ImplementationsResourceDocs.getResourceDocsList(requestedApiVersion).getOrElse(Nil)
filteredDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, tags, functions)
} yield JSONFactory1_4_0.createResourceDocsJson(filteredDocs, isVersion4OrHigher = true, localeParam)
requestedApiVersion <- NewStyle.function.tryons(
failMsg = s"$InvalidApiVersionString Current value: $requestedApiVersionString",
failCode = 400,
callContext = Some(cc)
) {
ApiVersionUtils.valueOf(requestedApiVersionString)
}
_ <- Helper.booleanToFuture(
failMsg = s"$InvalidApiVersionString This server supports only ${ApiVersion.v7_0_0}. Current value: $requestedApiVersionString",
failCode = 400,
cc = Some(cc)
) {
requestedApiVersion == ApiVersion.v7_0_0
}
http4sOnlyDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs.toList, tags, functions)
} yield JSONFactory1_4_0.createResourceDocsJson(http4sOnlyDocs, isVersion4OrHigher = true, localeParam, includeTechnology = true)
}
}

View File

@ -0,0 +1,49 @@
package code.api.ResourceDocs1_4_0
import code.api.Constant
import code.setup.{PropsReset, ServerSetup}
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.json.JsonAST.{JArray, JNothing, JNull, JString}
class ResourceDocsTechnologyTest extends ServerSetup with PropsReset {
private val v600 = ApiVersion.v6_0_0.toString
private val v500 = ApiVersion.v5_0_0.toString
feature("ResourceDocs implemented_by.technology") {
scenario(s"$v600 resource-docs should include implemented_by.technology") {
setPropsValues("resource_docs_requires_role" -> "false")
val request = (baseRequest / "obp" / v600 / "resource-docs" / v600 / "obp").GET
val response = makeGetRequest(request)
response.code should equal(200)
(response.body \ "resource_docs") match {
case JArray(docs) =>
val technology = docs.head \ "implemented_by" \ "technology"
technology should equal(JString(Constant.TECHNOLOGY_LIFTWEB))
case _ =>
fail("Expected resource_docs field to be an array")
}
}
scenario(s"$v500 resource-docs should not include implemented_by.technology") {
setPropsValues("resource_docs_requires_role" -> "false")
val request = (baseRequest / "obp" / v500 / "resource-docs" / v500 / "obp").GET
val response = makeGetRequest(request)
response.code should equal(200)
(response.body \ "resource_docs") match {
case JArray(docs) =>
val technology = docs.head \ "implemented_by" \ "technology"
technology match {
case JNothing | JNull => succeed
case _ => fail("Expected implemented_by.technology to be absent for v5.0.0 resource-docs")
}
case _ =>
fail("Expected resource_docs field to be an array")
}
}
}
}

View File

@ -1,5 +1,6 @@
package code.api.ResourceDocs1_4_0
import code.api.Constant
import code.api.ResourceDocs1_4_0.ResourceDocs140.ImplementationsResourceDocs
import code.api.berlin.group.ConstantsBG
import code.api.util.APIUtil.OAuth._
@ -21,6 +22,31 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
object VersionOfApi extends Tag(ApiVersion.v1_4_0.toString)
object ApiEndpoint1 extends Tag(nameOf(ImplementationsResourceDocs.getResourceDocsObp))
object ApiEndpoint2 extends Tag(nameOf(ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp))
private val v600 = ApiVersion.v6_0_0.toString
private val fq600 = ApiVersion.v6_0_0.fullyQualifiedVersion
private val v510 = ApiVersion.v5_1_0.toString
private val fq510 = ApiVersion.v5_1_0.fullyQualifiedVersion
private val v500 = ApiVersion.v5_0_0.toString
private val fq500 = ApiVersion.v5_0_0.fullyQualifiedVersion
private val v400 = ApiVersion.v4_0_0.toString
private val fq400 = ApiVersion.v4_0_0.fullyQualifiedVersion
private val v310 = ApiVersion.v3_1_0.toString
private val fq310 = ApiVersion.v3_1_0.fullyQualifiedVersion
private val v300 = ApiVersion.v3_0_0.toString
private val fq300 = ApiVersion.v3_0_0.fullyQualifiedVersion
private val v220 = ApiVersion.v2_2_0.toString
private val fq220 = ApiVersion.v2_2_0.fullyQualifiedVersion
private val v210 = ApiVersion.v2_1_0.toString
private val fq210 = ApiVersion.v2_1_0.fullyQualifiedVersion
private val v200 = ApiVersion.v2_0_0.toString
private val fq200 = ApiVersion.v2_0_0.fullyQualifiedVersion
private val v140 = ApiVersion.v1_4_0.toString
private val fq140 = ApiVersion.v1_4_0.fullyQualifiedVersion
private val v130 = ApiVersion.v1_3_0.toString
private val fq130 = ApiVersion.v1_3_0.fullyQualifiedVersion
private val v121 = ApiVersion.v1_2_1.toString
private val fq121 = ApiVersion.v1_2_1.fullyQualifiedVersion
override def beforeEach() = {
super.beforeEach()
@ -68,13 +94,23 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
def stringToNodeSeq(html : String) : NodeSeq = {
val newHtmlString =scala.xml.XML.loadString("<div>" + html + "</div>").toString()
//Note: `parse` method: We much enclose the div, otherwise only the first element is returned.
Html5.parse(newHtmlString).head
Html5.parse(newHtmlString).headOption.getOrElse(NodeSeq.Empty)
}
feature(s"test ${ApiEndpoint1.name} ") {
scenario(s"We will test ${ApiEndpoint1.name} Api -v6.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v600", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV6_0Request / "resource-docs" / v600 / "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)
responseDocs.resource_docs.head.implemented_by.technology shouldBe Some(Constant.TECHNOLOGY_LIFTWEB)
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq600", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV6_0Request / "resource-docs" / fq600 / "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]
@ -82,72 +118,64 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv6.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV6_0Request / "resource-docs" / "OBPv6.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 -v5.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / "v5.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v500", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / v500 / "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)
responseDocs.resource_docs.head.implemented_by.technology shouldBe None
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario("Test OpenAPI endpoint with valid parameters", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("content", "static"), ("tags", "Account"))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("content", "static"), ("tags", "Account"))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(200)
}
scenario("Test OpenAPI endpoint with invalid content parameter", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("content", "invalid"))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("content", "invalid"))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(400)
responseGetOpenAPI.body.toString should include("OBP-10052")
}
scenario("Test OpenAPI endpoint with empty tags parameter", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("tags", ""))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("tags", ""))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(400)
responseGetOpenAPI.body.toString should include("OBP-10053")
}
scenario("Test OpenAPI endpoint with empty functions parameter", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("functions", ""))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("functions", ""))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(400)
responseGetOpenAPI.body.toString should include("OBP-10054")
}
scenario("Test OpenAPI endpoint with valid multiple tags", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("tags", "Account,Bank"), ("content", "static"))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("tags", "Account,Bank"), ("content", "static"))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(200)
}
scenario("Test OpenAPI endpoint with Account-Firehose tag and static content", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("content", "static"), ("tags", "Account-Firehose"))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("content", "static"), ("tags", "Account-Firehose"))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(200)
}
scenario("Test OpenAPI endpoint with empty api-collection-id parameter", ApiEndpoint1, VersionOfApi) {
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / "v6.0.0" / "openapi").GET <<? List(("api-collection-id", ""))
val requestGetOpenAPI = (ResourceDocsV6_0Request / "resource-docs" / v600 / "openapi").GET <<? List(("api-collection-id", ""))
val responseGetOpenAPI = makeGetRequest(requestGetOpenAPI)
responseGetOpenAPI.code should equal(400)
responseGetOpenAPI.body.toString should include(InvalidApiCollectionIdParameter)
}
scenario(s"We will test ${ApiEndpoint1.name} Api -v5.1.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / "v5.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v510", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / v510 / "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]
@ -156,8 +184,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint1.name} Api -OBPv5.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / "OBPv5.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq500", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV5_0Request / "resource-docs" / fq500 / "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]
@ -166,8 +194,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / "v4.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v400", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v400 / "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]
@ -176,8 +204,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv4.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq400", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq400 / "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]
@ -186,8 +214,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v3.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v310", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v310 / "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]
@ -197,8 +225,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv3.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq310", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq310 / "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]
@ -207,8 +235,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v3.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v300", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v300 / "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]
@ -217,8 +245,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv3.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq300", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq300 / "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]
@ -227,8 +255,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v2.2.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v220", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v220 / "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]
@ -237,8 +265,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv2.2.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq220", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq220 / "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]
@ -247,8 +275,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v2.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v210", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v210 / "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]
@ -257,8 +285,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv2.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq210", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq210 / "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]
@ -267,8 +295,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v2.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v200", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v200 / "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]
@ -277,8 +305,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv2.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq200", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq200 / "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]
@ -287,16 +315,16 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v1.4.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v140", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v140 / "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 / "resource-docs" / "OBPv1.4.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq140", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq140 / "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]
@ -305,8 +333,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v1.3.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v130", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v130 / "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]
@ -315,8 +343,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv1.3.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq130", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq130 / "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]
@ -325,8 +353,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "v1.2.1" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$v121", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v121 / "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]
@ -335,8 +363,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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 / "resource-docs" / "OBPv1.2.1" / "obp").GET
scenario(s"We will test ${ApiEndpoint1.name} Api -$fq121", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / fq121 / "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]
@ -385,11 +413,11 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
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) {
scenario(s"We will test ${ApiEndpoint1.name} Api -$v400 - 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 requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v400 / "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]
@ -397,11 +425,11 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseGetObp.toString contains(AuthenticatedUserIsRequired) should be (true)
}
scenario(s"We will test ${ApiEndpoint1.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) {
scenario(s"We will test ${ApiEndpoint1.name} Api -$v400 - 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 requestGetObp = (ResourceDocsV4_0Request / "resource-docs" / v400 / "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]
@ -413,8 +441,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
}
feature(s"test ${ApiEndpoint2.name} ") {
scenario(s"We will test ${ApiEndpoint2.name} Api -v6.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v6.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v600", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v600 / "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]
@ -422,8 +450,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv6.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv6.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq600", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq600 / "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]
@ -431,8 +459,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
//This should not throw any exceptions
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v5.0.0/v4.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v5.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v500/$v400", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v500 / "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]
@ -441,8 +469,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v4.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v4.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v400", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v400 / "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]
@ -451,8 +479,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv4.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv4.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq400", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq400 / "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]
@ -461,8 +489,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v3.1.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v3.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v310", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v310 / "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]
@ -472,8 +500,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv3.1.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv3.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq310", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq310 / "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]
@ -482,8 +510,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v3.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v3.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v300", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v300 / "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]
@ -492,8 +520,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv3.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv3.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq300", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq300 / "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]
@ -502,8 +530,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v2.2.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v2.2.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v220", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v220 / "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]
@ -512,8 +540,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv2.2.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv2.2.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq220", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq220 / "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]
@ -522,8 +550,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v2.1.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v2.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v210", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v210 / "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]
@ -532,8 +560,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv2.1.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv2.1.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq210", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq210 / "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]
@ -542,8 +570,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v2.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v2.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v200", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v200 / "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]
@ -552,8 +580,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv2.0.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv2.0.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq200", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq200 / "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]
@ -562,16 +590,16 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v1.4.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.4.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v140", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v140 / "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 ${ApiEndpoint2.name} Api -OBPv1.4.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv1.4.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq140", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq140 / "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]
@ -580,8 +608,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v1.3.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.3.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v130", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v130 / "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]
@ -590,8 +618,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv1.3.0", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv1.3.0" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq130", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq130 / "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]
@ -600,8 +628,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v1.2.1", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "v1.2.1" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$v121", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v121 / "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]
@ -610,8 +638,8 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -OBPv1.2.1", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / "OBPv1.2.1" / "obp").GET
scenario(s"We will test ${ApiEndpoint2.name} Api -$fq121", ApiEndpoint1, VersionOfApi) {
val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / fq121 / "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]
@ -660,11 +688,11 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseDocs.resource_docs.map(responseDoc => stringToNodeSeq(responseDoc.description))
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v4.0.0 - resource_docs_requires_role props", ApiEndpoint1, VersionOfApi) {
scenario(s"We will test ${ApiEndpoint2.name} Api -$v400 - 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 requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v400 / "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]
@ -672,11 +700,11 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with
responseGetObp.toString contains(AuthenticatedUserIsRequired) should be (true)
}
scenario(s"We will test ${ApiEndpoint2.name} Api -v4.0.0 - resource_docs_requires_role props- login in user", ApiEndpoint1, VersionOfApi) {
scenario(s"We will test ${ApiEndpoint2.name} Api -$v400 - 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 requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "resource-docs" / v400 / "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]

View File

@ -2,6 +2,7 @@ package code.api.util.http4s
import cats.effect.IO
import cats.effect.unsafe.implicits.global
import com.openbankproject.commons.util.ApiShortVersions
import net.liftweb.common.{Empty, Full}
import org.http4s._
import org.http4s.dsl.io._
@ -23,49 +24,51 @@ import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers, Tag}
class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenWhenThen {
object Http4sCallContextBuilderTag extends Tag("Http4sCallContextBuilder")
private val v700 = ApiShortVersions.`v7.0.0`.toString
private val base = s"/obp/$v700"
feature("Http4sCallContextBuilder - URL extraction") {
scenario("Extract URL with path only", Http4sCallContextBuilderTag) {
Given("A request with path /obp/v7.0.0/banks")
Given(s"A request with path $base/banks")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("URL should match the request URI")
callContext.url should equal("/obp/v7.0.0/banks")
callContext.url should equal(s"$base/banks")
}
scenario("Extract URL with query parameters", Http4sCallContextBuilderTag) {
Given("A request with query parameters")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks?limit=10&offset=0")
uri = Uri.unsafeFromString(s"$base/banks?limit=10&offset=0")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("URL should include query parameters")
callContext.url should equal("/obp/v7.0.0/banks?limit=10&offset=0")
callContext.url should equal(s"$base/banks?limit=10&offset=0")
}
scenario("Extract URL with path parameters", Http4sCallContextBuilderTag) {
Given("A request with path parameters")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1")
uri = Uri.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("URL should include path parameters")
callContext.url should equal("/obp/v7.0.0/banks/gh.29.de/accounts/test1")
callContext.url should equal(s"$base/banks/gh.29.de/accounts/test1")
}
}
@ -75,7 +78,7 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A request with multiple headers")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("Content-Type"), "application/json"),
Header.Raw(org.typelevel.ci.CIString("Accept"), "application/json"),
@ -83,7 +86,7 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Headers should be converted to HTTPParam list")
callContext.requestHeaders should not be empty
@ -96,11 +99,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A request with no custom headers")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Headers list should be empty or contain only default headers")
// http4s may add default headers, so we just check it's a list
@ -115,11 +118,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val jsonBody = """{"name": "Test Bank", "id": "test-bank-1"}"""
val request = Request[IO](
method = Method.POST,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withEntity(jsonBody)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Body should be extracted as Some(string)")
callContext.httpBody should be(Some(jsonBody))
@ -129,11 +132,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A GET request with no body")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Body should be None")
callContext.httpBody should be(None)
@ -144,11 +147,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val jsonBody = """{"name": "Updated Bank"}"""
val request = Request[IO](
method = Method.PUT,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks/test-bank-1")
uri = Uri.unsafeFromString(s"$base/banks/test-bank-1")
).withEntity(jsonBody)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Body should be extracted")
callContext.httpBody should be(Some(jsonBody))
@ -162,13 +165,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val requestId = "test-correlation-id-12345"
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("X-Request-ID"), requestId)
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Correlation ID should match the header value")
callContext.correlationId should equal(requestId)
@ -178,11 +181,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A request without X-Request-ID header")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Correlation ID should be generated (UUID format)")
callContext.correlationId should not be empty
@ -198,13 +201,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val clientIp = "192.168.1.100"
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("X-Forwarded-For"), clientIp)
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("IP address should match the header value")
callContext.ipAddress should equal(clientIp)
@ -215,13 +218,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val forwardedFor = "192.168.1.100, 10.0.0.1, 172.16.0.1"
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("X-Forwarded-For"), forwardedFor)
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("IP address should be the first IP in the list")
callContext.ipAddress should equal("192.168.1.100")
@ -231,11 +234,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A request without X-Forwarded-For or remote address")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("IP address should be empty string")
callContext.ipAddress should equal("")
@ -249,13 +252,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val token = "eyJhbGciOiJIUzI1NiJ9.eyIiOiIifQ.test"
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("DirectLogin"), s"token=$token")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("DirectLogin params should contain token")
callContext.directLoginParams should contain key "token"
@ -267,13 +270,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val token = "eyJhbGciOiJIUzI1NiJ9.eyIiOiIifQ.test"
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("Authorization"), s"DirectLogin token=$token")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("DirectLogin params should contain token")
callContext.directLoginParams should contain key "token"
@ -287,13 +290,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A request with DirectLogin username and password")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("DirectLogin"), """username="testuser", password="testpass", consumer_key="key123"""")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("DirectLogin params should contain all parameters")
callContext.directLoginParams should contain key "username"
@ -309,13 +312,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val oauthHeader = """OAuth oauth_consumer_key="consumer123", oauth_token="token456", oauth_signature="sig789""""
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("Authorization"), oauthHeader)
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("OAuth params should be extracted")
callContext.oAuthParams should contain key "oauth_consumer_key"
@ -334,13 +337,13 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val bearerToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test.signature"
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("Authorization"), s"Bearer $bearerToken")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Authorization header should be stored")
callContext.authReqHeaderField should equal(Full(s"Bearer $bearerToken"))
@ -350,11 +353,11 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A request without Authorization header")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Auth header field should be Empty")
callContext.authReqHeaderField should equal(Empty)
@ -373,40 +376,40 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
Given("A POST request")
val request = Request[IO](
method = Method.POST,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("Verb should be POST")
callContext.verb should equal("POST")
}
scenario("Set implementedInVersion from parameter", Http4sCallContextBuilderTag) {
Given("A request with API version v7.0.0")
Given(s"A request with API version $v700")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext with version parameter")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("implementedInVersion should match the parameter")
callContext.implementedInVersion should equal("v7.0.0")
callContext.implementedInVersion should equal(v700)
}
scenario("Set startTime to current date", Http4sCallContextBuilderTag) {
Given("A request")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks")
uri = Uri.unsafeFromString(s"$base/banks")
)
When("Building CallContext")
val beforeTime = new java.util.Date()
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
val afterTime = new java.util.Date()
Then("startTime should be set and within reasonable range")
@ -427,7 +430,7 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
val request = Request[IO](
method = Method.POST,
uri = Uri.unsafeFromString("/obp/v7.0.0/banks?limit=10")
uri = Uri.unsafeFromString(s"$base/banks?limit=10")
).withHeaders(
Header.Raw(org.typelevel.ci.CIString("Content-Type"), "application/json"),
Header.Raw(org.typelevel.ci.CIString("DirectLogin"), s"token=$token"),
@ -436,12 +439,12 @@ class Http4sCallContextBuilderTest extends FeatureSpec with Matchers with GivenW
).withEntity(jsonBody)
When("Building CallContext")
val callContext = Http4sCallContextBuilder.fromRequest(request, "v7.0.0").unsafeRunSync()
val callContext = Http4sCallContextBuilder.fromRequest(request, v700).unsafeRunSync()
Then("All fields should be populated correctly")
callContext.url should equal("/obp/v7.0.0/banks?limit=10")
callContext.url should equal(s"$base/banks?limit=10")
callContext.verb should equal("POST")
callContext.implementedInVersion should equal("v7.0.0")
callContext.implementedInVersion should equal(v700)
callContext.correlationId should equal(correlationId)
callContext.ipAddress should equal(clientIp)
callContext.httpBody should be(Some(jsonBody))

View File

@ -2,6 +2,7 @@ package code.api.util.http4s
import code.api.util.APIUtil.ResourceDoc
import code.api.util.ApiTag.ResourceDocTag
import com.openbankproject.commons.util.ApiShortVersions
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.json.JsonAST.JObject
import org.http4s._
@ -25,6 +26,8 @@ import scala.collection.mutable.ArrayBuffer
class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThen {
object ResourceDocMatcherTag extends Tag("ResourceDocMatcher")
private val v700 = ApiShortVersions.`v7.0.0`.toString
private val base = s"/obp/$v700"
// Helper to create minimal ResourceDoc for testing
private def createResourceDoc(
@ -56,8 +59,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks", "getBanks")
)
When("Matching a GET request to /obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
When(s"Matching a GET request to $base/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -71,8 +74,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("POST", "/banks", "createBank")
)
When("Matching a POST request to /obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
When(s"Matching a POST request to $base/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val result = ResourceDocMatcher.findResourceDoc("POST", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -86,8 +89,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/management/metrics", "getMetrics")
)
When("Matching a GET request to /obp/v7.0.0/management/metrics")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/management/metrics")
When(s"Matching a GET request to $base/management/metrics")
val path = Uri.Path.unsafeFromString(s"$base/management/metrics")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -101,8 +104,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks", "getBanks")
)
When("Matching a POST request to /obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
When(s"Matching a POST request to $base/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val result = ResourceDocMatcher.findResourceDoc("POST", path, resourceDocs)
Then("Should return None")
@ -115,8 +118,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks", "getBanks")
)
When("Matching a GET request to /obp/v7.0.0/accounts")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/accounts")
When(s"Matching a GET request to $base/accounts")
val path = Uri.Path.unsafeFromString(s"$base/accounts")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should return None")
@ -132,8 +135,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks/BANK_ID", "getBank")
)
When("Matching a GET request to /obp/v7.0.0/banks/gh.29.de")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de")
When(s"Matching a GET request to $base/banks/gh.29.de")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -147,8 +150,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks/BANK_ID/accounts", "getBankAccounts")
)
When("Matching a GET request to /obp/v7.0.0/banks/test-bank-1/accounts")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/test-bank-1/accounts")
When(s"Matching a GET request to $base/banks/test-bank-1/accounts")
val path = Uri.Path.unsafeFromString(s"$base/banks/test-bank-1/accounts")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -160,8 +163,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
Given("A matched ResourceDoc with BANK_ID")
val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank")
When("Extracting path parameters from /obp/v7.0.0/banks/gh.29.de")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de")
When(s"Extracting path parameters from $base/banks/gh.29.de")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should extract BANK_ID value")
@ -178,8 +181,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID", "getBankAccount")
)
When("Matching a GET request to /obp/v7.0.0/banks/gh.29.de/accounts/test1")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1")
When(s"Matching a GET request to $base/banks/gh.29.de/accounts/test1")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -191,8 +194,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
Given("A matched ResourceDoc with BANK_ID and ACCOUNT_ID")
val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID", "getBankAccount")
When("Extracting path parameters from /obp/v7.0.0/banks/gh.29.de/accounts/test1")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1")
When(s"Extracting path parameters from $base/banks/gh.29.de/accounts/test1")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should extract both BANK_ID and ACCOUNT_ID values")
@ -208,8 +211,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/transactions", "getTransactions")
)
When("Matching a GET request to /obp/v7.0.0/banks/test-bank/accounts/acc-123/transactions")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/test-bank/accounts/acc-123/transactions")
When(s"Matching a GET request to $base/banks/test-bank/accounts/acc-123/transactions")
val path = Uri.Path.unsafeFromString(s"$base/banks/test-bank/accounts/acc-123/transactions")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -226,8 +229,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions", "getTransactionsForView")
)
When("Matching a GET request to /obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions")
When(s"Matching a GET request to $base/banks/gh.29.de/accounts/test1/owner/transactions")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1/owner/transactions")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -239,8 +242,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
Given("A matched ResourceDoc with BANK_ID, ACCOUNT_ID and VIEW_ID")
val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions", "getTransactionsForView")
When("Extracting path parameters from /obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions")
When(s"Extracting path parameters from $base/banks/gh.29.de/accounts/test1/owner/transactions")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1/owner/transactions")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should extract all three parameter values")
@ -258,8 +261,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/account", "getAccountForView")
)
When("Matching a GET request to /obp/v7.0.0/banks/test-bank/accounts/acc-1/public/account")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/test-bank/accounts/acc-1/public/account")
When(s"Matching a GET request to $base/banks/test-bank/accounts/acc-1/public/account")
val path = Uri.Path.unsafeFromString(s"$base/banks/test-bank/accounts/acc-1/public/account")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -277,7 +280,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a GET request with counterparty ID")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/counterparties/ff010868-ac7d-4f96-9fc5-70dd5757e891")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1/owner/counterparties/ff010868-ac7d-4f96-9fc5-70dd5757e891")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -290,7 +293,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID", "getCounterparty")
When("Extracting path parameters")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/counterparties/ff010868-ac7d-4f96-9fc5-70dd5757e891")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts/test1/owner/counterparties/ff010868-ac7d-4f96-9fc5-70dd5757e891")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should extract all parameter values including COUNTERPARTY_ID")
@ -311,7 +314,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a DELETE request")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/management/counterparties/counterparty-123")
val path = Uri.Path.unsafeFromString(s"$base/management/counterparties/counterparty-123")
val result = ResourceDocMatcher.findResourceDoc("DELETE", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -331,7 +334,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a request that doesn't match any ResourceDoc")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/accounts")
val path = Uri.Path.unsafeFromString(s"$base/accounts")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should return None")
@ -344,8 +347,8 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
createResourceDoc("GET", "/banks", "getBanks")
)
When("Matching a DELETE request to /obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
When(s"Matching a DELETE request to $base/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val result = ResourceDocMatcher.findResourceDoc("DELETE", path, resourceDocs)
Then("Should return None")
@ -359,7 +362,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a request with different segment count")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should return None")
@ -373,7 +376,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a request with different literal segment")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/transactions")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/transactions")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should return None")
@ -388,7 +391,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
val resourceDoc = createResourceDoc("GET", "/banks", "getBanks")
When("Extracting path parameters")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should return empty map")
@ -400,7 +403,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank")
When("Extracting path parameters with special characters")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de-test_bank")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de-test_bank")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should extract the full value including special characters")
@ -413,7 +416,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank")
When("Extracting parameters from path with different segment count")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/accounts")
val path = Uri.Path.unsafeFromString(s"$base/accounts")
val params = ResourceDocMatcher.extractPathParams(path, resourceDoc)
Then("Should return empty map due to segment count mismatch")
@ -458,9 +461,9 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
val resourceDoc = createResourceDoc("GET", "/banks", "getBanks")
val originalContext = code.api.util.CallContext(
correlationId = "test-correlation-id",
url = "/obp/v7.0.0/banks",
url = s"$base/banks",
verb = "GET",
implementedInVersion = "v7.0.0"
implementedInVersion = v700
)
When("Attaching ResourceDoc to CallContext")
@ -486,7 +489,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a specific request")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts")
val path = Uri.Path.unsafeFromString(s"$base/banks/gh.29.de/accounts")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should select the most specific matching ResourceDoc")
@ -502,7 +505,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching a request")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should return the first matching ResourceDoc")
@ -520,7 +523,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching with lowercase get")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks")
val path = Uri.Path.unsafeFromString(s"$base/banks")
val result = ResourceDocMatcher.findResourceDoc("get", path, resourceDocs)
Then("Should find the matching ResourceDoc")
@ -535,7 +538,7 @@ class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThe
)
When("Matching with different case /Banks")
val path = Uri.Path.unsafeFromString("/obp/v7.0.0/Banks")
val path = Uri.Path.unsafeFromString(s"$base/Banks")
val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs)
Then("Should not match (case-sensitive)")

View File

@ -1,13 +1,13 @@
package code.api.v1_4_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.usersJsonV400
import code.api.Constant
import java.util.Date
import code.api.util.APIUtil.ResourceDoc
import code.api.util.{APIUtil, ExampleValue}
import code.api.util.CustomJsonFormats
import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocJson
import code.api.v3_0_0.OBPAPI3_0_0
import code.setup.DefaultUsers
import net.liftweb.json.Extraction.decompose
import net.liftweb.json._
import org.everit.json.schema.loader.SchemaLoader
@ -44,7 +44,8 @@ case class AllCases(
jvalues: List[JValue]= List(APIUtil.defaultJValue)
)
class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers {
class JSONFactory1_4_0Test extends code.setup.ServerSetup {
override implicit val formats: Formats = CustomJsonFormats.formats
feature("Test JSONFactory1_4_0") {
scenario("prepareDescription should work well, extract the parameters from URL") {
@ -116,7 +117,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.createLocalisedResourceDocJson(resourceDoc,false, None,
urlParameters, "JSON request body fields:", "JSON response body fields:")
includeTechnology = false, urlParameters, "JSON request body fields:", "JSON response body fields:")
}
scenario("createResourceDocsJson should work well, no exception is good enough") {
@ -124,6 +125,21 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers {
val result = JSONFactory1_4_0.createResourceDocsJson(resourceDoc.toList, false, None)
}
scenario("Technology field should be None unless includeTechnology=true") {
val liftDoc: ResourceDoc = OBPAPI3_0_0.allResourceDocs(0)
val json1 = JSONFactory1_4_0.createLocalisedResourceDocJson(liftDoc, false, None, includeTechnology = false, urlParameters, "JSON request body fields:", "JSON response body fields:")
json1.implemented_by.technology shouldBe None
val json2 = JSONFactory1_4_0.createLocalisedResourceDocJson(liftDoc, false, None, includeTechnology = true, urlParameters, "JSON request body fields:", "JSON response body fields:")
json2.implemented_by.technology shouldBe Some(Constant.TECHNOLOGY_LIFTWEB)
}
scenario("Technology field should be http4s when includeTechnology=true and doc is http4s") {
val http4sDoc: ResourceDoc = code.api.v7_0_0.Http4s700.resourceDocs.head
val json = JSONFactory1_4_0.createLocalisedResourceDocJson(http4sDoc, true, None, includeTechnology = true, urlParameters, "JSON request body fields:", "JSON response body fields:")
json.implemented_by.technology shouldBe Some(Constant.TECHNOLOGY_HTTP4S)
}
scenario("createTypedBody should work well, no exception is good enough") {
val inputCaseClass = AllCases()
val result = JSONFactory1_4_0.createTypedBody(inputCaseClass)

View File

@ -1,9 +1,10 @@
package code.api.v7_0_0
import code.api.Constant
import cats.effect.IO
import cats.effect.unsafe.implicits.global
import code.api.util.ApiRole.{canGetCardsForBank, canReadResourceDoc}
import code.api.util.ErrorMessages.{AuthenticatedUserIsRequired, BankNotFound, UserHasMissingRoles}
import code.api.util.ErrorMessages.{AuthenticatedUserIsRequired, BankNotFound, InvalidApiVersionString, UserHasMissingRoles}
import code.setup.ServerSetupWithTestData
import net.liftweb.json.JValue
import net.liftweb.json.JsonAST.{JArray, JField, JObject, JString}
@ -246,8 +247,19 @@ class Http4s700RoutesTest extends ServerSetupWithTestData {
json match {
case JObject(fields) =>
toFieldMap(fields).get("resource_docs") match {
case Some(JArray(_)) =>
succeed
case Some(JArray(resourceDocs)) =>
resourceDocs.exists {
case JObject(rdFields) =>
toFieldMap(rdFields).get("implemented_by") match {
case Some(JObject(implFields)) =>
toFieldMap(implFields).get("technology") match {
case Some(JString(value)) => value == Constant.TECHNOLOGY_HTTP4S
case _ => false
}
case _ => false
}
case _ => false
} shouldBe true
case _ =>
fail("Expected resource_docs field to be an array")
}
@ -256,6 +268,82 @@ class Http4s700RoutesTest extends ServerSetupWithTestData {
}
}
scenario("Return only http4s technology endpoints", Http4s700RoutesTag) {
Given("GET /obp/v7.0.0/resource-docs/v7.0.0/obp request")
setPropsValues("resource_docs_requires_role" -> "false")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/resource-docs/v7.0.0/obp")
)
When("Running through wrapped routes")
val (status, json) = runAndParseJson(request)
Then("Response is 200 OK and includes no lift endpoints")
status shouldBe Status.Ok
json match {
case JObject(fields) =>
toFieldMap(fields).get("resource_docs") match {
case Some(JArray(resourceDocs)) =>
resourceDocs.exists {
case JObject(rdFields) =>
toFieldMap(rdFields).get("implemented_by") match {
case Some(JObject(implFields)) =>
toFieldMap(implFields).get("technology") match {
case Some(JString(value)) => value == Constant.TECHNOLOGY_HTTP4S
case _ => false
}
case _ => false
}
case _ => false
} shouldBe true
resourceDocs.exists {
case JObject(rdFields) =>
toFieldMap(rdFields).get("implemented_by") match {
case Some(JObject(implFields)) =>
toFieldMap(implFields).get("technology") match {
case Some(JString(value)) => value == Constant.TECHNOLOGY_LIFTWEB
case _ => false
}
case _ => false
}
case _ => false
} shouldBe false
case _ =>
fail("Expected resource_docs field to be an array")
}
case _ =>
fail("Expected JSON object for resource-docs endpoint")
}
}
scenario("Reject requesting non-v7 API version docs", Http4s700RoutesTag) {
Given("GET /obp/v7.0.0/resource-docs/v6.0.0/obp request")
setPropsValues("resource_docs_requires_role" -> "false")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/resource-docs/v6.0.0/obp")
)
When("Running through wrapped routes")
val (status, json) = runAndParseJson(request)
Then("Response is 400 Bad Request")
status.code shouldBe 400
json match {
case JObject(fields) =>
toFieldMap(fields).get("message") match {
case Some(JString(message)) =>
message should include(InvalidApiVersionString)
message should include("v6.0.0")
case _ =>
fail("Expected message field as JSON string for invalid-version response")
}
case _ =>
fail("Expected JSON object for invalid-version response")
}
}
scenario("Reject unauthenticated access when resource docs role is required", Http4s700RoutesTag) {
Given("GET /obp/v7.0.0/resource-docs/v7.0.0/obp request without auth headers and role required")
setPropsValues("resource_docs_requires_role" -> "true")

View File

@ -106,28 +106,79 @@ trait DefaultUsers {
// Create resource user, need provider
val defaultProvider = Constant.HostName
private def getOrCreateResourceUser(
provider: String,
providerId: String,
createdByConsentId: Option[String],
name: String,
email: String,
userId: Option[String],
company: String
): ResourceUser = {
UserX.findByProviderId(provider = provider, idGivenByProvider = providerId)
.map(_.asInstanceOf[ResourceUser])
.getOrElse {
try {
UserX
.createResourceUser(
provider = provider,
providerId = Some(providerId),
createdByConsentId = createdByConsentId,
name = Some(name),
email = Some(email),
userId = userId,
company = Some(company)
)
.openOrThrowException(attemptedToOpenAnEmptyBox)
} catch {
case e: Throwable =>
UserX.findByProviderId(provider = provider, idGivenByProvider = providerId)
.map(_.asInstanceOf[ResourceUser])
.getOrElse(throw e)
}
}
}
// create some resource user for test purposes
lazy val resourceUser1 = UserX.findByProviderId(provider = defaultProvider, idGivenByProvider= resourceUser1Name).map(_.asInstanceOf[ResourceUser])
.getOrElse(UserX.createResourceUser(provider = defaultProvider, providerId= Some(resourceUser1Name), createdByConsentId= None, name= Some(resourceUser1Name),
email= Some("resourceUser1@123.com"), userId= userId1, company = Some("Tesobe GmbH"))
.openOrThrowException(attemptedToOpenAnEmptyBox)
)
lazy val resourceUser1 = getOrCreateResourceUser(
provider = defaultProvider,
providerId = resourceUser1Name,
createdByConsentId = None,
name = resourceUser1Name,
email = "resourceUser1@123.com",
userId = userId1,
company = "Tesobe GmbH"
)
lazy val resourceUser2 = UserX.findByProviderId(provider = defaultProvider, idGivenByProvider= resourceUser2Name).map(_.asInstanceOf[ResourceUser])
.getOrElse(UserX.createResourceUser(provider = defaultProvider, providerId= Some(resourceUser2Name), createdByConsentId= None,
name= Some(resourceUser2Name),email= Some("resourceUser2@123.com"), userId= userId2, company = Some("Tesobe GmbH"))
.openOrThrowException(attemptedToOpenAnEmptyBox)
)
lazy val resourceUser2 = getOrCreateResourceUser(
provider = defaultProvider,
providerId = resourceUser2Name,
createdByConsentId = None,
name = resourceUser2Name,
email = "resourceUser2@123.com",
userId = userId2,
company = "Tesobe GmbH"
)
lazy val resourceUser3 = UserX.findByProviderId(provider = defaultProvider, idGivenByProvider= resourceUser3Name).map(_.asInstanceOf[ResourceUser])
.getOrElse(UserX.createResourceUser(provider = defaultProvider, providerId= Some(resourceUser3Name), createdByConsentId= None,
name= Some(resourceUser3Name),email= Some("resourceUser3@123.com"), userId= userId3, company = Some("Tesobe GmbH"))
.openOrThrowException(attemptedToOpenAnEmptyBox))
lazy val resourceUser3 = getOrCreateResourceUser(
provider = defaultProvider,
providerId = resourceUser3Name,
createdByConsentId = None,
name = resourceUser3Name,
email = "resourceUser3@123.com",
userId = userId3,
company = "Tesobe GmbH"
)
lazy val resourceUser4 = UserX.findByProviderId(provider = defaultProvider, idGivenByProvider= resourceUser4Name).map(_.asInstanceOf[ResourceUser])
.getOrElse(UserX.createResourceUser(provider = GatewayLogin.gateway, providerId = Some(resourceUser4Name), createdByConsentId= Some("simonr"), name= Some(resourceUser4Name),
email= Some("resourceUser4@123.com"), userId=userId4, company = Some("Tesobe GmbH"))
.openOrThrowException(attemptedToOpenAnEmptyBox))
lazy val resourceUser4 = getOrCreateResourceUser(
provider = GatewayLogin.gateway,
providerId = resourceUser4Name,
createdByConsentId = Some("simonr"),
name = resourceUser4Name,
email = "resourceUser4@123.com",
userId = userId4,
company = "Tesobe GmbH"
)
// create the tokens in database, we only need token-key and token-secretAllCases
lazy val testToken1 = Tokens.tokens.vend.createToken(

View File

@ -65,30 +65,56 @@ trait LocalMappedConnectorTestSetup extends TestConnectorSetupWithStandardPermis
}
override protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {
BankAccountRouting.create
.BankId(bankId.value)
.AccountId(accountId.value)
.AccountRoutingScheme(AccountRoutingScheme.IBAN.toString)
.AccountRoutingAddress(iban4j.Iban.random().toString())
.saveMe
BankAccountRouting.create
.BankId(bankId.value)
.AccountId(accountId.value)
.AccountRoutingScheme("AccountId")
.AccountRoutingAddress(accountId.value)
.saveMe
MappedBankAccount.create
.bank(bankId.value)
.theAccountId(accountId.value)
.accountCurrency(currency.toUpperCase)
.accountBalance(900000000)
.holder(randomString(4))
.accountLastUpdate(now)
.accountName(randomString(4))
.accountNumber(randomString(4))
.accountLabel(randomString(4))
.mBranchId(randomString(4))
.saveMe
def getOrCreateRouting(scheme: String, address: String): Unit = {
val existing = BankAccountRouting.find(
By(BankAccountRouting.BankId, bankId.value),
By(BankAccountRouting.AccountId, accountId.value),
By(BankAccountRouting.AccountRoutingScheme, scheme)
)
if (!existing.isDefined) {
try {
BankAccountRouting.create
.BankId(bankId.value)
.AccountId(accountId.value)
.AccountRoutingScheme(scheme)
.AccountRoutingAddress(address)
.saveMe
} catch {
case _: Throwable =>
}
}
()
}
getOrCreateRouting(AccountRoutingScheme.IBAN.toString, iban4j.Iban.random().toString())
getOrCreateRouting("AccountId", accountId.value)
val existingAccount = MappedBankAccount.find(
By(MappedBankAccount.bank, bankId.value),
By(MappedBankAccount.theAccountId, accountId.value)
)
existingAccount.openOr {
try {
MappedBankAccount.create
.bank(bankId.value)
.theAccountId(accountId.value)
.accountCurrency(currency.toUpperCase)
.accountBalance(900000000)
.holder(randomString(4))
.accountLastUpdate(now)
.accountName(randomString(4))
.accountNumber(randomString(4))
.accountLabel(randomString(4))
.mBranchId(randomString(4))
.saveMe
} catch {
case _: Throwable =>
MappedBankAccount.find(
By(MappedBankAccount.bank, bankId.value),
By(MappedBankAccount.theAccountId, accountId.value)
).openOrThrowException(attemptedToOpenAnEmptyBox)
}
}
}
override protected def updateAccountCurrency(bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {

View File

@ -143,6 +143,8 @@ object ApiVersion {
val berlinGroupV13 = ScannedApiVersion("berlin-group", "BG", "v1.3")
val mxofV100 = ScannedApiVersion("mxof", "MXOF", "v1.0.0")
val cnbv9 = ScannedApiVersion("CNBV9", "CNBV9", "v1.0.0")
val bahrainObfV100 = ScannedApiVersion("BAHRAIN-OBF", "BAHRAIN-OBF", "v1.0.0")
val auOpenBankingV100 = ScannedApiVersion("cds-au", "AU", "v1.0.0")
/**
* the ApiPathZero value must be got by obp-api project, so here is a workaround, let obp-api project modify this value