refactor(router): changed the storage of applepay_verified_domains from business_profile to merchant_connector_account table (#2147)

This commit is contained in:
Prajjwal Kumar
2023-09-13 19:34:35 +05:30
committed by GitHub
parent a09b7428e7
commit caa385a5a6
15 changed files with 97 additions and 88 deletions

View File

@ -734,6 +734,8 @@ pub struct MerchantConnectorResponse {
/// default value from merchant account is taken if not passed /// default value from merchant account is taken if not passed
#[schema(max_length = 64)] #[schema(max_length = 64)]
pub profile_id: Option<String>, pub profile_id: Option<String>,
/// identifier for the verified domains of a particular connector account
pub applepay_verified_domains: Option<Vec<String>>,
} }
/// Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc." /// Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc."

View File

@ -13,7 +13,7 @@ pub struct ApplepayMerchantVerificationConfigs {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ApplepayMerchantVerificationRequest { pub struct ApplepayMerchantVerificationRequest {
pub domain_names: Vec<String>, pub domain_names: Vec<String>,
pub business_profile_id: String, pub merchant_connector_account_id: String,
} }
/// Response to be sent for the verify/applepay api /// Response to be sent for the verify/applepay api

View File

@ -121,6 +121,7 @@ impl BusinessProfileUpdateInternal {
frm_routing_algorithm: self.frm_routing_algorithm, frm_routing_algorithm: self.frm_routing_algorithm,
payout_routing_algorithm: self.payout_routing_algorithm, payout_routing_algorithm: self.payout_routing_algorithm,
is_recon_enabled: self.is_recon_enabled.unwrap_or(source.is_recon_enabled), is_recon_enabled: self.is_recon_enabled.unwrap_or(source.is_recon_enabled),
applepay_verified_domains: self.applepay_verified_domains,
..source ..source
} }
} }

View File

@ -39,6 +39,8 @@ pub struct MerchantConnectorAccount {
#[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)] #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
pub frm_config: Option<Vec<Secret<serde_json::Value>>>, pub frm_config: Option<Vec<Secret<serde_json::Value>>>,
pub profile_id: Option<String>, pub profile_id: Option<String>,
#[diesel(deserialize_as = super::OptionalDieselArray<String>)]
pub applepay_verified_domains: Option<Vec<String>>,
} }
#[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)] #[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
@ -64,6 +66,8 @@ pub struct MerchantConnectorAccountNew {
#[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)] #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
pub frm_config: Option<Vec<Secret<serde_json::Value>>>, pub frm_config: Option<Vec<Secret<serde_json::Value>>>,
pub profile_id: Option<String>, pub profile_id: Option<String>,
#[diesel(deserialize_as = super::OptionalDieselArray<String>)]
pub applepay_verified_domains: Option<Vec<String>>,
} }
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)] #[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
@ -83,6 +87,8 @@ pub struct MerchantConnectorAccountUpdateInternal {
pub connector_webhook_details: Option<pii::SecretSerdeValue>, pub connector_webhook_details: Option<pii::SecretSerdeValue>,
#[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)] #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
pub frm_config: Option<Vec<Secret<serde_json::Value>>>, pub frm_config: Option<Vec<Secret<serde_json::Value>>>,
#[diesel(deserialize_as = super::OptionalDieselArray<String>)]
pub applepay_verified_domains: Option<Vec<String>>,
} }
impl MerchantConnectorAccountUpdateInternal { impl MerchantConnectorAccountUpdateInternal {

View File

@ -471,6 +471,7 @@ diesel::table! {
frm_config -> Nullable<Array<Nullable<Jsonb>>>, frm_config -> Nullable<Array<Nullable<Jsonb>>>,
#[max_length = 64] #[max_length = 64]
profile_id -> Nullable<Varchar>, profile_id -> Nullable<Varchar>,
applepay_verified_domains -> Nullable<Array<Nullable<Text>>>,
} }
} }

View File

@ -676,6 +676,7 @@ pub async fn create_payment_connector(
None => None, None => None,
}, },
profile_id: Some(profile_id.clone()), profile_id: Some(profile_id.clone()),
applepay_verified_domains: None,
}; };
let mca = state let mca = state
@ -837,6 +838,7 @@ pub async fn update_payment_connector(
} }
None => None, None => None,
}, },
applepay_verified_domains: None,
}; };
let updated_mca = db let updated_mca = db

View File

