From b002c97c9c11f7d725aa7ab5b29d49988baa6aea Mon Sep 17 00:00:00 2001 From: Jeeva Date: Mon, 12 Jun 2023 15:34:30 +0100 Subject: [PATCH] feat(db): implement `MerchantConnectorAccountInterface` for `MockDb` (#1248) Co-authored-by: jeeva --- .../src/db/merchant_connector_account.rs | 152 ++++++++++++++---- .../src/merchant_connector_account.rs | 34 +++- 2 files changed, 156 insertions(+), 30 deletions(-) diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index 997cc130c7..0550759380 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -1,5 +1,6 @@ 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; @@ -138,7 +139,7 @@ where async fn update_merchant_connector_account( &self, this: domain::MerchantConnectorAccount, - merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, + merchant_connector_account: MerchantConnectorAccountUpdateInternal, ) -> CustomResult; async fn delete_merchant_connector_account_by_merchant_id_merchant_connector_id( @@ -256,7 +257,7 @@ impl MerchantConnectorAccountInterface for Store { async fn update_merchant_connector_account( &self, this: domain::MerchantConnectorAccount, - merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, + merchant_connector_account: MerchantConnectorAccountUpdateInternal, ) -> CustomResult { let _merchant_connector_id = this.merchant_connector_id.clone(); let update_call = || async { @@ -307,37 +308,71 @@ impl MerchantConnectorAccountInterface for Store { #[async_trait::async_trait] impl MerchantConnectorAccountInterface for MockDb { - // safety: only used for testing - #[allow(clippy::unwrap_used)] async fn find_merchant_connector_account_by_merchant_id_connector_label( &self, merchant_id: &str, connector: &str, ) -> CustomResult { - let accounts = self.merchant_connector_accounts.lock().await; - let account = accounts + match self + .merchant_connector_accounts + .lock() + .await .iter() .find(|account| { account.merchant_id == merchant_id && account.connector_name == connector }) .cloned() - .unwrap(); - account - .convert(self, merchant_id) + .async_map(|account| async { + account + .convert(self, merchant_id) + .await + .change_context(errors::StorageError::DecryptionError) + }) .await - .change_context(errors::StorageError::DecryptionError) + { + Some(result) => result, + None => { + return Err(errors::StorageError::ValueNotFound( + "cannot find merchant connector account".to_string(), + ) + .into()) + } + } } async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id( &self, - _merchant_id: &str, - _merchant_connector_id: &str, + merchant_id: &str, + merchant_connector_id: &str, ) -> CustomResult { - // [#172]: Implement function for `MockDb` - Err(errors::StorageError::MockDbError)? + match self + .merchant_connector_accounts + .lock() + .await + .iter() + .find(|account| { + account.merchant_id == merchant_id + && account.merchant_connector_id == merchant_connector_id + }) + .cloned() + .async_map(|account| async { + account + .convert(self, merchant_id) + .await + .change_context(errors::StorageError::DecryptionError) + }) + .await + { + Some(result) => result, + None => { + return Err(errors::StorageError::ValueNotFound( + "cannot find merchant connector account".to_string(), + ) + .into()) + } + } } - #[allow(clippy::panic)] async fn insert_merchant_connector_account( &self, t: domain::MerchantConnectorAccount, @@ -373,28 +408,91 @@ impl MerchantConnectorAccountInterface for MockDb { async fn find_merchant_connector_account_by_merchant_id_and_disabled_list( &self, - _merchant_id: &str, - _get_disabled: bool, + merchant_id: &str, + get_disabled: bool, ) -> CustomResult, errors::StorageError> { - // [#172]: Implement function for `MockDb` - Err(errors::StorageError::MockDbError)? + let accounts = self + .merchant_connector_accounts + .lock() + .await + .iter() + .filter(|account: &&storage::MerchantConnectorAccount| { + if get_disabled { + account.merchant_id == merchant_id + } else { + account.merchant_id == merchant_id && account.disabled == Some(false) + } + }) + .cloned() + .collect::>(); + + let mut output = Vec::with_capacity(accounts.len()); + for account in accounts.into_iter() { + output.push( + account + .convert(self, merchant_id) + .await + .change_context(errors::StorageError::DecryptionError)?, + ) + } + Ok(output) } async fn update_merchant_connector_account( &self, - _this: domain::MerchantConnectorAccount, - _merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, + merchant_connector_account: domain::MerchantConnectorAccount, + updated_merchant_connector_account: MerchantConnectorAccountUpdateInternal, ) -> CustomResult { - // [#172]: Implement function for `MockDb` - Err(errors::StorageError::MockDbError)? + match self + .merchant_connector_accounts + .lock() + .await + .iter_mut() + .find(|account| Some(account.id) == merchant_connector_account.id) + .map(|a| { + let updated = + updated_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) + .await + .change_context(errors::StorageError::DecryptionError) + }) + .await + { + Some(result) => result, + None => { + return Err(errors::StorageError::ValueNotFound( + "cannot find merchant connector account to update".to_string(), + ) + .into()) + } + } } async fn delete_merchant_connector_account_by_merchant_id_merchant_connector_id( &self, - _merchant_id: &str, - _merchant_connector_id: &str, + merchant_id: &str, + merchant_connector_id: &str, ) -> CustomResult { - // [#172]: Implement function for `MockDb` - Err(errors::StorageError::MockDbError)? + let mut accounts = self.merchant_connector_accounts.lock().await; + match accounts.iter().position(|account| { + account.merchant_id == merchant_id + && account.merchant_connector_id == merchant_connector_id + }) { + Some(index) => { + accounts.remove(index); + return Ok(true); + } + None => { + return Err(errors::StorageError::ValueNotFound( + "cannot find merchant connector account to delete".to_string(), + ) + .into()) + } + } } } diff --git a/crates/storage_models/src/merchant_connector_account.rs b/crates/storage_models/src/merchant_connector_account.rs index c798602f64..ed34ab2673 100644 --- a/crates/storage_models/src/merchant_connector_account.rs +++ b/crates/storage_models/src/merchant_connector_account.rs @@ -1,5 +1,8 @@ +use std::fmt::Debug; + use common_utils::pii; use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; +use masking::Secret; use crate::{encryption::Encryption, enums as storage_enums, schema::merchant_connector_account}; @@ -29,7 +32,7 @@ pub struct MerchantConnectorAccount { pub business_country: storage_enums::CountryAlpha2, pub business_label: String, pub business_sub_label: Option, - pub frm_configs: Option>, + pub frm_configs: Option>, pub created_at: time::PrimitiveDateTime, pub modified_at: time::PrimitiveDateTime, } @@ -50,7 +53,7 @@ pub struct MerchantConnectorAccountNew { pub business_country: storage_enums::CountryAlpha2, pub business_label: String, pub business_sub_label: Option, - pub frm_configs: Option>, + pub frm_configs: Option>, pub created_at: time::PrimitiveDateTime, pub modified_at: time::PrimitiveDateTime, } @@ -67,6 +70,31 @@ pub struct MerchantConnectorAccountUpdateInternal { pub merchant_connector_id: Option, pub payment_methods_enabled: Option>, pub metadata: Option, - pub frm_configs: Option>, + pub frm_configs: Option>, pub modified_at: Option, } + +impl MerchantConnectorAccountUpdateInternal { + pub fn create_merchant_connector_account( + self, + source: MerchantConnectorAccount, + ) -> MerchantConnectorAccount { + MerchantConnectorAccount { + merchant_id: self.merchant_id.unwrap_or(source.merchant_id), + connector_type: self.connector_type.unwrap_or(source.connector_type), + connector_account_details: self + .connector_account_details + .unwrap_or(source.connector_account_details), + test_mode: self.test_mode, + disabled: self.disabled, + merchant_connector_id: self + .merchant_connector_id + .unwrap_or(source.merchant_connector_id), + payment_methods_enabled: self.payment_methods_enabled, + frm_configs: self.frm_configs, + modified_at: self.modified_at.unwrap_or(source.modified_at), + + ..source + } + } +}