use std::sync::Arc; use common_utils::{errors::CustomResult, types::keymanager::KeyManagerState}; use diesel_models as store; use error_stack::ResultExt; use futures::lock::{Mutex, MutexGuard}; use hyperswitch_domain_models::{ behaviour::{Conversion, ReverseConversion}, errors::StorageError, merchant_key_store::MerchantKeyStore, payments::{payment_attempt::PaymentAttempt, PaymentIntent}, }; use redis_interface::RedisSettings; use crate::redis::RedisStore; pub mod payment_attempt; pub mod payment_intent; #[cfg(feature = "payouts")] pub mod payout_attempt; #[cfg(feature = "payouts")] pub mod payouts; pub mod redis_conn; #[cfg(not(feature = "payouts"))] use hyperswitch_domain_models::{PayoutAttemptInterface, PayoutsInterface}; #[derive(Clone)] pub struct MockDb { pub addresses: Arc>>, pub configs: Arc>>, pub merchant_accounts: Arc>>, pub merchant_connector_accounts: Arc>>, pub payment_attempts: Arc>>, pub payment_intents: Arc>>, pub payment_methods: Arc>>, pub customers: Arc>>, pub refunds: Arc>>, pub processes: Arc>>, pub redis: Arc, pub api_keys: Arc>>, pub ephemeral_keys: Arc>>, pub cards_info: Arc>>, pub events: Arc>>, pub disputes: Arc>>, pub lockers: Arc>>, pub mandates: Arc>>, pub captures: Arc>>, pub merchant_key_store: Arc>>, pub business_profiles: Arc>>, pub reverse_lookups: Arc>>, pub payment_link: Arc>>, pub organizations: Arc>>, pub users: Arc>>, pub user_roles: Arc>>, pub authorizations: Arc>>, pub dashboard_metadata: Arc>>, #[cfg(feature = "payouts")] pub payout_attempt: Arc>>, #[cfg(feature = "payouts")] pub payouts: Arc>>, pub authentications: Arc>>, pub roles: Arc>>, pub user_key_store: Arc>>, pub user_authentication_methods: Arc>>, pub themes: Arc>>, } impl MockDb { pub async fn new(redis: &RedisSettings) -> error_stack::Result { Ok(Self { addresses: Default::default(), configs: Default::default(), merchant_accounts: Default::default(), merchant_connector_accounts: Default::default(), payment_attempts: Default::default(), payment_intents: Default::default(), payment_methods: Default::default(), customers: Default::default(), refunds: Default::default(), processes: Default::default(), redis: Arc::new( RedisStore::new(redis) .await .change_context(StorageError::InitializationError)?, ), api_keys: Default::default(), ephemeral_keys: Default::default(), cards_info: Default::default(), events: Default::default(), disputes: Default::default(), lockers: Default::default(), mandates: Default::default(), captures: Default::default(), merchant_key_store: Default::default(), business_profiles: Default::default(), reverse_lookups: Default::default(), payment_link: Default::default(), organizations: Default::default(), users: Default::default(), user_roles: Default::default(), authorizations: Default::default(), dashboard_metadata: Default::default(), #[cfg(feature = "payouts")] payout_attempt: Default::default(), #[cfg(feature = "payouts")] payouts: Default::default(), authentications: Default::default(), roles: Default::default(), user_key_store: Default::default(), user_authentication_methods: Default::default(), themes: Default::default(), }) } pub async fn find_resource( &self, state: &KeyManagerState, key_store: &MerchantKeyStore, resources: MutexGuard<'_, Vec>, filter_fn: impl Fn(&&D) -> bool, error_message: String, ) -> CustomResult where D: Sync + ReverseConversion + Clone, R: Conversion, { let resource = resources.iter().find(filter_fn).cloned(); match resource { Some(res) => Ok(res .convert( state, key_store.key.get_inner(), key_store.merchant_id.clone().into(), ) .await .change_context(StorageError::DecryptionError)?), None => Err(StorageError::ValueNotFound(error_message).into()), } } pub async fn find_resources( &self, state: &KeyManagerState, key_store: &MerchantKeyStore, resources: MutexGuard<'_, Vec>, filter_fn: impl Fn(&&D) -> bool, error_message: String, ) -> CustomResult, StorageError> where D: Sync + ReverseConversion + Clone, R: Conversion, { let resources: Vec<_> = resources.iter().filter(filter_fn).cloned().collect(); if resources.is_empty() { Err(StorageError::ValueNotFound(error_message).into()) } else { let pm_futures = resources .into_iter() .map(|pm| async { pm.convert( state, key_store.key.get_inner(), key_store.merchant_id.clone().into(), ) .await .change_context(StorageError::DecryptionError) }) .collect::>(); let domain_resources = futures::future::try_join_all(pm_futures).await?; Ok(domain_resources) } } pub async fn update_resource( &self, state: &KeyManagerState, key_store: &MerchantKeyStore, mut resources: MutexGuard<'_, Vec>, resource_updated: D, filter_fn: impl Fn(&&mut D) -> bool, error_message: String, ) -> CustomResult where D: Sync + ReverseConversion + Clone, R: Conversion, { if let Some(pm) = resources.iter_mut().find(filter_fn) { *pm = resource_updated.clone(); let result = resource_updated .convert( state, key_store.key.get_inner(), key_store.merchant_id.clone().into(), ) .await .change_context(StorageError::DecryptionError)?; Ok(result) } else { Err(StorageError::ValueNotFound(error_message).into()) } } } #[cfg(not(feature = "payouts"))] impl PayoutsInterface for MockDb {} #[cfg(not(feature = "payouts"))] impl PayoutAttemptInterface for MockDb {}