From 62c9ccae6ab0d128c54962675b88739ad7797fe6 Mon Sep 17 00:00:00 2001 From: Sai Harsha Vardhan <56996463+sai-harsha-vardhan@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:48:42 +0530 Subject: [PATCH] refactor(router): add openapi spec support for gsm apis (#2871) --- crates/api_models/src/events/gsm.rs | 6 + crates/api_models/src/gsm.rs | 32 +- crates/router/src/core/gsm.rs | 14 +- crates/router/src/openapi.rs | 13 +- crates/router/src/routes/gsm.rs | 68 +++++ crates/router/src/types.rs | 2 - crates/router/src/types/transformers.rs | 16 + openapi/openapi_spec.json | 382 ++++++++++++++++++++++++ 8 files changed, 515 insertions(+), 18 deletions(-) diff --git a/crates/api_models/src/events/gsm.rs b/crates/api_models/src/events/gsm.rs index d984ae1ff6..a653cc291d 100644 --- a/crates/api_models/src/events/gsm.rs +++ b/crates/api_models/src/events/gsm.rs @@ -31,3 +31,9 @@ impl ApiEventMetric for gsm::GsmDeleteResponse { Some(ApiEventsType::Gsm) } } + +impl ApiEventMetric for gsm::GsmResponse { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} diff --git a/crates/api_models/src/gsm.rs b/crates/api_models/src/gsm.rs index 6bd8fd99dd..254981b1f8 100644 --- a/crates/api_models/src/gsm.rs +++ b/crates/api_models/src/gsm.rs @@ -1,8 +1,10 @@ -use crate::enums; +use utoipa::ToSchema; -#[derive(Debug, serde::Deserialize, serde::Serialize)] +use crate::enums::Connector; + +#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct GsmCreateRequest { - pub connector: enums::Connector, + pub connector: Connector, pub flow: String, pub sub_flow: String, pub code: String, @@ -13,9 +15,9 @@ pub struct GsmCreateRequest { pub step_up_possible: bool, } -#[derive(Debug, serde::Deserialize, serde::Serialize)] +#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct GsmRetrieveRequest { - pub connector: enums::Connector, + pub connector: Connector, pub flow: String, pub sub_flow: String, pub code: String, @@ -33,6 +35,7 @@ pub struct GsmRetrieveRequest { serde::Serialize, serde::Deserialize, strum::EnumString, + ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] @@ -43,7 +46,7 @@ pub enum GsmDecision { DoDefault, } -#[derive(Debug, serde::Deserialize, serde::Serialize)] +#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct GsmUpdateRequest { pub connector: String, pub flow: String, @@ -56,7 +59,7 @@ pub struct GsmUpdateRequest { pub step_up_possible: Option, } -#[derive(Debug, serde::Deserialize, serde::Serialize)] +#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct GsmDeleteRequest { pub connector: String, pub flow: String, @@ -65,7 +68,7 @@ pub struct GsmDeleteRequest { pub message: String, } -#[derive(Debug, serde::Serialize)] +#[derive(Debug, serde::Serialize, ToSchema)] pub struct GsmDeleteResponse { pub gsm_rule_delete: bool, pub connector: String, @@ -73,3 +76,16 @@ pub struct GsmDeleteResponse { pub sub_flow: String, pub code: String, } + +#[derive(serde::Serialize, Debug, ToSchema)] +pub struct GsmResponse { + pub connector: String, + pub flow: String, + pub sub_flow: String, + pub code: String, + pub message: String, + pub status: String, + pub router_error: Option, + pub decision: String, + pub step_up_possible: bool, +} diff --git a/crates/router/src/core/gsm.rs b/crates/router/src/core/gsm.rs index d258606745..ed72275a73 100644 --- a/crates/router/src/core/gsm.rs +++ b/crates/router/src/core/gsm.rs @@ -10,7 +10,7 @@ use crate::{ }, db::gsm::GsmInterface, services, - types::{self, transformers::ForeignInto}, + types::transformers::ForeignInto, AppState, }; @@ -18,21 +18,21 @@ use crate::{ pub async fn create_gsm_rule( state: AppState, gsm_rule: gsm_api_types::GsmCreateRequest, -) -> RouterResponse { +) -> RouterResponse { let db = state.store.as_ref(); GsmInterface::add_gsm_rule(db, gsm_rule.foreign_into()) .await .to_duplicate_response(errors::ApiErrorResponse::GenericDuplicateError { message: "GSM with given key already exists in our records".to_string(), }) - .map(services::ApplicationResponse::Json) + .map(|gsm| services::ApplicationResponse::Json(gsm.foreign_into())) } #[instrument(skip_all)] pub async fn retrieve_gsm_rule( state: AppState, gsm_request: gsm_api_types::GsmRetrieveRequest, -) -> RouterResponse { +) -> RouterResponse { let db = state.store.as_ref(); let gsm_api_types::GsmRetrieveRequest { connector, @@ -46,14 +46,14 @@ pub async fn retrieve_gsm_rule( .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError { message: "GSM with given key does not exist in our records".to_string(), }) - .map(services::ApplicationResponse::Json) + .map(|gsm| services::ApplicationResponse::Json(gsm.foreign_into())) } #[instrument(skip_all)] pub async fn update_gsm_rule( state: AppState, gsm_request: gsm_api_types::GsmUpdateRequest, -) -> RouterResponse { +) -> RouterResponse { let db = state.store.as_ref(); let gsm_api_types::GsmUpdateRequest { connector, @@ -85,7 +85,7 @@ pub async fn update_gsm_rule( message: "GSM with given key does not exist in our records".to_string(), }) .attach_printable("Failed while updating Gsm rule") - .map(services::ApplicationResponse::Json) + .map(|gsm| services::ApplicationResponse::Json(gsm.foreign_into())) } #[instrument(skip_all)] diff --git a/crates/router/src/openapi.rs b/crates/router/src/openapi.rs index dbcd8cbe4c..095e1f45f9 100644 --- a/crates/router/src/openapi.rs +++ b/crates/router/src/openapi.rs @@ -114,7 +114,11 @@ Never share your secret api keys. Keep them guarded and secure. crate::routes::payouts::payouts_fulfill, crate::routes::payouts::payouts_retrieve, crate::routes::payouts::payouts_update, - crate::routes::payment_link::payment_link_retrieve + crate::routes::payment_link::payment_link_retrieve, + crate::routes::gsm::create_gsm_rule, + crate::routes::gsm::get_gsm_rule, + crate::routes::gsm::update_gsm_rule, + crate::routes::gsm::delete_gsm_rule, ), components(schemas( crate::types::api::refunds::RefundRequest, @@ -184,6 +188,13 @@ Never share your secret api keys. Keep them guarded and secure. api_models::admin::PaymentLinkColorSchema, api_models::disputes::DisputeResponse, api_models::disputes::DisputeResponsePaymentsRetrieve, + api_models::gsm::GsmCreateRequest, + api_models::gsm::GsmRetrieveRequest, + api_models::gsm::GsmUpdateRequest, + api_models::gsm::GsmDeleteRequest, + api_models::gsm::GsmDeleteResponse, + api_models::gsm::GsmResponse, + api_models::gsm::GsmDecision, api_models::payments::AddressDetails, api_models::payments::BankDebitData, api_models::payments::AliPayQr, diff --git a/crates/router/src/routes/gsm.rs b/crates/router/src/routes/gsm.rs index 02d943792d..ff70635959 100644 --- a/crates/router/src/routes/gsm.rs +++ b/crates/router/src/routes/gsm.rs @@ -8,6 +8,23 @@ use crate::{ services::{api, authentication as auth}, }; +/// Gsm - Create +/// +/// To create a Gsm Rule +#[utoipa::path( + post, + path = "/gsm", + request_body( + content = GsmCreateRequest, + ), + responses( + (status = 200, description = "Gsm created", body = GsmResponse), + (status = 400, description = "Missing Mandatory fields") + ), + tag = "Gsm", + operation_id = "Create Gsm Rule", + security(("admin_api_key" = [])), +)] #[instrument(skip_all, fields(flow = ?Flow::GsmRuleCreate))] pub async fn create_gsm_rule( state: web::Data, @@ -29,6 +46,23 @@ pub async fn create_gsm_rule( .await } +/// Gsm - Get +/// +/// To get a Gsm Rule +#[utoipa::path( + post, + path = "/gsm/get", + request_body( + content = GsmRetrieveRequest, + ), + responses( + (status = 200, description = "Gsm retrieved", body = GsmResponse), + (status = 400, description = "Missing Mandatory fields") + ), + tag = "Gsm", + operation_id = "Retrieve Gsm Rule", + security(("admin_api_key" = [])), +)] #[instrument(skip_all, fields(flow = ?Flow::GsmRuleRetrieve))] pub async fn get_gsm_rule( state: web::Data, @@ -49,6 +83,23 @@ pub async fn get_gsm_rule( .await } +/// Gsm - Update +/// +/// To update a Gsm Rule +#[utoipa::path( + post, + path = "/gsm/update", + request_body( + content = GsmUpdateRequest, + ), + responses( + (status = 200, description = "Gsm updated", body = GsmResponse), + (status = 400, description = "Missing Mandatory fields") + ), + tag = "Gsm", + operation_id = "Update Gsm Rule", + security(("admin_api_key" = [])), +)] #[instrument(skip_all, fields(flow = ?Flow::GsmRuleUpdate))] pub async fn update_gsm_rule( state: web::Data, @@ -70,6 +121,23 @@ pub async fn update_gsm_rule( .await } +/// Gsm - Delete +/// +/// To delete a Gsm Rule +#[utoipa::path( + post, + path = "/gsm/delete", + request_body( + content = GsmDeleteRequest, + ), + responses( + (status = 200, description = "Gsm deleted", body = GsmDeleteResponse), + (status = 400, description = "Missing Mandatory fields") + ), + tag = "Gsm", + operation_id = "Delete Gsm Rule", + security(("admin_api_key" = [])), +)] #[instrument(skip_all, fields(flow = ?Flow::GsmRuleDelete))] pub async fn delete_gsm_rule( state: web::Data, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 7e9725d1a3..7cf8f6b71f 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -1213,5 +1213,3 @@ impl } } } - -pub type GsmResponse = storage::GatewayStatusMap; diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 1cd016de18..69ce2df974 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -1047,3 +1047,19 @@ impl ForeignFrom for storage::GatewayStatusMapp } } } + +impl ForeignFrom for gsm_api_types::GsmResponse { + fn foreign_from(value: storage::GatewayStatusMap) -> Self { + Self { + connector: value.connector.to_string(), + flow: value.flow, + sub_flow: value.sub_flow, + code: value.code, + message: value.message, + decision: value.decision.to_string(), + status: value.status, + router_error: value.router_error, + step_up_possible: value.step_up_possible, + } + } +} diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index 23f8f1b362..c576c6c8a9 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -745,6 +745,166 @@ ] } }, + "/gsm": { + "post": { + "tags": [ + "Gsm" + ], + "summary": "Gsm - Create", + "description": "Gsm - Create\n\nTo create a Gsm Rule", + "operationId": "Create Gsm Rule", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmCreateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Gsm created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmResponse" + } + } + } + }, + "400": { + "description": "Missing Mandatory fields" + } + }, + "security": [ + { + "admin_api_key": [] + } + ] + } + }, + "/gsm/delete": { + "post": { + "tags": [ + "Gsm" + ], + "summary": "Gsm - Delete", + "description": "Gsm - Delete\n\nTo delete a Gsm Rule", + "operationId": "Delete Gsm Rule", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmDeleteRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Gsm deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmDeleteResponse" + } + } + } + }, + "400": { + "description": "Missing Mandatory fields" + } + }, + "security": [ + { + "admin_api_key": [] + } + ] + } + }, + "/gsm/get": { + "post": { + "tags": [ + "Gsm" + ], + "summary": "Gsm - Get", + "description": "Gsm - Get\n\nTo get a Gsm Rule", + "operationId": "Retrieve Gsm Rule", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmRetrieveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Gsm retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmResponse" + } + } + } + }, + "400": { + "description": "Missing Mandatory fields" + } + }, + "security": [ + { + "admin_api_key": [] + } + ] + } + }, + "/gsm/update": { + "post": { + "tags": [ + "Gsm" + ], + "summary": "Gsm - Update", + "description": "Gsm - Update\n\nTo update a Gsm Rule", + "operationId": "Update Gsm Rule", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Gsm updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GsmResponse" + } + } + } + }, + "400": { + "description": "Missing Mandatory fields" + } + }, + "security": [ + { + "admin_api_key": [] + } + ] + } + }, "/mandates/revoke/{mandate_id}": { "post": { "tags": [ @@ -5713,6 +5873,228 @@ } } }, + "GsmCreateRequest": { + "type": "object", + "required": [ + "connector", + "flow", + "sub_flow", + "code", + "message", + "status", + "decision", + "step_up_possible" + ], + "properties": { + "connector": { + "$ref": "#/components/schemas/Connector" + }, + "flow": { + "type": "string" + }, + "sub_flow": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + }, + "router_error": { + "type": "string", + "nullable": true + }, + "decision": { + "$ref": "#/components/schemas/GsmDecision" + }, + "step_up_possible": { + "type": "boolean" + } + } + }, + "GsmDecision": { + "type": "string", + "enum": [ + "retry", + "requeue", + "do_default" + ] + }, + "GsmDeleteRequest": { + "type": "object", + "required": [ + "connector", + "flow", + "sub_flow", + "code", + "message" + ], + "properties": { + "connector": { + "type": "string" + }, + "flow": { + "type": "string" + }, + "sub_flow": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "GsmDeleteResponse": { + "type": "object", + "required": [ + "gsm_rule_delete", + "connector", + "flow", + "sub_flow", + "code" + ], + "properties": { + "gsm_rule_delete": { + "type": "boolean" + }, + "connector": { + "type": "string" + }, + "flow": { + "type": "string" + }, + "sub_flow": { + "type": "string" + }, + "code": { + "type": "string" + } + } + }, + "GsmResponse": { + "type": "object", + "required": [ + "connector", + "flow", + "sub_flow", + "code", + "message", + "status", + "decision", + "step_up_possible" + ], + "properties": { + "connector": { + "type": "string" + }, + "flow": { + "type": "string" + }, + "sub_flow": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + }, + "router_error": { + "type": "string", + "nullable": true + }, + "decision": { + "type": "string" + }, + "step_up_possible": { + "type": "boolean" + } + } + }, + "GsmRetrieveRequest": { + "type": "object", + "required": [ + "connector", + "flow", + "sub_flow", + "code", + "message" + ], + "properties": { + "connector": { + "$ref": "#/components/schemas/Connector" + }, + "flow": { + "type": "string" + }, + "sub_flow": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "GsmUpdateRequest": { + "type": "object", + "required": [ + "connector", + "flow", + "sub_flow", + "code", + "message" + ], + "properties": { + "connector": { + "type": "string" + }, + "flow": { + "type": "string" + }, + "sub_flow": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string", + "nullable": true + }, + "router_error": { + "type": "string", + "nullable": true + }, + "decision": { + "allOf": [ + { + "$ref": "#/components/schemas/GsmDecision" + } + ], + "nullable": true + }, + "step_up_possible": { + "type": "boolean", + "nullable": true + } + } + }, "IndomaretVoucherData": { "type": "object", "required": [