diff --git a/crates/diesel_models/src/callback_mapper.rs b/crates/diesel_models/src/callback_mapper.rs new file mode 100644 index 000000000000..3d00b929b767 --- /dev/null +++ b/crates/diesel_models/src/callback_mapper.rs @@ -0,0 +1,27 @@ +use common_utils::pii; +use diesel::{Identifiable, Insertable, Queryable, Selectable}; +use serde::{self, Deserialize, Serialize}; + +use crate::schema::callback_mapper; + +#[derive( + Clone, + Debug, + Eq, + PartialEq, + Identifiable, + Queryable, + Selectable, + Serialize, + Deserialize, + Insertable, +)] +#[diesel(table_name = callback_mapper, primary_key(id, type_), check_for_backend(diesel::pg::Pg))] +pub struct CallbackMapper { + pub id: String, + #[serde(rename = "type")] + pub type_: String, + pub data: pii::SecretSerdeValue, + pub created_at: time::PrimitiveDateTime, + pub last_modified_at: time::PrimitiveDateTime, +} diff --git a/crates/diesel_models/src/lib.rs b/crates/diesel_models/src/lib.rs index cc3dc1361545..de413b728b13 100644 --- a/crates/diesel_models/src/lib.rs +++ b/crates/diesel_models/src/lib.rs @@ -10,6 +10,7 @@ pub mod authentication; pub mod authorization; pub mod blocklist; pub mod blocklist_fingerprint; +pub mod callback_mapper; pub mod customers; pub mod dispute; pub mod dynamic_routing_stats; @@ -60,11 +61,11 @@ use diesel_impl::{DieselArray, OptionalDieselArray}; pub type StorageResult = error_stack::Result; pub type PgPooledConn = async_bb8_diesel::Connection; pub use self::{ - address::*, api_keys::*, cards_info::*, configs::*, customers::*, dispute::*, ephemeral_key::*, - events::*, file::*, generic_link::*, locker_mock_up::*, mandate::*, merchant_account::*, - merchant_connector_account::*, payment_attempt::*, payment_intent::*, payment_method::*, - payout_attempt::*, payouts::*, process_tracker::*, refund::*, reverse_lookup::*, - user_authentication_method::*, + address::*, api_keys::*, callback_mapper::*, cards_info::*, configs::*, customers::*, + dispute::*, ephemeral_key::*, events::*, file::*, generic_link::*, locker_mock_up::*, + mandate::*, merchant_account::*, merchant_connector_account::*, payment_attempt::*, + payment_intent::*, payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, + refund::*, reverse_lookup::*, user_authentication_method::*, }; /// The types and implementations provided by this module are required for the schema generated by diff --git a/crates/diesel_models/src/query.rs b/crates/diesel_models/src/query.rs index ab044b5c6e69..ec661a1b4e07 100644 --- a/crates/diesel_models/src/query.rs +++ b/crates/diesel_models/src/query.rs @@ -10,6 +10,7 @@ pub mod authentication; pub mod authorization; pub mod blocklist; pub mod blocklist_fingerprint; +pub mod callback_mapper; pub mod customers; pub mod dashboard_metadata; pub mod dispute; diff --git a/crates/diesel_models/src/query/callback_mapper.rs b/crates/diesel_models/src/query/callback_mapper.rs new file mode 100644 index 000000000000..4b49455900e2 --- /dev/null +++ b/crates/diesel_models/src/query/callback_mapper.rs @@ -0,0 +1,20 @@ +use diesel::{associations::HasTable, ExpressionMethods}; + +use super::generics; +use crate::{ + callback_mapper::CallbackMapper, schema::callback_mapper::dsl, PgPooledConn, StorageResult, +}; + +impl CallbackMapper { + pub async fn insert(self, conn: &PgPooledConn) -> StorageResult { + generics::generic_insert(conn, self).await + } + + pub async fn find_by_id(conn: &PgPooledConn, id: &str) -> StorageResult { + generics::generic_find_one::<::Table, _, _>( + conn, + dsl::id.eq(id.to_owned()), + ) + .await + } +} diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 61a8a7e19b9e..1687fd6730b3 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -219,6 +219,22 @@ diesel::table! { } } +diesel::table! { + use diesel::sql_types::*; + use crate::enums::diesel_exports::*; + + callback_mapper (id, type_) { + #[max_length = 128] + id -> Varchar, + #[sql_name = "type"] + #[max_length = 64] + type_ -> Varchar, + data -> Jsonb, + created_at -> Timestamp, + last_modified_at -> Timestamp, + } +} + diesel::table! { use diesel::sql_types::*; use crate::enums::diesel_exports::*; @@ -1452,6 +1468,7 @@ diesel::allow_tables_to_appear_in_same_query!( blocklist_fingerprint, blocklist_lookup, business_profile, + callback_mapper, captures, cards_info, configs, diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index 6569c0353654..f9e628b11d24 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -227,6 +227,22 @@ diesel::table! { } } +diesel::table! { + use diesel::sql_types::*; + use crate::enums::diesel_exports::*; + + callback_mapper (id, type_) { + #[max_length = 128] + id -> Varchar, + #[sql_name = "type"] + #[max_length = 64] + type_ -> Varchar, + data -> Jsonb, + created_at -> Timestamp, + last_modified_at -> Timestamp, + } +} + diesel::table! { use diesel::sql_types::*; use crate::enums::diesel_exports::*; @@ -1400,6 +1416,7 @@ diesel::allow_tables_to_appear_in_same_query!( blocklist_fingerprint, blocklist_lookup, business_profile, + callback_mapper, captures, cards_info, configs, diff --git a/crates/hyperswitch_domain_models/src/callback_mapper.rs b/crates/hyperswitch_domain_models/src/callback_mapper.rs new file mode 100644 index 000000000000..fffc33e572a4 --- /dev/null +++ b/crates/hyperswitch_domain_models/src/callback_mapper.rs @@ -0,0 +1,12 @@ +use common_utils::pii; +use serde::{self, Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct CallbackMapper { + pub id: String, + #[serde(rename = "type")] + pub type_: String, + pub data: pii::SecretSerdeValue, + pub created_at: time::PrimitiveDateTime, + pub last_modified_at: time::PrimitiveDateTime, +} diff --git a/crates/hyperswitch_domain_models/src/lib.rs b/crates/hyperswitch_domain_models/src/lib.rs index fe152e876ccf..92baa97e29c3 100644 --- a/crates/hyperswitch_domain_models/src/lib.rs +++ b/crates/hyperswitch_domain_models/src/lib.rs @@ -2,6 +2,7 @@ pub mod address; pub mod api; pub mod behaviour; pub mod business_profile; +pub mod callback_mapper; pub mod consts; pub mod customer; pub mod disputes; diff --git a/crates/router/src/db.rs b/crates/router/src/db.rs index fbb75b6af603..72b03e46a34a 100644 --- a/crates/router/src/db.rs +++ b/crates/router/src/db.rs @@ -6,6 +6,7 @@ pub mod blocklist; pub mod blocklist_fingerprint; pub mod blocklist_lookup; pub mod business_profile; +pub mod callback_mapper; pub mod capture; pub mod cards_info; pub mod configs; diff --git a/crates/router/src/db/callback_mapper.rs b/crates/router/src/db/callback_mapper.rs new file mode 100644 index 000000000000..d2326c41bee6 --- /dev/null +++ b/crates/router/src/db/callback_mapper.rs @@ -0,0 +1,52 @@ +use error_stack::report; +use hyperswitch_domain_models::callback_mapper as domain; +use router_env::{instrument, tracing}; +use storage_impl::DataModelExt; + +use super::Store; +use crate::{ + connection, + core::errors::{self, CustomResult}, + types::storage, +}; + +#[async_trait::async_trait] +pub trait CallbackMapperInterface { + async fn insert_call_back_mapper( + &self, + call_back_mapper: domain::CallbackMapper, + ) -> CustomResult; + + async fn find_call_back_mapper_by_id( + &self, + id: &str, + ) -> CustomResult; +} + +#[async_trait::async_trait] +impl CallbackMapperInterface for Store { + #[instrument(skip_all)] + async fn insert_call_back_mapper( + &self, + call_back_mapper: domain::CallbackMapper, + ) -> CustomResult { + let conn = connection::pg_connection_write(self).await?; + call_back_mapper + .to_storage_model() + .insert(&conn) + .await + .map_err(|error| report!(errors::StorageError::from(error))) + .map(domain::CallbackMapper::from_storage_model) + } + + async fn find_call_back_mapper_by_id( + &self, + id: &str, + ) -> CustomResult { + let conn = connection::pg_connection_read(self).await?; + storage::CallbackMapper::find_by_id(&conn, id) + .await + .map_err(|error| report!(errors::StorageError::from(error))) + .map(domain::CallbackMapper::from_storage_model) + } +} diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs index f49173b35496..7b59d1a42a28 100644 --- a/crates/router/src/db/kafka_store.rs +++ b/crates/router/src/db/kafka_store.rs @@ -53,6 +53,7 @@ use crate::{ authentication::AuthenticationInterface, authorization::AuthorizationInterface, business_profile::ProfileInterface, + callback_mapper::CallbackMapperInterface, capture::CaptureInterface, cards_info::CardsInfoInterface, configs::ConfigInterface, @@ -3811,3 +3812,22 @@ impl ThemeInterface for KafkaStore { .await } } + +#[async_trait::async_trait] +impl CallbackMapperInterface for KafkaStore { + async fn insert_call_back_mapper( + &self, + call_back_mapper: domain::CallbackMapper, + ) -> CustomResult { + self.diesel_store + .insert_call_back_mapper(call_back_mapper) + .await + } + + async fn find_call_back_mapper_by_id( + &self, + id: &str, + ) -> CustomResult { + self.diesel_store.find_call_back_mapper_by_id(id).await + } +} diff --git a/crates/router/src/types/domain.rs b/crates/router/src/types/domain.rs index 070e583caabe..9a87b6d28be2 100644 --- a/crates/router/src/types/domain.rs +++ b/crates/router/src/types/domain.rs @@ -16,6 +16,10 @@ mod customers { pub use hyperswitch_domain_models::customer::*; } +mod callback_mapper { + pub use hyperswitch_domain_models::callback_mapper::CallbackMapper; +} + pub use customers::*; pub use merchant_account::*; @@ -39,6 +43,7 @@ pub mod user_key_store; pub use address::*; pub use business_profile::*; +pub use callback_mapper::*; pub use consts::*; pub use event::*; pub use merchant_connector_account::*; diff --git a/crates/router/src/types/storage.rs b/crates/router/src/types/storage.rs index 24573548d797..96a0d5800561 100644 --- a/crates/router/src/types/storage.rs +++ b/crates/router/src/types/storage.rs @@ -6,6 +6,7 @@ pub mod blocklist; pub mod blocklist_fingerprint; pub mod blocklist_lookup; pub mod business_profile; +pub mod callback_mapper; pub mod capture; pub mod cards_info; pub mod configs; @@ -63,13 +64,13 @@ pub use scheduler::db::process_tracker; pub use self::{ address::*, api_keys::*, authentication::*, authorization::*, blocklist::*, - blocklist_fingerprint::*, blocklist_lookup::*, business_profile::*, capture::*, cards_info::*, - configs::*, customers::*, dashboard_metadata::*, dispute::*, dynamic_routing_stats::*, - ephemeral_key::*, events::*, file::*, fraud_check::*, generic_link::*, gsm::*, - locker_mock_up::*, mandate::*, merchant_account::*, merchant_connector_account::*, - merchant_key_store::*, payment_link::*, payment_method::*, process_tracker::*, refund::*, - reverse_lookup::*, role::*, routing_algorithm::*, unified_translations::*, user::*, - user_authentication_method::*, user_role::*, + blocklist_fingerprint::*, blocklist_lookup::*, business_profile::*, callback_mapper::*, + capture::*, cards_info::*, configs::*, customers::*, dashboard_metadata::*, dispute::*, + dynamic_routing_stats::*, ephemeral_key::*, events::*, file::*, fraud_check::*, + generic_link::*, gsm::*, locker_mock_up::*, mandate::*, merchant_account::*, + merchant_connector_account::*, merchant_key_store::*, payment_link::*, payment_method::*, + process_tracker::*, refund::*, reverse_lookup::*, role::*, routing_algorithm::*, + unified_translations::*, user::*, user_authentication_method::*, user_role::*, }; use crate::types::api::routing; diff --git a/crates/router/src/types/storage/callback_mapper.rs b/crates/router/src/types/storage/callback_mapper.rs new file mode 100644 index 000000000000..4f66a56c6f3a --- /dev/null +++ b/crates/router/src/types/storage/callback_mapper.rs @@ -0,0 +1 @@ +pub use diesel_models::callback_mapper::CallbackMapper; diff --git a/crates/storage_impl/src/callback_mapper.rs b/crates/storage_impl/src/callback_mapper.rs new file mode 100644 index 000000000000..186f2b7f9270 --- /dev/null +++ b/crates/storage_impl/src/callback_mapper.rs @@ -0,0 +1,28 @@ +use diesel_models::callback_mapper::CallbackMapper as DieselCallbackMapper; +use hyperswitch_domain_models::callback_mapper::CallbackMapper; + +use crate::DataModelExt; + +impl DataModelExt for CallbackMapper { + type StorageModel = DieselCallbackMapper; + + fn to_storage_model(self) -> Self::StorageModel { + DieselCallbackMapper { + id: self.id, + type_: self.type_, + data: self.data, + created_at: self.created_at, + last_modified_at: self.last_modified_at, + } + } + + fn from_storage_model(storage_model: Self::StorageModel) -> Self { + Self { + id: storage_model.id, + type_: storage_model.type_, + data: storage_model.data, + created_at: storage_model.created_at, + last_modified_at: storage_model.last_modified_at, + } + } +} diff --git a/crates/storage_impl/src/lib.rs b/crates/storage_impl/src/lib.rs index 09bb42567df4..e0722ef52eaf 100644 --- a/crates/storage_impl/src/lib.rs +++ b/crates/storage_impl/src/lib.rs @@ -6,6 +6,7 @@ use hyperswitch_domain_models::errors::{StorageError, StorageResult}; use masking::StrongSecret; use redis::{kv_store::RedisConnInterface, pub_sub::PubSubInterface, RedisStore}; mod address; +pub mod callback_mapper; pub mod config; pub mod connection; pub mod customers; diff --git a/migrations/2024-11-13-105952_add_call-back-mapper_table/down.sql b/migrations/2024-11-13-105952_add_call-back-mapper_table/down.sql new file mode 100644 index 000000000000..8c2f4f54a170 --- /dev/null +++ b/migrations/2024-11-13-105952_add_call-back-mapper_table/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE IF EXISTS callback_mapper; \ No newline at end of file diff --git a/migrations/2024-11-13-105952_add_call-back-mapper_table/up.sql b/migrations/2024-11-13-105952_add_call-back-mapper_table/up.sql new file mode 100644 index 000000000000..604034f49348 --- /dev/null +++ b/migrations/2024-11-13-105952_add_call-back-mapper_table/up.sql @@ -0,0 +1,9 @@ +-- Your SQL goes here +CREATE TABLE IF NOT EXISTS callback_mapper ( + id VARCHAR(128) NOT NULL, + type VARCHAR(64) NOT NULL, + data JSONB NOT NULL, + created_at TIMESTAMP NOT NULL, + last_modified_at TIMESTAMP NOT NULL, + PRIMARY KEY (id, type) +); \ No newline at end of file