feat: fetch merchant key store only once per session (#1400)

Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com>
This commit is contained in:
Kartikeya Hegde
2023-06-22 14:40:28 +05:30
committed by GitHub
parent 957d5e0f62
commit d321aa1f72
65 changed files with 979 additions and 498 deletions

View File

@ -97,11 +97,9 @@ pub async fn get_address_for_payment_request(
address_id: Option<&str>,
merchant_id: &str,
customer_id: Option<&String>,
merchant_key_store: &domain::MerchantKeyStore,
) -> CustomResult<Option<domain::Address>, errors::ApiErrorResponse> {
let key = types::get_merchant_enc_key(db, merchant_id.to_string())
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting key for encryption")?;
let key = merchant_key_store.key.get_inner().peek();
Ok(match req_address {
Some(address) => {
@ -118,49 +116,49 @@ pub async fn get_address_for_payment_request(
.address
.as_ref()
.and_then(|value| value.line1.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
line2: address
.address
.as_ref()
.and_then(|value| value.line2.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
line3: address
.address
.as_ref()
.and_then(|value| value.line3.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
state: address
.address
.as_ref()
.and_then(|value| value.state.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
zip: address
.address
.as_ref()
.and_then(|value| value.zip.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
first_name: address
.address
.as_ref()
.and_then(|value| value.first_name.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
last_name: address
.address
.as_ref()
.and_then(|value| value.last_name.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
phone_number: address
.phone
.as_ref()
.and_then(|value| value.number.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
country_code: address
.phone
@ -172,7 +170,7 @@ pub async fn get_address_for_payment_request(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while encrypting address")?;
Some(
db.update_address(id.to_owned(), address_update)
db.update_address(id.to_owned(), address_update, merchant_key_store)
.await
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
)
@ -190,7 +188,7 @@ pub async fn get_address_for_payment_request(
.phone
.as_ref()
.and_then(|a| a.number.clone())
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
country_code: address
.phone
@ -203,40 +201,41 @@ pub async fn get_address_for_payment_request(
country: address_details.country,
line1: address_details
.line1
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
line2: address_details
.line2
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
line3: address_details
.line3
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
id: None,
state: address_details
.state
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
created_at: common_utils::date_time::now(),
first_name: address_details
.first_name
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
last_name: address_details
.last_name
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
modified_at: common_utils::date_time::now(),
zip: address_details
.zip
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
})
}
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while encrypting address while insert")?,
merchant_key_store,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
@ -246,7 +245,7 @@ pub async fn get_address_for_payment_request(
}
}
None => match address_id {
Some(id) => Some(db.find_address(id).await)
Some(id) => Some(db.find_address(id, merchant_key_store).await)
.transpose()
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
None => None,
@ -257,10 +256,11 @@ pub async fn get_address_for_payment_request(
pub async fn get_address_by_id(
db: &dyn StorageInterface,
address_id: Option<String>,
merchant_key_store: &domain::MerchantKeyStore,
) -> CustomResult<Option<domain::Address>, errors::ApiErrorResponse> {
match address_id {
None => Ok(None),
Some(address_id) => Ok(db.find_address(&address_id).await.ok()),
Some(address_id) => Ok(db.find_address(&address_id, merchant_key_store).await.ok()),
}
}
@ -870,12 +870,17 @@ pub async fn get_customer_from_details<F: Clone>(
customer_id: Option<String>,
merchant_id: &str,
payment_data: &mut PaymentData<F>,
merchant_key_store: &domain::MerchantKeyStore,
) -> CustomResult<Option<domain::Customer>, errors::StorageError> {
match customer_id {
None => Ok(None),
Some(c_id) => {
let customer = db
.find_customer_optional_by_customer_id_merchant_id(&c_id, merchant_id)
.find_customer_optional_by_customer_id_merchant_id(
&c_id,
merchant_id,
merchant_key_store,
)
.await?;
payment_data.email = payment_data.email.clone().or_else(|| {
customer.as_ref().and_then(|inner| {
@ -1010,6 +1015,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
payment_data: &mut PaymentData<F>,
req: Option<CustomerDetails>,
merchant_id: &str,
key_store: &domain::MerchantKeyStore,
) -> CustomResult<(BoxedOperation<'a, F, R>, Option<domain::Customer>), errors::StorageError> {
let request_customer_details = req
.get_required_value("customer")
@ -1022,7 +1028,11 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
let optional_customer = match customer_id {
Some(customer_id) => {
let customer_data = db
.find_customer_optional_by_customer_id_merchant_id(&customer_id, merchant_id)
.find_customer_optional_by_customer_id_merchant_id(
&customer_id,
merchant_id,
key_store,
)
.await?;
Some(match customer_data {
@ -1033,12 +1043,12 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
| request_customer_details.phone.is_some()
| request_customer_details.phone_country_code.is_some()
{
let key = types::get_merchant_enc_key(db, merchant_id.to_string()).await?;
let key = key_store.key.get_inner().peek();
let customer_update = async {
Ok(Update {
name: request_customer_details
.name
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
email: request_customer_details
.email
@ -1046,14 +1056,14 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
.async_lift(|inner| {
types::encrypt_optional(
inner.map(|inner| inner.expose()),
&key,
key,
)
})
.await?,
phone: request_customer_details
.phone
.clone()
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
phone_country_code: request_customer_details.phone_country_code,
description: None,
@ -1069,6 +1079,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
customer_id,
merchant_id.to_string(),
customer_update,
key_store,
)
.await
} else {
@ -1076,26 +1087,26 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
}
}
None => {
let key = types::get_merchant_enc_key(db, merchant_id.to_string()).await?;
let new_customer = async {
let key = key_store.key.get_inner().peek();
Ok(domain::Customer {
customer_id: customer_id.to_string(),
merchant_id: merchant_id.to_string(),
name: request_customer_details
.name
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
email: request_customer_details
.email
.clone()
.async_lift(|inner| {
types::encrypt_optional(inner.map(|inner| inner.expose()), &key)
types::encrypt_optional(inner.map(|inner| inner.expose()), key)
})
.await?,
phone: request_customer_details
.phone
.clone()
.async_lift(|inner| types::encrypt_optional(inner, &key))
.async_lift(|inner| types::encrypt_optional(inner, key))
.await?,
phone_country_code: request_customer_details.phone_country_code.clone(),
description: None,
@ -1110,15 +1121,19 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
.change_context(errors::StorageError::SerializationFailed)
.attach_printable("Failed while encrypting Customer while insert")?;
metrics::CUSTOMER_CREATED.add(&metrics::CONTEXT, 1, &[]);
db.insert_customer(new_customer).await
db.insert_customer(new_customer, key_store).await
}
})
}
None => match &payment_data.payment_intent.customer_id {
None => None,
Some(customer_id) => db
.find_customer_optional_by_customer_id_merchant_id(customer_id, merchant_id)
.await? // if customer_id is present in payment_intent but not found in customer table then shouldn't an error be thrown ?
.find_customer_optional_by_customer_id_merchant_id(
customer_id,
merchant_id,
key_store,
)
.await?
.map(Ok),
},
};
@ -2036,6 +2051,7 @@ pub async fn get_merchant_connector_account(
merchant_id: &str,
connector_label: &str,
creds_identifier: Option<String>,
key_store: &domain::MerchantKeyStore,
) -> RouterResult<MerchantConnectorAccountType> {
let db = &*state.store;
match creds_identifier {
@ -2075,6 +2091,7 @@ pub async fn get_merchant_connector_account(
.find_merchant_connector_account_by_merchant_id_connector_label(
merchant_id,
connector_label,
key_store,
)
.await
.map(MerchantConnectorAccountType::DbVal)