Skip to content

Commit

Permalink
feat(router): restricted customer update in payments-confirm and paym…
Browse files Browse the repository at this point in the history
…ents-update call via clientAuth (#1659)

Co-authored-by: Sahkal Poddar <sahkal.poddar@juspay.in>
Co-authored-by: Arun Raj M <jarnura47@gmail.com>
  • Loading branch information
3 people committed Jul 17, 2023
1 parent 5fbd1cc commit 94a5eb3
Show file tree
Hide file tree
Showing 14 changed files with 55 additions and 4 deletions.
4 changes: 3 additions & 1 deletion crates/router/src/core/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub async fn payments_operation_core<F, Req, Op, FData>(
operation: Op,
req: Req,
call_connector_action: CallConnectorAction,
auth_flow: services::AuthFlow,
) -> RouterResult<(PaymentData<F>, Req, Option<domain::Customer>)>
where
F: Send + Clone + Sync,
Expand All @@ -70,7 +71,6 @@ where
let operation: BoxedOperation<'_, F, Req> = Box::new(operation);

tracing::Span::current().record("merchant_id", merchant_account.merchant_id.as_str());

let (operation, validate_result) = operation
.to_validate_request()?
.validate_request(&req, &merchant_account)?;
Expand All @@ -85,6 +85,7 @@ where
validate_result.mandate_type.to_owned(),
&merchant_account,
&key_store,
auth_flow,
)
.await?;

Expand Down Expand Up @@ -246,6 +247,7 @@ where
operation.clone(),
req,
call_connector_action,
auth_flow,
)
.await?;

Expand Down
25 changes: 25 additions & 0 deletions crates/router/src/core/payments/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2550,3 +2550,28 @@ pub async fn get_additional_payment_data(
}
}
}

pub fn validate_customer_access(
payment_intent: &storage::PaymentIntent,
auth_flow: services::AuthFlow,
request: &api::PaymentsRequest,
) -> Result<(), errors::ApiErrorResponse> {
if auth_flow == services::AuthFlow::Client && request.customer_id.is_some() {
let is_not_same_customer = request
.clone()
.customer_id
.and_then(|customer| {
payment_intent
.clone()
.customer_id
.map(|payment_customer| payment_customer != customer)
})
.unwrap_or(false);
if is_not_same_customer {
Err(errors::ApiErrorResponse::GenericUnauthorized {
message: "Unauthorised access to update customer".to_string(),
})?;
}
}
Ok(())
}
2 changes: 2 additions & 0 deletions crates/router/src/core/payments/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::{
core::errors::{self, CustomResult, RouterResult},
db::StorageInterface,
routes::AppState,
services,
types::{
self, api, domain,
storage::{self, enums},
Expand Down Expand Up @@ -94,6 +95,7 @@ pub trait GetTracker<F, D, R>: Send {
mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
mechant_key_store: &domain::MerchantKeyStore,
auth_flow: services::AuthFlow,
) -> RouterResult<(BoxedOperation<'a, F, R>, D, Option<CustomerDetails>)>;
}

Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/core/payments/operations/payment_cancel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
api::{self, PaymentIdTypeExt},
domain,
Expand All @@ -37,6 +38,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsCancelRequest>
_mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsCancelRequest>,
PaymentData<F>,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/core/payments/operations/payment_capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
api::{self, PaymentIdTypeExt},
domain,
Expand All @@ -38,6 +39,7 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
_mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsCaptureRequest>,
payments::PaymentData<F>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
self,
api::{self, PaymentIdTypeExt},
Expand All @@ -39,6 +40,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Co
mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsRequest>,
PaymentData<F>,
Expand Down
6 changes: 4 additions & 2 deletions crates/router/src/core/payments/operations/payment_confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
self,
api::{self, PaymentIdTypeExt},
Expand All @@ -28,7 +29,6 @@ use crate::{
#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(ops = "all", flow = "authorize")]
pub struct PaymentConfirm;

#[async_trait]
impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for PaymentConfirm {
#[instrument(skip_all)]
Expand All @@ -40,6 +40,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsRequest>,
PaymentData<F>,
Expand All @@ -59,6 +60,8 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
.await
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

helpers::validate_customer_access(&payment_intent, auth_flow, request)?;

helpers::validate_payment_status_against_not_allowed_statuses(
&payment_intent.status,
&[
Expand Down Expand Up @@ -499,7 +502,6 @@ impl<F: Send + Clone> ValidateRequest<F, api::PaymentsRequest> for PaymentConfir
operations::ValidateResult<'a>,
)> {
helpers::validate_customer_details_in_request(request)?;

let given_payment_id = match &request.payment_id {
Some(id_type) => Some(
id_type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
merchant_key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsRequest>,
PaymentData<F>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
self,
api::{self, enums as api_enums, PaymentIdTypeExt},
Expand Down Expand Up @@ -71,6 +72,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym
_mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
_mechant_key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::VerifyRequest>,
PaymentData<F>,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/core/payments/operations/payment_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
api::{self, PaymentIdTypeExt},
domain,
Expand All @@ -40,6 +41,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
_mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsSessionRequest>,
PaymentData<F>,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/core/payments/operations/payment_start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
api::{self, PaymentIdTypeExt},
domain,
Expand All @@ -36,6 +37,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f
_mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
mechant_key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsStartRequest>,
PaymentData<F>,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/core/payments/operations/payment_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
api, domain,
storage::{self, enums},
Expand Down Expand Up @@ -163,6 +164,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRetrieveRequest
_mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
_auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsRetrieveRequest>,
PaymentData<F>,
Expand Down
5 changes: 4 additions & 1 deletion crates/router/src/core/payments/operations/payment_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
},
db::StorageInterface,
routes::AppState,
services,
types::{
api::{self, PaymentIdTypeExt},
domain,
Expand All @@ -39,6 +40,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
mandate_type: Option<api::MandateTransactionType>,
merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore,
auth_flow: services::AuthFlow,
) -> RouterResult<(
BoxedOperation<'a, F, api::PaymentsRequest>,
PaymentData<F>,
Expand All @@ -63,6 +65,8 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
.setup_future_usage
.or(payment_intent.setup_future_usage);

helpers::validate_customer_access(&payment_intent, auth_flow, request)?;

helpers::validate_card_data(request.payment_method_data.clone())?;

helpers::validate_payment_status_against_not_allowed_statuses(
Expand Down Expand Up @@ -548,7 +552,6 @@ impl<F: Send + Clone> ValidateRequest<F, api::PaymentsRequest> for PaymentUpdate
operations::ValidateResult<'a>,
)> {
helpers::validate_customer_details_in_request(request)?;

let given_payment_id = match &request.payment_id {
Some(id_type) => Some(
id_type
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/scheduler/workflows/payment_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
errors,
routes::AppState,
scheduler::{consumer, process_data, utils},
services,
types::{
api,
storage::{self, enums, ProcessTrackerExt},
Expand Down Expand Up @@ -54,6 +55,7 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow {
operations::PaymentStatus,
tracking_data.clone(),
payment_flows::CallConnectorAction::Trigger,
services::AuthFlow::Client,
)
.await?;

Expand Down

0 comments on commit 94a5eb3

Please sign in to comment.