From d321aa1f7296932074ce86d6d0df97f312777bc7 Mon Sep 17 00:00:00 2001 From: Kartikeya Hegde Date: Thu, 22 Jun 2023 14:40:28 +0530 Subject: [PATCH] feat: fetch merchant key store only once per session (#1400) Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com> --- crates/common_utils/src/crypto.rs | 13 +- .../src/compatibility/stripe/customers.rs | 20 +-- .../compatibility/stripe/payment_intents.rs | 39 +++--- .../src/compatibility/stripe/refunds.rs | 18 ++- .../src/compatibility/stripe/setup_intents.rs | 20 +-- crates/router/src/core/admin.rs | 131 +++++++++++++----- crates/router/src/core/customers.rs | 98 +++++++------ crates/router/src/core/disputes.rs | 17 ++- .../router/src/core/disputes/transformers.rs | 11 ++ crates/router/src/core/files.rs | 4 + crates/router/src/core/files/helpers.rs | 6 + .../router/src/core/payment_methods/cards.rs | 15 +- crates/router/src/core/payments.rs | 49 ++++++- crates/router/src/core/payments/flows.rs | 1 + .../src/core/payments/flows/authorize_flow.rs | 2 + .../src/core/payments/flows/cancel_flow.rs | 2 + .../src/core/payments/flows/capture_flow.rs | 2 + .../payments/flows/complete_authorize_flow.rs | 2 + .../src/core/payments/flows/psync_flow.rs | 2 + .../src/core/payments/flows/session_flow.rs | 2 + .../src/core/payments/flows/verify_flow.rs | 2 + crates/router/src/core/payments/helpers.rs | 89 +++++++----- crates/router/src/core/payments/operations.rs | 24 +++- .../payments/operations/payment_cancel.rs | 5 + .../payments/operations/payment_capture.rs | 4 + .../operations/payment_complete_authorize.rs | 10 +- .../payments/operations/payment_confirm.rs | 11 +- .../payments/operations/payment_create.rs | 10 +- .../operations/payment_method_validate.rs | 8 +- .../payments/operations/payment_session.rs | 11 +- .../core/payments/operations/payment_start.rs | 10 +- .../payments/operations/payment_status.rs | 27 +++- .../payments/operations/payment_update.rs | 10 +- .../router/src/core/payments/transformers.rs | 2 + crates/router/src/core/refunds.rs | 45 +++++- crates/router/src/core/utils.rs | 12 ++ crates/router/src/core/webhooks.rs | 10 ++ crates/router/src/db/address.rs | 67 +++++---- crates/router/src/db/customers.rs | 29 ++-- crates/router/src/db/merchant_account.rs | 63 ++++++--- .../src/db/merchant_connector_account.rs | 53 ++++--- crates/router/src/db/merchant_key_store.rs | 34 +++-- crates/router/src/routes/admin.rs | 23 +-- crates/router/src/routes/cards_info.rs | 2 +- crates/router/src/routes/customers.rs | 18 ++- crates/router/src/routes/disputes.rs | 18 ++- crates/router/src/routes/ephemeral_key.rs | 4 +- crates/router/src/routes/files.rs | 6 +- crates/router/src/routes/mandates.rs | 8 +- crates/router/src/routes/payment_methods.rs | 25 ++-- crates/router/src/routes/payments.rs | 67 +++++---- crates/router/src/routes/refunds.rs | 23 +-- crates/router/src/routes/webhooks.rs | 11 +- .../src/scheduler/workflows/payment_sync.rs | 12 ++ crates/router/src/services/authentication.rs | 103 +++++++++++--- crates/router/src/types/domain.rs | 3 +- crates/router/src/types/domain/address.rs | 16 +-- crates/router/src/types/domain/behaviour.rs | 19 +-- crates/router/src/types/domain/customer.rs | 23 +-- .../src/types/domain/merchant_account.rs | 14 +- .../domain/merchant_connector_account.rs | 20 +-- .../src/types/domain/merchant_key_store.rs | 9 +- crates/router/src/types/domain/types.rs | 15 +- crates/router/tests/payments.rs | 24 +++- crates/router/tests/payments2.rs | 24 +++- 65 files changed, 979 insertions(+), 498 deletions(-) diff --git a/crates/common_utils/src/crypto.rs b/crates/common_utils/src/crypto.rs index 0540bfe19d..e75f78f8dd 100644 --- a/crates/common_utils/src/crypto.rs +++ b/crates/common_utils/src/crypto.rs @@ -402,14 +402,25 @@ impl> Encryptable> { impl Encryptable { /// - /// Get the inner data while consumping self + /// Get the inner data while consuming self /// + #[inline] pub fn into_inner(self) -> T { self.inner } + + /// + /// Get the reference to inner value + /// + #[inline] + pub fn get_inner(&self) -> &T { + &self.inner + } + /// /// Get the inner encrypted data while consuming self /// + #[inline] pub fn into_encrypted(self) -> Secret, EncryptionStratergy> { self.encrypted } diff --git a/crates/router/src/compatibility/stripe/customers.rs b/crates/router/src/compatibility/stripe/customers.rs index 40c55422c0..71f562ea38 100644 --- a/crates/router/src/compatibility/stripe/customers.rs +++ b/crates/router/src/compatibility/stripe/customers.rs @@ -44,8 +44,8 @@ pub async fn customer_create( state.get_ref(), &req, create_cust_req, - |state, merchant_account, req| { - customers::create_customer(&*state.store, merchant_account, req) + |state, auth, req| { + customers::create_customer(&*state.store, auth.merchant_account, auth.key_store, req) }, &auth::ApiKeyAuth, ) @@ -78,8 +78,8 @@ pub async fn customer_retrieve( state.get_ref(), &req, payload, - |state, merchant_account, req| { - customers::retrieve_customer(&*state.store, merchant_account, req) + |state, auth, req| { + customers::retrieve_customer(&*state.store, auth.merchant_account, auth.key_store, req) }, &auth::ApiKeyAuth, ) @@ -121,8 +121,8 @@ pub async fn customer_update( state.get_ref(), &req, cust_update_req, - |state, merchant_account, req| { - customers::update_customer(&*state.store, merchant_account, req) + |state, auth, req| { + customers::update_customer(&*state.store, auth.merchant_account, req, auth.key_store) }, &auth::ApiKeyAuth, ) @@ -155,7 +155,9 @@ pub async fn customer_delete( state.get_ref(), &req, payload, - customers::delete_customer, + |state, auth, req| { + customers::delete_customer(state, auth.merchant_account, req, auth.key_store) + }, &auth::ApiKeyAuth, ) .await @@ -185,7 +187,9 @@ pub async fn list_customer_payment_method_api( state.get_ref(), &req, customer_id.as_ref(), - cards::list_customer_payment_method, + |state, auth, req| { + cards::list_customer_payment_method(state, auth.merchant_account, auth.key_store, req) + }, &auth::ApiKeyAuth, ) .await diff --git a/crates/router/src/compatibility/stripe/payment_intents.rs b/crates/router/src/compatibility/stripe/payment_intents.rs index 26fa136d09..f6fdfedf47 100644 --- a/crates/router/src/compatibility/stripe/payment_intents.rs +++ b/crates/router/src/compatibility/stripe/payment_intents.rs @@ -49,10 +49,11 @@ pub async fn payment_intents_create( state.get_ref(), &req, create_payment_req, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentCreate, req, api::AuthFlow::Merchant, @@ -100,10 +101,11 @@ pub async fn payment_intents_retrieve( state.get_ref(), &req, payload, - |state, merchant_account, payload| { + |state, auth, payload| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentStatus, payload, auth_flow, @@ -160,10 +162,11 @@ pub async fn payment_intents_retrieve_with_gateway_creds( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentStatus, req, api::AuthFlow::Merchant, @@ -221,10 +224,11 @@ pub async fn payment_intents_update( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentUpdate, req, auth_flow, @@ -284,10 +288,11 @@ pub async fn payment_intents_confirm( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentConfirm, req, auth_flow, @@ -337,10 +342,11 @@ pub async fn payment_intents_capture( state.get_ref(), &req, capture_payload, - |state, merchant_account, payload| { + |state, auth, payload| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentCapture, payload, api::AuthFlow::Merchant, @@ -394,10 +400,11 @@ pub async fn payment_intents_cancel( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentCancel, req, auth_flow, @@ -437,9 +444,7 @@ pub async fn payment_intent_list( state.get_ref(), &req, payload, - |state, merchant_account, req| { - payments::list_payments(&*state.store, merchant_account, req) - }, + |state, auth, req| payments::list_payments(&*state.store, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await diff --git a/crates/router/src/compatibility/stripe/refunds.rs b/crates/router/src/compatibility/stripe/refunds.rs index b288a72485..39b7785cd1 100644 --- a/crates/router/src/compatibility/stripe/refunds.rs +++ b/crates/router/src/compatibility/stripe/refunds.rs @@ -45,7 +45,9 @@ pub async fn refund_create( state.get_ref(), &req, create_refund_req, - refunds::refund_create_core, + |state, auth, req| { + refunds::refund_create_core(state, auth.merchant_account, auth.key_store, req) + }, &auth::ApiKeyAuth, ) .await @@ -82,10 +84,11 @@ pub async fn refund_retrieve_with_gateway_creds( state.get_ref(), &req, refund_request, - |state, merchant_account, refund_request| { + |state, auth, refund_request| { refunds::refund_response_wrapper( state, - merchant_account, + auth.merchant_account, + auth.key_store, refund_request, refunds::refund_retrieve_core, ) @@ -123,10 +126,11 @@ pub async fn refund_retrieve( state.get_ref(), &req, refund_request, - |state, merchant_account, refund_request| { + |state, auth, refund_request| { refunds::refund_response_wrapper( state, - merchant_account, + auth.merchant_account, + auth.key_store, refund_request, refunds::refund_retrieve_core, ) @@ -162,8 +166,8 @@ pub async fn refund_update( state.get_ref(), &req, create_refund_update_req, - |state, merchant_account, req| { - refunds::refund_update_core(&*state.store, merchant_account, &refund_id, req) + |state, auth, req| { + refunds::refund_update_core(&*state.store, auth.merchant_account, &refund_id, req) }, &auth::ApiKeyAuth, ) diff --git a/crates/router/src/compatibility/stripe/setup_intents.rs b/crates/router/src/compatibility/stripe/setup_intents.rs index 1b9a2fb90b..941afaeb49 100644 --- a/crates/router/src/compatibility/stripe/setup_intents.rs +++ b/crates/router/src/compatibility/stripe/setup_intents.rs @@ -50,10 +50,11 @@ pub async fn setup_intents_create( state.get_ref(), &req, create_payment_req, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentCreate, req, api::AuthFlow::Merchant, @@ -101,10 +102,11 @@ pub async fn setup_intents_retrieve( state.get_ref(), &req, payload, - |state, merchant_account, payload| { + |state, auth, payload| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentStatus, payload, auth_flow, @@ -163,10 +165,11 @@ pub async fn setup_intents_update( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentUpdate, req, auth_flow, @@ -226,10 +229,11 @@ pub async fn setup_intents_confirm( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentConfirm, req, auth_flow, diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index b547f635ff..d80744c83f 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -5,7 +5,7 @@ use common_utils::{ ext_traits::ValueExt, }; use error_stack::{report, FutureExt, ResultExt}; -use masking::Secret; //PeekInterface +use masking::{PeekInterface, Secret}; use storage_models::enums; use uuid::Uuid; @@ -21,7 +21,7 @@ use crate::{ types::{ self, api, domain::{ - self, merchant_key_store, + self, types::{self as domain_types, AsyncLift}, }, storage, @@ -116,7 +116,7 @@ pub async fn create_merchant_account( .attach_printable("Invalid routing algorithm given")?; } - let key_store = merchant_key_store::MerchantKeyStore { + let key_store = domain::MerchantKeyStore { merchant_id: req.merchant_id.clone(), key: domain_types::encrypt(key.to_vec().into(), master_key) .await @@ -131,12 +131,17 @@ pub async fn create_merchant_account( .payment_response_hash_key .or(Some(generate_cryptographically_secure_random_string(64))); - db.insert_merchant_key_store(key_store) + db.insert_merchant_key_store(key_store.clone(), &master_key.to_vec().into()) .await .to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?; - let parent_merchant_id = - get_parent_merchant(db, req.sub_merchants_enabled, req.parent_merchant_id).await?; + let parent_merchant_id = get_parent_merchant( + db, + req.sub_merchants_enabled, + req.parent_merchant_id, + &key_store, + ) + .await?; let merchant_account = async { Ok(domain::MerchantAccount { @@ -174,7 +179,7 @@ pub async fn create_merchant_account( .change_context(errors::ApiErrorResponse::InternalServerError)?; let merchant_account = db - .insert_merchant(merchant_account) + .insert_merchant(merchant_account, &key_store) .await .to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?; Ok(service_api::ApplicationResponse::Json( @@ -189,8 +194,16 @@ pub async fn get_merchant_account( db: &dyn StorageInterface, req: api::MerchantId, ) -> RouterResponse { + let key_store = db + .get_merchant_key_store_by_merchant_id( + &req.merchant_id, + &db.get_master_key().to_vec().into(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + let merchant_account = db - .find_merchant_account_by_merchant_id(&req.merchant_id) + .find_merchant_account_by_merchant_id(&req.merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -206,10 +219,13 @@ pub async fn merchant_account_update( merchant_id: &String, req: api::MerchantAccountUpdate, ) -> RouterResponse { - let key = domain_types::get_merchant_enc_key(db, merchant_id.clone()) + let key_store = db + .get_merchant_key_store_by_merchant_id( + &req.merchant_id, + &db.get_master_key().to_vec().into(), + ) .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to get data from merchant key store")?; + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; if &req.merchant_id != merchant_id { Err(report!(errors::ValidationError::IncorrectValueProvided { @@ -244,11 +260,13 @@ pub async fn merchant_account_update( }) .transpose()?; + let key = key_store.key.get_inner().peek(); + let updated_merchant_account = storage::MerchantAccountUpdate::Update { merchant_name: req .merchant_name .map(masking::Secret::new) - .async_lift(|inner| domain_types::encrypt_optional(inner, &key)) + .async_lift(|inner| domain_types::encrypt_optional(inner, key)) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Unable to encrypt merchant name")?, @@ -261,7 +279,7 @@ pub async fn merchant_account_update( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Unable to convert merchant_details to a value")? .map(masking::Secret::new) - .async_lift(|inner| domain_types::encrypt_optional(inner, &key)) + .async_lift(|inner| domain_types::encrypt_optional(inner, key)) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Unable to encrypt merchant details")?, @@ -282,6 +300,7 @@ pub async fn merchant_account_update( db, req.sub_merchants_enabled, req.parent_merchant_id, + &key_store, ) .await?, enable_payment_response_hash: req.enable_payment_response_hash, @@ -296,7 +315,7 @@ pub async fn merchant_account_update( }; let response = db - .update_specific_fields_in_merchant(merchant_id, updated_merchant_account) + .update_specific_fields_in_merchant(merchant_id, updated_merchant_account, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -327,6 +346,7 @@ async fn get_parent_merchant( db: &dyn StorageInterface, sub_merchants_enabled: Option, parent_merchant: Option, + key_store: &domain::MerchantKeyStore, ) -> RouterResult> { Ok(match sub_merchants_enabled { Some(true) => { @@ -339,7 +359,7 @@ async fn get_parent_merchant( message: "If `sub_merchants_enabled` is `true`, then `parent_merchant_id` is mandatory".to_string(), }) }) - .map(|id| validate_merchant_id(db, id).change_context( + .map(|id| validate_merchant_id(db, id,key_store).change_context( errors::ApiErrorResponse::InvalidDataValue { field_name: "parent_merchant_id" } ))? .await? @@ -353,8 +373,9 @@ async fn get_parent_merchant( async fn validate_merchant_id>( db: &dyn StorageInterface, merchant_id: S, + key_store: &domain::MerchantKeyStore, ) -> RouterResult { - db.find_merchant_account_by_merchant_id(&merchant_id.into()) + db.find_merchant_account_by_merchant_id(&merchant_id.into(), key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound) } @@ -420,10 +441,10 @@ pub async fn create_payment_connector( req: api::MerchantConnectorCreate, merchant_id: &String, ) -> RouterResponse { - let key = domain_types::get_merchant_enc_key(store, merchant_id.clone()) + let key_store = store + .get_merchant_key_store_by_merchant_id(merchant_id, &store.get_master_key().to_vec().into()) .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to get key from merchant key store")?; + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; req.metadata .clone() @@ -431,7 +452,7 @@ pub async fn create_payment_connector( .transpose()?; let merchant_account = store - .find_merchant_account_by_merchant_id(merchant_id) + .find_merchant_account_by_merchant_id(merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -491,7 +512,7 @@ pub async fn create_payment_connector( field_name: "connector_account_details", }, )?, - &key, + key_store.key.peek(), ) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -511,7 +532,7 @@ pub async fn create_payment_connector( }; let mca = store - .insert_merchant_connector_account(merchant_connector_account) + .insert_merchant_connector_account(merchant_connector_account, &key_store) .await .to_duplicate_response( errors::ApiErrorResponse::DuplicateMerchantConnectorAccount { @@ -538,8 +559,16 @@ pub async fn retrieve_payment_connector( merchant_id: String, merchant_connector_id: String, ) -> RouterResponse { + let key_store = store + .get_merchant_key_store_by_merchant_id( + &merchant_id, + &store.get_master_key().to_vec().into(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + let _merchant_account = store - .find_merchant_account_by_merchant_id(&merchant_id) + .find_merchant_account_by_merchant_id(&merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -547,6 +576,7 @@ pub async fn retrieve_payment_connector( .find_by_merchant_connector_account_merchant_id_merchant_connector_id( &merchant_id, &merchant_connector_id, + &key_store, ) .await .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { @@ -560,14 +590,26 @@ pub async fn list_payment_connectors( store: &dyn StorageInterface, merchant_id: String, ) -> RouterResponse> { + let key_store = store + .get_merchant_key_store_by_merchant_id( + &merchant_id, + &store.get_master_key().to_vec().into(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + // Validate merchant account store - .find_merchant_account_by_merchant_id(&merchant_id) + .find_merchant_account_by_merchant_id(&merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; let merchant_connector_accounts = store - .find_merchant_connector_account_by_merchant_id_and_disabled_list(&merchant_id, true) + .find_merchant_connector_account_by_merchant_id_and_disabled_list( + &merchant_id, + true, + &key_store, + ) .await .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?; let mut response = vec![]; @@ -586,12 +628,13 @@ pub async fn update_payment_connector( merchant_connector_id: &str, req: api_models::admin::MerchantConnectorUpdate, ) -> RouterResponse { - let key = domain_types::get_merchant_enc_key(db, merchant_id) + let key_store = db + .get_merchant_key_store_by_merchant_id(merchant_id, &db.get_master_key().to_vec().into()) .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to get key from merchant key store")?; + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + let _merchant_account = db - .find_merchant_account_by_merchant_id(merchant_id) + .find_merchant_account_by_merchant_id(merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -599,6 +642,7 @@ pub async fn update_payment_connector( .find_by_merchant_connector_account_merchant_id_merchant_connector_id( merchant_id, merchant_connector_id, + &key_store, ) .await .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { @@ -631,7 +675,9 @@ pub async fn update_payment_connector( merchant_connector_id: None, connector_account_details: req .connector_account_details - .async_lift(|inner| domain_types::encrypt_optional(inner, &key)) + .async_lift(|inner| { + domain_types::encrypt_optional(inner, key_store.key.get_inner().peek()) + }) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while encrypting data")?, @@ -643,7 +689,7 @@ pub async fn update_payment_connector( }; let updated_mca = db - .update_merchant_connector_account(mca, payment_connector.into()) + .update_merchant_connector_account(mca, payment_connector.into(), &key_store) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable_lazy(|| { @@ -660,8 +706,13 @@ pub async fn delete_payment_connector( merchant_id: String, merchant_connector_id: String, ) -> RouterResponse { + let key_store = db + .get_merchant_key_store_by_merchant_id(&merchant_id, &db.get_master_key().to_vec().into()) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + let _merchant_account = db - .find_merchant_account_by_merchant_id(&merchant_id) + .find_merchant_account_by_merchant_id(&merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -687,9 +738,14 @@ pub async fn kv_for_merchant( merchant_id: String, enable: bool, ) -> RouterResponse { + let key_store = db + .get_merchant_key_store_by_merchant_id(&merchant_id, &db.get_master_key().to_vec().into()) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + // check if the merchant account exists let merchant_account = db - .find_merchant_account_by_merchant_id(&merchant_id) + .find_merchant_account_by_merchant_id(&merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -702,6 +758,7 @@ pub async fn kv_for_merchant( storage::MerchantAccountUpdate::StorageSchemeUpdate { storage_scheme: enums::MerchantStorageScheme::RedisKv, }, + &key_store, ) .await } @@ -711,6 +768,7 @@ pub async fn kv_for_merchant( storage::MerchantAccountUpdate::StorageSchemeUpdate { storage_scheme: enums::MerchantStorageScheme::PostgresOnly, }, + &key_store, ) .await } @@ -737,9 +795,14 @@ pub async fn check_merchant_account_kv_status( db: &dyn StorageInterface, merchant_id: String, ) -> RouterResponse { + let key_store = db + .get_merchant_key_store_by_merchant_id(&merchant_id, &db.get_master_key().to_vec().into()) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; + // check if the merchant account exists let merchant_account = db - .find_merchant_account_by_merchant_id(&merchant_id) + .find_merchant_account_by_merchant_id(&merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index cc51d9316d..eaee9c7239 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -33,17 +33,14 @@ pub const REDACTED: &str = "Redacted"; pub async fn create_customer( db: &dyn StorageInterface, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, mut customer_data: customers::CustomerRequest, ) -> RouterResponse { let customer_id = &customer_data.customer_id; let merchant_id = &merchant_account.merchant_id; customer_data.merchant_id = merchant_id.to_owned(); - let key = types::get_merchant_enc_key(db, merchant_id.clone()) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while getting encryption key")?; - + let key = key_store.key.get_inner().peek(); if let Some(addr) = &customer_data.address { let customer_address: api_models::payments::AddressDetails = addr .peek() @@ -57,36 +54,36 @@ pub async fn create_customer( country: customer_address.country, line1: customer_address .line1 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line2: customer_address .line2 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line3: customer_address .line3 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, zip: customer_address .zip - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, state: customer_address .state - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, first_name: customer_address .first_name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, last_name: customer_address .last_name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, phone_number: customer_data .phone .clone() - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, country_code: customer_data.phone_country_code.clone(), customer_id: customer_id.to_string(), @@ -101,7 +98,7 @@ pub async fn create_customer( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while encrypting address")?; - db.insert_address(address) + db.insert_address(address, &key_store) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while inserting new address")?; @@ -113,17 +110,15 @@ pub async fn create_customer( merchant_id: merchant_id.to_string(), name: customer_data .name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, email: customer_data .email - .async_lift(|inner| { - types::encrypt_optional(inner.map(|inner| inner.expose()), &key) - }) + .async_lift(|inner| types::encrypt_optional(inner.map(|inner| inner.expose()), key)) .await?, phone: customer_data .phone - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, description: customer_data.description, phone_country_code: customer_data.phone_country_code, @@ -138,11 +133,11 @@ pub async fn create_customer( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while encrypting Customer")?; - let customer = match db.insert_customer(new_customer).await { + let customer = match db.insert_customer(new_customer, &key_store).await { Ok(customer) => customer, Err(error) => { if error.current_context().is_db_unique_violation() { - db.find_customer_by_customer_id_merchant_id(customer_id, merchant_id) + db.find_customer_by_customer_id_merchant_id(customer_id, merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::InternalServerError) .attach_printable(format!( @@ -165,10 +160,15 @@ pub async fn create_customer( pub async fn retrieve_customer( db: &dyn StorageInterface, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: customers::CustomerId, ) -> RouterResponse { let response = db - .find_customer_by_customer_id_merchant_id(&req.customer_id, &merchant_account.merchant_id) + .find_customer_by_customer_id_merchant_id( + &req.customer_id, + &merchant_account.merchant_id, + &key_store, + ) .await .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; @@ -180,12 +180,17 @@ pub async fn delete_customer( state: &AppState, merchant_account: domain::MerchantAccount, req: customers::CustomerId, + key_store: domain::MerchantKeyStore, ) -> RouterResponse { let db = &state.store; - db.find_customer_by_customer_id_merchant_id(&req.customer_id, &merchant_account.merchant_id) - .await - .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; + db.find_customer_by_customer_id_merchant_id( + &req.customer_id, + &merchant_account.merchant_id, + &key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; let customer_mandates = db .find_mandate_by_merchant_id_customer_id(&merchant_account.merchant_id, &req.customer_id) @@ -235,12 +240,10 @@ pub async fn delete_customer( } }; - let key = types::get_merchant_enc_key(&**db, merchant_account.merchant_id.clone()) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while getting key for encryption")?; + let key = key_store.key.get_inner().peek(); + let redacted_encrypted_value: Encryptable> = - Encryptable::encrypt(REDACTED.to_string().into(), &key, GcmAes256) + Encryptable::encrypt(REDACTED.to_string().into(), key, GcmAes256) .await .change_context(errors::ApiErrorResponse::InternalServerError)?; @@ -263,6 +266,7 @@ pub async fn delete_customer( &req.customer_id, &merchant_account.merchant_id, update_address, + &key_store, ) .await { @@ -281,7 +285,7 @@ pub async fn delete_customer( let updated_customer = storage::CustomerUpdate::Update { name: Some(redacted_encrypted_value.clone()), email: Some( - Encryptable::encrypt(REDACTED.to_string().into(), &key, GcmAes256) + Encryptable::encrypt(REDACTED.to_string().into(), key, GcmAes256) .await .change_context(errors::ApiErrorResponse::InternalServerError)?, ), @@ -295,6 +299,7 @@ pub async fn delete_customer( req.customer_id.clone(), merchant_account.merchant_id, updated_customer, + &key_store, ) .await .change_context(errors::ApiErrorResponse::CustomerNotFound)?; @@ -314,19 +319,18 @@ pub async fn update_customer( db: &dyn StorageInterface, merchant_account: domain::MerchantAccount, update_customer: customers::CustomerRequest, + key_store: domain::MerchantKeyStore, ) -> RouterResponse { //Add this in update call if customer can be updated anywhere else db.find_customer_by_customer_id_merchant_id( &update_customer.customer_id, &merchant_account.merchant_id, + &key_store, ) .await .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; - let key = types::get_merchant_enc_key(db, merchant_account.merchant_id.clone()) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while getting key for encryption")?; + let key = key_store.key.get_inner().peek(); if let Some(addr) = &update_customer.address { let customer_address: api_models::payments::AddressDetails = addr @@ -340,36 +344,36 @@ pub async fn update_customer( country: customer_address.country, line1: customer_address .line1 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line2: customer_address .line2 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line3: customer_address .line3 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, zip: customer_address .zip - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, state: customer_address .state - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, first_name: customer_address .first_name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, last_name: customer_address .last_name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, phone_number: update_customer .phone .clone() - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, country_code: update_customer.phone_country_code.clone(), }) @@ -381,6 +385,7 @@ pub async fn update_customer( &update_customer.customer_id, &merchant_account.merchant_id, update_address, + &key_store, ) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -398,17 +403,17 @@ pub async fn update_customer( Ok(storage::CustomerUpdate::Update { name: update_customer .name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, email: update_customer .email .async_lift(|inner| { - types::encrypt_optional(inner.map(|inner| inner.expose()), &key) + types::encrypt_optional(inner.map(|inner| inner.expose()), key) }) .await?, phone: update_customer .phone - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, phone_country_code: update_customer.phone_country_code, metadata: update_customer.metadata, @@ -419,6 +424,7 @@ pub async fn update_customer( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while encrypting while updating customer")?, + &key_store, ) .await .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; diff --git a/crates/router/src/core/disputes.rs b/crates/router/src/core/disputes.rs index c90f91c927..5f1a59b548 100644 --- a/crates/router/src/core/disputes.rs +++ b/crates/router/src/core/disputes.rs @@ -63,6 +63,7 @@ pub async fn retrieve_disputes_list( pub async fn accept_dispute( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: disputes::DisputeId, ) -> RouterResponse { let db = &state.store; @@ -119,6 +120,7 @@ pub async fn accept_dispute( &payment_intent, &payment_attempt, &merchant_account, + &key_store, &dispute, ) .await?; @@ -164,6 +166,7 @@ pub async fn accept_dispute( pub async fn submit_evidence( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: dispute_models::SubmitEvidenceRequest, ) -> RouterResponse { let db = &state.store; @@ -192,8 +195,14 @@ pub async fn submit_evidence( }) }, )?; - let submit_evidence_request_data = - transformers::get_evidence_request_data(state, &merchant_account, req, &dispute).await?; + let submit_evidence_request_data = transformers::get_evidence_request_data( + state, + &merchant_account, + &key_store, + req, + &dispute, + ) + .await?; let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &dispute.payment_id, @@ -226,6 +235,7 @@ pub async fn submit_evidence( &payment_intent, &payment_attempt, &merchant_account, + &key_store, &dispute, submit_evidence_request_data, ) @@ -264,6 +274,7 @@ pub async fn submit_evidence( &payment_intent, &payment_attempt, &merchant_account, + &key_store, &dispute, ) .await?; @@ -316,6 +327,7 @@ pub async fn submit_evidence( pub async fn attach_evidence( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, attach_evidence_request: api::AttachEvidenceRequest, ) -> RouterResponse { let db = &state.store; @@ -350,6 +362,7 @@ pub async fn attach_evidence( let create_file_response = files::files_create_core( state, merchant_account, + key_store, attach_evidence_request.create_file_request, ) .await?; diff --git a/crates/router/src/core/disputes/transformers.rs b/crates/router/src/core/disputes/transformers.rs index 1e9fdc899e..6163cfab46 100644 --- a/crates/router/src/core/disputes/transformers.rs +++ b/crates/router/src/core/disputes/transformers.rs @@ -16,6 +16,7 @@ use crate::{ pub async fn get_evidence_request_data( state: &AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, evidence_request: api_models::disputes::SubmitEvidenceRequest, dispute: &storage_models::dispute::Dispute, ) -> CustomResult { @@ -24,6 +25,7 @@ pub async fn get_evidence_request_data( state, evidence_request.cancellation_policy, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -32,6 +34,7 @@ pub async fn get_evidence_request_data( state, evidence_request.customer_communication, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -40,6 +43,7 @@ pub async fn get_evidence_request_data( state, evidence_request.customer_signature, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -47,6 +51,7 @@ pub async fn get_evidence_request_data( state, evidence_request.receipt, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -55,6 +60,7 @@ pub async fn get_evidence_request_data( state, evidence_request.refund_policy, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -63,6 +69,7 @@ pub async fn get_evidence_request_data( state, evidence_request.service_documentation, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -71,6 +78,7 @@ pub async fn get_evidence_request_data( state, evidence_request.shipping_documentation, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -81,6 +89,7 @@ pub async fn get_evidence_request_data( state, evidence_request.invoice_showing_distinct_transactions, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -89,6 +98,7 @@ pub async fn get_evidence_request_data( state, evidence_request.recurring_transaction_agreement, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; @@ -97,6 +107,7 @@ pub async fn get_evidence_request_data( state, evidence_request.uncategorized_file, merchant_account, + key_store, api::FileDataRequired::NotRequired, ) .await?; diff --git a/crates/router/src/core/files.rs b/crates/router/src/core/files.rs index f2f70547a1..446ebb08a9 100644 --- a/crates/router/src/core/files.rs +++ b/crates/router/src/core/files.rs @@ -19,6 +19,7 @@ use crate::{ pub async fn files_create_core( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, create_file_request: api::CreateFileRequest, ) -> RouterResponse { helpers::validate_file_upload(state, merchant_account.clone(), create_file_request.clone()) @@ -49,6 +50,7 @@ pub async fn files_create_core( helpers::upload_and_get_provider_provider_file_id_connector_label( state, &merchant_account, + &key_store, &create_file_request, file_key.clone(), ) @@ -91,6 +93,7 @@ pub async fn files_delete_core( pub async fn files_retrieve_core( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: api::FileId, ) -> RouterResponse { let file_metadata_object = state @@ -104,6 +107,7 @@ pub async fn files_retrieve_core( state, Some(req.file_id), &merchant_account, + &key_store, api::FileDataRequired::Required, ) .await?; diff --git a/crates/router/src/core/files/helpers.rs b/crates/router/src/core/files/helpers.rs index 751dd5b047..2cd504d58d 100644 --- a/crates/router/src/core/files/helpers.rs +++ b/crates/router/src/core/files/helpers.rs @@ -154,6 +154,7 @@ pub async fn retrieve_file_from_connector( state: &AppState, file_metadata: storage_models::file::FileMetadata, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::ApiErrorResponse> { let connector = &types::Connector::foreign_try_from( file_metadata @@ -177,6 +178,7 @@ pub async fn retrieve_file_from_connector( let router_data = utils::construct_retrieve_file_router_data( state, merchant_account, + key_store, &file_metadata, connector, ) @@ -210,6 +212,7 @@ pub async fn retrieve_file_and_provider_file_id_from_file_id( state: &AppState, file_id: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, is_connector_file_data_required: api::FileDataRequired, ) -> CustomResult<(Option>, Option), errors::ApiErrorResponse> { match file_id { @@ -249,6 +252,7 @@ pub async fn retrieve_file_and_provider_file_id_from_file_id( state, file_metadata_object, merchant_account, + key_store, ) .await?, ), @@ -265,6 +269,7 @@ pub async fn retrieve_file_and_provider_file_id_from_file_id( pub async fn upload_and_get_provider_provider_file_id_connector_label( state: &AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, create_file_request: &api::CreateFileRequest, file_key: String, ) -> CustomResult< @@ -327,6 +332,7 @@ pub async fn upload_and_get_provider_provider_file_id_connector_label( &payment_intent, &payment_attempt, merchant_account, + key_store, create_file_request, &dispute.connector, file_key, diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index a5a5c0917f..959aad9941 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -765,6 +765,7 @@ pub fn get_banks( pub async fn list_payment_methods( state: &routes::AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, mut req: api::PaymentMethodListRequest, ) -> errors::RouterResponse { let db = &*state.store; @@ -780,7 +781,7 @@ pub async fn list_payment_methods( let address = payment_intent .as_ref() .async_map(|pi| async { - helpers::get_address_by_id(db, pi.shipping_address_id.clone()).await + helpers::get_address_by_id(db, pi.shipping_address_id.clone(), &key_store).await }) .await .transpose()? @@ -805,6 +806,7 @@ pub async fn list_payment_methods( .find_merchant_connector_account_by_merchant_id_and_disabled_list( &merchant_account.merchant_id, false, + &key_store, ) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -1558,13 +1560,18 @@ async fn filter_payment_mandate_based( pub async fn list_customer_payment_method( state: &routes::AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, customer_id: &str, ) -> errors::RouterResponse { let db = &*state.store; - db.find_customer_by_customer_id_merchant_id(customer_id, &merchant_account.merchant_id) - .await - .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; + db.find_customer_by_customer_id_merchant_id( + customer_id, + &merchant_account.merchant_id, + &key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; let resp = db .find_payment_method_by_customer_id_merchant_id_list( diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 4c4c904958..1a3057bb97 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -49,6 +49,7 @@ use crate::{ pub async fn payments_operation_core( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, operation: Op, req: Req, call_connector_action: CallConnectorAction, @@ -87,6 +88,7 @@ where &req, validate_result.mandate_type.to_owned(), &merchant_account, + &key_store, ) .await?; @@ -102,7 +104,7 @@ where &*state.store, &mut payment_data, customer_details, - validate_result.merchant_id, + &key_store, ) .await .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound) @@ -113,6 +115,7 @@ where state, &req, &merchant_account, + &key_store, &mut payment_data, ) .await?; @@ -125,6 +128,7 @@ where state, &customer, &merchant_account, + &key_store, &mut payment_data, ) .await?; @@ -144,6 +148,7 @@ where let router_data = call_connector_service( state, &merchant_account, + &key_store, connector, &operation, &mut payment_data, @@ -172,6 +177,7 @@ where call_multiple_connectors_service( state, &merchant_account, + &key_store, connectors, &operation, payment_data, @@ -194,6 +200,7 @@ where customer.clone(), validate_result.storage_scheme, updated_customer, + &key_store, ) .await?; } @@ -205,6 +212,7 @@ where pub async fn payments_core( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, operation: Op, req: Req, auth_flow: services::AuthFlow, @@ -230,6 +238,7 @@ where let (payment_data, req, customer) = payments_operation_core( state, merchant_account, + key_store, operation.clone(), req, call_connector_action, @@ -267,6 +276,7 @@ pub trait PaymentRedirectFlow: Sync { &self, state: &AppState, merchant_account: domain::MerchantAccount, + merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, connector_action: CallConnectorAction, ) -> RouterResponse; @@ -286,6 +296,7 @@ pub trait PaymentRedirectFlow: Sync { &self, state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, ) -> RouterResponse { metrics::REDIRECTION_TRIGGERED.add( @@ -328,7 +339,13 @@ pub trait PaymentRedirectFlow: Sync { .attach_printable("Failed to decide the response flow")?; let response = self - .call_payment_flow(state, merchant_account.clone(), req.clone(), flow_type) + .call_payment_flow( + state, + merchant_account.clone(), + key_store, + req.clone(), + flow_type, + ) .await; let payments_response = match response? { @@ -354,6 +371,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { &self, state: &AppState, merchant_account: domain::MerchantAccount, + merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, connector_action: CallConnectorAction, ) -> RouterResponse { @@ -374,6 +392,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { payments_core::( state, merchant_account, + merchant_key_store, payment_complete_authorize::CompleteAuthorize, payment_confirm_req, services::api::AuthFlow::Merchant, @@ -441,6 +460,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync { &self, state: &AppState, merchant_account: domain::MerchantAccount, + merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, connector_action: CallConnectorAction, ) -> RouterResponse { @@ -460,6 +480,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync { payments_core::( state, merchant_account, + merchant_key_store, PaymentStatus, payment_sync_req, services::api::AuthFlow::Merchant, @@ -492,6 +513,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync { pub async fn call_connector_service( state: &AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, connector: api::ConnectorData, operation: &BoxedOperation<'_, F, ApiRequest>, payment_data: &mut PaymentData, @@ -515,7 +537,13 @@ where let stime_connector = Instant::now(); let mut router_data = payment_data - .construct_router_data(state, connector.connector.id(), merchant_account, customer) + .construct_router_data( + state, + connector.connector.id(), + merchant_account, + key_store, + customer, + ) .await?; let add_access_token_result = router_data @@ -575,6 +603,7 @@ where customer.clone(), merchant_account.storage_scheme, updated_customer, + key_store, ) .await?; @@ -608,6 +637,7 @@ where pub async fn call_multiple_connectors_service( state: &AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, connectors: Vec, _operation: &Op, mut payment_data: PaymentData, @@ -633,7 +663,7 @@ where for session_connector_data in connectors.iter() { let connector_id = session_connector_data.connector.connector.id(); let router_data = payment_data - .construct_router_data(state, connector_id, merchant_account, customer) + .construct_router_data(state, connector_id, merchant_account, key_store, customer) .await?; let res = router_data.decide_flows( @@ -689,6 +719,7 @@ pub async fn call_create_connector_customer_if_required( state: &AppState, customer: &Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, ) -> RouterResult> where @@ -737,6 +768,7 @@ where state, connector.connector.id(), merchant_account, + key_store, customer, ) .await?; @@ -1237,6 +1269,7 @@ pub async fn get_connector_choice( state: &AppState, req: &Req, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, ) -> RouterResult> where @@ -1244,7 +1277,13 @@ where { let connector_choice = operation .to_domain()? - .get_connector(merchant_account, state, req, &payment_data.payment_intent) + .get_connector( + merchant_account, + state, + req, + &payment_data.payment_intent, + key_store, + ) .await?; let connector = if should_call_connector(operation, payment_data) { diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 39110a0805..c1f5af13b6 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -26,6 +26,7 @@ pub trait ConstructFlowSpecificData { state: &AppState, connector_id: &str, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, customer: &Option, ) -> RouterResult>; } diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 9d530a0a03..1c3a87355b 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -27,6 +27,7 @@ impl state: &AppState, connector_id: &str, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, customer: &Option, ) -> RouterResult< types::RouterData< @@ -40,6 +41,7 @@ impl self.clone(), connector_id, merchant_account, + key_store, customer, ) .await diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs index 6c590a9cf9..a8cf41188d 100644 --- a/crates/router/src/core/payments/flows/cancel_flow.rs +++ b/crates/router/src/core/payments/flows/cancel_flow.rs @@ -20,6 +20,7 @@ impl ConstructFlowSpecificData, ) -> RouterResult { transformers::construct_payment_router_data::( @@ -27,6 +28,7 @@ impl ConstructFlowSpecificData, ) -> RouterResult { transformers::construct_payment_router_data::( @@ -28,6 +29,7 @@ impl self.clone(), connector_id, merchant_account, + key_store, customer, ) .await 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 f78305de02..fbe3d345fc 100644 --- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs +++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs @@ -24,6 +24,7 @@ impl state: &AppState, connector_id: &str, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, customer: &Option, ) -> RouterResult< types::RouterData< @@ -40,6 +41,7 @@ impl self.clone(), connector_id, merchant_account, + key_store, customer, ) .await diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs index 4f1d877fea..40093fbed9 100644 --- a/crates/router/src/core/payments/flows/psync_flow.rs +++ b/crates/router/src/core/payments/flows/psync_flow.rs @@ -20,6 +20,7 @@ impl ConstructFlowSpecificData, ) -> RouterResult< types::RouterData, @@ -29,6 +30,7 @@ impl ConstructFlowSpecificData, ) -> RouterResult { transformers::construct_payment_router_data::( @@ -34,6 +35,7 @@ impl self.clone(), connector_id, merchant_account, + key_store, customer, ) .await diff --git a/crates/router/src/core/payments/flows/verify_flow.rs b/crates/router/src/core/payments/flows/verify_flow.rs index bd30f1e786..f269e4b921 100644 --- a/crates/router/src/core/payments/flows/verify_flow.rs +++ b/crates/router/src/core/payments/flows/verify_flow.rs @@ -21,6 +21,7 @@ impl ConstructFlowSpecificData, ) -> RouterResult { transformers::construct_payment_router_data::( @@ -28,6 +29,7 @@ impl ConstructFlowSpecificData, merchant_id: &str, customer_id: Option<&String>, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::ApiErrorResponse> { - let key = types::get_merchant_enc_key(db, merchant_id.to_string()) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while getting key for encryption")?; + let key = merchant_key_store.key.get_inner().peek(); Ok(match req_address { Some(address) => { @@ -118,49 +116,49 @@ pub async fn get_address_for_payment_request( .address .as_ref() .and_then(|value| value.line1.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line2: address .address .as_ref() .and_then(|value| value.line2.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line3: address .address .as_ref() .and_then(|value| value.line3.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, state: address .address .as_ref() .and_then(|value| value.state.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, zip: address .address .as_ref() .and_then(|value| value.zip.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, first_name: address .address .as_ref() .and_then(|value| value.first_name.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, last_name: address .address .as_ref() .and_then(|value| value.last_name.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, phone_number: address .phone .as_ref() .and_then(|value| value.number.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, country_code: address .phone @@ -172,7 +170,7 @@ pub async fn get_address_for_payment_request( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while encrypting address")?; Some( - db.update_address(id.to_owned(), address_update) + db.update_address(id.to_owned(), address_update, merchant_key_store) .await .to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?, ) @@ -190,7 +188,7 @@ pub async fn get_address_for_payment_request( .phone .as_ref() .and_then(|a| a.number.clone()) - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, country_code: address .phone @@ -203,40 +201,41 @@ pub async fn get_address_for_payment_request( country: address_details.country, line1: address_details .line1 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line2: address_details .line2 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, line3: address_details .line3 - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, id: None, state: address_details .state - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, created_at: common_utils::date_time::now(), first_name: address_details .first_name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, last_name: address_details .last_name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, modified_at: common_utils::date_time::now(), zip: address_details .zip - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, }) } .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while encrypting address while insert")?, + merchant_key_store, ) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -246,7 +245,7 @@ pub async fn get_address_for_payment_request( } } None => match address_id { - Some(id) => Some(db.find_address(id).await) + Some(id) => Some(db.find_address(id, merchant_key_store).await) .transpose() .to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?, None => None, @@ -257,10 +256,11 @@ pub async fn get_address_for_payment_request( pub async fn get_address_by_id( db: &dyn StorageInterface, address_id: Option, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::ApiErrorResponse> { match address_id { None => Ok(None), - Some(address_id) => Ok(db.find_address(&address_id).await.ok()), + Some(address_id) => Ok(db.find_address(&address_id, merchant_key_store).await.ok()), } } @@ -870,12 +870,17 @@ pub async fn get_customer_from_details( customer_id: Option, merchant_id: &str, payment_data: &mut PaymentData, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { match customer_id { None => Ok(None), Some(c_id) => { let customer = db - .find_customer_optional_by_customer_id_merchant_id(&c_id, merchant_id) + .find_customer_optional_by_customer_id_merchant_id( + &c_id, + merchant_id, + merchant_key_store, + ) .await?; payment_data.email = payment_data.email.clone().or_else(|| { customer.as_ref().and_then(|inner| { @@ -1010,6 +1015,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( payment_data: &mut PaymentData, req: Option, merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult<(BoxedOperation<'a, F, R>, Option), errors::StorageError> { let request_customer_details = req .get_required_value("customer") @@ -1022,7 +1028,11 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( let optional_customer = match customer_id { Some(customer_id) => { let customer_data = db - .find_customer_optional_by_customer_id_merchant_id(&customer_id, merchant_id) + .find_customer_optional_by_customer_id_merchant_id( + &customer_id, + merchant_id, + key_store, + ) .await?; Some(match customer_data { @@ -1033,12 +1043,12 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( | request_customer_details.phone.is_some() | request_customer_details.phone_country_code.is_some() { - let key = types::get_merchant_enc_key(db, merchant_id.to_string()).await?; + let key = key_store.key.get_inner().peek(); let customer_update = async { Ok(Update { name: request_customer_details .name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, email: request_customer_details .email @@ -1046,14 +1056,14 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( .async_lift(|inner| { types::encrypt_optional( inner.map(|inner| inner.expose()), - &key, + key, ) }) .await?, phone: request_customer_details .phone .clone() - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, phone_country_code: request_customer_details.phone_country_code, description: None, @@ -1069,6 +1079,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( customer_id, merchant_id.to_string(), customer_update, + key_store, ) .await } else { @@ -1076,26 +1087,26 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( } } None => { - let key = types::get_merchant_enc_key(db, merchant_id.to_string()).await?; let new_customer = async { + let key = key_store.key.get_inner().peek(); Ok(domain::Customer { customer_id: customer_id.to_string(), merchant_id: merchant_id.to_string(), name: request_customer_details .name - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, email: request_customer_details .email .clone() .async_lift(|inner| { - types::encrypt_optional(inner.map(|inner| inner.expose()), &key) + types::encrypt_optional(inner.map(|inner| inner.expose()), key) }) .await?, phone: request_customer_details .phone .clone() - .async_lift(|inner| types::encrypt_optional(inner, &key)) + .async_lift(|inner| types::encrypt_optional(inner, key)) .await?, phone_country_code: request_customer_details.phone_country_code.clone(), description: None, @@ -1110,15 +1121,19 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( .change_context(errors::StorageError::SerializationFailed) .attach_printable("Failed while encrypting Customer while insert")?; metrics::CUSTOMER_CREATED.add(&metrics::CONTEXT, 1, &[]); - db.insert_customer(new_customer).await + db.insert_customer(new_customer, key_store).await } }) } None => match &payment_data.payment_intent.customer_id { None => None, Some(customer_id) => db - .find_customer_optional_by_customer_id_merchant_id(customer_id, merchant_id) - .await? // if customer_id is present in payment_intent but not found in customer table then shouldn't an error be thrown ? + .find_customer_optional_by_customer_id_merchant_id( + customer_id, + merchant_id, + key_store, + ) + .await? .map(Ok), }, }; @@ -2036,6 +2051,7 @@ pub async fn get_merchant_connector_account( merchant_id: &str, connector_label: &str, creds_identifier: Option, + key_store: &domain::MerchantKeyStore, ) -> RouterResult { let db = &*state.store; match creds_identifier { @@ -2075,6 +2091,7 @@ pub async fn get_merchant_connector_account( .find_merchant_connector_account_by_merchant_id_connector_label( merchant_id, connector_label, + key_store, ) .await .map(MerchantConnectorAccountType::DbVal) diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 0a61dd8755..dc39c073a9 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -92,6 +92,7 @@ pub trait GetTracker: Send { request: &R, mandate_type: Option, merchant_account: &domain::MerchantAccount, + mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'a, F, R>, D, Option)>; } @@ -103,7 +104,7 @@ pub trait Domain: Send + Sync { db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult<(BoxedOperation<'a, F, R>, Option), errors::StorageError>; #[allow(clippy::too_many_arguments)] @@ -128,10 +129,12 @@ pub trait Domain: Send + Sync { state: &AppState, request: &R, payment_intent: &storage::payment_intent::PaymentIntent, + mechant_key_store: &domain::MerchantKeyStore, ) -> CustomResult; } #[async_trait] +#[allow(clippy::too_many_arguments)] pub trait UpdateTracker: Send { async fn update_trackers<'b>( &'b self, @@ -140,6 +143,7 @@ pub trait UpdateTracker: Send { customer: Option, storage_scheme: enums::MerchantStorageScheme, updated_customer: Option, + mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, Req>, D)> where F: 'b + Send; @@ -171,7 +175,7 @@ where db: &dyn StorageInterface, payment_data: &mut PaymentData, _request: Option, - merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsRetrieveRequest>, @@ -184,8 +188,9 @@ where helpers::get_customer_from_details( db, payment_data.payment_intent.customer_id.clone(), - merchant_id, + &merchant_key_store.merchant_id, payment_data, + merchant_key_store, ) .await?, )) @@ -197,6 +202,7 @@ where state: &AppState, _request: &api::PaymentsRetrieveRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, None).await } @@ -227,7 +233,7 @@ where db: &dyn StorageInterface, payment_data: &mut PaymentData, _request: Option, - merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsCaptureRequest>, @@ -240,8 +246,9 @@ where helpers::get_customer_from_details( db, payment_data.payment_intent.customer_id.clone(), - merchant_id, + &merchant_key_store.merchant_id, payment_data, + merchant_key_store, ) .await?, )) @@ -265,6 +272,7 @@ where state: &AppState, _request: &api::PaymentsCaptureRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, None).await } @@ -282,7 +290,7 @@ where db: &dyn StorageInterface, payment_data: &mut PaymentData, _request: Option, - merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsCancelRequest>, @@ -295,8 +303,9 @@ where helpers::get_customer_from_details( db, payment_data.payment_intent.customer_id.clone(), - merchant_id, + &merchant_key_store.merchant_id, payment_data, + merchant_key_store, ) .await?, )) @@ -321,6 +330,7 @@ where state: &AppState, _request: &api::PaymentsCancelRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, None).await } diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 0b32c0629a..fd11946561 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -36,6 +36,7 @@ impl GetTracker, api::PaymentsCancelRequest> request: &api::PaymentsCancelRequest, _mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsCancelRequest>, PaymentData, @@ -81,14 +82,17 @@ impl GetTracker, api::PaymentsCancelRequest> payment_intent.shipping_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; + let billing_address = helpers::get_address_for_payment_request( db, None, payment_intent.billing_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; @@ -170,6 +174,7 @@ impl UpdateTracker, api::PaymentsCancelRequest> for _customer: Option, storage_scheme: enums::MerchantStorageScheme, _updated_customer: Option, + _mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'b, F, api::PaymentsCancelRequest>, PaymentData, diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index 621871d326..2f6696dedb 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -37,6 +37,7 @@ impl GetTracker, api::PaymentsCaptu request: &api::PaymentsCaptureRequest, _mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsCaptureRequest>, payments::PaymentData, @@ -100,6 +101,7 @@ impl GetTracker, api::PaymentsCaptu payment_intent.shipping_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; @@ -109,6 +111,7 @@ impl GetTracker, api::PaymentsCaptu payment_intent.billing_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; @@ -178,6 +181,7 @@ impl UpdateTracker, api::PaymentsCaptureRe _customer: Option, _storage_scheme: enums::MerchantStorageScheme, _updated_customer: Option, + _mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'b, F, api::PaymentsCaptureRequest>, payments::PaymentData, 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 8a1dc78008..eb581f9cde 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -38,6 +38,7 @@ impl GetTracker, api::PaymentsRequest> for Co request: &api::PaymentsRequest, mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, PaymentData, @@ -134,6 +135,7 @@ impl GetTracker, api::PaymentsRequest> for Co payment_intent.shipping_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; let billing_address = helpers::get_address_for_payment_request( @@ -142,6 +144,7 @@ impl GetTracker, api::PaymentsRequest> for Co payment_intent.billing_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; @@ -224,7 +227,7 @@ impl Domain for CompleteAuthorize { db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsRequest>, @@ -237,7 +240,8 @@ impl Domain for CompleteAuthorize { db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -277,6 +281,7 @@ impl Domain for CompleteAuthorize { state: &AppState, request: &api::PaymentsRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _key_store: &domain::MerchantKeyStore, ) -> CustomResult { // Use a new connector in the confirm call or use the same one which was passed when // creating the payment or if none is passed then use the routing algorithm @@ -294,6 +299,7 @@ impl UpdateTracker, api::PaymentsRequest> for Comple _customer: Option, _storage_scheme: storage_enums::MerchantStorageScheme, _updated_customer: Option, + _merchant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData)> where F: 'b + Send, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 454084c1a6..c6a9ef6c0e 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -39,6 +39,7 @@ impl GetTracker, api::PaymentsRequest> for Pa request: &api::PaymentsRequest, mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, PaymentData, @@ -174,6 +175,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .customer_id .as_ref() .or(customer_details.customer_id.as_ref()), + key_store, ) .await?; let billing_address = helpers::get_address_for_payment_request( @@ -185,6 +187,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .customer_id .as_ref() .or(customer_details.customer_id.as_ref()), + key_store, ) .await?; @@ -278,7 +281,7 @@ impl Domain for PaymentConfirm { db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsRequest>, @@ -291,7 +294,8 @@ impl Domain for PaymentConfirm { db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -331,6 +335,7 @@ impl Domain for PaymentConfirm { state: &AppState, request: &api::PaymentsRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _key_store: &domain::MerchantKeyStore, ) -> CustomResult { // Use a new connector in the confirm call or use the same one which was passed when // creating the payment or if none is passed then use the routing algorithm @@ -348,6 +353,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, updated_customer: Option, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData)> where F: 'b + Send, @@ -454,6 +460,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen customer.customer_id.to_owned(), customer.merchant_id.to_owned(), updated_customer, + key_store, ) .await .change_context(errors::ApiErrorResponse::InternalServerError) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index e68eb0c485..4b9d78c3a7 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -47,6 +47,7 @@ impl GetTracker, api::PaymentsRequest> for Pa request: &api::PaymentsRequest, mandate_type: Option, merchant_account: &domain::MerchantAccount, + merchant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, PaymentData, @@ -82,6 +83,7 @@ impl GetTracker, api::PaymentsRequest> for Pa None, merchant_id, customer_details.customer_id.as_ref(), + merchant_key_store, ) .await?; @@ -91,6 +93,7 @@ impl GetTracker, api::PaymentsRequest> for Pa None, merchant_id, customer_details.customer_id.as_ref(), + merchant_key_store, ) .await?; @@ -272,7 +275,7 @@ impl Domain for PaymentCreate { db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsRequest>, @@ -285,7 +288,8 @@ impl Domain for PaymentCreate { db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -318,6 +322,7 @@ impl Domain for PaymentCreate { state: &AppState, request: &api::PaymentsRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, request.routing.clone()).await } @@ -333,6 +338,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen _customer: Option, storage_scheme: enums::MerchantStorageScheme, _updated_customer: Option, + _merchant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData)> where F: 'b + Send, diff --git a/crates/router/src/core/payments/operations/payment_method_validate.rs b/crates/router/src/core/payments/operations/payment_method_validate.rs index 15d6ba59db..ff63ed050a 100644 --- a/crates/router/src/core/payments/operations/payment_method_validate.rs +++ b/crates/router/src/core/payments/operations/payment_method_validate.rs @@ -71,6 +71,7 @@ impl GetTracker, api::VerifyRequest> for Paym request: &api::VerifyRequest, _mandate_type: Option, merchant_account: &domain::MerchantAccount, + _mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::VerifyRequest>, PaymentData, @@ -205,6 +206,7 @@ impl UpdateTracker, api::VerifyRequest> for PaymentM _customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, _updated_customer: Option, + _mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, api::VerifyRequest>, PaymentData)> where F: 'b + Send, @@ -246,7 +248,7 @@ where db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::VerifyRequest>, @@ -259,7 +261,8 @@ where db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -283,6 +286,7 @@ where state: &AppState, _request: &api::VerifyRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _mechant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, None).await } diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 9576eec59a..f96efe544e 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -39,6 +39,7 @@ impl GetTracker, api::PaymentsSessionRequest> request: &api::PaymentsSessionRequest, _mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsSessionRequest>, PaymentData, @@ -88,6 +89,7 @@ impl GetTracker, api::PaymentsSessionRequest> payment_intent.shipping_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; @@ -97,6 +99,7 @@ impl GetTracker, api::PaymentsSessionRequest> payment_intent.billing_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + key_store, ) .await?; @@ -189,6 +192,7 @@ impl UpdateTracker, api::PaymentsSessionRequest> for _customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, _updated_customer: Option, + _mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'b, F, api::PaymentsSessionRequest>, PaymentData, @@ -250,7 +254,7 @@ where db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> errors::CustomResult< ( BoxedOperation<'a, F, api::PaymentsSessionRequest>, @@ -263,7 +267,8 @@ where db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -297,6 +302,7 @@ where state: &AppState, request: &api::PaymentsSessionRequest, payment_intent: &storage::payment_intent::PaymentIntent, + key_store: &domain::MerchantKeyStore, ) -> RouterResult { let connectors = &state.conf.connectors; let db = &state.store; @@ -305,6 +311,7 @@ where .find_merchant_connector_account_by_merchant_id_and_disabled_list( &merchant_account.merchant_id, false, + key_store, ) .await .change_context(errors::ApiErrorResponse::InternalServerError) diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index 0c2fa20584..fd36baffb5 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -35,6 +35,7 @@ impl GetTracker, api::PaymentsStartRequest> f _request: &api::PaymentsStartRequest, _mandate_type: Option, merchant_account: &domain::MerchantAccount, + mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsStartRequest>, PaymentData, @@ -82,6 +83,7 @@ impl GetTracker, api::PaymentsStartRequest> f payment_intent.shipping_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + mechant_key_store, ) .await?; let billing_address = helpers::get_address_for_payment_request( @@ -90,6 +92,7 @@ impl GetTracker, api::PaymentsStartRequest> f payment_intent.billing_address_id.as_deref(), merchant_id, payment_intent.customer_id.as_ref(), + mechant_key_store, ) .await?; @@ -161,6 +164,7 @@ impl UpdateTracker, api::PaymentsStartRequest> for P _customer: Option, _storage_scheme: storage_enums::MerchantStorageScheme, _updated_customer: Option, + _mechant_key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'b, F, api::PaymentsStartRequest>, PaymentData, @@ -215,7 +219,7 @@ where db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsStartRequest>, @@ -228,7 +232,8 @@ where db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -252,6 +257,7 @@ where state: &AppState, _request: &api::PaymentsStartRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _mechant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, None).await } diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 7220ae3908..6b66c90223 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -56,7 +56,7 @@ impl Domain for PaymentStatus { db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsRequest>, @@ -69,7 +69,8 @@ impl Domain for PaymentStatus { db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -102,6 +103,7 @@ impl Domain for PaymentStatus { state: &AppState, request: &api::PaymentsRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, request.routing.clone()).await } @@ -116,6 +118,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen _customer: Option, _storage_scheme: enums::MerchantStorageScheme, _updated_customer: Option, + _key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData)> where F: 'b + Send, @@ -133,6 +136,7 @@ impl UpdateTracker, api::PaymentsRetrieveRequest> fo _customer: Option, _storage_scheme: enums::MerchantStorageScheme, _updated_customer: Option, + _key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'b, F, api::PaymentsRetrieveRequest>, PaymentData, @@ -156,6 +160,7 @@ impl GetTracker, api::PaymentsRetrieveRequest request: &api::PaymentsRetrieveRequest, _mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRetrieveRequest>, PaymentData, @@ -164,6 +169,7 @@ impl GetTracker, api::PaymentsRetrieveRequest get_tracker_for_sync( payment_id, &merchant_account.merchant_id, + key_store, &*state.store, request, self, @@ -180,6 +186,7 @@ async fn get_tracker_for_sync< >( payment_id: &api::PaymentIdType, merchant_id: &str, + mechant_key_store: &domain::MerchantKeyStore, db: &dyn StorageInterface, request: &api::PaymentsRetrieveRequest, operation: Op, @@ -211,10 +218,18 @@ async fn get_tracker_for_sync< currency = payment_attempt.currency.get_required_value("currency")?; amount = payment_attempt.amount.into(); - let shipping_address = - helpers::get_address_by_id(db, payment_intent.shipping_address_id.clone()).await?; - let billing_address = - helpers::get_address_by_id(db, payment_intent.billing_address_id.clone()).await?; + let shipping_address = helpers::get_address_by_id( + db, + payment_intent.shipping_address_id.clone(), + mechant_key_store, + ) + .await?; + let billing_address = helpers::get_address_by_id( + db, + payment_intent.billing_address_id.clone(), + mechant_key_store, + ) + .await?; let refunds = db .find_refund_by_payment_id_merchant_id(&payment_id_str, merchant_id, storage_scheme) diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 4765e6a7e3..3acae6a2fb 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -38,6 +38,7 @@ impl GetTracker, api::PaymentsRequest> for Pa request: &api::PaymentsRequest, mandate_type: Option, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, PaymentData, @@ -138,6 +139,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .customer_id .as_ref() .or(customer_details.customer_id.as_ref()), + key_store, ) .await?; let billing_address = helpers::get_address_for_payment_request( @@ -149,6 +151,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .customer_id .as_ref() .or(customer_details.customer_id.as_ref()), + key_store, ) .await?; @@ -318,7 +321,7 @@ impl Domain for PaymentUpdate { db: &dyn StorageInterface, payment_data: &mut PaymentData, request: Option, - merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult< ( BoxedOperation<'a, F, api::PaymentsRequest>, @@ -331,7 +334,8 @@ impl Domain for PaymentUpdate { db, payment_data, request, - merchant_id, + &key_store.merchant_id, + key_store, ) .await } @@ -364,6 +368,7 @@ impl Domain for PaymentUpdate { state: &AppState, request: &api::PaymentsRequest, _payment_intent: &storage::payment_intent::PaymentIntent, + _key_store: &domain::MerchantKeyStore, ) -> CustomResult { helpers::get_connector_default(state, request.routing.clone()).await } @@ -379,6 +384,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, _updated_customer: Option, + _key_store: &domain::MerchantKeyStore, ) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData)> where F: 'b + Send, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index c8cf6405a7..cc61b606e3 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -31,6 +31,7 @@ pub async fn construct_payment_router_data<'a, F, T>( payment_data: PaymentData, connector_id: &str, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, customer: &Option, ) -> RouterResult> where @@ -53,6 +54,7 @@ where merchant_account.merchant_id.as_str(), &connector_label, payment_data.creds_identifier.to_owned(), + key_store, ) .await?; diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs index 32e41ae994..e749fc2550 100644 --- a/crates/router/src/core/refunds.rs +++ b/crates/router/src/core/refunds.rs @@ -30,6 +30,7 @@ use crate::{ pub async fn refund_create_core( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: refunds::RefundRequest, ) -> RouterResponse { let db = &*state.store; @@ -100,6 +101,7 @@ pub async fn refund_create_core( validate_and_create_refund( state, &merchant_account, + &key_store, &payment_attempt, &payment_intent, amount, @@ -115,6 +117,7 @@ pub async fn trigger_refund_to_gateway( state: &AppState, refund: &storage::Refund, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, creds_identifier: Option, @@ -156,6 +159,7 @@ pub async fn trigger_refund_to_gateway( state, &routed_through, merchant_account, + key_store, (payment_attempt.amount, currency), payment_intent, payment_attempt, @@ -247,16 +251,19 @@ pub async fn trigger_refund_to_gateway( pub async fn refund_response_wrapper<'a, F, Fut, T, Req>( state: &'a AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, request: Req, f: F, ) -> RouterResponse where - F: Fn(&'a AppState, domain::MerchantAccount, Req) -> Fut, + F: Fn(&'a AppState, domain::MerchantAccount, domain::MerchantKeyStore, Req) -> Fut, Fut: futures::Future>, T: ForeignInto, { Ok(services::ApplicationResponse::Json( - f(state, merchant_account, request).await?.foreign_into(), + f(state, merchant_account, key_store, request) + .await? + .foreign_into(), )) } @@ -264,6 +271,7 @@ where pub async fn refund_retrieve_core( state: &AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, request: refunds::RefundsRetrieveRequest, ) -> RouterResult { let refund_id = request.refund_id; @@ -323,6 +331,7 @@ pub async fn refund_retrieve_core( sync_refund_with_gateway( state, &merchant_account, + &key_store, &payment_attempt, &payment_intent, &refund, @@ -356,6 +365,7 @@ fn should_call_refund(refund: &storage_models::refund::Refund, force_sync: bool) pub async fn sync_refund_with_gateway( state: &AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, refund: &storage::Refund, @@ -376,6 +386,7 @@ pub async fn sync_refund_with_gateway( state, &connector_id, merchant_account, + key_store, (payment_attempt.amount, currency), payment_intent, payment_attempt, @@ -486,9 +497,11 @@ pub async fn refund_update_core( // ********************************************** VALIDATIONS ********************************************** #[instrument(skip_all)] +#[allow(clippy::too_many_arguments)] pub async fn validate_and_create_refund( state: &AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, refund_amount: i64, @@ -610,6 +623,7 @@ pub async fn validate_and_create_refund( refund, refund_type, merchant_account, + key_store, payment_attempt, payment_intent, creds_identifier, @@ -679,11 +693,13 @@ impl ForeignFrom for api::RefundResponse { // ********************************************** PROCESS TRACKER ********************************************** #[instrument(skip_all)] +#[allow(clippy::too_many_arguments)] pub async fn schedule_refund_execution( state: &AppState, refund: storage::Refund, refund_type: api_models::refunds::RefundType, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, creds_identifier: Option, @@ -718,6 +734,7 @@ pub async fn schedule_refund_execution( state, &refund, merchant_account, + key_store, payment_attempt, payment_intent, creds_identifier, @@ -768,14 +785,23 @@ pub async fn sync_refund_with_gateway_workflow( ) })?; + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + &refund_core.merchant_id, + &state.store.get_master_key().to_vec().into(), + ) + .await?; + let merchant_account = state .store - .find_merchant_account_by_merchant_id(&refund_core.merchant_id) + .find_merchant_account_by_merchant_id(&refund_core.merchant_id, &key_store) .await?; let response = refund_retrieve_core( state, merchant_account, + key_store, refunds::RefundsRetrieveRequest { refund_id: refund_core.refund_internal_reference_id, force_sync: Some(true), @@ -839,8 +865,16 @@ pub async fn trigger_refund_execute_workflow( ) })?; + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + &refund_core.merchant_id, + &state.store.get_master_key().to_vec().into(), + ) + .await?; + let merchant_account = db - .find_merchant_account_by_merchant_id(&refund_core.merchant_id) + .find_merchant_account_by_merchant_id(&refund_core.merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -855,7 +889,7 @@ pub async fn trigger_refund_execute_workflow( match (&refund.sent_to_gateway, &refund.refund_status) { (false, enums::RefundStatus::Pending) => { let merchant_account = db - .find_merchant_account_by_merchant_id(&refund.merchant_id) + .find_merchant_account_by_merchant_id(&refund.merchant_id, &key_store) .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; @@ -883,6 +917,7 @@ pub async fn trigger_refund_execute_workflow( state, &refund, &merchant_account, + &key_store, &payment_attempt, &payment_intent, None, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 7158a4fb8e..53c97ffdb3 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -24,6 +24,7 @@ pub async fn construct_refund_router_data<'a, F>( state: &'a AppState, connector_id: &str, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, money: (i64, enums::Currency), payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, @@ -42,6 +43,7 @@ pub async fn construct_refund_router_data<'a, F>( merchant_account.merchant_id.as_str(), &connector_label, creds_identifier, + key_store, ) .await?; @@ -238,6 +240,7 @@ pub async fn construct_accept_dispute_router_data<'a>( payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, dispute: &storage::Dispute, ) -> RouterResult { let connector_id = &dispute.connector; @@ -252,6 +255,7 @@ pub async fn construct_accept_dispute_router_data<'a>( merchant_account.merchant_id.as_str(), &connector_label, None, + key_store, ) .await?; let auth_type: types::ConnectorAuthType = merchant_connector_account @@ -299,6 +303,7 @@ pub async fn construct_submit_evidence_router_data<'a>( payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, dispute: &storage::Dispute, submit_evidence_request_data: types::SubmitEvidenceRequestData, ) -> RouterResult { @@ -314,6 +319,7 @@ pub async fn construct_submit_evidence_router_data<'a>( merchant_account.merchant_id.as_str(), &connector_label, None, + key_store, ) .await?; let auth_type: types::ConnectorAuthType = merchant_connector_account @@ -359,6 +365,7 @@ pub async fn construct_upload_file_router_data<'a>( payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, create_file_request: &types::api::CreateFileRequest, connector_id: &str, file_key: String, @@ -369,6 +376,7 @@ pub async fn construct_upload_file_router_data<'a>( merchant_account.merchant_id.as_str(), &connector_label, None, + key_store, ) .await?; let auth_type: types::ConnectorAuthType = merchant_connector_account @@ -418,6 +426,7 @@ pub async fn construct_defend_dispute_router_data<'a>( payment_intent: &'a storage::PaymentIntent, payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, dispute: &storage::Dispute, ) -> RouterResult { let _db = &*state.store; @@ -433,6 +442,7 @@ pub async fn construct_defend_dispute_router_data<'a>( merchant_account.merchant_id.as_str(), &connector_label, None, + key_store, ) .await?; let auth_type: types::ConnectorAuthType = merchant_connector_account @@ -478,6 +488,7 @@ pub async fn construct_defend_dispute_router_data<'a>( pub async fn construct_retrieve_file_router_data<'a>( state: &'a AppState, merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, file_metadata: &storage_models::file::FileMetadata, connector_id: &str, ) -> RouterResult { @@ -492,6 +503,7 @@ pub async fn construct_retrieve_file_router_data<'a>( merchant_account.merchant_id.as_str(), &connector_label, None, + key_store, ) .await?; let auth_type: types::ConnectorAuthType = merchant_connector_account diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index 9b04c4e778..cdddc6b3af 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -31,6 +31,7 @@ const OUTGOING_WEBHOOK_TIMEOUT_SECS: u64 = 5; pub async fn payments_incoming_webhook_flow( state: AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, source_verified: bool, ) -> CustomResult<(), errors::ApiErrorResponse> { @@ -45,6 +46,7 @@ pub async fn payments_incoming_webhook_flow( payments::payments_core::( &state, merchant_account.clone(), + key_store, payments::operations::PaymentStatus, api::PaymentsRetrieveRequest { resource_id: id, @@ -107,6 +109,7 @@ pub async fn payments_incoming_webhook_flow( pub async fn refunds_incoming_webhook_flow( state: AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, connector_name: &str, source_verified: bool, @@ -173,6 +176,7 @@ pub async fn refunds_incoming_webhook_flow( refunds::refund_retrieve_core( &state, merchant_account.clone(), + key_store, api_models::refunds::RefundsRetrieveRequest { refund_id: refund_id.to_owned(), force_sync: Some(true), @@ -387,6 +391,7 @@ pub async fn disputes_incoming_webhook_flow( async fn bank_transfer_webhook_flow( state: AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, source_verified: bool, ) -> CustomResult<(), errors::ApiErrorResponse> { @@ -408,6 +413,7 @@ async fn bank_transfer_webhook_flow( payments::payments_core::( &state, merchant_account.to_owned(), + key_store, payments::PaymentConfirm, request, services::api::AuthFlow::Merchant, @@ -621,6 +627,7 @@ pub async fn webhooks_core( state: &AppState, req: &actix_web::HttpRequest, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, connector_name: &str, body: actix_web::web::Bytes, ) -> RouterResponse { @@ -705,6 +712,7 @@ pub async fn webhooks_core( api::WebhookFlow::Payment => payments_incoming_webhook_flow::( state.clone(), merchant_account, + key_store, webhook_details, source_verified, ) @@ -714,6 +722,7 @@ pub async fn webhooks_core( api::WebhookFlow::Refund => refunds_incoming_webhook_flow::( state.clone(), merchant_account, + key_store, webhook_details, connector_name, source_verified, @@ -737,6 +746,7 @@ pub async fn webhooks_core( api::WebhookFlow::BankTransfer => bank_transfer_webhook_flow::( state.clone(), merchant_account, + key_store, webhook_details, source_verified, ) diff --git a/crates/router/src/db/address.rs b/crates/router/src/db/address.rs index 8df8b03330..57bd8c0111 100644 --- a/crates/router/src/db/address.rs +++ b/crates/router/src/db/address.rs @@ -24,16 +24,19 @@ where &self, address_id: String, address: storage::AddressUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn insert_address( &self, address: domain::Address, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn find_address( &self, address_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn update_address_by_merchant_id_customer_id( @@ -41,6 +44,7 @@ where customer_id: &str, merchant_id: &str, address: storage::AddressUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError>; } @@ -49,6 +53,7 @@ impl AddressInterface for Store { async fn find_address( &self, address_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_read(self).await?; storage::Address::find_by_address_id(&conn, address_id) @@ -56,9 +61,8 @@ impl AddressInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|address| async { - let merchant_id = address.merchant_id.clone(); address - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -69,6 +73,7 @@ impl AddressInterface for Store { &self, address_id: String, address: storage::AddressUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; storage::Address::update_by_address_id(&conn, address_id, address.into()) @@ -76,9 +81,8 @@ impl AddressInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|address| async { - let merchant_id = address.merchant_id.clone(); address - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -88,6 +92,7 @@ impl AddressInterface for Store { async fn insert_address( &self, address: domain::Address, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; address @@ -99,9 +104,8 @@ impl AddressInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|address| async { - let merchant_id = address.merchant_id.clone(); address - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -113,6 +117,7 @@ impl AddressInterface for Store { customer_id: &str, merchant_id: &str, address: storage::AddressUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { let conn = connection::pg_connection_write(self).await?; storage::Address::update_by_merchant_id_customer_id( @@ -127,10 +132,9 @@ impl AddressInterface for Store { .async_and_then(|addresses| async { let mut output = Vec::with_capacity(addresses.len()); for address in addresses.into_iter() { - let merchant_id = address.merchant_id.clone(); output.push( address - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError)?, ) @@ -146,6 +150,7 @@ impl AddressInterface for MockDb { async fn find_address( &self, address_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { match self .addresses @@ -154,14 +159,11 @@ impl AddressInterface for MockDb { .iter() .find(|address| address.address_id == address_id) { - Some(address) => { - let merchant_id = address.merchant_id.clone(); - address - .clone() - .convert(self, &merchant_id) - .await - .change_context(errors::StorageError::DecryptionError) - } + Some(address) => address + .clone() + .convert(key_store.key.get_inner()) + .await + .change_context(errors::StorageError::DecryptionError), None => { return Err( errors::StorageError::ValueNotFound("address not found".to_string()).into(), @@ -174,6 +176,7 @@ impl AddressInterface for MockDb { &self, address_id: String, address_update: storage::AddressUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { match self .addresses @@ -187,25 +190,21 @@ impl AddressInterface for MockDb { *a = address_updated.clone(); address_updated }) { - Some(address_updated) => { - let merchant_id = address_updated.merchant_id.clone(); - address_updated - .convert(self, &merchant_id) - .await - .change_context(errors::StorageError::DecryptionError) - } - None => { - return Err(errors::StorageError::ValueNotFound( - "cannot find address to update".to_string(), - ) - .into()) - } + Some(address_updated) => address_updated + .convert(key_store.key.get_inner()) + .await + .change_context(errors::StorageError::DecryptionError), + None => Err(errors::StorageError::ValueNotFound( + "cannot find address to update".to_string(), + ) + .into()), } } async fn insert_address( &self, address_new: domain::Address, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let mut addresses = self.addresses.lock().await; @@ -213,11 +212,10 @@ impl AddressInterface for MockDb { .await .change_context(errors::StorageError::EncryptionError)?; - let merchant_id = address.merchant_id.clone(); addresses.push(address.clone()); address - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } @@ -227,6 +225,7 @@ impl AddressInterface for MockDb { customer_id: &str, merchant_id: &str, address_update: storage::AddressUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { match self .addresses @@ -244,15 +243,13 @@ impl AddressInterface for MockDb { }) { Some(address) => { let address: domain::Address = address - .convert(self, merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError)?; Ok(vec![address]) } None => { - return Err( - errors::StorageError::ValueNotFound("address not found".to_string()).into(), - ) + Err(errors::StorageError::ValueNotFound("address not found".to_string()).into()) } } } diff --git a/crates/router/src/db/customers.rs b/crates/router/src/db/customers.rs index 130c64508d..855a85e2c4 100644 --- a/crates/router/src/db/customers.rs +++ b/crates/router/src/db/customers.rs @@ -33,6 +33,7 @@ where &self, customer_id: &str, merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError>; async fn update_customer_by_customer_id_merchant_id( @@ -40,17 +41,20 @@ where customer_id: String, merchant_id: String, customer: storage::CustomerUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn find_customer_by_customer_id_merchant_id( &self, customer_id: &str, merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn insert_customer( &self, customer_data: domain::Customer, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; } @@ -60,6 +64,7 @@ impl CustomerInterface for Store { &self, customer_id: &str, merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { let conn = connection::pg_connection_read(self).await?; let maybe_customer: Option = @@ -72,7 +77,7 @@ impl CustomerInterface for Store { .map_err(Into::into) .into_report()? .async_map(|c| async { - c.convert(self, merchant_id) + c.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -95,6 +100,7 @@ impl CustomerInterface for Store { customer_id: String, merchant_id: String, customer: storage::CustomerUpdate, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; storage::Customer::update_by_customer_id_merchant_id( @@ -107,8 +113,7 @@ impl CustomerInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|c| async { - let merchant_id = c.merchant_id.clone(); - c.convert(self, &merchant_id) + c.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -119,6 +124,7 @@ impl CustomerInterface for Store { &self, customer_id: &str, merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_read(self).await?; let customer: domain::Customer = @@ -127,8 +133,7 @@ impl CustomerInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|c| async { - let merchant_id = c.merchant_id.clone(); - c.convert(self, &merchant_id) + c.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -144,6 +149,7 @@ impl CustomerInterface for Store { async fn insert_customer( &self, customer_data: domain::Customer, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; customer_data @@ -155,8 +161,7 @@ impl CustomerInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|c| async { - let merchant_id = c.merchant_id.clone(); - c.convert(self, &merchant_id) + c.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -183,6 +188,7 @@ impl CustomerInterface for MockDb { &self, customer_id: &str, merchant_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { let customers = self.customers.lock().await; let customer = customers @@ -193,8 +199,7 @@ impl CustomerInterface for MockDb { .cloned(); customer .async_map(|c| async { - let merchant_id = c.merchant_id.clone(); - c.convert(self, &merchant_id) + c.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -207,6 +212,7 @@ impl CustomerInterface for MockDb { _customer_id: String, _merchant_id: String, _customer: storage::CustomerUpdate, + _key_store: &domain::MerchantKeyStore, ) -> CustomResult { // [#172]: Implement function for `MockDb` Err(errors::StorageError::MockDbError)? @@ -216,6 +222,7 @@ impl CustomerInterface for MockDb { &self, _customer_id: &str, _merchant_id: &str, + _key_store: &domain::MerchantKeyStore, ) -> CustomResult { // [#172]: Implement function for `MockDb` Err(errors::StorageError::MockDbError)? @@ -225,6 +232,7 @@ impl CustomerInterface for MockDb { async fn insert_customer( &self, customer_data: domain::Customer, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let mut customers = self.customers.lock().await; @@ -232,11 +240,10 @@ impl CustomerInterface for MockDb { .await .change_context(errors::StorageError::EncryptionError)?; - let merchant_id = customer.merchant_id.clone(); customers.push(customer.clone()); customer - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs index b7cade2f2b..c888a5faa2 100644 --- a/crates/router/src/db/merchant_account.rs +++ b/crates/router/src/db/merchant_account.rs @@ -1,12 +1,14 @@ use common_utils::ext_traits::AsyncExt; use error_stack::{IntoReport, ResultExt}; -use super::{MockDb, Store}; +use super::{MasterKeyInterface, MockDb, Store}; #[cfg(feature = "accounts_cache")] use crate::cache::{self, ACCOUNTS_CACHE}; use crate::{ connection, core::errors::{self, CustomResult}, + db::merchant_key_store::MerchantKeyStoreInterface, + services::authentication, types::{ domain::{ self, @@ -25,29 +27,33 @@ where async fn insert_merchant( &self, merchant_account: domain::MerchantAccount, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn find_merchant_account_by_merchant_id( &self, merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn update_merchant( &self, this: domain::MerchantAccount, merchant_account: storage::MerchantAccountUpdate, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn update_specific_fields_in_merchant( &self, merchant_id: &str, merchant_account: storage::MerchantAccountUpdate, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn find_merchant_account_by_publishable_key( &self, publishable_key: &str, - ) -> CustomResult; + ) -> CustomResult; async fn delete_merchant_account_by_merchant_id( &self, @@ -60,9 +66,9 @@ impl MerchantAccountInterface for Store { async fn insert_merchant( &self, merchant_account: domain::MerchantAccount, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; - let merchant_id = merchant_account.merchant_id.clone(); merchant_account .construct_new() .await @@ -71,7 +77,7 @@ impl MerchantAccountInterface for Store { .await .map_err(Into::into) .into_report()? - .convert(self, &merchant_id) + .convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } @@ -79,6 +85,7 @@ impl MerchantAccountInterface for Store { async fn find_merchant_account_by_merchant_id( &self, merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { let fetch_func = || async { let conn = connection::pg_connection_read(self).await?; @@ -92,7 +99,7 @@ impl MerchantAccountInterface for Store { { fetch_func() .await? - .convert(self, merchant_id) + .convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } @@ -101,7 +108,7 @@ impl MerchantAccountInterface for Store { { super::cache::get_or_populate_in_memory(self, merchant_id, fetch_func, &ACCOUNTS_CACHE) .await? - .convert(self, merchant_id) + .convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } @@ -111,6 +118,7 @@ impl MerchantAccountInterface for Store { &self, this: domain::MerchantAccount, merchant_account: storage::MerchantAccountUpdate, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { let _merchant_id = this.merchant_id.clone(); let update_func = || async { @@ -123,7 +131,7 @@ impl MerchantAccountInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|item| async { - item.convert(self, &_merchant_id) + item.convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -150,6 +158,7 @@ impl MerchantAccountInterface for Store { &self, merchant_id: &str, merchant_account: storage::MerchantAccountUpdate, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { let update_func = || async { let conn = connection::pg_connection_write(self).await?; @@ -162,7 +171,7 @@ impl MerchantAccountInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|item| async { - item.convert(self, merchant_id) + item.convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -188,19 +197,26 @@ impl MerchantAccountInterface for Store { async fn find_merchant_account_by_publishable_key( &self, publishable_key: &str, - ) -> CustomResult { + ) -> CustomResult { let conn = connection::pg_connection_read(self).await?; - storage::MerchantAccount::find_by_publishable_key(&conn, publishable_key) + let merchant = storage::MerchantAccount::find_by_publishable_key(&conn, publishable_key) .await .map_err(Into::into) - .into_report() - .async_and_then(|item| async { - let merchant_id = item.merchant_id.clone(); - item.convert(self, &merchant_id) - .await - .change_context(errors::StorageError::DecryptionError) - }) - .await + .into_report()?; + let key_store = self + .get_merchant_key_store_by_merchant_id( + &merchant.merchant_id, + &self.get_master_key().to_vec().into(), + ) + .await?; + + Ok(authentication::AuthenticationData { + merchant_account: merchant + .convert(key_store.key.get_inner()) + .await + .change_context(errors::StorageError::DecryptionError)?, + key_store, + }) } async fn delete_merchant_account_by_merchant_id( @@ -238,16 +254,16 @@ impl MerchantAccountInterface for MockDb { async fn insert_merchant( &self, merchant_account: domain::MerchantAccount, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { let mut accounts = self.merchant_accounts.lock().await; let account = Conversion::convert(merchant_account) .await .change_context(errors::StorageError::EncryptionError)?; - let merchant_id = account.merchant_id.clone(); accounts.push(account.clone()); account - .convert(self, &merchant_id) + .convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } @@ -256,6 +272,7 @@ impl MerchantAccountInterface for MockDb { async fn find_merchant_account_by_merchant_id( &self, merchant_id: &str, + merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { let accounts = self.merchant_accounts.lock().await; let account: Option = accounts @@ -263,7 +280,7 @@ impl MerchantAccountInterface for MockDb { .find(|account| account.merchant_id == merchant_id) .cloned() .async_map(|a| async { - a.convert(self, merchant_id) + a.convert(merchant_key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -281,6 +298,7 @@ impl MerchantAccountInterface for MockDb { &self, _this: domain::MerchantAccount, _merchant_account: storage::MerchantAccountUpdate, + _merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { // [#172]: Implement function for `MockDb` Err(errors::StorageError::MockDbError)? @@ -290,6 +308,7 @@ impl MerchantAccountInterface for MockDb { &self, _merchant_id: &str, _merchant_account: storage::MerchantAccountUpdate, + _merchant_key_store: &domain::MerchantKeyStore, ) -> CustomResult { // [#TODO]: Implement function for `MockDb` Err(errors::StorageError::MockDbError)? @@ -298,7 +317,7 @@ impl MerchantAccountInterface for MockDb { async fn find_merchant_account_by_publishable_key( &self, _publishable_key: &str, - ) -> CustomResult { + ) -> CustomResult { // [#172]: Implement function for `MockDb` Err(errors::StorageError::MockDbError)? } diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index 0550759380..ce0e6cd510 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -1,6 +1,5 @@ use common_utils::ext_traits::{AsyncExt, ByteSliceExt, Encode}; use error_stack::{IntoReport, ResultExt}; -use storage_models::merchant_connector_account::MerchantConnectorAccountUpdateInternal; #[cfg(feature = "accounts_cache")] use super::cache; @@ -117,29 +116,34 @@ where &self, merchant_id: &str, connector_label: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn insert_merchant_connector_account( &self, t: domain::MerchantConnectorAccount, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id( &self, merchant_id: &str, merchant_connector_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn find_merchant_connector_account_by_merchant_id_and_disabled_list( &self, merchant_id: &str, get_disabled: bool, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError>; async fn update_merchant_connector_account( &self, this: domain::MerchantConnectorAccount, - merchant_connector_account: MerchantConnectorAccountUpdateInternal, + merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, + key_store: &domain::MerchantKeyStore, ) -> CustomResult; async fn delete_merchant_connector_account_by_merchant_id_merchant_connector_id( @@ -155,6 +159,7 @@ impl MerchantConnectorAccountInterface for Store { &self, merchant_id: &str, connector_label: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_read(self).await?; storage::MerchantConnectorAccount::find_by_merchant_id_connector( @@ -166,7 +171,7 @@ impl MerchantConnectorAccountInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|item| async { - item.convert(self, merchant_id) + item.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -177,6 +182,7 @@ impl MerchantConnectorAccountInterface for Store { &self, merchant_id: &str, merchant_connector_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let find_call = || async { let conn = connection::pg_connection_read(self).await?; @@ -194,7 +200,7 @@ impl MerchantConnectorAccountInterface for Store { { find_call() .await? - .convert(self, merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DeserializationFailed) } @@ -203,7 +209,7 @@ impl MerchantConnectorAccountInterface for Store { { cache::get_or_populate_redis(self, merchant_connector_id, find_call) .await? - .convert(self, merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DeserializationFailed) } @@ -212,6 +218,7 @@ impl MerchantConnectorAccountInterface for Store { async fn insert_merchant_connector_account( &self, t: domain::MerchantConnectorAccount, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; t.construct_new() @@ -222,8 +229,7 @@ impl MerchantConnectorAccountInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|item| async { - let merchant_id = item.merchant_id.clone(); - item.convert(self, &merchant_id) + item.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -234,6 +240,7 @@ impl MerchantConnectorAccountInterface for Store { &self, merchant_id: &str, get_disabled: bool, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { let conn = connection::pg_connection_read(self).await?; storage::MerchantConnectorAccount::find_by_merchant_id(&conn, merchant_id, get_disabled) @@ -244,7 +251,7 @@ impl MerchantConnectorAccountInterface for Store { let mut output = Vec::with_capacity(items.len()); for item in items.into_iter() { output.push( - item.convert(self, merchant_id) + item.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError)?, ) @@ -257,7 +264,8 @@ impl MerchantConnectorAccountInterface for Store { async fn update_merchant_connector_account( &self, this: domain::MerchantConnectorAccount, - merchant_connector_account: MerchantConnectorAccountUpdateInternal, + merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let _merchant_connector_id = this.merchant_connector_id.clone(); let update_call = || async { @@ -270,8 +278,7 @@ impl MerchantConnectorAccountInterface for Store { .map_err(Into::into) .into_report() .async_and_then(|item| async { - let merchant_id = item.merchant_id.clone(); - item.convert(self, &merchant_id) + item.convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -312,6 +319,7 @@ impl MerchantConnectorAccountInterface for MockDb { &self, merchant_id: &str, connector: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { match self .merchant_connector_accounts @@ -324,7 +332,7 @@ impl MerchantConnectorAccountInterface for MockDb { .cloned() .async_map(|account| async { account - .convert(self, merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -344,6 +352,7 @@ impl MerchantConnectorAccountInterface for MockDb { &self, merchant_id: &str, merchant_connector_id: &str, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { match self .merchant_connector_accounts @@ -357,7 +366,7 @@ impl MerchantConnectorAccountInterface for MockDb { .cloned() .async_map(|account| async { account - .convert(self, merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) @@ -376,9 +385,9 @@ impl MerchantConnectorAccountInterface for MockDb { async fn insert_merchant_connector_account( &self, t: domain::MerchantConnectorAccount, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { let mut accounts = self.merchant_connector_accounts.lock().await; - let merchant_id = t.merchant_id.clone(); let account = storage::MerchantConnectorAccount { #[allow(clippy::as_conversions)] id: accounts.len() as i32, @@ -401,7 +410,7 @@ impl MerchantConnectorAccountInterface for MockDb { }; accounts.push(account.clone()); account - .convert(self, &merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) } @@ -410,6 +419,7 @@ impl MerchantConnectorAccountInterface for MockDb { &self, merchant_id: &str, get_disabled: bool, + key_store: &domain::MerchantKeyStore, ) -> CustomResult, errors::StorageError> { let accounts = self .merchant_connector_accounts @@ -430,7 +440,7 @@ impl MerchantConnectorAccountInterface for MockDb { for account in accounts.into_iter() { output.push( account - .convert(self, merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError)?, ) @@ -440,24 +450,25 @@ impl MerchantConnectorAccountInterface for MockDb { async fn update_merchant_connector_account( &self, - merchant_connector_account: domain::MerchantConnectorAccount, - updated_merchant_connector_account: MerchantConnectorAccountUpdateInternal, + this: domain::MerchantConnectorAccount, + merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, + key_store: &domain::MerchantKeyStore, ) -> CustomResult { match self .merchant_connector_accounts .lock() .await .iter_mut() - .find(|account| Some(account.id) == merchant_connector_account.id) + .find(|account| Some(account.id) == this.id) .map(|a| { let updated = - updated_merchant_connector_account.create_merchant_connector_account(a.clone()); + merchant_connector_account.create_merchant_connector_account(a.clone()); *a = updated.clone(); updated }) .async_map(|account| async { account - .convert(self, &merchant_connector_account.merchant_id) + .convert(key_store.key.get_inner()) .await .change_context(errors::StorageError::DecryptionError) }) diff --git a/crates/router/src/db/merchant_key_store.rs b/crates/router/src/db/merchant_key_store.rs index d560e7cda3..08123894b9 100644 --- a/crates/router/src/db/merchant_key_store.rs +++ b/crates/router/src/db/merchant_key_store.rs @@ -1,4 +1,5 @@ use error_stack::{IntoReport, ResultExt}; +use masking::Secret; #[cfg(feature = "accounts_cache")] use crate::cache::ACCOUNTS_CACHE; @@ -8,8 +9,8 @@ use crate::{ db::MockDb, services::Store, types::domain::{ + self, behaviour::{Conversion, ReverseConversion}, - merchant_key_store, }, }; @@ -17,23 +18,25 @@ use crate::{ pub trait MerchantKeyStoreInterface { async fn insert_merchant_key_store( &self, - merchant_key_store: merchant_key_store::MerchantKeyStore, - ) -> CustomResult; + merchant_key_store: domain::MerchantKeyStore, + key: &Secret>, + ) -> CustomResult; async fn get_merchant_key_store_by_merchant_id( &self, merchant_id: &str, - ) -> CustomResult; + key: &Secret>, + ) -> CustomResult; } #[async_trait::async_trait] impl MerchantKeyStoreInterface for Store { async fn insert_merchant_key_store( &self, - merchant_key_store: merchant_key_store::MerchantKeyStore, - ) -> CustomResult { + merchant_key_store: domain::MerchantKeyStore, + key: &Secret>, + ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; - let merchant_id = merchant_key_store.merchant_id.clone(); merchant_key_store .construct_new() .await @@ -42,14 +45,15 @@ impl MerchantKeyStoreInterface for Store { .await .map_err(Into::into) .into_report()? - .convert(self, &merchant_id) + .convert(key) .await .change_context(errors::StorageError::DecryptionError) } async fn get_merchant_key_store_by_merchant_id( &self, merchant_id: &str, - ) -> CustomResult { + key: &Secret>, + ) -> CustomResult { let fetch_func = || async { let conn = connection::pg_connection_read(self).await?; @@ -65,7 +69,7 @@ impl MerchantKeyStoreInterface for Store { { fetch_func() .await? - .convert(self, merchant_id) + .convert(key) .await .change_context(errors::StorageError::DecryptionError) } @@ -80,7 +84,7 @@ impl MerchantKeyStoreInterface for Store { &ACCOUNTS_CACHE, ) .await? - .convert(self, merchant_id) + .convert(key) .await .change_context(errors::StorageError::DecryptionError) } @@ -91,15 +95,17 @@ impl MerchantKeyStoreInterface for Store { impl MerchantKeyStoreInterface for MockDb { async fn insert_merchant_key_store( &self, - _merchant_key_store: merchant_key_store::MerchantKeyStore, - ) -> CustomResult { + _merchant_key_store: domain::MerchantKeyStore, + _key: &Secret>, + ) -> CustomResult { // [#172]: Implement function for `MockDb` Err(errors::StorageError::MockDbError.into()) } async fn get_merchant_key_store_by_merchant_id( &self, _merchant_id: &str, - ) -> CustomResult { + _key: &Secret>, + ) -> CustomResult { // [#172]: Implement function for `MockDb` Err(errors::StorageError::MockDbError.into()) } diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs index 94e9c0f49b..dd8ca8d323 100644 --- a/crates/router/src/routes/admin.rs +++ b/crates/router/src/routes/admin.rs @@ -63,10 +63,9 @@ pub async fn retrieve_merchant_account( mid: web::Path, ) -> HttpResponse { let flow = Flow::MerchantsAccountRetrieve; - let payload = web::Json(admin::MerchantId { - merchant_id: mid.into_inner(), - }) - .into_inner(); + let merchant_id = mid.into_inner(); + let payload = web::Json(admin::MerchantId { merchant_id }).into_inner(); + api::server_wrap( flow, state.get_ref(), @@ -137,13 +136,13 @@ pub async fn delete_merchant_account( mid: web::Path, ) -> HttpResponse { let flow = Flow::MerchantsAccountDelete; - let payload = web::Json(admin::MerchantId { - merchant_id: mid.into_inner(), - }) - .into_inner(); + let mid = mid.into_inner(); + let state = state.get_ref(); + + let payload = web::Json(admin::MerchantId { merchant_id: mid }).into_inner(); api::server_wrap( flow, - state.get_ref(), + state, &req, payload, |state, _, req| merchant_account_delete(&*state.store, req.merchant_id), @@ -219,6 +218,7 @@ pub async fn payment_connector_retrieve( merchant_connector_id, }) .into_inner(); + api::server_wrap( flow, state.get_ref(), @@ -258,6 +258,7 @@ pub async fn payment_connector_list( ) -> HttpResponse { let flow = Flow::MerchantConnectorsList; let merchant_id = path.into_inner(); + api::server_wrap( flow, state.get_ref(), @@ -298,6 +299,7 @@ pub async fn payment_connector_update( ) -> HttpResponse { let flow = Flow::MerchantConnectorsUpdate; let (merchant_id, merchant_connector_id) = path.into_inner(); + api::server_wrap( flow, state.get_ref(), @@ -338,6 +340,7 @@ pub async fn payment_connector_delete( ) -> HttpResponse { let flow = Flow::MerchantConnectorsDelete; let (merchant_id, merchant_connector_id) = path.into_inner(); + let payload = web::Json(admin::MerchantConnectorId { merchant_id, merchant_connector_id, @@ -369,6 +372,7 @@ pub async fn merchant_account_toggle_kv( let flow = Flow::ConfigKeyUpdate; let payload = json_payload.into_inner(); let merchant_id = path.into_inner(); + api::server_wrap( flow, state.get_ref(), @@ -393,6 +397,7 @@ pub async fn merchant_account_kv_status( ) -> HttpResponse { let flow = Flow::ConfigKeyFetch; let merchant_id = path.into_inner(); + api::server_wrap( flow, state.get_ref(), diff --git a/crates/router/src/routes/cards_info.rs b/crates/router/src/routes/cards_info.rs index 98645b875d..9586d92689 100644 --- a/crates/router/src/routes/cards_info.rs +++ b/crates/router/src/routes/cards_info.rs @@ -46,7 +46,7 @@ pub async fn card_iin_info( state.as_ref(), &req, payload, - cards_info::retrieve_card_info, + |state, auth, req| cards_info::retrieve_card_info(state, auth.merchant_account, req), &*auth, ) .await diff --git a/crates/router/src/routes/customers.rs b/crates/router/src/routes/customers.rs index 58d06439e5..321da8a8cc 100644 --- a/crates/router/src/routes/customers.rs +++ b/crates/router/src/routes/customers.rs @@ -35,7 +35,9 @@ pub async fn customers_create( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, req| create_customer(&*state.store, merchant_account, req), + |state, auth, req| { + create_customer(&*state.store, auth.merchant_account, auth.key_store, req) + }, &auth::ApiKeyAuth, ) .await @@ -79,7 +81,9 @@ pub async fn customers_retrieve( state.get_ref(), &req, payload, - |state, merchant_account, req| retrieve_customer(&*state.store, merchant_account, req), + |state, auth, req| { + retrieve_customer(&*state.store, auth.merchant_account, auth.key_store, req) + }, &*auth, ) .await @@ -116,7 +120,9 @@ pub async fn customers_update( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, req| update_customer(&*state.store, merchant_account, req), + |state, auth, req| { + update_customer(&*state.store, auth.merchant_account, req, auth.key_store) + }, &auth::ApiKeyAuth, ) .await @@ -153,7 +159,7 @@ pub async fn customers_delete( state.get_ref(), &req, payload, - delete_customer, + |state, auth, req| delete_customer(state, auth.merchant_account, req, auth.key_store), &auth::ApiKeyAuth, ) .await @@ -175,8 +181,8 @@ pub async fn get_customer_mandates( state.get_ref(), &req, customer_id, - |state, merchant_account, req| { - crate::core::mandate::get_customer_mandates(state, merchant_account, req) + |state, auth, req| { + crate::core::mandate::get_customer_mandates(state, auth.merchant_account, req) }, &auth::ApiKeyAuth, ) diff --git a/crates/router/src/routes/disputes.rs b/crates/router/src/routes/disputes.rs index 4e291d0085..7747569e70 100644 --- a/crates/router/src/routes/disputes.rs +++ b/crates/router/src/routes/disputes.rs @@ -41,7 +41,7 @@ pub async fn retrieve_dispute( state.get_ref(), &req, dispute_id, - disputes::retrieve_dispute, + |state, auth, req| disputes::retrieve_dispute(state, auth.merchant_account, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -84,7 +84,7 @@ pub async fn retrieve_disputes_list( state.get_ref(), &req, payload, - disputes::retrieve_disputes_list, + |state, auth, req| disputes::retrieve_disputes_list(state, auth.merchant_account, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -120,7 +120,9 @@ pub async fn accept_dispute( state.get_ref(), &req, dispute_id, - disputes::accept_dispute, + |state, auth, req| { + disputes::accept_dispute(state, auth.merchant_account, auth.key_store, req) + }, auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -151,7 +153,9 @@ pub async fn submit_dispute_evidence( state.get_ref(), &req, json_payload.into_inner(), - disputes::submit_evidence, + |state, auth, req| { + disputes::submit_evidence(state, auth.merchant_account, auth.key_store, req) + }, auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -190,7 +194,9 @@ pub async fn attach_dispute_evidence( state.get_ref(), &req, attach_evidence_request, - disputes::attach_evidence, + |state, auth, req| { + disputes::attach_evidence(state, auth.merchant_account, auth.key_store, req) + }, auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -226,7 +232,7 @@ pub async fn retrieve_dispute_evidence( state.get_ref(), &req, dispute_id, - disputes::retrieve_dispute_evidence, + |state, auth, req| disputes::retrieve_dispute_evidence(state, auth.merchant_account, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await diff --git a/crates/router/src/routes/ephemeral_key.rs b/crates/router/src/routes/ephemeral_key.rs index bd5ca361bf..7d49ef444f 100644 --- a/crates/router/src/routes/ephemeral_key.rs +++ b/crates/router/src/routes/ephemeral_key.rs @@ -21,8 +21,8 @@ pub async fn ephemeral_key_create( state.get_ref(), &req, payload, - |state, merchant_account, req| { - helpers::make_ephemeral_key(state, req.customer_id, merchant_account.merchant_id) + |state, auth, req| { + helpers::make_ephemeral_key(state, req.customer_id, auth.merchant_account.merchant_id) }, &auth::ApiKeyAuth, ) diff --git a/crates/router/src/routes/files.rs b/crates/router/src/routes/files.rs index 2553022e7a..6b643f3b5c 100644 --- a/crates/router/src/routes/files.rs +++ b/crates/router/src/routes/files.rs @@ -42,7 +42,7 @@ pub async fn files_create( state.get_ref(), &req, create_file_request, - files_create_core, + |state, auth, req| files_create_core(state, auth.merchant_account, auth.key_store, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -80,7 +80,7 @@ pub async fn files_delete( state.get_ref(), &req, file_id, - files_delete_core, + |state, auth, req| files_delete_core(state, auth.merchant_account, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await @@ -118,7 +118,7 @@ pub async fn files_retrieve( state.get_ref(), &req, file_id, - files_retrieve_core, + |state, auth, req| files_retrieve_core(state, auth.merchant_account, auth.key_store, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await diff --git a/crates/router/src/routes/mandates.rs b/crates/router/src/routes/mandates.rs index a0e211f2dc..77feade91c 100644 --- a/crates/router/src/routes/mandates.rs +++ b/crates/router/src/routes/mandates.rs @@ -41,7 +41,7 @@ pub async fn get_mandate( state.get_ref(), &req, mandate_id, - mandate::get_mandate, + |state, auth, req| mandate::get_mandate(state, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await @@ -80,9 +80,7 @@ pub async fn revoke_mandate( state.get_ref(), &req, mandate_id, - |state, merchant_account, req| { - mandate::revoke_mandate(&*state.store, merchant_account, req) - }, + |state, auth, req| mandate::revoke_mandate(&*state.store, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await @@ -123,7 +121,7 @@ pub async fn retrieve_mandates_list( state.get_ref(), &req, payload, - mandate::retrieve_mandates_list, + |state, auth, req| mandate::retrieve_mandates_list(state, auth.merchant_account, req), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), ) .await diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs index 446c51837a..3132739360 100644 --- a/crates/router/src/routes/payment_methods.rs +++ b/crates/router/src/routes/payment_methods.rs @@ -35,8 +35,8 @@ pub async fn create_payment_method_api( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, req| async move { - cards::add_payment_method(state, req, &merchant_account).await + |state, auth, req| async move { + cards::add_payment_method(state, req, &auth.merchant_account).await }, &auth::ApiKeyAuth, ) @@ -85,7 +85,9 @@ pub async fn list_payment_method_api( state.get_ref(), &req, payload, - cards::list_payment_methods, + |state, auth, req| { + cards::list_payment_methods(state, auth.merchant_account, auth.key_store, req) + }, &*auth, ) .await @@ -136,8 +138,13 @@ pub async fn list_customer_payment_method_api( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, _| { - cards::list_customer_payment_method(state, merchant_account, &customer_id) + |state, auth, _| { + cards::list_customer_payment_method( + state, + auth.merchant_account, + auth.key_store, + &customer_id, + ) }, &*auth_type, ) @@ -178,7 +185,7 @@ pub async fn payment_method_retrieve_api( state.get_ref(), &req, payload, - |state, merchant_account, pm| cards::retrieve_payment_method(state, pm, merchant_account), + |state, auth, pm| cards::retrieve_payment_method(state, pm, auth.merchant_account), &auth::ApiKeyAuth, ) .await @@ -217,10 +224,10 @@ pub async fn payment_method_update_api( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, payload| { + |state, auth, payload| { cards::update_customer_payment_method( state, - merchant_account, + auth.merchant_account, payload, &payment_method_id, ) @@ -262,7 +269,7 @@ pub async fn payment_method_delete_api( state.get_ref(), &req, pm, - cards::delete_payment_method, + |state, auth, req| cards::delete_payment_method(state, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index d81cef5171..beabcb7896 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -51,11 +51,12 @@ pub async fn payments_create( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { authorize_verify_select( payments::PaymentCreate, state, - merchant_account, + auth.merchant_account, + auth.key_store, req, api::AuthFlow::Merchant, ) @@ -100,10 +101,11 @@ pub async fn payments_start( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state,auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::operations::PaymentStart, req, api::AuthFlow::Client, @@ -158,10 +160,11 @@ pub async fn payments_retrieve( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentStatus, req, api::AuthFlow::Merchant, @@ -214,10 +217,11 @@ pub async fn payments_retrieve_with_gateway_creds( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentStatus, req, api::AuthFlow::Merchant, @@ -276,11 +280,12 @@ pub async fn payments_update( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { authorize_verify_select( payments::PaymentUpdate, state, - merchant_account, + auth.merchant_account, + auth.key_store, req, auth_flow, ) @@ -341,11 +346,12 @@ pub async fn payments_confirm( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { authorize_verify_select( payments::PaymentConfirm, state, - merchant_account, + auth.merchant_account, + auth.key_store, req, auth_flow, ) @@ -392,10 +398,11 @@ pub async fn payments_capture( state.get_ref(), &req, capture_payload, - |state, merchant_account, payload| { + |state, auth, payload| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentCapture, payload, api::AuthFlow::Merchant, @@ -436,7 +443,7 @@ pub async fn payments_connector_session( state.get_ref(), &req, sessions_payload, - |state, merchant_account, payload| { + |state, auth, payload| { payments::payments_core::< api_types::Session, payment_types::PaymentsSessionResponse, @@ -445,7 +452,8 @@ pub async fn payments_connector_session( _, >( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentSession, payload, api::AuthFlow::Client, @@ -500,10 +508,11 @@ pub async fn payments_redirect_response( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::PaymentRedirectSync {}.handle_payments_redirect_response( state, - merchant_account, + auth.merchant_account, + auth.key_store, req, ) }, @@ -554,10 +563,11 @@ pub async fn payments_redirect_response_with_creds_identifier( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::PaymentRedirectSync {}.handle_payments_redirect_response( state, - merchant_account, + auth.merchant_account, + auth.key_store, req, ) }, @@ -591,10 +601,11 @@ pub async fn payments_complete_authorize( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::PaymentRedirectCompleteAuthorize {}.handle_payments_redirect_response( state, - merchant_account, + auth.merchant_account, + auth.key_store, req, ) }, @@ -638,10 +649,11 @@ pub async fn payments_cancel( state.get_ref(), &req, payload, - |state, merchant_account, req| { + |state, auth, req| { payments::payments_core::( state, - merchant_account, + auth.merchant_account, + auth.key_store, payments::PaymentCancel, req, api::AuthFlow::Merchant, @@ -693,9 +705,7 @@ pub async fn payments_list( state.get_ref(), &req, payload, - |state, merchant_account, req| { - payments::list_payments(&*state.store, merchant_account, req) - }, + |state, auth, req| payments::list_payments(&*state.store, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await @@ -705,6 +715,7 @@ async fn authorize_verify_select( operation: Op, state: &app::AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, req: api_models::payments::PaymentsRequest, auth_flow: api::AuthFlow, ) -> app::core::errors::RouterResponse @@ -731,6 +742,7 @@ where >( state, merchant_account, + key_store, operation, req, auth_flow, @@ -742,6 +754,7 @@ where payments::payments_core::( state, merchant_account, + key_store, operation, req, auth_flow, diff --git a/crates/router/src/routes/refunds.rs b/crates/router/src/routes/refunds.rs index ae13ff36fd..57ac968f54 100644 --- a/crates/router/src/routes/refunds.rs +++ b/crates/router/src/routes/refunds.rs @@ -36,7 +36,7 @@ pub async fn refunds_create( state.get_ref(), &req, json_payload.into_inner(), - refund_create_core, + |state, auth, req| refund_create_core(state, auth.merchant_account, auth.key_store, req), &auth::ApiKeyAuth, ) .await @@ -79,10 +79,11 @@ pub async fn refunds_retrieve( state.get_ref(), &req, refund_request, - |state, merchant_account, refund_request| { + |state, auth, refund_request| { refund_response_wrapper( state, - merchant_account, + auth.merchant_account, + auth.key_store, refund_request, refund_retrieve_core, ) @@ -119,8 +120,14 @@ pub async fn refunds_retrieve_with_body( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, req| { - refund_response_wrapper(state, merchant_account, req, refund_retrieve_core) + |state, auth, req| { + refund_response_wrapper( + state, + auth.merchant_account, + auth.key_store, + req, + refund_retrieve_core, + ) }, &auth::ApiKeyAuth, ) @@ -160,8 +167,8 @@ pub async fn refunds_update( state.get_ref(), &req, json_payload.into_inner(), - |state, merchant_account, req| { - refund_update_core(&*state.store, merchant_account, &refund_id, req) + |state, auth, req| { + refund_update_core(&*state.store, auth.merchant_account, &refund_id, req) }, &auth::ApiKeyAuth, ) @@ -204,7 +211,7 @@ pub async fn refunds_list( state.get_ref(), &req, payload.into_inner(), - |state, merchant_account, req| refund_list(&*state.store, merchant_account, req), + |state, auth, req| refund_list(&*state.store, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await diff --git a/crates/router/src/routes/webhooks.rs b/crates/router/src/routes/webhooks.rs index e6c8801a40..722b627c83 100644 --- a/crates/router/src/routes/webhooks.rs +++ b/crates/router/src/routes/webhooks.rs @@ -23,8 +23,15 @@ pub async fn receive_incoming_webhook( state.get_ref(), &req, body, - |state, merchant_account, body| { - webhooks::webhooks_core::(state, &req, merchant_account, &connector_name, body) + |state, auth, body| { + webhooks::webhooks_core::( + state, + &req, + auth.merchant_account, + auth.key_store, + &connector_name, + body, + ) }, &auth::MerchantIdAuth(merchant_id), ) diff --git a/crates/router/src/scheduler/workflows/payment_sync.rs b/crates/router/src/scheduler/workflows/payment_sync.rs index d0e70c3d58..b14cd8bc1b 100644 --- a/crates/router/src/scheduler/workflows/payment_sync.rs +++ b/crates/router/src/scheduler/workflows/payment_sync.rs @@ -27,18 +27,30 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { .clone() .parse_value("PaymentsRetrieveRequest")?; + let key_store = db + .get_merchant_key_store_by_merchant_id( + tracking_data + .merchant_id + .as_ref() + .get_required_value("merchant_id")?, + &db.get_master_key().to_vec().into(), + ) + .await?; + let merchant_account = db .find_merchant_account_by_merchant_id( tracking_data .merchant_id .as_ref() .get_required_value("merchant_id")?, + &key_store, ) .await?; let (payment_data, _, _) = payment_flows::payments_operation_core::( state, merchant_account.clone(), + key_store, operations::PaymentStatus, tracking_data.clone(), payment_flows::CallConnectorAction::Trigger, diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index d6e9350e0f..5744d1f899 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -21,6 +21,11 @@ use crate::{ utils::OptionExt, }; +pub struct AuthenticationData { + pub merchant_account: domain::MerchantAccount, + pub key_store: domain::MerchantKeyStore, +} + pub trait AuthInfo { fn get_merchant_id(&self) -> Option<&str>; } @@ -31,9 +36,9 @@ impl AuthInfo for () { } } -impl AuthInfo for domain::MerchantAccount { +impl AuthInfo for AuthenticationData { fn get_merchant_id(&self) -> Option<&str> { - Some(&self.merchant_id) + Some(&self.merchant_account.merchant_id) } } @@ -70,7 +75,7 @@ where } #[async_trait] -impl AuthenticateAndFetch for ApiKeyAuth +impl AuthenticateAndFetch for ApiKeyAuth where A: AppStateInfo + Sync, { @@ -78,7 +83,7 @@ where &self, request_headers: &HeaderMap, state: &A, - ) -> RouterResult { + ) -> RouterResult { let api_key = get_api_key(request_headers) .change_context(errors::ApiErrorResponse::Unauthorized)? .trim(); @@ -118,11 +123,26 @@ where .attach_printable("API key has expired"); } - state + let key_store = state .store() - .find_merchant_account_by_merchant_id(&stored_api_key.merchant_id) + .get_merchant_key_store_by_merchant_id( + &stored_api_key.merchant_id, + &state.store().get_master_key().to_vec().into(), + ) .await - .to_not_found_response(errors::ApiErrorResponse::Unauthorized) + .change_context(errors::ApiErrorResponse::Unauthorized) + .attach_printable("Failed to fetch merchant key store for the merchant id")?; + + let merchant = state + .store() + .find_merchant_account_by_merchant_id(&stored_api_key.merchant_id, &key_store) + .await + .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?; + + Ok(AuthenticationData { + merchant_account: merchant, + key_store, + }) } } @@ -188,7 +208,7 @@ where pub struct MerchantIdAuth(pub String); #[async_trait] -impl AuthenticateAndFetch for MerchantIdAuth +impl AuthenticateAndFetch for MerchantIdAuth where A: AppStateInfo + Sync, { @@ -196,10 +216,26 @@ where &self, _request_headers: &HeaderMap, state: &A, - ) -> RouterResult { - state + ) -> RouterResult { + let key_store = state .store() - .find_merchant_account_by_merchant_id(self.0.as_ref()) + .get_merchant_key_store_by_merchant_id( + self.0.as_ref(), + &state.store().get_master_key().to_vec().into(), + ) + .await + .map_err(|e| { + if e.current_context().is_db_not_found() { + e.change_context(errors::ApiErrorResponse::Unauthorized) + } else { + e.change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to fetch merchant key store for the merchant id") + } + })?; + + let merchant = state + .store() + .find_merchant_account_by_merchant_id(self.0.as_ref(), &key_store) .await .map_err(|e| { if e.current_context().is_db_not_found() { @@ -207,7 +243,12 @@ where } else { e.change_context(errors::ApiErrorResponse::InternalServerError) } - }) + })?; + + Ok(AuthenticationData { + merchant_account: merchant, + key_store, + }) } } @@ -215,7 +256,7 @@ where pub struct PublishableKeyAuth; #[async_trait] -impl AuthenticateAndFetch for PublishableKeyAuth +impl AuthenticateAndFetch for PublishableKeyAuth where A: AppStateInfo + Sync, { @@ -223,9 +264,10 @@ where &self, request_headers: &HeaderMap, state: &A, - ) -> RouterResult { + ) -> RouterResult { let publishable_key = get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?; + state .store() .find_merchant_account_by_publishable_key(publishable_key) @@ -273,7 +315,7 @@ struct JwtAuthPayloadFetchMerchantAccount { } #[async_trait] -impl AuthenticateAndFetch for JWTAuth +impl AuthenticateAndFetch for JWTAuth where A: AppStateInfo + Sync, { @@ -281,15 +323,30 @@ where &self, request_headers: &HeaderMap, state: &A, - ) -> RouterResult { + ) -> RouterResult { let mut token = get_jwt(request_headers)?; token = strip_jwt_token(token)?; let payload = decode_jwt::(token, state).await?; - state + let key_store = state .store() - .find_merchant_account_by_merchant_id(&payload.merchant_id) + .get_merchant_key_store_by_merchant_id( + &payload.merchant_id, + &state.store().get_master_key().to_vec().into(), + ) .await .change_context(errors::ApiErrorResponse::InvalidJwtToken) + .attach_printable("Failed to fetch merchant key store for the merchant id")?; + + let merchant = state + .store() + .find_merchant_account_by_merchant_id(&payload.merchant_id, &key_store) + .await + .change_context(errors::ApiErrorResponse::InvalidJwtToken)?; + + Ok(AuthenticationData { + merchant_account: merchant, + key_store, + }) } } @@ -318,7 +375,7 @@ impl ClientSecretFetch for api_models::cards_info::CardsInfoRequest { pub fn get_auth_type_and_flow( headers: &HeaderMap, ) -> RouterResult<( - Box>, + Box>, api::AuthFlow, )> { let api_key = get_api_key(headers)?; @@ -333,13 +390,13 @@ pub fn check_client_secret_and_get_auth( headers: &HeaderMap, payload: &impl ClientSecretFetch, ) -> RouterResult<( - Box>, + Box>, api::AuthFlow, )> where T: AppStateInfo, - ApiKeyAuth: AuthenticateAndFetch, - PublishableKeyAuth: AuthenticateAndFetch, + ApiKeyAuth: AuthenticateAndFetch, + PublishableKeyAuth: AuthenticateAndFetch, { let api_key = get_api_key(headers)?; @@ -367,7 +424,7 @@ pub async fn is_ephemeral_auth( headers: &HeaderMap, db: &dyn StorageInterface, customer_id: &str, -) -> RouterResult>> { +) -> RouterResult>> { let api_key = get_api_key(headers)?; if !api_key.starts_with("epk") { diff --git a/crates/router/src/types/domain.rs b/crates/router/src/types/domain.rs index 2c9b13d8a3..44123850d4 100644 --- a/crates/router/src/types/domain.rs +++ b/crates/router/src/types/domain.rs @@ -3,10 +3,11 @@ pub mod behaviour; mod customer; mod merchant_account; mod merchant_connector_account; -pub mod merchant_key_store; +mod merchant_key_store; pub mod types; pub use address::*; pub use customer::*; pub use merchant_account::*; pub use merchant_connector_account::*; +pub use merchant_key_store::*; diff --git a/crates/router/src/types/domain/address.rs b/crates/router/src/types/domain/address.rs index 5ecbafda5d..d12797df19 100644 --- a/crates/router/src/types/domain/address.rs +++ b/crates/router/src/types/domain/address.rs @@ -1,10 +1,10 @@ use async_trait::async_trait; use common_utils::{ - crypto::{self}, - date_time, + crypto, date_time, errors::{CustomResult, ValidationError}, }; use error_stack::ResultExt; +use masking::{PeekInterface, Secret}; use storage_models::{address::AddressUpdateInternal, encryption::Encryption, enums}; use time::{OffsetDateTime, PrimitiveDateTime}; @@ -12,7 +12,6 @@ use super::{ behaviour, types::{self, AsyncLift}, }; -use crate::db::StorageInterface; #[derive(Clone, Debug, serde::Serialize)] pub struct Address { @@ -72,17 +71,10 @@ impl behaviour::Conversion for Address { async fn convert_back( other: Self::DstType, - db: &dyn StorageInterface, - merchant_id: &str, + key: &Secret>, ) -> CustomResult { - let key = types::get_merchant_enc_key(db, merchant_id) - .await - .change_context(ValidationError::InvalidValue { - message: "Failed while getting key from key store".to_string(), - })?; - async { - let inner_decrypt = |inner| types::decrypt(inner, &key); + let inner_decrypt = |inner| types::decrypt(inner, key.peek()); Ok(Self { id: Some(other.id), address_id: other.address_id, diff --git a/crates/router/src/types/domain/behaviour.rs b/crates/router/src/types/domain/behaviour.rs index 2f95fe1611..db7159fad5 100644 --- a/crates/router/src/types/domain/behaviour.rs +++ b/crates/router/src/types/domain/behaviour.rs @@ -1,6 +1,6 @@ use common_utils::errors::{CustomResult, ValidationError}; -use crate::db::StorageInterface; +use crate::pii::Secret; /// Trait for converting domain types to storage models #[async_trait::async_trait] @@ -11,8 +11,7 @@ pub trait Conversion { async fn convert_back( item: Self::DstType, - db: &dyn StorageInterface, - merchant_id: &str, + key: &Secret>, ) -> CustomResult where Self: Sized; @@ -22,20 +21,12 @@ pub trait Conversion { #[async_trait::async_trait] pub trait ReverseConversion { - async fn convert( - self, - db: &dyn StorageInterface, - merchant_id: &str, - ) -> CustomResult; + async fn convert(self, key: &Secret>) -> CustomResult; } #[async_trait::async_trait] impl> ReverseConversion for T { - async fn convert( - self, - db: &dyn StorageInterface, - merchant_id: &str, - ) -> CustomResult { - U::convert_back(self, db, merchant_id).await + async fn convert(self, key: &Secret>) -> CustomResult { + U::convert_back(self, key).await } } diff --git a/crates/router/src/types/domain/customer.rs b/crates/router/src/types/domain/customer.rs index 03c5c535c2..f14fc65d28 100644 --- a/crates/router/src/types/domain/customer.rs +++ b/crates/router/src/types/domain/customer.rs @@ -1,16 +1,11 @@ -use common_utils::{ - crypto::{self}, - date_time, pii, -}; +use common_utils::{crypto, date_time, pii}; use error_stack::ResultExt; +use masking::{PeekInterface, Secret}; use storage_models::{customers::CustomerUpdateInternal, encryption::Encryption}; use time::PrimitiveDateTime; use super::types::{self, AsyncLift}; -use crate::{ - db::StorageInterface, - errors::{CustomResult, ValidationError}, -}; +use crate::errors::{CustomResult, ValidationError}; #[derive(Clone, Debug)] pub struct Customer { @@ -53,20 +48,14 @@ impl super::behaviour::Conversion for Customer { async fn convert_back( item: Self::DstType, - db: &dyn StorageInterface, - merchant_id: &str, + key: &Secret>, ) -> CustomResult where Self: Sized, { - let key = types::get_merchant_enc_key(db, merchant_id) - .await - .change_context(ValidationError::InvalidValue { - message: "Failed while getting key from key store".to_string(), - })?; async { - let inner_decrypt = |inner| types::decrypt(inner, &key); - let inner_decrypt_email = |inner| types::decrypt(inner, &key); + let inner_decrypt = |inner| types::decrypt(inner, key.peek()); + let inner_decrypt_email = |inner| types::decrypt(inner, key.peek()); Ok(Self { id: Some(item.id), customer_id: item.customer_id, diff --git a/crates/router/src/types/domain/merchant_account.rs b/crates/router/src/types/domain/merchant_account.rs index 83ef523767..91df5b34b7 100644 --- a/crates/router/src/types/domain/merchant_account.rs +++ b/crates/router/src/types/domain/merchant_account.rs @@ -3,12 +3,12 @@ use common_utils::{ date_time, pii, }; use error_stack::ResultExt; +use masking::{PeekInterface, Secret}; use storage_models::{ encryption::Encryption, enums, merchant_account::MerchantAccountUpdateInternal, }; use crate::{ - db::StorageInterface, errors::{CustomResult, ValidationError}, types::domain::types::{self, AsyncLift}, }; @@ -147,17 +147,11 @@ impl super::behaviour::Conversion for MerchantAccount { async fn convert_back( item: Self::DstType, - db: &dyn StorageInterface, - merchant_id: &str, + key: &Secret>, ) -> CustomResult where Self: Sized, { - let key = types::get_merchant_enc_key(db, merchant_id.to_owned()) - .await - .change_context(ValidationError::InvalidValue { - message: "Failed while getting key from key store".to_string(), - })?; async { Ok(Self { id: Some(item.id), @@ -168,11 +162,11 @@ impl super::behaviour::Conversion for MerchantAccount { redirect_to_merchant_with_http_post: item.redirect_to_merchant_with_http_post, merchant_name: item .merchant_name - .async_lift(|inner| types::decrypt(inner, &key)) + .async_lift(|inner| types::decrypt(inner, key.peek())) .await?, merchant_details: item .merchant_details - .async_lift(|inner| types::decrypt(inner, &key)) + .async_lift(|inner| types::decrypt(inner, key.peek())) .await?, webhook_details: item.webhook_details, sub_merchants_enabled: item.sub_merchants_enabled, diff --git a/crates/router/src/types/domain/merchant_connector_account.rs b/crates/router/src/types/domain/merchant_connector_account.rs index 9e97b58795..3838112061 100644 --- a/crates/router/src/types/domain/merchant_connector_account.rs +++ b/crates/router/src/types/domain/merchant_connector_account.rs @@ -5,18 +5,13 @@ use common_utils::{ pii, }; use error_stack::ResultExt; -use masking::Secret; +use masking::{PeekInterface, Secret}; use storage_models::{ encryption::Encryption, enums, merchant_connector_account::MerchantConnectorAccountUpdateInternal, }; -use super::{ - behaviour, - types::{self, TypeEncryption}, -}; -use crate::db::StorageInterface; - +use super::{behaviour, types::TypeEncryption}; #[derive(Clone, Debug)] pub struct MerchantConnectorAccount { pub id: Option, @@ -87,22 +82,15 @@ impl behaviour::Conversion for MerchantConnectorAccount { async fn convert_back( other: Self::DstType, - db: &dyn StorageInterface, - merchant_id: &str, + key: &Secret>, ) -> CustomResult { - let key = types::get_merchant_enc_key(db, merchant_id) - .await - .change_context(ValidationError::InvalidValue { - message: "Error while getting key from keystore".to_string(), - })?; - Ok(Self { id: Some(other.id), merchant_id: other.merchant_id, connector_name: other.connector_name, connector_account_details: Encryptable::decrypt( other.connector_account_details, - &key, + key.peek(), GcmAes256, ) .await diff --git a/crates/router/src/types/domain/merchant_key_store.rs b/crates/router/src/types/domain/merchant_key_store.rs index 6917261e97..8661b2609b 100644 --- a/crates/router/src/types/domain/merchant_key_store.rs +++ b/crates/router/src/types/domain/merchant_key_store.rs @@ -3,11 +3,10 @@ use common_utils::{ custom_serde, date_time, }; use error_stack::ResultExt; -use masking::Secret; +use masking::{PeekInterface, Secret}; use time::PrimitiveDateTime; use crate::{ - db::StorageInterface, errors::{CustomResult, ValidationError}, types::domain::types::TypeEncryption, }; @@ -34,15 +33,13 @@ impl super::behaviour::Conversion for MerchantKeyStore { async fn convert_back( item: Self::DstType, - db: &dyn StorageInterface, - _merchant_id: &str, + key: &Secret>, ) -> CustomResult where Self: Sized, { - let key = &db.get_master_key(); Ok(Self { - key: Encryptable::decrypt(item.key, key, GcmAes256) + key: Encryptable::decrypt(item.key, key.peek(), GcmAes256) .await .change_context(ValidationError::InvalidValue { message: "Failed while decrypting customer data".to_string(), diff --git a/crates/router/src/types/domain/types.rs b/crates/router/src/types/domain/types.rs index 82dd32bcfd..d144717e29 100644 --- a/crates/router/src/types/domain/types.rs +++ b/crates/router/src/types/domain/types.rs @@ -5,7 +5,7 @@ use common_utils::{ ext_traits::AsyncExt, }; use error_stack::{IntoReport, ResultExt}; -use masking::{ExposeInterface, PeekInterface, Secret}; +use masking::{PeekInterface, Secret}; use router_env::{instrument, tracing}; use storage_models::encryption::Encryption; @@ -134,19 +134,6 @@ impl< } } -pub async fn get_merchant_enc_key( - db: &dyn crate::db::StorageInterface, - merchant_id: impl AsRef, -) -> CustomResult, crate::core::errors::StorageError> { - let merchant_id = merchant_id.as_ref(); - let key = db - .get_merchant_key_store_by_merchant_id(merchant_id) - .await? - .key - .into_inner(); - Ok(key.expose()) -} - pub trait Lift { type SelfWrapper; type OtherWrapper; diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index 6a9b7b0d94..45df6c2e25 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -277,9 +277,18 @@ async fn payments_create_core() { let tx: oneshot::Sender<()> = oneshot::channel().0; let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest, tx).await; + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + "juspay_merchant", + &state.store.get_master_key().to_vec().into(), + ) + .await + .unwrap(); + let merchant_account = state .store - .find_merchant_account_by_merchant_id("juspay_merchant") + .find_merchant_account_by_merchant_id("juspay_merchant", &key_store) .await .unwrap(); @@ -344,6 +353,7 @@ async fn payments_create_core() { payments::payments_core::( &state, merchant_account, + key_store, payments::PaymentCreate, req, services::AuthFlow::Merchant, @@ -428,9 +438,18 @@ async fn payments_create_core_adyen_no_redirect() { let merchant_id = "arunraj".to_string(); let payment_id = "pay_mbabizu24mvu3mela5njyhpit10".to_string(); + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + "juspay_merchant", + &state.store.get_master_key().to_vec().into(), + ) + .await + .unwrap(); + let merchant_account = state .store - .find_merchant_account_by_merchant_id("juspay_merchant") + .find_merchant_account_by_merchant_id("juspay_merchant", &key_store) .await .unwrap(); @@ -490,6 +509,7 @@ async fn payments_create_core_adyen_no_redirect() { payments::payments_core::( &state, merchant_account, + key_store, payments::PaymentCreate, req, services::AuthFlow::Merchant, diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index 1713e33c03..bcfd9a0599 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -37,9 +37,18 @@ async fn payments_create_core() { let tx: oneshot::Sender<()> = oneshot::channel().0; let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest, tx).await; + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + "juspay_merchant", + &state.store.get_master_key().to_vec().into(), + ) + .await + .unwrap(); + let merchant_account = state .store - .find_merchant_account_by_merchant_id("juspay_merchant") + .find_merchant_account_by_merchant_id("juspay_merchant", &key_store) .await .unwrap(); @@ -104,6 +113,7 @@ async fn payments_create_core() { router::core::payments::payments_core::( &state, merchant_account, + key_store, payments::PaymentCreate, req, services::AuthFlow::Merchant, @@ -194,9 +204,18 @@ async fn payments_create_core_adyen_no_redirect() { let merchant_id = "arunraj".to_string(); let payment_id = "pay_mbabizu24mvu3mela5njyhpit10".to_string(); + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + "juspay_merchant", + &state.store.get_master_key().to_vec().into(), + ) + .await + .unwrap(); + let merchant_account = state .store - .find_merchant_account_by_merchant_id("juspay_merchant") + .find_merchant_account_by_merchant_id("juspay_merchant", &key_store) .await .unwrap(); @@ -256,6 +275,7 @@ async fn payments_create_core_adyen_no_redirect() { router::core::payments::payments_core::( &state, merchant_account, + key_store, payments::PaymentCreate, req, services::AuthFlow::Merchant,