From a0567b7ba3e33a5ccb3532a79ff8172c9a534eb9 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Sep 2025 15:13:05 +0200 Subject: [PATCH 1/2] refactor/Add support for API version 6.0.0 in ResourceDocs --- .../ResourceDocsAPIMethods.scala | 38 +++++++---------- .../scala/code/api/util/ApiVersionUtils.scala | 4 +- .../main/scala/code/api/util/JwsUtil.scala | 9 ++-- .../ResourceDocs1_4_0/ResourceDocsTest.scala | 42 +++++++++++++++++-- .../ResourceDocsV140ServerSetup.scala | 1 + .../SwaggerFactoryUnitTest.scala | 4 +- 6 files changed, 64 insertions(+), 34 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 98865ed6a9..160513ab29 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -1,18 +1,14 @@ package code.api.ResourceDocs1_4_0 import code.api.Constant.{GET_DYNAMIC_RESOURCE_DOCS_TTL, GET_STATIC_RESOURCE_DOCS_TTL, PARAM_LOCALE} -import java.util.UUID.randomUUID - import code.api.OBPRestHelper -import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.canGetCustomersJson import code.api.cache.Caching -import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints} -import code.api.dynamic.entity.helper.DynamicEntityHelper import code.api.util.APIUtil._ -import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc, canReadStaticResourceDoc} +import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc} import code.api.util.ApiTag._ -import code.api.util.DynamicUtil.{dynamicCompileResult, logger} import code.api.util.ExampleValue.endpointMappingRequestBodyExample +import code.api.util.FutureUtil.EndpointContext +import code.api.util.NewStyle.HttpCode import code.api.util._ import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson import code.api.v1_4_0.{APIMethods140, JSONFactory1_4_0, OBPAPI1_4_0} @@ -20,35 +16,30 @@ import code.api.v2_2_0.{APIMethods220, OBPAPI2_2_0} import code.api.v3_0_0.OBPAPI3_0_0 import code.api.v3_1_0.OBPAPI3_1_0 import code.api.v4_0_0.{APIMethods400, OBPAPI4_0_0} +import code.api.v5_0_0.OBPAPI5_0_0 +import code.api.v5_1_0.OBPAPI5_1_0 +import code.api.v6_0_0.OBPAPI6_0_0 import code.apicollectionendpoint.MappedApiCollectionEndpointsProvider +import code.util.Helper import code.util.Helper.{MdcLoggable, ObpS, SILENCE_IS_GOLDEN} import com.github.dwickern.macros.NameOf.nameOf -import com.openbankproject.commons.model.{BankId, ListResult, User} -import com.openbankproject.commons.model.enums.ContentParam.{ALL, DYNAMIC, STATIC} import com.openbankproject.commons.model.enums.ContentParam +import com.openbankproject.commons.model.enums.ContentParam.{ALL, DYNAMIC, STATIC} +import com.openbankproject.commons.model.{BankId, ListResult, User} import com.openbankproject.commons.util.ApiStandards._ import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} -import com.tesobe.CacheKeyFromArguments import net.liftweb.common.{Box, Empty, Full} -import net.liftweb.http.{JsonResponse, LiftRules, S} +import net.liftweb.http.LiftRules import net.liftweb.json import net.liftweb.json.JsonAST.{JField, JString, JValue} import net.liftweb.json._ -import net.liftweb.util.Helpers.tryo -import net.liftweb.util.Props -import java.util.concurrent.ConcurrentHashMap - -import code.api.util.FutureUtil.EndpointContext -import code.api.util.NewStyle.HttpCode -import code.api.v5_0_0.OBPAPI5_0_0 -import code.api.v5_1_0.{OBPAPI5_1_0, UserAttributeJsonV510} -import code.util.Helper +import java.util.concurrent.ConcurrentHashMap import scala.collection.immutable.{List, Nil} import scala.concurrent.Future // JObject creation -import code.api.v1_2_1.{APIInfoJSON, APIMethods121, HostedBy, OBPAPI1_2_1} +import code.api.v1_2_1.{APIMethods121, OBPAPI1_2_1} import code.api.v1_3_0.{APIMethods130, OBPAPI1_3_0} import code.api.v2_0_0.{APIMethods200, OBPAPI2_0_0} import code.api.v2_1_0.{APIMethods210, OBPAPI2_1_0} @@ -58,9 +49,6 @@ import scala.collection.mutable.ArrayBuffer // So we can include resource docs from future versions import code.api.util.ErrorMessages._ import code.util.Helper.booleanToBox - -import scala.concurrent.duration._ - import com.openbankproject.commons.ExecutionContext.Implicits.global @@ -123,6 +111,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth logger.debug(s"getResourceDocsList says requestedApiVersion is $requestedApiVersion") val resourceDocs = requestedApiVersion match { + case ApiVersion.v6_0_0 => OBPAPI6_0_0.allResourceDocs case ApiVersion.v5_1_0 => OBPAPI5_1_0.allResourceDocs case ApiVersion.v5_0_0 => OBPAPI5_0_0.allResourceDocs case ApiVersion.v4_0_0 => OBPAPI4_0_0.allResourceDocs @@ -141,6 +130,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth logger.debug(s"There are ${resourceDocs.length} resource docs available to $requestedApiVersion") val versionRoutes = requestedApiVersion match { + case ApiVersion.v6_0_0 => OBPAPI6_0_0.routes case ApiVersion.v5_1_0 => OBPAPI5_1_0.routes case ApiVersion.v5_0_0 => OBPAPI5_0_0.routes case ApiVersion.v4_0_0 => OBPAPI4_0_0.routes diff --git a/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala b/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala index fc872ae791..5e93b6f7bd 100644 --- a/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala +++ b/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala @@ -1,7 +1,7 @@ package code.api.util -import com.openbankproject.commons.util.{ScannedApiVersion} import com.openbankproject.commons.util.ApiVersion._ +import com.openbankproject.commons.util.ScannedApiVersion object ApiVersionUtils { @@ -18,6 +18,7 @@ object ApiVersionUtils { v4_0_0 :: v5_0_0 :: v5_1_0 :: + v6_0_0 :: `dynamic-endpoint` :: `dynamic-entity` :: scannedApis @@ -39,6 +40,7 @@ object ApiVersionUtils { case v4_0_0.fullyQualifiedVersion | v4_0_0.apiShortVersion => v4_0_0 case v5_0_0.fullyQualifiedVersion | v5_0_0.apiShortVersion => v5_0_0 case v5_1_0.fullyQualifiedVersion | v5_1_0.apiShortVersion => v5_1_0 + case v6_0_0.fullyQualifiedVersion | v6_0_0.apiShortVersion => v6_0_0 case `dynamic-endpoint`.fullyQualifiedVersion | `dynamic-endpoint`.apiShortVersion => `dynamic-endpoint` case `dynamic-entity`.fullyQualifiedVersion | `dynamic-entity`.apiShortVersion => `dynamic-entity` case version if(scannedApis.map(_.fullyQualifiedVersion).contains(version)) diff --git a/obp-api/src/main/scala/code/api/util/JwsUtil.scala b/obp-api/src/main/scala/code/api/util/JwsUtil.scala index 8503ebf9b5..fb49658cc7 100644 --- a/obp-api/src/main/scala/code/api/util/JwsUtil.scala +++ b/obp-api/src/main/scala/code/api/util/JwsUtil.scala @@ -1,9 +1,5 @@ package code.api.util -import java.security.interfaces.RSAPublicKey -import java.time.format.DateTimeFormatter -import java.time.{Duration, ZoneOffset, ZonedDateTime} -import java.util import code.api.{CertificateConstants, Constant} import code.util.Helper.MdcLoggable import com.nimbusds.jose.crypto.RSASSAVerifier @@ -16,6 +12,10 @@ import net.liftweb.http.provider.HTTPParam import net.liftweb.json import net.liftweb.util.SecurityHelpers +import java.security.interfaces.RSAPublicKey +import java.time.format.DateTimeFormatter +import java.time.{Duration, ZoneOffset, ZonedDateTime} +import java.util import scala.collection.immutable.{HashMap, List} import scala.jdk.CollectionConverters.seqAsJavaListConverter @@ -147,6 +147,7 @@ object JwsUtil extends MdcLoggable { "BGv1.3"->"berlin-group/v1.3", "OBPv4.0.0"->"obp/v4.0.0", "OBPv5.0.0"->"obp/v5.0.0", + "OBPv6.0.0"->"obp/v6.0.0", "OBPv3.1.0"->"obp/v3.1.0", "UKv1.3"->"open-banking/v3.1" ).withDefaultValue("{Not found any standard to match}") diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index 152cca1210..6251462510 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -2,15 +2,13 @@ package code.api.ResourceDocs1_4_0 import code.api.ResourceDocs1_4_0.ResourceDocs140.ImplementationsResourceDocs import code.api.berlin.group.ConstantsBG -import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} import code.api.util.APIUtil.OAuth._ - -import java.util +import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} import code.api.util.{ApiRole, CustomJsonFormats} import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson import code.setup.{DefaultUsers, PropsReset} -import com.openbankproject.commons.util.{ApiVersion, Functions} import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.util.{ApiVersion, Functions} import net.liftweb.json import net.liftweb.json.JsonAST._ import net.liftweb.json.{Formats, JString, Serializer, TypeInfo} @@ -75,6 +73,24 @@ class ResourceDocsTest extends ResourceDocsV140ServerSetup with PropsReset with 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 + 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 -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 val responseGetObp = makeGetRequest(requestGetObp) @@ -351,6 +367,24 @@ 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 + 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 ${ApiEndpoint2.name} Api -OBPv6.0.0", ApiEndpoint1, VersionOfApi) { + val requestGetObp = (ResourceDocsV1_4Request /"banks"/ testBankId1.value/ "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 ${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 val responseGetObp = makeGetRequest(requestGetObp) diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsV140ServerSetup.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsV140ServerSetup.scala index 16c9ea21fb..16d3751119 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsV140ServerSetup.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsV140ServerSetup.scala @@ -13,5 +13,6 @@ trait ResourceDocsV140ServerSetup extends ServerSetupWithTestData { def ResourceDocsV4_0Request = baseRequest / "obp" / "v4.0.0" def ResourceDocsV5_0Request = baseRequest / "obp" / "v5.0.0" def ResourceDocsV5_1Request = baseRequest / "obp" / "v5.1.0" + def ResourceDocsV6_0Request = baseRequest / "obp" / "v6.0.0" } diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerFactoryUnitTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerFactoryUnitTest.scala index 5a1f15e2d9..7a76d612a0 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerFactoryUnitTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerFactoryUnitTest.scala @@ -9,6 +9,7 @@ import code.api.v3_1_0.OBPAPI3_1_0 import code.api.v4_0_0.OBPAPI4_0_0 import code.api.v5_0_0.OBPAPI5_0_0 import code.api.v5_1_0.OBPAPI5_1_0 +import code.api.v6_0_0.OBPAPI6_0_0 import code.util.Helper.MdcLoggable import scala.collection.mutable.ArrayBuffer @@ -56,7 +57,8 @@ class SwaggerFactoryUnitTest extends V140ServerSetup with MdcLoggable { feature("Test all V300, V220 and V210, exampleRequestBodies and successResponseBodies and all the case classes in SwaggerDefinitionsJSON") { scenario("Test all the case classes") { val resourceDocList: ArrayBuffer[ResourceDoc] = ArrayBuffer.empty - OBPAPI5_1_0.allResourceDocs// ++ + OBPAPI6_0_0.allResourceDocs ++ + OBPAPI5_1_0.allResourceDocs ++ OBPAPI5_0_0.allResourceDocs ++ OBPAPI4_0_0.allResourceDocs ++ OBPAPI3_1_0.allResourceDocs ++ From 777c30941e83eb6f13dd113f19f6d340e7786ba9 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Sep 2025 15:34:43 +0200 Subject: [PATCH 2/2] test/Update ApiVersionUtilsTest to reflect the addition of a new API version, increasing expected version count from 23 to 24 --- obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala b/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala index a7b008233a..1a14ed8965 100644 --- a/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala +++ b/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala @@ -20,6 +20,6 @@ class ApiVersionUtilsTest extends V400ServerSetup { versions.map(version => ApiVersionUtils.valueOf(version.fullyQualifiedVersion)) //NOTE, when we added the new version, better fix this number manually. and also check the versions - versions.length shouldBe(23) + versions.length shouldBe(24) }} } \ No newline at end of file