From db1470c13b4356a1ff6034464cced86a668dcead Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 12:06:01 +0100 Subject: [PATCH 01/16] refactor/remove the versions from swagger operationId --- .../scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 30aa308c9..0ccd62f6b 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -495,7 +495,7 @@ object SwaggerJSONFactory extends MdcLoggable { tags = rd.tags.map(_.tag), summary = rd.summary, description = PegdownOptions.convertPegdownToHtmlTweaked(rd.description.stripMargin).replaceAll("\n", ""), - operationId =s"${rd.implementedInApiVersion.fullyQualifiedVersion }-${rd.partialFunctionName.toString }", + operationId =s"${rd.partialFunctionName}", parameters ={ val description = rd.exampleRequestBody match { case EmptyBody => "" From 495243821713afd8b420bdfb591e5ef65db8f4e7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 13:08:50 +0100 Subject: [PATCH 02/16] bugfix/fixed the swagger response for getScannedApiVersions --- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index f2e2848e9..be108828f 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8891,7 +8891,7 @@ trait APIMethods400 { EmptyBody, ListResult( "scanned_api_versions", - List(ApiVersion.v3_1_0) + List(Extraction.decompose(ApiVersion.v3_1_0)) ), List( UnknownError From c068611fb2181fc2e6c36878c1a0a69ee62990e4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 21:00:38 +0100 Subject: [PATCH 03/16] bugfix/fixed the JArray for the getSchema method and added a TOD --- .../api/ResourceDocs1_4_0/SwaggerJSONFactory.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 0ccd62f6b..49ba294d4 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -18,6 +18,7 @@ import java.math.{BigDecimal => JBigDecimal} import code.api.AUOpenBanking.v1_0_0.ApiCollector import code.api.Constant import code.api.Polish.v2_1_1_1.OBP_PAPI_2_1_1_1 +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{NotSupportedYet, notSupportedYet} import code.api.STET.v1_4.OBP_STET_1_4 import code.api.UKOpenBanking.v2_0_0.OBP_UKOpenBanking_200 import code.api.UKOpenBanking.v3_1_0.OBP_UKOpenBanking_310 @@ -152,7 +153,8 @@ object SwaggerJSONFactory extends MdcLoggable { case example: ListResult[_] => val listResult = example.asInstanceOf[ListResult[List[_]]] Some(ResponseObjectSchemaJson(listResult)) - case s:scala.Product => Some(ResponseObjectSchemaJson(s"#/definitions/${s.getClass.getSimpleName}")) + //TODO if value is List, need to be modified to Array later. + case s:scala.Product if(!value.isInstanceOf[List[scala.Product]]) => Some(ResponseObjectSchemaJson(s"#/definitions/${s.getClass.getSimpleName}")) case _ => Some(ResponseObjectSchemaJson(s"#/definitions/NotSupportedYet")) } } @@ -824,9 +826,10 @@ object SwaggerJSONFactory extends MdcLoggable { */ private def getAllEntities(entities: List[AnyRef]) = { val notNullEntities = entities.filter(null !=) + val notSupportYetEntity = entities.filter(_.getClass.getSimpleName.equals(NotSupportedYet.getClass.getSimpleName.replace("$",""))) val existsEntityTypes: Set[universe.Type] = notNullEntities.map(ReflectUtils.getType).toSet - (notNullEntities ::: notNullEntities.flatMap(getNestedRefEntities(_, existsEntityTypes))) + (notSupportYetEntity ::: notNullEntities ::: notNullEntities.flatMap(getNestedRefEntities(_, existsEntityTypes))) .distinctBy(_.getClass) } @@ -919,7 +922,8 @@ object SwaggerJSONFactory extends MdcLoggable { any => any != null && !excludeTypes.exists(_.isInstance(any)) } - val docEntityExamples: List[AnyRef] = (resourceDocList.map(_.exampleRequestBody.asInstanceOf[AnyRef]) ::: + val docEntityExamples: List[AnyRef] = (List(notSupportedYet)::: + resourceDocList.map(_.exampleRequestBody.asInstanceOf[AnyRef]) ::: resourceDocList.map(_.successResponseBody.asInstanceOf[AnyRef]) ).filter(predicate) From 3657a73a6b6141d200899ca43713555ec669bf41 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 22:02:04 +0100 Subject: [PATCH 04/16] refactor/tweaked getCustomerMessages ->getCustomersMessages --- .../src/main/scala/code/api/v1_4_0/APIMethods140.scala | 8 ++++---- obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala | 2 +- obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala | 2 +- obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala | 2 +- obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala | 2 +- obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala | 2 +- obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index af7f03ede..fc27ef582 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -93,12 +93,12 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ } resourceDocs += ResourceDoc( - getCustomerMessages, + getCustomersMessages, apiVersion, - "getCustomerMessages", + "createCustomerMessage", "GET", "/banks/BANK_ID/customer/messages", - "Get Customer Messages for a Customer", + "Get Customer Messages for all Customers", """Get messages for the logged in customer |Messages sent to the currently authenticated user. | @@ -108,7 +108,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ List(UserNotLoggedIn, UnknownError), List(apiTagMessage, apiTagCustomer)) - lazy val getCustomerMessages : OBPEndpoint = { + lazy val getCustomersMessages : OBPEndpoint = { case "banks" :: BankId(bankId) :: "customer" :: "messages" :: Nil JsonGet _ => { cc =>{ for { diff --git a/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala index 2442a7791..53d05775a 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala @@ -97,7 +97,7 @@ object OBPAPI1_4_0 extends OBPRestHelper with APIMethods140 with MdcLoggable wit val endpointsOf1_4_0 = List( Implementations1_4_0.getCustomer, Implementations1_4_0.addCustomer, - Implementations1_4_0.getCustomerMessages, + Implementations1_4_0.getCustomersMessages, Implementations1_4_0.addCustomerMessage, Implementations1_4_0.getBranches, Implementations1_4_0.getAtms, diff --git a/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala b/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala index 07b068e0e..d9ddd26ea 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala @@ -127,7 +127,7 @@ object OBPAPI2_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints 2.0.0 (less info about the views) val endpointsOf1_4_0 = List( Implementations1_4_0.getCustomer, // Now in 2.0.0 Implementations1_4_0.addCustomer, - Implementations1_4_0.getCustomerMessages, + Implementations1_4_0.getCustomersMessages, Implementations1_4_0.addCustomerMessage, Implementations1_4_0.getBranches, Implementations1_4_0.getAtms, diff --git a/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala b/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala index 9c6ce8c32..60483c9a7 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala @@ -120,7 +120,7 @@ object OBPAPI2_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints 1.4.0 - val endpointsOf1_4_0 = Implementations1_4_0.getCustomerMessages :: + val endpointsOf1_4_0 = Implementations1_4_0.getCustomersMessages :: Implementations1_4_0.addCustomerMessage :: Implementations1_4_0.getBranches :: Implementations1_4_0.getAtms :: diff --git a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala index 02a3ed636..5ce8551c7 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala @@ -94,7 +94,7 @@ object OBPAPI2_2_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints 1.4.0 - val endpointsOf1_4_0 = Implementations1_4_0.getCustomerMessages :: + val endpointsOf1_4_0 = Implementations1_4_0.getCustomersMessages :: Implementations1_4_0.addCustomerMessage :: Implementations1_4_0.getBranches :: Implementations1_4_0.getAtms :: diff --git a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala index c39a566ae..61102f756 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala @@ -130,7 +130,7 @@ object OBPAPI3_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints from 1.4.0 - val endpointsOf1_4_0 = Implementations1_4_0.getCustomerMessages :: + val endpointsOf1_4_0 = Implementations1_4_0.getCustomersMessages :: Implementations1_4_0.addCustomerMessage :: // Implementations1_4_0.getBranches :: //now in V300 // Implementations1_4_0.getAtms :: //now in V300 diff --git a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala index 79818a9fc..2b1f371bd 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala @@ -130,7 +130,7 @@ object OBPAPI3_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w // Possible Endpoints from 1.4.0 - val endpointsOf1_4_0 = Implementations1_4_0.getCustomerMessages :: + val endpointsOf1_4_0 = Implementations1_4_0.getCustomersMessages :: Implementations1_4_0.addCustomerMessage :: // Implementations1_4_0.getBranches :: //now in V300 // Implementations1_4_0.getAtms :: //now in V300 From 8fc9593b2d6ef2142646857b72a6a8bbd5c1cdaf Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 22:24:09 +0100 Subject: [PATCH 05/16] refactor/remove the versions from swagger operationId -revert --- .../scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 49ba294d4..6940c8750 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -497,7 +497,7 @@ object SwaggerJSONFactory extends MdcLoggable { tags = rd.tags.map(_.tag), summary = rd.summary, description = PegdownOptions.convertPegdownToHtmlTweaked(rd.description.stripMargin).replaceAll("\n", ""), - operationId =s"${rd.partialFunctionName}", + operationId = s"${rd.implementedInApiVersion.fullyQualifiedVersion }-${rd.partialFunctionName.toString }", parameters ={ val description = rd.exampleRequestBody match { case EmptyBody => "" From 859d63c51533a3e2c01d746ad5925a6ac676a454 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 22:33:11 +0100 Subject: [PATCH 06/16] refactor/typo --- obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index fc27ef582..e3d98ff83 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -95,7 +95,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ resourceDocs += ResourceDoc( getCustomersMessages, apiVersion, - "createCustomerMessage", + "getCustomersMessages", "GET", "/banks/BANK_ID/customer/messages", "Get Customer Messages for all Customers", From 61287925e1ea5bb48b9bd545780c122336b087fd Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 22:54:22 +0100 Subject: [PATCH 07/16] refactor/swagger if requiredFields is empty, remove the [] --- .../code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 6940c8750..70cb4994f 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -751,7 +751,11 @@ object SwaggerJSONFactory extends MdcLoggable { val requiredFields = if (jFields.isEmpty) "[]" else jFields.map(_.name).map(name => s""" "$name" """).mkString("[", ",", "]") - s""" {"type":"object", "properties": { ${allFields.mkString(",")} }, "required": $requiredFields }""" + if(requiredFields.equals("[]")) { + s""" {"type":"object", "properties": { ${allFields.mkString(",")} } }""" + } else{ + s""" {"type":"object", "properties": { ${allFields.mkString(",")} }, "required": $requiredFields }""" + } case _ if isTypeOf[JValue] => Objects.nonNull(exampleValue) From 97b0e31d8eec191a3ae3b42fd57bcc9b0cdd1972 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 23:02:32 +0100 Subject: [PATCH 08/16] refactor/remove the duplicated apiTagApi --- .../scala/code/api/v4_0_0/APIMethods400.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index be108828f..72a795640 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -11762,7 +11762,7 @@ trait APIMethods400 { InvalidJsonFormat, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canCreateSystemLevelEndpointTag))) lazy val createSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { @@ -11803,7 +11803,7 @@ trait APIMethods400 { InvalidJsonFormat, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canUpdateSystemLevelEndpointTag))) lazy val updateSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonPut json -> _ => { @@ -11843,7 +11843,7 @@ trait APIMethods400 { UserHasMissingRoles, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canGetSystemLevelEndpointTag))) lazy val getSystemLevelEndpointTags: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { @@ -11875,7 +11875,7 @@ trait APIMethods400 { UserHasMissingRoles, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canDeleteSystemLevelEndpointTag))) lazy val deleteSystemLevelEndpointTag: OBPEndpoint = { case "management" :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonDelete _ => { @@ -11907,7 +11907,7 @@ trait APIMethods400 { InvalidJsonFormat, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canCreateBankLevelEndpointTag))) lazy val createBankLevelEndpointTag: OBPEndpoint = { case "management" :: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: Nil JsonPost json -> _ => { @@ -11950,7 +11950,7 @@ trait APIMethods400 { InvalidJsonFormat, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canUpdateBankLevelEndpointTag))) lazy val updateBankLevelEndpointTag: OBPEndpoint = { case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonPut json -> _ => { @@ -11992,7 +11992,7 @@ trait APIMethods400 { UserHasMissingRoles, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canGetBankLevelEndpointTag))) lazy val getBankLevelEndpointTags: OBPEndpoint = { case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: Nil JsonGet _ => { @@ -12026,7 +12026,7 @@ trait APIMethods400 { UserHasMissingRoles, UnknownError ), - List(apiTagApi, apiTagApi, apiTagNewStyle), + List(apiTagApi, apiTagNewStyle), Some(List(canDeleteBankLevelEndpointTag))) lazy val deleteBankLevelEndpointTag: OBPEndpoint = { case "management":: "banks" :: bankId :: "endpoints" :: operationId :: "tags" :: endpointTagId :: Nil JsonDelete _ => { From 7c4a0b4239cc14debad1c1f54664bfe336bf51cd Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 15 Mar 2023 23:03:09 +0100 Subject: [PATCH 09/16] test/added the test for SwaggerFactoryUnitTest --- .../ResourceDocs1_4_0/SwaggerFactoryUnitTest.scala | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 058aa0973..83e0467b9 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 @@ -7,6 +7,8 @@ import code.api.v2_2_0.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.OBPAPI4_0_0 +import code.api.v5_0_0.OBPAPI5_0_0 +import code.api.v5_1_0.OBPAPI5_1_0 import code.util.Helper.MdcLoggable import scala.collection.mutable.ArrayBuffer @@ -53,7 +55,14 @@ 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] = OBPAPI3_1_0.allResourceDocs ++ OBPAPI3_0_0.allResourceDocs ++ OBPAPI2_2_0.allResourceDocs ++ OBPAPI2_1_0.allResourceDocs + val resourceDocList: ArrayBuffer[ResourceDoc] = + OBPAPI5_1_0.allResourceDocs ++ + OBPAPI5_0_0.allResourceDocs ++ + OBPAPI4_0_0.allResourceDocs ++ + OBPAPI3_1_0.allResourceDocs ++ + OBPAPI3_0_0.allResourceDocs ++ + OBPAPI2_2_0.allResourceDocs ++ + OBPAPI2_1_0.allResourceDocs //Translate every entity(JSON Case Class) in a list to appropriate swagger format val listOfExampleRequestBodyDefinition = From 1d84cfc9936f58d97d775026fb6ea4fa55da3cb1 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 17 Mar 2023 07:46:44 +0100 Subject: [PATCH 10/16] docfix/added the userAgreementJson --- .../api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 149402a25..b6dfa76f9 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1924,6 +1924,11 @@ object SwaggerDefinitionsJSON { entitlements = entitlementJSONs ) + val userAgreementJson = UserAgreementJson( + ExampleValue.typeExample.value, + ExampleValue.textExample.value, + ) + val userJsonV400 = UserJsonV400( user_id = ExampleValue.userIdExample.value, email = ExampleValue.emailExample.value, @@ -1932,7 +1937,7 @@ object SwaggerDefinitionsJSON { username = usernameExample.value, entitlements = entitlementJSONs, views = None, - agreements = None, + agreements = Some(List(userAgreementJson)), is_deleted = false, last_marketing_agreement_signed_date = Some(DateWithDayExampleObject), is_locked = false From 0be0b35963394f743ddc8eba72719446a825908b Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 17 Mar 2023 13:38:15 +0300 Subject: [PATCH 11/16] refactor/tweaked the error message --- obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index c49a66bfb..e72686b20 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -1342,7 +1342,7 @@ trait APIMethods500 { for { (Full(u), callContext) <- SS.user _ <- NewStyle.function.hasAtLeastOneEntitlement(failMsg = createProductEntitlementsRequiredText)(bankId.value, u.userId, createProductEntitlements, callContext) - failMsg = s"$InvalidJsonFormat The Json body should be the $PutProductJsonV400 " + failMsg = s"$InvalidJsonFormat The Json body should be the $PutProductJsonV500 " product <- NewStyle.function.tryons(failMsg, 400, callContext) { json.extract[PutProductJsonV500] } From aca5e3d1478a58c24d9906c14c6a52786fadfc86 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 21 Mar 2023 12:15:02 +0100 Subject: [PATCH 12/16] bugfix/fixed the None value for swaggerDocs --- .../scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 70cb4994f..6d4b2a8a4 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -607,7 +607,6 @@ object SwaggerJSONFactory extends MdcLoggable { val exampleValue = paramValue match { case Some(v) => v - case None => "" case _ => paramValue } @@ -640,7 +639,7 @@ object SwaggerJSONFactory extends MdcLoggable { OBPEnumeration.getValuesByType(enumType).map(it => s""""$it"""").mkString(",") } def example = exampleValue match { - case null => "" + case null | None => "" case v: JValue => s""", "example": "${JsonUtils.toString(v)}" """ case v => s""", "example": "$v" """ } From 76870327f1337f083351c398c3a67eef7b49fcdb Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 23 Mar 2023 15:26:34 +0100 Subject: [PATCH 13/16] bugfix/fixed the swaggerDocs for V500 and V510 --- .../ResourceDocsAPIMethods.scala | 14 ++--- .../SwaggerDefinitionsJSON.scala | 58 +++++++++++++------ .../SwaggerJSONFactory.scala | 5 +- .../scala/code/api/v3_0_0/APIMethods300.scala | 2 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 6 +- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 4 ++ .../v4_0_0/EndpointMappingBankLevelTest.scala | 4 +- .../code/api/v4_0_0/EndpointMappingTest.scala | 4 +- 8 files changed, 63 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 b0f2c8311..e5e538d39 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 @@ -4,6 +4,7 @@ import code.api.Constant.PARAM_LOCALE import java.util.UUID.randomUUID import code.api.OBPRestHelper +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.canGetCustomers import code.api.builder.OBP_APIBuilder import code.api.cache.Caching import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints} @@ -24,7 +25,7 @@ import code.util.Helper.MdcLoggable 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 import com.openbankproject.commons.util.ApiStandards._ import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} import com.tesobe.CacheKeyFromArguments @@ -176,11 +177,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth { // only `obp` standard show the `localResourceDocs` case version: ScannedApiVersion - if(version.apiStandard == obp.toString && version==ApiVersion.v4_0_0) => - activePlusLocalResourceDocs ++= localResourceDocs.filterNot(_.partialFunctionName == nameOf(getResourceDocsObp)) - case version: ScannedApiVersion - if(version.apiStandard == obp.toString && version!=ApiVersion.v4_0_0) => - activePlusLocalResourceDocs ++= localResourceDocs.filterNot(_.partialFunctionName == nameOf(getResourceDocsObpV400)) + if(version.apiStandard == obp.toString) => + activePlusLocalResourceDocs ++= localResourceDocs case _ => ; // all other standards only show their own apis. } @@ -410,7 +408,9 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth emptyObjectJson, emptyObjectJson, UnknownError :: Nil, - List(apiTagDocumentation)) + List(apiTagDocumentation), + Some(List(canGetCustomers)) + ) val exampleResourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), false, None) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index b6dfa76f9..8f424a8ef 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -11,7 +11,7 @@ import code.api.dynamic.endpoint.helper.practise.PractiseEndpoint import code.api.util.APIUtil.{defaultJValue, _} import code.api.util.ApiRole._ import code.api.util.ExampleValue._ -import code.api.util.{APIUtil, ApiTrigger, ExampleValue} +import code.api.util.{APIUtil, ApiRole, ApiTrigger, ExampleValue} import code.api.v2_2_0.JSONFactory220.{AdapterImplementationJson, MessageDocJson, MessageDocsJson} import code.api.v3_0_0.JSONFactory300.createBranchJsonV300 import code.api.v3_0_0.custom.JSONFactoryCustom300 @@ -31,7 +31,7 @@ import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model import com.openbankproject.commons.model.PinResetReason.{FORGOT, GOOD_SECURITY_PRACTICE} import com.openbankproject.commons.model.enums.{AttributeCategory, CardAttributeType, ChallengeType} -import com.openbankproject.commons.model.{UserAuthContextUpdateStatus, ViewBasic, _} +import com.openbankproject.commons.model.{TransactionRequestSimple, UserAuthContextUpdateStatus, ViewBasic, _} import com.openbankproject.commons.util.{ApiVersion, FieldNameApiVersions, ReflectUtils, RequiredArgs, RequiredInfo} import net.liftweb.json import java.net.URLEncoder @@ -582,17 +582,29 @@ object SwaggerDefinitionsJSON { creditorAccount = PaymentAccount(iban = "DE75512108001245126199"), creditorName = "John Miles" ) + + val transactionRequestSimple= TransactionRequestSimple( + otherBankRoutingScheme = bankRoutingSchemeExample.value, + otherBankRoutingAddress = bankRoutingAddressExample.value, + otherBranchRoutingScheme = branchRoutingSchemeExample.value, + otherBranchRoutingAddress = branchRoutingAddressExample.value, + otherAccountRoutingScheme = accountRoutingSchemeExample.value, + otherAccountRoutingAddress = accountRoutingAddressExample.value, + otherAccountSecondaryRoutingScheme = accountRoutingSchemeExample.value, + otherAccountSecondaryRoutingAddress = accountRoutingAddressExample.value + ) val transactionRequestBodyAllTypes = TransactionRequestBodyAllTypes ( to_sandbox_tan = Some(transactionRequestAccount), to_sepa = Some(transactionRequestIban), to_counterparty = Some(transactionRequestCounterpartyId), + to_simple = Some(transactionRequestSimple), to_transfer_to_phone = Some(transactionRequestTransferToPhone), to_transfer_to_atm = Some(transactionRequestTransferToAtm), to_transfer_to_account = Some(transactionRequestTransferToAccount), to_sepa_credit_transfers = Some(sepaCreditTransfers), value = amountOfMoney, - description = "String" + description = descriptionExample.value ) val transactionRequest = TransactionRequest( @@ -1928,6 +1940,25 @@ object SwaggerDefinitionsJSON { ExampleValue.typeExample.value, ExampleValue.textExample.value, ) + val viewJSON300 = ViewJSON300( + bank_id = bankIdExample.value, + account_id = accountIdExample.value, + view_id = viewIdExample.value + ) + + val viewsJSON300 = ViewsJSON300( + list = List(viewJSON300) + ) + + val userJsonV300 = UserJsonV300( + user_id = ExampleValue.userIdExample.value, + email = ExampleValue.emailExample.value, + provider_id = providerIdValueExample.value, + provider = providerValueExample.value, + username = usernameExample.value, + entitlements = entitlementJSONs, + views = Some(viewsJSON300) + ) val userJsonV400 = UserJsonV400( user_id = ExampleValue.userIdExample.value, @@ -1936,24 +1967,11 @@ object SwaggerDefinitionsJSON { provider = providerValueExample.value, username = usernameExample.value, entitlements = entitlementJSONs, - views = None, + views = Some(viewsJSON300), agreements = Some(List(userAgreementJson)), is_deleted = false, last_marketing_agreement_signed_date = Some(DateWithDayExampleObject), is_locked = false - ) - val userJsonWithAgreementsV400 = UserJsonV400( - user_id = ExampleValue.userIdExample.value, - email = ExampleValue.emailExample.value, - provider_id = providerIdValueExample.value, - provider = providerValueExample.value, - username = usernameExample.value, - entitlements = entitlementJSONs, - views = None, - agreements = Some(Nil), - is_deleted = false, - last_marketing_agreement_signed_date = Some(DateWithDayExampleObject), - is_locked = false ) val userIdJsonV400 = UserIdJsonV400( user_id = ExampleValue.userIdExample.value @@ -4353,6 +4371,8 @@ object SwaggerDefinitionsJSON { views_available = List(viewBasicCommons), bank_id = bankIdExample.value ) + + val canGetCustomers = ApiRole.canGetCustomers val cardAttributeCommons = CardAttributeCommons( bankId = Some(BankId(bankIdExample.value)), @@ -4843,7 +4863,9 @@ object SwaggerDefinitionsJSON { successResponseBody = Option(json.parse(successResponseBodyExample.value)) ) - val jsonCodeTemplate = "code" -> URLEncoder.encode("""println("hello")""", "UTF-8") + val jsonCodeTemplateJson = JsonCodeTemplateJson( + URLEncoder.encode("""println("hello")""", "UTF-8") + ) val supportedCurrenciesJson = SupportedCurrenciesJson( supportedCurrenciesExample.value diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 6d4b2a8a4..3267f8f6d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -606,7 +606,7 @@ object SwaggerJSONFactory extends MdcLoggable { val paramValue = it._2 val exampleValue = paramValue match { - case Some(v) => v + case Some(v) => v // Here it will get the value from Option/Box, case _ => paramValue } @@ -652,6 +652,7 @@ object SwaggerJSONFactory extends MdcLoggable { //Boolean - 4 kinds case _ if isAnyOfType[Boolean, JBool, XBoolean] => s""" {"type":"boolean" $example}""" + case _ if exampleValue.isInstanceOf[Boolean] => s""" {"type":"boolean" $example}""" //TODO. Here need to be enhanced. case _ if isAnyOfType[Option[Boolean], Option[JBool], Option[XBoolean]] => s""" {"type":"boolean" $example}""" case _ if isAnyOfType[Coll[Boolean], Coll[JBool], Coll[XBoolean]] => s""" {"type":"array", "items":{"type": "boolean"}}""" case _ if isAnyOfType[Option[Coll[Boolean]],Option[Coll[JBool]],Option[Coll[XBoolean]]] => s""" {"type":"array", "items":{"type": "boolean"}}""" @@ -707,6 +708,8 @@ object SwaggerJSONFactory extends MdcLoggable { val value = exampleValue match { case Some(v: Array[_]) if v.nonEmpty => v.head case Some(coll :Coll[_]) if coll.nonEmpty => coll.head + case (v: Array[_]) if v.nonEmpty => v.head + case (coll: Coll[_]) if coll.nonEmpty => coll.head case _ => null } s""" {"type": "array", "items":${buildSwaggerSchema(tp, value)}}""" diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 77e1ccbda..aea646289 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -1591,7 +1591,7 @@ trait APIMethods300 { |${authenticationRequiredMessage(true)} """.stripMargin, EmptyBody, - userJsonV200, + userJsonV300, List(UserNotLoggedIn, UnknownError), List(apiTagUser, apiTagNewStyle)) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 72a795640..54d1e0ff5 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -3615,7 +3615,7 @@ trait APIMethods400 { | """.stripMargin, EmptyBody, - userJsonWithAgreementsV400, + userJsonV400, List(UserNotLoggedIn, UserHasMissingRoles, UserNotFoundById, UnknownError), List(apiTagUser, apiTagNewStyle), Some(List(canGetAnyUser))) @@ -10600,7 +10600,7 @@ trait APIMethods400 { |auto compilation and debug |""", jsonResourceDocFragment, - jsonCodeTemplate, + jsonCodeTemplateJson, List( $UserNotLoggedIn, InvalidJsonFormat, @@ -10633,7 +10633,7 @@ trait APIMethods400 { code = DynamicEndpointCodeGenerator.buildTemplate(resourceDocFragment) } yield { - ("code" -> URLEncoder.encode(code, "UTF-8"), HttpCode.`201`(cc.callContext)) + (JsonCodeTemplateJson(URLEncoder.encode(code, "UTF-8")), HttpCode.`201`(cc.callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index 634430445..c17132116 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -1083,6 +1083,10 @@ case class CustomerMessageJsonV400( from_person: String ) +case class JsonCodeTemplateJson( + code: String +) + object JSONFactory400 { def createCustomerMessageJson(cMessage : CustomerMessage) : CustomerMessageJsonV400 = { diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingBankLevelTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingBankLevelTest.scala index 337ba386c..e9c4c579b 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingBankLevelTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingBankLevelTest.scala @@ -1,6 +1,6 @@ package code.api.v4_0_0 -import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.jsonCodeTemplate +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.jsonCodeTemplateJson import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole._ import code.api.util.ErrorMessages.{UserNotLoggedIn, _} @@ -30,7 +30,7 @@ class EndpointMappingBankLevelTest extends V400ServerSetup { object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.deleteBankLevelEndpointMapping)) val rightEntity = endpointMappingRequestBodyExample - val wrongEntity = jsonCodeTemplate + val wrongEntity = jsonCodeTemplateJson feature("Add a EndpointMapping v4.0.0- Unauthorized access") { scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) { diff --git a/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingTest.scala index ea15d52a8..3a994b0c1 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/EndpointMappingTest.scala @@ -1,6 +1,6 @@ package code.api.v4_0_0 -import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.jsonCodeTemplate +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.jsonCodeTemplateJson import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole.{CanCreateEndpointMapping, _} import code.api.util.ErrorMessages.{UserNotLoggedIn, _} @@ -30,7 +30,7 @@ class EndpointMappingTest extends V400ServerSetup { object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.deleteEndpointMapping)) val rightEntity = endpointMappingRequestBodyExample - val wrongEntity = jsonCodeTemplate + val wrongEntity = jsonCodeTemplateJson feature("Add a EndpointMapping v4.0.0- Unauthorized access") { scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) { From a133a74f5e6f880bc54e77e0067af2206c59169d Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 17 Mar 2023 17:29:08 +0300 Subject: [PATCH 14/16] refactor/renamed MetricsJSON--> MetricsJsonV220 --- .../api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 2 +- .../src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 8f424a8ef..c4c3a87dd 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -3267,7 +3267,7 @@ object SwaggerDefinitionsJSON { log_level = "Debug", remote_data_secret_matched = Some(true) ) - val metricsJSON = MetricsJSON( + val metricsJSON = MetricsJsonV220( property = "String", value = "Mapper" ) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala index ca73db103..15eb4e55c 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/JSONFactory2.2.0.scala @@ -273,9 +273,9 @@ case class CreateAccountJSONV220( case class CachedFunctionJSON(function_name: String, ttl_in_seconds: Int) case class PortJSON(property: String, value: String) case class AkkaJSON(ports: List[PortJSON], log_level: String, remote_data_secret_matched: Option[Boolean]) -case class MetricsJSON(property: String, value: String) +case class MetricsJsonV220(property: String, value: String) case class WarehouseJSON(property: String, value: String) -case class ElasticSearchJSON(metrics: List[MetricsJSON], warehouse: List[WarehouseJSON]) +case class ElasticSearchJSON(metrics: List[MetricsJsonV220], warehouse: List[WarehouseJSON]) case class ScopesJSON(require_scopes_for_all_roles: Boolean, require_scopes_for_listed_roles: List[String]) case class ConfigurationJSON(akka: AkkaJSON, elastic_search: ElasticSearchJSON, cache: List[CachedFunctionJSON], scopes: ScopesJSON) @@ -797,8 +797,8 @@ object JSONFactory220 { val akka = AkkaJSON(akkaPorts, ObpActorConfig.akka_loglevel, APIUtil.akkaSanityCheck()) val cache = f1::f2::f3::f4::f5::f6::f7::f8::Nil - val metrics = MetricsJSON("es.metrics.port.tcp", APIUtil.getPropsValue("es.metrics.port.tcp", "9300")) :: - MetricsJSON("es.metrics.port.http", APIUtil.getPropsValue("es.metrics.port.tcp", "9200")) :: + val metrics = MetricsJsonV220("es.metrics.port.tcp", APIUtil.getPropsValue("es.metrics.port.tcp", "9300")) :: + MetricsJsonV220("es.metrics.port.http", APIUtil.getPropsValue("es.metrics.port.tcp", "9200")) :: Nil val warehouse = WarehouseJSON("es.warehouse.port.tcp", APIUtil.getPropsValue("es.warehouse.port.tcp", "9300")) :: WarehouseJSON("es.warehouse.port.http", APIUtil.getPropsValue("es.warehouse.port.http", "9200")) :: From fa6b673678df21253f665364ae92e48f2bb75470 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 23 Mar 2023 15:52:07 +0100 Subject: [PATCH 15/16] refactor/remove the version in swagger operationId --- .../scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala | 2 +- obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 3267f8f6d..1b2d2261f 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -497,7 +497,7 @@ object SwaggerJSONFactory extends MdcLoggable { tags = rd.tags.map(_.tag), summary = rd.summary, description = PegdownOptions.convertPegdownToHtmlTweaked(rd.description.stripMargin).replaceAll("\n", ""), - operationId = s"${rd.implementedInApiVersion.fullyQualifiedVersion }-${rd.partialFunctionName.toString }", + operationId = s"${rd.partialFunctionName}", parameters ={ val description = rd.exampleRequestBody match { case EmptyBody => "" diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index e3d98ff83..4f93f9dda 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -12,6 +12,7 @@ import code.branches.Branches import code.customer.CustomerX import code.usercustomerlinks.UserCustomerLink import code.views.Views +import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model._ import com.openbankproject.commons.util.ApiVersion import net.liftweb.common.{Box, Full} @@ -128,7 +129,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ resourceDocs += ResourceDoc( addCustomerMessage, apiVersion, - "createCustomerMessage", + nameOf(addCustomerMessage), "POST", "/banks/BANK_ID/customer/CUSTOMER_ID/messages", "Create Customer Message", From 6c9ce3eaaba2a581e8efe7de48ed7cbafa34f2ae Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 24 Mar 2023 15:28:38 +0100 Subject: [PATCH 16/16] test/fixed the failed tests for swagger --- .../ResourceDocsAPIMethods.scala | 4 ++-- .../SwaggerDefinitionsJSON.scala | 2 +- .../src/test/resources/frozen_type_meta_data | Bin 141029 -> 141360 bytes .../SwaggerFactoryUnitTest.scala | 3 --- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index e5e538d39..e772faa7b 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 @@ -4,7 +4,7 @@ import code.api.Constant.PARAM_LOCALE import java.util.UUID.randomUUID import code.api.OBPRestHelper -import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.canGetCustomers +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.canGetCustomersJson import code.api.builder.OBP_APIBuilder import code.api.cache.Caching import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints} @@ -409,7 +409,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth emptyObjectJson, UnknownError :: Nil, List(apiTagDocumentation), - Some(List(canGetCustomers)) + Some(List(canGetCustomersJson)) ) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index c4c3a87dd..1b29e850d 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -4372,7 +4372,7 @@ object SwaggerDefinitionsJSON { bank_id = bankIdExample.value ) - val canGetCustomers = ApiRole.canGetCustomers + val canGetCustomersJson = ApiRole.canGetCustomers val cardAttributeCommons = CardAttributeCommons( bankId = Some(BankId(bankIdExample.value)), diff --git a/obp-api/src/test/resources/frozen_type_meta_data b/obp-api/src/test/resources/frozen_type_meta_data index 1d577364c9ea4569e0f563693a6efad238893460..99ced818b4cde4065f51e3f7317c4f88d064da4a 100644 GIT binary patch delta 8143 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