@ -649,6 +649,7 @@ impl MerchantConnectorAccountInterface for MockDb {
modified_at: common_utils::date_time::now(), modified_at: common_utils::date_time::now(),
connector_webhook_details: t.connector_webhook_details, connector_webhook_details: t.connector_webhook_details,
profile_id: t.profile_id, profile_id: t.profile_id,
applepay_verified_domains: t.applepay_verified_domains,
}; };
accounts.push(account.clone()); accounts.push(account.clone());
account account
@ -843,6 +844,7 @@ mod merchant_connector_account_cache_tests {
modified_at: date_time::now(), modified_at: date_time::now(),
connector_webhook_details: None, connector_webhook_details: None,
profile_id: Some(profile_id.to_string()), profile_id: Some(profile_id.to_string()),
applepay_verified_domains: None,
}; };
db.insert_merchant_connector_account(mca.clone(), &merchant_key) db.insert_merchant_connector_account(mca.clone(), &merchant_key)

View File

@ -12,7 +12,7 @@ use super::dummy_connector::*;
#[cfg(feature = "payouts")] #[cfg(feature = "payouts")]
use super::payouts::*; use super::payouts::*;
#[cfg(all(feature = "olap", feature = "kms"))] #[cfg(all(feature = "olap", feature = "kms"))]
use super::verification::{apple_pay_merchant_registration, retrieve_apple_pay_verified_domains}; use super::verification::apple_pay_merchant_registration;
#[cfg(feature = "olap")] #[cfg(feature = "olap")]
use super::{admin::*, api_keys::*, disputes::*, files::*}; use super::{admin::*, api_keys::*, disputes::*, files::*};
use super::{cache::*, health::*}; use super::{cache::*, health::*};
@ -589,9 +589,5 @@ impl Verify {
web::resource("/{merchant_id}/apple_pay") web::resource("/{merchant_id}/apple_pay")
.route(web::post().to(apple_pay_merchant_registration)), .route(web::post().to(apple_pay_merchant_registration)),
) )
.service(
web::resource("/applepay_verified_domains")
.route(web::get().to(retrieve_apple_pay_verified_domains)),
)
} }
} }

View File

@ -1,5 +1,4 @@
use actix_web::{web, HttpRequest, Responder}; use actix_web::{web, HttpRequest, Responder};
#[cfg(all(feature = "olap", feature = "kms"))]
use api_models::verifications; use api_models::verifications;
use router_env::{instrument, tracing, Flow}; use router_env::{instrument, tracing, Flow};
@ -15,39 +14,22 @@ pub async fn apple_pay_merchant_registration(
state: web::Data<AppState>, state: web::Data<AppState>,
req: HttpRequest, req: HttpRequest,
json_payload: web::Json<verifications::ApplepayMerchantVerificationRequest>, json_payload: web::Json<verifications::ApplepayMerchantVerificationRequest>,
path: web::Path<String>,
) -> impl Responder { ) -> impl Responder {
let flow = Flow::Verification; let flow = Flow::Verification;
let merchant_id = path.into_inner();
api::server_wrap( api::server_wrap(
flow, flow,
state.get_ref(), state.get_ref(),
&req, &req,
json_payload, json_payload,
|state, _, body| { |state, _, body| {
verification::verify_merchant_creds_for_applepay(state, &req, body, &state.conf.kms) verification::verify_merchant_creds_for_applepay(
}, state,
auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
)
.await
}
#[instrument(skip_all, fields(flow = ?Flow::Verification))]
pub async fn retrieve_apple_pay_verified_domains(
state: web::Data<AppState>,
req: HttpRequest,
params: web::Query<verifications::ApplepayGetVerifiedDomainsParam>,
) -> impl Responder {
let flow = Flow::Verification;
let business_profile_id = &params.business_profile_id;
api::server_wrap(
flow,
state.get_ref(),
&req, &req,
business_profile_id.clone(), body,
|state, _, _| { &state.conf.kms,
verification::get_verified_apple_domains_with_business_profile_id( merchant_id.clone(),
&*state.store,
business_profile_id.clone(),
) )
}, },
auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),

View File

@ -33,6 +33,7 @@ pub struct MerchantConnectorAccount {
pub modified_at: time::PrimitiveDateTime, pub modified_at: time::PrimitiveDateTime,
pub connector_webhook_details: Option<pii::SecretSerdeValue>, pub connector_webhook_details: Option<pii::SecretSerdeValue>,
pub profile_id: Option<String>, pub profile_id: Option<String>,
pub applepay_verified_domains: Option<Vec<String>>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -49,6 +50,7 @@ pub enum MerchantConnectorAccountUpdate {
metadata: Option<pii::SecretSerdeValue>, metadata: Option<pii::SecretSerdeValue>,
frm_configs: Option<Vec<Secret<serde_json::Value>>>, frm_configs: Option<Vec<Secret<serde_json::Value>>>,
connector_webhook_details: Option<pii::SecretSerdeValue>, connector_webhook_details: Option<pii::SecretSerdeValue>,
applepay_verified_domains: Option<Vec<String>>,
}, },
} }
@ -82,6 +84,7 @@ impl behaviour::Conversion for MerchantConnectorAccount {
modified_at: self.modified_at, modified_at: self.modified_at,
connector_webhook_details: self.connector_webhook_details, connector_webhook_details: self.connector_webhook_details,
profile_id: self.profile_id, profile_id: self.profile_id,
applepay_verified_domains: self.applepay_verified_domains,
}, },
) )
} }
@ -119,6 +122,7 @@ impl behaviour::Conversion for MerchantConnectorAccount {
modified_at: other.modified_at, modified_at: other.modified_at,
connector_webhook_details: other.connector_webhook_details, connector_webhook_details: other.connector_webhook_details,
profile_id: other.profile_id, profile_id: other.profile_id,
applepay_verified_domains: other.applepay_verified_domains,
}) })
} }
@ -144,6 +148,7 @@ impl behaviour::Conversion for MerchantConnectorAccount {
modified_at: now, modified_at: now,
connector_webhook_details: self.connector_webhook_details, connector_webhook_details: self.connector_webhook_details,
profile_id: self.profile_id, profile_id: self.profile_id,
applepay_verified_domains: self.applepay_verified_domains,
}) })
} }
} }
@ -163,6 +168,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
metadata, metadata,
frm_configs, frm_configs,
connector_webhook_details, connector_webhook_details,
applepay_verified_domains,
} => Self { } => Self {
merchant_id, merchant_id,
connector_type, connector_type,
@ -177,6 +183,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
frm_config: frm_configs, frm_config: frm_configs,
modified_at: Some(common_utils::date_time::now()), modified_at: Some(common_utils::date_time::now()),
connector_webhook_details, connector_webhook_details,
applepay_verified_domains,
}, },
} }
} }

