revert: connector_label in webhook url is reverted back to connector_name (#1779)

This commit is contained in:
Hrithikesh
2023-07-25 09:58:28 +05:30
committed by GitHub
parent 4ce53092a6
commit a229c37a7c
7 changed files with 167 additions and 45 deletions

View File

@ -70,6 +70,29 @@ impl MerchantConnectorAccount {
.await
}
#[instrument(skip(conn))]
pub async fn find_by_merchant_id_connector_name(
conn: &PgPooledConn,
merchant_id: &str,
connector_name: &str,
) -> StorageResult<Vec<Self>> {
generics::generic_filter::<
<Self as HasTable>::Table,
_,
<<Self as HasTable>::Table as Table>::PrimaryKey,
_,
>(
conn,
dsl::merchant_id
.eq(merchant_id.to_owned())
.and(dsl::connector_name.eq(connector_name.to_owned())),
None,
None,
None,
)
.await
}
#[instrument(skip(conn))]
pub async fn find_by_merchant_id_merchant_connector_id(
conn: &PgPooledConn,

View File

@ -101,7 +101,7 @@ impl Webhooks {
web::scope("/webhooks")
.app_data(web::Data::new(config))
.service(
web::resource("/{merchant_id}/{connector_label}")
web::resource("/{merchant_id}/{connector_name}")
.route(
web::post().to(webhooks::receive_incoming_webhook::<StripeOutgoingWebhook>),
)

View File

@ -630,18 +630,9 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>(
req: &actix_web::HttpRequest,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
connector_label: &str,
connector_name: &str,
body: actix_web::web::Bytes,
) -> RouterResponse<serde_json::Value> {
let connector_name = connector_label
.split('_') //connector_name will be the first string after splitting connector_label
.next()
.ok_or(errors::ApiErrorResponse::InvalidDataValue {
field_name: "connector_label",
})
.into_report()
.attach_printable("Failed to infer connector_name from connector_label")?;
metrics::WEBHOOK_INCOMING_COUNT.add(
&metrics::CONTEXT,
1,
@ -688,7 +679,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>(
let process_webhook_further = utils::lookup_webhook_event(
&*state.store,
connector_label,
connector_name,
&merchant_account.merchant_id,
&event_type,
)
@ -704,7 +695,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>(
&*state.store,
&request_details,
&merchant_account.merchant_id,
connector_label,
connector_name,
&key_store,
)
.await

View File

@ -1,4 +1,7 @@
use std::cmp::Ordering;
use common_utils::ext_traits::{AsyncExt, ByteSliceExt, Encode};
use diesel_models::errors as storage_errors;
use error_stack::{IntoReport, ResultExt};
use super::{MockDb, Store};
@ -119,6 +122,13 @@ where
key_store: &domain::MerchantKeyStore,
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;
async fn find_merchant_connector_account_by_merchant_id_connector_name(
&self,
merchant_id: &str,
connector_name: &str,
key_store: &domain::MerchantKeyStore,
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;
async fn insert_merchant_connector_account(
&self,
t: domain::MerchantConnectorAccount,
@ -200,6 +210,53 @@ impl MerchantConnectorAccountInterface for Store {
}
}
async fn find_merchant_connector_account_by_merchant_id_connector_name(
&self,
merchant_id: &str,
connector_name: &str,
key_store: &domain::MerchantKeyStore,
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
let find_call = || async {
let conn = connection::pg_connection_read(self).await?;
storage::MerchantConnectorAccount::find_by_merchant_id_connector_name(
&conn,
merchant_id,
connector_name,
)
.await
.map_err(Into::into)
.into_report()
};
let mca_list = find_call().await?;
match mca_list.len().cmp(&1) {
Ordering::Less => {
Err(errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into())
.attach_printable(format!(
"No records found for {} and {}",
merchant_id, connector_name
))
}
Ordering::Greater => Err(errors::StorageError::DatabaseError(
storage_errors::DatabaseError::Others.into(),
))
.into_report()
.attach_printable(format!(
"Found multiple records for {} and {}",
merchant_id, connector_name
)),
Ordering::Equal => match mca_list.first() {
Some(mca) => mca
.to_owned()
.convert(key_store.key.get_inner())
.await
.change_context(errors::StorageError::DeserializationFailed),
None => Err(
errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into(),
),
},
}
}
async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
&self,
merchant_id: &str,
@ -377,7 +434,7 @@ impl MerchantConnectorAccountInterface for MockDb {
.await
.iter()
.find(|account| {
account.merchant_id == merchant_id && account.connector_name == connector
account.merchant_id == merchant_id && account.connector_label == connector
})
.cloned()
.async_map(|account| async {
@ -398,6 +455,51 @@ impl MerchantConnectorAccountInterface for MockDb {
}
}
async fn find_merchant_connector_account_by_merchant_id_connector_name(
&self,
merchant_id: &str,
connector_name: &str,
key_store: &domain::MerchantKeyStore,
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
let mca_list = self
.merchant_connector_accounts
.lock()
.await
.iter()
.filter(|account| {
account.merchant_id == merchant_id && account.connector_name == connector_name
})
.cloned()
.collect::<Vec<_>>();
match mca_list.len().cmp(&1) {
Ordering::Less => {
Err(errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into())
.attach_printable(format!(
"No records found for {} and {}",
merchant_id, connector_name
))
}
Ordering::Greater => Err(errors::StorageError::DatabaseError(
storage_errors::DatabaseError::Others.into(),
))
.into_report()
.attach_printable(format!(
"Found multiple records for {} and {}",
merchant_id, connector_name
)),
Ordering::Equal => match mca_list.first() {
Some(mca) => mca
.to_owned()
.convert(key_store.key.get_inner())
.await
.change_context(errors::StorageError::DeserializationFailed),
None => Err(
errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into(),
),
},
}
}
async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
&self,
merchant_id: &str,

View File

@ -410,7 +410,7 @@ impl Webhooks {
web::scope("/webhooks")
.app_data(web::Data::new(config))
.service(
web::resource("/{merchant_id}/{connector_label}")
web::resource("/{merchant_id}/{connector_name}")
.route(
web::post().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
)

View File

@ -15,7 +15,7 @@ pub async fn receive_incoming_webhook<W: types::OutgoingWebhookType>(
path: web::Path<(String, String)>,
) -> impl Responder {
let flow = Flow::IncomingWebhookReceive;
let (merchant_id, connector_label) = path.into_inner();
let (merchant_id, connector_name) = path.into_inner();
api::server_wrap(
flow,
@ -28,7 +28,7 @@ pub async fn receive_incoming_webhook<W: types::OutgoingWebhookType>(
&req,
auth.merchant_account,
auth.key_store,
&connector_label,
&connector_name,
body,
)
},

View File

@ -11,7 +11,7 @@ use super::ConnectorCommon;
use crate::{
core::errors::{self, CustomResult},
db::StorageInterface,
services,
logger, services,
types::domain,
utils::crypto,
};
@ -79,43 +79,49 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
&self,
db: &dyn StorageInterface,
merchant_id: &str,
connector_label: &str,
connector_name: &str,
key_store: &domain::MerchantKeyStore,
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
let debug_suffix = format!(
"For merchant_id: {}, and connector_label: {}",
merchant_id, connector_label
"For merchant_id: {}, and connector_name: {}",
merchant_id, connector_name
);
let merchant_connector_webhook_details = db
.find_merchant_connector_account_by_merchant_id_connector_label(
let default_secret = "default_secret".to_string();
let merchant_connector_account_result = db
.find_merchant_connector_account_by_merchant_id_connector_name(
merchant_id,
connector_label,
connector_name,
key_store,
)
.await
.change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
.attach_printable_lazy(|| {
format!(
"Fetch merchant_webhook_secret from MCA table failed {}",
debug_suffix
)
})?
.connector_webhook_details;
.await;
let merchant_secret = match merchant_connector_webhook_details {
Some(merchant_connector_webhook_details) => merchant_connector_webhook_details
.parse_value::<MerchantConnectorWebhookDetails>("MerchantConnectorWebhookDetails")
.change_context_lazy(|| errors::ConnectorError::WebhookSourceVerificationFailed)
.attach_printable_lazy(|| {
format!(
"Deserializing MerchantConnectorWebhookDetails failed {}",
debug_suffix
let merchant_secret = match merchant_connector_account_result {
Ok(mca) => match mca.connector_webhook_details {
Some(merchant_connector_webhook_details) => merchant_connector_webhook_details
.parse_value::<MerchantConnectorWebhookDetails>(
"MerchantConnectorWebhookDetails",
)
})?
.merchant_secret
.expose(),
None => "default_secret".to_string(),
.change_context_lazy(|| errors::ConnectorError::WebhookSourceVerificationFailed)
.attach_printable_lazy(|| {
format!(
"Deserializing MerchantConnectorWebhookDetails failed {}",
debug_suffix
)
})?
.merchant_secret
.expose(),
None => default_secret,
},
Err(err) => {
logger::error!(
"Failed to fetch merchant_secret for source verification {}",
debug_suffix
);
logger::error!("DB error = {:?}", err);
default_secret
}
};
//need to fetch merchant secret from config table with caching in future for enhanced performance
//If merchant has not set the secret for webhook source verification, "default_secret" is returned.