From d84e62441f39c165af7dc1c8d893344ff85c1711 Mon Sep 17 00:00:00 2001 From: Pa1NarK <69745008+pixincreate@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:06:34 +0530 Subject: [PATCH 01/10] chore(cypress): remove logs that expose `globalState` (#4844) --- .../e2e/ConnectorTest/00000-AccountCreate.cy.js | 2 -- .../ConnectorTest/00001-CustomerCreate.cy.js | 2 -- .../ConnectorTest/00002-ConnectorCreate.cy.js | 2 -- .../00003-NoThreeDSAutoCapture.cy.js | 4 ---- .../00004-ThreeDSAutoCapture.cy.js | 6 ------ .../00005-NoThreeDSManualCapture.cy.js | 2 -- .../e2e/ConnectorTest/00006-VoidPayment.cy.js | 2 -- .../e2e/ConnectorTest/00007-SyncPayment.cy.js | 2 -- .../e2e/ConnectorTest/00008-RefundPayment.cy.js | 4 ---- .../e2e/ConnectorTest/00009-SyncRefund.cy.js | 2 -- .../00010-CreateSingleuseMandate.cy.js | 2 -- .../00011-CreateMultiuseMandate.cy.js | 2 -- .../00012-ListAndRevokeMandate.cy.js | 2 -- .../e2e/ConnectorTest/00013-SaveCardFlow.cy.js | 1 - .../ConnectorTest/00014-ZeroAuthMandate.cy.js | 2 -- .../00015-ThreeDSManualCapture.cy.js | 2 -- .../e2e/ConnectorTest/00016-BankTransfers.cy.js | 4 ---- .../e2e/ConnectorTest/00017-BankRedirect.cy.js | 17 ----------------- 18 files changed, 60 deletions(-) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00000-AccountCreate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00000-AccountCreate.cy.js index 4c16fef8df41..aed901c29972 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00000-AccountCreate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00000-AccountCreate.cy.js @@ -9,11 +9,9 @@ describe("Account Create flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00001-CustomerCreate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00001-CustomerCreate.cy.js index c21152ca896e..5e8bcb5aa14c 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00001-CustomerCreate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00001-CustomerCreate.cy.js @@ -9,11 +9,9 @@ describe("Customer Create flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) it("customer-create-call-test", () => { diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00002-ConnectorCreate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00002-ConnectorCreate.cy.js index 1241048f2862..927f0d020110 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00002-ConnectorCreate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00002-ConnectorCreate.cy.js @@ -8,12 +8,10 @@ describe("Connector Account Create flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00003-NoThreeDSAutoCapture.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00003-NoThreeDSAutoCapture.cy.js index 4dc3f2a3e78f..ec36fa16023e 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00003-NoThreeDSAutoCapture.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00003-NoThreeDSAutoCapture.cy.js @@ -13,12 +13,10 @@ describe("Card - NoThreeDS payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) @@ -78,7 +76,5 @@ describe("Card - NoThreeDS payment flow test", () => { it("retrieve-payment-call-test", () => { cy.retrievePaymentCallTest(globalState); }); - - }); }); diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00004-ThreeDSAutoCapture.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00004-ThreeDSAutoCapture.cy.js index c970d9716eff..3178170021c5 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00004-ThreeDSAutoCapture.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00004-ThreeDSAutoCapture.cy.js @@ -19,16 +19,12 @@ describe("Card - ThreeDS payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); - cy.task('cli_log', "SEEDING GLOBAL STATE -> " + JSON.stringify(globalState)); }) }) afterEach("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); - cy.task('cli_log', " FLUSHING GLOBAL STATE -> " + JSON.stringify(globalState)); }) @@ -41,7 +37,6 @@ describe("Card - ThreeDS payment flow test", () => { }); it("payment_methods-call-test", () => { - cy.task('cli_log', "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -49,7 +44,6 @@ describe("Card - ThreeDS payment flow test", () => { let data = getConnectorDetails(globalState.get("connectorId"))["card_pm"]["3DSAutoCapture"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task('cli_log', "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmCallTest(confirmBody, req_data, res_data, true, globalState); if(should_continue) should_continue = utils.should_continue_further(res_data); }); diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00005-NoThreeDSManualCapture.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00005-NoThreeDSManualCapture.cy.js index 48a22f5a5c03..4ee4483c961a 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00005-NoThreeDSManualCapture.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00005-NoThreeDSManualCapture.cy.js @@ -14,12 +14,10 @@ describe("Card - NoThreeDS Manual payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00006-VoidPayment.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00006-VoidPayment.cy.js index 15f2e0e7930a..ef8157775688 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00006-VoidPayment.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00006-VoidPayment.cy.js @@ -13,12 +13,10 @@ describe("Card - NoThreeDS Manual payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00007-SyncPayment.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00007-SyncPayment.cy.js index 10c16f7ff6e9..1920cdd09dbc 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00007-SyncPayment.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00007-SyncPayment.cy.js @@ -19,12 +19,10 @@ describe("Card - Sync payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) it("create-payment-call-test", () => { diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00008-RefundPayment.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00008-RefundPayment.cy.js index 028e48a41dc8..672c5cf8f4aa 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00008-RefundPayment.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00008-RefundPayment.cy.js @@ -18,13 +18,11 @@ describe("Card - Refund flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) afterEach("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) @@ -534,13 +532,11 @@ describe("Card - Refund flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) afterEach("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00009-SyncRefund.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00009-SyncRefund.cy.js index 31e5e6855d6a..f0cdc9a68903 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00009-SyncRefund.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00009-SyncRefund.cy.js @@ -20,12 +20,10 @@ describe("Card - Sync Refund flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00010-CreateSingleuseMandate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00010-CreateSingleuseMandate.cy.js index 4ece0319324e..ec85017f55d3 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00010-CreateSingleuseMandate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00010-CreateSingleuseMandate.cy.js @@ -13,12 +13,10 @@ describe("Card - SingleUse Mandates flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00011-CreateMultiuseMandate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00011-CreateMultiuseMandate.cy.js index 898258c8d6a3..3e14d69db88e 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00011-CreateMultiuseMandate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00011-CreateMultiuseMandate.cy.js @@ -13,12 +13,10 @@ describe("Card - MultiUse Mandates flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00012-ListAndRevokeMandate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00012-ListAndRevokeMandate.cy.js index 8de48fbf95a4..1f9782f22740 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00012-ListAndRevokeMandate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00012-ListAndRevokeMandate.cy.js @@ -13,12 +13,10 @@ describe("Card - SingleUse Mandates flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00013-SaveCardFlow.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00013-SaveCardFlow.cy.js index 1168a5690893..828fb5101ac7 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00013-SaveCardFlow.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00013-SaveCardFlow.cy.js @@ -15,7 +15,6 @@ describe("Card - SaveCard payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00014-ZeroAuthMandate.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00014-ZeroAuthMandate.cy.js index ee0edcb94ac2..7a0eba4b6ad9 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00014-ZeroAuthMandate.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00014-ZeroAuthMandate.cy.js @@ -12,12 +12,10 @@ describe("Card - SingleUse Mandates flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00015-ThreeDSManualCapture.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00015-ThreeDSManualCapture.cy.js index 4c3d2a1cd0b5..50d136b59600 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00015-ThreeDSManualCapture.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00015-ThreeDSManualCapture.cy.js @@ -15,13 +15,11 @@ describe("Card - ThreeDS Manual payment flow test", () => { cy.task('getGlobalState').then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }) }) afterEach("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task('setGlobalState', globalState.data); }) diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00016-BankTransfers.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00016-BankTransfers.cy.js index ae5f09871024..da4fab34b8e5 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00016-BankTransfers.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00016-BankTransfers.cy.js @@ -9,12 +9,10 @@ describe("Bank Transfers", () => { before("seed global state", () => { cy.task("getGlobalState").then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }); }); after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task("setGlobalState", globalState.data); }); @@ -46,7 +44,6 @@ describe("Bank Transfers", () => { }); it("payment_methods-call-test", () => { - cy.task("cli_log", "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -56,7 +53,6 @@ describe("Bank Transfers", () => { ]["Pix"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task("cli_log", "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmBankTransferCallTest( confirmBody, req_data, diff --git a/cypress-tests/cypress/e2e/ConnectorTest/00017-BankRedirect.cy.js b/cypress-tests/cypress/e2e/ConnectorTest/00017-BankRedirect.cy.js index c08468022a80..3a636b2020a0 100644 --- a/cypress-tests/cypress/e2e/ConnectorTest/00017-BankRedirect.cy.js +++ b/cypress-tests/cypress/e2e/ConnectorTest/00017-BankRedirect.cy.js @@ -9,22 +9,15 @@ describe("Bank Redirect tests", () => { before("seed global state", () => { cy.task("getGlobalState").then((state) => { globalState = new State(state); - console.log("seeding globalState -> " + JSON.stringify(globalState)); }); }); after("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task("setGlobalState", globalState.data); }); afterEach("flush global state", () => { - console.log("flushing globalState -> " + JSON.stringify(globalState)); cy.task("setGlobalState", globalState.data); - cy.task( - "cli_log", - " FLUSHING GLOBAL STATE -> " + JSON.stringify(globalState) - ); }); context("Blik Create and Confirm flow test", () => { @@ -55,7 +48,6 @@ describe("Bank Redirect tests", () => { }); it("payment_methods-call-test", () => { - cy.task("cli_log", "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -65,7 +57,6 @@ describe("Bank Redirect tests", () => { ]["blik"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task("cli_log", "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmBankRedirectCallTest( confirmBody, req_data, @@ -105,7 +96,6 @@ describe("Bank Redirect tests", () => { }); it("payment_methods-call-test", () => { - cy.task("cli_log", "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -115,7 +105,6 @@ describe("Bank Redirect tests", () => { ]["eps"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task("cli_log", "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmBankRedirectCallTest( confirmBody, req_data, @@ -167,7 +156,6 @@ describe("Bank Redirect tests", () => { }); it("payment_methods-call-test", () => { - cy.task("cli_log", "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -177,7 +165,6 @@ describe("Bank Redirect tests", () => { ]["ideal"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task("cli_log", "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmBankRedirectCallTest( confirmBody, req_data, @@ -228,7 +215,6 @@ describe("Bank Redirect tests", () => { }); it("payment_methods-call-test", () => { - cy.task("cli_log", "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -238,7 +224,6 @@ describe("Bank Redirect tests", () => { ]["giropay"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task("cli_log", "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmBankRedirectCallTest( confirmBody, req_data, @@ -289,7 +274,6 @@ describe("Bank Redirect tests", () => { }); it("payment_methods-call-test", () => { - cy.task("cli_log", "PM CALL "); cy.paymentMethodsCallTest(globalState); }); @@ -299,7 +283,6 @@ describe("Bank Redirect tests", () => { ]["sofort"]; let req_data = data["Request"]; let res_data = data["Response"]; - cy.task("cli_log", "GLOBAL STATE -> " + JSON.stringify(globalState.data)); cy.confirmBankRedirectCallTest( confirmBody, req_data, From 69b2f76be7a2c0deba2c069a87c10a33253e2216 Mon Sep 17 00:00:00 2001 From: Hrithikesh <61539176+hrithikesh026@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:22:44 +0530 Subject: [PATCH 02/10] fix(connector): make few fields optional in struct NetceteraErrorDetails (#4827) --- crates/router/src/connector/netcetera.rs | 2 +- .../router/src/connector/netcetera/transformers.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/router/src/connector/netcetera.rs b/crates/router/src/connector/netcetera.rs index 43df87db40f4..714873cfb531 100644 --- a/crates/router/src/connector/netcetera.rs +++ b/crates/router/src/connector/netcetera.rs @@ -107,7 +107,7 @@ impl ConnectorCommon for Netcetera { status_code: res.status_code, code: response.error_details.error_code, message: response.error_details.error_description, - reason: Some(response.error_details.error_detail), + reason: response.error_details.error_detail, attempt_status: None, connector_transaction_id: None, }) diff --git a/crates/router/src/connector/netcetera/transformers.rs b/crates/router/src/connector/netcetera/transformers.rs index 66813716fb91..0fcecadef249 100644 --- a/crates/router/src/connector/netcetera/transformers.rs +++ b/crates/router/src/connector/netcetera/transformers.rs @@ -105,8 +105,8 @@ impl NetceteraPreAuthenticationResponse::Failure(error_response) => { Err(types::ErrorResponse { code: error_response.error_details.error_code, - message: error_response.error_details.error_detail, - reason: Some(error_response.error_details.error_description), + message: error_response.error_details.error_description, + reason: error_response.error_details.error_detail, status_code: item.http_code, attempt_status: None, connector_transaction_id: None, @@ -174,8 +174,8 @@ impl } NetceteraAuthenticationResponse::Error(error_response) => Err(types::ErrorResponse { code: error_response.error_details.error_code, - message: error_response.error_details.error_detail, - reason: Some(error_response.error_details.error_description), + message: error_response.error_details.error_description, + reason: error_response.error_details.error_detail, status_code: item.http_code, attempt_status: None, connector_transaction_id: None, @@ -235,20 +235,20 @@ pub struct NetceteraErrorDetails { pub error_code: String, /// Code indicating the 3-D Secure component that identified the error. - pub error_component: String, + pub error_component: Option, /// Text describing the problem identified. pub error_description: String, /// Additional detail regarding the problem identified. - pub error_detail: String, + pub error_detail: Option, /// Universally unique identifier for the transaction assigned by the 3DS SDK. #[serde(rename = "sdkTransID")] pub sdk_trans_id: Option, /// The Message Type that was identified as erroneous. - pub error_message_type: String, + pub error_message_type: Option, } #[derive(Debug, Serialize, Deserialize)] From 865007717c5c7e617ca1b447ea5f9bb3d274cac3 Mon Sep 17 00:00:00 2001 From: Swangi Kumari <85639103+swangi-kumari@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:24:56 +0530 Subject: [PATCH 03/10] refactor(connector): [Klarna] Add shipping Address in Klarna Session and Payment Request (#4836) --- crates/router/src/connector/klarna.rs | 1 + .../src/connector/klarna/transformers.rs | 40 ++++++++ crates/router/src/connector/utils.rs | 95 +++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs index 3258e08ba991..2059b00ac363 100644 --- a/crates/router/src/connector/klarna.rs +++ b/crates/router/src/connector/klarna.rs @@ -665,6 +665,7 @@ impl req, ))?; let connector_req = klarna::KlarnaPaymentsRequest::try_from(&connector_router_data)?; + Ok(RequestContent::Json(Box::new(connector_req))) } diff --git a/crates/router/src/connector/klarna/transformers.rs b/crates/router/src/connector/klarna/transformers.rs index c14af3aad318..69b9dfc67bb9 100644 --- a/crates/router/src/connector/klarna/transformers.rs +++ b/crates/router/src/connector/klarna/transformers.rs @@ -75,6 +75,7 @@ pub struct KlarnaPaymentsRequest { purchase_country: enums::CountryAlpha2, purchase_currency: enums::Currency, merchant_reference1: Option, + shipping_address: Option, } #[derive(Debug, Deserialize, Serialize)] @@ -90,6 +91,21 @@ pub struct KlarnaSessionRequest { purchase_currency: enums::Currency, order_amount: i64, order_lines: Vec, + shipping_address: Option, +} + +#[derive(Debug, Serialize)] +pub struct KlarnaShippingAddress { + city: Option, + country: Option, + email: Option, + given_name: Option>, + family_name: Option>, + phone: Option>, + postal_code: Option>, + region: Option>, + street_address: Option>, + street_address2: Option>, } #[derive(Deserialize, Serialize, Debug)] @@ -123,6 +139,18 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsSessionRouterData>> for KlarnaSes total_amount: i64::from(data.quantity) * (data.amount), }) .collect(), + shipping_address: Some(KlarnaShippingAddress { + city: item.router_data.get_optional_shipping_city(), + country: item.router_data.get_optional_shipping_country(), + email: item.router_data.get_optional_shipping_email(), + given_name: item.router_data.get_optional_shipping_first_name(), + family_name: item.router_data.get_optional_shipping_last_name(), + phone: item.router_data.get_optional_shipping_phone_number(), + postal_code: item.router_data.get_optional_shipping_zip(), + region: item.router_data.get_optional_shipping_state(), + street_address: item.router_data.get_optional_shipping_line1(), + street_address2: item.router_data.get_optional_shipping_line2(), + }), }), None => Err(report!(errors::ConnectorError::MissingRequiredField { field_name: "order_details", @@ -176,6 +204,18 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsAuthorizeRouterData>> for KlarnaP .collect(), merchant_reference1: Some(item.router_data.connector_request_reference_id.clone()), auto_capture: request.is_auto_capture()?, + shipping_address: Some(KlarnaShippingAddress { + city: item.router_data.get_optional_shipping_city(), + country: item.router_data.get_optional_shipping_country(), + email: item.router_data.get_optional_shipping_email(), + given_name: item.router_data.get_optional_shipping_first_name(), + family_name: item.router_data.get_optional_shipping_last_name(), + phone: item.router_data.get_optional_shipping_phone_number(), + postal_code: item.router_data.get_optional_shipping_zip(), + region: item.router_data.get_optional_shipping_state(), + street_address: item.router_data.get_optional_shipping_line1(), + street_address2: item.router_data.get_optional_shipping_line2(), + }), }), None => Err(report!(errors::ConnectorError::MissingRequiredField { field_name: "order_details" diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index ba0ef166808c..6737bbf3af0f 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -101,6 +101,16 @@ pub trait RouterData { fn get_optional_billing(&self) -> Option<&api::Address>; fn get_optional_shipping(&self) -> Option<&api::Address>; + fn get_optional_shipping_line1(&self) -> Option>; + fn get_optional_shipping_line2(&self) -> Option>; + fn get_optional_shipping_city(&self) -> Option; + fn get_optional_shipping_country(&self) -> Option; + fn get_optional_shipping_zip(&self) -> Option>; + fn get_optional_shipping_state(&self) -> Option>; + fn get_optional_shipping_first_name(&self) -> Option>; + fn get_optional_shipping_last_name(&self) -> Option>; + fn get_optional_shipping_phone_number(&self) -> Option>; + fn get_optional_shipping_email(&self) -> Option; fn get_optional_billing_full_name(&self) -> Option>; fn get_optional_billing_line1(&self) -> Option>; @@ -199,6 +209,91 @@ impl RouterData for types::RouterData Option> { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.first_name) + }) + } + + fn get_optional_shipping_last_name(&self) -> Option> { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.last_name) + }) + } + + fn get_optional_shipping_line1(&self) -> Option> { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.line1) + }) + } + + fn get_optional_shipping_line2(&self) -> Option> { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.line2) + }) + } + + fn get_optional_shipping_city(&self) -> Option { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.city) + }) + } + + fn get_optional_shipping_state(&self) -> Option> { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.state) + }) + } + + fn get_optional_shipping_country(&self) -> Option { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.country) + }) + } + + fn get_optional_shipping_zip(&self) -> Option> { + self.address.get_shipping().and_then(|shipping_address| { + shipping_address + .clone() + .address + .and_then(|shipping_address_details| shipping_address_details.zip) + }) + } + + fn get_optional_shipping_email(&self) -> Option { + self.address + .get_shipping() + .and_then(|shipping_address| shipping_address.clone().email) + } + + fn get_optional_shipping_phone_number(&self) -> Option> { + self.address + .get_shipping() + .and_then(|shipping_address| shipping_address.clone().phone) + .and_then(|phone_details| phone_details.get_number_with_country_code().ok()) + } + fn get_description(&self) -> Result { self.description .clone() From ccee1a9ce9e860bfa04e74329fb47fd73f010b23 Mon Sep 17 00:00:00 2001 From: ivor-juspay <138492857+ivor-juspay@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:46:17 +0530 Subject: [PATCH 04/10] feat(consolidated-kafka-events): add consolidated kafka payment events (#4798) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Sampras Lopes --- config/config.example.toml | 26 ++-- config/deployments/env_specific.toml | 1 + config/development.toml | 6 +- config/docker_compose.toml | 10 +- crates/router/src/events.rs | 1 + crates/router/src/services/kafka.rs | 105 +++++++++++++--- .../src/services/kafka/dispute_event.rs | 77 ++++++++++++ .../services/kafka/payment_attempt_event.rs | 119 ++++++++++++++++++ .../services/kafka/payment_intent_event.rs | 75 +++++++++++ .../router/src/services/kafka/refund_event.rs | 74 +++++++++++ 10 files changed, 455 insertions(+), 39 deletions(-) create mode 100644 crates/router/src/services/kafka/dispute_event.rs create mode 100644 crates/router/src/services/kafka/payment_attempt_event.rs create mode 100644 crates/router/src/services/kafka/payment_intent_event.rs create mode 100644 crates/router/src/services/kafka/refund_event.rs diff --git a/config/config.example.toml b/config/config.example.toml index 5433d7a8e46e..5d40d0e55ef9 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -263,8 +263,7 @@ stripe = { banks = "alior_bank,bank_millennium,bank_nowy_bfg_sa,bank_pekao_sa,ba # This data is used to call respective connectors for wallets and cards [connectors.supported] -wallets = ["klarna", - "mifinity", "braintree", "applepay"] +wallets = ["klarna", "mifinity", "braintree", "applepay"] rewards = ["cashtocode", "zen"] cards = [ "adyen", @@ -352,8 +351,8 @@ email_role_arn = "" # The amazon resource name ( arn ) of the role which sts_role_session_name = "" # An identifier for the assumed role session, used to uniquely identify a session. [user] -password_validity_in_days = 90 # Number of days after which password should be updated -two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside +password_validity_in_days = 90 # Number of days after which password should be updated +two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside #tokenization configuration which describe token lifetime and payment method for specific connector [tokenization] @@ -364,7 +363,7 @@ stax = { long_lived_token = true, payment_method = "card,bank_debit" } square = { long_lived_token = false, payment_method = "card" } braintree = { long_lived_token = false, payment_method = "card" } gocardless = { long_lived_token = true, payment_method = "bank_debit" } -billwerk = {long_lived_token = false, payment_method = "card"} +billwerk = { long_lived_token = false, payment_method = "card" } [temp_locker_enable_config] stripe = { payment_method = "bank_transfer" } @@ -397,16 +396,16 @@ slack_invite_url = "https://www.example.com/" # Slack invite url for hyperswit discord_invite_url = "https://www.example.com/" # Discord invite url for hyperswitch [mandates.supported_payment_methods] -card.credit = { connector_list = "stripe,adyen,cybersource,bankofamerica"} # Mandate supported payment method type and connector for card -wallet.paypal = { connector_list = "adyen" } # Mandate supported payment method type and connector for wallets -pay_later.klarna = { connector_list = "adyen" } # Mandate supported payment method type and connector for pay_later -bank_debit.ach = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit -bank_debit.becs = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit -bank_debit.sepa = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit -bank_redirect.ideal = { connector_list = "stripe,adyen,globalpay" } # Mandate supported payment method type and connector for bank_redirect +card.credit = { connector_list = "stripe,adyen,cybersource,bankofamerica" } # Mandate supported payment method type and connector for card +wallet.paypal = { connector_list = "adyen" } # Mandate supported payment method type and connector for wallets +pay_later.klarna = { connector_list = "adyen" } # Mandate supported payment method type and connector for pay_later +bank_debit.ach = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit +bank_debit.becs = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit +bank_debit.sepa = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit +bank_redirect.ideal = { connector_list = "stripe,adyen,globalpay" } # Mandate supported payment method type and connector for bank_redirect bank_redirect.sofort = { connector_list = "stripe,adyen,globalpay" } wallet.apple_pay = { connector_list = "stripe,adyen,cybersource,noon,bankofamerica" } -wallet.google_pay = { connector_list = "bankofamerica"} +wallet.google_pay = { connector_list = "bankofamerica" } bank_redirect.giropay = { connector_list = "adyen,globalpay" } @@ -589,6 +588,7 @@ outgoing_webhook_logs_topic = "topic" # Kafka topic to be used for outgoing webh dispute_analytics_topic = "topic" # Kafka topic to be used for Dispute events audit_events_topic = "topic" # Kafka topic to be used for Payment Audit events payout_analytics_topic = "topic" # Kafka topic to be used for Payouts and PayoutAttempt events +consolidated_events_topic = "topic" # Kafka topic to be used for Consolidated events # File storage configuration [file_storage] diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml index fc02335dcf53..7215e1931a40 100644 --- a/config/deployments/env_specific.toml +++ b/config/deployments/env_specific.toml @@ -81,6 +81,7 @@ outgoing_webhook_logs_topic = "topic" # Kafka topic to be used for outgoing webh dispute_analytics_topic = "topic" # Kafka topic to be used for Dispute events audit_events_topic = "topic" # Kafka topic to be used for Payment Audit events payout_analytics_topic = "topic" # Kafka topic to be used for Payouts and PayoutAttempt events +consolidated_events_topic = "topic" # Kafka topic to be used for Consolidated events # File storage configuration [file_storage] diff --git a/config/development.toml b/config/development.toml index 56d74e674897..496ce6477a8d 100644 --- a/config/development.toml +++ b/config/development.toml @@ -89,8 +89,7 @@ vault_private_key = "" tunnel_private_key = "" [connectors.supported] -wallets = ["klarna", - "mifinity", "braintree", "applepay", "adyen"] +wallets = ["klarna", "mifinity", "braintree", "applepay", "adyen"] rewards = ["cashtocode", "zen"] cards = [ "aci", @@ -559,7 +558,7 @@ redis_lock_expiry_seconds = 180 # 3 * 60 seconds delay_between_retries_in_milliseconds = 500 [kv_config] -ttl = 900 # 15 * 60 seconds +ttl = 900 # 15 * 60 seconds soft_kill = false [frm] @@ -579,6 +578,7 @@ outgoing_webhook_logs_topic = "hyperswitch-outgoing-webhook-events" dispute_analytics_topic = "hyperswitch-dispute-events" audit_events_topic = "hyperswitch-audit-events" payout_analytics_topic = "hyperswitch-payout-events" +consolidated_events_topic = "hyperswitch-consolidated-events" [analytics] source = "sqlx" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 3dac84e21d83..b94b5c8afbb6 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -180,8 +180,7 @@ zsl.base_url = "https://api.sitoffalb.net/" apple_pay = { country = "AU,CN,HK,JP,MO,MY,NZ,SG,TW,AM,AT,AZ,BY,BE,BG,HR,CY,CZ,DK,EE,FO,FI,FR,GE,DE,GR,GL,GG,HU,IS,IE,IM,IT,KZ,JE,LV,LI,LT,LU,MT,MD,MC,ME,NL,NO,PL,PT,RO,SM,RS,SK,SI,ES,SE,CH,UA,GB,AR,CO,CR,BR,MX,PE,BH,IL,JO,KW,PS,QA,SA,AE,CA,UM,US,KR,VN,MA,ZA,VA,CL,SV,GT,HN,PA", currency = "AED,AUD,CHF,CAD,EUR,GBP,HKD,SGD,USD" } [connectors.supported] -wallets = ["klarna", - "mifinity", "braintree", "applepay"] +wallets = ["klarna", "mifinity", "braintree", "applepay"] rewards = ["cashtocode", "zen"] cards = [ "aci", @@ -239,7 +238,7 @@ cards = [ "worldline", "worldpay", "zen", - "zsl" + "zsl", ] [delayed_session_response] @@ -269,7 +268,7 @@ stax = { long_lived_token = true, payment_method = "card,bank_debit" } square = { long_lived_token = false, payment_method = "card" } braintree = { long_lived_token = false, payment_method = "card" } gocardless = { long_lived_token = true, payment_method = "bank_debit" } -billwerk = {long_lived_token = false, payment_method = "card"} +billwerk = { long_lived_token = false, payment_method = "card" } [temp_locker_enable_config] stripe = { payment_method = "bank_transfer" } @@ -433,6 +432,7 @@ outgoing_webhook_logs_topic = "hyperswitch-outgoing-webhook-events" dispute_analytics_topic = "hyperswitch-dispute-events" audit_events_topic = "hyperswitch-audit-events" payout_analytics_topic = "hyperswitch-payout-events" +consolidated_events_topic = "hyperswitch-consolidated-events" [analytics] source = "sqlx" @@ -454,7 +454,7 @@ connection_timeout = 10 queue_strategy = "Fifo" [kv_config] -ttl = 900 # 15 * 60 seconds +ttl = 900 # 15 * 60 seconds soft_kill = false [frm] diff --git a/crates/router/src/events.rs b/crates/router/src/events.rs index 4bca58248351..e1ecd09804cf 100644 --- a/crates/router/src/events.rs +++ b/crates/router/src/events.rs @@ -30,6 +30,7 @@ pub enum EventType { AuditEvent, #[cfg(feature = "payouts")] Payout, + Consolidated, } #[derive(Debug, Default, Deserialize, Clone)] diff --git a/crates/router/src/services/kafka.rs b/crates/router/src/services/kafka.rs index 6f2aa9fcd100..3523ab9261fd 100644 --- a/crates/router/src/services/kafka.rs +++ b/crates/router/src/services/kafka.rs @@ -12,9 +12,13 @@ use rdkafka::{ pub mod payout; use crate::events::EventType; mod dispute; +mod dispute_event; mod payment_attempt; +mod payment_attempt_event; mod payment_intent; +mod payment_intent_event; mod refund; +mod refund_event; use diesel_models::refund::Refund; use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, PaymentIntent}; use serde::Serialize; @@ -23,8 +27,10 @@ use time::{OffsetDateTime, PrimitiveDateTime}; #[cfg(feature = "payouts")] use self::payout::KafkaPayout; use self::{ - dispute::KafkaDispute, payment_attempt::KafkaPaymentAttempt, - payment_intent::KafkaPaymentIntent, refund::KafkaRefund, + dispute::KafkaDispute, dispute_event::KafkaDisputeEvent, payment_attempt::KafkaPaymentAttempt, + payment_attempt_event::KafkaPaymentAttemptEvent, payment_intent::KafkaPaymentIntent, + payment_intent_event::KafkaPaymentIntentEvent, refund::KafkaRefund, + refund_event::KafkaRefundEvent, }; use crate::types::storage::Dispute; @@ -89,6 +95,42 @@ impl<'a, T: KafkaMessage> KafkaMessage for KafkaEvent<'a, T> { } } +#[derive(serde::Serialize, Debug)] +struct KafkaConsolidatedLog<'a, T: KafkaMessage> { + #[serde(flatten)] + event: &'a T, + tenant_id: TenantID, +} + +#[derive(serde::Serialize, Debug)] +struct KafkaConsolidatedEvent<'a, T: KafkaMessage> { + log: KafkaConsolidatedLog<'a, T>, + log_type: EventType, +} + +impl<'a, T: KafkaMessage> KafkaConsolidatedEvent<'a, T> { + fn new(event: &'a T, tenant_id: TenantID) -> Self { + Self { + log: KafkaConsolidatedLog { event, tenant_id }, + log_type: event.event_type(), + } + } +} + +impl<'a, T: KafkaMessage> KafkaMessage for KafkaConsolidatedEvent<'a, T> { + fn key(&self) -> String { + self.log.event.key() + } + + fn event_type(&self) -> EventType { + EventType::Consolidated + } + + fn creation_timestamp(&self) -> Option { + self.log.event.creation_timestamp() + } +} + #[derive(Debug, serde::Deserialize, Clone, Default)] #[serde(default)] pub struct KafkaSettings { @@ -103,6 +145,7 @@ pub struct KafkaSettings { audit_events_topic: String, #[cfg(feature = "payouts")] payout_analytics_topic: String, + consolidated_events_topic: String, } impl KafkaSettings { @@ -175,6 +218,12 @@ impl KafkaSettings { )) })?; + common_utils::fp_utils::when(self.consolidated_events_topic.is_default_or_empty(), || { + Err(ApplicationError::InvalidConfigurationValueError( + "Consolidated Events topic must not be empty".into(), + )) + })?; + Ok(()) } } @@ -192,6 +241,7 @@ pub struct KafkaProducer { audit_events_topic: String, #[cfg(feature = "payouts")] payout_analytics_topic: String, + consolidated_events_topic: String, } struct RdKafkaProducer(ThreadedProducer); @@ -233,23 +283,13 @@ impl KafkaProducer { audit_events_topic: conf.audit_events_topic.clone(), #[cfg(feature = "payouts")] payout_analytics_topic: conf.payout_analytics_topic.clone(), + consolidated_events_topic: conf.consolidated_events_topic.clone(), }) } pub fn log_event(&self, event: &T) -> MQResult<()> { router_env::logger::debug!("Logging Kafka Event {event:?}"); - let topic = match event.event_type() { - EventType::PaymentIntent => &self.intent_analytics_topic, - EventType::PaymentAttempt => &self.attempt_analytics_topic, - EventType::Refund => &self.refund_analytics_topic, - EventType::ApiLogs => &self.api_logs_topic, - EventType::ConnectorApiLogs => &self.connector_logs_topic, - EventType::OutgoingWebhookLogs => &self.outgoing_webhook_logs_topic, - EventType::Dispute => &self.dispute_analytics_topic, - EventType::AuditEvent => &self.audit_events_topic, - #[cfg(feature = "payouts")] - EventType::Payout => &self.payout_analytics_topic, - }; + let topic = self.get_topic(event.event_type()); self.producer .0 .send( @@ -281,11 +321,18 @@ impl KafkaProducer { format!("Failed to add negative attempt event {negative_event:?}") })?; }; + self.log_event(&KafkaEvent::new( &KafkaPaymentAttempt::from_storage(attempt), tenant_id.clone(), )) - .attach_printable_lazy(|| format!("Failed to add positive attempt event {attempt:?}")) + .attach_printable_lazy(|| format!("Failed to add positive attempt event {attempt:?}"))?; + + self.log_event(&KafkaConsolidatedEvent::new( + &KafkaPaymentAttemptEvent::from_storage(attempt), + tenant_id.clone(), + )) + .attach_printable_lazy(|| format!("Failed to add consolidated attempt event {attempt:?}")) } pub async fn log_payment_attempt_delete( @@ -317,11 +364,18 @@ impl KafkaProducer { format!("Failed to add negative intent event {negative_event:?}") })?; }; + self.log_event(&KafkaEvent::new( &KafkaPaymentIntent::from_storage(intent), tenant_id.clone(), )) - .attach_printable_lazy(|| format!("Failed to add positive intent event {intent:?}")) + .attach_printable_lazy(|| format!("Failed to add positive intent event {intent:?}"))?; + + self.log_event(&KafkaConsolidatedEvent::new( + &KafkaPaymentIntentEvent::from_storage(intent), + tenant_id.clone(), + )) + .attach_printable_lazy(|| format!("Failed to add consolidated intent event {intent:?}")) } pub async fn log_payment_intent_delete( @@ -353,11 +407,18 @@ impl KafkaProducer { format!("Failed to add negative refund event {negative_event:?}") })?; }; + self.log_event(&KafkaEvent::new( &KafkaRefund::from_storage(refund), tenant_id.clone(), )) - .attach_printable_lazy(|| format!("Failed to add positive refund event {refund:?}")) + .attach_printable_lazy(|| format!("Failed to add positive refund event {refund:?}"))?; + + self.log_event(&KafkaConsolidatedEvent::new( + &KafkaRefundEvent::from_storage(refund), + tenant_id.clone(), + )) + .attach_printable_lazy(|| format!("Failed to add consolidated refund event {refund:?}")) } pub async fn log_refund_delete( @@ -389,11 +450,18 @@ impl KafkaProducer { format!("Failed to add negative dispute event {negative_event:?}") })?; }; + self.log_event(&KafkaEvent::new( &KafkaDispute::from_storage(dispute), tenant_id.clone(), )) - .attach_printable_lazy(|| format!("Failed to add positive dispute event {dispute:?}")) + .attach_printable_lazy(|| format!("Failed to add positive dispute event {dispute:?}"))?; + + self.log_event(&KafkaConsolidatedEvent::new( + &KafkaDisputeEvent::from_storage(dispute), + tenant_id.clone(), + )) + .attach_printable_lazy(|| format!("Failed to add consolidated dispute event {dispute:?}")) } #[cfg(feature = "payouts")] @@ -437,6 +505,7 @@ impl KafkaProducer { EventType::AuditEvent => &self.audit_events_topic, #[cfg(feature = "payouts")] EventType::Payout => &self.payout_analytics_topic, + EventType::Consolidated => &self.consolidated_events_topic, } } } diff --git a/crates/router/src/services/kafka/dispute_event.rs b/crates/router/src/services/kafka/dispute_event.rs new file mode 100644 index 000000000000..71e0a11e04d5 --- /dev/null +++ b/crates/router/src/services/kafka/dispute_event.rs @@ -0,0 +1,77 @@ +use diesel_models::enums as storage_enums; +use masking::Secret; +use time::OffsetDateTime; + +use crate::types::storage::dispute::Dispute; + +#[serde_with::skip_serializing_none] +#[derive(serde::Serialize, Debug)] +pub struct KafkaDisputeEvent<'a> { + pub dispute_id: &'a String, + pub dispute_amount: i64, + pub currency: &'a String, + pub dispute_stage: &'a storage_enums::DisputeStage, + pub dispute_status: &'a storage_enums::DisputeStatus, + pub payment_id: &'a String, + pub attempt_id: &'a String, + pub merchant_id: &'a String, + pub connector_status: &'a String, + pub connector_dispute_id: &'a String, + pub connector_reason: Option<&'a String>, + pub connector_reason_code: Option<&'a String>, + #[serde(default, with = "time::serde::timestamp::milliseconds::option")] + pub challenge_required_by: Option, + #[serde(default, with = "time::serde::timestamp::milliseconds::option")] + pub connector_created_at: Option, + #[serde(default, with = "time::serde::timestamp::milliseconds::option")] + pub connector_updated_at: Option, + #[serde(default, with = "time::serde::timestamp::milliseconds")] + pub created_at: OffsetDateTime, + #[serde(default, with = "time::serde::timestamp::milliseconds")] + pub modified_at: OffsetDateTime, + pub connector: &'a String, + pub evidence: &'a Secret, + pub profile_id: Option<&'a String>, + pub merchant_connector_id: Option<&'a String>, +} + +impl<'a> KafkaDisputeEvent<'a> { + pub fn from_storage(dispute: &'a Dispute) -> Self { + Self { + dispute_id: &dispute.dispute_id, + dispute_amount: dispute.amount.parse::().unwrap_or_default(), + currency: &dispute.currency, + dispute_stage: &dispute.dispute_stage, + dispute_status: &dispute.dispute_status, + payment_id: &dispute.payment_id, + attempt_id: &dispute.attempt_id, + merchant_id: &dispute.merchant_id, + connector_status: &dispute.connector_status, + connector_dispute_id: &dispute.connector_dispute_id, + connector_reason: dispute.connector_reason.as_ref(), + connector_reason_code: dispute.connector_reason_code.as_ref(), + challenge_required_by: dispute.challenge_required_by.map(|i| i.assume_utc()), + connector_created_at: dispute.connector_created_at.map(|i| i.assume_utc()), + connector_updated_at: dispute.connector_updated_at.map(|i| i.assume_utc()), + created_at: dispute.created_at.assume_utc(), + modified_at: dispute.modified_at.assume_utc(), + connector: &dispute.connector, + evidence: &dispute.evidence, + profile_id: dispute.profile_id.as_ref(), + merchant_connector_id: dispute.merchant_connector_id.as_ref(), + } + } +} + +impl<'a> super::KafkaMessage for KafkaDisputeEvent<'a> { + fn key(&self) -> String { + format!( + "{}_{}_{}", + self.merchant_id, self.payment_id, self.dispute_id + ) + } + + fn event_type(&self) -> crate::events::EventType { + crate::events::EventType::Dispute + } +} diff --git a/crates/router/src/services/kafka/payment_attempt_event.rs b/crates/router/src/services/kafka/payment_attempt_event.rs new file mode 100644 index 000000000000..bb4d69eda27f --- /dev/null +++ b/crates/router/src/services/kafka/payment_attempt_event.rs @@ -0,0 +1,119 @@ +// use diesel_models::enums::MandateDetails; +use common_utils::types::MinorUnit; +use diesel_models::enums as storage_enums; +use hyperswitch_domain_models::{ + mandates::MandateDetails, payments::payment_attempt::PaymentAttempt, +}; +use time::OffsetDateTime; + +#[serde_with::skip_serializing_none] +#[derive(serde::Serialize, Debug)] +pub struct KafkaPaymentAttemptEvent<'a> { + pub payment_id: &'a String, + pub merchant_id: &'a String, + pub attempt_id: &'a String, + pub status: storage_enums::AttemptStatus, + pub amount: MinorUnit, + pub currency: Option, + pub save_to_locker: Option, + pub connector: Option<&'a String>, + pub error_message: Option<&'a String>, + pub offer_amount: Option, + pub surcharge_amount: Option, + pub tax_amount: Option, + pub payment_method_id: Option<&'a String>, + pub payment_method: Option, + pub connector_transaction_id: Option<&'a String>, + pub capture_method: Option, + #[serde(default, with = "time::serde::timestamp::milliseconds::option")] + pub capture_on: Option, + pub confirm: bool, + pub authentication_type: Option, + #[serde(with = "time::serde::timestamp::milliseconds")] + pub created_at: OffsetDateTime, + #[serde(with = "time::serde::timestamp::milliseconds")] + pub modified_at: OffsetDateTime, + #[serde(default, with = "time::serde::timestamp::milliseconds::option")] + pub last_synced: Option, + pub cancellation_reason: Option<&'a String>, + pub amount_to_capture: Option, + pub mandate_id: Option<&'a String>, + pub browser_info: Option, + pub error_code: Option<&'a String>, + pub connector_metadata: Option, + // TODO: These types should implement copy ideally + pub payment_experience: Option<&'a storage_enums::PaymentExperience>, + pub payment_method_type: Option<&'a storage_enums::PaymentMethodType>, + pub payment_method_data: Option, + pub error_reason: Option<&'a String>, + pub multiple_capture_count: Option, + pub amount_capturable: MinorUnit, + pub merchant_connector_id: Option<&'a String>, + pub net_amount: MinorUnit, + pub unified_code: Option<&'a String>, + pub unified_message: Option<&'a String>, + pub mandate_data: Option<&'a MandateDetails>, + pub client_source: Option<&'a String>, + pub client_version: Option<&'a String>, +} + +impl<'a> KafkaPaymentAttemptEvent<'a> { + pub fn from_storage(attempt: &'a PaymentAttempt) -> Self { + Self { + payment_id: &attempt.payment_id, + merchant_id: &attempt.merchant_id, + attempt_id: &attempt.attempt_id, + status: attempt.status, + amount: attempt.amount, + currency: attempt.currency, + save_to_locker: attempt.save_to_locker, + connector: attempt.connector.as_ref(), + error_message: attempt.error_message.as_ref(), + offer_amount: attempt.offer_amount, + surcharge_amount: attempt.surcharge_amount, + tax_amount: attempt.tax_amount, + payment_method_id: attempt.payment_method_id.as_ref(), + payment_method: attempt.payment_method, + connector_transaction_id: attempt.connector_transaction_id.as_ref(), + capture_method: attempt.capture_method, + capture_on: attempt.capture_on.map(|i| i.assume_utc()), + confirm: attempt.confirm, + authentication_type: attempt.authentication_type, + created_at: attempt.created_at.assume_utc(), + modified_at: attempt.modified_at.assume_utc(), + last_synced: attempt.last_synced.map(|i| i.assume_utc()), + cancellation_reason: attempt.cancellation_reason.as_ref(), + amount_to_capture: attempt.amount_to_capture, + mandate_id: attempt.mandate_id.as_ref(), + browser_info: attempt.browser_info.as_ref().map(|v| v.to_string()), + error_code: attempt.error_code.as_ref(), + connector_metadata: attempt.connector_metadata.as_ref().map(|v| v.to_string()), + payment_experience: attempt.payment_experience.as_ref(), + payment_method_type: attempt.payment_method_type.as_ref(), + payment_method_data: attempt.payment_method_data.as_ref().map(|v| v.to_string()), + error_reason: attempt.error_reason.as_ref(), + multiple_capture_count: attempt.multiple_capture_count, + amount_capturable: attempt.amount_capturable, + merchant_connector_id: attempt.merchant_connector_id.as_ref(), + net_amount: attempt.net_amount, + unified_code: attempt.unified_code.as_ref(), + unified_message: attempt.unified_message.as_ref(), + mandate_data: attempt.mandate_data.as_ref(), + client_source: attempt.client_source.as_ref(), + client_version: attempt.client_version.as_ref(), + } + } +} + +impl<'a> super::KafkaMessage for KafkaPaymentAttemptEvent<'a> { + fn key(&self) -> String { + format!( + "{}_{}_{}", + self.merchant_id, self.payment_id, self.attempt_id + ) + } + + fn event_type(&self) -> crate::events::EventType { + crate::events::EventType::PaymentAttempt + } +} diff --git a/crates/router/src/services/kafka/payment_intent_event.rs b/crates/router/src/services/kafka/payment_intent_event.rs new file mode 100644 index 000000000000..a3fbd9ddc458 --- /dev/null +++ b/crates/router/src/services/kafka/payment_intent_event.rs @@ -0,0 +1,75 @@ +use common_utils::{id_type, types::MinorUnit}; +use diesel_models::enums as storage_enums; +use hyperswitch_domain_models::payments::PaymentIntent; +use time::OffsetDateTime; + +#[serde_with::skip_serializing_none] +#[derive(serde::Serialize, Debug)] +pub struct KafkaPaymentIntentEvent<'a> { + pub payment_id: &'a String, + pub merchant_id: &'a String, + pub status: storage_enums::IntentStatus, + pub amount: MinorUnit, + pub currency: Option, + pub amount_captured: Option, + pub customer_id: Option<&'a id_type::CustomerId>, + pub description: Option<&'a String>, + pub return_url: Option<&'a String>, + pub connector_id: Option<&'a String>, + pub statement_descriptor_name: Option<&'a String>, + pub statement_descriptor_suffix: Option<&'a String>, + #[serde(with = "time::serde::timestamp::milliseconds")] + pub created_at: OffsetDateTime, + #[serde(with = "time::serde::timestamp::milliseconds")] + pub modified_at: OffsetDateTime, + #[serde(default, with = "time::serde::timestamp::milliseconds::option")] + pub last_synced: Option, + pub setup_future_usage: Option, + pub off_session: Option, + pub client_secret: Option<&'a String>, + pub active_attempt_id: String, + pub business_country: Option, + pub business_label: Option<&'a String>, + pub attempt_count: i16, + pub payment_confirm_source: Option, +} + +impl<'a> KafkaPaymentIntentEvent<'a> { + pub fn from_storage(intent: &'a PaymentIntent) -> Self { + Self { + payment_id: &intent.payment_id, + merchant_id: &intent.merchant_id, + status: intent.status, + amount: intent.amount, + currency: intent.currency, + amount_captured: intent.amount_captured, + customer_id: intent.customer_id.as_ref(), + description: intent.description.as_ref(), + return_url: intent.return_url.as_ref(), + connector_id: intent.connector_id.as_ref(), + statement_descriptor_name: intent.statement_descriptor_name.as_ref(), + statement_descriptor_suffix: intent.statement_descriptor_suffix.as_ref(), + created_at: intent.created_at.assume_utc(), + modified_at: intent.modified_at.assume_utc(), + last_synced: intent.last_synced.map(|i| i.assume_utc()), + setup_future_usage: intent.setup_future_usage, + off_session: intent.off_session, + client_secret: intent.client_secret.as_ref(), + active_attempt_id: intent.active_attempt.get_id(), + business_country: intent.business_country, + business_label: intent.business_label.as_ref(), + attempt_count: intent.attempt_count, + payment_confirm_source: intent.payment_confirm_source, + } + } +} + +impl<'a> super::KafkaMessage for KafkaPaymentIntentEvent<'a> { + fn key(&self) -> String { + format!("{}_{}", self.merchant_id, self.payment_id) + } + + fn event_type(&self) -> crate::events::EventType { + crate::events::EventType::PaymentIntent + } +} diff --git a/crates/router/src/services/kafka/refund_event.rs b/crates/router/src/services/kafka/refund_event.rs new file mode 100644 index 000000000000..6aa80b243c11 --- /dev/null +++ b/crates/router/src/services/kafka/refund_event.rs @@ -0,0 +1,74 @@ +use common_utils::types::MinorUnit; +use diesel_models::{enums as storage_enums, refund::Refund}; +use time::OffsetDateTime; + +#[serde_with::skip_serializing_none] +#[derive(serde::Serialize, Debug)] +pub struct KafkaRefundEvent<'a> { + pub internal_reference_id: &'a String, + pub refund_id: &'a String, //merchant_reference id + pub payment_id: &'a String, + pub merchant_id: &'a String, + pub connector_transaction_id: &'a String, + pub connector: &'a String, + pub connector_refund_id: Option<&'a String>, + pub external_reference_id: Option<&'a String>, + pub refund_type: &'a storage_enums::RefundType, + pub total_amount: &'a MinorUnit, + pub currency: &'a storage_enums::Currency, + pub refund_amount: &'a MinorUnit, + pub refund_status: &'a storage_enums::RefundStatus, + pub sent_to_gateway: &'a bool, + pub refund_error_message: Option<&'a String>, + pub refund_arn: Option<&'a String>, + #[serde(default, with = "time::serde::timestamp::milliseconds")] + pub created_at: OffsetDateTime, + #[serde(default, with = "time::serde::timestamp::milliseconds")] + pub modified_at: OffsetDateTime, + pub description: Option<&'a String>, + pub attempt_id: &'a String, + pub refund_reason: Option<&'a String>, + pub refund_error_code: Option<&'a String>, +} + +impl<'a> KafkaRefundEvent<'a> { + pub fn from_storage(refund: &'a Refund) -> Self { + Self { + internal_reference_id: &refund.internal_reference_id, + refund_id: &refund.refund_id, + payment_id: &refund.payment_id, + merchant_id: &refund.merchant_id, + connector_transaction_id: &refund.connector_transaction_id, + connector: &refund.connector, + connector_refund_id: refund.connector_refund_id.as_ref(), + external_reference_id: refund.external_reference_id.as_ref(), + refund_type: &refund.refund_type, + total_amount: &refund.total_amount, + currency: &refund.currency, + refund_amount: &refund.refund_amount, + refund_status: &refund.refund_status, + sent_to_gateway: &refund.sent_to_gateway, + refund_error_message: refund.refund_error_message.as_ref(), + refund_arn: refund.refund_arn.as_ref(), + created_at: refund.created_at.assume_utc(), + modified_at: refund.updated_at.assume_utc(), + description: refund.description.as_ref(), + attempt_id: &refund.attempt_id, + refund_reason: refund.refund_reason.as_ref(), + refund_error_code: refund.refund_error_code.as_ref(), + } + } +} + +impl<'a> super::KafkaMessage for KafkaRefundEvent<'a> { + fn key(&self) -> String { + format!( + "{}_{}_{}_{}", + self.merchant_id, self.payment_id, self.attempt_id, self.refund_id + ) + } + + fn event_type(&self) -> crate::events::EventType { + crate::events::EventType::Refund + } +} From 67f017f6f035b102ce7a0102b157a884ce9d4109 Mon Sep 17 00:00:00 2001 From: Sai Harsha Vardhan <56996463+sai-harsha-vardhan@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:04:12 +0530 Subject: [PATCH 05/10] feat(router): send `three_ds_requestor_url` in authentication_response for external 3ds flow (#4828) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- crates/api_models/src/payments.rs | 2 ++ crates/router/src/core/authentication.rs | 6 ++++-- .../src/core/authentication/transformers.rs | 18 ++++-------------- crates/router/src/core/payments.rs | 18 +++++++++++++++++- openapi/openapi_spec.json | 7 ++++++- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index f4e49058c9b2..cda13289aa52 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4595,6 +4595,8 @@ pub struct PaymentsExternalAuthenticationResponse { pub three_dsserver_trans_id: Option, /// Contains the JWS object created by the ACS for the ARes message pub acs_signed_content: Option, + /// Three DS Requestor URL + pub three_ds_requestor_url: String, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] diff --git a/crates/router/src/core/authentication.rs b/crates/router/src/core/authentication.rs index 5acd14bb3ee2..7828473df607 100644 --- a/crates/router/src/core/authentication.rs +++ b/crates/router/src/core/authentication.rs @@ -20,13 +20,13 @@ use crate::{ #[allow(clippy::too_many_arguments)] pub async fn perform_authentication( state: &AppState, + merchant_id: String, authentication_connector: String, payment_method_data: payments::PaymentMethodData, payment_method: common_enums::PaymentMethod, billing_address: payments::Address, shipping_address: Option, browser_details: Option, - business_profile: storage::BusinessProfile, merchant_connector_account: payments_core::helpers::MerchantConnectorAccountType, amount: Option, currency: Option, @@ -38,8 +38,10 @@ pub async fn perform_authentication( threeds_method_comp_ind: payments::ThreeDsCompletionIndicator, email: Option, webhook_url: String, + three_ds_requestor_url: String, ) -> CustomResult { let router_data = transformers::construct_authentication_router_data( + merchant_id, authentication_connector.clone(), payment_method_data, payment_method, @@ -50,7 +52,6 @@ pub async fn perform_authentication( currency, message_category, device_channel, - business_profile, merchant_connector_account, authentication_data.clone(), return_url, @@ -58,6 +59,7 @@ pub async fn perform_authentication( threeds_method_comp_ind, email, webhook_url, + three_ds_requestor_url, )?; let response = utils::do_auth_connector_call(state, authentication_connector.clone(), router_data).await?; diff --git a/crates/router/src/core/authentication/transformers.rs b/crates/router/src/core/authentication/transformers.rs index e0e9ee0b5263..2255e1ff5820 100644 --- a/crates/router/src/core/authentication/transformers.rs +++ b/crates/router/src/core/authentication/transformers.rs @@ -26,6 +26,7 @@ const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_AUTHENTICATION_FLOW: &str = #[allow(clippy::too_many_arguments)] pub fn construct_authentication_router_data( + merchant_id: String, authentication_connector: String, payment_method_data: payments::PaymentMethodData, payment_method: PaymentMethod, @@ -36,7 +37,6 @@ pub fn construct_authentication_router_data( currency: Option, message_category: types::api::authentication::MessageCategory, device_channel: payments::DeviceChannel, - business_profile: storage::BusinessProfile, merchant_connector_account: payments_helpers::MerchantConnectorAccountType, authentication_data: storage::Authentication, return_url: Option, @@ -44,18 +44,8 @@ pub fn construct_authentication_router_data( threeds_method_comp_ind: payments::ThreeDsCompletionIndicator, email: Option, webhook_url: String, + three_ds_requestor_url: String, ) -> RouterResult { - let authentication_details: api_models::admin::AuthenticationConnectorDetails = - business_profile - .authentication_connector_details - .clone() - .get_required_value("authentication_details") - .attach_printable("authentication_details not configured by the merchant")? - .parse_value("AuthenticationDetails") - .change_context(errors::ApiErrorResponse::UnprocessableEntity { - message: "Invalid data format found for authentication_details".into(), - }) - .attach_printable("Error while parsing authentication_details from merchant_account")?; let router_request = types::authentication::ConnectorAuthenticationRequestData { payment_method_data: From::from(payment_method_data), billing_address, @@ -71,14 +61,14 @@ pub fn construct_authentication_router_data( return_url, sdk_information, email, - three_ds_requestor_url: authentication_details.three_ds_requestor_url, + three_ds_requestor_url, threeds_method_comp_ind, webhook_url, }; construct_router_data( authentication_connector, payment_method, - business_profile.merchant_id.clone(), + merchant_id.clone(), types::PaymentAddress::default(), router_request, &merchant_connector_account, diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 7bc0b532239e..a5f9c2a5e462 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -3918,8 +3918,23 @@ pub async fn payment_external_authentication( id: profile_id.to_string(), })?; + let authentication_details: api_models::admin::AuthenticationConnectorDetails = + business_profile + .authentication_connector_details + .clone() + .get_required_value("authentication_connector_details") + .attach_printable("authentication_connector_details not configured by the merchant")? + .parse_value("AuthenticationConnectorDetails") + .change_context(errors::ApiErrorResponse::UnprocessableEntity { + message: "Invalid data format found for authentication_connector_details".into(), + }) + .attach_printable( + "Error while parsing authentication_connector_details from business_profile", + )?; + let authentication_response = Box::pin(authentication_core::perform_authentication( &state, + business_profile.merchant_id, authentication_connector, payment_method_details.0, payment_method_details.1, @@ -3931,7 +3946,6 @@ pub async fn payment_external_authentication( })?, shipping_address.as_ref().map(|address| address.into()), browser_info, - business_profile, merchant_connector_account, Some(amount), Some(currency), @@ -3943,6 +3957,7 @@ pub async fn payment_external_authentication( req.threeds_method_comp_ind, optional_customer.and_then(|customer| customer.email.map(pii::Email::from)), webhook_url, + authentication_details.three_ds_requestor_url.clone(), )) .await?; Ok(services::ApplicationResponse::Json( @@ -3957,6 +3972,7 @@ pub async fn payment_external_authentication( acs_trans_id: authentication_response.acs_trans_id, three_dsserver_trans_id: authentication_response.three_dsserver_trans_id, acs_signed_content: authentication_response.acs_signed_content, + three_ds_requestor_url: authentication_details.three_ds_requestor_url, }, )) } diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index fe3c934f4ab1..f42481798a49 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -14594,7 +14594,8 @@ "PaymentsExternalAuthenticationResponse": { "type": "object", "required": [ - "trans_status" + "trans_status", + "three_ds_requestor_url" ], "properties": { "trans_status": { @@ -14629,6 +14630,10 @@ "type": "string", "description": "Contains the JWS object created by the ACS for the ARes message", "nullable": true + }, + "three_ds_requestor_url": { + "type": "string", + "description": "Three DS Requestor URL" } } }, From e5da133fe00b5736dc3c55bf4ee86fa77158dbe7 Mon Sep 17 00:00:00 2001 From: Hrithikesh <61539176+hrithikesh026@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:21:49 +0530 Subject: [PATCH 06/10] refactor(connector): airwallex convert init payment to preprocessing (#4842) --- crates/api_models/src/enums.rs | 3 + crates/router/src/connector/airwallex.rs | 60 +-- .../src/connector/airwallex/transformers.rs | 21 +- crates/router/src/core/payments.rs | 8 + crates/router/src/core/payments/flows.rs | 1 - .../src/core/payments/flows/authorize_flow.rs | 7 +- .../.meta.json | 7 + .../Payments - Capture/.event.meta.json | 3 + .../Payments - Capture/event.test.js | 94 +++++ .../Payments - Capture/request.json | 39 ++ .../Payments - Capture/response.json | 1 + .../Payments - Create/.event.meta.json | 3 + .../Payments - Create/event.test.js | 71 ++++ .../Payments - Create/request.json | 84 ++++ .../Payments - Create/response.json | 1 + .../Payments - Retrieve/.event.meta.json | 3 + .../Payments - Retrieve/event.test.js | 71 ++++ .../Payments - Retrieve/request.json | 28 ++ .../Payments - Retrieve/response.json | 1 + .../Payments - Capture/event.test.js | 2 +- .../Payments - Capture/request.json | 2 +- .../airwallex.postman_collection.json | 396 +++++++++++++++++- 22 files changed, 851 insertions(+), 55 deletions(-) create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/.meta.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/.event.meta.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/event.test.js create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/request.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/response.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/.event.meta.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/event.test.js create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/request.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/response.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/.event.meta.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/event.test.js create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/request.json create mode 100644 postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/response.json diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index 19ce82e59bb4..81e50b020e73 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -249,6 +249,9 @@ impl Connector { Self::Checkout | Self::Nmi| Self::Cybersource => true, } } + pub fn is_pre_processing_required_before_authorize(&self) -> bool { + matches!(self, Self::Airwallex) + } } #[derive( diff --git a/crates/router/src/connector/airwallex.rs b/crates/router/src/connector/airwallex.rs index ca511534b974..fbc25909489c 100644 --- a/crates/router/src/connector/airwallex.rs +++ b/crates/router/src/connector/airwallex.rs @@ -18,7 +18,7 @@ use crate::{ payments, }, events::connector_api_logs::ConnectorEvent, - headers, logger, routes, + headers, logger, services::{ self, request::{self, Mask}, @@ -27,7 +27,6 @@ use crate::{ types::{ self, api::{self, ConnectorCommon, ConnectorCommonExt}, - transformers::ForeignFrom, ErrorResponse, Response, RouterData, }, utils::{crypto, BytesExt}, @@ -123,6 +122,7 @@ impl ConnectorValidation for Airwallex { } impl api::Payment for Airwallex {} +impl api::PaymentsPreProcessing for Airwallex {} impl api::PaymentsCompleteAuthorize for Airwallex {} impl api::MandateSetup for Airwallex {} impl @@ -242,14 +242,14 @@ impl ConnectorIntegration for Airwallex { fn get_headers( &self, - req: &types::PaymentsInitRouterData, + req: &types::PaymentsPreProcessingRouterData, connectors: &settings::Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -261,7 +261,7 @@ impl fn get_url( &self, - _req: &types::PaymentsInitRouterData, + _req: &types::PaymentsPreProcessingRouterData, connectors: &settings::Connectors, ) -> CustomResult { Ok(format!( @@ -273,7 +273,7 @@ impl fn get_request_body( &self, - req: &types::PaymentsInitRouterData, + req: &types::PaymentsPreProcessingRouterData, _connectors: &settings::Connectors, ) -> CustomResult { let req_obj = airwallex::AirwallexIntentRequest::try_from(req)?; @@ -282,16 +282,20 @@ impl fn build_request( &self, - req: &types::PaymentsInitRouterData, + req: &types::PaymentsPreProcessingRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Post) - .url(&types::PaymentsInitType::get_url(self, req, connectors)?) + .url(&types::PaymentsPreProcessingType::get_url( + self, req, connectors, + )?) .attach_default_headers() - .headers(types::PaymentsInitType::get_headers(self, req, connectors)?) - .set_body(types::PaymentsInitType::get_request_body( + .headers(types::PaymentsPreProcessingType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsPreProcessingType::get_request_body( self, req, connectors, )?) .build(), @@ -300,10 +304,10 @@ impl fn handle_response( &self, - data: &types::PaymentsInitRouterData, + data: &types::PaymentsPreProcessingRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { + ) -> CustomResult { let response: airwallex::AirwallexPaymentsResponse = res .response .parse_struct("airwallex AirwallexPaymentsResponse") @@ -335,36 +339,6 @@ impl api::PaymentAuthorize for Airwallex {} impl ConnectorIntegration for Airwallex { - async fn execute_pretasks( - &self, - router_data: &mut types::PaymentsAuthorizeRouterData, - app_state: &routes::AppState, - ) -> CustomResult<(), errors::ConnectorError> { - let integ: Box< - &(dyn ConnectorIntegration< - api::InitPayment, - types::PaymentsAuthorizeData, - types::PaymentsResponseData, - > + Send - + Sync - + 'static), - > = Box::new(&Self); - let authorize_data = &types::PaymentsInitRouterData::foreign_from(( - &router_data.to_owned(), - router_data.request.clone(), - )); - let resp = services::execute_connector_processing_step( - app_state, - integ, - authorize_data, - payments::CallConnectorAction::Trigger, - None, - ) - .await?; - router_data.reference_id = resp.reference_id; - Ok(()) - } - fn get_headers( &self, req: &types::PaymentsAuthorizeRouterData, diff --git a/crates/router/src/connector/airwallex/transformers.rs b/crates/router/src/connector/airwallex/transformers.rs index 587a14caedfd..56a6ebe2e448 100644 --- a/crates/router/src/connector/airwallex/transformers.rs +++ b/crates/router/src/connector/airwallex/transformers.rs @@ -41,13 +41,26 @@ pub struct AirwallexIntentRequest { //ID created in merchant's order system that corresponds to this PaymentIntent. merchant_order_id: String, } -impl TryFrom<&types::PaymentsInitRouterData> for AirwallexIntentRequest { +impl TryFrom<&types::PaymentsPreProcessingRouterData> for AirwallexIntentRequest { type Error = error_stack::Report; - fn try_from(item: &types::PaymentsInitRouterData) -> Result { + fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result { + // amount and currency will always be Some since PaymentsPreProcessingData is constructed using PaymentsAuthorizeData + let amount = item + .request + .amount + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "amount", + })?; + let currency = + item.request + .currency + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "currency", + })?; Ok(Self { request_id: Uuid::new_v4().to_string(), - amount: utils::to_currency_base_unit(item.request.amount, item.request.currency)?, - currency: item.request.currency, + amount: utils::to_currency_base_unit(amount, currency)?, + currency, merchant_order_id: item.connector_request_reference_id.clone(), }) } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index a5f9c2a5e462..3988f3d4fd0d 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -1885,6 +1885,14 @@ where dyn api::Connector: services::api::ConnectorIntegration, { + if !is_operation_complete_authorize(&operation) + && connector + .connector_name + .is_pre_processing_required_before_authorize() + { + router_data = router_data.preprocessing_steps(state, connector).await?; + return Ok((router_data, should_continue_payment)); + } //TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check let router_data_and_should_continue_payment = match payment_data.payment_method_data.clone() { Some(api_models::payments::PaymentMethodData::BankTransfer(data)) => match data.deref() { diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index bf924c25982f..158e28e69678 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -928,7 +928,6 @@ impl default_imp_for_pre_processing_steps!( connector::Aci, - connector::Airwallex, connector::Authorizedotnet, connector::Bambora, connector::Billwerk, diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 931ea26a9f8e..5990b29f372a 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -322,13 +322,14 @@ pub async fn authorize_preprocessing_steps( ), ], ); - - let authorize_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>( + let mut authorize_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>( resp.clone(), router_data.request.to_owned(), resp.response, ); - + if connector.connector_name == api_models::enums::Connector::Airwallex { + authorize_router_data.reference_id = resp.reference_id; + } Ok(authorize_router_data) } else { Ok(router_data.clone()) diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/.meta.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/.meta.json new file mode 100644 index 000000000000..e4ef30e39e8d --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/.meta.json @@ -0,0 +1,7 @@ +{ + "childrenOrder": [ + "Payments - Create", + "Payments - Capture", + "Payments - Retrieve" + ] +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/.event.meta.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/.event.meta.json new file mode 100644 index 000000000000..0731450e6b25 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/.event.meta.json @@ -0,0 +1,3 @@ +{ + "eventOrder": ["event.test.js"] +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/event.test.js b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/event.test.js new file mode 100644 index 000000000000..f560d84ea730 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/event.test.js @@ -0,0 +1,94 @@ +// Validate status 2xx +pm.test("[POST]::/payments/:id/capture - Status code is 2xx", function () { + pm.response.to.be.success; +}); + +// Validate if response header has matching content-type +pm.test( + "[POST]::/payments/:id/capture - Content-Type is application/json", + function () { + pm.expect(pm.response.headers.get("Content-Type")).to.include( + "application/json", + ); + }, +); + +// Validate if response has JSON Body +pm.test("[POST]::/payments/:id/capture - Response has JSON Body", function () { + pm.response.to.have.jsonBody(); +}); + +// Set response object as internal variable +let jsonData = {}; +try { + jsonData = pm.response.json(); +} catch (e) {} + +// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id +if (jsonData?.payment_id) { + pm.collectionVariables.set("payment_id", jsonData.payment_id); + console.log( + "- use {{payment_id}} as collection variable for value", + jsonData.payment_id, + ); +} else { + console.log( + "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.", + ); +} + +// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id +if (jsonData?.mandate_id) { + pm.collectionVariables.set("mandate_id", jsonData.mandate_id); + console.log( + "- use {{mandate_id}} as collection variable for value", + jsonData.mandate_id, + ); +} else { + console.log( + "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.", + ); +} + +// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret +if (jsonData?.client_secret) { + pm.collectionVariables.set("client_secret", jsonData.client_secret); + console.log( + "- use {{client_secret}} as collection variable for value", + jsonData.client_secret, + ); +} else { + console.log( + "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.", + ); +} + +// Response body should have value "succeeded" for "status" +if (jsonData?.status) { + pm.test( + "[POST]:://payments/:id/capture - Content check if value for 'status' matches 'partially_captured'", + function () { + pm.expect(jsonData.status).to.eql("partially_captured"); + }, + ); +} + +// Response body should have value "6540" for "amount" +if (jsonData?.amount) { + pm.test( + "[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'", + function () { + pm.expect(jsonData.amount).to.eql(6540); + }, + ); +} + +// Response body should have value "6000" for "amount_received" +if (jsonData?.amount_received) { + pm.test( + "[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'", + function () { + pm.expect(jsonData.amount_received).to.eql(6000); + }, + ); +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/request.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/request.json new file mode 100644 index 000000000000..9fe257ed85e6 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/request.json @@ -0,0 +1,39 @@ +{ + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "options": { + "raw": { + "language": "json" + } + }, + "raw_json_formatted": { + "amount_to_capture": 6000, + "statement_descriptor_name": "Joseph", + "statement_descriptor_suffix": "JS" + } + }, + "url": { + "raw": "{{baseUrl}}/payments/:id/capture", + "host": ["{{baseUrl}}"], + "path": ["payments", ":id", "capture"], + "variable": [ + { + "key": "id", + "value": "{{payment_id}}", + "description": "(Required) unique payment id" + } + ] + }, + "description": "To capture the funds for an uncaptured payment" +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/response.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/response.json new file mode 100644 index 000000000000..fe51488c7066 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Capture/response.json @@ -0,0 +1 @@ +[] diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/.event.meta.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/.event.meta.json new file mode 100644 index 000000000000..0731450e6b25 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/.event.meta.json @@ -0,0 +1,3 @@ +{ + "eventOrder": ["event.test.js"] +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/event.test.js b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/event.test.js new file mode 100644 index 000000000000..d683186aa007 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/event.test.js @@ -0,0 +1,71 @@ +// Validate status 2xx +pm.test("[POST]::/payments - Status code is 2xx", function () { + pm.response.to.be.success; +}); + +// Validate if response header has matching content-type +pm.test("[POST]::/payments - Content-Type is application/json", function () { + pm.expect(pm.response.headers.get("Content-Type")).to.include( + "application/json", + ); +}); + +// Validate if response has JSON Body +pm.test("[POST]::/payments - Response has JSON Body", function () { + pm.response.to.have.jsonBody(); +}); + +// Set response object as internal variable +let jsonData = {}; +try { + jsonData = pm.response.json(); +} catch (e) {} + +// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id +if (jsonData?.payment_id) { + pm.collectionVariables.set("payment_id", jsonData.payment_id); + console.log( + "- use {{payment_id}} as collection variable for value", + jsonData.payment_id, + ); +} else { + console.log( + "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.", + ); +} + +// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id +if (jsonData?.mandate_id) { + pm.collectionVariables.set("mandate_id", jsonData.mandate_id); + console.log( + "- use {{mandate_id}} as collection variable for value", + jsonData.mandate_id, + ); +} else { + console.log( + "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.", + ); +} + +// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret +if (jsonData?.client_secret) { + pm.collectionVariables.set("client_secret", jsonData.client_secret); + console.log( + "- use {{client_secret}} as collection variable for value", + jsonData.client_secret, + ); +} else { + console.log( + "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.", + ); +} + +// Response body should have value "requires_capture" for "status" +if (jsonData?.status) { + pm.test( + "[POST]::/payments - Content check if value for 'status' matches 'requires_capture'", + function () { + pm.expect(jsonData.status).to.eql("requires_capture"); + }, + ); +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/request.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/request.json new file mode 100644 index 000000000000..0cc6a0477a98 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/request.json @@ -0,0 +1,84 @@ +{ + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "options": { + "raw": { + "language": "json" + } + }, + "raw_json_formatted": { + "amount": 6540, + "currency": "USD", + "confirm": true, + "capture_method": "manual", + "capture_on": "2022-09-10T10:11:12Z", + "amount_to_capture": 6540, + "customer_id": "AirwallexCustomer", + "email": "guest@example.com", + "name": "John Doe", + "phone": "999999999", + "phone_country_code": "+65", + "description": "Its my first payment request", + "authentication_type": "no_three_ds", + "return_url": "https://duck.com", + "payment_method": "card", + "payment_method_data": { + "card": { + "card_number": "4035501000000008", + "card_exp_month": "10", + "card_exp_year": "2025", + "card_holder_name": "joseph Doe", + "card_cvc": "123" + } + }, + "billing": { + "address": { + "line1": "1467", + "line2": "Harrison Street", + "line3": "Harrison Street", + "city": "San Fransico", + "state": "California", + "zip": "94122", + "country": "US", + "first_name": "PiX" + } + }, + "shipping": { + "address": { + "line1": "1467", + "line2": "Harrison Street", + "line3": "Harrison Street", + "city": "San Fransico", + "state": "California", + "zip": "94122", + "country": "US", + "first_name": "PiX" + } + }, + "statement_descriptor_name": "joseph", + "statement_descriptor_suffix": "JS", + "metadata": { + "udf1": "value1", + "new_customer": "true", + "login_date": "2019-09-10T10:11:12Z" + } + } + }, + "url": { + "raw": "{{baseUrl}}/payments", + "host": ["{{baseUrl}}"], + "path": ["payments"] + }, + "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture" +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/response.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/response.json new file mode 100644 index 000000000000..fe51488c7066 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Create/response.json @@ -0,0 +1 @@ +[] diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/.event.meta.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/.event.meta.json new file mode 100644 index 000000000000..0731450e6b25 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/.event.meta.json @@ -0,0 +1,3 @@ +{ + "eventOrder": ["event.test.js"] +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/event.test.js b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/event.test.js new file mode 100644 index 000000000000..ca68dd7045be --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/event.test.js @@ -0,0 +1,71 @@ +// Validate status 2xx +pm.test("[GET]::/payments/:id - Status code is 2xx", function () { + pm.response.to.be.success; +}); + +// Validate if response header has matching content-type +pm.test("[GET]::/payments/:id - Content-Type is application/json", function () { + pm.expect(pm.response.headers.get("Content-Type")).to.include( + "application/json", + ); +}); + +// Validate if response has JSON Body +pm.test("[GET]::/payments/:id - Response has JSON Body", function () { + pm.response.to.have.jsonBody(); +}); + +// Set response object as internal variable +let jsonData = {}; +try { + jsonData = pm.response.json(); +} catch (e) {} + +// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id +if (jsonData?.payment_id) { + pm.collectionVariables.set("payment_id", jsonData.payment_id); + console.log( + "- use {{payment_id}} as collection variable for value", + jsonData.payment_id, + ); +} else { + console.log( + "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.", + ); +} + +// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id +if (jsonData?.mandate_id) { + pm.collectionVariables.set("mandate_id", jsonData.mandate_id); + console.log( + "- use {{mandate_id}} as collection variable for value", + jsonData.mandate_id, + ); +} else { + console.log( + "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.", + ); +} + +// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret +if (jsonData?.client_secret) { + pm.collectionVariables.set("client_secret", jsonData.client_secret); + console.log( + "- use {{client_secret}} as collection variable for value", + jsonData.client_secret, + ); +} else { + console.log( + "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.", + ); +} + +// Response body should have value "succeeded" for "status" +if (jsonData?.status) { + pm.test( + "[POST]::/payments - Content check if value for 'status' matches 'partially_captured'", + function () { + pm.expect(jsonData.status).to.eql("partially_captured"); + }, + ); +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/request.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/request.json new file mode 100644 index 000000000000..6cd4b7d96c52 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/request.json @@ -0,0 +1,28 @@ +{ + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "url": { + "raw": "{{baseUrl}}/payments/:id?force_sync=true", + "host": ["{{baseUrl}}"], + "path": ["payments", ":id"], + "query": [ + { + "key": "force_sync", + "value": "true" + } + ], + "variable": [ + { + "key": "id", + "value": "{{payment_id}}", + "description": "(Required) unique payment id" + } + ] + }, + "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment" +} diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/response.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/response.json new file mode 100644 index 000000000000..fe51488c7066 --- /dev/null +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario11-Create payment with Manual Partial capture/Payments - Retrieve/response.json @@ -0,0 +1 @@ +[] diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/event.test.js b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/event.test.js index 2d7dbc507fb0..2681a4daa9e9 100644 --- a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/event.test.js +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/event.test.js @@ -88,7 +88,7 @@ if (jsonData?.amount_received) { pm.test( "[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'", function () { - pm.expect(jsonData.amount_received).to.eql(6000); + pm.expect(jsonData.amount_received).to.eql(6540); }, ); } diff --git a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/request.json b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/request.json index 9fe257ed85e6..cceb2b55f0a7 100644 --- a/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/request.json +++ b/postman/collection-dir/airwallex/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Capture/request.json @@ -18,7 +18,7 @@ } }, "raw_json_formatted": { - "amount_to_capture": 6000, + "amount_to_capture": 6540, "statement_descriptor_name": "Joseph", "statement_descriptor_suffix": "JS" } diff --git a/postman/collection-json/airwallex.postman_collection.json b/postman/collection-json/airwallex.postman_collection.json index 3e6b467f9bd4..ce92a22c8bb1 100644 --- a/postman/collection-json/airwallex.postman_collection.json +++ b/postman/collection-json/airwallex.postman_collection.json @@ -806,6 +806,398 @@ { "name": "Happy Cases", "item": [ + { + "name": "Scenario11-Create payment with Manual Partial capture", + "item": [ + { + "name": "Payments - Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Validate status 2xx", + "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {", + " pm.response.to.be.success;", + "});", + "", + "// Validate if response header has matching content-type", + "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(", + " \"application/json\",", + " );", + "});", + "", + "// Validate if response has JSON Body", + "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {", + " pm.response.to.have.jsonBody();", + "});", + "", + "// Set response object as internal variable", + "let jsonData = {};", + "try {", + " jsonData = pm.response.json();", + "} catch (e) {}", + "", + "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id", + "if (jsonData?.payment_id) {", + " pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);", + " console.log(", + " \"- use {{payment_id}} as collection variable for value\",", + " jsonData.payment_id,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",", + " );", + "}", + "", + "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id", + "if (jsonData?.mandate_id) {", + " pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);", + " console.log(", + " \"- use {{mandate_id}} as collection variable for value\",", + " jsonData.mandate_id,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",", + " );", + "}", + "", + "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret", + "if (jsonData?.client_secret) {", + " pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);", + " console.log(", + " \"- use {{client_secret}} as collection variable for value\",", + " jsonData.client_secret,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",", + " );", + "}", + "", + "// Response body should have value \"requires_capture\" for \"status\"", + "if (jsonData?.status) {", + " pm.test(", + " \"[POST]::/payments - Content check if value for 'status' matches 'requires_capture'\",", + " function () {", + " pm.expect(jsonData.status).to.eql(\"requires_capture\");", + " },", + " );", + "}", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "options": { + "raw": { + "language": "json" + } + }, + "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"AirwallexCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4035501000000008\",\"card_exp_month\":\"10\",\"card_exp_year\":\"2025\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}" + }, + "url": { + "raw": "{{baseUrl}}/payments", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "payments" + ] + }, + "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture" + }, + "response": [] + }, + { + "name": "Payments - Capture", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Validate status 2xx", + "pm.test(\"[POST]::/payments/:id/capture - Status code is 2xx\", function () {", + " pm.response.to.be.success;", + "});", + "", + "// Validate if response header has matching content-type", + "pm.test(", + " \"[POST]::/payments/:id/capture - Content-Type is application/json\",", + " function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(", + " \"application/json\",", + " );", + " },", + ");", + "", + "// Validate if response has JSON Body", + "pm.test(\"[POST]::/payments/:id/capture - Response has JSON Body\", function () {", + " pm.response.to.have.jsonBody();", + "});", + "", + "// Set response object as internal variable", + "let jsonData = {};", + "try {", + " jsonData = pm.response.json();", + "} catch (e) {}", + "", + "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id", + "if (jsonData?.payment_id) {", + " pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);", + " console.log(", + " \"- use {{payment_id}} as collection variable for value\",", + " jsonData.payment_id,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",", + " );", + "}", + "", + "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id", + "if (jsonData?.mandate_id) {", + " pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);", + " console.log(", + " \"- use {{mandate_id}} as collection variable for value\",", + " jsonData.mandate_id,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",", + " );", + "}", + "", + "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret", + "if (jsonData?.client_secret) {", + " pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);", + " console.log(", + " \"- use {{client_secret}} as collection variable for value\",", + " jsonData.client_secret,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",", + " );", + "}", + "", + "// Response body should have value \"succeeded\" for \"status\"", + "if (jsonData?.status) {", + " pm.test(", + " \"[POST]:://payments/:id/capture - Content check if value for 'status' matches 'partially_captured'\",", + " function () {", + " pm.expect(jsonData.status).to.eql(\"partially_captured\");", + " },", + " );", + "}", + "", + "// Response body should have value \"6540\" for \"amount\"", + "if (jsonData?.amount) {", + " pm.test(", + " \"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'\",", + " function () {", + " pm.expect(jsonData.amount).to.eql(6540);", + " },", + " );", + "}", + "", + "// Response body should have value \"6000\" for \"amount_received\"", + "if (jsonData?.amount_received) {", + " pm.test(", + " \"[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'\",", + " function () {", + " pm.expect(jsonData.amount_received).to.eql(6000);", + " },", + " );", + "}", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "options": { + "raw": { + "language": "json" + } + }, + "raw": "{\"amount_to_capture\":6000,\"statement_descriptor_name\":\"Joseph\",\"statement_descriptor_suffix\":\"JS\"}" + }, + "url": { + "raw": "{{baseUrl}}/payments/:id/capture", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "payments", + ":id", + "capture" + ], + "variable": [ + { + "key": "id", + "value": "{{payment_id}}", + "description": "(Required) unique payment id" + } + ] + }, + "description": "To capture the funds for an uncaptured payment" + }, + "response": [] + }, + { + "name": "Payments - Retrieve", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Validate status 2xx", + "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {", + " pm.response.to.be.success;", + "});", + "", + "// Validate if response header has matching content-type", + "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {", + " pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(", + " \"application/json\",", + " );", + "});", + "", + "// Validate if response has JSON Body", + "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {", + " pm.response.to.have.jsonBody();", + "});", + "", + "// Set response object as internal variable", + "let jsonData = {};", + "try {", + " jsonData = pm.response.json();", + "} catch (e) {}", + "", + "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id", + "if (jsonData?.payment_id) {", + " pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);", + " console.log(", + " \"- use {{payment_id}} as collection variable for value\",", + " jsonData.payment_id,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",", + " );", + "}", + "", + "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id", + "if (jsonData?.mandate_id) {", + " pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);", + " console.log(", + " \"- use {{mandate_id}} as collection variable for value\",", + " jsonData.mandate_id,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",", + " );", + "}", + "", + "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret", + "if (jsonData?.client_secret) {", + " pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);", + " console.log(", + " \"- use {{client_secret}} as collection variable for value\",", + " jsonData.client_secret,", + " );", + "} else {", + " console.log(", + " \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",", + " );", + "}", + "", + "// Response body should have value \"succeeded\" for \"status\"", + "if (jsonData?.status) {", + " pm.test(", + " \"[POST]::/payments - Content check if value for 'status' matches 'partially_captured'\",", + " function () {", + " pm.expect(jsonData.status).to.eql(\"partially_captured\");", + " },", + " );", + "}", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "url": { + "raw": "{{baseUrl}}/payments/:id?force_sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "payments", + ":id" + ], + "query": [ + { + "key": "force_sync", + "value": "true" + } + ], + "variable": [ + { + "key": "id", + "value": "{{payment_id}}", + "description": "(Required) unique payment id" + } + ] + }, + "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment" + }, + "response": [] + } + ] + }, { "name": "Scenario1-Create payment with confirm true", "item": [ @@ -2050,7 +2442,7 @@ " pm.test(", " \"[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'\",", " function () {", - " pm.expect(jsonData.amount_received).to.eql(6000);", + " pm.expect(jsonData.amount_received).to.eql(6540);", " },", " );", "}", @@ -2079,7 +2471,7 @@ "language": "json" } }, - "raw": "{\"amount_to_capture\":6000,\"statement_descriptor_name\":\"Joseph\",\"statement_descriptor_suffix\":\"JS\"}" + "raw": "{\"amount_to_capture\":6540,\"statement_descriptor_name\":\"Joseph\",\"statement_descriptor_suffix\":\"JS\"}" }, "url": { "raw": "{{baseUrl}}/payments/:id/capture", From a1788b8da942f0e32a80b37eac4eecece2bef77d Mon Sep 17 00:00:00 2001 From: DEEPANSHU BANSAL <41580413+deepanshu-iiitu@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:37:37 +0530 Subject: [PATCH 07/10] feat(connector): [AUTHORIZEDOTNET] Support payment_method_id in recurring mandate payment (#4841) --- .../connector/authorizedotnet/transformers.rs | 106 +++++++++--------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs index b281d0a0a773..15aedad7599d 100644 --- a/crates/router/src/connector/authorizedotnet/transformers.rs +++ b/crates/router/src/connector/authorizedotnet/transformers.rs @@ -1,16 +1,15 @@ use common_utils::{ errors::CustomResult, ext_traits::{Encode, ValueExt}, - id_type, pii, }; use error_stack::ResultExt; use masking::{ExposeInterface, PeekInterface, Secret, StrongSecret}; +use rand::distributions::{Alphanumeric, DistString}; use serde::{Deserialize, Serialize}; use crate::{ connector::utils::{ - self, missing_field_err, CardData, PaymentsSyncRequestData, RefundsRequestData, RouterData, - WalletData, + self, CardData, PaymentsSyncRequestData, RefundsRequestData, RouterData, WalletData, }, core::errors, services, @@ -179,7 +178,7 @@ struct PaymentProfileDetails { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct CustomerDetails { - id: id_type::CustomerId, + id: String, } #[derive(Debug, Serialize)] @@ -273,10 +272,7 @@ pub struct AuthorizedotnetZeroMandateRequest { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct Profile { - merchant_customer_id: id_type::CustomerId, - #[serde(skip_serializing_if = "Option::is_none")] - description: Option, - email: Option, + description: String, payment_profiles: PaymentProfiles, } @@ -318,12 +314,8 @@ impl TryFrom<&types::SetupMandateRouterData> for CreateCustomerProfileRequest { create_customer_profile_request: AuthorizedotnetZeroMandateRequest { merchant_authentication, profile: Profile { - merchant_customer_id: item - .customer_id - .clone() - .ok_or_else(missing_field_err("customer_id"))?, - description: item.description.clone(), - email: item.request.email.clone(), + //The payment ID is included in the description because the connector requires unique description when creating a mandate. + description: item.payment_id.clone(), payment_profiles: PaymentProfiles { customer_type: CustomerType::Individual, payment: PaymentDetails::CreditCard(CreditCardDetails { @@ -393,16 +385,18 @@ impl response: Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::NoResponseId, redirection_data: None, - mandate_reference: item.response.customer_profile_id.map(|mandate_id| { - types::MandateReference { - connector_mandate_id: Some(mandate_id), - payment_method_id: item + mandate_reference: item.response.customer_profile_id.map( + |customer_profile_id| types::MandateReference { + connector_mandate_id: item .response .customer_payment_profile_id_list .first() - .cloned(), - } - }), + .map(|payment_profile_id| { + format!("{customer_profile_id}-{payment_profile_id}") + }), + payment_method_id: None, + }, + ), connector_metadata: None, network_txn_id: None, connector_response_reference_id: None, @@ -635,27 +629,24 @@ impl api_models::payments::ConnectorMandateReferenceId, ), ) -> Result { + let mandate_id = connector_mandate_id + .connector_mandate_id + .ok_or(errors::ConnectorError::MissingConnectorMandateID)?; Ok(Self { transaction_type: TransactionType::try_from(item.router_data.request.capture_method)?, amount: item.amount, currency_code: item.router_data.request.currency, payment: None, - profile: Some(ProfileDetails::CustomerProfileDetails( - CustomerProfileDetails { - customer_profile_id: Secret::from( - connector_mandate_id - .connector_mandate_id - .ok_or(errors::ConnectorError::MissingConnectorMandateID)?, - ), - payment_profile: PaymentProfileDetails { - payment_profile_id: Secret::from( - connector_mandate_id - .payment_method_id - .ok_or(errors::ConnectorError::MissingConnectorMandateID)?, - ), - }, - }, - )), + profile: mandate_id + .split_once('-') + .map(|(customer_profile_id, payment_profile_id)| { + ProfileDetails::CustomerProfileDetails(CustomerProfileDetails { + customer_profile_id: Secret::from(customer_profile_id.to_string()), + payment_profile: PaymentProfileDetails { + payment_profile_id: Secret::from(payment_profile_id.to_string()), + }, + }) + }), order: Order { description: item.router_data.connector_request_reference_id.clone(), }, @@ -709,11 +700,13 @@ impl create_profile: true, })), Some(CustomerDetails { - id: item - .router_data - .customer_id - .clone() - .ok_or_else(missing_field_err("customer_id"))?, + //The payment ID is included in the customer details because the connector requires unique customer information with a length of fewer than 20 characters when creating a mandate. + //If the length exceeds 20 characters, a random alphanumeric string is used instead. + id: if item.router_data.payment_id.len() <= 20 { + item.router_data.payment_id.clone() + } else { + Alphanumeric.sample_string(&mut rand::thread_rng(), 20) + }, }), ) } else { @@ -1087,6 +1080,24 @@ impl .and_then(|x| x.secure_acceptance_url.to_owned()); let redirection_data = url.map(|url| services::RedirectForm::from((url, services::Method::Get))); + let mandate_reference = item.response.profile_response.map(|profile_response| { + let payment_profile_id = profile_response + .customer_payment_profile_id_list + .and_then(|customer_payment_profile_id_list| { + customer_payment_profile_id_list.first().cloned() + }); + types::MandateReference { + connector_mandate_id: profile_response.customer_profile_id.and_then( + |customer_profile_id| { + payment_profile_id.map(|payment_profile_id| { + format!("{customer_profile_id}-{payment_profile_id}") + }) + }, + ), + payment_method_id: None, + } + }); + Ok(Self { status, response: match error { @@ -1096,16 +1107,7 @@ impl transaction_response.transaction_id.clone(), ), redirection_data, - mandate_reference: item.response.profile_response.map( - |profile_response| types::MandateReference { - connector_mandate_id: profile_response.customer_profile_id, - payment_method_id: profile_response - .customer_payment_profile_id_list - .and_then(|customer_payment_profile_id_list| { - customer_payment_profile_id_list.first().cloned() - }), - }, - ), + mandate_reference, connector_metadata: metadata, network_txn_id: transaction_response .network_trans_id From 15d6c3e846a77dec6b6a5165d86044a9b9fd52f1 Mon Sep 17 00:00:00 2001 From: Jagan Date: Mon, 3 Jun 2024 17:57:30 +0530 Subject: [PATCH 08/10] feat(multitenancy): add support for multitenancy and handle the same in router, producer, consumer, drainer and analytics (#4630) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Arun Raj M --- config/config.example.toml | 6 + config/deployments/env_specific.toml | 7 +- config/development.toml | 6 + config/docker_compose.toml | 6 + crates/analytics/src/lib.rs | 8 +- crates/analytics/src/sqlx.rs | 14 +- crates/common_utils/src/consts.rs | 3 + crates/common_utils/src/lib.rs | 23 ++ crates/drainer/src/connection.rs | 17 +- crates/drainer/src/handler.rs | 77 +++--- crates/drainer/src/health_check.rs | 48 ++-- crates/drainer/src/lib.rs | 13 +- crates/drainer/src/main.rs | 19 +- crates/drainer/src/secrets_transformers.rs | 1 + crates/drainer/src/services.rs | 20 +- crates/drainer/src/settings.rs | 52 ++++- .../src/errors/api_error_response.rs | 10 + crates/redis_interface/src/commands.rs | 100 +++++--- crates/redis_interface/src/lib.rs | 31 ++- crates/router/src/bin/scheduler.rs | 72 ++++-- .../src/compatibility/stripe/customers.rs | 2 +- .../router/src/compatibility/stripe/errors.rs | 7 +- crates/router/src/compatibility/wrap.rs | 7 +- crates/router/src/configs/defaults.rs | 1 - .../src/configs/secrets_transformers.rs | 1 + crates/router/src/configs/settings.rs | 41 +++- crates/router/src/connector/nuvei.rs | 2 +- crates/router/src/connector/shift4.rs | 2 +- crates/router/src/connector/square.rs | 2 +- crates/router/src/connector/wise.rs | 2 +- crates/router/src/core/admin.rs | 46 ++-- crates/router/src/core/api_keys.rs | 12 +- crates/router/src/core/api_locking.rs | 6 +- crates/router/src/core/authentication.rs | 8 +- .../router/src/core/authentication/utils.rs | 10 +- crates/router/src/core/blocklist.rs | 10 +- .../router/src/core/blocklist/transformers.rs | 4 +- crates/router/src/core/blocklist/utils.rs | 20 +- crates/router/src/core/cache.rs | 4 +- crates/router/src/core/cards_info.rs | 2 +- crates/router/src/core/conditional_config.rs | 8 +- crates/router/src/core/configs.rs | 10 +- .../router/src/core/connector_onboarding.rs | 10 +- .../src/core/connector_onboarding/paypal.rs | 16 +- crates/router/src/core/currency.rs | 6 +- crates/router/src/core/customers.rs | 12 +- crates/router/src/core/disputes.rs | 16 +- .../router/src/core/disputes/transformers.rs | 8 +- crates/router/src/core/files.rs | 8 +- crates/router/src/core/files/helpers.rs | 12 +- crates/router/src/core/fraud_check.rs | 16 +- crates/router/src/core/fraud_check/flows.rs | 4 +- .../core/fraud_check/flows/checkout_flow.rs | 8 +- .../fraud_check/flows/fulfillment_flow.rs | 4 +- .../core/fraud_check/flows/record_return.rs | 8 +- .../src/core/fraud_check/flows/sale_flow.rs | 8 +- .../fraud_check/flows/transaction_flow.rs | 8 +- .../router/src/core/fraud_check/operation.rs | 10 +- .../fraud_check/operation/fraud_check_post.rs | 10 +- .../fraud_check/operation/fraud_check_pre.rs | 8 +- crates/router/src/core/gsm.rs | 10 +- crates/router/src/core/health_check.rs | 2 +- crates/router/src/core/locker_migration.rs | 7 +- crates/router/src/core/mandate.rs | 14 +- crates/router/src/core/mandate/helpers.rs | 4 +- crates/router/src/core/payment_link.rs | 10 +- crates/router/src/core/payment_methods.rs | 6 +- .../router/src/core/payment_methods/cards.rs | 60 ++--- .../surcharge_decision_configs.rs | 8 +- .../router/src/core/payment_methods/vault.rs | 21 +- crates/router/src/core/payments.rs | 79 +++---- .../router/src/core/payments/access_token.rs | 6 +- .../src/core/payments/conditional_configs.rs | 6 +- crates/router/src/core/payments/customers.rs | 6 +- crates/router/src/core/payments/flows.rs | 16 +- .../src/core/payments/flows/approve_flow.rs | 10 +- .../src/core/payments/flows/authorize_flow.rs | 18 +- .../src/core/payments/flows/cancel_flow.rs | 10 +- .../src/core/payments/flows/capture_flow.rs | 10 +- .../payments/flows/complete_authorize_flow.rs | 16 +- .../flows/incremental_authorization_flow.rs | 10 +- .../src/core/payments/flows/psync_flow.rs | 14 +- .../src/core/payments/flows/reject_flow.rs | 10 +- .../src/core/payments/flows/session_flow.rs | 23 +- .../core/payments/flows/setup_mandate_flow.rs | 14 +- crates/router/src/core/payments/helpers.rs | 57 +++-- crates/router/src/core/payments/operations.rs | 48 ++-- .../payments/operations/payment_approve.rs | 6 +- .../payments/operations/payment_cancel.rs | 6 +- .../payments/operations/payment_capture.rs | 6 +- .../operations/payment_complete_authorize.rs | 14 +- .../payments/operations/payment_confirm.rs | 22 +- .../payments/operations/payment_create.rs | 20 +- .../payments/operations/payment_reject.rs | 6 +- .../payments/operations/payment_response.rs | 34 +-- .../payments/operations/payment_session.rs | 12 +- .../core/payments/operations/payment_start.rs | 12 +- .../payments/operations/payment_status.rs | 16 +- .../payments/operations/payment_update.rs | 14 +- .../payments_incremental_authorization.rs | 12 +- crates/router/src/core/payments/retry.rs | 12 +- crates/router/src/core/payments/routing.rs | 56 +++-- .../router/src/core/payments/tokenization.rs | 8 +- .../router/src/core/payments/transformers.rs | 28 +-- crates/router/src/core/payments/types.rs | 6 +- crates/router/src/core/payouts.rs | 52 ++--- .../router/src/core/payouts/access_token.rs | 8 +- crates/router/src/core/payouts/helpers.rs | 16 +- crates/router/src/core/payouts/retry.rs | 12 +- crates/router/src/core/payouts/validator.rs | 4 +- crates/router/src/core/pm_auth.rs | 23 +- crates/router/src/core/poll.rs | 6 +- crates/router/src/core/refunds.rs | 32 +-- crates/router/src/core/routing.rs | 22 +- .../src/core/surcharge_decision_config.rs | 8 +- crates/router/src/core/user.rs | 85 +++---- .../src/core/user/dashboard_metadata.rs | 14 +- crates/router/src/core/user/sample_data.rs | 6 +- crates/router/src/core/user_role.rs | 18 +- crates/router/src/core/user_role/role.rs | 18 +- crates/router/src/core/utils.rs | 20 +- crates/router/src/core/verification.rs | 6 +- crates/router/src/core/verification/utils.rs | 4 +- crates/router/src/core/verify_connector.rs | 4 +- crates/router/src/core/webhooks.rs | 46 ++-- .../src/core/webhooks/webhook_events.rs | 10 +- crates/router/src/db/api_keys.rs | 19 +- crates/router/src/db/kafka_store.rs | 3 +- .../src/db/merchant_connector_account.rs | 10 +- crates/router/src/lib.rs | 2 +- crates/router/src/routes.rs | 3 +- crates/router/src/routes/app.rs | 221 +++++++++++++----- crates/router/src/routes/customers.rs | 2 +- .../router/src/routes/dummy_connector/core.rs | 16 +- .../src/routes/dummy_connector/utils.rs | 12 +- crates/router/src/routes/health.rs | 4 +- crates/router/src/routes/payment_methods.rs | 35 ++- crates/router/src/routes/payments.rs | 5 +- crates/router/src/routes/recon.rs | 10 +- crates/router/src/services.rs | 22 +- crates/router/src/services/api.rs | 70 ++++-- crates/router/src/services/api/client.rs | 8 +- crates/router/src/services/authentication.rs | 104 +++++---- .../src/services/authentication/blacklist.rs | 26 +-- crates/router/src/services/authorization.rs | 12 +- .../src/services/authorization/roles.rs | 4 +- crates/router/src/services/email/types.rs | 4 +- crates/router/src/services/pm_auth.rs | 4 +- crates/router/src/types/api/mandates.rs | 6 +- .../router/src/types/api/verify_connector.rs | 6 +- .../src/types/api/verify_connector/paypal.rs | 4 +- crates/router/src/types/api/webhooks.rs | 2 +- crates/router/src/types/domain/user.rs | 45 ++-- .../src/types/domain/user/decision_manager.rs | 24 +- .../src/types/storage/payment_attempt.rs | 27 ++- crates/router/src/utils.rs | 4 +- .../router/src/utils/connector_onboarding.rs | 8 +- .../src/utils/connector_onboarding/paypal.rs | 4 +- crates/router/src/utils/currency.rs | 34 +-- crates/router/src/utils/user.rs | 20 +- .../src/utils/user/dashboard_metadata.rs | 14 +- crates/router/src/utils/user/sample_data.rs | 4 +- .../router/src/utils/user/two_factor_auth.rs | 16 +- crates/router/src/utils/user_role.rs | 10 +- crates/router/src/workflows/api_key_expiry.rs | 10 +- .../attach_payout_account_workflow.rs | 8 +- .../src/workflows/outgoing_webhook_retry.rs | 10 +- crates/router/src/workflows/payment_sync.rs | 12 +- crates/router/src/workflows/refund_router.rs | 8 +- crates/router/src/workflows/tokenized_data.rs | 8 +- crates/router/tests/cache.rs | 36 ++- crates/router/tests/connectors/aci.rs | 22 +- crates/router/tests/connectors/utils.rs | 52 ++++- crates/router/tests/payments.rs | 12 +- crates/router/tests/payments2.rs | 12 +- crates/router/tests/services.rs | 14 +- crates/scheduler/src/consumer.rs | 63 +++-- crates/scheduler/src/consumer/workflows.rs | 4 +- crates/scheduler/src/errors.rs | 2 + crates/scheduler/src/producer.rs | 29 ++- crates/scheduler/src/scheduler.rs | 36 ++- crates/scheduler/src/utils.rs | 19 +- crates/storage_impl/src/config.rs | 24 ++ crates/storage_impl/src/database/store.rs | 52 +++-- crates/storage_impl/src/lib.rs | 72 +++--- crates/storage_impl/src/redis/cache.rs | 168 ++++++++++--- crates/storage_impl/src/redis/pub_sub.rs | 62 ++++- loadtest/config/development.toml | 6 + 188 files changed, 2261 insertions(+), 1415 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index 5d40d0e55ef9..8aa0ca9e52f2 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -629,3 +629,9 @@ disputes = "hyperswitch-dispute-events" [saved_payment_methods] sdk_eligible_payment_methods = "card" + +[multitenancy] +enabled = false + +[multitenancy.tenants] +public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "public", redis_key_prefix = ""} # schema -> Postgres db schema, redis_key_prefix -> redis key distinguisher, base_url -> url of the tenant \ No newline at end of file diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml index 7215e1931a40..a097e1b66dcd 100644 --- a/config/deployments/env_specific.toml +++ b/config/deployments/env_specific.toml @@ -230,7 +230,6 @@ recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authent # Server configuration [server] -base_url = "https://server_base_url" workers = 8 port = 8080 host = "127.0.0.1" @@ -253,3 +252,9 @@ encryption_manager = "aws_kms" # Encryption manager client to be used [encryption_management.aws_kms] key_id = "kms_key_id" # The AWS key ID used by the KMS SDK for decrypting data. region = "kms_region" # The AWS region used by the KMS SDK for decrypting data. + +[multitenancy] +enabled = false + +[multitenancy.tenants] +public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "public", redis_key_prefix = ""} \ No newline at end of file diff --git a/config/development.toml b/config/development.toml index 496ce6477a8d..d12a667b6315 100644 --- a/config/development.toml +++ b/config/development.toml @@ -628,3 +628,9 @@ disputes = "hyperswitch-dispute-events" [saved_payment_methods] sdk_eligible_payment_methods = "card" + +[multitenancy] +enabled = false + +[multitenancy.tenants] +public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "public", redis_key_prefix = ""} \ No newline at end of file diff --git a/config/docker_compose.toml b/config/docker_compose.toml index b94b5c8afbb6..3f6c9523e933 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -492,3 +492,9 @@ disputes = "hyperswitch-dispute-events" [saved_payment_methods] sdk_eligible_payment_methods = "card" + +[multitenancy] +enabled = false + +[multitenancy.tenants] +public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "public", redis_key_prefix = ""} \ No newline at end of file diff --git a/crates/analytics/src/lib.rs b/crates/analytics/src/lib.rs index 1deca1e07519..f658f6790972 100644 --- a/crates/analytics/src/lib.rs +++ b/crates/analytics/src/lib.rs @@ -601,20 +601,20 @@ impl AnalyticsProvider { } } - pub async fn from_conf(config: &AnalyticsConfig) -> Self { + pub async fn from_conf(config: &AnalyticsConfig, tenant: &str) -> Self { match config { - AnalyticsConfig::Sqlx { sqlx } => Self::Sqlx(SqlxClient::from_conf(sqlx).await), + AnalyticsConfig::Sqlx { sqlx } => Self::Sqlx(SqlxClient::from_conf(sqlx, tenant).await), AnalyticsConfig::Clickhouse { clickhouse } => Self::Clickhouse(ClickhouseClient { config: Arc::new(clickhouse.clone()), }), AnalyticsConfig::CombinedCkh { sqlx, clickhouse } => Self::CombinedCkh( - SqlxClient::from_conf(sqlx).await, + SqlxClient::from_conf(sqlx, tenant).await, ClickhouseClient { config: Arc::new(clickhouse.clone()), }, ), AnalyticsConfig::CombinedSqlx { sqlx, clickhouse } => Self::CombinedSqlx( - SqlxClient::from_conf(sqlx).await, + SqlxClient::from_conf(sqlx, tenant).await, ClickhouseClient { config: Arc::new(clickhouse.clone()), }, diff --git a/crates/analytics/src/sqlx.rs b/crates/analytics/src/sqlx.rs index d3cb24a00c26..3a1b7f2d4685 100644 --- a/crates/analytics/src/sqlx.rs +++ b/crates/analytics/src/sqlx.rs @@ -4,12 +4,14 @@ use api_models::{ analytics::refunds::RefundType, enums::{DisputeStage, DisputeStatus}, }; -use common_utils::errors::{CustomResult, ParsingError}; +use common_utils::{ + errors::{CustomResult, ParsingError}, + DbConnectionParams, +}; use diesel_models::enums::{ AttemptStatus, AuthenticationType, Currency, PaymentMethod, RefundStatus, }; use error_stack::ResultExt; -use masking::PeekInterface; use sqlx::{ postgres::{PgArgumentBuffer, PgPoolOptions, PgRow, PgTypeInfo, PgValueRef}, Decode, Encode, @@ -49,12 +51,8 @@ impl Default for SqlxClient { } impl SqlxClient { - pub async fn from_conf(conf: &Database) -> Self { - let password = &conf.password.peek(); - let database_url = format!( - "postgres://{}:{}@{}:{}/{}", - conf.username, password, conf.host, conf.port, conf.dbname - ); + pub async fn from_conf(conf: &Database, schema: &str) -> Self { + let database_url = conf.get_database_url(schema); #[allow(clippy::expect_used)] let pool = PgPoolOptions::new() .max_connections(conf.pool_size) diff --git a/crates/common_utils/src/consts.rs b/crates/common_utils/src/consts.rs index 0ea826d15cdd..0fe5cd7d7c7b 100644 --- a/crates/common_utils/src/consts.rs +++ b/crates/common_utils/src/consts.rs @@ -84,6 +84,9 @@ pub const DEFAULT_TTL_FOR_EXTENDED_CARD_INFO: u16 = 15 * 60; /// Max ttl for Extended card info in redis (in seconds) pub const MAX_TTL_FOR_EXTENDED_CARD_INFO: u16 = 60 * 60 * 2; +/// Default tenant to be used when multitenancy is disabled +pub const DEFAULT_TENANT: &str = "public"; + /// Max Length for MerchantReferenceId pub const MAX_ALLOWED_MERCHANT_REFERENCE_ID_LENGTH: u8 = 64; diff --git a/crates/common_utils/src/lib.rs b/crates/common_utils/src/lib.rs index d77442ad40f1..4e515e3d6a74 100644 --- a/crates/common_utils/src/lib.rs +++ b/crates/common_utils/src/lib.rs @@ -2,6 +2,8 @@ #![warn(missing_docs, missing_debug_implementations)] #![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR" ), "/", "README.md"))] +use masking::{PeekInterface, Secret}; + use crate::{ consts::ID_LENGTH, id_type::{CustomerId, MerchantReferenceId}, @@ -224,6 +226,27 @@ pub fn generate_time_ordered_id(prefix: &str) -> String { format!("{prefix}_{}", uuid::Uuid::now_v7().as_simple()) } +#[allow(missing_docs)] +pub trait DbConnectionParams { + fn get_username(&self) -> &str; + fn get_password(&self) -> Secret; + fn get_host(&self) -> &str; + fn get_port(&self) -> u16; + fn get_dbname(&self) -> &str; + fn get_database_url(&self, schema: &str) -> String { + format!( + "postgres://{}:{}@{}:{}/{}?application_name={}&options=-c search_path%3D{}", + self.get_username(), + self.get_password().peek(), + self.get_host(), + self.get_port(), + self.get_dbname(), + schema, + schema, + ) + } +} + #[cfg(test)] mod nanoid_tests { #![allow(clippy::unwrap_used)] diff --git a/crates/drainer/src/connection.rs b/crates/drainer/src/connection.rs index c539e9a734ce..ec3bc44973b6 100644 --- a/crates/drainer/src/connection.rs +++ b/crates/drainer/src/connection.rs @@ -1,6 +1,6 @@ use bb8::PooledConnection; +use common_utils::DbConnectionParams; use diesel::PgConnection; -use masking::PeekInterface; use crate::{settings::Database, Settings}; @@ -18,15 +18,12 @@ pub async fn redis_connection(conf: &Settings) -> redis_interface::RedisConnecti /// /// Will panic if could not create a db pool #[allow(clippy::expect_used)] -pub async fn diesel_make_pg_pool(database: &Database, _test_transaction: bool) -> PgPool { - let database_url = format!( - "postgres://{}:{}@{}:{}/{}", - database.username, - database.password.peek(), - database.host, - database.port, - database.dbname - ); +pub async fn diesel_make_pg_pool( + database: &Database, + _test_transaction: bool, + schema: &str, +) -> PgPool { + let database_url = database.get_database_url(schema); let manager = async_bb8_diesel::ConnectionManager::::new(database_url); let pool = bb8::Pool::builder() .max_size(database.pool_size) diff --git a/crates/drainer/src/handler.rs b/crates/drainer/src/handler.rs index 35ad467d5feb..77aefb422aff 100644 --- a/crates/drainer/src/handler.rs +++ b/crates/drainer/src/handler.rs @@ -1,4 +1,7 @@ -use std::sync::{atomic, Arc}; +use std::{ + collections::HashMap, + sync::{atomic, Arc}, +}; use router_env::tracing::Instrument; use tokio::{ @@ -31,12 +34,12 @@ pub struct HandlerInner { loop_interval: Duration, active_tasks: Arc, conf: DrainerSettings, - store: Arc, + stores: HashMap>, running: Arc, } impl Handler { - pub fn from_conf(conf: DrainerSettings, store: Arc) -> Self { + pub fn from_conf(conf: DrainerSettings, stores: HashMap>) -> Self { let shutdown_interval = Duration::from_millis(conf.shutdown_interval.into()); let loop_interval = Duration::from_millis(conf.loop_interval.into()); @@ -49,7 +52,7 @@ impl Handler { loop_interval, active_tasks, conf, - store, + stores, running, }; @@ -68,21 +71,23 @@ impl Handler { while self.running.load(atomic::Ordering::SeqCst) { metrics::DRAINER_HEALTH.add(&metrics::CONTEXT, 1, &[]); - if self.store.is_stream_available(stream_index).await { - let _task_handle = tokio::spawn( - drainer_handler( - self.store.clone(), - stream_index, - self.conf.max_read_count, - self.active_tasks.clone(), - jobs_picked.clone(), - ) - .in_current_span(), - ); + for store in self.stores.values() { + if store.is_stream_available(stream_index).await { + let _task_handle = tokio::spawn( + drainer_handler( + store.clone(), + stream_index, + self.conf.max_read_count, + self.active_tasks.clone(), + jobs_picked.clone(), + ) + .in_current_span(), + ); + } } stream_index = utils::increment_stream_index( (stream_index, jobs_picked.clone()), - self.store.config.drainer_num_partitions, + self.conf.num_partitions, ) .await; time::sleep(self.loop_interval).await; @@ -116,18 +121,33 @@ impl Handler { pub fn spawn_error_handlers(&self, tx: mpsc::Sender<()>) -> errors::DrainerResult<()> { let (redis_error_tx, redis_error_rx) = oneshot::channel(); + let redis_conn_clone = self + .stores + .values() + .next() + .map(|store| store.redis_conn.clone()); + match redis_conn_clone { + None => { + logger::error!("No redis connection found"); + Err( + errors::DrainerError::UnexpectedError("No redis connection found".to_string()) + .into(), + ) + } + Some(redis_conn_clone) => { + // Spawn a task to monitor if redis is down or not + let _task_handle = tokio::spawn( + async move { redis_conn_clone.on_error(redis_error_tx).await } + .in_current_span(), + ); - let redis_conn_clone = self.store.redis_conn.clone(); - - // Spawn a task to monitor if redis is down or not - let _task_handle = tokio::spawn( - async move { redis_conn_clone.on_error(redis_error_tx).await }.in_current_span(), - ); - - //Spawns a task to send shutdown signal if redis goes down - let _task_handle = tokio::spawn(redis_error_receiver(redis_error_rx, tx).in_current_span()); + //Spawns a task to send shutdown signal if redis goes down + let _task_handle = + tokio::spawn(redis_error_receiver(redis_error_rx, tx).in_current_span()); - Ok(()) + Ok(()) + } + } } } @@ -208,7 +228,10 @@ async fn drainer( }; // parse_stream_entries returns error if no entries is found, handle it - let entries = utils::parse_stream_entries(&stream_read, stream_name)?; + let entries = utils::parse_stream_entries( + &stream_read, + store.redis_conn.add_prefix(stream_name).as_str(), + )?; let read_count = entries.len(); metrics::JOBS_PICKED_PER_STREAM.add( diff --git a/crates/drainer/src/health_check.rs b/crates/drainer/src/health_check.rs index 443cb5b6f3fb..10514108991b 100644 --- a/crates/drainer/src/health_check.rs +++ b/crates/drainer/src/health_check.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use actix_web::{web, Scope}; use async_bb8_diesel::{AsyncConnection, AsyncRunQueryDsl}; @@ -8,9 +8,9 @@ use error_stack::ResultExt; use router_env::{instrument, logger, tracing}; use crate::{ - connection::{pg_connection, redis_connection}, + connection::pg_connection, errors::HealthCheckError, - services::{self, Store}, + services::{self, log_and_return_error_response, Store}, Settings, }; @@ -20,10 +20,10 @@ pub const TEST_STREAM_DATA: &[(&str, &str)] = &[("data", "sample_data")]; pub struct Health; impl Health { - pub fn server(conf: Settings, store: Arc) -> Scope { + pub fn server(conf: Settings, stores: HashMap>) -> Scope { web::scope("health") .app_data(web::Data::new(conf)) - .app_data(web::Data::new(store)) + .app_data(web::Data::new(stores)) .service(web::resource("").route(web::get().to(health))) .service(web::resource("/ready").route(web::get().to(deep_health_check))) } @@ -38,25 +38,35 @@ pub async fn health() -> impl actix_web::Responder { #[instrument(skip_all)] pub async fn deep_health_check( conf: web::Data, - store: web::Data>, + stores: web::Data>>, ) -> impl actix_web::Responder { - match deep_health_check_func(conf, store).await { - Ok(response) => services::http_response_json( - serde_json::to_string(&response) + let mut deep_health_res = HashMap::new(); + for (tenant, store) in stores.iter() { + logger::info!("Tenant: {:?}", tenant); + + let response = match deep_health_check_func(conf.clone(), store).await { + Ok(response) => serde_json::to_string(&response) .map_err(|err| { logger::error!(serialization_error=?err); }) .unwrap_or_default(), - ), - - Err(err) => services::log_and_return_error_response(err), + Err(err) => return log_and_return_error_response(err), + }; + deep_health_res.insert(tenant.clone(), response); } + services::http_response_json( + serde_json::to_string(&deep_health_res) + .map_err(|err| { + logger::error!(serialization_error=?err); + }) + .unwrap_or_default(), + ) } #[instrument(skip_all)] pub async fn deep_health_check_func( conf: web::Data, - store: web::Data>, + store: &Arc, ) -> Result> { logger::info!("Deep health check was called"); @@ -146,8 +156,11 @@ impl HealthCheckInterface for Store { Ok(()) } - async fn health_check_redis(&self, conf: &Settings) -> CustomResult<(), HealthCheckRedisError> { - let redis_conn = redis_connection(conf).await; + async fn health_check_redis( + &self, + _conf: &Settings, + ) -> CustomResult<(), HealthCheckRedisError> { + let redis_conn = self.redis_conn.clone(); redis_conn .serialize_and_set_key_with_expiry("test_key", "test_value", 30) @@ -181,15 +194,14 @@ impl HealthCheckInterface for Store { logger::debug!("Stream append succeeded"); - let output = self - .redis_conn + let output = redis_conn .stream_read_entries(TEST_STREAM_NAME, "0-0", Some(10)) .await .change_context(HealthCheckRedisError::StreamReadFailed)?; logger::debug!("Stream read succeeded"); let (_, id_to_trim) = output - .get(TEST_STREAM_NAME) + .get(&redis_conn.add_prefix(TEST_STREAM_NAME)) .and_then(|entries| { entries .last() diff --git a/crates/drainer/src/lib.rs b/crates/drainer/src/lib.rs index cb2b55d202f9..5b67640663c6 100644 --- a/crates/drainer/src/lib.rs +++ b/crates/drainer/src/lib.rs @@ -10,7 +10,7 @@ pub mod settings; mod stream; mod types; mod utils; -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; mod secrets_transformers; use actix_web::dev::Server; @@ -30,8 +30,11 @@ use crate::{ connection::pg_connection, services::Store, settings::DrainerSettings, types::StreamData, }; -pub async fn start_drainer(store: Arc, conf: DrainerSettings) -> errors::DrainerResult<()> { - let drainer_handler = handler::Handler::from_conf(conf, store); +pub async fn start_drainer( + stores: HashMap>, + conf: DrainerSettings, +) -> errors::DrainerResult<()> { + let drainer_handler = handler::Handler::from_conf(conf, stores); let (tx, rx) = mpsc::channel::<()>(1); @@ -59,11 +62,11 @@ pub async fn start_drainer(store: Arc, conf: DrainerSettings) -> errors:: pub async fn start_web_server( conf: Settings, - store: Arc, + stores: HashMap>, ) -> Result { let server = conf.server.clone(); let web_server = actix_web::HttpServer::new(move || { - actix_web::App::new().service(health_check::Health::server(conf.clone(), store.clone())) + actix_web::App::new().service(health_check::Health::server(conf.clone(), stores.clone())) }) .bind((server.host.as_str(), server.port))? .run(); diff --git a/crates/drainer/src/main.rs b/crates/drainer/src/main.rs index 64e66619d744..f3f822129c34 100644 --- a/crates/drainer/src/main.rs +++ b/crates/drainer/src/main.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use drainer::{ errors::DrainerResult, logger::logger, services, settings, start_drainer, start_web_server, }; @@ -17,7 +19,11 @@ async fn main() -> DrainerResult<()> { let state = settings::AppState::new(conf.clone()).await; - let store = std::sync::Arc::new(services::Store::new(&state.conf, false).await); + let mut stores = HashMap::new(); + for (tenant_name, tenant) in conf.multitenancy.get_tenants() { + let store = std::sync::Arc::new(services::Store::new(&state.conf, false, tenant).await); + stores.insert(tenant_name.clone(), store); + } #[cfg(feature = "vergen")] println!("Starting drainer (Version: {})", router_env::git_tag!()); @@ -29,9 +35,12 @@ async fn main() -> DrainerResult<()> { ); #[allow(clippy::expect_used)] - let web_server = Box::pin(start_web_server(state.conf.as_ref().clone(), store.clone())) - .await - .expect("Failed to create the server"); + let web_server = Box::pin(start_web_server( + state.conf.as_ref().clone(), + stores.clone(), + )) + .await + .expect("Failed to create the server"); tokio::spawn( async move { @@ -44,7 +53,7 @@ async fn main() -> DrainerResult<()> { logger::debug!(startup_config=?conf); logger::info!("Drainer started [{:?}] [{:?}]", conf.drainer, conf.log); - start_drainer(store.clone(), conf.drainer).await?; + start_drainer(stores.clone(), conf.drainer).await?; Ok(()) } diff --git a/crates/drainer/src/secrets_transformers.rs b/crates/drainer/src/secrets_transformers.rs index 4ffb584a1529..0582ccd798b1 100644 --- a/crates/drainer/src/secrets_transformers.rs +++ b/crates/drainer/src/secrets_transformers.rs @@ -45,5 +45,6 @@ pub async fn fetch_raw_secrets( drainer: conf.drainer, encryption_management: conf.encryption_management, secrets_management: conf.secrets_management, + multitenancy: conf.multitenancy, } } diff --git a/crates/drainer/src/services.rs b/crates/drainer/src/services.rs index 9e0165548a01..55ffe0c4e7fa 100644 --- a/crates/drainer/src/services.rs +++ b/crates/drainer/src/services.rs @@ -2,16 +2,18 @@ use std::sync::Arc; use actix_web::{body, HttpResponse, ResponseError}; use error_stack::Report; +use redis_interface::RedisConnectionPool; use crate::{ connection::{diesel_make_pg_pool, PgPool}, logger, + settings::Tenant, }; #[derive(Clone)] pub struct Store { pub master_pool: PgPool, - pub redis_conn: Arc, + pub redis_conn: Arc, pub config: StoreConfig, pub request_id: Option, } @@ -28,11 +30,19 @@ impl Store { /// Panics if there is a failure while obtaining the HashiCorp client using the provided configuration. /// This panic indicates a critical failure in setting up external services, and the application cannot proceed without a valid HashiCorp client. /// - pub async fn new(config: &crate::Settings, test_transaction: bool) -> Self { + pub async fn new(config: &crate::Settings, test_transaction: bool, tenant: &Tenant) -> Self { + let redis_conn = crate::connection::redis_connection(config).await; Self { - master_pool: diesel_make_pg_pool(config.master_database.get_inner(), test_transaction) - .await, - redis_conn: Arc::new(crate::connection::redis_connection(config).await), + master_pool: diesel_make_pg_pool( + config.master_database.get_inner(), + test_transaction, + &tenant.schema, + ) + .await, + redis_conn: Arc::new(RedisConnectionPool::clone( + &redis_conn, + &tenant.redis_key_prefix, + )), config: StoreConfig { drainer_stream_name: config.drainer.stream_name.clone(), drainer_num_partitions: config.drainer.num_partitions, diff --git a/crates/drainer/src/settings.rs b/crates/drainer/src/settings.rs index e68ede9e8b2e..311cee0cede7 100644 --- a/crates/drainer/src/settings.rs +++ b/crates/drainer/src/settings.rs @@ -1,6 +1,6 @@ -use std::{path::PathBuf, sync::Arc}; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; -use common_utils::ext_traits::ConfigExt; +use common_utils::{ext_traits::ConfigExt, DbConnectionParams}; use config::{Environment, File}; use external_services::managers::{ encryption_management::EncryptionManagementConfig, secrets_management::SecretsManagementConfig, @@ -73,6 +73,7 @@ pub struct Settings { pub drainer: DrainerSettings, pub encryption_management: EncryptionManagementConfig, pub secrets_management: SecretsManagementConfig, + pub multitenancy: Multitenancy, } #[derive(Debug, Deserialize, Clone)] @@ -87,6 +88,24 @@ pub struct Database { pub connection_timeout: u64, } +impl DbConnectionParams for Database { + fn get_username(&self) -> &str { + &self.username + } + fn get_password(&self) -> Secret { + self.password.clone() + } + fn get_host(&self) -> &str { + &self.host + } + fn get_port(&self) -> u16 { + self.port + } + fn get_dbname(&self) -> &str { + &self.dbname + } +} + #[derive(Debug, Clone, Deserialize)] #[serde(default)] pub struct DrainerSettings { @@ -97,6 +116,35 @@ pub struct DrainerSettings { pub loop_interval: u32, // in milliseconds } +#[derive(Debug, Deserialize, Clone, Default)] +pub struct Multitenancy { + pub enabled: bool, + pub tenants: TenantConfig, +} +impl Multitenancy { + pub fn get_tenants(&self) -> &HashMap { + &self.tenants.0 + } + pub fn get_tenant_names(&self) -> Vec { + self.tenants.0.keys().cloned().collect() + } + pub fn get_tenant(&self, tenant_id: &str) -> Option<&Tenant> { + self.tenants.0.get(tenant_id) + } +} + +#[derive(Debug, Deserialize, Clone, Default)] +#[serde(transparent)] +pub struct TenantConfig(pub HashMap); + +#[derive(Debug, Deserialize, Clone, Default)] +pub struct Tenant { + pub name: String, + pub base_url: String, + pub schema: String, + pub redis_key_prefix: String, +} + #[derive(Debug, Deserialize, Clone)] #[serde(default)] pub struct Server { diff --git a/crates/hyperswitch_domain_models/src/errors/api_error_response.rs b/crates/hyperswitch_domain_models/src/errors/api_error_response.rs index 26a6f1618fa5..053eb493ce48 100644 --- a/crates/hyperswitch_domain_models/src/errors/api_error_response.rs +++ b/crates/hyperswitch_domain_models/src/errors/api_error_response.rs @@ -271,6 +271,10 @@ pub enum ApiErrorResponse { InvalidCookie, #[error(error_type = ErrorType::InvalidRequestError, code = "IR_27", message = "Extended card info does not exist")] ExtendedCardInfoNotFound, + #[error(error_type = ErrorType::ProcessingError, code = "HE_06", message = "Missing tenant id")] + MissingTenantId, + #[error(error_type = ErrorType::ProcessingError, code = "HE_06", message = "Invalid tenant id: {tenant_id}")] + InvalidTenant { tenant_id: String }, } #[derive(Clone)] @@ -603,6 +607,12 @@ impl ErrorSwitch for ApiErrorRespon Self::ExtendedCardInfoNotFound => { AER::NotFound(ApiError::new("IR", 27, "Extended card info does not exist", None)) } + Self::MissingTenantId => { + AER::InternalServerError(ApiError::new("HE", 6, "Missing Tenant ID in the request".to_string(), None)) + } + Self::InvalidTenant { tenant_id } => { + AER::InternalServerError(ApiError::new("HE", 6, format!("Invalid Tenant {tenant_id}"), None)) + } } } } diff --git a/crates/redis_interface/src/commands.rs b/crates/redis_interface/src/commands.rs index 504820822c08..ccfeb3e5b12e 100644 --- a/crates/redis_interface/src/commands.rs +++ b/crates/redis_interface/src/commands.rs @@ -31,6 +31,13 @@ use crate::{ }; impl super::RedisConnectionPool { + pub fn add_prefix(&self, key: &str) -> String { + if self.key_prefix.is_empty() { + key.to_string() + } else { + format!("{}:{}", self.key_prefix, key) + } + } #[instrument(level = "DEBUG", skip(self))] pub async fn set_key(&self, key: &str, value: V) -> CustomResult<(), errors::RedisError> where @@ -39,7 +46,7 @@ impl super::RedisConnectionPool { { self.pool .set( - key, + self.add_prefix(key), value, Some(Expiration::EX(self.config.default_ttl.into())), None, @@ -144,7 +151,7 @@ impl super::RedisConnectionPool { self.pool .set( - key, + self.add_prefix(key), serialized.as_slice(), Some(Expiration::EX(seconds)), None, @@ -160,7 +167,7 @@ impl super::RedisConnectionPool { V: FromRedis + Unpin + Send + 'static, { self.pool - .get(key) + .get(self.add_prefix(key)) .await .change_context(errors::RedisError::GetFailed) } @@ -171,7 +178,7 @@ impl super::RedisConnectionPool { V: Into + Unpin + Send + 'static, { self.pool - .exists(key) + .exists(self.add_prefix(key)) .await .change_context(errors::RedisError::GetFailed) } @@ -197,7 +204,7 @@ impl super::RedisConnectionPool { #[instrument(level = "DEBUG", skip(self))] pub async fn delete_key(&self, key: &str) -> CustomResult { self.pool - .del(key) + .del(self.add_prefix(key)) .await .change_context(errors::RedisError::DeleteFailed) } @@ -214,7 +221,13 @@ impl super::RedisConnectionPool { V::Error: Into + Send + Sync, { self.pool - .set(key, value, Some(Expiration::EX(seconds)), None, false) + .set( + self.add_prefix(key), + value, + Some(Expiration::EX(seconds)), + None, + false, + ) .await .change_context(errors::RedisError::SetExFailed) } @@ -232,7 +245,7 @@ impl super::RedisConnectionPool { { self.pool .set( - key, + self.add_prefix(key), value, Some(Expiration::EX( seconds.unwrap_or(self.config.default_ttl.into()), @@ -251,7 +264,7 @@ impl super::RedisConnectionPool { seconds: i64, ) -> CustomResult<(), errors::RedisError> { self.pool - .expire(key, seconds) + .expire(self.add_prefix(key), seconds) .await .change_context(errors::RedisError::SetExpiryFailed) } @@ -263,7 +276,7 @@ impl super::RedisConnectionPool { timestamp: i64, ) -> CustomResult<(), errors::RedisError> { self.pool - .expire_at(key, timestamp) + .expire_at(self.add_prefix(key), timestamp) .await .change_context(errors::RedisError::SetExpiryFailed) } @@ -281,7 +294,7 @@ impl super::RedisConnectionPool { { let output: Result<(), _> = self .pool - .hset(key, values) + .hset(self.add_prefix(key), values) .await .change_context(errors::RedisError::SetHashFailed); // setting expiry for the key @@ -306,7 +319,7 @@ impl super::RedisConnectionPool { { let output: Result = self .pool - .hsetnx(key, field, value) + .hsetnx(self.add_prefix(key), field, value) .await .change_context(errors::RedisError::SetHashFieldFailed); @@ -368,7 +381,7 @@ impl super::RedisConnectionPool { Ok(self .pool .next() - .hscan::<&str, &str>(key, pattern, count) + .hscan::<&str, &str>(&self.add_prefix(key), pattern, count) .filter_map(|value| async move { match value { Ok(mut v) => { @@ -419,7 +432,7 @@ impl super::RedisConnectionPool { V: FromRedis + Unpin + Send + 'static, { self.pool - .hget(key, field) + .hget(self.add_prefix(key), field) .await .change_context(errors::RedisError::GetHashFieldFailed) } @@ -456,7 +469,7 @@ impl super::RedisConnectionPool { V::Error: Into + Send, { self.pool - .sadd(key, members) + .sadd(self.add_prefix(key), members) .await .change_context(errors::RedisError::SetAddMembersFailed) } @@ -473,7 +486,7 @@ impl super::RedisConnectionPool { F::Error: Into + Send + Sync, { self.pool - .xadd(stream, false, None, entry_id, fields) + .xadd(self.add_prefix(stream), false, None, entry_id, fields) .await .change_context(errors::RedisError::StreamAppendFailed) } @@ -488,7 +501,7 @@ impl super::RedisConnectionPool { Ids: Into + Debug + Send + Sync, { self.pool - .xdel(stream, ids) + .xdel(self.add_prefix(stream), ids) .await .change_context(errors::RedisError::StreamDeleteFailed) } @@ -504,7 +517,7 @@ impl super::RedisConnectionPool { C::Error: Into + Send + Sync, { self.pool - .xtrim(stream, xcap) + .xtrim(self.add_prefix(stream), xcap) .await .change_context(errors::RedisError::StreamTrimFailed) } @@ -520,22 +533,34 @@ impl super::RedisConnectionPool { Ids: Into + Debug + Send + Sync, { self.pool - .xack(stream, group, ids) + .xack(self.add_prefix(stream), group, ids) .await .change_context(errors::RedisError::StreamAcknowledgeFailed) } #[instrument(level = "DEBUG", skip(self))] - pub async fn stream_get_length(&self, stream: K) -> CustomResult - where - K: Into + Debug + Send + Sync, - { + pub async fn stream_get_length(&self, stream: &str) -> CustomResult { self.pool - .xlen(stream) + .xlen(self.add_prefix(stream)) .await .change_context(errors::RedisError::GetLengthFailed) } + pub fn get_keys_with_prefix(&self, keys: K) -> MultipleKeys + where + K: Into + Debug + Send + Sync, + { + let multiple_keys: MultipleKeys = keys.into(); + let res = multiple_keys + .inner() + .iter() + .filter_map(|key| key.as_str()) + .map(|k| self.add_prefix(k)) + .map(RedisKey::from) + .collect::>(); + MultipleKeys::from(res) + } + #[instrument(level = "DEBUG", skip(self))] pub async fn stream_read_entries( &self, @@ -547,11 +572,12 @@ impl super::RedisConnectionPool { K: Into + Debug + Send + Sync, Ids: Into + Debug + Send + Sync, { + let strms = self.get_keys_with_prefix(streams); self.pool .xread_map( Some(read_count.unwrap_or(self.config.default_stream_read_count)), None, - streams, + strms, ids, ) .await @@ -579,10 +605,22 @@ impl super::RedisConnectionPool { match group { Some((group_name, consumer_name)) => { self.pool - .xreadgroup_map(group_name, consumer_name, count, block, false, streams, ids) + .xreadgroup_map( + group_name, + consumer_name, + count, + block, + false, + self.get_keys_with_prefix(streams), + ids, + ) + .await + } + None => { + self.pool + .xread_map(count, block, self.get_keys_with_prefix(streams), ids) .await } - None => self.pool.xread_map(count, block, streams, ids).await, } .map_err(|err| match err.kind() { RedisErrorKind::NotFound | RedisErrorKind::Parse => { @@ -610,7 +648,7 @@ impl super::RedisConnectionPool { } self.pool - .xgroup_create(stream, group, id, true) + .xgroup_create(self.add_prefix(stream), group, id, true) .await .change_context(errors::RedisError::ConsumerGroupCreateFailed) } @@ -622,7 +660,7 @@ impl super::RedisConnectionPool { group: &str, ) -> CustomResult { self.pool - .xgroup_destroy(stream, group) + .xgroup_destroy(self.add_prefix(stream), group) .await .change_context(errors::RedisError::ConsumerGroupDestroyFailed) } @@ -636,7 +674,7 @@ impl super::RedisConnectionPool { consumer: &str, ) -> CustomResult { self.pool - .xgroup_delconsumer(stream, group, consumer) + .xgroup_delconsumer(self.add_prefix(stream), group, consumer) .await .change_context(errors::RedisError::ConsumerGroupRemoveConsumerFailed) } @@ -649,7 +687,7 @@ impl super::RedisConnectionPool { id: &RedisEntryId, ) -> CustomResult { self.pool - .xgroup_setid(stream, group, id) + .xgroup_setid(self.add_prefix(stream), group, id) .await .change_context(errors::RedisError::ConsumerGroupSetIdFailed) } @@ -669,7 +707,7 @@ impl super::RedisConnectionPool { { self.pool .xclaim( - stream, + self.add_prefix(stream), group, consumer, min_idle_time, diff --git a/crates/redis_interface/src/lib.rs b/crates/redis_interface/src/lib.rs index df74d728331f..dc4fd3bbc9cc 100644 --- a/crates/redis_interface/src/lib.rs +++ b/crates/redis_interface/src/lib.rs @@ -30,10 +30,11 @@ use fred::{interfaces::ClientLike, prelude::EventInterface}; pub use self::types::*; pub struct RedisConnectionPool { - pub pool: fred::prelude::RedisPool, - config: RedisConfig, - pub subscriber: SubscriberClient, - pub publisher: RedisClient, + pub pool: Arc, + pub key_prefix: String, + pub config: Arc, + pub subscriber: Arc, + pub publisher: Arc, pub is_redis_available: Arc, } @@ -166,14 +167,24 @@ impl RedisConnectionPool { let config = RedisConfig::from(conf); Ok(Self { - pool, - config, + pool: Arc::new(pool), + config: Arc::new(config), is_redis_available: Arc::new(atomic::AtomicBool::new(true)), - subscriber, - publisher, + subscriber: Arc::new(subscriber), + publisher: Arc::new(publisher), + key_prefix: String::default(), }) } - + pub fn clone(&self, key_prefix: &str) -> Self { + Self { + pool: Arc::clone(&self.pool), + key_prefix: key_prefix.to_string(), + config: Arc::clone(&self.config), + subscriber: Arc::clone(&self.subscriber), + publisher: Arc::clone(&self.publisher), + is_redis_available: Arc::clone(&self.is_redis_available), + } + } pub async fn on_error(&self, tx: tokio::sync::oneshot::Sender<()>) { use futures::StreamExt; use tokio_stream::wrappers::BroadcastStream; @@ -211,7 +222,7 @@ impl RedisConnectionPool { } } -struct RedisConfig { +pub struct RedisConfig { default_ttl: u32, default_stream_read_count: u64, default_hash_ttl: u32, diff --git a/crates/router/src/bin/scheduler.rs b/crates/router/src/bin/scheduler.rs index 5341a1b09c1e..7e78a355e5c4 100644 --- a/crates/router/src/bin/scheduler.rs +++ b/crates/router/src/bin/scheduler.rs @@ -1,5 +1,5 @@ #![recursion_limit = "256"] -use std::{str::FromStr, sync::Arc}; +use std::{collections::HashMap, str::FromStr, sync::Arc}; use actix_web::{dev::Server, web, Scope}; use api_models::health_check::SchedulerHealthCheckResponse; @@ -22,7 +22,7 @@ use router_env::{ }; use scheduler::{ consumer::workflows::ProcessTrackerWorkflow, errors::ProcessTrackerError, - workflows::ProcessTrackerWorkflows, SchedulerAppState, + workflows::ProcessTrackerWorkflows, SchedulerSessionState, }; use storage_impl::errors::ApplicationError; use tokio::sync::{mpsc, oneshot}; @@ -146,24 +146,54 @@ pub async fn deep_health_check( state: web::Data, service: web::Data, ) -> impl actix_web::Responder { - let report = deep_health_check_func(state, service).await; - match report { - Ok(response) => services::http_response_json( - serde_json::to_string(&response) - .map_err(|err| { - logger::error!(serialization_error=?err); - }) - .unwrap_or_default(), - ), - Err(err) => api::log_and_return_error_response(err), + let mut checks = HashMap::new(); + let stores = state.stores.clone(); + let app_state = Arc::clone(&state.into_inner()); + let service_name = service.into_inner(); + for (tenant, _) in stores { + let session_state_res = app_state.clone().get_session_state(&tenant, || { + errors::ApiErrorResponse::MissingRequiredField { + field_name: "tenant_id", + } + .into() + }); + let session_state = match session_state_res { + Ok(state) => state, + Err(err) => { + return api::log_and_return_error_response(err); + } + }; + let report = deep_health_check_func(session_state, &service_name).await; + match report { + Ok(response) => { + checks.insert( + tenant, + serde_json::to_string(&response) + .map_err(|err| { + logger::error!(serialization_error=?err); + }) + .unwrap_or_default(), + ); + } + Err(err) => { + return api::log_and_return_error_response(err); + } + } } + services::http_response_json( + serde_json::to_string(&checks) + .map_err(|err| { + logger::error!(serialization_error=?err); + }) + .unwrap_or_default(), + ) } #[instrument(skip_all)] pub async fn deep_health_check_func( - state: web::Data, - service: web::Data, + state: routes::SessionState, + service: &str, ) -> errors::RouterResult { - logger::info!("{} deep health check was called", service.into_inner()); + logger::info!("{} deep health check was called", service); logger::debug!("Database health check begin"); @@ -215,10 +245,10 @@ pub async fn deep_health_check_func( pub struct WorkflowRunner; #[async_trait::async_trait] -impl ProcessTrackerWorkflows for WorkflowRunner { +impl ProcessTrackerWorkflows for WorkflowRunner { async fn trigger_workflow<'a>( &'a self, - state: &'a routes::AppState, + state: &'a routes::SessionState, process: storage::ProcessTracker, ) -> CustomResult<(), ProcessTrackerError> { let runner = process @@ -233,7 +263,7 @@ impl ProcessTrackerWorkflows for WorkflowRunner { .attach_printable("Failed to parse workflow runner name")?; let get_operation = |runner: storage::ProcessTrackerRunner| -> CustomResult< - Box>, + Box>, ProcessTrackerError, > { match runner { @@ -286,7 +316,7 @@ impl ProcessTrackerWorkflows for WorkflowRunner { let operation = get_operation(runner)?; let app_state = &state.clone(); - let output = operation.execute_workflow(app_state, process.clone()).await; + let output = operation.execute_workflow(state, process.clone()).await; match output { Ok(_) => operation.success_handler(app_state, process).await, Err(error) => match operation @@ -327,6 +357,10 @@ async fn start_scheduler( Arc::new(scheduler_settings), channel, WorkflowRunner {}, + |state, tenant| { + Arc::new(state.clone()) + .get_session_state(tenant, || ProcessTrackerError::TenantNotFound.into()) + }, ) .await } diff --git a/crates/router/src/compatibility/stripe/customers.rs b/crates/router/src/compatibility/stripe/customers.rs index 67c0f973b969..65abb012b9a7 100644 --- a/crates/router/src/compatibility/stripe/customers.rs +++ b/crates/router/src/compatibility/stripe/customers.rs @@ -155,7 +155,7 @@ pub async fn customer_delete( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth: auth::AuthenticationData, req, _| { customers::delete_customer(state, auth.merchant_account, req, auth.key_store) }, &auth::ApiKeyAuth, diff --git a/crates/router/src/compatibility/stripe/errors.rs b/crates/router/src/compatibility/stripe/errors.rs index 528381061cf5..17fcea9b828f 100644 --- a/crates/router/src/compatibility/stripe/errors.rs +++ b/crates/router/src/compatibility/stripe/errors.rs @@ -264,6 +264,8 @@ pub enum StripeErrorCode { PaymentMethodDeleteFailed, #[error(error_type = StripeErrorType::InvalidRequestError, code = "", message = "Extended card info does not exist")] ExtendedCardInfoNotFound, + #[error(error_type = StripeErrorType::InvalidRequestError, code = "IR_28", message = "Invalid tenant")] + InvalidTenant, // [#216]: https://github.com/juspay/hyperswitch/issues/216 // Implement the remaining stripe error codes @@ -646,6 +648,8 @@ impl From for StripeErrorCode { Self::InvalidWalletToken { wallet_name } } errors::ApiErrorResponse::ExtendedCardInfoNotFound => Self::ExtendedCardInfoNotFound, + errors::ApiErrorResponse::InvalidTenant { tenant_id: _ } + | errors::ApiErrorResponse::MissingTenantId => Self::InvalidTenant, } } } @@ -725,7 +729,8 @@ impl actix_web::ResponseError for StripeErrorCode { | Self::InternalServerError | Self::MandateActive | Self::CustomerRedacted - | Self::WebhookProcessingError => StatusCode::INTERNAL_SERVER_ERROR, + | Self::WebhookProcessingError + | Self::InvalidTenant => StatusCode::INTERNAL_SERVER_ERROR, Self::ReturnUrlUnavailable => StatusCode::SERVICE_UNAVAILABLE, Self::ExternalConnectorError { status_code, .. } => { StatusCode::from_u16(*status_code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR) diff --git a/crates/router/src/compatibility/wrap.rs b/crates/router/src/compatibility/wrap.rs index 96163727da37..b6012c425a58 100644 --- a/crates/router/src/compatibility/wrap.rs +++ b/crates/router/src/compatibility/wrap.rs @@ -10,7 +10,7 @@ use crate::{ events::api_logs::ApiEventMetric, routes::{ app::{AppStateInfo, ReqState}, - metrics, AppState, + metrics, AppState, SessionState, }, services::{self, api, authentication as auth, logger}, }; @@ -22,11 +22,11 @@ pub async fn compatibility_api_wrap<'a, 'b, U, T, Q, F, Fut, S, E, E2>( request: &'a HttpRequest, payload: T, func: F, - api_authentication: &dyn auth::AuthenticateAndFetch, + api_authentication: &dyn auth::AuthenticateAndFetch, lock_action: api_locking::LockAction, ) -> HttpResponse where - F: Fn(AppState, U, T, ReqState) -> Fut, + F: Fn(SessionState, U, T, ReqState) -> Fut, Fut: Future, E2>>, E2: ErrorSwitch + std::error::Error + Send + Sync + 'static, Q: Serialize + std::fmt::Debug + 'a + ApiEventMetric, @@ -49,6 +49,7 @@ where api::server_wrap_util( &flow, state.clone().into(), + request.headers(), req_state, request, payload, diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs index 77f424d8333a..c989e4c04c0d 100644 --- a/crates/router/src/configs/defaults.rs +++ b/crates/router/src/configs/defaults.rs @@ -11,7 +11,6 @@ impl Default for super::settings::Server { workers: num_cpus::get_physical(), host: "localhost".into(), request_body_limit: 16 * 1024, // POST request body is limited to 16KiB - base_url: "http://localhost:8080".into(), shutdown_timeout: 30, } } diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index dc8b5dd6bd53..2f90833905e6 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -367,5 +367,6 @@ pub(crate) async fn fetch_raw_secrets( cors: conf.cors, unmasked_headers: conf.unmasked_headers, saved_payment_methods: conf.saved_payment_methods, + multitenancy: conf.multitenancy, } } diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 8ac27cce3189..c71ed4496b08 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -120,9 +120,49 @@ pub struct Settings { #[cfg(feature = "olap")] pub connector_onboarding: SecretStateContainer, pub unmasked_headers: UnmaskedHeaders, + pub multitenancy: Multitenancy, pub saved_payment_methods: EligiblePaymentMethods, } +#[derive(Debug, Deserialize, Clone, Default)] +pub struct Multitenancy { + pub tenants: TenantConfig, + pub enabled: bool, +} + +impl Multitenancy { + pub fn get_tenants(&self) -> &HashMap { + &self.tenants.0 + } + pub fn get_tenant_names(&self) -> Vec { + self.tenants.0.keys().cloned().collect() + } + pub fn get_tenant(&self, tenant_id: &str) -> Option<&Tenant> { + self.tenants.0.get(tenant_id) + } +} + +#[derive(Debug, Deserialize, Clone, Default)] +#[serde(transparent)] +pub struct TenantConfig(pub HashMap); + +#[derive(Debug, Deserialize, Clone, Default)] +pub struct Tenant { + pub name: String, + pub base_url: String, + pub schema: String, + pub redis_key_prefix: String, +} + +impl storage_impl::config::TenantConfig for Tenant { + fn get_schema(&self) -> &str { + self.schema.as_str() + } + fn get_redis_key_prefix(&self) -> &str { + self.redis_key_prefix.as_str() + } +} + #[derive(Debug, Deserialize, Clone, Default)] pub struct UnmaskedHeaders { #[serde(deserialize_with = "deserialize_hashset")] @@ -447,7 +487,6 @@ pub struct Server { pub workers: usize, pub host: String, pub request_body_limit: usize, - pub base_url: String, pub shutdown_timeout: u64, } diff --git a/crates/router/src/connector/nuvei.rs b/crates/router/src/connector/nuvei.rs index bc556336c3ce..132311f87844 100644 --- a/crates/router/src/connector/nuvei.rs +++ b/crates/router/src/connector/nuvei.rs @@ -526,7 +526,7 @@ impl ConnectorIntegration CustomResult<(), errors::ConnectorError> { let integ: Box< &(dyn ConnectorIntegration< diff --git a/crates/router/src/connector/shift4.rs b/crates/router/src/connector/shift4.rs index 6c54c7019c83..f314d621de41 100644 --- a/crates/router/src/connector/shift4.rs +++ b/crates/router/src/connector/shift4.rs @@ -216,7 +216,7 @@ impl ConnectorIntegration CustomResult<(), errors::ConnectorError> { if router_data.auth_type == enums::AuthenticationType::ThreeDs && router_data.payment_method == enums::PaymentMethod::Card diff --git a/crates/router/src/connector/square.rs b/crates/router/src/connector/square.rs index f9a81031b07a..4e0812d16124 100644 --- a/crates/router/src/connector/square.rs +++ b/crates/router/src/connector/square.rs @@ -196,7 +196,7 @@ impl async fn execute_pretasks( &self, router_data: &mut types::TokenizationRouterData, - app_state: &crate::routes::AppState, + app_state: &crate::routes::SessionState, ) -> CustomResult<(), errors::ConnectorError> { let integ: Box< &(dyn ConnectorIntegration< diff --git a/crates/router/src/connector/wise.rs b/crates/router/src/connector/wise.rs index 667e182b674b..763adca1eeec 100644 --- a/crates/router/src/connector/wise.rs +++ b/crates/router/src/connector/wise.rs @@ -506,7 +506,7 @@ impl services::ConnectorIntegration, - app_state: &routes::AppState, + app_state: &routes::SessionState, ) -> CustomResult<(), errors::ConnectorError> { // Create a quote let quote_router_data = diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index bac825a341c7..6b582c2c9579 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -26,7 +26,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services::{self, api as service_api}, types::{ self, api, @@ -50,7 +50,7 @@ pub fn create_merchant_publishable_key() -> String { } pub async fn create_merchant_account( - state: AppState, + state: SessionState, req: api::MerchantAccountCreate, ) -> RouterResponse { let db = state.store.as_ref(); @@ -287,7 +287,7 @@ pub async fn create_merchant_account( #[cfg(feature = "olap")] pub async fn list_merchant_account( - state: AppState, + state: SessionState, req: api_models::admin::MerchantAccountListRequest, ) -> RouterResponse> { let merchant_accounts = state @@ -311,7 +311,7 @@ pub async fn list_merchant_account( } pub async fn get_merchant_account( - state: AppState, + state: SessionState, req: api::MerchantId, ) -> RouterResponse { let db = state.store.as_ref(); @@ -399,7 +399,7 @@ pub async fn create_business_profile_from_business_labels( /// For backwards compatibility /// If any of the fields of merchant account are updated, then update these fields in business profiles pub async fn update_business_profile_cascade( - state: AppState, + state: SessionState, merchant_account_update: api::MerchantAccountUpdate, merchant_id: String, ) -> RouterResult<()> { @@ -463,7 +463,7 @@ pub async fn update_business_profile_cascade( } pub async fn merchant_account_update( - state: AppState, + state: SessionState, merchant_id: &String, req: api::MerchantAccountUpdate, ) -> RouterResponse { @@ -617,7 +617,7 @@ pub async fn merchant_account_update( } pub async fn merchant_account_delete( - state: AppState, + state: SessionState, merchant_id: String, ) -> RouterResponse { let mut is_deleted = false; @@ -733,7 +733,7 @@ fn validate_certificate_in_mca_metadata( } pub async fn create_payment_connector( - state: AppState, + state: SessionState, req: api::MerchantConnectorCreate, merchant_id: &String, ) -> RouterResponse { @@ -1084,7 +1084,7 @@ async fn validate_pm_auth( } pub async fn retrieve_payment_connector( - state: AppState, + state: SessionState, merchant_id: String, merchant_connector_id: String, ) -> RouterResponse { @@ -1117,7 +1117,7 @@ pub async fn retrieve_payment_connector( } pub async fn list_payment_connectors( - state: AppState, + state: SessionState, merchant_id: String, ) -> RouterResponse> { let store = state.store.as_ref(); @@ -1154,7 +1154,7 @@ pub async fn list_payment_connectors( } pub async fn update_payment_connector( - state: AppState, + state: SessionState, merchant_id: &str, merchant_connector_id: &str, req: api_models::admin::MerchantConnectorUpdate, @@ -1305,7 +1305,7 @@ pub async fn update_payment_connector( } pub async fn delete_payment_connector( - state: AppState, + state: SessionState, merchant_id: String, merchant_connector_id: String, ) -> RouterResponse { @@ -1350,7 +1350,7 @@ pub async fn delete_payment_connector( } pub async fn kv_for_merchant( - state: AppState, + state: SessionState, merchant_id: String, enable: bool, ) -> RouterResponse { @@ -1417,7 +1417,7 @@ pub async fn kv_for_merchant( } pub async fn toggle_kv_for_all_merchants( - state: AppState, + state: SessionState, enable: bool, ) -> RouterResponse { let db = state.store.as_ref(); @@ -1447,7 +1447,7 @@ pub async fn toggle_kv_for_all_merchants( } pub async fn check_merchant_account_kv_status( - state: AppState, + state: SessionState, merchant_id: String, ) -> RouterResponse { let db = state.store.as_ref(); @@ -1519,7 +1519,7 @@ pub async fn create_and_insert_business_profile( } pub async fn create_business_profile( - state: AppState, + state: SessionState, request: api::BusinessProfileCreate, merchant_id: &str, ) -> RouterResponse { @@ -1566,7 +1566,7 @@ pub async fn create_business_profile( } pub async fn list_business_profile( - state: AppState, + state: SessionState, merchant_id: String, ) -> RouterResponse> { let db = state.store.as_ref(); @@ -1586,7 +1586,7 @@ pub async fn list_business_profile( } pub async fn retrieve_business_profile( - state: AppState, + state: SessionState, profile_id: String, ) -> RouterResponse { let db = state.store.as_ref(); @@ -1604,7 +1604,7 @@ pub async fn retrieve_business_profile( } pub async fn delete_business_profile( - state: AppState, + state: SessionState, profile_id: String, merchant_id: &str, ) -> RouterResponse { @@ -1620,7 +1620,7 @@ pub async fn delete_business_profile( } pub async fn update_business_profile( - state: AppState, + state: SessionState, profile_id: &str, merchant_id: &str, request: api::BusinessProfileUpdate, @@ -1738,7 +1738,7 @@ pub async fn update_business_profile( } pub async fn extended_card_info_toggle( - state: AppState, + state: SessionState, profile_id: &str, ext_card_info_choice: admin_types::ExtendedCardInfoChoice, ) -> RouterResponse { @@ -1771,7 +1771,7 @@ pub async fn extended_card_info_toggle( } pub async fn connector_agnostic_mit_toggle( - state: AppState, + state: SessionState, merchant_id: &str, profile_id: &str, connector_agnostic_mit_choice: admin_types::ConnectorAgnosticMitChoice, @@ -2085,7 +2085,7 @@ pub(crate) fn validate_auth_and_metadata_type( #[cfg(feature = "dummy_connector")] pub async fn validate_dummy_connector_enabled( - state: &AppState, + state: &SessionState, connector_name: &api_enums::Connector, ) -> Result<(), errors::ApiErrorResponse> { if !state.conf.dummy_connector.enabled diff --git a/crates/router/src/core/api_keys.rs b/crates/router/src/core/api_keys.rs index 7f2b343b9681..8fe536731d3d 100644 --- a/crates/router/src/core/api_keys.rs +++ b/crates/router/src/core/api_keys.rs @@ -9,7 +9,7 @@ use crate::{ configs::settings, consts, core::errors::{self, RouterResponse, StorageErrorExt}, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services::ApplicationResponse, types::{api, storage, transformers::ForeignInto}, utils, @@ -110,7 +110,7 @@ impl PlaintextApiKey { #[instrument(skip_all)] pub async fn create_api_key( - state: AppState, + state: SessionState, api_key: api::CreateApiKeyRequest, merchant_id: String, ) -> RouterResponse { @@ -244,7 +244,7 @@ pub async fn add_api_key_expiry_task( #[instrument(skip_all)] pub async fn retrieve_api_key( - state: AppState, + state: SessionState, merchant_id: &str, key_id: &str, ) -> RouterResponse { @@ -261,7 +261,7 @@ pub async fn retrieve_api_key( #[instrument(skip_all)] pub async fn update_api_key( - state: AppState, + state: SessionState, api_key: api::UpdateApiKeyRequest, ) -> RouterResponse { let merchant_id = api_key.merchant_id.clone(); @@ -395,7 +395,7 @@ pub async fn update_api_key_expiry_task( #[instrument(skip_all)] pub async fn revoke_api_key( - state: AppState, + state: SessionState, merchant_id: &str, key_id: &str, ) -> RouterResponse { @@ -463,7 +463,7 @@ pub async fn revoke_api_key_expiry_task( #[instrument(skip_all)] pub async fn list_api_keys( - state: AppState, + state: SessionState, merchant_id: String, limit: Option, offset: Option, diff --git a/crates/router/src/core/api_locking.rs b/crates/router/src/core/api_locking.rs index ec205f524271..8723c5fc1417 100644 --- a/crates/router/src/core/api_locking.rs +++ b/crates/router/src/core/api_locking.rs @@ -6,7 +6,7 @@ use redis_interface as redis; use router_env::{instrument, logger, tracing}; use super::errors::{self, RouterResult}; -use crate::routes::{app::AppStateInfo, lock_utils}; +use crate::routes::{app::SessionStateInfo, lock_utils}; pub const API_LOCK_PREFIX: &str = "API_LOCK"; @@ -50,7 +50,7 @@ impl LockAction { #[instrument(skip_all)] pub async fn perform_locking_action(self, state: &A, merchant_id: String) -> RouterResult<()> where - A: AppStateInfo, + A: SessionStateInfo, { match self { Self::Hold { input } => { @@ -111,7 +111,7 @@ impl LockAction { #[instrument(skip_all)] pub async fn free_lock_action(self, state: &A, merchant_id: String) -> RouterResult<()> where - A: AppStateInfo, + A: SessionStateInfo, { match self { Self::Hold { input } => { diff --git a/crates/router/src/core/authentication.rs b/crates/router/src/core/authentication.rs index 7828473df607..ec799365f7a4 100644 --- a/crates/router/src/core/authentication.rs +++ b/crates/router/src/core/authentication.rs @@ -12,14 +12,14 @@ use masking::ExposeInterface; use super::errors::StorageErrorExt; use crate::{ core::{errors::ApiErrorResponse, payments as payments_core}, - routes::AppState, + routes::SessionState, types::{self as core_types, api, domain, storage}, utils::check_if_pull_mechanism_for_external_3ds_enabled_from_connector_metadata, }; #[allow(clippy::too_many_arguments)] pub async fn perform_authentication( - state: &AppState, + state: &SessionState, merchant_id: String, authentication_connector: String, payment_method_data: payments::PaymentMethodData, @@ -78,7 +78,7 @@ pub async fn perform_authentication( } pub async fn perform_post_authentication( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, business_profile: storage::BusinessProfile, authentication_id: String, @@ -117,7 +117,7 @@ pub async fn perform_post_authentication( } pub async fn perform_pre_authentication( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, card_number: cards::CardNumber, token: String, diff --git a/crates/router/src/core/authentication/utils.rs b/crates/router/src/core/authentication/utils.rs index 6128352f2bd9..ec44f299c70e 100644 --- a/crates/router/src/core/authentication/utils.rs +++ b/crates/router/src/core/authentication/utils.rs @@ -8,7 +8,7 @@ use crate::{ payments, }, errors::RouterResult, - routes::AppState, + routes::SessionState, services::{self, execute_connector_processing_step}, types::{ api, authentication::AuthenticationResponseData, domain, storage, @@ -48,7 +48,7 @@ pub fn get_connector_data_if_separate_authn_supported( } pub async fn update_trackers( - state: &AppState, + state: &SessionState, router_data: RouterData, authentication: storage::Authentication, acquirer_details: Option, @@ -171,7 +171,7 @@ impl ForeignFrom for common_enums::AttemptSt } pub async fn create_new_authentication( - state: &AppState, + state: &SessionState, merchant_id: String, authentication_connector: String, token: String, @@ -228,7 +228,7 @@ pub async fn create_new_authentication( } pub async fn do_auth_connector_call( - state: &AppState, + state: &SessionState, authentication_connector_name: String, router_data: RouterData, ) -> RouterResult> @@ -255,7 +255,7 @@ where } pub async fn get_authentication_connector_data( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, business_profile: &storage::BusinessProfile, ) -> RouterResult<( diff --git a/crates/router/src/core/blocklist.rs b/crates/router/src/core/blocklist.rs index 12a0802517c4..947acc506dff 100644 --- a/crates/router/src/core/blocklist.rs +++ b/crates/router/src/core/blocklist.rs @@ -5,13 +5,13 @@ use api_models::blocklist as api_blocklist; use crate::{ core::errors::{self, RouterResponse}, - routes::AppState, + routes::SessionState, services, types::domain, }; pub async fn add_entry_to_blocklist( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, body: api_blocklist::AddToBlocklistRequest, ) -> RouterResponse { @@ -21,7 +21,7 @@ pub async fn add_entry_to_blocklist( } pub async fn remove_entry_from_blocklist( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, body: api_blocklist::DeleteFromBlocklistRequest, ) -> RouterResponse { @@ -31,7 +31,7 @@ pub async fn remove_entry_from_blocklist( } pub async fn list_blocklist_entries( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, query: api_blocklist::ListBlocklistQuery, ) -> RouterResponse> { @@ -41,7 +41,7 @@ pub async fn list_blocklist_entries( } pub async fn toggle_blocklist_guard( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, query: api_blocklist::ToggleBlocklistQuery, ) -> RouterResponse { diff --git a/crates/router/src/core/blocklist/transformers.rs b/crates/router/src/core/blocklist/transformers.rs index a2583e5b6045..c3499445602d 100644 --- a/crates/router/src/core/blocklist/transformers.rs +++ b/crates/router/src/core/blocklist/transformers.rs @@ -111,7 +111,7 @@ async fn generate_jwe_payload_for_request( #[instrument(skip_all)] pub async fn generate_fingerprint( - state: &routes::AppState, + state: &routes::SessionState, card_number: StrongSecret, hash_key: StrongSecret, locker_choice: api_enums::LockerChoice, @@ -129,7 +129,7 @@ pub async fn generate_fingerprint( #[instrument(skip_all)] async fn call_to_locker_for_fingerprint( - state: &routes::AppState, + state: &routes::SessionState, payload: &blocklist::GenerateFingerprintRequest, locker_choice: api_enums::LockerChoice, ) -> CustomResult { diff --git a/crates/router/src/core/blocklist/utils.rs b/crates/router/src/core/blocklist/utils.rs index bc8724da8235..6c0d3fcd6c3b 100644 --- a/crates/router/src/core/blocklist/utils.rs +++ b/crates/router/src/core/blocklist/utils.rs @@ -5,7 +5,7 @@ use diesel_models::configs; use error_stack::ResultExt; use masking::StrongSecret; -use super::{errors, transformers::generate_fingerprint, AppState}; +use super::{errors, transformers::generate_fingerprint, SessionState}; use crate::{ consts, core::{ @@ -18,7 +18,7 @@ use crate::{ }; pub async fn delete_entry_from_blocklist( - state: &AppState, + state: &SessionState, merchant_id: String, request: api_blocklist::DeleteFromBlocklistRequest, ) -> RouterResult { @@ -44,7 +44,7 @@ pub async fn delete_entry_from_blocklist( } pub async fn toggle_blocklist_guard_for_merchant( - state: &AppState, + state: &SessionState, merchant_id: String, query: api_blocklist::ToggleBlocklistQuery, ) -> CustomResult { @@ -94,7 +94,7 @@ pub fn get_blocklist_guard_key(merchant_id: &str) -> String { } pub async fn list_blocklist_entries_for_merchant( - state: &AppState, + state: &SessionState, merchant_id: String, query: api_blocklist::ListBlocklistQuery, ) -> RouterResult> { @@ -138,7 +138,7 @@ fn validate_extended_card_bin(bin: &str) -> RouterResult<()> { } pub async fn insert_entry_into_blocklist( - state: &AppState, + state: &SessionState, merchant_id: String, to_block: api_blocklist::AddToBlocklistRequest, ) -> RouterResult { @@ -207,7 +207,7 @@ pub async fn insert_entry_into_blocklist( } pub async fn get_merchant_fingerprint_secret( - state: &AppState, + state: &SessionState, merchant_id: &str, ) -> RouterResult { let key = get_merchant_fingerprint_secret_key(merchant_id); @@ -246,7 +246,7 @@ fn get_merchant_fingerprint_secret_key(merchant_id: &str) -> String { async fn duplicate_check_insert_bin( bin: &str, - state: &AppState, + state: &SessionState, merchant_id: &str, data_kind: common_enums::BlocklistDataKind, ) -> RouterResult { @@ -287,7 +287,7 @@ async fn duplicate_check_insert_bin( } async fn delete_card_bin_blocklist_entry( - state: &AppState, + state: &SessionState, bin: &str, merchant_id: &str, ) -> RouterResult { @@ -301,7 +301,7 @@ async fn delete_card_bin_blocklist_entry( } pub async fn validate_data_for_blocklist( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut PaymentData, ) -> CustomResult @@ -452,7 +452,7 @@ where } pub async fn generate_payment_fingerprint( - state: &AppState, + state: &SessionState, merchant_id: String, payment_method_data: Option, ) -> CustomResult, errors::ApiErrorResponse> { diff --git a/crates/router/src/core/cache.rs b/crates/router/src/core/cache.rs index 8f3cf765e920..8cda60cf7009 100644 --- a/crates/router/src/core/cache.rs +++ b/crates/router/src/core/cache.rs @@ -3,10 +3,10 @@ use error_stack::{report, ResultExt}; use storage_impl::redis::cache::{publish_into_redact_channel, CacheKind}; use super::errors; -use crate::{routes::AppState, services}; +use crate::{routes::SessionState, services}; pub async fn invalidate( - state: AppState, + state: SessionState, key: &str, ) -> CustomResult, errors::ApiErrorResponse> { let store = state.store.as_ref(); diff --git a/crates/router/src/core/cards_info.rs b/crates/router/src/core/cards_info.rs index 4352e1808c73..bc01a786d154 100644 --- a/crates/router/src/core/cards_info.rs +++ b/crates/router/src/core/cards_info.rs @@ -21,7 +21,7 @@ fn verify_iin_length(card_iin: &str) -> Result<(), errors::ApiErrorResponse> { #[instrument(skip_all)] pub async fn retrieve_card_info( - state: routes::AppState, + state: routes::SessionState, merchant_account: domain::MerchantAccount, request: api_models::cards_info::CardsInfoRequest, ) -> RouterResponse { diff --git a/crates/router/src/core/conditional_config.rs b/crates/router/src/core/conditional_config.rs index c352e825052a..a8bc8a797dc3 100644 --- a/crates/router/src/core/conditional_config.rs +++ b/crates/router/src/core/conditional_config.rs @@ -12,14 +12,14 @@ use super::routing::helpers::{ }; use crate::{ core::errors::{self, RouterResponse}, - routes::AppState, + routes::SessionState, services::api as service_api, types::domain, utils::OptionExt, }; pub async fn upsert_conditional_config( - state: AppState, + state: SessionState, key_store: domain::MerchantKeyStore, merchant_account: domain::MerchantAccount, request: DecisionManager, @@ -149,7 +149,7 @@ pub async fn upsert_conditional_config( } pub async fn delete_conditional_config( - state: AppState, + state: SessionState, key_store: domain::MerchantKeyStore, merchant_account: domain::MerchantAccount, ) -> RouterResponse<()> { @@ -177,7 +177,7 @@ pub async fn delete_conditional_config( } pub async fn retrieve_conditional_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, ) -> RouterResponse { let db = state.store.as_ref(); diff --git a/crates/router/src/core/configs.rs b/crates/router/src/core/configs.rs index ba2303167d76..be8dfc83828d 100644 --- a/crates/router/src/core/configs.rs +++ b/crates/router/src/core/configs.rs @@ -2,12 +2,12 @@ use error_stack::ResultExt; use crate::{ core::errors::{self, utils::StorageErrorExt, RouterResponse}, - routes::AppState, + routes::SessionState, services::ApplicationResponse, types::{api, transformers::ForeignInto}, }; -pub async fn set_config(state: AppState, config: api::Config) -> RouterResponse { +pub async fn set_config(state: SessionState, config: api::Config) -> RouterResponse { let store = state.store.as_ref(); let config = store .insert_config(diesel_models::configs::ConfigNew { @@ -21,7 +21,7 @@ pub async fn set_config(state: AppState, config: api::Config) -> RouterResponse< Ok(ApplicationResponse::Json(config.foreign_into())) } -pub async fn read_config(state: AppState, key: &str) -> RouterResponse { +pub async fn read_config(state: SessionState, key: &str) -> RouterResponse { let store = state.store.as_ref(); let config = store .find_config_by_key(key) @@ -31,7 +31,7 @@ pub async fn read_config(state: AppState, key: &str) -> RouterResponse RouterResponse { let store = state.store.as_ref(); @@ -42,7 +42,7 @@ pub async fn update_config( Ok(ApplicationResponse::Json(config.foreign_into())) } -pub async fn config_delete(state: AppState, key: String) -> RouterResponse { +pub async fn config_delete(state: SessionState, key: String) -> RouterResponse { let store = state.store.as_ref(); let config = store .delete_config_by_key(&key) diff --git a/crates/router/src/core/connector_onboarding.rs b/crates/router/src/core/connector_onboarding.rs index b69b2996a6ac..d6c20cc28104 100644 --- a/crates/router/src/core/connector_onboarding.rs +++ b/crates/router/src/core/connector_onboarding.rs @@ -7,18 +7,18 @@ use crate::{ services::{authentication as auth, ApplicationResponse}, types as oss_types, utils::connector_onboarding as utils, - AppState, + SessionState, }; pub mod paypal; #[async_trait::async_trait] pub trait AccessToken { - async fn access_token(state: &AppState) -> RouterResult; + async fn access_token(state: &SessionState) -> RouterResult; } pub async fn get_action_url( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, request: api::ActionUrlRequest, _req_state: ReqState, @@ -53,7 +53,7 @@ pub async fn get_action_url( } pub async fn sync_onboarding_status( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, request: api::OnboardingSyncRequest, _req_state: ReqState, @@ -107,7 +107,7 @@ pub async fn sync_onboarding_status( } pub async fn reset_tracking_id( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, request: api::ResetTrackingIdRequest, _req_state: ReqState, diff --git a/crates/router/src/core/connector_onboarding/paypal.rs b/crates/router/src/core/connector_onboarding/paypal.rs index 616fcbdc8cc3..6f28cfcbf8ec 100644 --- a/crates/router/src/core/connector_onboarding/paypal.rs +++ b/crates/router/src/core/connector_onboarding/paypal.rs @@ -11,10 +11,10 @@ use crate::{ services::{send_request, ApplicationResponse, Request}, types::{self as oss_types, api as oss_api_types, api::connector_onboarding as types}, utils::connector_onboarding as utils, - AppState, + SessionState, }; -fn build_referral_url(state: AppState) -> String { +fn build_referral_url(state: SessionState) -> String { format!( "{}v2/customer/partner-referrals", state.conf.connectors.paypal.base_url @@ -22,7 +22,7 @@ fn build_referral_url(state: AppState) -> String { } async fn build_referral_request( - state: AppState, + state: SessionState, tracking_id: String, return_url: String, ) -> RouterResult { @@ -37,7 +37,7 @@ async fn build_referral_request( } pub async fn get_action_url_from_paypal( - state: AppState, + state: SessionState, tracking_id: String, return_url: String, ) -> RouterResult { @@ -61,7 +61,7 @@ pub async fn get_action_url_from_paypal( parsed_response.extract_action_url() } -fn merchant_onboarding_status_url(state: AppState, tracking_id: String) -> String { +fn merchant_onboarding_status_url(state: SessionState, tracking_id: String) -> String { let partner_id = state .conf .connector_onboarding @@ -78,7 +78,7 @@ fn merchant_onboarding_status_url(state: AppState, tracking_id: String) -> Strin } pub async fn sync_merchant_onboarding_status( - state: AppState, + state: SessionState, tracking_id: String, ) -> RouterResult { let access_token = utils::paypal::generate_access_token(state.clone()).await?; @@ -113,7 +113,7 @@ pub async fn sync_merchant_onboarding_status( } async fn find_paypal_merchant_by_tracking_id( - state: AppState, + state: SessionState, tracking_id: String, access_token: &oss_types::AccessToken, ) -> RouterResult> { @@ -139,7 +139,7 @@ async fn find_paypal_merchant_by_tracking_id( } pub async fn update_mca( - state: &AppState, + state: &SessionState, merchant_id: String, connector_id: String, auth_details: oss_types::ConnectorAuthType, diff --git a/crates/router/src/core/currency.rs b/crates/router/src/core/currency.rs index f2791deb7b6e..96d75098271b 100644 --- a/crates/router/src/core/currency.rs +++ b/crates/router/src/core/currency.rs @@ -5,11 +5,11 @@ use crate::{ core::errors::ApiErrorResponse, services::ApplicationResponse, utils::currency::{self, convert_currency, get_forex_rates}, - AppState, + SessionState, }; pub async fn retrieve_forex( - state: AppState, + state: SessionState, ) -> CustomResult, ApiErrorResponse> { let forex_api = state.conf.forex_api.get_inner(); Ok(ApplicationResponse::Json( @@ -27,7 +27,7 @@ pub async fn retrieve_forex( } pub async fn convert_forex( - state: AppState, + state: SessionState, amount: i64, to_currency: String, from_currency: String, diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index 1c983dcde950..ad1a292df090 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -13,7 +13,7 @@ use crate::{ payment_methods::cards, }, pii::PeekInterface, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{ api::customers, @@ -30,7 +30,7 @@ pub const REDACTED: &str = "Redacted"; #[instrument(skip(state))] pub async fn create_customer( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, mut customer_data: customers::CustomerRequest, @@ -142,7 +142,7 @@ pub async fn create_customer( #[instrument(skip(state))] pub async fn retrieve_customer( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: customers::CustomerId, @@ -172,7 +172,7 @@ pub async fn retrieve_customer( #[instrument(skip(state))] pub async fn list_customers( - state: AppState, + state: SessionState, merchant_id: String, key_store: domain::MerchantKeyStore, ) -> errors::CustomerResponse> { @@ -193,7 +193,7 @@ pub async fn list_customers( #[instrument(skip_all)] pub async fn delete_customer( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: customers::CustomerId, key_store: domain::MerchantKeyStore, @@ -348,7 +348,7 @@ pub async fn delete_customer( #[instrument(skip(state))] pub async fn update_customer( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, update_customer: customers::CustomerRequest, key_store: domain::MerchantKeyStore, diff --git a/crates/router/src/core/disputes.rs b/crates/router/src/core/disputes.rs index f608100c08a7..883612869039 100644 --- a/crates/router/src/core/disputes.rs +++ b/crates/router/src/core/disputes.rs @@ -10,7 +10,7 @@ use super::{ }; use crate::{ core::{files, payments, utils as core_utils}, - routes::AppState, + routes::SessionState, services, types::{ api::{self, disputes}, @@ -24,7 +24,7 @@ use crate::{ #[instrument(skip(state))] pub async fn retrieve_dispute( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: disputes::DisputeId, ) -> RouterResponse { @@ -41,7 +41,7 @@ pub async fn retrieve_dispute( #[instrument(skip(state))] pub async fn retrieve_disputes_list( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, constraints: api_models::disputes::DisputeListConstraints, ) -> RouterResponse> { @@ -60,7 +60,7 @@ pub async fn retrieve_disputes_list( #[instrument(skip(state))] pub async fn accept_dispute( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: disputes::DisputeId, @@ -161,7 +161,7 @@ pub async fn accept_dispute( #[instrument(skip(state))] pub async fn submit_evidence( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: dispute_models::SubmitEvidenceRequest, @@ -324,7 +324,7 @@ pub async fn submit_evidence( } pub async fn attach_evidence( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, attach_evidence_request: api::AttachEvidenceRequest, @@ -401,7 +401,7 @@ pub async fn attach_evidence( #[instrument(skip(state))] pub async fn retrieve_dispute_evidence( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: disputes::DisputeId, ) -> RouterResponse> { @@ -424,7 +424,7 @@ pub async fn retrieve_dispute_evidence( } pub async fn delete_evidence( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, delete_evidence_request: dispute_models::DeleteEvidenceRequest, ) -> RouterResponse { diff --git a/crates/router/src/core/disputes/transformers.rs b/crates/router/src/core/disputes/transformers.rs index 936184fc9937..d37410d5ef83 100644 --- a/crates/router/src/core/disputes/transformers.rs +++ b/crates/router/src/core/disputes/transformers.rs @@ -4,7 +4,7 @@ use error_stack::ResultExt; use crate::{ core::{errors, files::helpers::retrieve_file_and_provider_file_id_from_file_id}, - routes::AppState, + routes::SessionState, types::{ api::{self, DisputeEvidence}, domain, @@ -14,7 +14,7 @@ use crate::{ }; pub async fn get_evidence_request_data( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, evidence_request: api_models::disputes::SubmitEvidenceRequest, @@ -203,7 +203,7 @@ pub fn update_dispute_evidence( } pub async fn get_dispute_evidence_block( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, evidence_type: EvidenceType, file_id: String, @@ -271,7 +271,7 @@ pub fn delete_evidence_file( } pub async fn get_dispute_evidence_vec( - state: &AppState, + state: &SessionState, merchant_account: domain::MerchantAccount, dispute_evidence: DisputeEvidence, ) -> CustomResult, errors::ApiErrorResponse> { diff --git a/crates/router/src/core/files.rs b/crates/router/src/core/files.rs index 5dedcb148633..9ba5c29ce760 100644 --- a/crates/router/src/core/files.rs +++ b/crates/router/src/core/files.rs @@ -6,13 +6,13 @@ use error_stack::ResultExt; use super::errors::{self, RouterResponse}; use crate::{ consts, - routes::AppState, + routes::SessionState, services::ApplicationResponse, types::{api, domain}, }; pub async fn files_create_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, create_file_request: api::CreateFileRequest, @@ -78,7 +78,7 @@ pub async fn files_create_core( } pub async fn files_delete_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: api::FileId, ) -> RouterResponse { @@ -94,7 +94,7 @@ pub async fn files_delete_core( } pub async fn files_retrieve_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: api::FileId, diff --git a/crates/router/src/core/files/helpers.rs b/crates/router/src/core/files/helpers.rs index 0c6a88d8270c..0be198377b86 100644 --- a/crates/router/src/core/files/helpers.rs +++ b/crates/router/src/core/files/helpers.rs @@ -8,7 +8,7 @@ use crate::{ errors::{self, StorageErrorExt}, payments, utils, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, transformers::ForeignTryFrom}, }; @@ -31,7 +31,7 @@ pub async fn get_file_purpose(field: &mut Field) -> Option { } pub async fn validate_file_upload( - state: &AppState, + state: &SessionState, merchant_account: domain::MerchantAccount, create_file_request: api::CreateFileRequest, ) -> CustomResult<(), errors::ApiErrorResponse> { @@ -81,7 +81,7 @@ pub async fn validate_file_upload( } pub async fn delete_file_using_file_id( - state: &AppState, + state: &SessionState, file_key: String, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { @@ -113,7 +113,7 @@ pub async fn delete_file_using_file_id( } pub async fn retrieve_file_from_connector( - state: &AppState, + state: &SessionState, file_metadata: diesel_models::file::FileMetadata, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -171,7 +171,7 @@ pub async fn retrieve_file_from_connector( } pub async fn retrieve_file_and_provider_file_id_from_file_id( - state: &AppState, + state: &SessionState, file_id: Option, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -227,7 +227,7 @@ pub async fn retrieve_file_and_provider_file_id_from_file_id( //Upload file to connector if it supports / store it in S3 and return file_upload_provider, provider_file_id accordingly pub async fn upload_and_get_provider_provider_file_id_profile_id( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, create_file_request: &api::CreateFileRequest, diff --git a/crates/router/src/core/fraud_check.rs b/crates/router/src/core/fraud_check.rs index dddcf581296f..f7f7108c2baa 100644 --- a/crates/router/src/core/fraud_check.rs +++ b/crates/router/src/core/fraud_check.rs @@ -24,7 +24,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ self as oss_types, @@ -50,7 +50,7 @@ pub mod types; #[instrument(skip_all)] pub async fn call_frm_service( - state: &AppState, + state: &SessionState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, merchant_account: &domain::MerchantAccount, @@ -302,7 +302,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn make_frm_data_and_fraud_check_operation<'a, F>( _db: &dyn StorageInterface, - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_data: payments::PaymentData, frm_routing_algorithm: FrmRoutingAlgorithm, @@ -370,7 +370,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn pre_payment_frm_core<'a, F, Req>( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut payments::PaymentData, frm_info: &mut FrmInfo, @@ -456,7 +456,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn post_payment_frm_core<'a, F>( - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: &domain::MerchantAccount, payment_data: &mut payments::PaymentData, @@ -547,7 +547,7 @@ pub async fn call_frm_before_connector_call<'a, F, Req>( operation: &BoxedOperation<'_, F, Req>, merchant_account: &domain::MerchantAccount, payment_data: &mut payments::PaymentData, - state: &AppState, + state: &SessionState, frm_info: &mut Option>, customer: &Option, should_continue_transaction: &mut bool, @@ -643,7 +643,7 @@ impl From for PaymentDetails { #[instrument(skip_all)] pub async fn frm_fulfillment_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: frm_core_types::FrmFulfillmentRequest, @@ -705,7 +705,7 @@ pub async fn make_fulfillment_api_call( db: &dyn StorageInterface, fraud_check: FraudCheck, payment_intent: PaymentIntent, - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: frm_core_types::FrmFulfillmentRequest, diff --git a/crates/router/src/core/fraud_check/flows.rs b/crates/router/src/core/fraud_check/flows.rs index 3d4916a372be..896d062bc14c 100644 --- a/crates/router/src/core/fraud_check/flows.rs +++ b/crates/router/src/core/fraud_check/flows.rs @@ -11,7 +11,7 @@ use crate::{ errors::RouterResult, payments::{self, flows::ConstructFlowSpecificData}, }, - routes::AppState, + routes::SessionState, services, types::{ api::{Connector, FraudCheckConnectorData}, @@ -24,7 +24,7 @@ use crate::{ pub trait FeatureFrm { async fn decide_frm_flows<'a>( self, - state: &AppState, + state: &SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/flows/checkout_flow.rs b/crates/router/src/core/fraud_check/flows/checkout_flow.rs index c754682f72d5..74353e83b3d5 100644 --- a/crates/router/src/core/fraud_check/flows/checkout_flow.rs +++ b/crates/router/src/core/fraud_check/flows/checkout_flow.rs @@ -19,7 +19,7 @@ use crate::{ storage::enums as storage_enums, BrowserInformation, ConnectorAuthType, ResponseId, RouterData, }, - AppState, + SessionState, }; #[async_trait] @@ -28,7 +28,7 @@ impl ConstructFlowSpecificData( &self, - _state: &AppState, + _state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -138,7 +138,7 @@ impl ConstructFlowSpecificData for FrmCheckoutRouterData { async fn decide_frm_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, merchant_account: &domain::MerchantAccount, @@ -156,7 +156,7 @@ impl FeatureFrm for FrmCheckoutRouter pub async fn decide_frm_flow<'a, 'b>( router_data: &'b mut FrmCheckoutRouterData, - state: &'a AppState, + state: &'a SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, _merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs b/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs index 1f4f2ccebeee..f91d87c808c0 100644 --- a/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs +++ b/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs @@ -13,12 +13,12 @@ use crate::{ fraud_check::{FraudCheckFulfillmentData, FrmFulfillmentRouterData}, storage, ConnectorAuthType, ErrorResponse, PaymentAddress, RouterData, }, - utils, AppState, + utils, SessionState, }; #[instrument(skip_all)] pub async fn construct_fulfillment_router_data<'a>( - state: &'a AppState, + state: &'a SessionState, payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/flows/record_return.rs b/crates/router/src/core/fraud_check/flows/record_return.rs index b854a3337700..b8f8810f09b3 100644 --- a/crates/router/src/core/fraud_check/flows/record_return.rs +++ b/crates/router/src/core/fraud_check/flows/record_return.rs @@ -19,7 +19,7 @@ use crate::{ storage::enums as storage_enums, ConnectorAuthType, ResponseId, RouterData, }, - utils, AppState, + utils, SessionState, }; #[async_trait] @@ -28,7 +28,7 @@ impl ConstructFlowSpecificData( &self, - _state: &AppState, + _state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -110,7 +110,7 @@ impl ConstructFlowSpecificData for FrmRecordReturnRouterData { async fn decide_frm_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, merchant_account: &domain::MerchantAccount, @@ -128,7 +128,7 @@ impl FeatureFrm for FrmRecordReturnRou pub async fn decide_frm_flow<'a, 'b>( router_data: &'b mut FrmRecordReturnRouterData, - state: &'a AppState, + state: &'a SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, _merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/flows/sale_flow.rs b/crates/router/src/core/fraud_check/flows/sale_flow.rs index 829f8b736b0b..b605c5406568 100644 --- a/crates/router/src/core/fraud_check/flows/sale_flow.rs +++ b/crates/router/src/core/fraud_check/flows/sale_flow.rs @@ -17,7 +17,7 @@ use crate::{ storage::enums as storage_enums, ConnectorAuthType, ResponseId, RouterData, }, - AppState, + SessionState, }; #[async_trait] @@ -26,7 +26,7 @@ impl ConstructFlowSpecificData( &self, - _state: &AppState, + _state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -119,7 +119,7 @@ impl ConstructFlowSpecificData for FrmSaleRouterData { async fn decide_frm_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, merchant_account: &domain::MerchantAccount, @@ -137,7 +137,7 @@ impl FeatureFrm for FrmSaleRouterData { pub async fn decide_frm_flow<'a, 'b>( router_data: &'b mut FrmSaleRouterData, - state: &'a AppState, + state: &'a SessionState, connector: &FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, _merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/flows/transaction_flow.rs b/crates/router/src/core/fraud_check/flows/transaction_flow.rs index 0b851d7b6263..8c496792a81e 100644 --- a/crates/router/src/core/fraud_check/flows/transaction_flow.rs +++ b/crates/router/src/core/fraud_check/flows/transaction_flow.rs @@ -18,7 +18,7 @@ use crate::{ storage::enums as storage_enums, ConnectorAuthType, ResponseId, RouterData, }, - AppState, + SessionState, }; #[async_trait] @@ -31,7 +31,7 @@ impl { async fn construct_router_data<'a>( &self, - _state: &AppState, + _state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -123,7 +123,7 @@ impl impl FeatureFrm for FrmTransactionRouterData { async fn decide_frm_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &frm_api::FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, merchant_account: &domain::MerchantAccount, @@ -141,7 +141,7 @@ impl FeatureFrm for FrmTransact pub async fn decide_frm_flow<'a, 'b>( router_data: &'b mut FrmTransactionRouterData, - state: &'a AppState, + state: &'a SessionState, connector: &frm_api::FraudCheckConnectorData, call_connector_action: payments::CallConnectorAction, _merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/operation.rs b/crates/router/src/core/fraud_check/operation.rs index a9b95cdf3b5e..33a370ac8499 100644 --- a/crates/router/src/core/fraud_check/operation.rs +++ b/crates/router/src/core/fraud_check/operation.rs @@ -15,7 +15,7 @@ use crate::{ payments, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, types::{domain, fraud_check::FrmRouterData}, }; @@ -40,7 +40,7 @@ pub trait FraudCheckOperation: Send + std::fmt::Debug { pub trait GetTracker: Send { async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: D, frm_connector_details: ConnectorDetailsCore, ) -> RouterResult>; @@ -51,7 +51,7 @@ pub trait GetTracker: Send { pub trait Domain: Send + Sync { async fn post_payment_frm<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, req_state: ReqState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, @@ -64,7 +64,7 @@ pub trait Domain: Send + Sync { async fn pre_payment_frm<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, merchant_account: &domain::MerchantAccount, @@ -79,7 +79,7 @@ pub trait Domain: Send + Sync { #[allow(clippy::too_many_arguments)] async fn execute_post_tasks( &self, - _state: &AppState, + _state: &SessionState, _req_state: ReqState, frm_data: &mut FrmData, _merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/operation/fraud_check_post.rs b/crates/router/src/core/fraud_check/operation/fraud_check_post.rs index 6a310aa131dd..cc4fc0370e97 100644 --- a/crates/router/src/core/fraud_check/operation/fraud_check_post.rs +++ b/crates/router/src/core/fraud_check/operation/fraud_check_post.rs @@ -38,7 +38,7 @@ use crate::{ }, ResponseId, }, - utils, AppState, + utils, SessionState, }; #[derive(Debug, Clone, Copy)] @@ -73,7 +73,7 @@ impl GetTracker for FraudCheckPost { #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: PaymentToFrmData, frm_connector_details: ConnectorDetailsCore, ) -> RouterResult> { @@ -142,7 +142,7 @@ impl Domain for FraudCheckPost { #[instrument(skip_all)] async fn post_payment_frm<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, _req_state: ReqState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, @@ -182,7 +182,7 @@ impl Domain for FraudCheckPost { #[instrument(skip_all)] async fn execute_post_tasks( &self, - state: &AppState, + state: &SessionState, req_state: ReqState, frm_data: &mut FrmData, merchant_account: &domain::MerchantAccount, @@ -293,7 +293,7 @@ impl Domain for FraudCheckPost { #[instrument(skip_all)] async fn pre_payment_frm<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs b/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs index ae316e7a1108..272cd5aa7044 100644 --- a/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs +++ b/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs @@ -32,7 +32,7 @@ use crate::{ }, ResponseId, }, - AppState, + SessionState, }; #[derive(Debug, Clone, Copy)] @@ -67,7 +67,7 @@ impl GetTracker for FraudCheckPre { #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: PaymentToFrmData, frm_connector_details: ConnectorDetailsCore, ) -> RouterResult> { @@ -139,7 +139,7 @@ impl Domain for FraudCheckPre { #[instrument(skip_all)] async fn post_payment_frm<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, _req_state: ReqState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, @@ -178,7 +178,7 @@ impl Domain for FraudCheckPre { async fn pre_payment_frm<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut payments::PaymentData, frm_data: &mut FrmData, merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/gsm.rs b/crates/router/src/core/gsm.rs index 668c1773e2cd..4a678a5c4089 100644 --- a/crates/router/src/core/gsm.rs +++ b/crates/router/src/core/gsm.rs @@ -11,12 +11,12 @@ use crate::{ db::gsm::GsmInterface, services, types::transformers::ForeignInto, - AppState, + SessionState, }; #[instrument(skip_all)] pub async fn create_gsm_rule( - state: AppState, + state: SessionState, gsm_rule: gsm_api_types::GsmCreateRequest, ) -> RouterResponse { let db = state.store.as_ref(); @@ -30,7 +30,7 @@ pub async fn create_gsm_rule( #[instrument(skip_all)] pub async fn retrieve_gsm_rule( - state: AppState, + state: SessionState, gsm_request: gsm_api_types::GsmRetrieveRequest, ) -> RouterResponse { let db = state.store.as_ref(); @@ -51,7 +51,7 @@ pub async fn retrieve_gsm_rule( #[instrument(skip_all)] pub async fn update_gsm_rule( - state: AppState, + state: SessionState, gsm_request: gsm_api_types::GsmUpdateRequest, ) -> RouterResponse { let db = state.store.as_ref(); @@ -94,7 +94,7 @@ pub async fn update_gsm_rule( #[instrument(skip_all)] pub async fn delete_gsm_rule( - state: AppState, + state: SessionState, gsm_request: gsm_api_types::GsmDeleteRequest, ) -> RouterResponse { let db = state.store.as_ref(); diff --git a/crates/router/src/core/health_check.rs b/crates/router/src/core/health_check.rs index e90fe77e8087..6092ac8bbb98 100644 --- a/crates/router/src/core/health_check.rs +++ b/crates/router/src/core/health_check.rs @@ -31,7 +31,7 @@ pub trait HealthCheckInterface { } #[async_trait::async_trait] -impl HealthCheckInterface for app::AppState { +impl HealthCheckInterface for app::SessionState { async fn health_check_db(&self) -> CustomResult { let db = &*self.store; db.health_check_db().await?; diff --git a/crates/router/src/core/locker_migration.rs b/crates/router/src/core/locker_migration.rs index 9dbc54287484..d968e62bea88 100644 --- a/crates/router/src/core/locker_migration.rs +++ b/crates/router/src/core/locker_migration.rs @@ -7,13 +7,13 @@ use futures::TryFutureExt; use super::{errors::StorageErrorExt, payment_methods::cards}; use crate::{ errors, - routes::AppState, + routes::SessionState, services::{self, logger}, types::{api, domain}, }; pub async fn rust_locker_migration( - state: AppState, + state: SessionState, merchant_id: &str, ) -> CustomResult, errors::ApiErrorResponse> { let db = state.store.as_ref(); @@ -75,7 +75,7 @@ pub async fn rust_locker_migration( } pub async fn call_to_locker( - state: &AppState, + state: &SessionState, payment_methods: Vec, customer_id: &id_type::CustomerId, merchant_id: &str, @@ -140,6 +140,7 @@ pub async fn call_to_locker( merchant_account, api_enums::LockerChoice::HyperswitchCardVault, Some(pm.locker_id.as_ref().unwrap_or(&pm.payment_method_id)), + ) .await .change_context(errors::ApiErrorResponse::InternalServerError) diff --git a/crates/router/src/core/mandate.rs b/crates/router/src/core/mandate.rs index 839f55dea2db..f484467f3547 100644 --- a/crates/router/src/core/mandate.rs +++ b/crates/router/src/core/mandate.rs @@ -14,7 +14,7 @@ use crate::{ payments::CallConnectorAction, }, db::StorageInterface, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{ self, @@ -32,7 +32,7 @@ use crate::{ #[instrument(skip(state))] pub async fn get_mandate( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: mandates::MandateId, @@ -60,7 +60,7 @@ pub async fn get_mandate( #[instrument(skip(state))] pub async fn revoke_mandate( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: mandates::MandateId, @@ -223,7 +223,7 @@ pub async fn update_connector_mandate_id( #[instrument(skip(state))] pub async fn get_customer_mandates( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: customers::CustomerId, @@ -271,7 +271,7 @@ where } } pub async fn update_mandate_procedure( - state: &AppState, + state: &SessionState, resp: types::RouterData, mandate: Mandate, merchant_id: &str, @@ -342,7 +342,7 @@ where } pub async fn mandate_procedure( - state: &AppState, + state: &SessionState, resp: &types::RouterData, customer_id: &Option, pm_id: Option, @@ -472,7 +472,7 @@ where #[instrument(skip(state))] pub async fn retrieve_mandates_list( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, constraints: api_models::mandates::MandateListConstraints, diff --git a/crates/router/src/core/mandate/helpers.rs b/crates/router/src/core/mandate/helpers.rs index 4e9d07b7f828..b0c727925df5 100644 --- a/crates/router/src/core/mandate/helpers.rs +++ b/crates/router/src/core/mandate/helpers.rs @@ -7,12 +7,12 @@ use hyperswitch_domain_models::mandates::MandateData; use crate::{ core::{errors, payments}, - routes::AppState, + routes::SessionState, types::{api, domain}, }; pub async fn get_profile_id_for_mandate( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, mandate: Mandate, ) -> CustomResult { diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 9b8fd3cbe0ef..e4ef38ae3512 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -14,7 +14,7 @@ use time::PrimitiveDateTime; use super::errors::{self, RouterResult, StorageErrorExt}; use crate::{ errors::RouterResponse, - routes::AppState, + routes::SessionState, services, types::{ api::payment_link::PaymentLinkResponseExt, domain, storage::enums as storage_enums, @@ -23,7 +23,7 @@ use crate::{ }; pub async fn retrieve_payment_link( - state: AppState, + state: SessionState, payment_link_id: String, ) -> RouterResponse { let db = &*state.store; @@ -47,7 +47,7 @@ pub async fn retrieve_payment_link( } pub async fn initiate_payment_link_flow( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, merchant_id: String, payment_id: String, @@ -287,7 +287,7 @@ fn validate_sdk_requirements( } pub async fn list_payment_link( - state: AppState, + state: SessionState, merchant: domain::MerchantAccount, constraints: api_models::payments::PaymentLinkListConstraints, ) -> RouterResponse> { @@ -501,7 +501,7 @@ fn check_payment_link_invalid_conditions( } pub async fn get_payment_link_status( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, merchant_id: String, payment_id: String, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 71f0bdac03a9..b6d95248abc6 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -13,7 +13,7 @@ use router_env::{instrument, tracing}; use crate::{ core::{errors::RouterResult, payments::helpers, pm_auth as core_pm_auth}, - routes::AppState, + routes::SessionState, types::{ api::{self, payments}, domain, storage, @@ -23,7 +23,7 @@ use crate::{ #[instrument(skip_all)] pub async fn retrieve_payment_method( pm_data: &Option, - state: &AppState, + state: &SessionState, payment_intent: &PaymentIntent, payment_attempt: &PaymentAttempt, merchant_key_store: &domain::MerchantKeyStore, @@ -95,7 +95,7 @@ pub async fn retrieve_payment_method( #[instrument(skip_all)] pub async fn retrieve_payment_method_with_token( - state: &AppState, + state: &SessionState, merchant_key_store: &domain::MerchantKeyStore, token_data: &storage::PaymentTokenData, payment_intent: &PaymentIntent, diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index 66a695b2b0c5..c62f47b5362b 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -263,7 +263,7 @@ pub async fn get_or_insert_payment_method( #[instrument(skip_all)] pub async fn get_client_secret_or_add_payment_method( - state: routes::AppState, + state: routes::SessionState, req: api::PaymentMethodCreate, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -337,7 +337,7 @@ pub fn authenticate_pm_client_secret_and_check_expiry( #[instrument(skip_all)] pub async fn add_payment_method_data( - state: routes::AppState, + state: routes::SessionState, req: api::PaymentMethodCreate, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -513,7 +513,7 @@ pub async fn add_payment_method_data( #[instrument(skip_all)] pub async fn add_payment_method( - state: routes::AppState, + state: routes::SessionState, req: api::PaymentMethodCreate, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -761,7 +761,7 @@ pub async fn insert_payment_method( #[instrument(skip_all)] pub async fn update_customer_payment_method( - state: routes::AppState, + state: routes::SessionState, merchant_account: domain::MerchantAccount, req: api::PaymentMethodUpdate, payment_method_id: &str, @@ -1017,7 +1017,7 @@ pub fn validate_payment_method_update( #[cfg(feature = "payouts")] pub async fn add_bank_to_locker( - state: &routes::AppState, + state: &routes::SessionState, req: api::PaymentMethodCreate, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -1082,7 +1082,7 @@ pub async fn add_bank_to_locker( /// The response will be the tuple of PaymentMethodResponse and the duplication check of payment_method pub async fn add_card_to_locker( - state: &routes::AppState, + state: &routes::SessionState, req: api::PaymentMethodCreate, card: &api::CardDetail, customer_id: &id_type::CustomerId, @@ -1130,7 +1130,7 @@ pub async fn add_card_to_locker( } pub async fn get_card_from_locker( - state: &routes::AppState, + state: &routes::SessionState, customer_id: &id_type::CustomerId, merchant_id: &str, card_reference: &str, @@ -1171,7 +1171,7 @@ pub async fn get_card_from_locker( } pub async fn delete_card_from_locker( - state: &routes::AppState, + state: &routes::SessionState, customer_id: &id_type::CustomerId, merchant_id: &str, card_reference: &str, @@ -1195,7 +1195,7 @@ pub async fn delete_card_from_locker( #[instrument(skip_all)] pub async fn add_card_hs( - state: &routes::AppState, + state: &routes::SessionState, req: api::PaymentMethodCreate, card: &api::CardDetail, customer_id: &id_type::CustomerId, @@ -1259,7 +1259,7 @@ pub async fn decode_and_decrypt_locker_data( #[instrument(skip_all)] pub async fn get_payment_method_from_hs_locker<'a>( - state: &'a routes::AppState, + state: &'a routes::SessionState, key_store: &domain::MerchantKeyStore, customer_id: &id_type::CustomerId, merchant_id: &str, @@ -1321,7 +1321,7 @@ pub async fn get_payment_method_from_hs_locker<'a>( #[instrument(skip_all)] pub async fn call_to_locker_hs<'a>( - state: &routes::AppState, + state: &routes::SessionState, payload: &payment_methods::StoreLockerReq<'a>, customer_id: &id_type::CustomerId, locker_choice: api_enums::LockerChoice, @@ -1394,7 +1394,7 @@ pub async fn update_payment_method_connector_mandate_details( } #[instrument(skip_all)] pub async fn get_card_from_hs_locker<'a>( - state: &'a routes::AppState, + state: &'a routes::SessionState, customer_id: &id_type::CustomerId, merchant_id: &str, card_reference: &'a str, @@ -1447,7 +1447,7 @@ pub async fn get_card_from_hs_locker<'a>( #[instrument(skip_all)] pub async fn delete_card_from_hs_locker<'a>( - state: &routes::AppState, + state: &routes::SessionState, customer_id: &id_type::CustomerId, merchant_id: &str, card_reference: &'a str, @@ -1652,7 +1652,7 @@ pub async fn mock_delete_card<'a>( } //------------------------------------------------------------------------------ pub fn get_banks( - state: &routes::AppState, + state: &routes::SessionState, pm_type: common_enums::enums::PaymentMethodType, connectors: Vec, ) -> Result, errors::ApiErrorResponse> { @@ -1734,7 +1734,7 @@ fn get_val(str: String, val: &serde_json::Value) -> Option { } pub async fn list_payment_methods( - state: routes::AppState, + state: routes::SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, mut req: api::PaymentMethodListRequest, @@ -2660,7 +2660,7 @@ async fn validate_payment_method_and_client_secret( } pub async fn call_surcharge_decision_management( - state: routes::AppState, + state: routes::SessionState, merchant_account: &domain::MerchantAccount, business_profile: &BusinessProfile, payment_attempt: &storage::PaymentAttempt, @@ -2710,7 +2710,7 @@ pub async fn call_surcharge_decision_management( } pub async fn call_surcharge_decision_management_for_saved_card( - state: &routes::AppState, + state: &routes::SessionState, merchant_account: &domain::MerchantAccount, business_profile: &BusinessProfile, payment_attempt: &storage::PaymentAttempt, @@ -3313,7 +3313,7 @@ async fn filter_payment_mandate_based( } pub async fn do_list_customer_pm_fetch_customer_if_not_passed( - state: routes::AppState, + state: routes::SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: Option, @@ -3369,7 +3369,7 @@ pub async fn do_list_customer_pm_fetch_customer_if_not_passed( } pub async fn list_customer_payment_method( - state: &routes::AppState, + state: &routes::SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, payment_intent: Option, @@ -3684,7 +3684,7 @@ pub async fn list_customer_payment_method( Ok(services::ApplicationResponse::Json(response)) } pub async fn get_mca_status( - state: &routes::AppState, + state: &routes::SessionState, key_store: &domain::MerchantKeyStore, merchant_id: &str, connector_mandate_details: Option, @@ -3744,7 +3744,7 @@ where pub async fn get_card_details_with_locker_fallback( pm: &payment_method::PaymentMethod, key: &[u8], - state: &routes::AppState, + state: &routes::SessionState, ) -> errors::RouterResult> { let card_decrypted = decrypt::(pm.payment_method_data.clone(), key) @@ -3775,7 +3775,7 @@ pub async fn get_card_details_with_locker_fallback( pub async fn get_card_details_without_locker_fallback( pm: &payment_method::PaymentMethod, key: &[u8], - state: &routes::AppState, + state: &routes::SessionState, ) -> errors::RouterResult { let card_decrypted = decrypt::(pm.payment_method_data.clone(), key) @@ -3800,7 +3800,7 @@ pub async fn get_card_details_without_locker_fallback( } pub async fn get_card_details_from_locker( - state: &routes::AppState, + state: &routes::SessionState, pm: &storage::PaymentMethod, ) -> errors::RouterResult { let card = get_card_from_locker( @@ -3819,7 +3819,7 @@ pub async fn get_card_details_from_locker( } pub async fn get_lookup_key_from_locker( - state: &routes::AppState, + state: &routes::SessionState, payment_token: &str, pm: &storage::PaymentMethod, merchant_key_store: &domain::MerchantKeyStore, @@ -4004,7 +4004,7 @@ pub async fn set_default_payment_method( pub async fn update_last_used_at( pm_id: &str, - state: &routes::AppState, + state: &routes::SessionState, storage_scheme: MerchantStorageScheme, ) -> errors::RouterResult<()> { let update_last_used = storage::PaymentMethodUpdate::LastUsedUpdate { @@ -4026,7 +4026,7 @@ pub async fn update_last_used_at( } #[cfg(feature = "payouts")] pub async fn get_bank_from_hs_locker( - state: &routes::AppState, + state: &routes::SessionState, key_store: &domain::MerchantKeyStore, temp_token: &str, customer_id: &id_type::CustomerId, @@ -4079,7 +4079,7 @@ pub struct TempLockerCardSupport; impl TempLockerCardSupport { #[instrument(skip_all)] async fn create_payment_method_data_in_temp_locker( - state: &routes::AppState, + state: &routes::SessionState, payment_token: &str, card: api::CardDetailFromLocker, pm: &storage::PaymentMethod, @@ -4161,7 +4161,7 @@ impl TempLockerCardSupport { #[instrument(skip_all)] pub async fn retrieve_payment_method( - state: routes::AppState, + state: routes::SessionState, pm: api::PaymentMethodId, key_store: domain::MerchantKeyStore, merchant_account: domain::MerchantAccount, @@ -4217,7 +4217,7 @@ pub async fn retrieve_payment_method( #[instrument(skip_all)] pub async fn delete_payment_method( - state: routes::AppState, + state: routes::SessionState, merchant_account: domain::MerchantAccount, pm_id: api::PaymentMethodId, key_store: domain::MerchantKeyStore, @@ -4342,7 +4342,7 @@ where } pub async fn list_countries_currencies_for_connector_payment_method( - state: routes::AppState, + state: routes::SessionState, req: ListCountriesCurrenciesRequest, ) -> errors::RouterResponse { Ok(services::ApplicationResponse::Json( diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index 76881950e3bf..14beb6be1310 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -26,7 +26,7 @@ use crate::{ storage::{self, payment_attempt::PaymentAttemptExt}, transformers::ForeignTryFrom, }, - AppState, + SessionState, }; static CONF_CACHE: StaticCache = StaticCache::new(); @@ -95,7 +95,7 @@ impl SurchargeSource { } pub async fn perform_surcharge_decision_management_for_payment_method_list( - state: &AppState, + state: &SessionState, algorithm_ref: routing::RoutingAlgorithmRef, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, @@ -215,7 +215,7 @@ pub async fn perform_surcharge_decision_management_for_payment_method_list( } pub async fn perform_surcharge_decision_management_for_session_flow( - state: &AppState, + state: &SessionState, algorithm_ref: routing::RoutingAlgorithmRef, payment_data: &mut PaymentData, payment_method_type_list: &Vec, @@ -276,7 +276,7 @@ where Ok(surcharge_metadata) } pub async fn perform_surcharge_decision_management_for_saved_cards( - state: &AppState, + state: &SessionState, algorithm_ref: routing::RoutingAlgorithmRef, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index e0d8bada65ef..9e20017d57fb 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -818,7 +818,7 @@ pub struct Vault; impl Vault { #[instrument(skip_all)] pub async fn get_payment_method_data_from_locker( - state: &routes::AppState, + state: &routes::SessionState, lookup_key: &str, merchant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(Option, SupplementaryVaultData)> { @@ -834,7 +834,7 @@ impl Vault { #[instrument(skip_all)] pub async fn store_payment_method_data_in_locker( - state: &routes::AppState, + state: &routes::SessionState, token_id: Option, payment_method: &api::PaymentMethodData, customer_id: Option, @@ -869,7 +869,7 @@ impl Vault { #[cfg(feature = "payouts")] #[instrument(skip_all)] pub async fn get_payout_method_data_from_temporary_locker( - state: &routes::AppState, + state: &routes::SessionState, lookup_key: &str, merchant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(Option, SupplementaryVaultData)> { @@ -886,7 +886,7 @@ impl Vault { #[cfg(feature = "payouts")] #[instrument(skip_all)] pub async fn store_payout_method_data_in_locker( - state: &routes::AppState, + state: &routes::SessionState, token_id: Option, payout_method: &api::PayoutMethodData, customer_id: Option, @@ -920,7 +920,7 @@ impl Vault { #[instrument(skip_all)] pub async fn delete_locker_payment_method_by_lookup_key( - state: &routes::AppState, + state: &routes::SessionState, lookup_key: &Option, ) { if let Some(lookup_key) = lookup_key { @@ -942,7 +942,7 @@ fn get_redis_locker_key(lookup_key: &str) -> String { #[instrument(skip(state, value1, value2))] pub async fn create_tokenize( - state: &routes::AppState, + state: &routes::SessionState, value1: String, value2: Option, lookup_key: String, @@ -1007,7 +1007,7 @@ pub async fn create_tokenize( #[instrument(skip(state))] pub async fn get_tokenized_data( - state: &routes::AppState, + state: &routes::SessionState, lookup_key: &str, _should_get_value2: bool, encryption_key: &masking::Secret>, @@ -1069,7 +1069,10 @@ pub async fn get_tokenized_data( } #[instrument(skip(state))] -pub async fn delete_tokenized_data(state: &routes::AppState, lookup_key: &str) -> RouterResult<()> { +pub async fn delete_tokenized_data( + state: &routes::SessionState, + lookup_key: &str, +) -> RouterResult<()> { let redis_key = get_redis_locker_key(lookup_key); let func = || async { metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]); @@ -1153,7 +1156,7 @@ pub async fn add_delete_tokenized_data_task( } pub async fn start_tokenize_data_workflow( - state: &routes::AppState, + state: &routes::SessionState, tokenize_tracker: &storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { let db = &*state.store; diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 3988f3d4fd0d..caaecdc8629c 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -77,7 +77,7 @@ use crate::{ }, db::StorageInterface, logger, - routes::{app::ReqState, metrics, payment_methods::ParentPaymentMethodToken, AppState}, + routes::{app::ReqState, metrics, payment_methods::ParentPaymentMethodToken, SessionState}, services::{self, api::Authenticate}, types::{ self as router_types, @@ -97,7 +97,7 @@ use crate::{ #[allow(clippy::too_many_arguments, clippy::type_complexity)] #[instrument(skip_all, fields(payment_id, merchant_id))] pub async fn payments_operation_core( - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -571,7 +571,7 @@ where #[instrument(skip_all)] pub async fn call_decision_manager( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut PaymentData, ) -> RouterResult<()> @@ -606,7 +606,7 @@ where #[instrument(skip_all)] async fn populate_surcharge_details( - state: &AppState, + state: &SessionState, payment_data: &mut PaymentData, ) -> RouterResult<()> where @@ -686,7 +686,7 @@ pub fn get_connector_data( #[instrument(skip_all)] pub async fn call_surcharge_decision_management_for_session_flow( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut PaymentData, session_connector_data: &[api::SessionConnectorData], @@ -741,7 +741,7 @@ where } #[allow(clippy::too_many_arguments)] pub async fn payments_core( - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -794,7 +794,7 @@ where payment_data, customer, auth_flow, - &state.conf.server, + &state.base_url, operation, &state.conf.connector_request_reference_id_config, connector_http_status_code, @@ -826,7 +826,7 @@ pub trait PaymentRedirectFlow: Sync { #[allow(clippy::too_many_arguments)] async fn call_payment_flow( &self, - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, @@ -848,7 +848,7 @@ pub trait PaymentRedirectFlow: Sync { #[allow(clippy::too_many_arguments)] async fn handle_payments_redirect_response( &self, - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -923,7 +923,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { #[allow(clippy::too_many_arguments)] async fn call_payment_flow( &self, - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, @@ -1055,7 +1055,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync { #[allow(clippy::too_many_arguments)] async fn call_payment_flow( &self, - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, @@ -1146,7 +1146,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize { #[allow(clippy::too_many_arguments)] async fn call_payment_flow( &self, - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, @@ -1378,7 +1378,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize { #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn call_connector_service( - state: &AppState, + state: &SessionState, req_state: ReqState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -1613,7 +1613,7 @@ where } async fn blocklist_guard( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, operation: &BoxedOperation<'_, F, ApiRequest>, payment_data: &mut PaymentData, @@ -1652,7 +1652,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn call_multiple_connectors_service( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connectors: Vec, @@ -1769,7 +1769,7 @@ where } pub async fn call_create_connector_customer_if_required( - state: &AppState, + state: &SessionState, customer: &Option, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -1871,7 +1871,7 @@ where } async fn complete_preprocessing_steps_if_required( - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, payment_data: &PaymentData, mut router_data: RouterData, @@ -2011,7 +2011,7 @@ pub fn is_preprocessing_required_for_wallets(connector_name: String) -> bool { #[instrument(skip_all)] pub async fn construct_profile_id_and_get_mca<'a, F>( - state: &'a AppState, + state: &'a SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut PaymentData, connector_name: &str, @@ -2049,7 +2049,7 @@ where } fn is_payment_method_tokenization_enabled_for_connector( - state: &AppState, + state: &SessionState, connector_name: &str, payment_method: &storage::enums::PaymentMethod, payment_method_type: &Option, @@ -2168,7 +2168,7 @@ fn is_payment_method_type_allowed_for_connector( } async fn decide_payment_method_tokenize_action( - state: &AppState, + state: &SessionState, connector_name: &str, payment_method: &storage::enums::PaymentMethod, pm_parent_token: Option<&String>, @@ -2241,7 +2241,7 @@ pub enum TokenizationAction { #[allow(clippy::too_many_arguments)] pub async fn get_connector_tokenization_action_when_confirm_true( - state: &AppState, + state: &SessionState, operation: &BoxedOperation<'_, F, Req>, payment_data: &mut PaymentData, validate_result: &operations::ValidateResult<'_>, @@ -2365,7 +2365,7 @@ where } pub async fn tokenize_in_router_when_confirm_false_or_external_authentication( - state: &AppState, + state: &SessionState, operation: &BoxedOperation<'_, F, Req>, payment_data: &mut PaymentData, validate_result: &operations::ValidateResult<'_>, @@ -2616,7 +2616,7 @@ pub fn is_operation_complete_authorize(operation: &Op) -> bool { #[cfg(feature = "olap")] pub async fn list_payments( - state: AppState, + state: SessionState, merchant: domain::MerchantAccount, constraints: api::PaymentListConstraints, ) -> RouterResponse { @@ -2682,7 +2682,7 @@ pub async fn list_payments( } #[cfg(feature = "olap")] pub async fn apply_filters_on_payments( - state: AppState, + state: SessionState, merchant: domain::MerchantAccount, constraints: api::PaymentListFilterConstraints, ) -> RouterResponse { @@ -2735,7 +2735,7 @@ pub async fn apply_filters_on_payments( #[cfg(feature = "olap")] pub async fn get_filters_for_payments( - state: AppState, + state: SessionState, merchant: domain::MerchantAccount, time_range: api::TimeRange, ) -> RouterResponse { @@ -2773,7 +2773,7 @@ pub async fn get_filters_for_payments( #[cfg(feature = "olap")] pub async fn get_payment_filters( - state: AppState, + state: SessionState, merchant: domain::MerchantAccount, ) -> RouterResponse { let merchant_connector_accounts = if let services::ApplicationResponse::Json(data) = @@ -2931,7 +2931,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn get_connector_choice( operation: &BoxedOperation<'_, F, Req>, - state: &AppState, + state: &SessionState, req: &Req, merchant_account: &domain::MerchantAccount, business_profile: &storage::business_profile::BusinessProfile, @@ -3010,7 +3010,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn connector_selection( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, business_profile: &storage::business_profile::BusinessProfile, key_store: &domain::MerchantKeyStore, @@ -3085,7 +3085,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn decide_connector( - state: AppState, + state: SessionState, merchant_account: &domain::MerchantAccount, business_profile: &storage::business_profile::BusinessProfile, key_store: &domain::MerchantKeyStore, @@ -3332,7 +3332,7 @@ where } pub async fn decide_multiplex_connector_for_normal_or_recurring_payment( - state: &AppState, + state: &SessionState, payment_data: &mut PaymentData, routing_data: &mut storage::RoutingData, connectors: Vec, @@ -3511,7 +3511,7 @@ pub async fn decide_multiplex_connector_for_normal_or_recurring_payment, connector: enums::Connector, payment_method_info: &storage::PaymentMethod, @@ -3540,7 +3540,7 @@ pub fn should_add_task_to_process_tracker(payment_data: &PaymentData( - state: AppState, + state: SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, @@ -3652,7 +3652,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn route_connector_v1( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, business_profile: &storage::business_profile::BusinessProfile, key_store: &domain::MerchantKeyStore, @@ -3775,7 +3775,7 @@ where #[instrument(skip_all)] pub async fn payment_external_authentication( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: api_models::payments::PaymentsExternalAuthenticationRequest, @@ -3908,15 +3908,12 @@ pub async fn payment_external_authentication( .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("missing connector in payment_attempt")?; let return_url = Some(helpers::create_authorize_url( - &state.conf.server.base_url, + &state.base_url, &payment_attempt.clone(), payment_connector_name, )); - let webhook_url = helpers::create_webhook_url( - &state.conf.server.base_url, - merchant_id, - &authentication_connector, - ); + let webhook_url = + helpers::create_webhook_url(&state.base_url, merchant_id, &authentication_connector); let business_profile = state .store @@ -3987,7 +3984,7 @@ pub async fn payment_external_authentication( #[instrument(skip_all)] pub async fn get_extended_card_info( - state: AppState, + state: SessionState, merchant_id: String, payment_id: String, ) -> RouterResponse { diff --git a/crates/router/src/core/payments/access_token.rs b/crates/router/src/core/payments/access_token.rs index 0c5aa13eb2f9..4241db6742da 100644 --- a/crates/router/src/core/payments/access_token.rs +++ b/crates/router/src/core/payments/access_token.rs @@ -9,7 +9,7 @@ use crate::{ errors::{self, RouterResult}, payments, }, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services::{self, logger}, types::{self, api as api_types, domain}, }; @@ -53,7 +53,7 @@ pub async fn add_access_token< Req: Debug + Clone + 'static, Res: Debug + Clone + 'static, >( - state: &AppState, + state: &SessionState, connector: &api_types::ConnectorData, merchant_account: &domain::MerchantAccount, router_data: &types::RouterData, @@ -194,7 +194,7 @@ pub async fn add_access_token< } pub async fn refresh_connector_auth( - state: &AppState, + state: &SessionState, connector: &api_types::ConnectorData, _merchant_account: &domain::MerchantAccount, router_data: &types::RouterData< diff --git a/crates/router/src/core/payments/conditional_configs.rs b/crates/router/src/core/payments/conditional_configs.rs index 5dc78d42e5ea..c73fa3659b70 100644 --- a/crates/router/src/core/payments/conditional_configs.rs +++ b/crates/router/src/core/payments/conditional_configs.rs @@ -21,7 +21,7 @@ pub type ConditionalConfigResult = errors::CustomResult; #[instrument(skip_all)] pub async fn perform_decision_management( - state: &routes::AppState, + state: &routes::SessionState, algorithm_ref: routing::RoutingAlgorithmRef, merchant_id: &str, payment_data: &mut payments::PaymentData, @@ -51,7 +51,7 @@ pub async fn perform_decision_management( #[instrument(skip_all)] pub async fn ensure_algorithm_cached( - state: &routes::AppState, + state: &routes::SessionState, merchant_id: &str, timestamp: i64, algorithm_id: &str, @@ -73,7 +73,7 @@ pub async fn ensure_algorithm_cached( #[instrument(skip_all)] pub async fn refresh_routing_cache( - state: &routes::AppState, + state: &routes::SessionState, key: String, algorithm_id: &str, timestamp: i64, diff --git a/crates/router/src/core/payments/customers.rs b/crates/router/src/core/payments/customers.rs index ff56eaf46ebf..448e5fedb8b1 100644 --- a/crates/router/src/core/payments/customers.rs +++ b/crates/router/src/core/payments/customers.rs @@ -6,14 +6,14 @@ use crate::{ payments, }, logger, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{self, api, domain, storage}, }; #[instrument(skip_all)] pub async fn create_connector_customer( - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, router_data: &types::RouterData, customer_request_data: types::ConnectorCustomerData, @@ -88,7 +88,7 @@ pub fn get_connector_customer_details_if_present<'a>( } pub fn should_call_connector_create_customer<'a>( - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, customer: &'a Option, connector_label: &str, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 158e28e69678..674fa4539276 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -19,7 +19,7 @@ use crate::{ errors::{ConnectorError, CustomResult, RouterResult}, payments::{self, helpers}, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, storage}, }; @@ -28,7 +28,7 @@ use crate::{ pub trait ConstructFlowSpecificData { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -42,7 +42,7 @@ pub trait ConstructFlowSpecificData { pub trait Feature { async fn decide_flows<'a>( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -55,7 +55,7 @@ pub trait Feature { async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult @@ -66,7 +66,7 @@ pub trait Feature { async fn add_payment_method_token<'a>( &mut self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, _tokenization_action: &payments::TokenizationAction, ) -> RouterResult> @@ -80,7 +80,7 @@ pub trait Feature { async fn preprocessing_steps<'a>( self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, ) -> RouterResult where @@ -93,7 +93,7 @@ pub trait Feature { async fn create_connector_customer<'a>( &self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, ) -> RouterResult> where @@ -107,7 +107,7 @@ pub trait Feature { /// Returns the connector request and a bool which specifies whether to proceed with further async fn build_flow_specific_connector_request( &mut self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/flows/approve_flow.rs b/crates/router/src/core/payments/flows/approve_flow.rs index 95ca0c3e31c7..6d4a88c0bf0e 100644 --- a/crates/router/src/core/payments/flows/approve_flow.rs +++ b/crates/router/src/core/payments/flows/approve_flow.rs @@ -6,7 +6,7 @@ use crate::{ errors::{ApiErrorResponse, NotImplementedMessage, RouterResult}, payments::{self, access_token, helpers, transformers, PaymentData}, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, storage}, }; @@ -18,7 +18,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -47,7 +47,7 @@ impl Feature { async fn decide_flows<'a>( self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, _connector_request: Option, @@ -61,7 +61,7 @@ impl Feature async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -70,7 +70,7 @@ impl Feature async fn build_flow_specific_connector_request( &mut self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 5990b29f372a..d672da99910d 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -11,7 +11,7 @@ use crate::{ }, }, logger, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{self, api, domain, storage}, }; @@ -26,7 +26,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -58,7 +58,7 @@ impl impl Feature for types::PaymentsAuthorizeRouterData { async fn decide_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -93,7 +93,7 @@ impl Feature for types::PaymentsAu async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -102,7 +102,7 @@ impl Feature for types::PaymentsAu async fn add_payment_method_token<'a>( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, tokenization_action: &payments::TokenizationAction, ) -> RouterResult> { @@ -119,7 +119,7 @@ impl Feature for types::PaymentsAu async fn preprocessing_steps<'a>( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, ) -> RouterResult { authorize_preprocessing_steps(state, &self, true, connector).await @@ -127,7 +127,7 @@ impl Feature for types::PaymentsAu async fn create_connector_customer<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, ) -> RouterResult> { customers::create_connector_customer( @@ -141,7 +141,7 @@ impl Feature for types::PaymentsAu async fn build_flow_specific_connector_request( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { @@ -266,7 +266,7 @@ impl mandate::MandateBehaviour for types::PaymentsAuthorizeData { } pub async fn authorize_preprocessing_steps( - state: &AppState, + state: &SessionState, router_data: &types::RouterData, confirm: bool, connector: &api::ConnectorData, diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs index 0e90ab40b696..d7e8cc3d9b57 100644 --- a/crates/router/src/core/payments/flows/cancel_flow.rs +++ b/crates/router/src/core/payments/flows/cancel_flow.rs @@ -6,7 +6,7 @@ use crate::{ errors::{ConnectorErrorExt, RouterResult}, payments::{self, access_token, helpers, transformers, PaymentData}, }, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{self, api, domain, storage}, }; @@ -17,7 +17,7 @@ impl ConstructFlowSpecificData( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -46,7 +46,7 @@ impl Feature { async fn decide_flows<'a>( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -83,7 +83,7 @@ impl Feature async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -92,7 +92,7 @@ impl Feature async fn build_flow_specific_connector_request( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/flows/capture_flow.rs b/crates/router/src/core/payments/flows/capture_flow.rs index b979eb2a337d..268281e51573 100644 --- a/crates/router/src/core/payments/flows/capture_flow.rs +++ b/crates/router/src/core/payments/flows/capture_flow.rs @@ -6,7 +6,7 @@ use crate::{ errors::{ConnectorErrorExt, RouterResult}, payments::{self, access_token, helpers, transformers, Feature, PaymentData}, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, storage}, }; @@ -18,7 +18,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -47,7 +47,7 @@ impl Feature { async fn decide_flows<'a>( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -75,7 +75,7 @@ impl Feature async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -84,7 +84,7 @@ impl Feature async fn build_flow_specific_connector_request( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/flows/complete_authorize_flow.rs b/crates/router/src/core/payments/flows/complete_authorize_flow.rs index c14cf6c80892..5d0cb9f9f381 100644 --- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs +++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs @@ -6,7 +6,7 @@ use crate::{ errors::{ConnectorErrorExt, RouterResult}, payments::{self, access_token, helpers, transformers, PaymentData}, }, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{self, api, domain, storage}, }; @@ -21,7 +21,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -60,7 +60,7 @@ impl Feature { async fn decide_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -88,7 +88,7 @@ impl Feature async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -97,7 +97,7 @@ impl Feature async fn add_payment_method_token<'a>( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, _tokenization_action: &payments::TokenizationAction, ) -> RouterResult> { @@ -119,7 +119,7 @@ impl Feature async fn build_flow_specific_connector_request( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { @@ -144,7 +144,7 @@ impl Feature async fn preprocessing_steps<'a>( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, ) -> RouterResult { complete_authorize_preprocessing_steps(state, &self, true, connector).await @@ -152,7 +152,7 @@ impl Feature } pub async fn complete_authorize_preprocessing_steps( - state: &AppState, + state: &SessionState, router_data: &types::RouterData, confirm: bool, connector: &api::ConnectorData, diff --git a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs index 716228d73f7b..58e5db8fbdef 100644 --- a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs +++ b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs @@ -6,7 +6,7 @@ use crate::{ errors::{ConnectorErrorExt, RouterResult}, payments::{self, access_token, helpers, transformers, Feature, PaymentData}, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, storage}, }; @@ -21,7 +21,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -54,7 +54,7 @@ impl Feature( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -82,7 +82,7 @@ impl Feature( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -91,7 +91,7 @@ impl Feature RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs index 51627e2d68b7..bec29f97e93f 100644 --- a/crates/router/src/core/payments/flows/psync_flow.rs +++ b/crates/router/src/core/payments/flows/psync_flow.rs @@ -8,7 +8,7 @@ use crate::{ errors::{ApiErrorResponse, ConnectorErrorExt, RouterResult}, payments::{self, access_token, helpers, transformers, PaymentData}, }, - routes::AppState, + routes::SessionState, services::{self, logger}, types::{self, api, domain, storage}, }; @@ -19,7 +19,7 @@ impl ConstructFlowSpecificData( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -50,7 +50,7 @@ impl Feature { async fn decide_flows<'a>( mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -101,7 +101,7 @@ impl Feature async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -110,7 +110,7 @@ impl Feature async fn build_flow_specific_connector_request( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { @@ -152,7 +152,7 @@ where { async fn execute_connector_processing_step_for_each_capture( &self, - _state: &AppState, + _state: &SessionState, _pending_connector_capture_id_list: Vec, _call_connector_action: payments::CallConnectorAction, _connector_integration: services::BoxedConnectorIntegration< @@ -170,7 +170,7 @@ impl RouterDataPSync { async fn execute_connector_processing_step_for_each_capture( &self, - state: &AppState, + state: &SessionState, pending_connector_capture_id_list: Vec, call_connector_action: payments::CallConnectorAction, connector_integration: services::BoxedConnectorIntegration< diff --git a/crates/router/src/core/payments/flows/reject_flow.rs b/crates/router/src/core/payments/flows/reject_flow.rs index 638efa054eb8..865c6ea201d0 100644 --- a/crates/router/src/core/payments/flows/reject_flow.rs +++ b/crates/router/src/core/payments/flows/reject_flow.rs @@ -6,7 +6,7 @@ use crate::{ errors::{ApiErrorResponse, NotImplementedMessage, RouterResult}, payments::{self, access_token, helpers, transformers, PaymentData}, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, storage}, }; @@ -17,7 +17,7 @@ impl ConstructFlowSpecificData( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -46,7 +46,7 @@ impl Feature { async fn decide_flows<'a>( self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, _connector_request: Option, @@ -60,7 +60,7 @@ impl Feature async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -69,7 +69,7 @@ impl Feature async fn build_flow_specific_connector_request( &mut self, - _state: &AppState, + _state: &SessionState, _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs index c74ed4bae153..76441f40759d 100644 --- a/crates/router/src/core/payments/flows/session_flow.rs +++ b/crates/router/src/core/payments/flows/session_flow.rs @@ -28,7 +28,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &routes::AppState, + state: &routes::SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -55,7 +55,7 @@ impl impl Feature for types::PaymentsSessionRouterData { async fn decide_flows<'a>( self, - state: &routes::AppState, + state: &routes::SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, _connector_request: Option, @@ -81,7 +81,7 @@ impl Feature for types::PaymentsSessio async fn add_access_token<'a>( &self, - state: &routes::AppState, + state: &routes::SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -123,7 +123,7 @@ fn is_dynamic_fields_required( } fn build_apple_pay_session_request( - state: &routes::AppState, + state: &routes::SessionState, request: payment_types::ApplepaySessionRequest, apple_pay_merchant_cert: masking::Secret, apple_pay_merchant_cert_key: masking::Secret, @@ -147,7 +147,7 @@ fn build_apple_pay_session_request( } async fn create_applepay_session_token( - state: &routes::AppState, + state: &routes::SessionState, router_data: &types::PaymentsSessionRouterData, connector: &api::ConnectorData, business_profile: &storage::business_profile::BusinessProfile, @@ -467,7 +467,7 @@ fn create_apple_pay_session_response( } fn create_gpay_session_token( - state: &routes::AppState, + state: &routes::SessionState, router_data: &types::PaymentsSessionRouterData, connector: &api::ConnectorData, business_profile: &storage::business_profile::BusinessProfile, @@ -598,7 +598,10 @@ fn create_gpay_session_token( } } -fn is_session_response_delayed(state: &routes::AppState, connector: &api::ConnectorData) -> bool { +fn is_session_response_delayed( + state: &routes::SessionState, + connector: &api::ConnectorData, +) -> bool { let connectors_with_delayed_response = &state .conf .delayed_session_response @@ -626,7 +629,7 @@ where { async fn decide_flow<'a, 'b>( &'b self, - state: &'a routes::AppState, + state: &'a routes::SessionState, connector: &api::ConnectorData, _confirm: Option, call_connector_action: payments::CallConnectorAction, @@ -635,7 +638,7 @@ where } fn create_paypal_sdk_session_token( - _state: &routes::AppState, + _state: &routes::SessionState, router_data: &types::PaymentsSessionRouterData, connector: &api::ConnectorData, _business_profile: &storage::business_profile::BusinessProfile, @@ -674,7 +677,7 @@ fn create_paypal_sdk_session_token( impl RouterDataSession for types::PaymentsSessionRouterData { async fn decide_flow<'a, 'b>( &'b self, - state: &'a routes::AppState, + state: &'a routes::SessionState, connector: &api::ConnectorData, _confirm: Option, call_connector_action: payments::CallConnectorAction, diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs index b0fa39d5258d..987d3f33803a 100644 --- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs +++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs @@ -9,7 +9,7 @@ use crate::{ self, access_token, customers, helpers, tokenization, transformers, PaymentData, }, }, - routes::AppState, + routes::SessionState, services, types::{self, api, domain, storage}, }; @@ -24,7 +24,7 @@ impl { async fn construct_router_data<'a>( &self, - state: &AppState, + state: &SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -51,7 +51,7 @@ impl impl Feature for types::SetupMandateRouterData { async fn decide_flows<'a>( self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, @@ -78,7 +78,7 @@ impl Feature for types::Setup async fn add_access_token<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, ) -> RouterResult { @@ -87,7 +87,7 @@ impl Feature for types::Setup async fn add_payment_method_token<'a>( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, tokenization_action: &payments::TokenizationAction, ) -> RouterResult> { @@ -104,7 +104,7 @@ impl Feature for types::Setup async fn create_connector_customer<'a>( &self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, ) -> RouterResult> { customers::create_connector_customer( @@ -118,7 +118,7 @@ impl Feature for types::Setup async fn build_flow_specific_connector_request( &mut self, - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, ) -> RouterResult<(Option, bool)> { diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 8f7ed4da2565..a58a6ae32b21 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -34,7 +34,7 @@ use super::{ CustomerDetails, PaymentData, }; use crate::{ - configs::settings::{ConnectorRequestReferenceIdConfig, Server, TempLockerEnableConfig}, + configs::settings::{ConnectorRequestReferenceIdConfig, TempLockerEnableConfig}, connector, consts::{self, BASE64_ENGINE}, core::{ @@ -46,7 +46,7 @@ use crate::{ pm_auth::retrieve_payment_method_from_auth_service, }, db::StorageInterface, - routes::{metrics, payment_methods as payment_methods_handler, AppState}, + routes::{metrics, payment_methods as payment_methods_handler, SessionState}, services, types::{ api::{self, admin, enums as api_enums, MandateValidationFieldsExt}, @@ -427,7 +427,7 @@ pub async fn get_address_by_id( } pub async fn get_token_pm_type_mandate_details( - state: &AppState, + state: &SessionState, request: &api::PaymentsRequest, mandate_type: Option, merchant_account: &domain::MerchantAccount, @@ -579,7 +579,7 @@ pub async fn get_token_pm_type_mandate_details( } pub async fn get_token_for_recurring_mandate( - state: &AppState, + state: &SessionState, req: &api::PaymentsRequest, merchant_account: &domain::MerchantAccount, merchant_key_store: &domain::MerchantKeyStore, @@ -1023,16 +1023,13 @@ pub fn validate_customer_id_mandatory_cases( } pub fn create_startpay_url( - server: &Server, + base_url: &str, payment_attempt: &PaymentAttempt, payment_intent: &PaymentIntent, ) -> String { format!( "{}/payments/redirect/{}/{}/{}", - server.base_url, - payment_intent.payment_id, - payment_intent.merchant_id, - payment_attempt.attempt_id + base_url, payment_intent.payment_id, payment_intent.merchant_id, payment_attempt.attempt_id ) } @@ -1050,7 +1047,7 @@ pub fn create_redirect_url( } pub fn create_authentication_url( - router_base_url: &String, + router_base_url: &str, payment_attempt: &PaymentAttempt, ) -> String { format!( @@ -1060,7 +1057,7 @@ pub fn create_authentication_url( } pub fn create_authorize_url( - router_base_url: &String, + router_base_url: &str, payment_attempt: &PaymentAttempt, connector_name: &String, ) -> String { @@ -1205,7 +1202,7 @@ pub fn payment_intent_status_fsm( } pub async fn add_domain_task_to_pt( operation: &Op, - state: &AppState, + state: &SessionState, payment_attempt: &PaymentAttempt, requeue: bool, schedule_time: Option, @@ -1494,7 +1491,7 @@ pub fn get_customer_details_from_request( } pub async fn get_connector_default( - _state: &AppState, + _state: &SessionState, request_connector: Option, ) -> CustomResult { Ok(request_connector.map_or( @@ -1676,7 +1673,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( } pub async fn retrieve_payment_method_with_temporary_token( - state: &AppState, + state: &SessionState, token: &str, payment_intent: &PaymentIntent, merchant_key_store: &domain::MerchantKeyStore, @@ -1773,7 +1770,7 @@ pub async fn retrieve_payment_method_with_temporary_token( } pub async fn retrieve_card_with_permanent_token( - state: &AppState, + state: &SessionState, locker_id: &str, payment_method_id: &str, payment_intent: &PaymentIntent, @@ -1838,7 +1835,7 @@ pub async fn retrieve_card_with_permanent_token( } pub async fn retrieve_payment_method_from_db_with_token_data( - state: &AppState, + state: &SessionState, token_data: &storage::PaymentTokenData, storage_scheme: storage::enums::MerchantStorageScheme, ) -> RouterResult> { @@ -1873,7 +1870,7 @@ pub async fn retrieve_payment_method_from_db_with_token_data( } pub async fn retrieve_payment_token_data( - state: &AppState, + state: &SessionState, token: String, payment_method: Option, ) -> RouterResult { @@ -1924,7 +1921,7 @@ pub async fn retrieve_payment_token_data( pub async fn make_pm_data<'a, F: Clone, R>( operation: BoxedOperation<'a, F, R>, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, @@ -2021,7 +2018,7 @@ pub async fn make_pm_data<'a, F: Clone, R>( } pub async fn store_in_vault_and_generate_ppmt( - state: &AppState, + state: &SessionState, payment_method_data: &api_models::payments::PaymentMethodData, payment_intent: &PaymentIntent, payment_attempt: &PaymentAttempt, @@ -2057,7 +2054,7 @@ pub async fn store_in_vault_and_generate_ppmt( } pub async fn store_payment_method_data_in_vault( - state: &AppState, + state: &SessionState, payment_attempt: &PaymentAttempt, payment_intent: &PaymentIntent, payment_method: enums::PaymentMethod, @@ -2541,7 +2538,7 @@ pub fn make_merchant_url_with_response( } pub async fn make_ephemeral_key( - state: AppState, + state: SessionState, customer_id: id_type::CustomerId, merchant_id: String, ) -> errors::RouterResponse { @@ -2563,7 +2560,7 @@ pub async fn make_ephemeral_key( } pub async fn delete_ephemeral_key( - state: AppState, + state: SessionState, ek_id: String, ) -> errors::RouterResponse { let db = state.store.as_ref(); @@ -3207,7 +3204,7 @@ impl MerchantConnectorAccountType { /// If profile_id is passed use it, or use connector_label to query merchant connector account #[instrument(skip_all)] pub async fn get_merchant_connector_account( - state: &AppState, + state: &SessionState, merchant_id: &str, creds_identifier: Option, key_store: &domain::MerchantKeyStore, @@ -3962,7 +3959,7 @@ pub fn get_applepay_metadata( } pub async fn get_apple_pay_retryable_connectors( - state: AppState, + state: SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut PaymentData, key_store: &domain::MerchantKeyStore, @@ -4067,7 +4064,7 @@ impl ApplePayData { pub async fn decrypt( &self, - state: &AppState, + state: &SessionState, ) -> CustomResult { let merchant_id = self.merchant_id(state).await?; let shared_secret = self.shared_secret(state).await?; @@ -4080,7 +4077,7 @@ impl ApplePayData { pub async fn merchant_id( &self, - state: &AppState, + state: &SessionState, ) -> CustomResult { let cert_data = state .conf @@ -4125,7 +4122,7 @@ impl ApplePayData { pub async fn shared_secret( &self, - state: &AppState, + state: &SessionState, ) -> CustomResult, errors::ApplePayDecryptionError> { let public_ec_bytes = BASE64_ENGINE .decode(self.header.ephemeral_public_key.peek().as_bytes()) @@ -4301,7 +4298,7 @@ pub fn validate_payment_link_request( } pub async fn get_gsm_record( - state: &AppState, + state: &SessionState, error_code: Option, error_message: Option, connector_name: String, @@ -4438,7 +4435,7 @@ pub fn update_additional_payment_data_with_connector_response_pm_data( } pub async fn get_payment_method_details_from_payment_token( - state: &AppState, + state: &SessionState, payment_attempt: &PaymentAttempt, payment_intent: &PaymentIntent, key_store: &domain::MerchantKeyStore, @@ -4589,7 +4586,7 @@ pub enum PaymentExternalAuthenticationFlow { } pub async fn get_payment_external_authentication_flow_during_confirm( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, business_profile: &storage::BusinessProfile, payment_data: &mut PaymentData, diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 35fc2897ea48..45e45bbe9cb6 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -29,7 +29,7 @@ use super::{helpers, CustomerDetails, PaymentData}; use crate::{ core::errors::{self, CustomResult, RouterResult}, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ self, @@ -102,7 +102,7 @@ pub trait GetTracker: Send { #[allow(clippy::too_many_arguments)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &R, merchant_account: &domain::MerchantAccount, @@ -127,7 +127,7 @@ pub trait Domain: Send + Sync { #[allow(clippy::too_many_arguments)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -140,7 +140,7 @@ pub trait Domain: Send + Sync { async fn add_task_to_process_tracker<'a>( &'a self, - _db: &'a AppState, + _db: &'a SessionState, _payment_attempt: &storage::PaymentAttempt, _requeue: bool, _schedule_time: Option, @@ -151,7 +151,7 @@ pub trait Domain: Send + Sync { async fn get_connector<'a>( &'a self, merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &R, payment_intent: &storage::PaymentIntent, mechant_key_store: &domain::MerchantKeyStore, @@ -159,7 +159,7 @@ pub trait Domain: Send + Sync { async fn populate_payment_data<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _payment_data: &mut PaymentData, _merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { @@ -168,7 +168,7 @@ pub trait Domain: Send + Sync { async fn call_external_three_ds_authentication_if_eligible<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, @@ -181,7 +181,7 @@ pub trait Domain: Send + Sync { #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -190,7 +190,7 @@ pub trait Domain: Send + Sync { async fn store_extended_card_info_temporarily<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _payment_id: &str, _business_profile: &storage::BusinessProfile, _payment_method_data: &Option, @@ -204,7 +204,7 @@ pub trait Domain: Send + Sync { pub trait UpdateTracker: Send { async fn update_trackers<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, req_state: ReqState, payment_data: D, customer: Option, @@ -222,7 +222,7 @@ pub trait UpdateTracker: Send { pub trait PostUpdateTracker: Send { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, payment_data: D, response: types::RouterData, @@ -233,7 +233,7 @@ pub trait PostUpdateTracker: Send { async fn save_pm_and_mandate<'b>( &self, - _state: &AppState, + _state: &SessionState, _resp: &types::RouterData, _merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -285,7 +285,7 @@ where async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, _request: &api::PaymentsRetrieveRequest, _payment_intent: &storage::PaymentIntent, _merchant_key_store: &domain::MerchantKeyStore, @@ -296,7 +296,7 @@ where #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -320,7 +320,7 @@ where #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -365,7 +365,7 @@ where #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_data: &mut PaymentData, _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, @@ -381,7 +381,7 @@ where async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, _request: &api::PaymentsCaptureRequest, _payment_intent: &storage::PaymentIntent, _merchant_key_store: &domain::MerchantKeyStore, @@ -392,7 +392,7 @@ where #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -438,7 +438,7 @@ where #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_data: &mut PaymentData, _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, @@ -454,7 +454,7 @@ where async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, _request: &api::PaymentsCancelRequest, _payment_intent: &storage::PaymentIntent, _merchant_key_store: &domain::MerchantKeyStore, @@ -465,7 +465,7 @@ where #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -500,7 +500,7 @@ where #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_data: &mut PaymentData, _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, @@ -516,7 +516,7 @@ where async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, _request: &api::PaymentsRejectRequest, _payment_intent: &storage::PaymentIntent, _merchant_key_store: &domain::MerchantKeyStore, @@ -527,7 +527,7 @@ where #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 52325db753a6..a492cb760389 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -12,7 +12,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::{helpers, operations, PaymentData}, }, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -34,7 +34,7 @@ impl GetTracker, api::PaymentsCaptureRequest> #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, _request: &api::PaymentsCaptureRequest, merchant_account: &domain::MerchantAccount, @@ -194,7 +194,7 @@ impl UpdateTracker, api::PaymentsCaptureRequest> for #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 64114fc40e65..ce79f9392c80 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -14,7 +14,7 @@ use crate::{ payments::{helpers, operations, PaymentData}, }, events::audit_events::{AuditEvent, AuditEventType}, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ self as core_types, @@ -34,7 +34,7 @@ impl GetTracker, api::PaymentsCancelRequest> #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsCancelRequest, merchant_account: &domain::MerchantAccount, @@ -207,7 +207,7 @@ impl UpdateTracker, api::PaymentsCancelRequest> for #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, req_state: ReqState, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index ec86d1d17245..447f7b929066 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -12,7 +12,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::{self, helpers, operations, types::MultipleCaptureData}, }, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ self as core_types, @@ -34,7 +34,7 @@ impl GetTracker, api::PaymentsCaptu #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsCaptureRequest, merchant_account: &domain::MerchantAccount, @@ -254,7 +254,7 @@ impl UpdateTracker, api::PaymentsCaptureRe #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, _req_state: ReqState, mut payment_data: payments::PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs index 49fe8ce20114..1ff95c37f667 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -15,7 +15,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -34,7 +34,7 @@ impl GetTracker, api::PaymentsRequest> for Co #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsRequest, merchant_account: &domain::MerchantAccount, @@ -367,7 +367,7 @@ impl Domain for CompleteAuthorize { #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: storage_enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -392,7 +392,7 @@ impl Domain for CompleteAuthorize { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_attempt: &storage::PaymentAttempt, _requeue: bool, _schedule_time: Option, @@ -403,7 +403,7 @@ impl Domain for CompleteAuthorize { async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &api::PaymentsRequest, _payment_intent: &storage::PaymentIntent, _key_store: &domain::MerchantKeyStore, @@ -416,7 +416,7 @@ impl Domain for CompleteAuthorize { #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -429,7 +429,7 @@ impl UpdateTracker, api::PaymentsRequest> for Comple #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - state: &'b AppState, + state: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index edda62d79f7c..ea5f2c0ecb43 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -29,7 +29,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ self, @@ -48,7 +48,7 @@ impl GetTracker, api::PaymentsRequest> for Pa #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsRequest, merchant_account: &domain::MerchantAccount, @@ -687,7 +687,7 @@ impl Domain for PaymentConfirm { #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: storage_enums::MerchantStorageScheme, key_store: &domain::MerchantKeyStore, @@ -717,7 +717,7 @@ impl Domain for PaymentConfirm { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_attempt: &storage::PaymentAttempt, requeue: bool, schedule_time: Option, @@ -732,7 +732,7 @@ impl Domain for PaymentConfirm { async move { helpers::add_domain_task_to_pt( &m_self, - m_state.as_ref(), + &m_state, &m_payment_attempt, requeue, schedule_time, @@ -748,7 +748,7 @@ impl Domain for PaymentConfirm { async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &api::PaymentsRequest, _payment_intent: &storage::PaymentIntent, _key_store: &domain::MerchantKeyStore, @@ -761,7 +761,7 @@ impl Domain for PaymentConfirm { #[instrument(skip_all)] async fn populate_payment_data<'a>( &'a self, - state: &AppState, + state: &SessionState, payment_data: &mut PaymentData, _merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { @@ -770,7 +770,7 @@ impl Domain for PaymentConfirm { async fn call_external_three_ds_authentication_if_eligible<'a>( &'a self, - state: &AppState, + state: &SessionState, payment_data: &mut PaymentData, should_continue_confirm_transaction: &mut bool, connector_call_type: &ConnectorCallType, @@ -857,7 +857,7 @@ impl Domain for PaymentConfirm { #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_data: &mut PaymentData, ) -> CustomResult { @@ -867,7 +867,7 @@ impl Domain for PaymentConfirm { #[instrument(skip_all)] async fn store_extended_card_info_temporarily<'a>( &'a self, - state: &AppState, + state: &SessionState, payment_id: &str, business_profile: &storage::BusinessProfile, payment_method_data: &Option, @@ -934,7 +934,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - state: &'b AppState, + state: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 9a4e87890582..bb249e9a9cd1 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -30,7 +30,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -54,7 +54,7 @@ impl GetTracker, api::PaymentsRequest> for Pa #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsRequest, merchant_account: &domain::MerchantAccount, @@ -215,7 +215,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .map(|merchant_name| merchant_name.into_inner().peek().to_owned()) .unwrap_or_default(); - let default_domain_name = state.conf.server.base_url.clone(); + let default_domain_name = state.base_url.clone(); let (payment_link_config, domain_name) = payment_link::get_payment_link_config_based_on_priority( @@ -497,7 +497,7 @@ impl Domain for PaymentCreate { #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -521,7 +521,7 @@ impl Domain for PaymentCreate { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_attempt: &PaymentAttempt, _requeue: bool, _schedule_time: Option, @@ -532,7 +532,7 @@ impl Domain for PaymentCreate { async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &api::PaymentsRequest, _payment_intent: &storage::PaymentIntent, _merchant_key_store: &domain::MerchantKeyStore, @@ -543,7 +543,7 @@ impl Domain for PaymentCreate { #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -556,7 +556,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - state: &'b AppState, + state: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, @@ -771,7 +771,7 @@ impl PaymentCreate { payment_method_type: Option, request: &api::PaymentsRequest, browser_info: Option, - state: &AppState, + state: &SessionState, payment_method_billing_address_id: Option, payment_method_info: &Option, key_store: &domain::MerchantKeyStore, @@ -1074,7 +1074,7 @@ impl PaymentCreate { #[instrument(skip_all)] pub async fn get_ephemeral_key( request: &api::PaymentsRequest, - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, ) -> Option { match request.customer_id.clone() { diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 60061d655c1c..cf8217718cbc 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -12,7 +12,7 @@ use crate::{ errors::{self, RouterResult, StorageErrorExt}, payments::{helpers, operations, PaymentAddress, PaymentData}, }, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -31,7 +31,7 @@ impl GetTracker, PaymentsCancelRequest> for P #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, _request: &PaymentsCancelRequest, merchant_account: &domain::MerchantAccount, @@ -191,7 +191,7 @@ impl UpdateTracker, PaymentsCancelRequest> for Payme #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - state: &'b AppState, + state: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 3b5bd9fd43ba..4843d1145d50 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -28,7 +28,7 @@ use crate::{ }, utils as core_utils, }, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, types::{ self, api, domain, storage::{self, enums}, @@ -51,7 +51,7 @@ impl PostUpdateTracker, types::PaymentsAuthor { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData< @@ -82,7 +82,7 @@ impl PostUpdateTracker, types::PaymentsAuthor async fn save_pm_and_mandate<'b>( &self, - state: &AppState, + state: &SessionState, resp: &types::RouterData, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -237,7 +237,7 @@ impl PostUpdateTracker, types::PaymentsIncrementalAu { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData< @@ -368,7 +368,7 @@ impl PostUpdateTracker, types::PaymentsIncrementalAu impl PostUpdateTracker, types::PaymentsSyncData> for PaymentResponse { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, payment_data: PaymentData, router_data: types::RouterData, @@ -389,7 +389,7 @@ impl PostUpdateTracker, types::PaymentsSyncData> for async fn save_pm_and_mandate<'b>( &self, - state: &AppState, + state: &SessionState, resp: &types::RouterData, merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -418,7 +418,7 @@ impl PostUpdateTracker, types::PaymentsSessionData> { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData, @@ -446,7 +446,7 @@ impl PostUpdateTracker, types::PaymentsCaptureData> { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData, @@ -472,7 +472,7 @@ impl PostUpdateTracker, types::PaymentsCaptureData> impl PostUpdateTracker, types::PaymentsCancelData> for PaymentResponse { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData, @@ -501,7 +501,7 @@ impl PostUpdateTracker, types::PaymentsApproveData> { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData, @@ -528,7 +528,7 @@ impl PostUpdateTracker, types::PaymentsApproveData> impl PostUpdateTracker, types::PaymentsRejectData> for PaymentResponse { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData, @@ -557,7 +557,7 @@ impl PostUpdateTracker, types::SetupMandateRequestDa { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData< @@ -590,7 +590,7 @@ impl PostUpdateTracker, types::SetupMandateRequestDa async fn save_pm_and_mandate<'b>( &self, - state: &AppState, + state: &SessionState, resp: &types::RouterData, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -658,7 +658,7 @@ impl PostUpdateTracker, types::CompleteAuthorizeData { async fn update_tracker<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, payment_id: &api::PaymentIdType, payment_data: PaymentData, response: types::RouterData, @@ -679,7 +679,7 @@ impl PostUpdateTracker, types::CompleteAuthorizeData async fn save_pm_and_mandate<'b>( &self, - state: &AppState, + state: &SessionState, resp: &types::RouterData, merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, @@ -704,7 +704,7 @@ impl PostUpdateTracker, types::CompleteAuthorizeData #[instrument(skip_all)] async fn payment_response_update_tracker( - state: &AppState, + state: &SessionState, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, router_data: types::RouterData, @@ -1235,7 +1235,7 @@ async fn payment_response_update_tracker( } async fn update_payment_method_status_and_ntid( - state: &AppState, + state: &SessionState, payment_data: &mut PaymentData, attempt_status: common_enums::AttemptStatus, payment_response: Result, diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 2aa01cd587fa..4d81914aca5f 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -14,7 +14,7 @@ use crate::{ payments::{self, helpers, operations, PaymentData}, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -35,7 +35,7 @@ impl GetTracker, api::PaymentsSessionRequest> #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsSessionRequest, merchant_account: &domain::MerchantAccount, @@ -218,7 +218,7 @@ impl UpdateTracker, api::PaymentsSessionRequest> for #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - state: &'b AppState, + state: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, @@ -316,7 +316,7 @@ where #[instrument(skip_all)] async fn make_pm_data<'b>( &'b self, - _state: &'b AppState, + _state: &'b SessionState, _payment_data: &mut PaymentData, _storage_scheme: storage_enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, @@ -342,7 +342,7 @@ where async fn get_connector<'a>( &'a self, merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &api::PaymentsSessionRequest, payment_intent: &storage::PaymentIntent, key_store: &domain::MerchantKeyStore, @@ -458,7 +458,7 @@ where #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> errors::CustomResult { diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index e5567e5b4748..7c1c117a7288 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -13,7 +13,7 @@ use crate::{ payments::{helpers, operations, CustomerDetails, PaymentAddress, PaymentData}, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -32,7 +32,7 @@ impl GetTracker, api::PaymentsStartRequest> f #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, _request: &api::PaymentsStartRequest, merchant_account: &domain::MerchantAccount, @@ -203,7 +203,7 @@ impl UpdateTracker, api::PaymentsStartRequest> for P #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - _state: &'b AppState, + _state: &'b SessionState, _req_state: ReqState, payment_data: PaymentData, _customer: Option, @@ -290,7 +290,7 @@ where #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: storage_enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -324,7 +324,7 @@ where async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, _request: &api::PaymentsStartRequest, _payment_intent: &storage::PaymentIntent, _mechant_key_store: &domain::MerchantKeyStore, @@ -335,7 +335,7 @@ where #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 0bedd70b921e..9971ea76aa3d 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -17,7 +17,7 @@ use crate::{ }, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api, domain, @@ -85,7 +85,7 @@ impl Domain for PaymentStatus { #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -109,7 +109,7 @@ impl Domain for PaymentStatus { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_attempt: &storage::PaymentAttempt, requeue: bool, schedule_time: Option, @@ -120,7 +120,7 @@ impl Domain for PaymentStatus { async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &api::PaymentsRequest, _payment_intent: &storage::PaymentIntent, _key_store: &domain::MerchantKeyStore, @@ -131,7 +131,7 @@ impl Domain for PaymentStatus { #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -143,7 +143,7 @@ impl Domain for PaymentStatus { impl UpdateTracker, api::PaymentsRequest> for PaymentStatus { async fn update_trackers<'b>( &'b self, - _state: &'b AppState, + _state: &'b SessionState, _req_state: ReqState, payment_data: PaymentData, _customer: Option, @@ -164,7 +164,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen impl UpdateTracker, api::PaymentsRetrieveRequest> for PaymentStatus { async fn update_trackers<'b>( &'b self, - _state: &'b AppState, + _state: &'b SessionState, _req_state: ReqState, payment_data: PaymentData, _customer: Option, @@ -191,7 +191,7 @@ impl GetTracker, api::PaymentsRetrieveRequest #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsRetrieveRequest, merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index e44dc0c1f2c1..ffa122e54af3 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -18,7 +18,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -37,7 +37,7 @@ impl GetTracker, api::PaymentsRequest> for Pa #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &api::PaymentsRequest, merchant_account: &domain::MerchantAccount, @@ -500,7 +500,7 @@ impl Domain for PaymentUpdate { #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_data: &mut PaymentData, storage_scheme: storage_enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, @@ -524,7 +524,7 @@ impl Domain for PaymentUpdate { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_attempt: &storage::PaymentAttempt, _requeue: bool, _schedule_time: Option, @@ -535,7 +535,7 @@ impl Domain for PaymentUpdate { async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, request: &api::PaymentsRequest, _payment_intent: &storage::PaymentIntent, _key_store: &domain::MerchantKeyStore, @@ -546,7 +546,7 @@ impl Domain for PaymentUpdate { #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut PaymentData, ) -> CustomResult { @@ -559,7 +559,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - state: &'b AppState, + state: &'b SessionState, _req_state: ReqState, mut payment_data: PaymentData, customer: Option, diff --git a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs index 56665d65a32d..26ffd65035d6 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -18,7 +18,7 @@ use crate::{ }, routes::{ app::{ReqState, StorageInterface}, - AppState, + SessionState, }, services, types::{ @@ -41,7 +41,7 @@ impl #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, payment_id: &api::PaymentIdType, request: &PaymentsIncrementalAuthorizationRequest, merchant_account: &domain::MerchantAccount, @@ -174,7 +174,7 @@ impl UpdateTracker, PaymentsIncrementalAut #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, - db: &'b AppState, + db: &'b SessionState, _req_state: ReqState, mut payment_data: payments::PaymentData, _customer: Option, @@ -307,7 +307,7 @@ impl Domain #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, _payment_data: &mut payments::PaymentData, _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, @@ -323,7 +323,7 @@ impl Domain async fn get_connector<'a>( &'a self, _merchant_account: &domain::MerchantAccount, - state: &AppState, + state: &SessionState, _request: &PaymentsIncrementalAuthorizationRequest, _payment_intent: &storage::PaymentIntent, _merchant_key_store: &domain::MerchantKeyStore, @@ -334,7 +334,7 @@ impl Domain #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, - _state: &AppState, + _state: &SessionState, _merchant_account: &domain::MerchantAccount, _payment_data: &mut payments::PaymentData, ) -> CustomResult { diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index 3bafd7774099..af41e3e4897b 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -31,7 +31,7 @@ use crate::{ #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn do_gsm_actions( - state: &app::AppState, + state: &app::SessionState, req_state: ReqState, payment_data: &mut payments::PaymentData, mut connectors: IntoIter, @@ -165,7 +165,7 @@ where #[instrument(skip_all)] pub async fn is_step_up_enabled_for_merchant_connector( - state: &app::AppState, + state: &app::SessionState, merchant_id: &str, connector_name: types::Connector, ) -> bool { @@ -189,7 +189,7 @@ pub async fn is_step_up_enabled_for_merchant_connector( #[instrument(skip_all)] pub async fn get_retries( - state: &app::AppState, + state: &app::SessionState, retries: Option, merchant_id: &str, ) -> Option { @@ -219,7 +219,7 @@ pub async fn get_retries( #[instrument(skip_all)] pub async fn get_gsm( - state: &app::AppState, + state: &app::SessionState, router_data: &types::RouterData, ) -> RouterResult> { let error_response = router_data.response.as_ref().err(); @@ -269,7 +269,7 @@ fn get_flow_name() -> RouterResult { #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn do_retry( - state: &routes::AppState, + state: &routes::SessionState, req_state: ReqState, connector: api::ConnectorData, operation: &operations::BoxedOperation<'_, F, ApiRequest>, @@ -326,7 +326,7 @@ where #[instrument(skip_all)] pub async fn modify_trackers( - state: &routes::AppState, + state: &routes::SessionState, connector: String, payment_data: &mut payments::PaymentData, storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs index d45f804268b3..145800ebc6aa 100644 --- a/crates/router/src/core/payments/routing.rs +++ b/crates/router/src/core/payments/routing.rs @@ -32,7 +32,7 @@ use rand::{ SeedableRng, }; use rustc_hash::FxHashMap; -use storage_impl::redis::cache::{CGRAPH_CACHE, ROUTING_CACHE}; +use storage_impl::redis::cache::{CacheKey, CGRAPH_CACHE, ROUTING_CACHE}; #[cfg(feature = "payouts")] use crate::core::payouts; @@ -50,7 +50,7 @@ use crate::{ transformers::{ForeignFrom, ForeignInto}, }, utils::{OptionExt, ValueExt}, - AppState, + SessionState, }; pub enum CachedAlgorithm { @@ -61,7 +61,7 @@ pub enum CachedAlgorithm { } pub struct SessionFlowRoutingInput<'a> { - pub state: &'a AppState, + pub state: &'a SessionState, pub country: Option, pub key_store: &'a domain::MerchantKeyStore, pub merchant_account: &'a domain::MerchantAccount, @@ -71,7 +71,7 @@ pub struct SessionFlowRoutingInput<'a> { } pub struct SessionRoutingPmTypeInput<'a> { - state: &'a AppState, + state: &'a SessionState, key_store: &'a domain::MerchantKeyStore, attempt_id: &'a str, routing_algorithm: &'a MerchantAccountRoutingAlgorithm, @@ -262,7 +262,7 @@ where } pub async fn perform_static_routing_v1( - state: &AppState, + state: &SessionState, merchant_id: &str, algorithm_ref: routing_types::RoutingAlgorithmRef, transaction_data: &routing::TransactionData<'_, F>, @@ -330,7 +330,7 @@ pub async fn perform_static_routing_v1( } async fn ensure_algorithm_cached_v1( - state: &AppState, + state: &SessionState, merchant_id: &str, algorithm_id: &str, #[cfg(feature = "business_profile_routing")] profile_id: Option, @@ -366,7 +366,10 @@ async fn ensure_algorithm_cached_v1( }; let cached_algorithm = ROUTING_CACHE - .get_val::>(key.as_str()) + .get_val::>(CacheKey { + key: key.clone(), + prefix: state.tenant.clone(), + }) .await; let algorithm = if let Some(algo) = cached_algorithm { @@ -428,7 +431,7 @@ fn execute_dsl_and_get_connector_v1( } pub async fn refresh_routing_cache_v1( - state: &AppState, + state: &SessionState, key: String, algorithm_id: &str, #[cfg(feature = "business_profile_routing")] profile_id: Option, @@ -483,7 +486,15 @@ pub async fn refresh_routing_cache_v1( let arc_cached_algorithm = Arc::new(cached_algorithm); - ROUTING_CACHE.push(key, arc_cached_algorithm.clone()).await; + ROUTING_CACHE + .push( + CacheKey { + key, + prefix: state.tenant.clone(), + }, + arc_cached_algorithm.clone(), + ) + .await; Ok(arc_cached_algorithm) } @@ -523,7 +534,7 @@ pub fn perform_volume_split( } pub async fn get_merchant_cgraph<'a>( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, #[cfg(feature = "business_profile_routing")] profile_id: Option, transaction_type: &api_enums::TransactionType, @@ -554,7 +565,10 @@ pub async fn get_merchant_cgraph<'a>( let cached_cgraph = CGRAPH_CACHE .get_val::>>( - key.as_str(), + CacheKey { + key: key.clone(), + prefix: state.tenant.clone(), + }, ) .await; @@ -576,7 +590,7 @@ pub async fn get_merchant_cgraph<'a>( } pub async fn refresh_cgraph_cache<'a>( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, key: String, #[cfg(feature = "business_profile_routing")] profile_id: Option, @@ -650,14 +664,22 @@ pub async fn refresh_cgraph_cache<'a>( .attach_printable("when construction cgraph")?, ); - CGRAPH_CACHE.push(key, Arc::clone(&cgraph)).await; + CGRAPH_CACHE + .push( + CacheKey { + key, + prefix: state.tenant.clone(), + }, + Arc::clone(&cgraph), + ) + .await; Ok(cgraph) } #[allow(clippy::too_many_arguments)] async fn perform_cgraph_filtering( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, chosen: Vec, backend_input: dsl_inputs::BackendInput, @@ -708,7 +730,7 @@ async fn perform_cgraph_filtering( } pub async fn perform_eligibility_analysis( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, chosen: Vec, transaction_data: &routing::TransactionData<'_, F>, @@ -735,7 +757,7 @@ pub async fn perform_eligibility_analysis( } pub async fn perform_fallback_routing( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, transaction_data: &routing::TransactionData<'_, F>, eligible_connectors: Option<&Vec>, @@ -781,7 +803,7 @@ pub async fn perform_fallback_routing( } pub async fn perform_eligibility_analysis_with_fallback( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, chosen: Vec, transaction_data: &routing::TransactionData<'_, F>, diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index c19c8c45753c..48637a0d2b32 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -18,7 +18,7 @@ use crate::{ mandate, payment_methods, payments, }, logger, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{ self, @@ -54,7 +54,7 @@ impl From<&types::RouterData #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn save_payment_method( - state: &AppState, + state: &SessionState, connector_name: String, merchant_connector_id: Option, save_payment_method_data: SavePaymentMethodData, @@ -646,7 +646,7 @@ async fn skip_saving_card_in_locker( } pub async fn save_in_locker( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, payment_method_request: api::PaymentMethodCreate, ) -> RouterResult<( @@ -719,7 +719,7 @@ pub fn create_payment_method_metadata( } pub async fn add_payment_method_token( - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, tokenization_action: &payments::TokenizationAction, router_data: &mut types::RouterData, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index a5859ea6dc6e..8eca589ca28e 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -15,7 +15,7 @@ use router_env::{instrument, tracing}; use super::{flows::Feature, types::AuthenticationData, PaymentData}; use crate::{ - configs::settings::{ConnectorRequestReferenceIdConfig, Server}, + configs::settings::ConnectorRequestReferenceIdConfig, connector::{Helcim, Nexinets}, core::{ errors::{self, RouterResponse, RouterResult}, @@ -23,7 +23,7 @@ use crate::{ utils as core_utils, }, headers::X_PAYMENT_CONFIRM_SOURCE, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services::{self, RedirectForm}, types::{ self, api, domain, @@ -36,7 +36,7 @@ use crate::{ #[instrument(skip_all)] pub async fn construct_payment_router_data<'a, F, T>( - state: &'a AppState, + state: &'a SessionState, payment_data: PaymentData, connector_id: &str, merchant_account: &domain::MerchantAccount, @@ -93,7 +93,7 @@ where }); let additional_data = PaymentAdditionalData { - router_base_url: state.conf.server.base_url.clone(), + router_base_url: state.base_url.clone(), connector_name: connector_id.to_string(), payment_data: payment_data.clone(), state, @@ -204,7 +204,7 @@ where data: D, customer: Option, auth_flow: services::AuthFlow, - server: &Server, + base_url: &str, operation: Op, connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig, connector_http_status_code: Option, @@ -223,7 +223,7 @@ where payment_data: PaymentData, customer: Option, auth_flow: services::AuthFlow, - server: &Server, + base_url: &str, operation: Op, connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig, connector_http_status_code: Option, @@ -253,7 +253,7 @@ where captures, customer, auth_flow, - server, + base_url, &operation, connector_request_reference_id_config, connector_http_status_code, @@ -273,7 +273,7 @@ where payment_data: PaymentData, _customer: Option, _auth_flow: services::AuthFlow, - _server: &Server, + _base_url: &str, _operation: Op, _connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig, _connector_http_status_code: Option, @@ -305,7 +305,7 @@ where data: PaymentData, customer: Option, _auth_flow: services::AuthFlow, - _server: &Server, + _base_url: &str, _operation: Op, _connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig, _connector_http_status_code: Option, @@ -361,7 +361,7 @@ pub fn payments_to_payments_response( captures: Option>, customer: Option, auth_flow: services::AuthFlow, - server: &Server, + base_url: &str, operation: &Op, connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig, connector_http_status_code: Option, @@ -589,7 +589,7 @@ where .or(payment_attempt.authentication_data.as_ref().map(|_| { api_models::payments::NextActionData::RedirectToUrl { redirect_to_url: helpers::create_startpay_url( - server, + base_url, &payment_attempt, &payment_intent, ), @@ -606,9 +606,9 @@ where .get_required_value("connector")?; Some(api_models::payments::NextActionData::ThreeDsInvoke { three_ds_data: api_models::payments::ThreeDsData { - three_ds_authentication_url: helpers::create_authentication_url(&server.base_url, &payment_attempt), + three_ds_authentication_url: helpers::create_authentication_url(base_url, &payment_attempt), three_ds_authorize_url: helpers::create_authorize_url( - &server.base_url, + base_url, &payment_attempt, payment_connector_name, ), @@ -1144,7 +1144,7 @@ where router_base_url: String, connector_name: String, payment_data: PaymentData, - state: &'a AppState, + state: &'a SessionState, customer_data: &'a Option, } impl TryFrom> for types::PaymentsAuthorizeData { diff --git a/crates/router/src/core/payments/types.rs b/crates/router/src/core/payments/types.rs index 92c9eec5ff80..1f16c4d667ea 100644 --- a/crates/router/src/core/payments/types.rs +++ b/crates/router/src/core/payments/types.rs @@ -18,7 +18,7 @@ use router_env::{instrument, tracing}; use crate::{ consts as router_consts, core::errors::{self, RouterResult}, - routes::AppState, + routes::SessionState, types::{ storage::{self, enums as storage_enums}, transformers::ForeignTryFrom, @@ -290,7 +290,7 @@ impl SurchargeMetadata { #[instrument(skip_all)] pub async fn persist_individual_surcharge_details_in_redis( &self, - state: &AppState, + state: &SessionState, business_profile: &BusinessProfile, ) -> RouterResult<()> { if !self.is_empty_result() { @@ -325,7 +325,7 @@ impl SurchargeMetadata { #[instrument(skip_all)] pub async fn get_individual_surcharge_detail_from_redis( - state: &AppState, + state: &SessionState, surcharge_key: SurchargeKey, payment_attempt_id: &str, ) -> CustomResult { diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs index 7aaf215ab51c..93c634b07fc9 100644 --- a/crates/router/src/core/payouts.rs +++ b/crates/router/src/core/payouts.rs @@ -34,7 +34,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::AppState, + routes::SessionState, services, types::{ self, @@ -71,7 +71,7 @@ pub fn get_next_connector( #[cfg(feature = "payouts")] pub async fn get_connector_choice( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector: Option, @@ -152,7 +152,7 @@ pub async fn get_connector_choice( #[instrument(skip_all)] pub async fn make_connector_decision( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_call_type: api::ConnectorCallType, @@ -254,7 +254,7 @@ pub async fn make_connector_decision( #[instrument(skip_all)] pub async fn payouts_core( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payout_data: &mut PayoutData, @@ -288,7 +288,7 @@ pub async fn payouts_core( #[instrument(skip_all)] pub async fn payouts_create_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: payouts::PayoutCreateRequest, @@ -339,7 +339,7 @@ pub async fn payouts_create_core( } pub async fn payouts_update_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: payouts::PayoutCreateRequest, @@ -470,7 +470,7 @@ pub async fn payouts_update_core( #[instrument(skip_all)] pub async fn payouts_retrieve_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: payouts::PayoutRetrieveRequest, @@ -488,7 +488,7 @@ pub async fn payouts_retrieve_core( #[instrument(skip_all)] pub async fn payouts_cancel_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: payouts::PayoutActionRequest, @@ -584,7 +584,7 @@ pub async fn payouts_cancel_core( #[instrument(skip_all)] pub async fn payouts_fulfill_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: payouts::PayoutActionRequest, @@ -670,7 +670,7 @@ pub async fn payouts_fulfill_core( #[cfg(feature = "olap")] pub async fn payouts_list_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, constraints: payouts::PayoutListConstraints, @@ -767,7 +767,7 @@ pub async fn payouts_list_core( #[cfg(feature = "olap")] pub async fn payouts_filtered_list_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, filters: payouts::PayoutListFilterConstraints, @@ -817,7 +817,7 @@ pub async fn payouts_filtered_list_core( #[cfg(feature = "olap")] pub async fn payouts_list_available_filters_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, time_range: api::TimeRange, ) -> RouterResponse { @@ -852,7 +852,7 @@ pub async fn payouts_list_available_filters_core( // ********************************************** HELPERS ********************************************** pub async fn call_connector_payout( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -962,7 +962,7 @@ pub async fn call_connector_payout( } pub async fn complete_create_recipient( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -989,7 +989,7 @@ pub async fn complete_create_recipient( } pub async fn create_recipient( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1124,7 +1124,7 @@ pub async fn create_recipient( } pub async fn complete_payout_eligibility( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1167,7 +1167,7 @@ pub async fn complete_payout_eligibility( } pub async fn check_payout_eligibility( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1281,7 +1281,7 @@ pub async fn check_payout_eligibility( } pub async fn complete_create_payout( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1343,7 +1343,7 @@ pub async fn complete_create_payout( } pub async fn create_payout( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1473,7 +1473,7 @@ pub async fn create_payout( } pub async fn complete_create_recipient_disburse_account( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1500,7 +1500,7 @@ pub async fn complete_create_recipient_disburse_account( } pub async fn create_recipient_disburse_account( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1586,7 +1586,7 @@ pub async fn create_recipient_disburse_account( } pub async fn cancel_payout( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1692,7 +1692,7 @@ pub async fn cancel_payout( } pub async fn fulfill_payout( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector_data: &api::ConnectorData, @@ -1904,7 +1904,7 @@ pub async fn response_handler( // DB entries #[allow(clippy::too_many_arguments)] pub async fn payout_create_db_entries( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, req: &payouts::PayoutCreateRequest, @@ -2061,7 +2061,7 @@ pub async fn payout_create_db_entries( } pub async fn make_payout_data( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, req: &payouts::PayoutRequest, @@ -2169,7 +2169,7 @@ pub async fn add_external_account_addition_task( } async fn validate_and_get_business_profile( - state: &AppState, + state: &SessionState, profile_id: &String, merchant_id: &str, ) -> RouterResult { diff --git a/crates/router/src/core/payouts/access_token.rs b/crates/router/src/core/payouts/access_token.rs index 8dddc0c570c9..af4f9e5f2883 100644 --- a/crates/router/src/core/payouts/access_token.rs +++ b/crates/router/src/core/payouts/access_token.rs @@ -7,7 +7,7 @@ use crate::{ errors::{self, RouterResult}, payments, }, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{self, api as api_types, domain, storage::enums}, }; @@ -17,7 +17,7 @@ use crate::{ /// There was an error, cannot proceed further #[cfg(feature = "payouts")] pub async fn create_access_token( - state: &AppState, + state: &SessionState, connector_data: &api_types::ConnectorData, merchant_account: &domain::MerchantAccount, router_data: &mut types::PayoutsRouterData, @@ -48,7 +48,7 @@ pub async fn create_access_token( #[cfg(feature = "payouts")] pub async fn add_access_token_for_payout( - state: &AppState, + state: &SessionState, connector: &api_types::ConnectorData, merchant_account: &domain::MerchantAccount, router_data: &types::PayoutsRouterData, @@ -132,7 +132,7 @@ pub async fn add_access_token_for_payout( #[cfg(feature = "payouts")] pub async fn refresh_connector_auth( - state: &AppState, + state: &SessionState, connector: &api_types::ConnectorData, _merchant_account: &domain::MerchantAccount, router_data: &types::RouterData< diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index 3059d3a4164c..6f8a7784aebb 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -25,7 +25,7 @@ use crate::{ routing::TransactionData, }, db::StorageInterface, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{ api::{self, enums as api_enums}, @@ -41,7 +41,7 @@ use crate::{ #[allow(clippy::too_many_arguments)] pub async fn make_payout_method_data<'a>( - state: &'a AppState, + state: &'a SessionState, payout_method_data: Option<&api::PayoutMethodData>, payout_token: Option<&str>, customer_id: &id_type::CustomerId, @@ -186,7 +186,7 @@ pub async fn make_payout_method_data<'a>( } pub async fn save_payout_data_to_locker( - state: &AppState, + state: &SessionState, payout_data: &mut PayoutData, payout_method_data: &api::PayoutMethodData, merchant_account: &domain::MerchantAccount, @@ -574,7 +574,7 @@ pub async fn save_payout_data_to_locker( } pub async fn get_or_create_customer_details( - state: &AppState, + state: &SessionState, customer_details: &CustomerDetails, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -638,7 +638,7 @@ pub async fn get_or_create_customer_details( } pub async fn decide_payout_connector( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, request_straight_through: Option, @@ -795,7 +795,7 @@ pub async fn decide_payout_connector( } pub async fn get_default_payout_connector( - _state: &AppState, + _state: &SessionState, request_connector: Option, ) -> CustomResult { Ok(request_connector.map_or( @@ -805,7 +805,7 @@ pub async fn get_default_payout_connector( } pub fn should_call_payout_connector_create_customer<'a>( - state: &AppState, + state: &SessionState, connector: &api::ConnectorData, customer: &'a Option, connector_label: &str, @@ -834,7 +834,7 @@ pub fn should_call_payout_connector_create_customer<'a>( } pub async fn get_gsm_record( - state: &AppState, + state: &SessionState, error_code: Option, error_message: Option, connector_name: Option, diff --git a/crates/router/src/core/payouts/retry.rs b/crates/router/src/core/payouts/retry.rs index 7cb929db94a2..792309920cb9 100644 --- a/crates/router/src/core/payouts/retry.rs +++ b/crates/router/src/core/payouts/retry.rs @@ -28,7 +28,7 @@ pub enum PayoutRetryType { #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn do_gsm_multiple_connector_actions( - state: &app::AppState, + state: &app::SessionState, mut connectors: IntoIter, original_connector_data: api::ConnectorData, payout_data: &mut PayoutData, @@ -95,7 +95,7 @@ pub async fn do_gsm_multiple_connector_actions( #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn do_gsm_single_connector_actions( - state: &app::AppState, + state: &app::SessionState, original_connector_data: api::ConnectorData, payout_data: &mut PayoutData, merchant_account: &domain::MerchantAccount, @@ -158,7 +158,7 @@ pub async fn do_gsm_single_connector_actions( #[instrument(skip_all)] pub async fn get_retries( - state: &app::AppState, + state: &app::SessionState, retries: Option, merchant_id: &str, retry_type: PayoutRetryType, @@ -196,7 +196,7 @@ pub async fn get_retries( #[instrument(skip_all)] pub async fn get_gsm( - state: &app::AppState, + state: &app::SessionState, original_connector_data: &api::ConnectorData, payout_data: &PayoutData, ) -> RouterResult> { @@ -236,7 +236,7 @@ pub fn get_gsm_decision( #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn do_retry( - state: &routes::AppState, + state: &routes::SessionState, connector: api::ConnectorData, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -251,7 +251,7 @@ pub async fn do_retry( #[instrument(skip_all)] pub async fn modify_trackers( - state: &routes::AppState, + state: &routes::SessionState, connector: &api::ConnectorData, merchant_account: &domain::MerchantAccount, payout_data: &mut PayoutData, diff --git a/crates/router/src/core/payouts/validator.rs b/crates/router/src/core/payouts/validator.rs index 1819c5152e0b..58972cf4276e 100644 --- a/crates/router/src/core/payouts/validator.rs +++ b/crates/router/src/core/payouts/validator.rs @@ -11,7 +11,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::AppState, + routes::SessionState, types::{api::payouts, domain, storage}, utils, }; @@ -45,7 +45,7 @@ pub async fn validate_uniqueness_of_payout_id_against_merchant_id( /// - payout_id is unique against merchant_id /// - payout_token provided is legitimate pub async fn validate_create_request( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, req: &payouts::PayoutCreateRequest, merchant_key_store: &domain::MerchantKeyStore, diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs index f184e166e22d..09d18963a29e 100644 --- a/crates/router/src/core/pm_auth.rs +++ b/crates/router/src/core/pm_auth.rs @@ -36,15 +36,12 @@ use crate::{ errors::{self, ApiErrorResponse, RouterResponse, RouterResult, StorageErrorExt}, payment_methods::cards, payments::helpers as oss_helpers, - pm_auth::helpers::{self as pm_auth_helpers}, + pm_auth::helpers as pm_auth_helpers, }, db::StorageInterface, logger, - routes::AppState, - services::{ - pm_auth::{self as pm_auth_services}, - ApplicationResponse, - }, + routes::SessionState, + services::{pm_auth as pm_auth_services, ApplicationResponse}, types::{ self, domain::{self, types::decrypt}, @@ -55,7 +52,7 @@ use crate::{ }; pub async fn create_link_token( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, payload: api_models::pm_auth::LinkTokenCreateRequest, @@ -160,7 +157,7 @@ pub async fn create_link_token( }; let connector_resp = pm_auth_services::execute_connector_processing_step( - state.as_ref(), + &state, connector_integration, &router_data, &connector.connector_name, @@ -205,7 +202,7 @@ impl ForeignTryFrom<&types::ConnectorAuthType> for PlaidAuthType { } pub async fn exchange_token_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, payload: api_models::pm_auth::ExchangeTokenCreateRequest, @@ -270,7 +267,7 @@ async fn store_bank_details_in_payment_methods( key_store: domain::MerchantKeyStore, payload: api_models::pm_auth::ExchangeTokenCreateRequest, merchant_account: domain::MerchantAccount, - state: AppState, + state: SessionState, bank_account_details_resp: pm_auth_types::BankAccountCredentialsResponse, connector_details: (&str, Secret), mca_id: String, @@ -523,7 +520,7 @@ pub async fn get_bank_account_creds( connector_name: &str, access_token: &Secret, auth_type: pm_auth_types::ConnectorAuthType, - state: &AppState, + state: &SessionState, bank_account_id: Option>, ) -> RouterResult { let connector_integration_bank_details: BoxedConnectorIntegration< @@ -578,7 +575,7 @@ async fn get_access_token_from_exchange_api( connector_name: &str, payload: &api_models::pm_auth::ExchangeTokenCreateRequest, auth_type: &pm_auth_types::ConnectorAuthType, - state: &AppState, + state: &SessionState, ) -> RouterResult> { let connector_integration: BoxedConnectorIntegration< '_, @@ -662,7 +659,7 @@ async fn get_selected_config_from_redis( } pub async fn retrieve_payment_method_from_auth_service( - state: &AppState, + state: &SessionState, key_store: &domain::MerchantKeyStore, auth_token: &payment_methods::BankAccountTokenData, payment_intent: &PaymentIntent, diff --git a/crates/router/src/core/poll.rs b/crates/router/src/core/poll.rs index 32a7b0f547ce..53b4b02e610e 100644 --- a/crates/router/src/core/poll.rs +++ b/crates/router/src/core/poll.rs @@ -4,11 +4,13 @@ use error_stack::ResultExt; use router_env::{instrument, tracing}; use super::errors; -use crate::{core::errors::RouterResponse, services::ApplicationResponse, types::domain, AppState}; +use crate::{ + core::errors::RouterResponse, services::ApplicationResponse, types::domain, SessionState, +}; #[instrument(skip_all)] pub async fn retrieve_poll_status( - state: AppState, + state: SessionState, req: crate::types::api::PollId, merchant_account: domain::MerchantAccount, ) -> RouterResponse { diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs index d2d2db71ef36..0d441e95382d 100644 --- a/crates/router/src/core/refunds.rs +++ b/crates/router/src/core/refunds.rs @@ -24,7 +24,7 @@ use crate::{ utils as core_utils, }, db, logger, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services, types::{ self, @@ -42,7 +42,7 @@ use crate::{ #[instrument(skip_all)] pub async fn refund_create_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: refunds::RefundRequest, @@ -134,7 +134,7 @@ pub async fn refund_create_core( #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn trigger_refund_to_gateway( - state: &AppState, + state: &SessionState, refund: &storage::Refund, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -317,14 +317,14 @@ pub async fn trigger_refund_to_gateway( // ********************************************** REFUND SYNC ********************************************** pub async fn refund_response_wrapper<'a, F, Fut, T, Req>( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, request: Req, f: F, ) -> RouterResponse where - F: Fn(AppState, domain::MerchantAccount, domain::MerchantKeyStore, Req) -> Fut, + F: Fn(SessionState, domain::MerchantAccount, domain::MerchantKeyStore, Req) -> Fut, Fut: futures::Future>, T: ForeignInto, { @@ -337,7 +337,7 @@ where #[instrument(skip_all)] pub async fn refund_retrieve_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, request: refunds::RefundsRetrieveRequest, @@ -432,7 +432,7 @@ fn should_call_refund(refund: &diesel_models::refund::Refund, force_sync: bool) #[instrument(skip_all)] pub async fn sync_refund_with_gateway( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payment_attempt: &storage::PaymentAttempt, @@ -546,7 +546,7 @@ pub async fn sync_refund_with_gateway( // ********************************************** REFUND UPDATE ********************************************** pub async fn refund_update_core( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: refunds::RefundUpdateRequest, ) -> RouterResponse { @@ -584,7 +584,7 @@ pub async fn refund_update_core( #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn validate_and_create_refund( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payment_attempt: &storage::PaymentAttempt, @@ -767,7 +767,7 @@ pub async fn validate_and_create_refund( #[instrument(skip_all)] #[cfg(feature = "olap")] pub async fn refund_list( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: api_models::refunds::RefundListRequest, ) -> RouterResponse { @@ -812,7 +812,7 @@ pub async fn refund_list( #[instrument(skip_all)] #[cfg(feature = "olap")] pub async fn refund_filter_list( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, req: api_models::payments::TimeRange, ) -> RouterResponse { @@ -832,7 +832,7 @@ pub async fn refund_filter_list( #[instrument(skip_all)] #[cfg(feature = "olap")] pub async fn get_filters_for_refunds( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, ) -> RouterResponse { let merchant_connector_accounts = if let services::ApplicationResponse::Json(data) = @@ -900,7 +900,7 @@ impl ForeignFrom for api::RefundResponse { #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn schedule_refund_execution( - state: &AppState, + state: &SessionState, refund: storage::Refund, refund_type: api_models::refunds::RefundType, merchant_account: &domain::MerchantAccount, @@ -979,7 +979,7 @@ pub async fn schedule_refund_execution( #[instrument(skip_all)] pub async fn sync_refund_with_gateway_workflow( - state: &AppState, + state: &SessionState, refund_tracker: &storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { let refund_core = @@ -1048,7 +1048,7 @@ pub async fn sync_refund_with_gateway_workflow( #[instrument(skip_all)] pub async fn start_refund_workflow( - state: &AppState, + state: &SessionState, refund_tracker: &storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { match refund_tracker.name.as_deref() { @@ -1064,7 +1064,7 @@ pub async fn start_refund_workflow( #[instrument(skip_all)] pub async fn trigger_refund_execute_workflow( - state: &AppState, + state: &SessionState, refund_tracker: &storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { let db = &*state.store; diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index 31825617398a..a64dadaa35d9 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -27,7 +27,7 @@ use crate::{ errors::{RouterResponse, StorageErrorExt}, metrics, utils as core_utils, }, - routes::AppState, + routes::SessionState, types::domain, utils::{self, OptionExt, ValueExt}, }; @@ -46,7 +46,7 @@ where } pub async fn retrieve_merchant_routing_dictionary( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, #[cfg(feature = "business_profile_routing")] query_params: RoutingRetrieveQuery, #[cfg(feature = "business_profile_routing")] transaction_type: &enums::TransactionType, @@ -93,7 +93,7 @@ pub async fn retrieve_merchant_routing_dictionary( } pub async fn create_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, request: routing_types::RoutingConfigRequest, @@ -248,7 +248,7 @@ pub async fn create_routing_config( } pub async fn link_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, #[cfg(not(feature = "business_profile_routing"))] key_store: domain::MerchantKeyStore, algorithm_id: String, @@ -371,7 +371,7 @@ pub async fn link_routing_config( } pub async fn retrieve_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, algorithm_id: RoutingAlgorithmId, ) -> RouterResponse { @@ -445,7 +445,7 @@ pub async fn retrieve_routing_config( } } pub async fn unlink_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, #[cfg(not(feature = "business_profile_routing"))] key_store: domain::MerchantKeyStore, #[cfg(feature = "business_profile_routing")] request: routing_types::RoutingConfigRequest, @@ -630,7 +630,7 @@ pub async fn unlink_routing_config( } pub async fn update_default_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, updated_config: Vec, transaction_type: &enums::TransactionType, @@ -679,7 +679,7 @@ pub async fn update_default_routing_config( } pub async fn retrieve_default_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, transaction_type: &enums::TransactionType, ) -> RouterResponse> { @@ -699,7 +699,7 @@ pub async fn retrieve_default_routing_config( } pub async fn retrieve_linked_routing_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, #[cfg(feature = "business_profile_routing")] query_params: RoutingRetrieveLinkQuery, #[cfg(feature = "business_profile_routing")] transaction_type: &enums::TransactionType, @@ -808,7 +808,7 @@ pub async fn retrieve_linked_routing_config( } pub async fn retrieve_default_routing_config_for_profiles( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, transaction_type: &enums::TransactionType, ) -> RouterResponse> { @@ -847,7 +847,7 @@ pub async fn retrieve_default_routing_config_for_profiles( } pub async fn update_default_routing_config_for_profile( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, updated_config: Vec, profile_id: String, diff --git a/crates/router/src/core/surcharge_decision_config.rs b/crates/router/src/core/surcharge_decision_config.rs index b489b92cdf1f..7f451e6008fe 100644 --- a/crates/router/src/core/surcharge_decision_config.rs +++ b/crates/router/src/core/surcharge_decision_config.rs @@ -15,14 +15,14 @@ use super::routing::helpers::{ }; use crate::{ core::errors::{self, RouterResponse}, - routes::AppState, + routes::SessionState, services::api as service_api, types::domain, utils::OptionExt, }; pub async fn upsert_surcharge_decision_config( - state: AppState, + state: SessionState, key_store: domain::MerchantKeyStore, merchant_account: domain::MerchantAccount, request: SurchargeDecisionConfigReq, @@ -139,7 +139,7 @@ pub async fn upsert_surcharge_decision_config( } pub async fn delete_surcharge_decision_config( - state: AppState, + state: SessionState, key_store: domain::MerchantKeyStore, merchant_account: domain::MerchantAccount, ) -> RouterResponse<()> { @@ -167,7 +167,7 @@ pub async fn delete_surcharge_decision_config( } pub async fn retrieve_surcharge_decision_config( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, ) -> RouterResponse { let db = state.store.as_ref(); diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index 9db47b74dc51..c259e87c93de 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -21,7 +21,7 @@ use super::errors::{StorageErrorExt, UserErrors, UserResponse, UserResult}; use crate::services::email::types as email_types; use crate::{ consts, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services::{authentication as auth, authorization::roles, ApplicationResponse}, types::{domain, transformers::ForeignInto}, utils::{self, user::two_factor_auth as tfa_utils}, @@ -33,7 +33,7 @@ pub mod sample_data; #[cfg(feature = "email")] pub async fn signup_with_merchant_id( - state: AppState, + state: SessionState, request: user_api::SignUpWithMerchantIdRequest, ) -> UserResponse { let new_user = domain::NewUser::try_from(request.clone())?; @@ -79,7 +79,7 @@ pub async fn signup_with_merchant_id( } pub async fn get_user_details( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, ) -> UserResponse { let user = user_from_token.get_user_from_db(&state).await?; @@ -99,7 +99,7 @@ pub async fn get_user_details( } pub async fn signup( - state: AppState, + state: SessionState, request: user_api::SignUpRequest, ) -> UserResponse> { let new_user = domain::NewUser::try_from(request)?; @@ -128,7 +128,7 @@ pub async fn signup( } pub async fn signup_token_only_flow( - state: AppState, + state: SessionState, request: user_api::SignUpRequest, ) -> UserResponse> { let new_user = domain::NewUser::try_from(request)?; @@ -163,7 +163,7 @@ pub async fn signup_token_only_flow( } pub async fn signin( - state: AppState, + state: SessionState, request: user_api::SignInRequest, ) -> UserResponse> { let user_from_db: domain::UserFromStorage = state @@ -207,7 +207,7 @@ pub async fn signin( } pub async fn signin_token_only_flow( - state: AppState, + state: SessionState, request: user_api::SignInRequest, ) -> UserResponse> { let user_from_db: domain::UserFromStorage = state @@ -233,7 +233,7 @@ pub async fn signin_token_only_flow( #[cfg(feature = "email")] pub async fn connect_account( - state: AppState, + state: SessionState, request: user_api::ConnectAccountRequest, ) -> UserResponse { let find_user = state.store.find_user_by_email(&request.email).await; @@ -324,13 +324,16 @@ pub async fn connect_account( } } -pub async fn signout(state: AppState, user_from_token: auth::UserFromToken) -> UserResponse<()> { +pub async fn signout( + state: SessionState, + user_from_token: auth::UserFromToken, +) -> UserResponse<()> { auth::blacklist::insert_user_in_blacklist(&state, &user_from_token.user_id).await?; auth::cookies::remove_cookie_response() } pub async fn change_password( - state: AppState, + state: SessionState, request: user_api::ChangePasswordRequest, user_from_token: auth::UserFromToken, ) -> UserResponse<()> { @@ -386,7 +389,7 @@ pub async fn change_password( #[cfg(feature = "email")] pub async fn forgot_password( - state: AppState, + state: SessionState, request: user_api::ForgotPasswordRequest, ) -> UserResponse<()> { let user_email = domain::UserEmail::from_pii_email(request.email)?; @@ -424,7 +427,7 @@ pub async fn forgot_password( } pub async fn rotate_password( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, request: user_api::RotatePasswordRequest, _req_state: ReqState, @@ -463,7 +466,7 @@ pub async fn rotate_password( #[cfg(feature = "email")] pub async fn reset_password_token_only_flow( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, request: user_api::ResetPasswordRequest, ) -> UserResponse<()> { @@ -517,7 +520,7 @@ pub async fn reset_password_token_only_flow( #[cfg(feature = "email")] pub async fn reset_password( - state: AppState, + state: SessionState, request: user_api::ResetPasswordRequest, ) -> UserResponse<()> { let token = request.token.expose(); @@ -569,7 +572,7 @@ pub async fn reset_password( } pub async fn invite_multiple_user( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, requests: Vec, req_state: ReqState, @@ -598,7 +601,7 @@ pub async fn invite_multiple_user( } async fn handle_invitation( - state: &AppState, + state: &SessionState, user_from_token: &auth::UserFromToken, request: &user_api::InviteUserRequest, req_state: &ReqState, @@ -656,7 +659,7 @@ async fn handle_invitation( //TODO: send email async fn handle_existing_user_invitation( - state: &AppState, + state: &SessionState, user_from_token: &auth::UserFromToken, request: &user_api::InviteUserRequest, invitee_user_from_db: domain::UserFromStorage, @@ -727,7 +730,7 @@ async fn handle_existing_user_invitation( } async fn handle_new_user_invitation( - state: &AppState, + state: &SessionState, user_from_token: &auth::UserFromToken, request: &user_api::InviteUserRequest, req_state: ReqState, @@ -839,7 +842,7 @@ async fn handle_new_user_invitation( #[cfg(feature = "email")] pub async fn resend_invite( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, request: user_api::ReInviteUserRequest, _req_state: ReqState, @@ -901,7 +904,7 @@ pub async fn resend_invite( #[cfg(feature = "email")] pub async fn accept_invite_from_email( - state: AppState, + state: SessionState, request: user_api::AcceptInviteFromEmailRequest, ) -> UserResponse { let token = request.token.expose(); @@ -968,7 +971,7 @@ pub async fn accept_invite_from_email( #[cfg(feature = "email")] pub async fn accept_invite_from_email_token_only_flow( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, request: user_api::AcceptInviteFromEmailRequest, ) -> UserResponse> { @@ -1034,7 +1037,7 @@ pub async fn accept_invite_from_email_token_only_flow( } pub async fn create_internal_user( - state: AppState, + state: SessionState, request: user_api::CreateInternalUserRequest, ) -> UserResponse<()> { let new_user = domain::NewUser::try_from(request)?; @@ -1097,7 +1100,7 @@ pub async fn create_internal_user( } pub async fn switch_merchant_id( - state: AppState, + state: SessionState, request: user_api::SwitchMerchantIdRequest, user_from_token: auth::UserFromToken, ) -> UserResponse { @@ -1196,7 +1199,7 @@ pub async fn switch_merchant_id( } pub async fn create_merchant_account( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, req: user_api::UserMerchantCreate, ) -> UserResponse<()> { @@ -1227,7 +1230,7 @@ pub async fn create_merchant_account( } pub async fn list_merchants_for_user( - state: AppState, + state: SessionState, user_from_token: Box, ) -> UserResponse> { let user_roles = state @@ -1260,7 +1263,7 @@ pub async fn list_merchants_for_user( } pub async fn get_user_details_in_merchant_account( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, request: user_api::GetUserRoleDetailsRequest, _req_state: ReqState, @@ -1304,7 +1307,7 @@ pub async fn get_user_details_in_merchant_account( } pub async fn list_users_for_merchant_account( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, ) -> UserResponse { let users_and_user_roles = state @@ -1352,7 +1355,7 @@ pub async fn list_users_for_merchant_account( #[cfg(feature = "email")] pub async fn verify_email( - state: AppState, + state: SessionState, req: user_api::VerifyEmailRequest, ) -> UserResponse { let token = req.token.clone().expose(); @@ -1411,7 +1414,7 @@ pub async fn verify_email( #[cfg(feature = "email")] pub async fn verify_email_token_only_flow( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, req: user_api::VerifyEmailRequest, ) -> UserResponse> { @@ -1469,7 +1472,7 @@ pub async fn verify_email_token_only_flow( #[cfg(feature = "email")] pub async fn send_verification_mail( - state: AppState, + state: SessionState, req: user_api::SendVerifyEmailRequest, ) -> UserResponse<()> { let user_email = domain::UserEmail::try_from(req.email)?; @@ -1509,7 +1512,7 @@ pub async fn send_verification_mail( #[cfg(feature = "recon")] pub async fn verify_token( - state: AppState, + state: SessionState, req: auth::ReconUser, ) -> UserResponse { let user = state @@ -1537,7 +1540,7 @@ pub async fn verify_token( } pub async fn update_user_details( - state: AppState, + state: SessionState, user_token: auth::UserFromToken, req: user_api::UpdateUserAccountDetailsRequest, _req_state: ReqState, @@ -1582,7 +1585,7 @@ pub async fn update_user_details( #[cfg(feature = "email")] pub async fn user_from_email( - state: AppState, + state: SessionState, req: user_api::UserFromEmailRequest, ) -> UserResponse { let token = req.token.expose(); @@ -1616,7 +1619,7 @@ pub async fn user_from_email( } pub async fn begin_totp( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, ) -> UserResponse { let user_from_db: domain::UserFromStorage = state @@ -1645,7 +1648,7 @@ pub async fn begin_totp( } pub async fn reset_totp( - state: AppState, + state: SessionState, user_token: auth::UserFromToken, ) -> UserResponse { let user_from_db: domain::UserFromStorage = state @@ -1678,7 +1681,7 @@ pub async fn reset_totp( } pub async fn verify_totp( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, req: user_api::VerifyTotpRequest, ) -> UserResponse { @@ -1714,7 +1717,7 @@ pub async fn verify_totp( } pub async fn update_totp( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, req: user_api::VerifyTotpRequest, ) -> UserResponse<()> { @@ -1779,7 +1782,7 @@ pub async fn update_totp( } pub async fn generate_recovery_codes( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, ) -> UserResponse { if !tfa_utils::check_totp_in_redis(&state, &user_token.user_id).await? { @@ -1811,7 +1814,7 @@ pub async fn generate_recovery_codes( } pub async fn verify_recovery_code( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, req: user_api::VerifyRecoveryCodeRequest, ) -> UserResponse { @@ -1856,7 +1859,7 @@ pub async fn verify_recovery_code( } pub async fn terminate_two_factor_auth( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, skip_two_factor_auth: bool, ) -> UserResponse { @@ -1908,7 +1911,7 @@ pub async fn terminate_two_factor_auth( } pub async fn check_two_factor_auth_status( - state: AppState, + state: SessionState, user_token: auth::UserFromToken, ) -> UserResponse { Ok(ApplicationResponse::Json( diff --git a/crates/router/src/core/user/dashboard_metadata.rs b/crates/router/src/core/user/dashboard_metadata.rs index ee1693b0c9d4..364898462946 100644 --- a/crates/router/src/core/user/dashboard_metadata.rs +++ b/crates/router/src/core/user/dashboard_metadata.rs @@ -12,14 +12,14 @@ use router_env::logger; use crate::services::email::types as email_types; use crate::{ core::errors::{UserErrors, UserResponse, UserResult}, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services::{authentication::UserFromToken, ApplicationResponse}, types::domain::{self, user::dashboard_metadata as types, MerchantKeyStore}, utils::user::dashboard_metadata as utils, }; pub async fn set_metadata( - state: AppState, + state: SessionState, user: UserFromToken, request: api::SetMetaDataRequest, _req_state: ReqState, @@ -33,7 +33,7 @@ pub async fn set_metadata( } pub async fn get_multiple_metadata( - state: AppState, + state: SessionState, user: UserFromToken, request: GetMultipleMetaDataPayload, _req_state: ReqState, @@ -230,7 +230,7 @@ fn into_response( } async fn insert_metadata( - state: &AppState, + state: &SessionState, user: UserFromToken, metadata_key: DBEnum, metadata_value: types::MetaData, @@ -571,7 +571,7 @@ async fn insert_metadata( } async fn fetch_metadata( - state: &AppState, + state: &SessionState, user: &UserFromToken, metadata_keys: Vec, ) -> UserResult> { @@ -606,7 +606,7 @@ async fn fetch_metadata( } pub async fn backfill_metadata( - state: &AppState, + state: &SessionState, user: &UserFromToken, key: &DBEnum, ) -> UserResult> { @@ -705,7 +705,7 @@ pub async fn backfill_metadata( } pub async fn get_merchant_connector_account_by_name( - state: &AppState, + state: &SessionState, merchant_id: &str, connector_name: &str, key_store: &MerchantKeyStore, diff --git a/crates/router/src/core/user/sample_data.rs b/crates/router/src/core/user/sample_data.rs index e1bde652305f..bab620620fa6 100644 --- a/crates/router/src/core/user/sample_data.rs +++ b/crates/router/src/core/user/sample_data.rs @@ -7,13 +7,13 @@ pub type SampleDataApiResponse = SampleDataResult>; use crate::{ core::errors::sample_data::SampleDataResult, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services::{authentication::UserFromToken, ApplicationResponse}, utils::user::sample_data::generate_sample_data, }; pub async fn generate_sample_data_for_user( - state: AppState, + state: SessionState, user_from_token: UserFromToken, req: SampleDataRequest, _req_state: ReqState, @@ -57,7 +57,7 @@ pub async fn generate_sample_data_for_user( } pub async fn delete_sample_data_for_user( - state: AppState, + state: SessionState, user_from_token: UserFromToken, _req: SampleDataRequest, _req_state: ReqState, diff --git a/crates/router/src/core/user_role.rs b/crates/router/src/core/user_role.rs index 0d196e1c4af6..8b636f9935b8 100644 --- a/crates/router/src/core/user_role.rs +++ b/crates/router/src/core/user_role.rs @@ -6,7 +6,7 @@ use router_env::logger; use crate::{ consts, core::errors::{StorageErrorExt, UserErrors, UserResponse}, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services::{ authentication as auth, authorization::{info, roles}, @@ -20,7 +20,7 @@ pub mod role; // TODO: To be deprecated once groups are stable pub async fn get_authorization_info_with_modules( - _state: AppState, + _state: SessionState, ) -> UserResponse { Ok(ApplicationResponse::Json( user_role_api::AuthorizationInfoResponse( @@ -33,7 +33,7 @@ pub async fn get_authorization_info_with_modules( } pub async fn get_authorization_info_with_groups( - _state: AppState, + _state: SessionState, ) -> UserResponse { Ok(ApplicationResponse::Json( user_role_api::AuthorizationInfoResponse( @@ -46,7 +46,7 @@ pub async fn get_authorization_info_with_groups( } pub async fn update_user_role( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, req: user_role_api::UpdateUserRoleRequest, _req_state: ReqState, @@ -117,7 +117,7 @@ pub async fn update_user_role( } pub async fn transfer_org_ownership( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, req: user_role_api::TransferOrgOwnershipRequest, _req_state: ReqState, @@ -169,7 +169,7 @@ pub async fn transfer_org_ownership( } pub async fn accept_invitation( - state: AppState, + state: SessionState, user_token: auth::UserFromToken, req: user_role_api::AcceptInvitationRequest, ) -> UserResponse<()> { @@ -199,7 +199,7 @@ pub async fn accept_invitation( } pub async fn merchant_select( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, req: user_role_api::MerchantSelectRequest, ) -> UserResponse> { @@ -253,7 +253,7 @@ pub async fn merchant_select( } pub async fn merchant_select_token_only_flow( - state: AppState, + state: SessionState, user_token: auth::UserFromSinglePurposeToken, req: user_role_api::MerchantSelectRequest, ) -> UserResponse> { @@ -303,7 +303,7 @@ pub async fn merchant_select_token_only_flow( } pub async fn delete_user_role( - state: AppState, + state: SessionState, user_from_token: auth::UserFromToken, request: user_role_api::DeleteUserRoleRequest, _req_state: ReqState, diff --git a/crates/router/src/core/user_role/role.rs b/crates/router/src/core/user_role/role.rs index 504d5dd632be..386156f58e74 100644 --- a/crates/router/src/core/user_role/role.rs +++ b/crates/router/src/core/user_role/role.rs @@ -7,7 +7,7 @@ use error_stack::{report, ResultExt}; use crate::{ consts, core::errors::{StorageErrorExt, UserErrors, UserResponse}, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, services::{ authentication::{blacklist, UserFromToken}, authorization::roles::{self, predefined_roles::PREDEFINED_ROLES}, @@ -18,7 +18,7 @@ use crate::{ }; pub async fn get_role_from_token_with_permissions( - state: AppState, + state: SessionState, user_from_token: UserFromToken, ) -> UserResponse { let role_info = user_from_token @@ -38,7 +38,7 @@ pub async fn get_role_from_token_with_permissions( } pub async fn get_role_from_token_with_groups( - state: AppState, + state: SessionState, user_from_token: UserFromToken, ) -> UserResponse { let role_info = user_from_token @@ -54,7 +54,7 @@ pub async fn get_role_from_token_with_groups( } pub async fn create_role( - state: AppState, + state: SessionState, user_from_token: UserFromToken, req: role_api::CreateRoleRequest, _req_state: ReqState, @@ -107,7 +107,7 @@ pub async fn create_role( // TODO: To be deprecated once groups are stable pub async fn list_invitable_roles_with_permissions( - state: AppState, + state: SessionState, user_from_token: UserFromToken, ) -> UserResponse { let predefined_roles_map = PREDEFINED_ROLES @@ -156,7 +156,7 @@ pub async fn list_invitable_roles_with_permissions( } pub async fn list_invitable_roles_with_groups( - state: AppState, + state: SessionState, user_from_token: UserFromToken, ) -> UserResponse { let predefined_roles_map = PREDEFINED_ROLES @@ -198,7 +198,7 @@ pub async fn list_invitable_roles_with_groups( // TODO: To be deprecated once groups are stable pub async fn get_role_with_permissions( - state: AppState, + state: SessionState, user_from_token: UserFromToken, role: role_api::GetRoleRequest, ) -> UserResponse { @@ -232,7 +232,7 @@ pub async fn get_role_with_permissions( } pub async fn get_role_with_groups( - state: AppState, + state: SessionState, user_from_token: UserFromToken, role: role_api::GetRoleRequest, ) -> UserResponse { @@ -260,7 +260,7 @@ pub async fn get_role_with_groups( } pub async fn update_role( - state: AppState, + state: SessionState, user_from_token: UserFromToken, req: role_api::UpdateRoleRequest, role_id: &str, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index e585724e96a0..679838a6dd53 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -25,7 +25,7 @@ use crate::{ consts, core::errors::{self, RouterResult, StorageErrorExt}, db::StorageInterface, - routes::AppState, + routes::SessionState, types::{ self, domain, storage::{self, enums}, @@ -45,7 +45,7 @@ const IRRELEVANT_ATTEMPT_ID_IN_DISPUTE_FLOW: &str = "irrelevant_attempt_id_in_di #[cfg(feature = "payouts")] #[instrument(skip_all)] pub async fn get_mca_for_payout<'a>( - state: &'a AppState, + state: &'a SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -72,7 +72,7 @@ pub async fn get_mca_for_payout<'a>( #[cfg(feature = "payouts")] #[instrument(skip_all)] pub async fn construct_payout_router_data<'a, F>( - state: &'a AppState, + state: &'a SessionState, connector_name: &api_models::enums::Connector, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -214,7 +214,7 @@ pub async fn construct_payout_router_data<'a, F>( #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn construct_refund_router_data<'a, F>( - state: &'a AppState, + state: &'a SessionState, connector_id: &str, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, @@ -263,7 +263,7 @@ pub async fn construct_refund_router_data<'a, F>( .change_context(errors::ApiErrorResponse::InternalServerError)?; let webhook_url = Some(helpers::create_webhook_url( - &state.conf.server.base_url.clone(), + &state.base_url.clone(), &merchant_account.merchant_id, &connector_id.to_string(), )); @@ -513,7 +513,7 @@ pub fn validate_dispute_stage_and_dispute_status( #[instrument(skip_all)] pub async fn construct_accept_dispute_router_data<'a>( - state: &'a AppState, + state: &'a SessionState, payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, @@ -607,7 +607,7 @@ pub async fn construct_accept_dispute_router_data<'a>( #[instrument(skip_all)] pub async fn construct_submit_evidence_router_data<'a>( - state: &'a AppState, + state: &'a SessionState, payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, @@ -701,7 +701,7 @@ pub async fn construct_submit_evidence_router_data<'a>( #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn construct_upload_file_router_data<'a>( - state: &'a AppState, + state: &'a SessionState, payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, @@ -799,7 +799,7 @@ pub async fn construct_upload_file_router_data<'a>( #[instrument(skip_all)] pub async fn construct_defend_dispute_router_data<'a>( - state: &'a AppState, + state: &'a SessionState, payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, @@ -895,7 +895,7 @@ pub async fn construct_defend_dispute_router_data<'a>( #[instrument(skip_all)] pub async fn construct_retrieve_file_router_data<'a>( - state: &'a AppState, + state: &'a SessionState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, file_metadata: &diesel_models::file::FileMetadata, diff --git a/crates/router/src/core/verification.rs b/crates/router/src/core/verification.rs index 802a4ec3c638..b6e71b2828fa 100644 --- a/crates/router/src/core/verification.rs +++ b/crates/router/src/core/verification.rs @@ -4,12 +4,12 @@ use common_utils::{errors::CustomResult, request::RequestContent}; use error_stack::ResultExt; use masking::ExposeInterface; -use crate::{core::errors, headers, logger, routes::AppState, services}; +use crate::{core::errors, headers, logger, routes::SessionState, services}; const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant"; pub async fn verify_merchant_creds_for_applepay( - state: AppState, + state: SessionState, body: verifications::ApplepayMerchantVerificationRequest, merchant_id: String, ) -> CustomResult, errors::ApiErrorResponse> @@ -83,7 +83,7 @@ pub async fn verify_merchant_creds_for_applepay( } pub async fn get_verified_apple_domains_with_mid_mca_id( - state: AppState, + state: SessionState, merchant_id: String, merchant_connector_id: String, ) -> CustomResult< diff --git a/crates/router/src/core/verification/utils.rs b/crates/router/src/core/verification/utils.rs index 56960d3cb480..7518091ee871 100644 --- a/crates/router/src/core/verification/utils.rs +++ b/crates/router/src/core/verification/utils.rs @@ -4,13 +4,13 @@ use error_stack::{Report, ResultExt}; use crate::{ core::errors::{self, utils::StorageErrorExt}, logger, - routes::AppState, + routes::SessionState, types, types::storage, }; pub async fn check_existence_and_add_domain_to_db( - state: &AppState, + state: &SessionState, merchant_id: String, merchant_connector_id: String, domain_from_req: Vec, diff --git a/crates/router/src/core/verify_connector.rs b/crates/router/src/core/verify_connector.rs index 8a8b0a14f7db..f42f9336a18b 100644 --- a/crates/router/src/core/verify_connector.rs +++ b/crates/router/src/core/verify_connector.rs @@ -13,11 +13,11 @@ use crate::{ transformers::ForeignInto, }, utils::verify_connector as utils, - AppState, + SessionState, }; pub async fn verify_connector_credentials( - state: AppState, + state: SessionState, req: VerifyConnectorRequest, ) -> errors::RouterResponse<()> { let boxed_connector = api::ConnectorData::get_connector_by_name( diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index c5055d4c8c25..7962e86e1228 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -39,10 +39,10 @@ use crate::{ }, logger, routes::{ - app::{AppStateInfo, ReqState}, + app::{ReqState, SessionStateInfo}, lock_utils, metrics::request::add_attributes, - AppState, + SessionState, }, services::{self, authentication as auth}, types::{ @@ -59,7 +59,7 @@ const OUTGOING_WEBHOOK_TIMEOUT_SECS: u64 = 5; const MERCHANT_ID: &str = "merchant_id"; pub async fn payments_incoming_webhook_flow( - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, @@ -204,7 +204,7 @@ pub async fn payments_incoming_webhook_flow( #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn refunds_incoming_webhook_flow( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, key_store: domain::MerchantKeyStore, @@ -302,7 +302,7 @@ pub async fn refunds_incoming_webhook_flow( } pub async fn get_payment_attempt_from_object_reference_id( - state: &AppState, + state: &SessionState, object_reference_id: webhooks::ObjectReferenceId, merchant_account: &domain::MerchantAccount, ) -> CustomResult< @@ -342,7 +342,7 @@ pub async fn get_payment_attempt_from_object_reference_id( #[allow(clippy::too_many_arguments)] pub async fn get_or_update_dispute_object( - state: AppState, + state: SessionState, option_dispute: Option, dispute_details: api::disputes::DisputePayload, merchant_id: &str, @@ -418,7 +418,7 @@ pub async fn get_or_update_dispute_object( #[allow(clippy::too_many_arguments)] pub async fn external_authentication_incoming_webhook_flow( - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -592,7 +592,7 @@ pub async fn external_authentication_incoming_webhook_flow( } pub async fn mandates_incoming_webhook_flow( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, key_store: domain::MerchantKeyStore, @@ -680,7 +680,7 @@ pub async fn mandates_incoming_webhook_flow( #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub(crate) async fn frm_incoming_webhook_flow( - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -792,7 +792,7 @@ pub(crate) async fn frm_incoming_webhook_flow( #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn disputes_incoming_webhook_flow( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, key_store: domain::MerchantKeyStore, @@ -862,7 +862,7 @@ pub async fn disputes_incoming_webhook_flow( } async fn bank_transfer_webhook_flow( - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, @@ -951,7 +951,7 @@ async fn bank_transfer_webhook_flow( #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub(crate) async fn create_event_and_trigger_outgoing_webhook( - state: AppState, + state: SessionState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, merchant_key_store: &domain::MerchantKeyStore, @@ -1091,7 +1091,7 @@ pub(crate) async fn create_event_and_trigger_outgoing_webhook( #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub(crate) async fn trigger_webhook_and_raise_event( - state: AppState, + state: SessionState, business_profile: diesel_models::business_profile::BusinessProfile, merchant_key_store: &domain::MerchantKeyStore, event: domain::Event, @@ -1123,7 +1123,7 @@ pub(crate) async fn trigger_webhook_and_raise_event( } async fn trigger_webhook_to_merchant( - state: AppState, + state: SessionState, business_profile: diesel_models::business_profile::BusinessProfile, merchant_key_store: &domain::MerchantKeyStore, event: domain::Event, @@ -1189,7 +1189,7 @@ async fn trigger_webhook_to_merchant( logger::debug!(outgoing_webhook_response=?response); let update_event_if_client_error = - |state: AppState, + |state: SessionState, merchant_key_store: domain::MerchantKeyStore, merchant_id: String, event_id: String, @@ -1234,7 +1234,7 @@ async fn trigger_webhook_to_merchant( }; let api_client_error_handler = - |state: AppState, + |state: SessionState, merchant_key_store: domain::MerchantKeyStore, merchant_id: String, event_id: String, @@ -1261,7 +1261,7 @@ async fn trigger_webhook_to_merchant( Ok::<_, error_stack::Report>(()) }; - let update_event_in_storage = |state: AppState, + let update_event_in_storage = |state: SessionState, merchant_key_store: domain::MerchantKeyStore, merchant_id: String, event_id: String, @@ -1339,7 +1339,7 @@ async fn trigger_webhook_to_merchant( ) }; let success_response_handler = - |state: AppState, + |state: SessionState, merchant_id: String, process_tracker: Option, business_status: &'static str| async move { @@ -1521,7 +1521,7 @@ async fn trigger_webhook_to_merchant( } fn raise_webhooks_analytics_event( - state: AppState, + state: SessionState, trigger_webhook_result: CustomResult<(), errors::WebhooksFlowError>, content: Option, merchant_id: String, @@ -1558,7 +1558,7 @@ fn raise_webhooks_analytics_event( #[allow(clippy::too_many_arguments)] pub async fn webhooks_wrapper( flow: &impl router_env::types::FlowMetric, - state: AppState, + state: SessionState, req_state: ReqState, req: &actix_web::HttpRequest, merchant_account: domain::MerchantAccount, @@ -1622,7 +1622,7 @@ pub async fn webhooks_wrapper( #[instrument(skip_all)] pub async fn webhooks_core( - state: AppState, + state: SessionState, req_state: ReqState, req: &actix_web::HttpRequest, merchant_account: domain::MerchantAccount, @@ -2019,7 +2019,7 @@ pub async fn get_payment_id( } fn get_connector_by_connector_name( - state: &AppState, + state: &SessionState, connector_name: &str, merchant_connector_id: Option, ) -> CustomResult<(&'static (dyn api::Connector + Sync), String), errors::ApiErrorResponse> { @@ -2067,7 +2067,7 @@ fn get_connector_by_connector_name( /// This function fetches the merchant connector account ( if the url used is /{merchant_connector_id}) /// if merchant connector id is not passed in the request, then this will return None for mca async fn fetch_optional_mca_and_connector( - state: &AppState, + state: &SessionState, merchant_account: &domain::MerchantAccount, connector_name_or_mca_id: &str, key_store: &domain::MerchantKeyStore, diff --git a/crates/router/src/core/webhooks/webhook_events.rs b/crates/router/src/core/webhooks/webhook_events.rs index f248edd652bf..2cb16a53b3a8 100644 --- a/crates/router/src/core/webhooks/webhook_events.rs +++ b/crates/router/src/core/webhooks/webhook_events.rs @@ -4,7 +4,7 @@ use router_env::{instrument, tracing}; use crate::{ core::errors::{self, RouterResponse, StorageErrorExt}, - routes::AppState, + routes::SessionState, services::ApplicationResponse, types::{api, domain, storage, transformers::ForeignTryFrom}, utils::{OptionExt, StringExt}, @@ -20,7 +20,7 @@ enum MerchantAccountOrBusinessProfile { #[instrument(skip(state))] pub async fn list_initial_delivery_attempts( - state: AppState, + state: SessionState, merchant_id_or_profile_id: String, constraints: api::webhook_events::EventListConstraints, ) -> RouterResponse> { @@ -108,7 +108,7 @@ pub async fn list_initial_delivery_attempts( #[instrument(skip(state))] pub async fn list_delivery_attempts( - state: AppState, + state: SessionState, merchant_id_or_profile_id: String, initial_attempt_id: String, ) -> RouterResponse> { @@ -157,7 +157,7 @@ pub async fn list_delivery_attempts( #[instrument(skip(state))] pub async fn retry_delivery_attempt( - state: AppState, + state: SessionState, merchant_id_or_profile_id: String, event_id: String, ) -> RouterResponse { @@ -254,7 +254,7 @@ pub async fn retry_delivery_attempt( } async fn determine_identifier_and_get_key_store( - state: AppState, + state: SessionState, merchant_id_or_profile_id: String, ) -> errors::RouterResult<(MerchantAccountOrBusinessProfile, domain::MerchantKeyStore)> { let store = state.store.as_ref(); diff --git a/crates/router/src/db/api_keys.rs b/crates/router/src/db/api_keys.rs index 5d2f1c57a2a1..ea63a8817043 100644 --- a/crates/router/src/db/api_keys.rs +++ b/crates/router/src/db/api_keys.rs @@ -373,7 +373,7 @@ impl ApiKeyInterface for MockDb { #[cfg(test)] mod tests { use storage_impl::redis::{ - cache::{self, CacheKind, ACCOUNTS_CACHE}, + cache::{self, CacheKey, CacheKind, ACCOUNTS_CACHE}, kv_store::RedisConnInterface, pub_sub::PubSubInterface, }; @@ -525,15 +525,12 @@ mod tests { .await .unwrap(); - assert!( - ACCOUNTS_CACHE - .get_val::(&format!( - "{}_{}", - merchant_id, - hashed_api_key.into_inner() - ),) - .await - .is_none() - ) + assert!(ACCOUNTS_CACHE + .get_val::(CacheKey { + key: format!("{}_{}", merchant_id, hashed_api_key.into_inner()), + prefix: String::default(), + },) + .await + .is_none()) } } diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs index 0e3b365ae075..910ad085f631 100644 --- a/crates/router/src/db/kafka_store.rs +++ b/crates/router/src/db/kafka_store.rs @@ -1098,8 +1098,9 @@ impl QueueInterface for KafkaStore { entry_id: &RedisEntryId, fields: Vec<(&str, String)>, ) -> CustomResult<(), RedisError> { + let stream_name = format!("{}_{}", &self.tenant_id.0, stream); self.diesel_store - .stream_append_entry(stream, entry_id, fields) + .stream_append_entry(&stream_name, entry_id, fields) .await } diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index b0f57367dbee..aea37b517be6 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -769,7 +769,7 @@ mod merchant_connector_account_cache_tests { use error_stack::ResultExt; use masking::PeekInterface; use storage_impl::redis::{ - cache::{self, CacheKind, ACCOUNTS_CACHE}, + cache::{self, CacheKey, CacheKind, ACCOUNTS_CACHE}, kv_store::RedisConnInterface, pub_sub::PubSubInterface, }; @@ -902,10 +902,10 @@ mod merchant_connector_account_cache_tests { .unwrap(); assert!(ACCOUNTS_CACHE - .get_val::(&format!( - "{}_{}", - merchant_id, connector_label - ),) + .get_val::(CacheKey { + key: format!("{}_{}", merchant_id, connector_label), + prefix: String::default(), + },) .await .is_none()) } diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index 2e9ecc13dcb1..7344b85d150d 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -32,7 +32,7 @@ use actix_web::{ use http::StatusCode; use hyperswitch_interfaces::secrets_interface::secret_state::SecuredSecret; use router_env::tracing::Instrument; -use routes::AppState; +use routes::{AppState, SessionState}; use storage_impl::errors::ApplicationResult; use tokio::sync::{mpsc, oneshot}; diff --git a/crates/router/src/routes.rs b/crates/router/src/routes.rs index cd216cb0e81b..9f13635ca901 100644 --- a/crates/router/src/routes.rs +++ b/crates/router/src/routes.rs @@ -60,7 +60,8 @@ pub use self::app::Recon; pub use self::app::{ ApiKeys, AppState, BusinessProfile, Cache, Cards, Configs, ConnectorOnboarding, Customers, Disputes, EphemeralKey, Files, Gsm, Health, Mandates, MerchantAccount, - MerchantConnectorAccount, PaymentLink, PaymentMethods, Payments, Poll, Refunds, User, Webhooks, + MerchantConnectorAccount, PaymentLink, PaymentMethods, Payments, Poll, Refunds, SessionState, + User, Webhooks, }; #[cfg(feature = "olap")] pub use self::app::{Blocklist, Routing, Verify, WebhookEvents}; diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index a7d17e602d53..5af3a2bef25c 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use actix_web::{web, Scope}; #[cfg(all(feature = "business_profile_routing", feature = "olap"))] @@ -14,7 +14,7 @@ use hyperswitch_interfaces::{ }; use router_env::tracing_actix_web::RequestId; use scheduler::SchedulerInterface; -use storage_impl::MockDb; +use storage_impl::{config::TenantConfig, redis::RedisStore, MockDb}; use tokio::sync::oneshot; #[cfg(feature = "olap")] @@ -43,7 +43,8 @@ use super::{ephemeral_key::*, webhooks::*}; use super::{pm_auth, poll::retrieve_poll_status}; #[cfg(feature = "olap")] pub use crate::analytics::opensearch::OpenSearchClient; -use crate::configs::secrets_transformers; +#[cfg(feature = "olap")] +use crate::analytics::AnalyticsProvider; #[cfg(all(feature = "frm", feature = "oltp"))] use crate::routes::fraud_check as frm_routes; #[cfg(all(feature = "recon", feature = "olap"))] @@ -56,7 +57,11 @@ pub use crate::{ db::{StorageImpl, StorageInterface}, events::EventsHandler, routes::cards_info::card_iin_info, - services::get_store, + services::{get_cache_store, get_store}, +}; +use crate::{ + configs::{secrets_transformers, Settings}, + db::kafka_store::{KafkaStore, TenantID}, }; #[derive(Clone)] @@ -64,33 +69,87 @@ pub struct ReqState { pub event_context: events::EventContext, } +#[derive(Clone)] +pub struct SessionState { + pub store: Box, + pub conf: Arc>, + pub api_client: Box, + pub event_handler: EventsHandler, + #[cfg(feature = "email")] + pub email_client: Arc, + #[cfg(feature = "olap")] + pub pool: AnalyticsProvider, + pub file_storage_client: Box, + pub request_id: Option, + pub base_url: String, + pub tenant: String, + #[cfg(feature = "olap")] + pub opensearch_client: Arc, +} +impl scheduler::SchedulerSessionState for SessionState { + fn get_db(&self) -> Box { + self.store.get_scheduler_db() + } +} +impl SessionState { + pub fn get_req_state(&self) -> ReqState { + ReqState { + event_context: events::EventContext::new(self.event_handler.clone()), + } + } +} + +pub trait SessionStateInfo { + fn conf(&self) -> settings::Settings; + fn store(&self) -> Box; + fn event_handler(&self) -> EventsHandler; + fn get_request_id(&self) -> Option; + fn add_request_id(&mut self, request_id: RequestId); +} + +impl SessionStateInfo for SessionState { + fn store(&self) -> Box { + self.store.to_owned() + } + fn conf(&self) -> settings::Settings { + self.conf.as_ref().to_owned() + } + fn event_handler(&self) -> EventsHandler { + self.event_handler.clone() + } + fn get_request_id(&self) -> Option { + self.api_client.get_request_id() + } + fn add_request_id(&mut self, request_id: RequestId) { + self.api_client.add_request_id(request_id); + self.store.add_request_id(request_id.to_string()); + self.request_id.replace(request_id); + } +} #[derive(Clone)] pub struct AppState { pub flow_name: String, - pub store: Box, + pub stores: HashMap>, pub conf: Arc>, pub event_handler: EventsHandler, #[cfg(feature = "email")] pub email_client: Arc, pub api_client: Box, #[cfg(feature = "olap")] - pub pool: crate::analytics::AnalyticsProvider, + pub pools: HashMap, #[cfg(feature = "olap")] - pub opensearch_client: OpenSearchClient, + pub opensearch_client: Arc, pub request_id: Option, pub file_storage_client: Box, pub encryption_client: Box, } - impl scheduler::SchedulerAppState for AppState { - fn get_db(&self) -> Box { - self.store.get_scheduler_db() + fn get_tenants(&self) -> Vec { + self.conf.multitenancy.get_tenant_names() } } - pub trait AppStateInfo { fn conf(&self) -> settings::Settings; - fn store(&self) -> Box; fn event_handler(&self) -> EventsHandler; #[cfg(feature = "email")] fn email_client(&self) -> Arc; @@ -104,9 +163,6 @@ impl AppStateInfo for AppState { fn conf(&self) -> settings::Settings { self.conf.as_ref().to_owned() } - fn store(&self) -> Box { - self.store.to_owned() - } #[cfg(feature = "email")] fn email_client(&self) -> Arc { self.email_client.to_owned() @@ -116,7 +172,6 @@ impl AppStateInfo for AppState { } fn add_request_id(&mut self, request_id: RequestId) { self.api_client.add_request_id(request_id); - self.store.add_request_id(request_id.to_string()); self.request_id.replace(request_id); } @@ -183,43 +238,38 @@ impl AppState { #[allow(clippy::expect_used)] #[cfg(feature = "olap")] - let opensearch_client = conf - .opensearch - .get_opensearch_client() - .await - .expect("Failed to create opensearch client"); - - let store: Box = match storage_impl { - StorageImpl::Postgresql | StorageImpl::PostgresqlTest => match &event_handler { - EventsHandler::Kafka(kafka_client) => Box::new( - crate::db::KafkaStore::new( - #[allow(clippy::expect_used)] - get_store(&conf.clone(), shut_down_signal, testable) - .await - .expect("Failed to create store"), - kafka_client.clone(), - crate::db::kafka_store::TenantID("default".to_string()), - ) - .await, - ), - EventsHandler::Logs(_) => Box::new( - #[allow(clippy::expect_used)] - get_store(&conf, shut_down_signal, testable) - .await - .expect("Failed to create store"), - ), - }, - #[allow(clippy::expect_used)] - StorageImpl::Mock => Box::new( - MockDb::new(&conf.redis) - .await - .expect("Failed to create mock store"), - ), - }; + let opensearch_client = Arc::new( + conf.opensearch + .get_opensearch_client() + .await + .expect("Failed to create opensearch client"), + ); #[cfg(feature = "olap")] - let pool = - crate::analytics::AnalyticsProvider::from_conf(conf.analytics.get_inner()).await; + let mut pools: HashMap = HashMap::new(); + let mut stores = HashMap::new(); + #[allow(clippy::expect_used)] + let cache_store = get_cache_store(&conf.clone(), shut_down_signal, testable) + .await + .expect("Failed to create store"); + for (tenant_name, tenant) in conf.clone().multitenancy.get_tenants() { + let store: Box = Self::get_store_interface( + &storage_impl, + &event_handler, + &conf, + tenant, + Arc::clone(&cache_store), + testable, + ) + .await; + stores.insert(tenant_name.clone(), store); + #[cfg(feature = "olap")] + let pool = + AnalyticsProvider::from_conf(conf.analytics.get_inner(), tenant_name.as_str()) + .await; + #[cfg(feature = "olap")] + pools.insert(tenant_name.clone(), pool); + } #[cfg(feature = "email")] let email_client = Arc::new(create_email_client(&conf).await); @@ -228,14 +278,14 @@ impl AppState { Self { flow_name: String::from("default"), - store, + stores, conf: Arc::new(conf), #[cfg(feature = "email")] email_client, api_client, event_handler, #[cfg(feature = "olap")] - pool, + pools, #[cfg(feature = "olap")] opensearch_client, request_id: None, @@ -246,6 +296,43 @@ impl AppState { .await } + async fn get_store_interface( + storage_impl: &StorageImpl, + event_handler: &EventsHandler, + conf: &Settings, + tenant: &settings::Tenant, + cache_store: Arc, + testable: bool, + ) -> Box { + match storage_impl { + StorageImpl::Postgresql | StorageImpl::PostgresqlTest => match event_handler { + EventsHandler::Kafka(kafka_client) => Box::new( + KafkaStore::new( + #[allow(clippy::expect_used)] + get_store(&conf.clone(), tenant, Arc::clone(&cache_store), testable) + .await + .expect("Failed to create store"), + kafka_client.clone(), + TenantID(tenant.get_schema().to_string()), + ) + .await, + ), + EventsHandler::Logs(_) => Box::new( + #[allow(clippy::expect_used)] + get_store(conf, tenant, Arc::clone(&cache_store), testable) + .await + .expect("Failed to create store"), + ), + }, + #[allow(clippy::expect_used)] + StorageImpl::Mock => Box::new( + MockDb::new(&conf.redis) + .await + .expect("Failed to create mock store"), + ), + } + } + pub async fn new( conf: settings::Settings, shut_down_signal: oneshot::Sender<()>, @@ -265,6 +352,34 @@ impl AppState { event_context: events::EventContext::new(self.event_handler.clone()), } } + pub fn get_session_state(self: Arc, tenant: &str, err: F) -> Result + where + F: FnOnce() -> E + Copy, + { + Ok(SessionState { + store: self.stores.get(tenant).ok_or_else(err)?.clone(), + conf: Arc::clone(&self.conf), + api_client: self.api_client.clone(), + event_handler: self.event_handler.clone(), + #[cfg(feature = "olap")] + pool: self.pools.get(tenant).ok_or_else(err)?.clone(), + file_storage_client: self.file_storage_client.clone(), + request_id: self.request_id, + base_url: self + .conf + .multitenancy + .get_tenant(tenant) + .ok_or_else(err)? + .clone() + .base_url + .clone(), + tenant: tenant.to_string().clone(), + #[cfg(feature = "email")] + email_client: Arc::clone(&self.email_client), + #[cfg(feature = "olap")] + opensearch_client: Arc::clone(&self.opensearch_client), + }) + } } pub struct Health; diff --git a/crates/router/src/routes/customers.rs b/crates/router/src/routes/customers.rs index 4d86ae829e08..87366cf5c6d9 100644 --- a/crates/router/src/routes/customers.rs +++ b/crates/router/src/routes/customers.rs @@ -47,7 +47,7 @@ pub async fn customers_retrieve( let auth = if auth::is_jwt_auth(req.headers()) { Box::new(auth::JWTAuth(Permission::CustomerRead)) } else { - match auth::is_ephemeral_auth(req.headers(), &*state.store, &payload.customer_id).await { + match auth::is_ephemeral_auth(req.headers(), &payload.customer_id) { Ok(auth) => auth, Err(err) => return api::log_and_return_error_response(err), } diff --git a/crates/router/src/routes/dummy_connector/core.rs b/crates/router/src/routes/dummy_connector/core.rs index e8f84b3047eb..513a586d193a 100644 --- a/crates/router/src/routes/dummy_connector/core.rs +++ b/crates/router/src/routes/dummy_connector/core.rs @@ -1,4 +1,4 @@ -use app::AppState; +use app::SessionState; use common_utils::generate_id_with_default_len; use error_stack::ResultExt; @@ -10,7 +10,7 @@ use crate::{ }; pub async fn payment( - state: AppState, + state: SessionState, req: types::DummyConnectorPaymentRequest, ) -> types::DummyConnectorResponse { utils::tokio_mock_sleep( @@ -41,7 +41,7 @@ pub async fn payment( } pub async fn payment_data( - state: AppState, + state: SessionState, req: types::DummyConnectorPaymentRetrieveRequest, ) -> types::DummyConnectorResponse { utils::tokio_mock_sleep( @@ -55,7 +55,7 @@ pub async fn payment_data( } pub async fn payment_authorize( - state: AppState, + state: SessionState, req: types::DummyConnectorPaymentConfirmRequest, ) -> types::DummyConnectorResponse { let payment_data = utils::get_payment_data_by_attempt_id(&state, req.attempt_id.clone()).await; @@ -64,7 +64,7 @@ pub async fn payment_authorize( if let Ok(payment_data_inner) = payment_data { let return_url = format!( "{}/dummy-connector/complete/{}", - state.conf.server.base_url, req.attempt_id + state.base_url, req.attempt_id ); Ok(api::ApplicationResponse::FileData(( utils::get_authorize_page(payment_data_inner, return_url, dummy_connector_conf) @@ -83,7 +83,7 @@ pub async fn payment_authorize( } pub async fn payment_complete( - state: AppState, + state: SessionState, req: types::DummyConnectorPaymentCompleteRequest, ) -> types::DummyConnectorResponse<()> { utils::tokio_mock_sleep( @@ -145,7 +145,7 @@ pub async fn payment_complete( } pub async fn refund_payment( - state: AppState, + state: SessionState, req: types::DummyConnectorRefundRequest, ) -> types::DummyConnectorResponse { utils::tokio_mock_sleep( @@ -197,7 +197,7 @@ pub async fn refund_payment( } pub async fn refund_data( - state: AppState, + state: SessionState, req: types::DummyConnectorRefundRetrieveRequest, ) -> types::DummyConnectorResponse { let refund_id = req.refund_id; diff --git a/crates/router/src/routes/dummy_connector/utils.rs b/crates/router/src/routes/dummy_connector/utils.rs index 8bba182ad0a5..6211c3abf800 100644 --- a/crates/router/src/routes/dummy_connector/utils.rs +++ b/crates/router/src/routes/dummy_connector/utils.rs @@ -11,7 +11,7 @@ use super::{ consts, errors, types::{self, GetPaymentMethodDetails}, }; -use crate::{configs::settings, routes::AppState}; +use crate::{configs::settings, routes::SessionState}; pub async fn tokio_mock_sleep(delay: u64, tolerance: u64) { let mut rng = rand::thread_rng(); @@ -26,7 +26,7 @@ pub async fn tokio_mock_sleep(delay: u64, tolerance: u64) { } pub async fn store_data_in_redis( - state: &AppState, + state: &SessionState, key: String, data: impl serde::Serialize + Debug, ttl: i64, @@ -46,7 +46,7 @@ pub async fn store_data_in_redis( } pub async fn get_payment_data_from_payment_id( - state: &AppState, + state: &SessionState, payment_id: String, ) -> types::DummyConnectorResult { let redis_conn = state @@ -65,7 +65,7 @@ pub async fn get_payment_data_from_payment_id( } pub async fn get_payment_data_by_attempt_id( - state: &AppState, + state: &SessionState, attempt_id: String, ) -> types::DummyConnectorResult { let redis_conn = state @@ -336,12 +336,12 @@ impl ProcessPaymentAttempt for types::DummyConnectorPaymentMethodData { impl types::DummyConnectorPaymentData { pub fn process_payment_attempt( - state: &AppState, + state: &SessionState, payment_attempt: types::DummyConnectorPaymentAttempt, ) -> types::DummyConnectorResult { let redirect_url = format!( "{}/dummy-connector/authorize/{}", - state.conf.server.base_url, payment_attempt.attempt_id + state.base_url, payment_attempt.attempt_id ); payment_attempt .clone() diff --git a/crates/router/src/routes/health.rs b/crates/router/src/routes/health.rs index 7d35a91a31eb..721dbd6a78dd 100644 --- a/crates/router/src/routes/health.rs +++ b/crates/router/src/routes/health.rs @@ -40,7 +40,9 @@ pub async fn deep_health_check( .await } -async fn deep_health_check_func(state: app::AppState) -> RouterResponse { +async fn deep_health_check_func( + state: app::SessionState, +) -> RouterResponse { logger::info!("Deep health check was called"); logger::debug!("Database health check begin"); diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs index 96daf95d1156..e36a8fc3ea51 100644 --- a/crates/router/src/routes/payment_methods.rs +++ b/crates/router/src/routes/payment_methods.rs @@ -5,7 +5,7 @@ use error_stack::ResultExt; use router_env::{instrument, logger, tracing, Flow}; use time::PrimitiveDateTime; -use super::app::AppState; +use super::app::{AppState, SessionState}; use crate::{ core::{api_locking, errors, payment_methods::cards}, services::{api, authentication as auth, authorization::permissions::Permission}, @@ -139,11 +139,10 @@ pub async fn list_customer_payment_method_api( let payload = query_payload.into_inner(); let customer_id = customer_id.into_inner().0; - let ephemeral_auth = - match auth::is_ephemeral_auth(req.headers(), &*state.store, &customer_id).await { - Ok(auth) => auth, - Err(err) => return api::log_and_return_error_response(err), - }; + let ephemeral_auth = match auth::is_ephemeral_auth(req.headers(), &customer_id) { + Ok(auth) => auth, + Err(err) => return api::log_and_return_error_response(err), + }; Box::pin(api::server_wrap( flow, state, @@ -343,28 +342,28 @@ pub async fn default_payment_method_set_api( ) -> HttpResponse { let flow = Flow::DefaultPaymentMethodsSet; let payload = path.into_inner(); - let customer_id = payload.clone().customer_id; + let pc = payload.clone(); + let customer_id = &pc.customer_id; - let ephemeral_auth = - match auth::is_ephemeral_auth(req.headers(), &*state.store, &customer_id).await { - Ok(auth) => auth, - Err(err) => return api::log_and_return_error_response(err), - }; - let db = &*state.store.clone(); + let ephemeral_auth = match auth::is_ephemeral_auth(req.headers(), customer_id) { + Ok(auth) => auth, + Err(err) => return api::log_and_return_error_response(err), + }; Box::pin(api::server_wrap( flow, state, &req, payload, - |_state, auth: auth::AuthenticationData, default_payment_method, _| { + |state, auth: auth::AuthenticationData, default_payment_method, _| async move { cards::set_default_payment_method( - db, + &*state.clone().store, auth.merchant_account.merchant_id, auth.key_store, - &customer_id, + customer_id, default_payment_method.payment_method_id, auth.merchant_account.storage_scheme, ) + .await }, &*ephemeral_auth, api_locking::LockAction::NotApplicable, @@ -416,7 +415,7 @@ impl ParentPaymentMethodToken { &self, intent_created_at: Option, token: PaymentTokenData, - state: &AppState, + state: &SessionState, ) -> CustomResult<(), errors::ApiErrorResponse> { let token_json_str = token .encode_to_string_of_json() @@ -452,7 +451,7 @@ impl ParentPaymentMethodToken { .contains(&status) } - pub async fn delete(&self, state: &AppState) -> CustomResult<(), errors::ApiErrorResponse> { + pub async fn delete(&self, state: &SessionState) -> CustomResult<(), errors::ApiErrorResponse> { let redis_conn = state .store .get_redis_conn() diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index ab6b0f450db1..a89410a2b0f9 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -681,6 +681,7 @@ pub async fn payments_redirect_response( auth.merchant_account, auth.key_store, req, + ) }, &auth::MerchantIdAuth(merchant_id), @@ -742,6 +743,7 @@ pub async fn payments_redirect_response_with_creds_identifier( auth.merchant_account, auth.key_store, req, + ) }, &auth::MerchantIdAuth(merchant_id), @@ -786,6 +788,7 @@ pub async fn payments_complete_authorize_redirect( auth.merchant_account, auth.key_store, req, + ) }, &auth::MerchantIdAuth(merchant_id), @@ -1142,7 +1145,7 @@ pub async fn payments_reject( #[allow(clippy::too_many_arguments)] async fn authorize_verify_select( operation: Op, - state: app::AppState, + state: app::SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, diff --git a/crates/router/src/routes/recon.rs b/crates/router/src/routes/recon.rs index fc0794ff9e0b..053037b57a5f 100644 --- a/crates/router/src/routes/recon.rs +++ b/crates/router/src/routes/recon.rs @@ -4,7 +4,7 @@ use error_stack::ResultExt; use masking::{ExposeInterface, PeekInterface, Secret}; use router_env::Flow; -use super::AppState; +use super::{AppState, SessionState}; use crate::{ core::{ api_locking, @@ -70,7 +70,7 @@ pub async fn get_recon_token(state: web::Data, req: HttpRequest) -> Ht } pub async fn send_recon_request( - state: AppState, + state: SessionState, user: UserFromToken, ) -> RouterResponse { let db = &*state.store; @@ -150,7 +150,7 @@ pub async fn send_recon_request( } pub async fn recon_merchant_account_update( - state: AppState, + state: SessionState, req: recon_api::ReconUpdateMerchantRequest, ) -> RouterResponse { let merchant_id = &req.merchant_id.clone(); @@ -217,7 +217,7 @@ pub async fn recon_merchant_account_update( } pub async fn generate_recon_token( - state: AppState, + state: SessionState, req: ReconUser, ) -> RouterResponse { let db = &*state.store; @@ -243,7 +243,7 @@ pub async fn generate_recon_token( pub async fn get_recon_auth_token( user: UserFromStorage, - state: AppState, + state: SessionState, ) -> RouterResult> { ReconToken::new_token(user.0.user_id.clone(), &state.conf).await } diff --git a/crates/router/src/services.rs b/crates/router/src/services.rs index bb50e27b8cd6..5c860aa8a615 100644 --- a/crates/router/src/services.rs +++ b/crates/router/src/services.rs @@ -13,12 +13,14 @@ pub mod recon; #[cfg(feature = "email")] pub mod email; +use std::sync::Arc; + use error_stack::ResultExt; use hyperswitch_domain_models::errors::StorageResult; use masking::{ExposeInterface, StrongSecret}; #[cfg(feature = "kv_store")] use storage_impl::KVRouterStore; -use storage_impl::RouterStore; +use storage_impl::{redis::RedisStore, RouterStore}; use tokio::sync::oneshot; pub use self::{api::*, encryption::*}; @@ -40,7 +42,8 @@ pub type Store = KVRouterStore; #[allow(clippy::expect_used)] pub async fn get_store( config: &Settings, - shut_down_signal: oneshot::Sender<()>, + tenant: &crate::configs::settings::Tenant, + cache_store: Arc, test_transaction: bool, ) -> StorageResult { let master_config = config.master_database.clone().into_inner(); @@ -61,13 +64,13 @@ pub async fn get_store( let conf = (master_config.into(), replica_config.into()); let store: RouterStore = if test_transaction { - RouterStore::test_store(conf, &config.redis, master_enc_key).await? + RouterStore::test_store(conf, tenant, &config.redis, master_enc_key).await? } else { RouterStore::from_config( conf, - &config.redis, + tenant, master_enc_key, - shut_down_signal, + cache_store, storage_impl::redis::cache::PUB_SUB_CHANNEL, ) .await? @@ -85,6 +88,15 @@ pub async fn get_store( Ok(store) } +#[allow(clippy::expect_used)] +pub async fn get_cache_store( + config: &Settings, + shut_down_signal: oneshot::Sender<()>, + _test_transaction: bool, +) -> StorageResult> { + RouterStore::::cache_store(&config.redis, shut_down_signal).await +} + #[inline] pub fn generate_aes256_key() -> errors::CustomResult<[u8; 32], common_utils::errors::CryptoError> { use ring::rand::SecureRandom; diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 5f69a9d40339..098060e144b2 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -1,14 +1,16 @@ pub mod client; pub mod request; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, error::Error, fmt::Debug, future::Future, str, + sync::Arc, time::{Duration, Instant}, }; +use actix_http::header::HeaderMap; use actix_web::{ body, http::header::HeaderValue, web, FromRequest, HttpRequest, HttpResponse, Responder, ResponseError, @@ -45,9 +47,9 @@ use crate::{ }, logger, routes::{ - app::{AppStateInfo, ReqState}, + app::{AppStateInfo, ReqState, SessionStateInfo}, metrics::{self, request as metrics_request}, - AppState, + AppState, SessionState, }, types::{ self, @@ -174,7 +176,7 @@ pub trait ConnectorIntegration: ConnectorIntegrationAny, - _app_state: &AppState, + _app_state: &SessionState, ) -> CustomResult<(), errors::ConnectorError> { Ok(()) } @@ -184,7 +186,7 @@ pub trait ConnectorIntegration: ConnectorIntegrationAny, - _app_state: &AppState, + _app_state: &SessionState, ) -> CustomResult<(), errors::ConnectorError> { Ok(()) } @@ -297,7 +299,7 @@ pub async fn execute_connector_processing_step< Req: Debug + Clone + 'static, Resp: Debug + Clone + 'static, >( - state: &'b AppState, + state: &'b SessionState, connector_integration: BoxedConnectorIntegration<'a, T, Req, Resp>, req: &'b types::RouterData, call_connector_action: payments::CallConnectorAction, @@ -555,7 +557,7 @@ where #[instrument(skip_all)] pub async fn call_connector_api( - state: &AppState, + state: &SessionState, request: Request, flow_name: &str, ) -> CustomResult, errors::ApiClientError> { @@ -591,7 +593,7 @@ pub async fn call_connector_api( #[instrument(skip_all)] pub async fn send_request( - state: &AppState, + state: &SessionState, request: Request, option_timeout_secs: Option, ) -> CustomResult { @@ -915,15 +917,16 @@ pub enum AuthFlow { pub async fn server_wrap_util<'a, 'b, U, T, Q, F, Fut, E, OErr>( flow: &'a impl router_env::types::FlowMetric, state: web::Data, + incoming_request_header: &HeaderMap, mut request_state: ReqState, request: &'a HttpRequest, payload: T, func: F, - api_auth: &dyn AuthenticateAndFetch, + api_auth: &dyn AuthenticateAndFetch, lock_action: api_locking::LockAction, ) -> CustomResult, OErr> where - F: Fn(AppState, U, T, ReqState) -> Fut, + F: Fn(SessionState, U, T, ReqState) -> Fut, 'b: 'a, Fut: Future, E>>, Q: Serialize + Debug + 'a + ApiEventMetric, @@ -945,17 +948,49 @@ where let mut app_state = state.get_ref().clone(); - app_state.add_request_id(request_id); let start_instant = Instant::now(); let serialized_request = masking::masked_serialize(&payload) .attach_printable("Failed to serialize json request") .change_context(errors::ApiErrorResponse::InternalServerError.switch())?; let mut event_type = payload.get_api_event_type(); + let tenants: HashSet<_> = state + .conf + .multitenancy + .get_tenant_names() + .into_iter() + .collect(); + let tenant_id = if !state.conf.multitenancy.enabled { + common_utils::consts::DEFAULT_TENANT.to_string() + } else { + incoming_request_header + .get("x-tenant-id") + .and_then(|value| value.to_str().ok()) + .ok_or_else(|| errors::ApiErrorResponse::MissingTenantId.switch()) + .map(|req_tenant_id| { + if !tenants.contains(req_tenant_id) { + Err(errors::ApiErrorResponse::InvalidTenant { + tenant_id: req_tenant_id.to_string(), + } + .switch()) + } else { + Ok(req_tenant_id.to_string()) + } + })?? + }; + // let tenant_id = "public".to_string(); + let mut session_state = + Arc::new(app_state.clone()).get_session_state(tenant_id.as_str(), || { + errors::ApiErrorResponse::InvalidTenant { + tenant_id: tenant_id.clone(), + } + .switch() + })?; + session_state.add_request_id(request_id); // Currently auth failures are not recorded as API events let (auth_out, auth_type) = api_auth - .authenticate_and_fetch(request.headers(), &app_state) + .authenticate_and_fetch(request.headers(), &session_state) .await .switch()?; @@ -975,14 +1010,14 @@ where let output = { lock_action .clone() - .perform_locking_action(&app_state, merchant_id.to_owned()) + .perform_locking_action(&session_state, merchant_id.to_owned()) .await .switch()?; - let res = func(app_state.clone(), auth_out, payload, request_state) + let res = func(session_state.clone(), auth_out, payload, request_state) .await .switch(); lock_action - .free_lock_action(&app_state, merchant_id.to_owned()) + .free_lock_action(&session_state, merchant_id.to_owned()) .await .switch()?; res @@ -1064,11 +1099,11 @@ pub async fn server_wrap<'a, T, U, Q, F, Fut, E>( request: &'a HttpRequest, payload: T, func: F, - api_auth: &dyn AuthenticateAndFetch, + api_auth: &dyn AuthenticateAndFetch, lock_action: api_locking::LockAction, ) -> HttpResponse where - F: Fn(AppState, U, T, ReqState) -> Fut, + F: Fn(SessionState, U, T, ReqState) -> Fut, Fut: Future, E>>, Q: Serialize + Debug + ApiEventMetric + 'a, T: Debug + Serialize + ApiEventMetric, @@ -1109,6 +1144,7 @@ where server_wrap_util( &flow, state.clone(), + incoming_request_header, req_state, request, payload, diff --git a/crates/router/src/services/api/client.rs b/crates/router/src/services/api/client.rs index d6c55baf602b..add93e991194 100644 --- a/crates/router/src/services/api/client.rs +++ b/crates/router/src/services/api/client.rs @@ -15,7 +15,7 @@ use crate::{ errors::{ApiClientError, CustomResult}, payments, }, - routes::AppState, + routes::SessionState, }; static NON_PROXIED_CLIENT: OnceCell = OnceCell::new(); @@ -165,7 +165,7 @@ where async fn send_request( &self, - state: &AppState, + state: &SessionState, request: Request, option_timeout_secs: Option, forward_to_kafka: bool, @@ -340,7 +340,7 @@ impl ApiClient for ProxyClient { } async fn send_request( &self, - state: &AppState, + state: &SessionState, request: Request, option_timeout_secs: Option, _forward_to_kafka: bool, @@ -392,7 +392,7 @@ impl ApiClient for MockApiClient { async fn send_request( &self, - _state: &AppState, + _state: &SessionState, _request: Request, _option_timeout_secs: Option, _forward_to_kafka: bool, diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index 64a7c8069f78..28f9ccd1a778 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -25,14 +25,13 @@ use crate::consts; #[cfg(feature = "olap")] use crate::core::errors::UserResult; #[cfg(feature = "recon")] -use crate::routes::AppState; +use crate::routes::SessionState; use crate::{ core::{ api_keys, errors::{self, utils::StorageErrorExt, RouterResult}, }, - db::StorageInterface, - routes::app::AppStateInfo, + routes::app::SessionStateInfo, services::api, types::domain, utils::OptionExt, @@ -226,7 +225,7 @@ impl GetUserIdFromAuth for UserFromSinglePurposeToken { #[async_trait] pub trait AuthenticateAndFetch where - A: AppStateInfo, + A: SessionStateInfo, { async fn authenticate_and_fetch( &self, @@ -243,7 +242,7 @@ pub struct NoAuth; #[async_trait] impl AuthenticateAndFetch<(), A> for NoAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -257,7 +256,7 @@ where #[async_trait] impl AuthenticateAndFetch for ApiKeyAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -335,7 +334,7 @@ pub(crate) struct SinglePurposeJWTAuth(pub TokenPurpose); #[async_trait] impl AuthenticateAndFetch for SinglePurposeJWTAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -368,7 +367,7 @@ where #[async_trait] impl AuthenticateAndFetch, A> for SinglePurposeJWTAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -403,7 +402,7 @@ pub struct AdminApiAuth; #[async_trait] impl AuthenticateAndFetch<(), A> for AdminApiAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -425,13 +424,42 @@ where } } +#[derive(Debug)] +pub struct EphemeralKeyAuth(pub id_type::CustomerId); + +#[async_trait] +impl AuthenticateAndFetch for EphemeralKeyAuth +where + A: SessionStateInfo + Sync, +{ + async fn authenticate_and_fetch( + &self, + request_headers: &HeaderMap, + state: &A, + ) -> RouterResult<(AuthenticationData, AuthenticationType)> { + let api_key = + get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?; + let ephemeral_key = state + .store() + .get_ephemeral_key(api_key) + .await + .change_context(errors::ApiErrorResponse::Unauthorized)?; + + if ephemeral_key.customer_id.ne(&self.0) { + return Err(report!(errors::ApiErrorResponse::InvalidEphemeralKey)); + } + MerchantIdAuth(ephemeral_key.merchant_id) + .authenticate_and_fetch(request_headers, state) + .await + } +} #[derive(Debug)] pub struct MerchantIdAuth(pub String); #[async_trait] impl AuthenticateAndFetch for MerchantIdAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -485,7 +513,7 @@ pub struct PublishableKeyAuth; #[async_trait] impl AuthenticateAndFetch for PublishableKeyAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -529,7 +557,7 @@ struct JwtAuthPayloadFetchUnit { #[async_trait] impl AuthenticateAndFetch<(), A> for JWTAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -558,7 +586,7 @@ where #[async_trait] impl AuthenticateAndFetch for JWTAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -596,7 +624,7 @@ pub struct JWTAuthMerchantFromRoute { #[async_trait] impl AuthenticateAndFetch<(), A> for JWTAuthMerchantFromRoute where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -633,7 +661,7 @@ pub struct JWTAuthMerchantOrProfileFromRoute { #[async_trait] impl AuthenticateAndFetch<(), A> for JWTAuthMerchantOrProfileFromRoute where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -690,7 +718,7 @@ where pub async fn parse_jwt_payload(headers: &HeaderMap, state: &A) -> RouterResult where T: serde::de::DeserializeOwned, - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { let token = match get_cookie_from_header(headers).and_then(cookies::parse_cookie) { Ok(cookies) => cookies, @@ -708,7 +736,7 @@ where #[async_trait] impl AuthenticateAndFetch for JWTAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -758,7 +786,7 @@ pub type AuthenticationDataWithUserId = (AuthenticationData, String); #[async_trait] impl AuthenticateAndFetch for JWTAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -809,7 +837,7 @@ pub struct DashboardNoPermissionAuth; #[async_trait] impl AuthenticateAndFetch for DashboardNoPermissionAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -840,7 +868,7 @@ where #[async_trait] impl AuthenticateAndFetch, A> for DashboardNoPermissionAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -871,7 +899,7 @@ where #[async_trait] impl AuthenticateAndFetch<(), A> for DashboardNoPermissionAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -890,7 +918,7 @@ where #[async_trait] impl AuthenticateAndFetch for DashboardNoPermissionAuth where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -987,7 +1015,7 @@ impl ClientSecretFetch for api_models::payment_methods::PaymentMethodUpdate { } } -pub fn get_auth_type_and_flow( +pub fn get_auth_type_and_flow( headers: &HeaderMap, ) -> RouterResult<( Box>, @@ -1009,7 +1037,7 @@ pub fn check_client_secret_and_get_auth( api::AuthFlow, )> where - T: AppStateInfo, + T: SessionStateInfo, ApiKeyAuth: AuthenticateAndFetch, PublishableKeyAuth: AuthenticateAndFetch, { @@ -1034,27 +1062,17 @@ where Ok((Box::new(ApiKeyAuth), api::AuthFlow::Merchant)) } -pub async fn is_ephemeral_auth( +pub fn is_ephemeral_auth( headers: &HeaderMap, - db: &dyn StorageInterface, customer_id: &id_type::CustomerId, ) -> RouterResult>> { let api_key = get_api_key(headers)?; if !api_key.starts_with("epk") { - return Ok(Box::new(ApiKeyAuth)); + Ok(Box::new(ApiKeyAuth)) + } else { + Ok(Box::new(EphemeralKeyAuth(customer_id.to_owned()))) } - - let ephemeral_key = db - .get_ephemeral_key(api_key) - .await - .change_context(errors::ApiErrorResponse::Unauthorized)?; - - if ephemeral_key.customer_id.ne(customer_id) { - return Err(report!(errors::ApiErrorResponse::InvalidEphemeralKey)); - } - - Ok(Box::new(MerchantIdAuth(ephemeral_key.merchant_id))) } pub fn is_jwt_auth(headers: &HeaderMap) -> bool { @@ -1064,7 +1082,7 @@ pub fn is_jwt_auth(headers: &HeaderMap) -> bool { .is_ok() } -pub async fn decode_jwt(token: &str, state: &impl AppStateInfo) -> RouterResult +pub async fn decode_jwt(token: &str, state: &impl SessionStateInfo) -> RouterResult where T: serde::de::DeserializeOwned, { @@ -1140,7 +1158,7 @@ pub struct ReconAdmin; #[cfg(feature = "recon")] impl AuthenticateAndFetch<(), A> for ReconAdmin where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { async fn authenticate_and_fetch( &self, @@ -1176,13 +1194,13 @@ impl AuthInfo for ReconUser { } #[cfg(all(feature = "olap", feature = "recon"))] #[async_trait] -impl AuthenticateAndFetch for ReconJWT { +impl AuthenticateAndFetch for ReconJWT { async fn authenticate_and_fetch( &self, request_headers: &HeaderMap, - state: &AppState, + state: &SessionState, ) -> RouterResult<(ReconUser, AuthenticationType)> { - let payload = parse_jwt_payload::(request_headers, state).await?; + let payload = parse_jwt_payload::(request_headers, state).await?; Ok(( ReconUser { diff --git a/crates/router/src/services/authentication/blacklist.rs b/crates/router/src/services/authentication/blacklist.rs index c1abb0647525..8a3aefd8fc04 100644 --- a/crates/router/src/services/authentication/blacklist.rs +++ b/crates/router/src/services/authentication/blacklist.rs @@ -13,17 +13,17 @@ use crate::consts::{EMAIL_TOKEN_BLACKLIST_PREFIX, EMAIL_TOKEN_TIME_IN_SECS}; use crate::{ consts::{JWT_TOKEN_TIME_IN_SECS, ROLE_BLACKLIST_PREFIX, USER_BLACKLIST_PREFIX}, core::errors::{ApiErrorResponse, RouterResult}, - routes::app::AppStateInfo, + routes::app::SessionStateInfo, }; #[cfg(feature = "olap")] use crate::{ core::errors::{UserErrors, UserResult}, - routes::AppState, + routes::SessionState, services::authorization as authz, }; #[cfg(feature = "olap")] -pub async fn insert_user_in_blacklist(state: &AppState, user_id: &str) -> UserResult<()> { +pub async fn insert_user_in_blacklist(state: &SessionState, user_id: &str) -> UserResult<()> { let user_blacklist_key = format!("{}{}", USER_BLACKLIST_PREFIX, user_id); let expiry = expiry_to_i64(JWT_TOKEN_TIME_IN_SECS).change_context(UserErrors::InternalServerError)?; @@ -39,7 +39,7 @@ pub async fn insert_user_in_blacklist(state: &AppState, user_id: &str) -> UserRe } #[cfg(feature = "olap")] -pub async fn insert_role_in_blacklist(state: &AppState, role_id: &str) -> UserResult<()> { +pub async fn insert_role_in_blacklist(state: &SessionState, role_id: &str) -> UserResult<()> { let role_blacklist_key = format!("{}{}", ROLE_BLACKLIST_PREFIX, role_id); let expiry = expiry_to_i64(JWT_TOKEN_TIME_IN_SECS).change_context(UserErrors::InternalServerError)?; @@ -58,7 +58,7 @@ pub async fn insert_role_in_blacklist(state: &AppState, role_id: &str) -> UserRe } #[cfg(feature = "olap")] -async fn invalidate_role_cache(state: &AppState, role_id: &str) -> RouterResult<()> { +async fn invalidate_role_cache(state: &SessionState, role_id: &str) -> RouterResult<()> { let redis_conn = get_redis_connection(state)?; redis_conn .delete_key(authz::get_cache_key_from_role_id(role_id).as_str()) @@ -67,7 +67,7 @@ async fn invalidate_role_cache(state: &AppState, role_id: &str) -> RouterResult< .change_context(ApiErrorResponse::InternalServerError) } -pub async fn check_user_in_blacklist( +pub async fn check_user_in_blacklist( state: &A, user_id: &str, token_expiry: u64, @@ -82,7 +82,7 @@ pub async fn check_user_in_blacklist( .map(|timestamp| timestamp.map_or(false, |timestamp| timestamp > token_issued_at)) } -pub async fn check_role_in_blacklist( +pub async fn check_role_in_blacklist( state: &A, role_id: &str, token_expiry: u64, @@ -98,7 +98,7 @@ pub async fn check_role_in_blacklist( } #[cfg(feature = "email")] -pub async fn insert_email_token_in_blacklist(state: &AppState, token: &str) -> UserResult<()> { +pub async fn insert_email_token_in_blacklist(state: &SessionState, token: &str) -> UserResult<()> { let redis_conn = get_redis_connection(state).change_context(UserErrors::InternalServerError)?; let blacklist_key = format!("{}{token}", EMAIL_TOKEN_BLACKLIST_PREFIX); let expiry = @@ -110,7 +110,7 @@ pub async fn insert_email_token_in_blacklist(state: &AppState, token: &str) -> U } #[cfg(feature = "email")] -pub async fn check_email_token_in_blacklist(state: &AppState, token: &str) -> UserResult<()> { +pub async fn check_email_token_in_blacklist(state: &SessionState, token: &str) -> UserResult<()> { let redis_conn = get_redis_connection(state).change_context(UserErrors::InternalServerError)?; let blacklist_key = format!("{}{token}", EMAIL_TOKEN_BLACKLIST_PREFIX); let key_exists = redis_conn @@ -124,7 +124,7 @@ pub async fn check_email_token_in_blacklist(state: &AppState, token: &str) -> Us Ok(()) } -fn get_redis_connection(state: &A) -> RouterResult> { +fn get_redis_connection(state: &A) -> RouterResult> { state .store() .get_redis_conn() @@ -140,14 +140,14 @@ fn expiry_to_i64(expiry: u64) -> RouterResult { pub trait BlackList { async fn check_in_blacklist(&self, state: &A) -> RouterResult where - A: AppStateInfo + Sync; + A: SessionStateInfo + Sync; } #[async_trait::async_trait] impl BlackList for AuthToken { async fn check_in_blacklist(&self, state: &A) -> RouterResult where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { Ok( check_user_in_blacklist(state, &self.user_id, self.exp).await? @@ -161,7 +161,7 @@ impl BlackList for AuthToken { impl BlackList for SinglePurposeToken { async fn check_in_blacklist(&self, state: &A) -> RouterResult where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { check_user_in_blacklist(state, &self.user_id, self.exp).await } diff --git a/crates/router/src/services/authorization.rs b/crates/router/src/services/authorization.rs index 33edb173255f..768c57a36d0c 100644 --- a/crates/router/src/services/authorization.rs +++ b/crates/router/src/services/authorization.rs @@ -9,7 +9,7 @@ use super::authentication::AuthToken; use crate::{ consts, core::errors::{ApiErrorResponse, RouterResult, StorageErrorExt}, - routes::app::AppStateInfo, + routes::app::SessionStateInfo, }; #[cfg(feature = "olap")] @@ -23,7 +23,7 @@ pub async fn get_permissions( token: &AuthToken, ) -> RouterResult> where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { if let Some(permissions) = get_permissions_from_predefined_roles(&token.role_id) { return Ok(permissions); @@ -55,7 +55,7 @@ async fn get_permissions_from_cache( role_id: &str, ) -> RouterResult> where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { let redis_conn = get_redis_connection(state)?; @@ -82,7 +82,7 @@ async fn get_permissions_from_db( org_id: &str, ) -> RouterResult> where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { state .store() @@ -99,7 +99,7 @@ pub async fn set_permissions_in_cache( expiry: i64, ) -> RouterResult<()> where - A: AppStateInfo + Sync, + A: SessionStateInfo + Sync, { let redis_conn = get_redis_connection(state)?; @@ -139,7 +139,7 @@ pub fn check_authorization( ) } -fn get_redis_connection(state: &A) -> RouterResult> { +fn get_redis_connection(state: &A) -> RouterResult> { state .store() .get_redis_conn() diff --git a/crates/router/src/services/authorization/roles.rs b/crates/router/src/services/authorization/roles.rs index f99892c565d9..8e5cb6fbeaa9 100644 --- a/crates/router/src/services/authorization/roles.rs +++ b/crates/router/src/services/authorization/roles.rs @@ -4,7 +4,7 @@ use common_enums::{PermissionGroup, RoleScope}; use common_utils::errors::CustomResult; use super::{permission_groups::get_permissions_vec, permissions::Permission}; -use crate::{core::errors, routes::AppState}; +use crate::{core::errors, routes::SessionState}; pub mod predefined_roles; @@ -67,7 +67,7 @@ impl RoleInfo { } pub async fn from_role_id( - state: &AppState, + state: &SessionState, role_id: &str, merchant_id: &str, org_id: &str, diff --git a/crates/router/src/services/email/types.rs b/crates/router/src/services/email/types.rs index ee51d976b40e..d05e6ab22575 100644 --- a/crates/router/src/services/email/types.rs +++ b/crates/router/src/services/email/types.rs @@ -7,7 +7,7 @@ use error_stack::ResultExt; use external_services::email::{EmailContents, EmailData, EmailError}; use masking::{ExposeInterface, PeekInterface, Secret}; -use crate::{configs, consts, routes::AppState}; +use crate::{configs, consts, routes::SessionState}; #[cfg(feature = "olap")] use crate::{ core::errors::{UserErrors, UserResult}, @@ -407,7 +407,7 @@ pub struct BizEmailProd { } impl BizEmailProd { - pub fn new(state: &AppState, data: ProdIntent) -> UserResult { + pub fn new(state: &SessionState, data: ProdIntent) -> UserResult { Ok(Self { recipient_email: (domain::UserEmail::new( consts::user::BUSINESS_EMAIL.to_string().into(), diff --git a/crates/router/src/services/pm_auth.rs b/crates/router/src/services/pm_auth.rs index a54ba8819954..d63dadc8b157 100644 --- a/crates/router/src/services/pm_auth.rs +++ b/crates/router/src/services/pm_auth.rs @@ -7,12 +7,12 @@ use pm_auth::{ use crate::{ core::errors::{self}, logger, - routes::AppState, + routes::SessionState, services::{self}, }; pub async fn execute_connector_processing_step<'b, 'a, T, Req, Resp>( - state: &'b AppState, + state: &'b SessionState, connector_integration: BoxedConnectorIntegration<'a, T, Req, Resp>, req: &'b PaymentAuthRouterData, connector: &pm_auth_types::PaymentMethodAuthConnectors, diff --git a/crates/router/src/types/api/mandates.rs b/crates/router/src/types/api/mandates.rs index 0e80fd224da1..71b90ab41c3d 100644 --- a/crates/router/src/types/api/mandates.rs +++ b/crates/router/src/types/api/mandates.rs @@ -11,7 +11,7 @@ use crate::{ payment_methods, }, newtype, - routes::AppState, + routes::SessionState, types::{ api, domain, storage::{self, enums as storage_enums}, @@ -26,7 +26,7 @@ newtype!( #[async_trait::async_trait] pub(crate) trait MandateResponseExt: Sized { async fn from_db_mandate( - state: &AppState, + state: &SessionState, key_store: domain::MerchantKeyStore, mandate: storage::Mandate, storage_scheme: storage_enums::MerchantStorageScheme, @@ -36,7 +36,7 @@ pub(crate) trait MandateResponseExt: Sized { #[async_trait::async_trait] impl MandateResponseExt for MandateResponse { async fn from_db_mandate( - state: &AppState, + state: &SessionState, key_store: domain::MerchantKeyStore, mandate: storage::Mandate, storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/types/api/verify_connector.rs b/crates/router/src/types/api/verify_connector.rs index 60749f647891..0b932f9aeb1e 100644 --- a/crates/router/src/types/api/verify_connector.rs +++ b/crates/router/src/types/api/verify_connector.rs @@ -8,7 +8,7 @@ use crate::{ services, services::ConnectorIntegration, types::{self, api, domain, storage::enums as storage_enums}, - AppState, + SessionState, }; #[derive(Clone)] @@ -113,7 +113,7 @@ impl VerifyConnectorData { #[async_trait::async_trait] pub trait VerifyConnector { async fn verify( - state: &AppState, + state: &SessionState, connector_data: VerifyConnectorData, ) -> errors::RouterResponse<()> { let authorize_data = connector_data.get_payment_authorize_data(); @@ -147,7 +147,7 @@ pub trait VerifyConnector { } async fn get_access_token( - _state: &AppState, + _state: &SessionState, _connector_data: VerifyConnectorData, ) -> errors::CustomResult, errors::ApiErrorResponse> { // AccessToken is None for the connectors without the AccessToken Flow. diff --git a/crates/router/src/types/api/verify_connector/paypal.rs b/crates/router/src/types/api/verify_connector/paypal.rs index 2cb2a8061d12..99b7feb66166 100644 --- a/crates/router/src/types/api/verify_connector/paypal.rs +++ b/crates/router/src/types/api/verify_connector/paypal.rs @@ -4,7 +4,7 @@ use super::{VerifyConnector, VerifyConnectorData}; use crate::{ connector, core::errors, - routes::AppState, + routes::SessionState, services, types::{self, api}, }; @@ -12,7 +12,7 @@ use crate::{ #[async_trait::async_trait] impl VerifyConnector for connector::Paypal { async fn get_access_token( - state: &AppState, + state: &SessionState, connector_data: VerifyConnectorData, ) -> errors::CustomResult, errors::ApiErrorResponse> { let token_data: types::AccessTokenRequestData = diff --git a/crates/router/src/types/api/webhooks.rs b/crates/router/src/types/api/webhooks.rs index 964885cae551..726a5a154269 100644 --- a/crates/router/src/types/api/webhooks.rs +++ b/crates/router/src/types/api/webhooks.rs @@ -146,7 +146,7 @@ pub trait IncomingWebhook: ConnectorCommon + Sync { async fn verify_webhook_source_verification_call( &self, - state: &crate::routes::AppState, + state: &crate::routes::SessionState, merchant_account: &domain::MerchantAccount, merchant_connector_account: domain::MerchantConnectorAccount, connector_name: &str, diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs index 91323b0c16d3..60d75ce81d1b 100644 --- a/crates/router/src/types/domain/user.rs +++ b/crates/router/src/types/domain/user.rs @@ -30,7 +30,7 @@ use crate::{ errors::{self, UserErrors, UserResult}, }, db::StorageInterface, - routes::AppState, + routes::SessionState, services::{self, authentication as auth, authentication::UserFromToken, authorization::info}, types::transformers::ForeignFrom, utils::{self, user::password}, @@ -237,7 +237,7 @@ impl UserCompanyName { pub struct NewUserOrganization(diesel_org::OrganizationNew); impl NewUserOrganization { - pub async fn insert_org_in_db(self, state: AppState) -> UserResult { + pub async fn insert_org_in_db(self, state: SessionState) -> UserResult { state .store .insert_organization(self.0) @@ -351,7 +351,7 @@ impl NewUserMerchant { self.new_organization.clone() } - pub async fn check_if_already_exists_in_db(&self, state: AppState) -> UserResult<()> { + pub async fn check_if_already_exists_in_db(&self, state: SessionState) -> UserResult<()> { if state .store .get_merchant_key_store_by_merchant_id( @@ -370,7 +370,10 @@ impl NewUserMerchant { Ok(()) } - pub async fn create_new_merchant_and_insert_in_db(&self, state: AppState) -> UserResult<()> { + pub async fn create_new_merchant_and_insert_in_db( + &self, + state: SessionState, + ) -> UserResult<()> { self.check_if_already_exists_in_db(state.clone()).await?; Box::pin(admin::create_merchant_account( state.clone(), @@ -554,7 +557,7 @@ impl NewUser { .attach_printable("Error while inserting user") } - pub async fn check_if_already_exists_in_db(&self, state: AppState) -> UserResult<()> { + pub async fn check_if_already_exists_in_db(&self, state: SessionState) -> UserResult<()> { if state .store .find_user_by_email(&self.get_email().into_inner()) @@ -568,7 +571,7 @@ impl NewUser { pub async fn insert_user_and_merchant_in_db( &self, - state: AppState, + state: SessionState, ) -> UserResult { self.check_if_already_exists_in_db(state.clone()).await?; let db = state.store.as_ref(); @@ -585,7 +588,7 @@ impl NewUser { pub async fn insert_user_role_in_db( self, - state: AppState, + state: SessionState, role_id: String, user_status: UserStatus, ) -> UserResult { @@ -790,7 +793,7 @@ impl UserFromStorage { self.0.email.clone() } - pub async fn get_role_from_db(&self, state: AppState) -> UserResult { + pub async fn get_role_from_db(&self, state: SessionState) -> UserResult { state .store .find_user_role_by_user_id(&self.0.user_id) @@ -798,7 +801,7 @@ impl UserFromStorage { .change_context(UserErrors::InternalServerError) } - pub async fn get_roles_from_db(&self, state: &AppState) -> UserResult> { + pub async fn get_roles_from_db(&self, state: &SessionState) -> UserResult> { state .store .list_user_roles_by_user_id(&self.0.user_id) @@ -807,7 +810,7 @@ impl UserFromStorage { } #[cfg(feature = "email")] - pub fn get_verification_days_left(&self, state: &AppState) -> UserResult> { + pub fn get_verification_days_left(&self, state: &SessionState) -> UserResult> { if self.0.is_verified { return Ok(None); } @@ -829,7 +832,7 @@ impl UserFromStorage { Ok(Some(days_left_for_verification.whole_days())) } - pub fn is_password_rotate_required(&self, state: &AppState) -> UserResult { + pub fn is_password_rotate_required(&self, state: &SessionState) -> UserResult { let last_password_modified_at = if let Some(last_password_modified_at) = self.0.last_password_modified_at { last_password_modified_at.date() @@ -855,7 +858,7 @@ impl UserFromStorage { pub async fn get_role_from_db_by_merchant_id( &self, - state: &AppState, + state: &SessionState, merchant_id: &str, ) -> CustomResult { state @@ -866,7 +869,7 @@ impl UserFromStorage { pub async fn get_preferred_or_active_user_role_from_db( &self, - state: &AppState, + state: &SessionState, ) -> CustomResult { if let Some(preferred_merchant_id) = self.get_preferred_merchant_id() { self.get_role_from_db_by_merchant_id(state, &preferred_merchant_id) @@ -887,7 +890,7 @@ impl UserFromStorage { } } - pub async fn get_or_create_key_store(&self, state: &AppState) -> UserResult { + pub async fn get_or_create_key_store(&self, state: &SessionState) -> UserResult { let master_key = state.store.get_master_key(); let key_store_result = state .store @@ -936,7 +939,7 @@ impl UserFromStorage { pub async fn decrypt_and_get_totp_secret( &self, - state: &AppState, + state: &SessionState, ) -> UserResult>> { if self.0.totp_secret.is_none() { return Ok(None); @@ -1023,7 +1026,7 @@ impl SignInWithRoleStrategyType { pub async fn get_signin_response( self, - state: &AppState, + state: &SessionState, ) -> UserResult { match self { Self::SingleRole(strategy) => strategy.get_signin_response(state).await, @@ -1038,7 +1041,10 @@ pub struct SignInWithSingleRoleStrategy { } impl SignInWithSingleRoleStrategy { - async fn get_signin_response(self, state: &AppState) -> UserResult { + async fn get_signin_response( + self, + state: &SessionState, + ) -> UserResult { let token = utils::user::generate_jwt_auth_token(state, &self.user, &self.user_role).await?; utils::user_role::set_role_permissions_in_cache_by_user_role(state, &self.user_role).await; @@ -1058,7 +1064,10 @@ pub struct SignInWithMultipleRolesStrategy { } impl SignInWithMultipleRolesStrategy { - async fn get_signin_response(self, state: &AppState) -> UserResult { + async fn get_signin_response( + self, + state: &SessionState, + ) -> UserResult { let merchant_accounts = state .store .list_multiple_merchant_accounts( diff --git a/crates/router/src/types/domain/user/decision_manager.rs b/crates/router/src/types/domain/user/decision_manager.rs index 5a0388c7f36f..41ae12350fb3 100644 --- a/crates/router/src/types/domain/user/decision_manager.rs +++ b/crates/router/src/types/domain/user/decision_manager.rs @@ -5,7 +5,7 @@ use masking::Secret; use super::UserFromStorage; use crate::{ core::errors::{StorageErrorExt, UserErrors, UserResult}, - routes::AppState, + routes::SessionState, services::authentication as auth, utils, }; @@ -17,7 +17,7 @@ pub enum UserFlow { } impl UserFlow { - async fn is_required(&self, user: &UserFromStorage, state: &AppState) -> UserResult { + async fn is_required(&self, user: &UserFromStorage, state: &SessionState) -> UserResult { match self { Self::SPTFlow(flow) => flow.is_required(user, state).await, Self::JWTFlow(flow) => flow.is_required(user, state).await, @@ -36,7 +36,7 @@ pub enum SPTFlow { } impl SPTFlow { - async fn is_required(&self, user: &UserFromStorage, state: &AppState) -> UserResult { + async fn is_required(&self, user: &UserFromStorage, state: &SessionState) -> UserResult { match self { // TOTP Self::TOTP => Ok(true), @@ -54,7 +54,7 @@ impl SPTFlow { pub async fn generate_spt( self, - state: &AppState, + state: &SessionState, next_flow: &NextFlow, ) -> UserResult> { auth::SinglePurposeToken::new_token( @@ -74,13 +74,17 @@ pub enum JWTFlow { } impl JWTFlow { - async fn is_required(&self, _user: &UserFromStorage, _state: &AppState) -> UserResult { + async fn is_required( + &self, + _user: &UserFromStorage, + _state: &SessionState, + ) -> UserResult { Ok(true) } pub async fn generate_jwt( self, - state: &AppState, + state: &SessionState, next_flow: &NextFlow, user_role: &UserRole, ) -> UserResult> { @@ -183,7 +187,7 @@ impl CurrentFlow { }) } - pub async fn next(&self, user: UserFromStorage, state: &AppState) -> UserResult { + pub async fn next(&self, user: UserFromStorage, state: &SessionState) -> UserResult { let flows = self.origin.get_flows(); let remaining_flows = flows.iter().skip(self.current_flow_index + 1); for flow in remaining_flows { @@ -209,7 +213,7 @@ impl NextFlow { pub async fn from_origin( origin: Origin, user: UserFromStorage, - state: &AppState, + state: &SessionState, ) -> UserResult { let flows = origin.get_flows(); for flow in flows { @@ -228,7 +232,7 @@ impl NextFlow { self.next_flow } - pub async fn get_token(&self, state: &AppState) -> UserResult> { + pub async fn get_token(&self, state: &SessionState) -> UserResult> { match self.next_flow { UserFlow::SPTFlow(spt_flow) => spt_flow.generate_spt(state, self).await, UserFlow::JWTFlow(jwt_flow) => { @@ -251,7 +255,7 @@ impl NextFlow { pub async fn get_token_with_user_role( &self, - state: &AppState, + state: &SessionState, user_role: &UserRole, ) -> UserResult> { match self.next_flow { diff --git a/crates/router/src/types/storage/payment_attempt.rs b/crates/router/src/types/storage/payment_attempt.rs index 4ad45f554ce7..1cba84ad9f03 100644 --- a/crates/router/src/types/storage/payment_attempt.rs +++ b/crates/router/src/types/storage/payment_attempt.rs @@ -124,8 +124,11 @@ mod tests { ..PaymentAttemptNew::default() }; - let response = state - .store + let store = state + .stores + .get(state.conf.multitenancy.get_tenant_names().first().unwrap()) + .unwrap(); + let response = store .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly) .await .unwrap(); @@ -165,14 +168,16 @@ mod tests { attempt_id: attempt_id.clone(), ..PaymentAttemptNew::default() }; - state - .store + let store = state + .stores + .get(state.conf.multitenancy.get_tenant_names().first().unwrap()) + .unwrap(); + store .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly) .await .unwrap(); - let response = state - .store + let response = store .find_payment_attempt_by_payment_id_merchant_id_attempt_id( &payment_id, &merchant_id, @@ -218,14 +223,16 @@ mod tests { attempt_id: uuid.clone(), ..PaymentAttemptNew::default() }; - state - .store + let store = state + .stores + .get(state.conf.multitenancy.get_tenant_names().first().unwrap()) + .unwrap(); + store .insert_payment_attempt(payment_attempt, enums::MerchantStorageScheme::PostgresOnly) .await .unwrap(); - let response = state - .store + let response = store .find_payment_attempt_by_payment_id_merchant_id_attempt_id( &uuid, "1", diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index da6cac195ca2..b83d3138b7ce 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -826,7 +826,7 @@ pub async fn trigger_payments_webhook( key_store: &domain::MerchantKeyStore, payment_data: crate::core::payments::PaymentData, customer: Option, - state: &crate::routes::AppState, + state: &crate::routes::SessionState, operation: Op, ) -> RouterResult<()> where @@ -858,7 +858,7 @@ where captures, customer, services::AuthFlow::Merchant, - &state.conf.server, + &state.base_url, &operation, &state.conf.connector_request_reference_id_config, None, diff --git a/crates/router/src/utils/connector_onboarding.rs b/crates/router/src/utils/connector_onboarding.rs index aeea146df292..15ad2eb89540 100644 --- a/crates/router/src/utils/connector_onboarding.rs +++ b/crates/router/src/utils/connector_onboarding.rs @@ -5,7 +5,7 @@ use super::errors::StorageErrorExt; use crate::{ consts, core::errors::{ApiErrorResponse, NotImplementedMessage, RouterResult}, - routes::{app::settings, AppState}, + routes::{app::settings, SessionState}, types::{self, api::enums}, }; @@ -41,7 +41,7 @@ pub fn is_enabled( } pub async fn check_if_connector_exists( - state: &AppState, + state: &SessionState, connector_id: &str, merchant_id: &str, ) -> RouterResult<()> { @@ -70,7 +70,7 @@ pub async fn check_if_connector_exists( } pub async fn set_tracking_id_in_configs( - state: &AppState, + state: &SessionState, connector_id: &str, connector: enums::Connector, ) -> RouterResult<()> { @@ -115,7 +115,7 @@ pub async fn set_tracking_id_in_configs( } pub async fn get_tracking_id_from_configs( - state: &AppState, + state: &SessionState, connector_id: &str, connector: enums::Connector, ) -> RouterResult { diff --git a/crates/router/src/utils/connector_onboarding/paypal.rs b/crates/router/src/utils/connector_onboarding/paypal.rs index 708763a44409..9827a4b09375 100644 --- a/crates/router/src/utils/connector_onboarding/paypal.rs +++ b/crates/router/src/utils/connector_onboarding/paypal.rs @@ -5,7 +5,7 @@ use http::header; use crate::{ connector, core::errors::{ApiErrorResponse, RouterResult}, - routes::AppState, + routes::SessionState, types, types::api::{ enums, @@ -14,7 +14,7 @@ use crate::{ utils::verify_connector as verify_connector_utils, }; -pub async fn generate_access_token(state: AppState) -> RouterResult { +pub async fn generate_access_token(state: SessionState) -> RouterResult { let connector = enums::Connector::Paypal; let boxed_connector = types::api::ConnectorData::convert_connector( &state.conf.connectors, diff --git a/crates/router/src/utils/currency.rs b/crates/router/src/utils/currency.rs index 5cf68635c4e1..c16b46e51870 100644 --- a/crates/router/src/utils/currency.rs +++ b/crates/router/src/utils/currency.rs @@ -14,7 +14,7 @@ use tokio::{sync::RwLock, time::sleep}; use crate::{ logger, routes::app::settings::{Conversion, DefaultExchangeRates}, - services, AppState, + services, SessionState, }; const REDIX_FOREX_CACHE_KEY: &str = "{forex_cache}_lock"; const REDIX_FOREX_CACHE_DATA: &str = "{forex_cache}_data"; @@ -121,7 +121,7 @@ async fn save_forex_to_local( // Alternative handler for handling the case, When no data in local as well as redis #[allow(dead_code)] async fn waited_fetch_and_update_caches( - state: &AppState, + state: &SessionState, local_fetch_retry_delay: u64, local_fetch_retry_count: u64, ) -> CustomResult { @@ -171,7 +171,7 @@ impl From for CurrencyFactors { } } pub async fn get_forex_rates( - state: &AppState, + state: &SessionState, call_delay: i64, local_fetch_retry_delay: u64, local_fetch_retry_count: u64, @@ -197,7 +197,7 @@ pub async fn get_forex_rates( } async fn handler_local_no_data( - state: &AppState, + state: &SessionState, call_delay: i64, _local_fetch_retry_delay: u64, _local_fetch_retry_count: u64, @@ -216,7 +216,7 @@ async fn handler_local_no_data( } async fn successive_fetch_and_save_forex( - state: &AppState, + state: &SessionState, stale_redis_data: Option, ) -> CustomResult { match acquire_redis_lock(state).await { @@ -249,7 +249,7 @@ async fn successive_fetch_and_save_forex( } async fn successive_save_data_to_redis_local( - state: &AppState, + state: &SessionState, forex: FxExchangeRatesCacheEntry, ) -> CustomResult { Ok(save_forex_to_redis(state, &forex) @@ -268,7 +268,7 @@ async fn successive_save_data_to_redis_local( } async fn fallback_forex_redis_check( - state: &AppState, + state: &SessionState, redis_data: FxExchangeRatesCacheEntry, call_delay: i64, ) -> CustomResult { @@ -287,7 +287,7 @@ async fn fallback_forex_redis_check( } async fn handler_local_expired( - state: &AppState, + state: &SessionState, call_delay: i64, local_rates: FxExchangeRatesCacheEntry, ) -> CustomResult { @@ -316,7 +316,7 @@ async fn handler_local_expired( } async fn fetch_forex_rates( - state: &AppState, + state: &SessionState, ) -> Result> { let forex_api_key = state.conf.forex_api.get_inner().api_key.peek(); @@ -371,7 +371,7 @@ async fn fetch_forex_rates( } pub async fn fallback_fetch_forex_rates( - state: &AppState, + state: &SessionState, ) -> CustomResult { let fallback_forex_api_key = state.conf.forex_api.get_inner().fallback_api_key.peek(); @@ -438,7 +438,7 @@ pub async fn fallback_fetch_forex_rates( } async fn release_redis_lock( - state: &AppState, + state: &SessionState, ) -> Result> { state .store @@ -449,9 +449,9 @@ async fn release_redis_lock( .change_context(ForexCacheError::RedisLockReleaseFailed) } -async fn acquire_redis_lock(app_state: &AppState) -> CustomResult { - let forex_api = app_state.conf.forex_api.get_inner(); - app_state +async fn acquire_redis_lock(state: &SessionState) -> CustomResult { + let forex_api = state.conf.forex_api.get_inner(); + state .store .get_redis_conn() .change_context(ForexCacheError::RedisConnectionError)? @@ -472,7 +472,7 @@ async fn acquire_redis_lock(app_state: &AppState) -> CustomResult CustomResult<(), ForexCacheError> { app_state @@ -485,7 +485,7 @@ async fn save_forex_to_redis( } async fn retrieve_forex_from_redis( - app_state: &AppState, + app_state: &SessionState, ) -> CustomResult, ForexCacheError> { app_state .store @@ -510,7 +510,7 @@ async fn is_redis_expired( } pub async fn convert_currency( - state: AppState, + state: SessionState, amount: i64, to_currency: String, from_currency: String, diff --git a/crates/router/src/utils/user.rs b/crates/router/src/utils/user.rs index db1d0ea25088..eaa386d7f6cc 100644 --- a/crates/router/src/utils/user.rs +++ b/crates/router/src/utils/user.rs @@ -8,7 +8,7 @@ use redis_interface::RedisConnectionPool; use crate::{ core::errors::{StorageError, UserErrors, UserResult}, - routes::AppState, + routes::SessionState, services::{ authentication::{AuthToken, UserFromToken}, authorization::roles::RoleInfo, @@ -25,7 +25,7 @@ pub mod two_factor_auth; impl UserFromToken { pub async fn get_merchant_account_from_db( &self, - state: AppState, + state: SessionState, ) -> UserResult { let key_store = state .store @@ -55,7 +55,7 @@ impl UserFromToken { Ok(merchant_account) } - pub async fn get_user_from_db(&self, state: &AppState) -> UserResult { + pub async fn get_user_from_db(&self, state: &SessionState) -> UserResult { let user = state .store .find_user_by_id(&self.user_id) @@ -64,7 +64,7 @@ impl UserFromToken { Ok(user.into()) } - pub async fn get_role_info_from_db(&self, state: &AppState) -> UserResult { + pub async fn get_role_info_from_db(&self, state: &SessionState) -> UserResult { RoleInfo::from_role_id(state, &self.role_id, &self.merchant_id, &self.org_id) .await .change_context(UserErrors::InternalServerError) @@ -72,7 +72,7 @@ impl UserFromToken { } pub async fn generate_jwt_auth_token( - state: &AppState, + state: &SessionState, user: &UserFromStorage, user_role: &UserRole, ) -> UserResult> { @@ -88,7 +88,7 @@ pub async fn generate_jwt_auth_token( } pub async fn generate_jwt_auth_token_with_custom_role_attributes( - state: &AppState, + state: &SessionState, user: &UserFromStorage, merchant_id: String, org_id: String, @@ -106,7 +106,7 @@ pub async fn generate_jwt_auth_token_with_custom_role_attributes( } pub fn get_dashboard_entry_response( - state: &AppState, + state: &SessionState, user: UserFromStorage, user_role: UserRole, token: masking::Secret, @@ -126,7 +126,7 @@ pub fn get_dashboard_entry_response( #[allow(unused_variables)] pub fn get_verification_days_left( - state: &AppState, + state: &SessionState, user: &UserFromStorage, ) -> UserResult> { #[cfg(feature = "email")] @@ -176,7 +176,7 @@ pub fn get_multiple_merchant_details_with_status( } pub async fn get_user_from_db_by_email( - state: &AppState, + state: &SessionState, email: domain::UserEmail, ) -> CustomResult { state @@ -193,7 +193,7 @@ pub fn get_token_from_signin_response(resp: &user_api::SignInResponse) -> maskin } } -pub fn get_redis_connection(state: &AppState) -> UserResult> { +pub fn get_redis_connection(state: &SessionState) -> UserResult> { state .store .get_redis_conn() diff --git a/crates/router/src/utils/user/dashboard_metadata.rs b/crates/router/src/utils/user/dashboard_metadata.rs index 3979a8649447..5622a43f4dcf 100644 --- a/crates/router/src/utils/user/dashboard_metadata.rs +++ b/crates/router/src/utils/user/dashboard_metadata.rs @@ -13,11 +13,11 @@ use masking::Secret; use crate::{ core::errors::{UserErrors, UserResult}, - headers, AppState, + headers, SessionState, }; pub async fn insert_merchant_scoped_metadata_to_db( - state: &AppState, + state: &SessionState, user_id: String, merchant_id: String, org_id: String, @@ -50,7 +50,7 @@ pub async fn insert_merchant_scoped_metadata_to_db( }) } pub async fn insert_user_scoped_metadata_to_db( - state: &AppState, + state: &SessionState, user_id: String, merchant_id: String, org_id: String, @@ -84,7 +84,7 @@ pub async fn insert_user_scoped_metadata_to_db( } pub async fn get_merchant_scoped_metadata_from_db( - state: &AppState, + state: &SessionState, merchant_id: String, org_id: String, metadata_keys: Vec, @@ -97,7 +97,7 @@ pub async fn get_merchant_scoped_metadata_from_db( .attach_printable("DB Error Fetching DashboardMetaData") } pub async fn get_user_scoped_metadata_from_db( - state: &AppState, + state: &SessionState, user_id: String, merchant_id: String, org_id: String, @@ -121,7 +121,7 @@ pub async fn get_user_scoped_metadata_from_db( } pub async fn update_merchant_scoped_metadata( - state: &AppState, + state: &SessionState, user_id: String, merchant_id: String, org_id: String, @@ -149,7 +149,7 @@ pub async fn update_merchant_scoped_metadata( .change_context(UserErrors::InternalServerError) } pub async fn update_user_scoped_metadata( - state: &AppState, + state: &SessionState, user_id: String, merchant_id: String, org_id: String, diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index ea690af35aeb..9be2ddb57a4e 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -12,12 +12,12 @@ use time::OffsetDateTime; use crate::{ consts, core::errors::sample_data::{SampleDataError, SampleDataResult}, - AppState, + SessionState, }; #[allow(clippy::type_complexity)] pub async fn generate_sample_data( - state: &AppState, + state: &SessionState, req: SampleDataRequest, merchant_id: &str, ) -> SampleDataResult)>> { diff --git a/crates/router/src/utils/user/two_factor_auth.rs b/crates/router/src/utils/user/two_factor_auth.rs index 6bd693c07f5c..a0915f3ed86e 100644 --- a/crates/router/src/utils/user/two_factor_auth.rs +++ b/crates/router/src/utils/user/two_factor_auth.rs @@ -6,7 +6,7 @@ use totp_rs::{Algorithm, TOTP}; use crate::{ consts, core::errors::{UserErrors, UserResult}, - routes::AppState, + routes::SessionState, }; pub fn generate_default_totp( @@ -31,7 +31,7 @@ pub fn generate_default_totp( .change_context(UserErrors::InternalServerError) } -pub async fn check_totp_in_redis(state: &AppState, user_id: &str) -> UserResult { +pub async fn check_totp_in_redis(state: &SessionState, user_id: &str) -> UserResult { let redis_conn = super::get_redis_connection(state)?; let key = format!("{}{}", consts::user::REDIS_TOTP_PREFIX, user_id); redis_conn @@ -40,7 +40,7 @@ pub async fn check_totp_in_redis(state: &AppState, user_id: &str) -> UserResult< .change_context(UserErrors::InternalServerError) } -pub async fn check_recovery_code_in_redis(state: &AppState, user_id: &str) -> UserResult { +pub async fn check_recovery_code_in_redis(state: &SessionState, user_id: &str) -> UserResult { let redis_conn = super::get_redis_connection(state)?; let key = format!("{}{}", consts::user::REDIS_RECOVERY_CODE_PREFIX, user_id); redis_conn @@ -49,7 +49,7 @@ pub async fn check_recovery_code_in_redis(state: &AppState, user_id: &str) -> Us .change_context(UserErrors::InternalServerError) } -pub async fn insert_totp_in_redis(state: &AppState, user_id: &str) -> UserResult<()> { +pub async fn insert_totp_in_redis(state: &SessionState, user_id: &str) -> UserResult<()> { let redis_conn = super::get_redis_connection(state)?; let key = format!("{}{}", consts::user::REDIS_TOTP_PREFIX, user_id); redis_conn @@ -63,7 +63,7 @@ pub async fn insert_totp_in_redis(state: &AppState, user_id: &str) -> UserResult } pub async fn insert_totp_secret_in_redis( - state: &AppState, + state: &SessionState, user_id: &str, secret: &masking::Secret, ) -> UserResult<()> { @@ -79,7 +79,7 @@ pub async fn insert_totp_secret_in_redis( } pub async fn get_totp_secret_from_redis( - state: &AppState, + state: &SessionState, user_id: &str, ) -> UserResult>> { let redis_conn = super::get_redis_connection(state)?; @@ -90,7 +90,7 @@ pub async fn get_totp_secret_from_redis( .map(|secret| secret.map(Into::into)) } -pub async fn delete_totp_secret_from_redis(state: &AppState, user_id: &str) -> UserResult<()> { +pub async fn delete_totp_secret_from_redis(state: &SessionState, user_id: &str) -> UserResult<()> { let redis_conn = super::get_redis_connection(state)?; redis_conn .delete_key(&get_totp_secret_key(user_id)) @@ -103,7 +103,7 @@ fn get_totp_secret_key(user_id: &str) -> String { format!("{}{}", consts::user::REDIS_TOTP_SECRET_PREFIX, user_id) } -pub async fn insert_recovery_code_in_redis(state: &AppState, user_id: &str) -> UserResult<()> { +pub async fn insert_recovery_code_in_redis(state: &SessionState, user_id: &str) -> UserResult<()> { let redis_conn = super::get_redis_connection(state)?; let key = format!("{}{}", consts::user::REDIS_RECOVERY_CODE_PREFIX, user_id); redis_conn diff --git a/crates/router/src/utils/user_role.rs b/crates/router/src/utils/user_role.rs index ba4c28786670..d0ad08848ca2 100644 --- a/crates/router/src/utils/user_role.rs +++ b/crates/router/src/utils/user_role.rs @@ -9,7 +9,7 @@ use router_env::logger; use crate::{ consts, core::errors::{StorageErrorExt, UserErrors, UserResult}, - routes::AppState, + routes::SessionState, services::authorization::{self as authz, permissions::Permission, roles}, types::domain, }; @@ -73,7 +73,7 @@ pub fn validate_role_groups(groups: &[PermissionGroup]) -> UserResult<()> { } pub async fn validate_role_name( - state: &AppState, + state: &SessionState, role_name: &domain::RoleName, merchant_id: &str, org_id: &str, @@ -101,7 +101,7 @@ pub async fn validate_role_name( } pub async fn set_role_permissions_in_cache_by_user_role( - state: &AppState, + state: &SessionState, user_role: &UserRole, ) -> bool { set_role_permissions_in_cache_if_required( @@ -116,7 +116,7 @@ pub async fn set_role_permissions_in_cache_by_user_role( } pub async fn set_role_permissions_in_cache_if_required( - state: &AppState, + state: &SessionState, role_id: &str, merchant_id: &str, org_id: &str, @@ -143,7 +143,7 @@ pub async fn set_role_permissions_in_cache_if_required( } pub async fn get_multiple_role_info_for_user_roles( - state: &AppState, + state: &SessionState, user_roles: &[UserRole], ) -> UserResult> { futures::future::try_join_all(user_roles.iter().map(|user_role| async { diff --git a/crates/router/src/workflows/api_key_expiry.rs b/crates/router/src/workflows/api_key_expiry.rs index c5914810108c..dff7905a2624 100644 --- a/crates/router/src/workflows/api_key_expiry.rs +++ b/crates/router/src/workflows/api_key_expiry.rs @@ -1,12 +1,12 @@ use common_utils::{errors::ValidationError, ext_traits::ValueExt}; use diesel_models::{enums as storage_enums, ApiKeyExpiryTrackingData}; use router_env::logger; -use scheduler::{workflows::ProcessTrackerWorkflow, SchedulerAppState}; +use scheduler::{workflows::ProcessTrackerWorkflow, SchedulerSessionState}; use crate::{ errors, logger::error, - routes::{metrics, AppState}, + routes::{metrics, SessionState}, services::email::types::ApiKeyExpiryReminder, types::{api, domain::UserEmail, storage}, utils::OptionExt, @@ -15,10 +15,10 @@ use crate::{ pub struct ApiKeyExpiryWorkflow; #[async_trait::async_trait] -impl ProcessTrackerWorkflow for ApiKeyExpiryWorkflow { +impl ProcessTrackerWorkflow for ApiKeyExpiryWorkflow { async fn execute_workflow<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { let db = &*state.store; @@ -137,7 +137,7 @@ impl ProcessTrackerWorkflow for ApiKeyExpiryWorkflow { async fn error_handler<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, process: storage::ProcessTracker, _error: errors::ProcessTrackerError, ) -> errors::CustomResult<(), errors::ProcessTrackerError> { diff --git a/crates/router/src/workflows/attach_payout_account_workflow.rs b/crates/router/src/workflows/attach_payout_account_workflow.rs index 98d3f7844b4e..eb60510ad754 100644 --- a/crates/router/src/workflows/attach_payout_account_workflow.rs +++ b/crates/router/src/workflows/attach_payout_account_workflow.rs @@ -7,17 +7,17 @@ use scheduler::{ use crate::{ core::payouts, errors as core_errors, - routes::AppState, + routes::SessionState, types::{api, storage}, }; pub struct AttachPayoutAccountWorkflow; #[async_trait::async_trait] -impl ProcessTrackerWorkflow for AttachPayoutAccountWorkflow { +impl ProcessTrackerWorkflow for AttachPayoutAccountWorkflow { async fn execute_workflow<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { // Gather context @@ -63,7 +63,7 @@ impl ProcessTrackerWorkflow for AttachPayoutAccountWorkflow { async fn error_handler<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, error: errors::ProcessTrackerError, ) -> core_errors::CustomResult<(), errors::ProcessTrackerError> { diff --git a/crates/router/src/workflows/outgoing_webhook_retry.rs b/crates/router/src/workflows/outgoing_webhook_retry.rs index 63bdb7ec9894..53b275dfebce 100644 --- a/crates/router/src/workflows/outgoing_webhook_retry.rs +++ b/crates/router/src/workflows/outgoing_webhook_retry.rs @@ -17,18 +17,18 @@ use crate::{ core::webhooks::{self as webhooks_core, types::OutgoingWebhookTrackingData}, db::StorageInterface, errors, logger, - routes::{app::ReqState, AppState}, + routes::{app::ReqState, SessionState}, types::{domain, storage}, }; pub struct OutgoingWebhookRetryWorkflow; #[async_trait::async_trait] -impl ProcessTrackerWorkflow for OutgoingWebhookRetryWorkflow { +impl ProcessTrackerWorkflow for OutgoingWebhookRetryWorkflow { #[instrument(skip_all)] async fn execute_workflow<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { let delivery_attempt = storage::enums::WebhookDeliveryAttempt::AutomaticRetry; @@ -207,7 +207,7 @@ impl ProcessTrackerWorkflow for OutgoingWebhookRetryWorkflow { #[instrument(skip_all)] async fn error_handler<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, error: errors::ProcessTrackerError, ) -> errors::CustomResult<(), errors::ProcessTrackerError> { @@ -313,7 +313,7 @@ pub(crate) async fn retry_webhook_delivery_task( #[instrument(skip_all)] async fn get_outgoing_webhook_content_and_event_type( - state: AppState, + state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, diff --git a/crates/router/src/workflows/payment_sync.rs b/crates/router/src/workflows/payment_sync.rs index 14f372789ed3..c34b8ebe73ba 100644 --- a/crates/router/src/workflows/payment_sync.rs +++ b/crates/router/src/workflows/payment_sync.rs @@ -3,7 +3,7 @@ use error_stack::ResultExt; use router_env::logger; use scheduler::{ consumer::{self, types::process_data, workflows::ProcessTrackerWorkflow}, - errors as sch_errors, utils as scheduler_utils, SchedulerAppState, + errors as sch_errors, utils as scheduler_utils, }; use crate::{ @@ -14,7 +14,7 @@ use crate::{ }, db::StorageInterface, errors, - routes::AppState, + routes::SessionState, services, types::{ api, @@ -26,10 +26,10 @@ use crate::{ pub struct PaymentsSyncWorkflow; #[async_trait::async_trait] -impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { +impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { async fn execute_workflow<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, ) -> Result<(), sch_errors::ProcessTrackerError> { let db: &dyn StorageInterface = &*state.store; @@ -87,7 +87,7 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { match &payment_data.payment_attempt.status { status if terminal_status.contains(status) => { state - .get_db() + .store .as_scheduler() .finish_process_with_business_status(process, "COMPLETED_BY_PT".to_string()) .await? @@ -192,7 +192,7 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { async fn error_handler<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, error: sch_errors::ProcessTrackerError, ) -> errors::CustomResult<(), sch_errors::ProcessTrackerError> { diff --git a/crates/router/src/workflows/refund_router.rs b/crates/router/src/workflows/refund_router.rs index 934c208f9115..515e34c06897 100644 --- a/crates/router/src/workflows/refund_router.rs +++ b/crates/router/src/workflows/refund_router.rs @@ -1,16 +1,16 @@ use scheduler::consumer::workflows::ProcessTrackerWorkflow; use crate::{ - core::refunds as refund_flow, errors, logger::error, routes::AppState, types::storage, + core::refunds as refund_flow, errors, logger::error, routes::SessionState, types::storage, }; pub struct RefundWorkflowRouter; #[async_trait::async_trait] -impl ProcessTrackerWorkflow for RefundWorkflowRouter { +impl ProcessTrackerWorkflow for RefundWorkflowRouter { async fn execute_workflow<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { Ok(Box::pin(refund_flow::start_refund_workflow(state, &process)).await?) @@ -18,7 +18,7 @@ impl ProcessTrackerWorkflow for RefundWorkflowRouter { async fn error_handler<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, process: storage::ProcessTracker, _error: errors::ProcessTrackerError, ) -> errors::CustomResult<(), errors::ProcessTrackerError> { diff --git a/crates/router/src/workflows/tokenized_data.rs b/crates/router/src/workflows/tokenized_data.rs index 0674982f92fe..bc1842205ae4 100644 --- a/crates/router/src/workflows/tokenized_data.rs +++ b/crates/router/src/workflows/tokenized_data.rs @@ -1,16 +1,16 @@ use scheduler::consumer::workflows::ProcessTrackerWorkflow; use crate::{ - core::payment_methods::vault, errors, logger::error, routes::AppState, types::storage, + core::payment_methods::vault, errors, logger::error, routes::SessionState, types::storage, }; pub struct DeleteTokenizeDataWorkflow; #[async_trait::async_trait] -impl ProcessTrackerWorkflow for DeleteTokenizeDataWorkflow { +impl ProcessTrackerWorkflow for DeleteTokenizeDataWorkflow { async fn execute_workflow<'a>( &'a self, - state: &'a AppState, + state: &'a SessionState, process: storage::ProcessTracker, ) -> Result<(), errors::ProcessTrackerError> { Ok(vault::start_tokenize_data_workflow(state, &process).await?) @@ -18,7 +18,7 @@ impl ProcessTrackerWorkflow for DeleteTokenizeDataWorkflow { async fn error_handler<'a>( &'a self, - _state: &'a AppState, + _state: &'a SessionState, process: storage::ProcessTracker, _error: errors::ProcessTrackerError, ) -> errors::CustomResult<(), errors::ProcessTrackerError> { diff --git a/crates/router/tests/cache.rs b/crates/router/tests/cache.rs index c6eef06db7b1..f0c79e4dcbc0 100644 --- a/crates/router/tests/cache.rs +++ b/crates/router/tests/cache.rs @@ -1,6 +1,8 @@ #![allow(clippy::unwrap_used)] +use std::sync::Arc; + use router::{configs::settings::Settings, routes, services}; -use storage_impl::redis::cache; +use storage_impl::redis::cache::{self, CacheKey}; mod utils; @@ -9,13 +11,15 @@ async fn invalidate_existing_cache_success() { // Arrange Box::pin(utils::setup()).await; let (tx, _) = tokio::sync::oneshot::channel(); - let state = Box::pin(routes::AppState::new( + let app_state = Box::pin(routes::AppState::new( Settings::default(), tx, Box::new(services::MockApiClient), )) .await; - + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let cache_key = "cacheKey".to_string(); let cache_key_value = "val".to_string(); let _ = state @@ -29,11 +33,23 @@ async fn invalidate_existing_cache_success() { let client = awc::Client::default(); cache::CONFIG_CACHE - .push(cache_key.clone(), cache_key_value.clone()) + .push( + CacheKey { + key: cache_key.clone(), + prefix: String::default(), + }, + cache_key_value.clone(), + ) .await; cache::ACCOUNTS_CACHE - .push(cache_key.clone(), cache_key_value.clone()) + .push( + CacheKey { + key: cache_key.clone(), + prefix: String::default(), + }, + cache_key_value.clone(), + ) .await; // Act @@ -51,11 +67,17 @@ async fn invalidate_existing_cache_success() { println!("invalidate Cache: {response:?} : {response_body:?}"); assert_eq!(response.status(), awc::http::StatusCode::OK); assert!(cache::CONFIG_CACHE - .get_val::(&cache_key) + .get_val::(CacheKey { + key: cache_key.clone(), + prefix: String::default() + }) .await .is_none()); assert!(cache::ACCOUNTS_CACHE - .get_val::(&cache_key) + .get_val::(CacheKey { + key: cache_key, + prefix: String::default() + }) .await .is_none()); } diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 414ab8cd1d5f..10e8b3665303 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData, str::FromStr}; +use std::{marker::PhantomData, str::FromStr, sync::Arc}; use api_models::payments::{Address, AddressDetails, PhoneDetails}; use common_utils::id_type; @@ -191,13 +191,16 @@ async fn payments_create_success() { let conf = Settings::new().unwrap(); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); static CV: aci::Aci = aci::Aci; let connector = types::api::ConnectorData { @@ -236,13 +239,16 @@ async fn payments_create_failure() { static CV: aci::Aci = aci::Aci; let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let connector = types::api::ConnectorData { connector: Box::new(&CV), connector_name: types::Connector::Aci, @@ -297,13 +303,16 @@ async fn refund_for_successful_payments() { }; let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let connector_integration: services::BoxedConnectorIntegration< '_, types::api::Authorize, @@ -366,13 +375,16 @@ async fn refunds_create_failure() { }; let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let connector_integration: services::BoxedConnectorIntegration< '_, types::api::Execute, diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index b7be24f2a158..0de19f17b54a 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -1,4 +1,4 @@ -use std::{fmt::Debug, marker::PhantomData, str::FromStr, time::Duration}; +use std::{fmt::Debug, marker::PhantomData, str::FromStr, sync::Arc, time::Duration}; use async_trait::async_trait; use common_utils::pii::Email; @@ -95,13 +95,16 @@ pub trait ConnectorActions: Connector { payment_info, ); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); integration.execute_pretasks(&mut request, &state).await?; Box::pin(call_connector(request, integration)).await } @@ -120,13 +123,16 @@ pub trait ConnectorActions: Connector { ); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); integration.execute_pretasks(&mut request, &state).await?; Box::pin(call_connector(request, integration)).await } @@ -145,13 +151,16 @@ pub trait ConnectorActions: Connector { ); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); integration.execute_pretasks(&mut request, &state).await?; Box::pin(call_connector(request, integration)).await } @@ -174,13 +183,16 @@ pub trait ConnectorActions: Connector { ); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); integration.execute_pretasks(&mut request, &state).await?; Box::pin(call_connector(request, integration)).await } @@ -598,13 +610,16 @@ pub trait ConnectorActions: Connector { let mut request = self.get_payout_request(None, payout_type, payment_info); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); connector_integration .execute_pretasks(&mut request, &state) .await?; @@ -639,13 +654,16 @@ pub trait ConnectorActions: Connector { let mut request = self.get_payout_request(connector_payout_id, payout_type, payment_info); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); connector_integration .execute_pretasks(&mut request, &state) .await?; @@ -681,13 +699,16 @@ pub trait ConnectorActions: Connector { request.connector_customer = connector_customer; let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); connector_integration .execute_pretasks(&mut request, &state) .await?; @@ -723,13 +744,16 @@ pub trait ConnectorActions: Connector { self.get_payout_request(Some(connector_payout_id), payout_type, payment_info); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); connector_integration .execute_pretasks(&mut request, &state) .await?; @@ -811,13 +835,16 @@ pub trait ConnectorActions: Connector { let mut request = self.get_payout_request(None, payout_type, payment_info); let tx = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( Settings::new().unwrap(), StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); connector_integration .execute_pretasks(&mut request, &state) .await?; @@ -844,13 +871,16 @@ async fn call_connector< let conf = Settings::new().unwrap(); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); services::api::execute_connector_processing_step( &state, integration, diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index e76eee4c1792..ed11f3b8b1cb 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -2,6 +2,8 @@ mod utils; +use std::sync::Arc; + use common_utils::{id_type, types::MinorUnit}; use router::{ configs, @@ -276,13 +278,16 @@ async fn payments_create_core() { use configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let key_store = state .store @@ -457,13 +462,16 @@ async fn payments_create_core_adyen_no_redirect() { use crate::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let customer_id = format!("cust_{}", Uuid::new_v4()); let merchant_id = "arunraj".to_string(); diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index 42cfe3b74c1d..4c178e4122bb 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -2,6 +2,8 @@ mod utils; +use std::sync::Arc; + use common_utils::{id_type, types::MinorUnit}; use router::{ core::payments, @@ -36,13 +38,16 @@ async fn payments_create_core() { use router::configs::settings::Settings; let conf = Settings::new().expect("invalid settings"); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let key_store = state .store @@ -224,13 +229,16 @@ async fn payments_create_core_adyen_no_redirect() { let conf = Settings::new().expect("invalid settings"); let tx: oneshot::Sender<()> = oneshot::channel().0; - let state = Box::pin(routes::AppState::with_storage( + let app_state = Box::pin(routes::AppState::with_storage( conf, StorageImpl::PostgresqlTest, tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let customer_id = format!("cust_{}", Uuid::new_v4()); let merchant_id = "arunraj".to_string(); diff --git a/crates/router/tests/services.rs b/crates/router/tests/services.rs index eff7fe7f8738..d907000cccd9 100644 --- a/crates/router/tests/services.rs +++ b/crates/router/tests/services.rs @@ -1,4 +1,4 @@ -use std::sync::atomic; +use std::sync::{atomic, Arc}; use router::{configs::settings::Settings, routes, services}; @@ -6,16 +6,20 @@ mod utils; #[tokio::test] #[should_panic] +#[allow(clippy::unwrap_used)] async fn get_redis_conn_failure() { // Arrange utils::setup().await; let (tx, _) = tokio::sync::oneshot::channel(); - let state = Box::pin(routes::AppState::new( + let app_state = Box::pin(routes::AppState::new( Settings::default(), tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); let _ = state.store.get_redis_conn().map(|conn| { conn.is_redis_available @@ -30,16 +34,20 @@ async fn get_redis_conn_failure() { } #[tokio::test] +#[allow(clippy::unwrap_used)] async fn get_redis_conn_success() { // Arrange Box::pin(utils::setup()).await; let (tx, _) = tokio::sync::oneshot::channel(); - let state = Box::pin(routes::AppState::new( + let app_state = Box::pin(routes::AppState::new( Settings::default(), tx, Box::new(services::MockApiClient), )) .await; + let state = Arc::new(app_state) + .get_session_state("public", || {}) + .unwrap(); // Act let result = state.store.get_redis_conn(); diff --git a/crates/scheduler/src/consumer.rs b/crates/scheduler/src/consumer.rs index a95ac4932471..3e15a7cde0fb 100644 --- a/crates/scheduler/src/consumer.rs +++ b/crates/scheduler/src/consumer.rs @@ -1,6 +1,9 @@ // TODO: Figure out what to log -use std::sync::{self, atomic}; +use std::{ + sync::{self, atomic}, + time as std_time, +}; pub mod types; pub mod workflows; @@ -22,7 +25,7 @@ use super::env::logger; pub use super::workflows::ProcessTrackerWorkflow; use crate::{ configs::settings::SchedulerSettings, db::process_tracker::ProcessTrackerInterface, errors, - metrics, utils as pt_utils, SchedulerAppState, SchedulerInterface, + metrics, utils as pt_utils, SchedulerAppState, SchedulerInterface, SchedulerSessionState, }; // Valid consumer business statuses @@ -31,12 +34,16 @@ pub fn valid_business_statuses() -> Vec<&'static str> { } #[instrument(skip_all)] -pub async fn start_consumer( +pub async fn start_consumer( state: &T, settings: sync::Arc, - workflow_selector: impl workflows::ProcessTrackerWorkflows + 'static + Copy + std::fmt::Debug, + workflow_selector: impl workflows::ProcessTrackerWorkflows + 'static + Copy + std::fmt::Debug, (tx, mut rx): (mpsc::Sender<()>, mpsc::Receiver<()>), -) -> CustomResult<(), errors::ProcessTrackerError> { + app_state_to_session_state: F, +) -> CustomResult<(), errors::ProcessTrackerError> +where + F: Fn(&T, &str) -> CustomResult, +{ use std::time::Duration; use rand::distributions::{Distribution, Uniform}; @@ -77,17 +84,29 @@ pub async fn start_consumer( if settings.consumer.disabled { continue; } + consumer_operation_counter.fetch_add(1, atomic::Ordering::SeqCst); + let start_time = std_time::Instant::now(); + let tenants = state.get_tenants(); + for tenant in tenants { + let session_state = app_state_to_session_state(state, tenant.as_str())?; + pt_utils::consumer_operation_handler( + session_state.clone(), + settings.clone(), + |error| { + logger::error!(?error, "Failed to perform consumer operation"); + }, + workflow_selector, + ) + .await; + } + + let end_time = std_time::Instant::now(); + let duration = end_time.saturating_duration_since(start_time).as_secs_f64(); + logger::debug!("Time taken to execute consumer_operation: {}s", duration); - pt_utils::consumer_operation_handler( - state.clone(), - settings.clone(), - |error| { - logger::error!(?error, "Failed to perform consumer operation"); - }, - sync::Arc::clone(&consumer_operation_counter), - workflow_selector, - ) - .await; + let current_count = + consumer_operation_counter.fetch_sub(1, atomic::Ordering::SeqCst); + logger::info!("Current tasks being executed: {}", current_count); } Ok(()) | Err(mpsc::error::TryRecvError::Disconnected) => { logger::debug!("Awaiting shutdown!"); @@ -116,7 +135,7 @@ pub async fn start_consumer( } #[instrument(skip_all)] -pub async fn consumer_operations( +pub async fn consumer_operations( state: &T, settings: &SchedulerSettings, workflow_selector: impl workflows::ProcessTrackerWorkflows + 'static + Copy + std::fmt::Debug, @@ -125,13 +144,10 @@ pub async fn consumer_operations( let group_name = settings.consumer.consumer_group.clone(); let consumer_name = format!("consumer_{}", Uuid::new_v4()); - let group_created = &mut state + let _group_created = &mut state .get_db() .consumer_group_create(&stream_name, &group_name, &RedisEntryId::AfterLastID) .await; - if group_created.is_err() { - logger::info!("Consumer group {group_name} already exists"); - } let mut tasks = state .get_db() @@ -139,7 +155,9 @@ pub async fn consumer_operations( .fetch_consumer_tasks(&stream_name, &group_name, &consumer_name) .await?; - logger::info!("{} picked {} tasks", consumer_name, tasks.len()); + if !tasks.is_empty() { + logger::info!("{} picked {} tasks", consumer_name, tasks.len()); + } let mut handler = vec![]; for task in tasks.iter_mut() { @@ -216,11 +234,10 @@ pub async fn start_workflow( workflow_selector: impl workflows::ProcessTrackerWorkflows + 'static + std::fmt::Debug, ) -> CustomResult<(), errors::ProcessTrackerError> where - T: SchedulerAppState, + T: SchedulerSessionState, { tracing::Span::current().record("workflow_id", Uuid::new_v4().to_string()); logger::info!(pt.name=?process.name, pt.id=%process.id); - let res = workflow_selector .trigger_workflow(&state.clone(), process.clone()) .await diff --git a/crates/scheduler/src/consumer/workflows.rs b/crates/scheduler/src/consumer/workflows.rs index 3e8a4c8e5028..bbece87f3094 100644 --- a/crates/scheduler/src/consumer/workflows.rs +++ b/crates/scheduler/src/consumer/workflows.rs @@ -3,7 +3,7 @@ use common_utils::errors::CustomResult; pub use diesel_models::process_tracker as storage; use router_env::logger; -use crate::{errors, SchedulerAppState}; +use crate::{errors, SchedulerSessionState}; pub type WorkflowSelectorFn = fn(&storage::ProcessTracker) -> Result<(), errors::ProcessTrackerError>; @@ -26,7 +26,7 @@ pub trait ProcessTrackerWorkflows: Send + Sync { process: storage::ProcessTracker, ) -> CustomResult<(), errors::ProcessTrackerError> where - T: SchedulerAppState, + T: SchedulerSessionState, { let app_state = &state.clone(); let output = operation.execute_workflow(app_state, process.clone()).await; diff --git a/crates/scheduler/src/errors.rs b/crates/scheduler/src/errors.rs index e630287c316a..52ea03e0c470 100644 --- a/crates/scheduler/src/errors.rs +++ b/crates/scheduler/src/errors.rs @@ -59,6 +59,8 @@ pub enum ProcessTrackerError { EEmailError(error_stack::Report), #[error("Type Conversion error")] TypeConversionError, + #[error("Tenant not found")] + TenantNotFound, } #[macro_export] diff --git a/crates/scheduler/src/producer.rs b/crates/scheduler/src/producer.rs index 397aab84e912..6390bc66897a 100644 --- a/crates/scheduler/src/producer.rs +++ b/crates/scheduler/src/producer.rs @@ -16,17 +16,20 @@ use super::{ }; use crate::{ configs::settings::SchedulerSettings, errors, flow::SchedulerFlow, - scheduler::SchedulerInterface, utils::*, SchedulerAppState, + scheduler::SchedulerInterface, utils::*, SchedulerAppState, SchedulerSessionState, }; #[instrument(skip_all)] -pub async fn start_producer( +pub async fn start_producer( state: &T, scheduler_settings: Arc, (tx, mut rx): (mpsc::Sender<()>, mpsc::Receiver<()>), + app_state_to_session_state: F, ) -> CustomResult<(), errors::ProcessTrackerError> where + F: Fn(&T, &str) -> CustomResult, T: SchedulerAppState, + U: SchedulerSessionState, { use std::time::Duration; @@ -64,13 +67,17 @@ where match rx.try_recv() { Err(mpsc::error::TryRecvError::Empty) => { interval.tick().await; - match run_producer_flow(state, &scheduler_settings).await { - Ok(_) => (), - Err(error) => { - // Intentionally not propagating error to caller. - // Any errors that occur in the producer flow must be handled here only, as - // this is the topmost level function which is concerned with the producer flow. - error!(%error); + let tenants = state.get_tenants(); + for tenant in tenants { + let session_state = app_state_to_session_state(state, tenant.as_str())?; + match run_producer_flow(&session_state, &scheduler_settings).await { + Ok(_) => (), + Err(error) => { + // Intentionally not propagating error to caller. + // Any errors that occur in the producer flow must be handled here only, as + // this is the topmost level function which is concerned with the producer flow. + error!(%error); + } } } } @@ -78,7 +85,7 @@ where logger::debug!("Awaiting shutdown!"); rx.close(); shutdown_interval.tick().await; - logger::info!("Terminating consumer"); + logger::info!("Terminating producer"); break; } } @@ -97,7 +104,7 @@ pub async fn run_producer_flow( settings: &SchedulerSettings, ) -> CustomResult<(), errors::ProcessTrackerError> where - T: SchedulerAppState, + T: SchedulerSessionState, { lock_acquire_release::<_, _, _>(state.get_db().as_scheduler(), settings, move || async { let tasks = fetch_producer_tasks(state.get_db().as_scheduler(), settings).await?; diff --git a/crates/scheduler/src/scheduler.rs b/crates/scheduler/src/scheduler.rs index 273f10819f8d..39a45d02ba96 100644 --- a/crates/scheduler/src/scheduler.rs +++ b/crates/scheduler/src/scheduler.rs @@ -52,22 +52,46 @@ impl SchedulerInterface for MockDb {} #[async_trait::async_trait] pub trait SchedulerAppState: Send + Sync + Clone { + fn get_tenants(&self) -> Vec; +} +#[async_trait::async_trait] +pub trait SchedulerSessionState: Send + Sync + Clone { fn get_db(&self) -> Box; } - -pub async fn start_process_tracker( +pub async fn start_process_tracker< + T: SchedulerAppState + 'static, + U: SchedulerSessionState + 'static, + F, +>( state: &T, scheduler_flow: SchedulerFlow, scheduler_settings: Arc, channel: (mpsc::Sender<()>, mpsc::Receiver<()>), - runner_from_task: impl workflows::ProcessTrackerWorkflows + 'static + Copy + std::fmt::Debug, -) -> CustomResult<(), errors::ProcessTrackerError> { + runner_from_task: impl workflows::ProcessTrackerWorkflows + 'static + Copy + std::fmt::Debug, + app_state_to_session_state: F, +) -> CustomResult<(), errors::ProcessTrackerError> +where + F: Fn(&T, &str) -> CustomResult, +{ match scheduler_flow { SchedulerFlow::Producer => { - producer::start_producer(state, scheduler_settings, channel).await? + producer::start_producer( + state, + scheduler_settings, + channel, + app_state_to_session_state, + ) + .await? } SchedulerFlow::Consumer => { - consumer::start_consumer(state, scheduler_settings, runner_from_task, channel).await? + consumer::start_consumer( + state, + scheduler_settings, + runner_from_task, + channel, + app_state_to_session_state, + ) + .await? } SchedulerFlow::Cleaner => { error!("This flow has not been implemented yet!"); diff --git a/crates/scheduler/src/utils.rs b/crates/scheduler/src/utils.rs index 8b80b7c72c1f..7f073a8e10b9 100644 --- a/crates/scheduler/src/utils.rs +++ b/crates/scheduler/src/utils.rs @@ -1,7 +1,4 @@ -use std::{ - sync::{self, atomic}, - time as std_time, -}; +use std::sync; use common_utils::errors::CustomResult; use diesel_models::enums::{self, ProcessTrackerStatus}; @@ -17,7 +14,7 @@ use super::{ }; use crate::{ configs::settings::SchedulerSettings, consumer::types::ProcessTrackerBatch, errors, - flow::SchedulerFlow, metrics, SchedulerAppState, SchedulerInterface, + flow::SchedulerFlow, metrics, SchedulerInterface, SchedulerSessionState, }; pub async fn divide_and_append_tasks( @@ -258,26 +255,16 @@ pub async fn consumer_operation_handler( state: T, settings: sync::Arc, error_handler_fun: E, - consumer_operation_counter: sync::Arc, workflow_selector: impl workflows::ProcessTrackerWorkflows + 'static + Copy + std::fmt::Debug, ) where // Error handler function E: FnOnce(error_stack::Report), - T: SchedulerAppState + Send + Sync + 'static, + T: SchedulerSessionState + Send + Sync + 'static, { - consumer_operation_counter.fetch_add(1, atomic::Ordering::SeqCst); - let start_time = std_time::Instant::now(); - match consumer::consumer_operations(&state, &settings, workflow_selector).await { Ok(_) => (), Err(err) => error_handler_fun(err), } - let end_time = std_time::Instant::now(); - let duration = end_time.saturating_duration_since(start_time).as_secs_f64(); - logger::debug!("Time taken to execute consumer_operation: {}s", duration); - - let current_count = consumer_operation_counter.fetch_sub(1, atomic::Ordering::SeqCst); - logger::info!("Current tasks being executed: {}", current_count); } pub fn add_histogram_metrics( diff --git a/crates/storage_impl/src/config.rs b/crates/storage_impl/src/config.rs index fd95a6d315d6..e371936a04dd 100644 --- a/crates/storage_impl/src/config.rs +++ b/crates/storage_impl/src/config.rs @@ -1,3 +1,4 @@ +use common_utils::DbConnectionParams; use masking::Secret; #[derive(Debug, Clone, serde::Deserialize)] @@ -14,6 +15,29 @@ pub struct Database { pub max_lifetime: Option, } +impl DbConnectionParams for Database { + fn get_username(&self) -> &str { + &self.username + } + fn get_password(&self) -> Secret { + self.password.clone() + } + fn get_host(&self) -> &str { + &self.host + } + fn get_port(&self) -> u16 { + self.port + } + fn get_dbname(&self) -> &str { + &self.dbname + } +} + +pub trait TenantConfig: Send + Sync { + fn get_schema(&self) -> &str; + fn get_redis_key_prefix(&self) -> &str; +} + #[derive(Debug, serde::Deserialize, Clone, Copy, Default)] #[serde(rename_all = "PascalCase")] pub enum QueueStrategy { diff --git a/crates/storage_impl/src/database/store.rs b/crates/storage_impl/src/database/store.rs index 17ae76b5bb03..543cc47870d9 100644 --- a/crates/storage_impl/src/database/store.rs +++ b/crates/storage_impl/src/database/store.rs @@ -1,11 +1,11 @@ use async_bb8_diesel::{AsyncConnection, ConnectionError}; use bb8::CustomizeConnection; +use common_utils::DbConnectionParams; use diesel::PgConnection; use error_stack::ResultExt; use hyperswitch_domain_models::errors::{StorageError, StorageResult}; -use masking::PeekInterface; -use crate::config::Database; +use crate::config::{Database, TenantConfig}; pub type PgPool = bb8::Pool>; pub type PgPooledConn = async_bb8_diesel::Connection; @@ -13,7 +13,11 @@ pub type PgPooledConn = async_bb8_diesel::Connection; #[async_trait::async_trait] pub trait DatabaseStore: Clone + Send + Sync { type Config: Send; - async fn new(config: Self::Config, test_transaction: bool) -> StorageResult; + async fn new( + config: Self::Config, + tenant_config: &dyn TenantConfig, + test_transaction: bool, + ) -> StorageResult; fn get_master_pool(&self) -> &PgPool; fn get_replica_pool(&self) -> &PgPool; } @@ -26,9 +30,14 @@ pub struct Store { #[async_trait::async_trait] impl DatabaseStore for Store { type Config = Database; - async fn new(config: Database, test_transaction: bool) -> StorageResult { + async fn new( + config: Database, + tenant_config: &dyn TenantConfig, + test_transaction: bool, + ) -> StorageResult { Ok(Self { - master_pool: diesel_make_pg_pool(&config, test_transaction).await?, + master_pool: diesel_make_pg_pool(&config, tenant_config.get_schema(), test_transaction) + .await?, }) } @@ -50,14 +59,23 @@ pub struct ReplicaStore { #[async_trait::async_trait] impl DatabaseStore for ReplicaStore { type Config = (Database, Database); - async fn new(config: (Database, Database), test_transaction: bool) -> StorageResult { + async fn new( + config: (Database, Database), + tenant_config: &dyn TenantConfig, + test_transaction: bool, + ) -> StorageResult { let (master_config, replica_config) = config; - let master_pool = diesel_make_pg_pool(&master_config, test_transaction) - .await - .attach_printable("failed to create master pool")?; - let replica_pool = diesel_make_pg_pool(&replica_config, test_transaction) - .await - .attach_printable("failed to create replica pool")?; + let master_pool = + diesel_make_pg_pool(&master_config, tenant_config.get_schema(), test_transaction) + .await + .attach_printable("failed to create master pool")?; + let replica_pool = diesel_make_pg_pool( + &replica_config, + tenant_config.get_schema(), + test_transaction, + ) + .await + .attach_printable("failed to create replica pool")?; Ok(Self { master_pool, replica_pool, @@ -75,16 +93,10 @@ impl DatabaseStore for ReplicaStore { pub async fn diesel_make_pg_pool( database: &Database, + schema: &str, test_transaction: bool, ) -> StorageResult { - let database_url = format!( - "postgres://{}:{}@{}:{}/{}", - database.username, - database.password.peek(), - database.host, - database.port, - database.dbname - ); + let database_url = database.get_database_url(schema); let manager = async_bb8_diesel::ConnectionManager::::new(database_url); let mut pool = bb8::Pool::builder() .max_size(database.pool_size) diff --git a/crates/storage_impl/src/lib.rs b/crates/storage_impl/src/lib.rs index b1582bb6e9af..d55f812c5a21 100644 --- a/crates/storage_impl/src/lib.rs +++ b/crates/storage_impl/src/lib.rs @@ -29,7 +29,7 @@ use database::store::PgPool; #[cfg(not(feature = "payouts"))] use hyperswitch_domain_models::{PayoutAttemptInterface, PayoutsInterface}; pub use mock_db::MockDb; -use redis_interface::{errors::RedisError, SaddReply}; +use redis_interface::{errors::RedisError, RedisConnectionPool, SaddReply}; pub use crate::database::store::DatabaseStore; #[cfg(not(feature = "payouts"))] @@ -38,7 +38,7 @@ pub use crate::database::store::Store; #[derive(Debug, Clone)] pub struct RouterStore { db_store: T, - cache_store: RedisStore, + cache_store: Arc, master_encryption_key: StrongSecret>, pub request_id: Option, } @@ -55,19 +55,23 @@ where tokio::sync::oneshot::Sender<()>, &'static str, ); - async fn new(config: Self::Config, test_transaction: bool) -> StorageResult { + async fn new( + config: Self::Config, + tenant_config: &dyn config::TenantConfig, + test_transaction: bool, + ) -> StorageResult { let (db_conf, cache_conf, encryption_key, cache_error_signal, inmemory_cache_stream) = config; if test_transaction { - Self::test_store(db_conf, &cache_conf, encryption_key) + Self::test_store(db_conf, tenant_config, &cache_conf, encryption_key) .await .attach_printable("failed to create test router store") } else { Self::from_config( db_conf, - &cache_conf, + tenant_config, encryption_key, - cache_error_signal, + Self::cache_store(&cache_conf, cache_error_signal).await?, inmemory_cache_stream, ) .await @@ -83,9 +87,7 @@ where } impl RedisConnInterface for RouterStore { - fn get_redis_conn( - &self, - ) -> error_stack::Result, RedisError> { + fn get_redis_conn(&self) -> error_stack::Result, RedisError> { self.cache_store.get_redis_conn() } } @@ -93,23 +95,26 @@ impl RedisConnInterface for RouterStore { impl RouterStore { pub async fn from_config( db_conf: T::Config, - cache_conf: &redis_interface::RedisSettings, + tenant_config: &dyn config::TenantConfig, encryption_key: StrongSecret>, - cache_error_signal: tokio::sync::oneshot::Sender<()>, + cache_store: Arc, inmemory_cache_stream: &str, ) -> StorageResult { - let db_store = T::new(db_conf, false).await?; - let cache_store = RedisStore::new(cache_conf) - .await - .change_context(StorageError::InitializationError) - .attach_printable("Failed to create cache store")?; - cache_store.set_error_callback(cache_error_signal); + let db_store = T::new(db_conf, tenant_config, false).await?; + let redis_conn = cache_store.redis_conn.clone(); + let cache_store = Arc::new(RedisStore { + redis_conn: Arc::new(RedisConnectionPool::clone( + &redis_conn, + tenant_config.get_redis_key_prefix(), + )), + }); cache_store .redis_conn .subscribe(inmemory_cache_stream) .await .change_context(StorageError::InitializationError) .attach_printable("Failed to subscribe to inmemory cache stream")?; + Ok(Self { db_store, cache_store, @@ -118,6 +123,18 @@ impl RouterStore { }) } + pub async fn cache_store( + cache_conf: &redis_interface::RedisSettings, + cache_error_signal: tokio::sync::oneshot::Sender<()>, + ) -> StorageResult> { + let cache_store = RedisStore::new(cache_conf) + .await + .change_context(StorageError::InitializationError) + .attach_printable("Failed to create cache store")?; + cache_store.set_error_callback(cache_error_signal); + Ok(Arc::new(cache_store)) + } + pub fn master_key(&self) -> &StrongSecret> { &self.master_encryption_key } @@ -127,18 +144,19 @@ impl RouterStore { /// Will panic if `CONNECTOR_AUTH_FILE_PATH` is not set pub async fn test_store( db_conf: T::Config, + tenant_config: &dyn config::TenantConfig, cache_conf: &redis_interface::RedisSettings, encryption_key: StrongSecret>, ) -> StorageResult { // TODO: create an error enum and return proper error here - let db_store = T::new(db_conf, true).await?; + let db_store = T::new(db_conf, tenant_config, true).await?; let cache_store = RedisStore::new(cache_conf) .await .change_context(StorageError::InitializationError) .attach_printable("failed to create redis cache")?; Ok(Self { db_store, - cache_store, + cache_store: Arc::new(cache_store), master_encryption_key: encryption_key, request_id: None, }) @@ -162,9 +180,13 @@ where T: DatabaseStore, { type Config = (RouterStore, String, u8, u32, Option); - async fn new(config: Self::Config, _test_transaction: bool) -> StorageResult { - let (router_store, drainer_stream_name, drainer_num_partitions, ttl_for_kv, soft_kill_mode) = - config; + async fn new( + config: Self::Config, + tenant_config: &dyn config::TenantConfig, + _test_transaction: bool, + ) -> StorageResult { + let (router_store, _, drainer_num_partitions, ttl_for_kv, soft_kill_mode) = config; + let drainer_stream_name = format!("{}_{}", tenant_config.get_schema(), config.1); Ok(Self::from_store( router_store, drainer_stream_name, @@ -182,9 +204,7 @@ where } impl RedisConnInterface for KVRouterStore { - fn get_redis_conn( - &self, - ) -> error_stack::Result, RedisError> { + fn get_redis_conn(&self) -> error_stack::Result, RedisError> { self.router_store.get_redis_conn() } } @@ -282,7 +302,7 @@ pub trait UniqueConstraints { fn table_name(&self) -> &str; async fn check_for_constraints( &self, - redis_conn: &Arc, + redis_conn: &Arc, ) -> CustomResult<(), RedisError> { let constraints = self.unique_constraints(); let sadd_result = redis_conn diff --git a/crates/storage_impl/src/redis/cache.rs b/crates/storage_impl/src/redis/cache.rs index 4a72b86fefb7..c0375773b544 100644 --- a/crates/storage_impl/src/redis/cache.rs +++ b/crates/storage_impl/src/redis/cache.rs @@ -1,4 +1,4 @@ -use std::{any::Any, borrow::Cow, sync::Arc}; +use std::{any::Any, borrow::Cow, fmt::Debug, sync::Arc}; use common_utils::{ errors::{self, CustomResult}, @@ -8,7 +8,7 @@ use dyn_clone::DynClone; use error_stack::{Report, ResultExt}; use moka::future::Cache as MokaCache; use once_cell::sync::Lazy; -use redis_interface::{errors::RedisError, RedisValue}; +use redis_interface::{errors::RedisError, RedisConnectionPool, RedisValue}; use router_env::tracing::{self, instrument}; use crate::{ @@ -118,6 +118,23 @@ pub struct Cache { inner: MokaCache>, } +#[derive(Debug, Clone)] +pub struct CacheKey { + pub key: String, + // #TODO: make it usage specific enum Eg: CacheKind { Tenant(String), NoTenant, Partition(String) } + pub prefix: String, +} + +impl From for String { + fn from(val: CacheKey) -> Self { + if val.prefix.is_empty() { + val.key + } else { + format!("{}:{}", val.prefix, val.key) + } + } +} + impl Cache { /// With given `time_to_live` and `time_to_idle` creates a moka cache. /// @@ -138,44 +155,38 @@ impl Cache { } } - pub async fn push(&self, key: String, val: T) { - self.inner.insert(key, Arc::new(val)).await; + pub async fn push(&self, key: CacheKey, val: T) { + self.inner.insert(key.into(), Arc::new(val)).await; } - pub async fn get_val(&self, key: &str) -> Option { - let val = self.inner.get(key).await?; + pub async fn get_val(&self, key: CacheKey) -> Option { + let val = self.inner.get::(&key.into()).await?; (*val).as_any().downcast_ref::().cloned() } /// Check if a key exists in cache - pub async fn exists(&self, key: &str) -> bool { - self.inner.contains_key(key) + pub async fn exists(&self, key: CacheKey) -> bool { + self.inner.contains_key::(&key.into()) } - pub async fn remove(&self, key: &str) { - self.inner.invalidate(key).await; + pub async fn remove(&self, key: CacheKey) { + self.inner.invalidate::(&key.into()).await; } } #[instrument(skip_all)] pub async fn get_or_populate_redis( - store: &(dyn RedisConnInterface + Send + Sync), + redis: &Arc, key: impl AsRef, fun: F, ) -> CustomResult where - T: serde::Serialize + serde::de::DeserializeOwned + std::fmt::Debug, + T: serde::Serialize + serde::de::DeserializeOwned + Debug, F: FnOnce() -> Fut + Send, Fut: futures::Future> + Send, { let type_name = std::any::type_name::(); let key = key.as_ref(); - let redis = &store - .get_redis_conn() - .change_context(StorageError::RedisError( - RedisError::RedisConnectionError.into(), - )) - .attach_printable("Failed to get redis connection")?; let redis_val = redis.get_and_deserialize_key::(key, type_name).await; let get_data_set_redis = || async { let data = fun().await?; @@ -206,16 +217,35 @@ pub async fn get_or_populate_in_memory( cache: &Cache, ) -> CustomResult where - T: Cacheable + serde::Serialize + serde::de::DeserializeOwned + std::fmt::Debug + Clone, + T: Cacheable + serde::Serialize + serde::de::DeserializeOwned + Debug + Clone, F: FnOnce() -> Fut + Send, Fut: futures::Future> + Send, { - let cache_val = cache.get_val::(key).await; + let redis = &store + .get_redis_conn() + .change_context(StorageError::RedisError( + RedisError::RedisConnectionError.into(), + )) + .attach_printable("Failed to get redis connection")?; + let cache_val = cache + .get_val::(CacheKey { + key: key.to_string(), + prefix: redis.key_prefix.clone(), + }) + .await; if let Some(val) = cache_val { Ok(val) } else { - let val = get_or_populate_redis(store, key, fun).await?; - cache.push(key.to_string(), val.clone()).await; + let val = get_or_populate_redis(redis, key, fun).await?; + cache + .push( + CacheKey { + key: key.to_string(), + prefix: redis.key_prefix.clone(), + }, + val.clone(), + ) + .await; Ok(val) } } @@ -223,7 +253,7 @@ where #[instrument(skip_all)] pub async fn redact_cache( store: &(dyn RedisConnInterface + Send + Sync), - key: &str, + key: &'static str, fun: F, in_memory: Option<&Cache>, ) -> CustomResult @@ -232,7 +262,6 @@ where Fut: futures::Future> + Send, { let data = fun().await?; - in_memory.async_map(|cache| cache.remove(key)).await; let redis_conn = store .get_redis_conn() @@ -240,6 +269,11 @@ where RedisError::RedisConnectionError.into(), )) .attach_printable("Failed to get redis connection")?; + let tenant_key = CacheKey { + key: key.to_string(), + prefix: redis_conn.key_prefix.clone(), + }; + in_memory.async_map(|cache| cache.remove(tenant_key)).await; redis_conn .delete_key(key) @@ -312,9 +346,22 @@ mod cache_tests { #[tokio::test] async fn construct_and_get_cache() { let cache = Cache::new(1800, 1800, None); - cache.push("key".to_string(), "val".to_string()).await; + cache + .push( + CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string(), + }, + "val".to_string(), + ) + .await; assert_eq!( - cache.get_val::("key").await, + cache + .get_val::(CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string() + }) + .await, Some(String::from("val")) ); } @@ -322,25 +369,78 @@ mod cache_tests { #[tokio::test] async fn eviction_on_size_test() { let cache = Cache::new(2, 2, Some(0)); - cache.push("key".to_string(), "val".to_string()).await; - assert_eq!(cache.get_val::("key").await, None); + cache + .push( + CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string(), + }, + "val".to_string(), + ) + .await; + assert_eq!( + cache + .get_val::(CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string() + }) + .await, + None + ); } #[tokio::test] async fn invalidate_cache_for_key() { let cache = Cache::new(1800, 1800, None); - cache.push("key".to_string(), "val".to_string()).await; + cache + .push( + CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string(), + }, + "val".to_string(), + ) + .await; + + cache + .remove(CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string(), + }) + .await; - cache.remove("key").await; - - assert_eq!(cache.get_val::("key").await, None); + assert_eq!( + cache + .get_val::(CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string() + }) + .await, + None + ); } #[tokio::test] async fn eviction_on_time_test() { let cache = Cache::new(2, 2, None); - cache.push("key".to_string(), "val".to_string()).await; + cache + .push( + CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string(), + }, + "val".to_string(), + ) + .await; tokio::time::sleep(std::time::Duration::from_secs(3)).await; - assert_eq!(cache.get_val::("key").await, None); + assert_eq!( + cache + .get_val::(CacheKey { + key: "key".to_string(), + prefix: "prefix".to_string() + }) + .await, + None + ); } } diff --git a/crates/storage_impl/src/redis/pub_sub.rs b/crates/storage_impl/src/redis/pub_sub.rs index 830f6251d6b6..1f079784243a 100644 --- a/crates/storage_impl/src/redis/pub_sub.rs +++ b/crates/storage_impl/src/redis/pub_sub.rs @@ -2,7 +2,9 @@ use error_stack::ResultExt; use redis_interface::{errors as redis_errors, PubsubInterface, RedisValue}; use router_env::{logger, tracing::Instrument}; -use crate::redis::cache::{CacheKind, ACCOUNTS_CACHE, CGRAPH_CACHE, CONFIG_CACHE, ROUTING_CACHE}; +use crate::redis::cache::{ + CacheKey, CacheKind, ACCOUNTS_CACHE, CGRAPH_CACHE, CONFIG_CACHE, ROUTING_CACHE, +}; #[async_trait::async_trait] pub trait PubSubInterface { @@ -55,7 +57,7 @@ impl PubSubInterface for std::sync::Arc { #[inline] async fn on_message(&self) -> error_stack::Result<(), redis_errors::RedisError> { - logger::debug!("Started on message"); + logger::debug!("Started on message: {:?}", self.key_prefix); let mut rx = self.subscriber.on_message(); while let Ok(message) = rx.recv().await { logger::debug!("Invalidating {message:?}"); @@ -71,26 +73,66 @@ impl PubSubInterface for std::sync::Arc { let key = match key { CacheKind::Config(key) => { - CONFIG_CACHE.remove(key.as_ref()).await; + CONFIG_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; key } CacheKind::Accounts(key) => { - ACCOUNTS_CACHE.remove(key.as_ref()).await; + ACCOUNTS_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; key } CacheKind::CGraph(key) => { - CGRAPH_CACHE.remove(key.as_ref()).await; + CGRAPH_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; key } CacheKind::Routing(key) => { - ROUTING_CACHE.remove(key.as_ref()).await; + ROUTING_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; key } CacheKind::All(key) => { - CONFIG_CACHE.remove(key.as_ref()).await; - ACCOUNTS_CACHE.remove(key.as_ref()).await; - CGRAPH_CACHE.remove(key.as_ref()).await; - ROUTING_CACHE.remove(key.as_ref()).await; + CONFIG_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + ACCOUNTS_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + CGRAPH_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + ROUTING_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; key } }; diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index ad60418339c2..2abe90f6086a 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -322,3 +322,9 @@ partner_id = "" [unmasked_headers] keys = "user-agent" + +[multitenancy] +enabled = false + +[multitenancy.tenants] +public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "public", redis_key_prefix = ""} \ No newline at end of file From 0cbb2928bd054cb8e98c3811f397a837a8887486 Mon Sep 17 00:00:00 2001 From: Mani Chandra <84711804+ThisIsMani@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:22:42 +0530 Subject: [PATCH 09/10] feat(users): Create config for TOTP Issuer (#4776) --- config/config.example.toml | 5 ++-- config/deployments/integration_test.toml | 1 + config/deployments/production.toml | 1 + config/deployments/sandbox.toml | 1 + config/development.toml | 1 + config/docker_compose.toml | 1 + crates/router/src/configs/settings.rs | 1 + crates/router/src/consts/user.rs | 4 ++- crates/router/src/core/user.rs | 25 ++++++++++++++++--- .../router/src/utils/user/two_factor_auth.rs | 3 ++- loadtest/config/development.toml | 1 + 11 files changed, 36 insertions(+), 8 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index 8aa0ca9e52f2..ac428298e73d 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -351,8 +351,9 @@ email_role_arn = "" # The amazon resource name ( arn ) of the role which sts_role_session_name = "" # An identifier for the assumed role session, used to uniquely identify a session. [user] -password_validity_in_days = 90 # Number of days after which password should be updated -two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside +password_validity_in_days = 90 # Number of days after which password should be updated +two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside +totp_issuer_name = "Hyperswitch" # Name of the issuer for TOTP #tokenization configuration which describe token lifetime and payment method for specific connector [tokenization] diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index f6ed3ca5ea5b..8d76771f897e 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -114,6 +114,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 +totp_issuer_name = "Hyperswitch Integ" [frm] enabled = true diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 37b35eb47e7b..65f8d87215a6 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -121,6 +121,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 +totp_issuer_name = "Hyperswitch Production" [frm] enabled = false diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index fc496e34fc30..94f6d4b34302 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -121,6 +121,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 +totp_issuer_name = "Hyperswitch Sandbox" [frm] enabled = true diff --git a/config/development.toml b/config/development.toml index d12a667b6315..25fe55e60575 100644 --- a/config/development.toml +++ b/config/development.toml @@ -270,6 +270,7 @@ sts_role_session_name = "" [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 +totp_issuer_name = "Hyperswitch Dev" [bank_config.eps] stripe = { banks = "arzte_und_apotheker_bank,austrian_anadi_bank_ag,bank_austria,bankhaus_carl_spangler,bankhaus_schelhammer_und_schattera_ag,bawag_psk_ag,bks_bank_ag,brull_kallmus_bank_ag,btv_vier_lander_bank,capital_bank_grawe_gruppe_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_alpeadriabank_international_ag,hypo_noe_lb_fur_niederosterreich_u_wien,hypo_oberosterreich_salzburg_steiermark,hypo_tirol_bank_ag,hypo_vorarlberg_bank_ag,hypo_bank_burgenland_aktiengesellschaft,marchfelder_bank,oberbank_ag,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag,vr_bank_braunau" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 3f6c9523e933..f43ceca893d5 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -54,6 +54,7 @@ recon_admin_api_key = "recon_test_admin" [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 +totp_issuer_name = "Hyperswitch" [locker] host = "" diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index c71ed4496b08..9aa879a43870 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -436,6 +436,7 @@ pub struct Secrets { pub struct UserSettings { pub password_validity_in_days: u16, pub two_factor_auth_expiry_in_secs: i64, + pub totp_issuer_name: String, } #[derive(Debug, Deserialize, Clone)] diff --git a/crates/router/src/consts/user.rs b/crates/router/src/consts/user.rs index 3c6cd8b6ccd3..c7615aa4be4a 100644 --- a/crates/router/src/consts/user.rs +++ b/crates/router/src/consts/user.rs @@ -1,15 +1,17 @@ pub const MAX_NAME_LENGTH: usize = 70; pub const MAX_COMPANY_NAME_LENGTH: usize = 70; pub const BUSINESS_EMAIL: &str = "biz@hyperswitch.io"; + pub const RECOVERY_CODES_COUNT: usize = 8; pub const RECOVERY_CODE_LENGTH: usize = 8; // This is without counting the hyphen in between -pub const TOTP_ISSUER_NAME: &str = "Hyperswitch"; + /// The number of digits composing the auth code. pub const TOTP_DIGITS: usize = 6; /// Duration in seconds of a step. pub const TOTP_VALIDITY_DURATION_IN_SECONDS: u64 = 30; /// Number of totps allowed as network delay. 1 would mean one totp before current totp and one totp after are valids. pub const TOTP_TOLERANCE: u8 = 1; + pub const MAX_PASSWORD_LENGTH: usize = 70; pub const MIN_PASSWORD_LENGTH: usize = 8; diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index c259e87c93de..f4751c3a55a9 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -1635,7 +1635,11 @@ pub async fn begin_totp( })); } - let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), None)?; + let totp = tfa_utils::generate_default_totp( + user_from_db.get_email(), + None, + state.conf.user.totp_issuer_name.clone(), + )?; let secret = totp.get_secret_base32().into(); tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?; @@ -1668,7 +1672,12 @@ pub async fn reset_totp( return Err(UserErrors::TwoFactorAuthRequired.into()); } - let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), None)?; + let totp = tfa_utils::generate_default_totp( + user_from_db.get_email(), + None, + state.conf.user.totp_issuer_name.clone(), + )?; + let secret = totp.get_secret_base32().into(); tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?; @@ -1701,7 +1710,11 @@ pub async fn verify_totp( .await? .ok_or(UserErrors::InternalServerError)?; - let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), Some(user_totp_secret))?; + let totp = tfa_utils::generate_default_totp( + user_from_db.get_email(), + Some(user_totp_secret), + state.conf.user.totp_issuer_name.clone(), + )?; if totp .generate_current() @@ -1732,7 +1745,11 @@ pub async fn update_totp( .await? .ok_or(UserErrors::TotpSecretNotFound)?; - let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), Some(new_totp_secret))?; + let totp = tfa_utils::generate_default_totp( + user_from_db.get_email(), + Some(new_totp_secret), + state.conf.user.totp_issuer_name.clone(), + )?; if totp .generate_current() diff --git a/crates/router/src/utils/user/two_factor_auth.rs b/crates/router/src/utils/user/two_factor_auth.rs index a0915f3ed86e..f64eda4dc5a1 100644 --- a/crates/router/src/utils/user/two_factor_auth.rs +++ b/crates/router/src/utils/user/two_factor_auth.rs @@ -12,6 +12,7 @@ use crate::{ pub fn generate_default_totp( email: pii::Email, secret: Option>, + issuer: String, ) -> UserResult { let secret = secret .map(|sec| totp_rs::Secret::Encoded(sec.expose())) @@ -25,7 +26,7 @@ pub fn generate_default_totp( consts::user::TOTP_TOLERANCE, consts::user::TOTP_VALIDITY_DURATION_IN_SECONDS, secret, - Some(consts::user::TOTP_ISSUER_NAME.to_string()), + Some(issuer), email.expose().expose(), ) .change_context(UserErrors::InternalServerError) diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 2abe90f6086a..e46a710054e0 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -31,6 +31,7 @@ jwt_secret = "secret" [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 +totp_issuer_name = "Hyperswitch" [locker] host = "" From d242850b63173f314fb259451139464f09e0a9e9 Mon Sep 17 00:00:00 2001 From: Mani Chandra <84711804+ThisIsMani@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:40:13 +0530 Subject: [PATCH 10/10] refactor(users): Changes for Home and Signout APIs for TOTP Redis flows (#4851) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- crates/api_models/src/user.rs | 3 +++ crates/router/src/core/user.rs | 6 +++++ .../router/src/utils/user/two_factor_auth.rs | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/crates/api_models/src/user.rs b/crates/api_models/src/user.rs index ee9498cfeee4..a61b9fd7dffa 100644 --- a/crates/api_models/src/user.rs +++ b/crates/api_models/src/user.rs @@ -165,7 +165,10 @@ pub struct GetUserDetailsResponse { #[serde(skip_serializing)] pub user_id: String, pub org_id: String, + pub is_two_factor_auth_setup: bool, + pub recovery_codes_left: Option, } + #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct GetUserRoleDetailsRequest { pub email: pii::Email, diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index f4751c3a55a9..69a4cfc8a61c 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -94,6 +94,8 @@ pub async fn get_user_details( verification_days_left, role_id: user_from_token.role_id, org_id: user_from_token.org_id, + is_two_factor_auth_setup: user.get_totp_status() == TotpStatus::Set, + recovery_codes_left: user.get_recovery_codes().map(|codes| codes.len()), }, )) } @@ -328,6 +330,10 @@ pub async fn signout( state: SessionState, user_from_token: auth::UserFromToken, ) -> UserResponse<()> { + tfa_utils::delete_totp_from_redis(&state, &user_from_token.user_id).await?; + tfa_utils::delete_recovery_code_from_redis(&state, &user_from_token.user_id).await?; + tfa_utils::delete_totp_secret_from_redis(&state, &user_from_token.user_id).await?; + auth::blacklist::insert_user_in_blacklist(&state, &user_from_token.user_id).await?; auth::cookies::remove_cookie_response() } diff --git a/crates/router/src/utils/user/two_factor_auth.rs b/crates/router/src/utils/user/two_factor_auth.rs index f64eda4dc5a1..bebe58ebd866 100644 --- a/crates/router/src/utils/user/two_factor_auth.rs +++ b/crates/router/src/utils/user/two_factor_auth.rs @@ -116,3 +116,26 @@ pub async fn insert_recovery_code_in_redis(state: &SessionState, user_id: &str) .await .change_context(UserErrors::InternalServerError) } + +pub async fn delete_totp_from_redis(state: &SessionState, user_id: &str) -> UserResult<()> { + let redis_conn = super::get_redis_connection(state)?; + let key = format!("{}{}", consts::user::REDIS_TOTP_PREFIX, user_id); + redis_conn + .delete_key(&key) + .await + .change_context(UserErrors::InternalServerError) + .map(|_| ()) +} + +pub async fn delete_recovery_code_from_redis( + state: &SessionState, + user_id: &str, +) -> UserResult<()> { + let redis_conn = super::get_redis_connection(state)?; + let key = format!("{}{}", consts::user::REDIS_RECOVERY_CODE_PREFIX, user_id); + redis_conn + .delete_key(&key) + .await + .change_context(UserErrors::InternalServerError) + .map(|_| ()) +}