From ffcdcf906725dd5ddf5082801bc8e2dfeb6c4533 Mon Sep 17 00:00:00 2001 From: prajjwalkumar17 Date: Thu, 25 Jan 2024 15:29:17 +0530 Subject: [PATCH 1/3] chore: Add killswitch for blocklist feature --- .../payments/operations/payment_confirm.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index c81145c5de72..e67f7c2672f8 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -719,10 +719,22 @@ impl let m_db = state.clone().store; // Validate Blocklist + let mut fingerprint_id = None; + let mut is_pm_blocklisted = false; let merchant_id = payment_data.payment_attempt.merchant_id; + let blocklist_enabled_key = format!("guard_blocklist_for_{merchant_id}"); + let blocklist_guard_enabled = state + .store + .find_config_by_key_unwrap_or(&blocklist_enabled_key, Some("false".to_string())) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to fetch guard blocklist enabled config")?; + + let blocklist_guard_enabled = blocklist_guard_enabled.config != "false"; + + if blocklist_guard_enabled { let merchant_fingerprint_secret = blocklist_utils::get_merchant_fingerprint_secret(state, &merchant_id).await?; - // Hashed Fingerprint to check whether or not this payment should be blocked. let card_number_fingerprint = payment_data .payment_method_data @@ -795,11 +807,8 @@ impl }) .map(hex::encode); - let mut fingerprint_id = None; //validating the payment method. - let mut is_pm_blocklisted = false; - let mut blocklist_futures = Vec::new(); if let Some(card_number_fingerprint) = card_number_fingerprint.as_ref() { blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( @@ -868,7 +877,7 @@ impl ); } } - + } let surcharge_amount = payment_data .surcharge_details .as_ref() From d6391b61aea4b058b0d819c6812ad3c0e4b53fbf Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 10:04:59 +0000 Subject: [PATCH 2/3] chore: run formatter --- .../payments/operations/payment_confirm.rs | 266 +++++++++--------- 1 file changed, 134 insertions(+), 132 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index e67f7c2672f8..f09339e7e542 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -733,151 +733,153 @@ impl let blocklist_guard_enabled = blocklist_guard_enabled.config != "false"; if blocklist_guard_enabled { - let merchant_fingerprint_secret = - blocklist_utils::get_merchant_fingerprint_secret(state, &merchant_id).await?; - // Hashed Fingerprint to check whether or not this payment should be blocked. - let card_number_fingerprint = payment_data - .payment_method_data - .as_ref() - .and_then(|pm_data| match pm_data { - api_models::payments::PaymentMethodData::Card(card) => { - crypto::HmacSha512::sign_message( - &crypto::HmacSha512, - merchant_fingerprint_secret.as_bytes(), - card.card_number.clone().get_card_no().as_bytes(), - ) - .attach_printable("error in pm fingerprint creation") - .map_or_else( - |err| { - logger::error!(error=?err); - None - }, - Some, - ) - } - _ => None, - }) - .map(hex::encode); - - // Hashed Cardbin to check whether or not this payment should be blocked. - let card_bin_fingerprint = payment_data - .payment_method_data - .as_ref() - .and_then(|pm_data| match pm_data { - api_models::payments::PaymentMethodData::Card(card) => { - crypto::HmacSha512::sign_message( - &crypto::HmacSha512, - merchant_fingerprint_secret.as_bytes(), - card.card_number.clone().get_card_isin().as_bytes(), - ) - .attach_printable("error in card bin hash creation") - .map_or_else( - |err| { - logger::error!(error=?err); - None - }, - Some, - ) - } - _ => None, - }) - .map(hex::encode); - - // Hashed Extended Cardbin to check whether or not this payment should be blocked. - let extended_card_bin_fingerprint = payment_data - .payment_method_data - .as_ref() - .and_then(|pm_data| match pm_data { - api_models::payments::PaymentMethodData::Card(card) => { - crypto::HmacSha512::sign_message( - &crypto::HmacSha512, - merchant_fingerprint_secret.as_bytes(), - card.card_number.clone().get_extended_card_bin().as_bytes(), - ) - .attach_printable("error in extended card bin hash creation") - .map_or_else( - |err| { - logger::error!(error=?err); - None - }, - Some, - ) - } - _ => None, - }) - .map(hex::encode); - - - //validating the payment method. - let mut blocklist_futures = Vec::new(); - if let Some(card_number_fingerprint) = card_number_fingerprint.as_ref() { - blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( - &merchant_id, - card_number_fingerprint, - )); - } + let merchant_fingerprint_secret = + blocklist_utils::get_merchant_fingerprint_secret(state, &merchant_id).await?; + // Hashed Fingerprint to check whether or not this payment should be blocked. + let card_number_fingerprint = payment_data + .payment_method_data + .as_ref() + .and_then(|pm_data| match pm_data { + api_models::payments::PaymentMethodData::Card(card) => { + crypto::HmacSha512::sign_message( + &crypto::HmacSha512, + merchant_fingerprint_secret.as_bytes(), + card.card_number.clone().get_card_no().as_bytes(), + ) + .attach_printable("error in pm fingerprint creation") + .map_or_else( + |err| { + logger::error!(error=?err); + None + }, + Some, + ) + } + _ => None, + }) + .map(hex::encode); + + // Hashed Cardbin to check whether or not this payment should be blocked. + let card_bin_fingerprint = payment_data + .payment_method_data + .as_ref() + .and_then(|pm_data| match pm_data { + api_models::payments::PaymentMethodData::Card(card) => { + crypto::HmacSha512::sign_message( + &crypto::HmacSha512, + merchant_fingerprint_secret.as_bytes(), + card.card_number.clone().get_card_isin().as_bytes(), + ) + .attach_printable("error in card bin hash creation") + .map_or_else( + |err| { + logger::error!(error=?err); + None + }, + Some, + ) + } + _ => None, + }) + .map(hex::encode); + + // Hashed Extended Cardbin to check whether or not this payment should be blocked. + let extended_card_bin_fingerprint = payment_data + .payment_method_data + .as_ref() + .and_then(|pm_data| match pm_data { + api_models::payments::PaymentMethodData::Card(card) => { + crypto::HmacSha512::sign_message( + &crypto::HmacSha512, + merchant_fingerprint_secret.as_bytes(), + card.card_number.clone().get_extended_card_bin().as_bytes(), + ) + .attach_printable("error in extended card bin hash creation") + .map_or_else( + |err| { + logger::error!(error=?err); + None + }, + Some, + ) + } + _ => None, + }) + .map(hex::encode); + + //validating the payment method. + let mut blocklist_futures = Vec::new(); + if let Some(card_number_fingerprint) = card_number_fingerprint.as_ref() { + blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( + &merchant_id, + card_number_fingerprint, + )); + } - if let Some(card_bin_fingerprint) = card_bin_fingerprint.as_ref() { - blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( - &merchant_id, - card_bin_fingerprint, - )); - } + if let Some(card_bin_fingerprint) = card_bin_fingerprint.as_ref() { + blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( + &merchant_id, + card_bin_fingerprint, + )); + } - if let Some(extended_card_bin_fingerprint) = extended_card_bin_fingerprint.as_ref() { - blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( - &merchant_id, - extended_card_bin_fingerprint, - )); - } + if let Some(extended_card_bin_fingerprint) = extended_card_bin_fingerprint.as_ref() { + blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( + &merchant_id, + extended_card_bin_fingerprint, + )); + } - let blocklist_lookups = futures::future::join_all(blocklist_futures).await; + let blocklist_lookups = futures::future::join_all(blocklist_futures).await; - if blocklist_lookups.iter().any(|x| x.is_ok()) { - intent_status = storage_enums::IntentStatus::Failed; - attempt_status = storage_enums::AttemptStatus::Failure; - is_pm_blocklisted = true; - } + if blocklist_lookups.iter().any(|x| x.is_ok()) { + intent_status = storage_enums::IntentStatus::Failed; + attempt_status = storage_enums::AttemptStatus::Failure; + is_pm_blocklisted = true; + } - if let Some(encoded_hash) = card_number_fingerprint { - #[cfg(feature = "kms")] - let encrypted_fingerprint = kms::get_kms_client(&state.conf.kms) - .await - .encrypt(encoded_hash) - .await - .map_or_else( - |e| { - logger::error!(error=?e, "failed kms encryption of card fingerprint"); - None - }, - Some, - ); - - #[cfg(not(feature = "kms"))] - let encrypted_fingerprint = Some(encoded_hash); - - if let Some(encrypted_fingerprint) = encrypted_fingerprint { - fingerprint_id = db - .insert_blocklist_fingerprint_entry( - diesel_models::blocklist_fingerprint::BlocklistFingerprintNew { - merchant_id, - fingerprint_id: utils::generate_id(consts::ID_LENGTH, "fingerprint"), - encrypted_fingerprint, - data_kind: common_enums::BlocklistDataKind::PaymentMethod, - created_at: common_utils::date_time::now(), - }, - ) + if let Some(encoded_hash) = card_number_fingerprint { + #[cfg(feature = "kms")] + let encrypted_fingerprint = kms::get_kms_client(&state.conf.kms) + .await + .encrypt(encoded_hash) .await .map_or_else( |e| { - logger::error!(error=?e, "failed storing card fingerprint in db"); + logger::error!(error=?e, "failed kms encryption of card fingerprint"); None }, - |fp| Some(fp.fingerprint_id), + Some, ); + + #[cfg(not(feature = "kms"))] + let encrypted_fingerprint = Some(encoded_hash); + + if let Some(encrypted_fingerprint) = encrypted_fingerprint { + fingerprint_id = db + .insert_blocklist_fingerprint_entry( + diesel_models::blocklist_fingerprint::BlocklistFingerprintNew { + merchant_id, + fingerprint_id: utils::generate_id( + consts::ID_LENGTH, + "fingerprint", + ), + encrypted_fingerprint, + data_kind: common_enums::BlocklistDataKind::PaymentMethod, + created_at: common_utils::date_time::now(), + }, + ) + .await + .map_or_else( + |e| { + logger::error!(error=?e, "failed storing card fingerprint in db"); + None + }, + |fp| Some(fp.fingerprint_id), + ); + } } } - } let surcharge_amount = payment_data .surcharge_details .as_ref() From a2ce8ece027e2b387d7c52636d280c59f6762c08 Mon Sep 17 00:00:00 2001 From: prajjwalkumar17 Date: Thu, 25 Jan 2024 16:56:53 +0530 Subject: [PATCH 3/3] chore: addressed comments --- .../payments/operations/payment_confirm.rs | 280 +++++++++--------- 1 file changed, 145 insertions(+), 135 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index e67f7c2672f8..eba32ca0a53d 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -726,158 +726,168 @@ impl let blocklist_guard_enabled = state .store .find_config_by_key_unwrap_or(&blocklist_enabled_key, Some("false".to_string())) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to fetch guard blocklist enabled config")?; + .await; - let blocklist_guard_enabled = blocklist_guard_enabled.config != "false"; + let blocklist_guard_enabled: bool = match blocklist_guard_enabled { + Ok(config) => serde_json::from_str(&config.config).unwrap_or(false), - if blocklist_guard_enabled { - let merchant_fingerprint_secret = - blocklist_utils::get_merchant_fingerprint_secret(state, &merchant_id).await?; - // Hashed Fingerprint to check whether or not this payment should be blocked. - let card_number_fingerprint = payment_data - .payment_method_data - .as_ref() - .and_then(|pm_data| match pm_data { - api_models::payments::PaymentMethodData::Card(card) => { - crypto::HmacSha512::sign_message( - &crypto::HmacSha512, - merchant_fingerprint_secret.as_bytes(), - card.card_number.clone().get_card_no().as_bytes(), - ) - .attach_printable("error in pm fingerprint creation") - .map_or_else( - |err| { - logger::error!(error=?err); - None - }, - Some, - ) + // If it is not present in db we are defaulting it to false + Err(inner) => { + if !inner.current_context().is_db_not_found() { + logger::error!("Error fetching guard blocklist enabled config {:?}", inner); } - _ => None, - }) - .map(hex::encode); - - // Hashed Cardbin to check whether or not this payment should be blocked. - let card_bin_fingerprint = payment_data - .payment_method_data - .as_ref() - .and_then(|pm_data| match pm_data { - api_models::payments::PaymentMethodData::Card(card) => { - crypto::HmacSha512::sign_message( - &crypto::HmacSha512, - merchant_fingerprint_secret.as_bytes(), - card.card_number.clone().get_card_isin().as_bytes(), - ) - .attach_printable("error in card bin hash creation") - .map_or_else( - |err| { - logger::error!(error=?err); - None - }, - Some, - ) - } - _ => None, - }) - .map(hex::encode); - - // Hashed Extended Cardbin to check whether or not this payment should be blocked. - let extended_card_bin_fingerprint = payment_data - .payment_method_data - .as_ref() - .and_then(|pm_data| match pm_data { - api_models::payments::PaymentMethodData::Card(card) => { - crypto::HmacSha512::sign_message( - &crypto::HmacSha512, - merchant_fingerprint_secret.as_bytes(), - card.card_number.clone().get_extended_card_bin().as_bytes(), - ) - .attach_printable("error in extended card bin hash creation") - .map_or_else( - |err| { - logger::error!(error=?err); - None - }, - Some, - ) - } - _ => None, - }) - .map(hex::encode); - + false + } + }; - //validating the payment method. - let mut blocklist_futures = Vec::new(); - if let Some(card_number_fingerprint) = card_number_fingerprint.as_ref() { - blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( - &merchant_id, - card_number_fingerprint, - )); - } + if blocklist_guard_enabled { + let merchant_fingerprint_secret = + blocklist_utils::get_merchant_fingerprint_secret(state, &merchant_id).await?; + // Hashed Fingerprint to check whether or not this payment should be blocked. + let card_number_fingerprint = payment_data + .payment_method_data + .as_ref() + .and_then(|pm_data| match pm_data { + api_models::payments::PaymentMethodData::Card(card) => { + crypto::HmacSha512::sign_message( + &crypto::HmacSha512, + merchant_fingerprint_secret.as_bytes(), + card.card_number.clone().get_card_no().as_bytes(), + ) + .attach_printable("error in pm fingerprint creation") + .map_or_else( + |err| { + logger::error!(error=?err); + None + }, + Some, + ) + } + _ => None, + }) + .map(hex::encode); + + // Hashed Cardbin to check whether or not this payment should be blocked. + let card_bin_fingerprint = payment_data + .payment_method_data + .as_ref() + .and_then(|pm_data| match pm_data { + api_models::payments::PaymentMethodData::Card(card) => { + crypto::HmacSha512::sign_message( + &crypto::HmacSha512, + merchant_fingerprint_secret.as_bytes(), + card.card_number.clone().get_card_isin().as_bytes(), + ) + .attach_printable("error in card bin hash creation") + .map_or_else( + |err| { + logger::error!(error=?err); + None + }, + Some, + ) + } + _ => None, + }) + .map(hex::encode); + + // Hashed Extended Cardbin to check whether or not this payment should be blocked. + let extended_card_bin_fingerprint = payment_data + .payment_method_data + .as_ref() + .and_then(|pm_data| match pm_data { + api_models::payments::PaymentMethodData::Card(card) => { + crypto::HmacSha512::sign_message( + &crypto::HmacSha512, + merchant_fingerprint_secret.as_bytes(), + card.card_number.clone().get_extended_card_bin().as_bytes(), + ) + .attach_printable("error in extended card bin hash creation") + .map_or_else( + |err| { + logger::error!(error=?err); + None + }, + Some, + ) + } + _ => None, + }) + .map(hex::encode); + + //validating the payment method. + let mut blocklist_futures = Vec::new(); + if let Some(card_number_fingerprint) = card_number_fingerprint.as_ref() { + blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( + &merchant_id, + card_number_fingerprint, + )); + } - if let Some(card_bin_fingerprint) = card_bin_fingerprint.as_ref() { - blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( - &merchant_id, - card_bin_fingerprint, - )); - } + if let Some(card_bin_fingerprint) = card_bin_fingerprint.as_ref() { + blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( + &merchant_id, + card_bin_fingerprint, + )); + } - if let Some(extended_card_bin_fingerprint) = extended_card_bin_fingerprint.as_ref() { - blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( - &merchant_id, - extended_card_bin_fingerprint, - )); - } + if let Some(extended_card_bin_fingerprint) = extended_card_bin_fingerprint.as_ref() { + blocklist_futures.push(db.find_blocklist_lookup_entry_by_merchant_id_fingerprint( + &merchant_id, + extended_card_bin_fingerprint, + )); + } - let blocklist_lookups = futures::future::join_all(blocklist_futures).await; + let blocklist_lookups = futures::future::join_all(blocklist_futures).await; - if blocklist_lookups.iter().any(|x| x.is_ok()) { - intent_status = storage_enums::IntentStatus::Failed; - attempt_status = storage_enums::AttemptStatus::Failure; - is_pm_blocklisted = true; - } + if blocklist_lookups.iter().any(|x| x.is_ok()) { + intent_status = storage_enums::IntentStatus::Failed; + attempt_status = storage_enums::AttemptStatus::Failure; + is_pm_blocklisted = true; + } - if let Some(encoded_hash) = card_number_fingerprint { - #[cfg(feature = "kms")] - let encrypted_fingerprint = kms::get_kms_client(&state.conf.kms) - .await - .encrypt(encoded_hash) - .await - .map_or_else( - |e| { - logger::error!(error=?e, "failed kms encryption of card fingerprint"); - None - }, - Some, - ); - - #[cfg(not(feature = "kms"))] - let encrypted_fingerprint = Some(encoded_hash); - - if let Some(encrypted_fingerprint) = encrypted_fingerprint { - fingerprint_id = db - .insert_blocklist_fingerprint_entry( - diesel_models::blocklist_fingerprint::BlocklistFingerprintNew { - merchant_id, - fingerprint_id: utils::generate_id(consts::ID_LENGTH, "fingerprint"), - encrypted_fingerprint, - data_kind: common_enums::BlocklistDataKind::PaymentMethod, - created_at: common_utils::date_time::now(), - }, - ) + if let Some(encoded_hash) = card_number_fingerprint { + #[cfg(feature = "kms")] + let encrypted_fingerprint = kms::get_kms_client(&state.conf.kms) + .await + .encrypt(encoded_hash) .await .map_or_else( |e| { - logger::error!(error=?e, "failed storing card fingerprint in db"); + logger::error!(error=?e, "failed kms encryption of card fingerprint"); None }, - |fp| Some(fp.fingerprint_id), + Some, ); + + #[cfg(not(feature = "kms"))] + let encrypted_fingerprint = Some(encoded_hash); + + if let Some(encrypted_fingerprint) = encrypted_fingerprint { + fingerprint_id = db + .insert_blocklist_fingerprint_entry( + diesel_models::blocklist_fingerprint::BlocklistFingerprintNew { + merchant_id, + fingerprint_id: utils::generate_id( + consts::ID_LENGTH, + "fingerprint", + ), + encrypted_fingerprint, + data_kind: common_enums::BlocklistDataKind::PaymentMethod, + created_at: common_utils::date_time::now(), + }, + ) + .await + .map_or_else( + |e| { + logger::error!(error=?e, "failed storing card fingerprint in db"); + None + }, + |fp| Some(fp.fingerprint_id), + ); + } } } - } let surcharge_amount = payment_data .surcharge_details .as_ref()