View File

@ -667,6 +667,7 @@ impl TryFrom<domain::MerchantConnectorAccount> for api_models::admin::MerchantCo
}) })
.transpose()?, .transpose()?,
profile_id: item.profile_id, profile_id: item.profile_id,
applepay_verified_domains: item.applepay_verified_domains,
}) })
} }
} }

View File

@ -1,48 +1,27 @@
use actix_web::web; use actix_web::web;
#[cfg(all(feature = "olap", feature = "kms"))]
use api_models::verifications::{self, ApplepayMerchantResponse}; use api_models::verifications::{self, ApplepayMerchantResponse};
use common_utils::errors::CustomResult; use common_utils::errors::CustomResult;
use diesel_models::business_profile;
use error_stack::{Report, ResultExt}; use error_stack::{Report, ResultExt};
#[cfg(feature = "kms")] #[cfg(feature = "kms")]
use external_services::kms; use external_services::kms;
use crate::{ use crate::{
core::errors::{self, api_error_response}, core::errors::{self, api_error_response, utils::StorageErrorExt},
db::StorageInterface,
headers, logger, headers, logger,
routes::AppState, routes::AppState,
services, types, utils, services, types,
types::storage,
utils,
}; };
const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant"; const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant";
pub async fn get_verified_apple_domains_with_business_profile_id(
db: &dyn StorageInterface,
profile_id: String,
) -> CustomResult<
services::ApplicationResponse<api_models::verifications::ApplepayVerifiedDomainsResponse>,
api_error_response::ApiErrorResponse,
> {
let verified_domains = db
.find_business_profile_by_profile_id(&profile_id)
.await
.change_context(api_error_response::ApiErrorResponse::ResourceIdNotFound)?
.applepay_verified_domains
.unwrap_or_default();
Ok(services::api::ApplicationResponse::Json(
api_models::verifications::ApplepayVerifiedDomainsResponse {
status_code: 200,
verified_domains,
},
))
}
pub async fn verify_merchant_creds_for_applepay( pub async fn verify_merchant_creds_for_applepay(
state: &AppState, state: &AppState,
_req: &actix_web::HttpRequest, _req: &actix_web::HttpRequest,
body: web::Json<verifications::ApplepayMerchantVerificationRequest>, body: web::Json<verifications::ApplepayMerchantVerificationRequest>,
kms_config: &kms::KmsConfig, kms_config: &kms::KmsConfig,
merchant_id: String,
) -> CustomResult< ) -> CustomResult<
services::ApplicationResponse<ApplepayMerchantResponse>, services::ApplicationResponse<ApplepayMerchantResponse>,
api_error_response::ApiErrorResponse, api_error_response::ApiErrorResponse,
@ -110,7 +89,8 @@ pub async fn verify_merchant_creds_for_applepay(
Ok(_) => { Ok(_) => {
check_existence_and_add_domain_to_db( check_existence_and_add_domain_to_db(
state, state,
body.business_profile_id.clone(), merchant_id,
body.merchant_connector_account_id.clone(),
body.domain_names.clone(), body.domain_names.clone(),
) )
.await .await
@ -129,20 +109,34 @@ pub async fn verify_merchant_creds_for_applepay(
} }
}) })
} }
// Checks whether or not the domain verified is already present in db if not adds it
async fn check_existence_and_add_domain_to_db( async fn check_existence_and_add_domain_to_db(
state: &AppState, state: &AppState,
business_profile_id: String, merchant_id: String,
merchant_connector_id: String,
domain_from_req: Vec<String>, domain_from_req: Vec<String>,
) -> CustomResult<business_profile::BusinessProfile, errors::StorageError> { ) -> CustomResult<Vec<String>, errors::ApiErrorResponse> {
let business_profile = state let key_store = state
.store .store
.find_business_profile_by_profile_id(&business_profile_id) .get_merchant_key_store_by_merchant_id(
.await?; &merchant_id,
let business_profile_to_update = business_profile.clone(); &state.store.get_master_key().to_vec().into(),
let mut already_verified_domains = business_profile )
.await
.to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;
let merchant_connector_account = state
.store
.find_by_merchant_connector_account_merchant_id_merchant_connector_id(
&merchant_id,
&merchant_connector_id,
&key_store,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
let mut already_verified_domains = merchant_connector_account
.applepay_verified_domains .applepay_verified_domains
.clone()
.unwrap_or_default(); .unwrap_or_default();
let mut new_verified_domains: Vec<String> = domain_from_req let mut new_verified_domains: Vec<String> = domain_from_req
@ -151,30 +145,34 @@ async fn check_existence_and_add_domain_to_db(
.collect(); .collect();
already_verified_domains.append(&mut new_verified_domains); already_verified_domains.append(&mut new_verified_domains);
let updated_mca = storage::MerchantConnectorAccountUpdate::Update {
let update_business_profile = business_profile::BusinessProfileUpdateInternal { merchant_id: None,
applepay_verified_domains: Some(already_verified_domains), connector_type: None,
profile_name: Some(business_profile.profile_name), connector_name: None,
modified_at: Some(business_profile.modified_at), connector_account_details: None,
return_url: business_profile.return_url, test_mode: None,
enable_payment_response_hash: Some(business_profile.enable_payment_response_hash), disabled: None,
payment_response_hash_key: business_profile.payment_response_hash_key, merchant_connector_id: None,
redirect_to_merchant_with_http_post: Some( payment_methods_enabled: None,
business_profile.redirect_to_merchant_with_http_post, metadata: None,
), frm_configs: None,
webhook_details: business_profile.webhook_details, connector_webhook_details: None,
metadata: business_profile.metadata, applepay_verified_domains: Some(already_verified_domains.clone()),
routing_algorithm: business_profile.routing_algorithm,
intent_fulfillment_time: business_profile.intent_fulfillment_time,
frm_routing_algorithm: business_profile.frm_routing_algorithm,
payout_routing_algorithm: business_profile.payout_routing_algorithm,
is_recon_enabled: Some(business_profile.is_recon_enabled),
}; };
state state
.store .store
.update_business_profile_by_profile_id(business_profile_to_update, update_business_profile) .update_merchant_connector_account(
merchant_connector_account,
updated_mca.into(),
&key_store,
)
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!("Failed while updating MerchantConnectorAccount: id: {merchant_connector_id}")
})?;
Ok(already_verified_domains.clone())
} }
fn log_applepay_verification_response_if_error( fn log_applepay_verification_response_if_error(

View File

@ -0,0 +1 @@
ALTER TABLE merchant_connector_account DROP COLUMN IF EXISTS applepay_verified_domains;

View File

@ -0,0 +1,2 @@
ALTER TABLE merchant_connector_account
ADD COLUMN IF NOT EXISTS applepay_verified_domains text[];

View File

@ -6725,6 +6725,14 @@
"description": "The business profile this connector must be created in\ndefault value from merchant account is taken if not passed", "description": "The business profile this connector must be created in\ndefault value from merchant account is taken if not passed",
"nullable": true, "nullable": true,
"maxLength": 64 "maxLength": 64
},
"applepay_verified_domains": {
"type": "array",
"items": {
"type": "string"
},
"description": "identifier for the verified domains of a particular connector account",
"nullable": true
} }
} }
}, },