mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
refactor(router): Refactored Authentication (#327)
This commit is contained in:
@ -8,7 +8,7 @@ use crate::{
|
|||||||
compatibility::{stripe::errors, wrap},
|
compatibility::{stripe::errors, wrap},
|
||||||
core::customers,
|
core::customers,
|
||||||
routes,
|
routes,
|
||||||
services::api,
|
services::{api, authentication as auth},
|
||||||
types::api::customers as customer_types,
|
types::api::customers as customer_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ pub async fn customer_create(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
customers::create_customer(&*state.store, merchant_account, req)
|
customers::create_customer(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ pub async fn customer_retrieve(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
customers::retrieve_customer(&*state.store, merchant_account, req)
|
customers::retrieve_customer(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ pub async fn customer_update(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
customers::update_customer(&*state.store, merchant_account, req)
|
customers::update_customer(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ pub async fn customer_delete(
|
|||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
customers::delete_customer,
|
customers::delete_customer,
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use crate::{
|
|||||||
compatibility::{stripe::errors, wrap},
|
compatibility::{stripe::errors, wrap},
|
||||||
core::payments,
|
core::payments,
|
||||||
routes,
|
routes,
|
||||||
services::api,
|
services::{api, authentication as auth},
|
||||||
types::api::{self as api_types},
|
types::api::{self as api_types},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ pub async fn payment_intents_create(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -78,11 +78,10 @@ pub async fn payment_intents_retrieve(
|
|||||||
param: None,
|
param: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_type = match api::get_auth_type(&req) {
|
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||||
Ok(auth_type) => auth_type,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(report!(err)),
|
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
@ -107,7 +106,7 @@ pub async fn payment_intents_retrieve(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -138,12 +137,11 @@ pub async fn payment_intents_update(
|
|||||||
|
|
||||||
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(payment_id));
|
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(payment_id));
|
||||||
|
|
||||||
let auth_type;
|
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||||
(payload, auth_type) = match api::get_auth_type_and_check_client_secret(&req, payload) {
|
Ok(auth) => auth,
|
||||||
Ok(values) => values,
|
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
@ -168,7 +166,7 @@ pub async fn payment_intents_update(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -200,12 +198,12 @@ pub async fn payment_intents_confirm(
|
|||||||
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(payment_id));
|
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(payment_id));
|
||||||
payload.confirm = Some(true);
|
payload.confirm = Some(true);
|
||||||
|
|
||||||
let auth_type;
|
let (auth_type, auth_flow) =
|
||||||
(payload, auth_type) = match api::get_auth_type_and_check_client_secret(&req, payload) {
|
match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
|
||||||
Ok(values) => values,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
@ -230,7 +228,7 @@ pub async fn payment_intents_confirm(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -280,7 +278,7 @@ pub async fn payment_intents_capture(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -307,11 +305,11 @@ pub async fn payment_intents_cancel(
|
|||||||
let mut payload: payment_types::PaymentsCancelRequest = stripe_payload.into();
|
let mut payload: payment_types::PaymentsCancelRequest = stripe_payload.into();
|
||||||
payload.payment_id = payment_id;
|
payload.payment_id = payment_id;
|
||||||
|
|
||||||
let auth_type = match api::get_auth_type(&req) {
|
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||||
Ok(values) => values,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
@ -335,7 +333,7 @@ pub async fn payment_intents_cancel(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -366,7 +364,7 @@ pub async fn payment_intent_list(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
payments::list_payments(&*state.store, merchant_account, req)
|
payments::list_payments(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use crate::{
|
|||||||
compatibility::{stripe::errors, wrap},
|
compatibility::{stripe::errors, wrap},
|
||||||
core::refunds,
|
core::refunds,
|
||||||
routes,
|
routes,
|
||||||
services::api,
|
services::authentication as auth,
|
||||||
types::api::refunds as refund_types,
|
types::api::refunds as refund_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ pub async fn refund_create(
|
|||||||
&req,
|
&req,
|
||||||
create_refund_req,
|
create_refund_req,
|
||||||
refunds::refund_create_core,
|
refunds::refund_create_core,
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ pub async fn refund_retrieve(
|
|||||||
refunds::refund_retrieve_core,
|
refunds::refund_retrieve_core,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ pub async fn refund_update(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
refunds::refund_update_core(&*state.store, merchant_account, &refund_id, req)
|
refunds::refund_update_core(&*state.store, merchant_account, &refund_id, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use crate::{
|
|||||||
compatibility::{stripe::errors, wrap},
|
compatibility::{stripe::errors, wrap},
|
||||||
core::payments,
|
core::payments,
|
||||||
routes,
|
routes,
|
||||||
services::api,
|
services::{api, authentication as auth},
|
||||||
types::api as api_types,
|
types::api as api_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ pub async fn setup_intents_create(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -75,11 +75,10 @@ pub async fn setup_intents_retrieve(
|
|||||||
param: None,
|
param: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_type = match api::get_auth_type(&req) {
|
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||||
Ok(auth_type) => auth_type,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(report!(err)),
|
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
@ -104,7 +103,7 @@ pub async fn setup_intents_retrieve(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -131,12 +130,12 @@ pub async fn setup_intents_update(
|
|||||||
let mut payload: payment_types::PaymentsRequest = stripe_payload.into();
|
let mut payload: payment_types::PaymentsRequest = stripe_payload.into();
|
||||||
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id));
|
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id));
|
||||||
|
|
||||||
let auth_type;
|
let (auth_type, auth_flow) =
|
||||||
(payload, auth_type) = match api::get_auth_type_and_check_client_secret(&req, payload) {
|
match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
|
||||||
Ok(values) => values,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
@ -161,7 +160,7 @@ pub async fn setup_intents_update(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -189,12 +188,12 @@ pub async fn setup_intents_confirm(
|
|||||||
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id));
|
payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id));
|
||||||
payload.confirm = Some(true);
|
payload.confirm = Some(true);
|
||||||
|
|
||||||
let auth_type;
|
let (auth_type, auth_flow) =
|
||||||
(payload, auth_type) = match api::get_auth_type_and_check_client_secret(&req, payload) {
|
match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
|
||||||
Ok(values) => values,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
wrap::compatibility_api_wrap::<
|
wrap::compatibility_api_wrap::<
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
@ -219,7 +218,7 @@ pub async fn setup_intents_confirm(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,28 +8,25 @@ use serde::Serialize;
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::errors::{self, RouterResult},
|
core::errors::{self, RouterResult},
|
||||||
routes,
|
routes,
|
||||||
services::{api, logger},
|
services::{api, authentication as auth, logger},
|
||||||
types::storage,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[instrument(skip(request, payload, state, func))]
|
#[instrument(skip(request, payload, state, func, api_authentication))]
|
||||||
pub async fn compatibility_api_wrap<'a, 'b, A, T, Q, F, Fut, S, E>(
|
pub async fn compatibility_api_wrap<'a, 'b, U, T, Q, F, Fut, S, E>(
|
||||||
state: &'b routes::AppState,
|
state: &'b routes::AppState,
|
||||||
request: &'a HttpRequest,
|
request: &'a HttpRequest,
|
||||||
payload: T,
|
payload: T,
|
||||||
func: F,
|
func: F,
|
||||||
api_authentication: A,
|
api_authentication: &dyn auth::AuthenticateAndFetch<U>,
|
||||||
) -> HttpResponse
|
) -> HttpResponse
|
||||||
where
|
where
|
||||||
A: Into<api::ApiAuthentication<'a>> + std::fmt::Debug,
|
F: Fn(&'b routes::AppState, U, T) -> Fut,
|
||||||
F: Fn(&'b routes::AppState, storage::MerchantAccount, T) -> Fut,
|
|
||||||
Fut: Future<Output = RouterResult<api::BachResponse<Q>>>,
|
Fut: Future<Output = RouterResult<api::BachResponse<Q>>>,
|
||||||
Q: Serialize + std::fmt::Debug + 'a,
|
Q: Serialize + std::fmt::Debug + 'a,
|
||||||
S: From<Q> + Serialize,
|
S: From<Q> + Serialize,
|
||||||
E: From<errors::ApiErrorResponse> + Serialize + error_stack::Context + actix_web::ResponseError,
|
E: From<errors::ApiErrorResponse> + Serialize + error_stack::Context + actix_web::ResponseError,
|
||||||
T: std::fmt::Debug,
|
T: std::fmt::Debug,
|
||||||
{
|
{
|
||||||
let api_authentication = api_authentication.into();
|
|
||||||
let resp = api::server_wrap_util(state, request, payload, func, api_authentication).await;
|
let resp = api::server_wrap_util(state, request, payload, func, api_authentication).await;
|
||||||
match resp {
|
match resp {
|
||||||
Ok(api::BachResponse::Json(router_resp)) => {
|
Ok(api::BachResponse::Json(router_resp)) => {
|
||||||
|
|||||||
@ -593,37 +593,6 @@ pub(crate) async fn call_payment_method(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn client_secret_auth<P>(
|
|
||||||
payload: P,
|
|
||||||
auth_type: &services::api::MerchantAuthentication<'_>,
|
|
||||||
) -> RouterResult<P>
|
|
||||||
where
|
|
||||||
P: services::Authenticate,
|
|
||||||
{
|
|
||||||
match auth_type {
|
|
||||||
services::MerchantAuthentication::PublishableKey => {
|
|
||||||
payload
|
|
||||||
.get_client_secret()
|
|
||||||
.check_value_present("client_secret")
|
|
||||||
.change_context(errors::ApiErrorResponse::MissingRequiredField {
|
|
||||||
field_name: "client_secret".to_owned(),
|
|
||||||
})?;
|
|
||||||
Ok(payload)
|
|
||||||
}
|
|
||||||
services::api::MerchantAuthentication::ApiKey => {
|
|
||||||
if payload.get_client_secret().is_some() {
|
|
||||||
Err(report!(errors::ApiErrorResponse::InvalidRequestData {
|
|
||||||
message: "client_secret is not a valid parameter".to_owned(),
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
Ok(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Err(report!(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Unexpected Auth type")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_customer_from_details(
|
pub async fn get_customer_from_details(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn StorageInterface,
|
||||||
customer_id: Option<String>,
|
customer_id: Option<String>,
|
||||||
|
|||||||
@ -2,7 +2,11 @@ use actix_web::{web, HttpRequest, HttpResponse};
|
|||||||
use router_env::{instrument, tracing, Flow};
|
use router_env::{instrument, tracing, Flow};
|
||||||
|
|
||||||
use super::app::AppState;
|
use super::app::AppState;
|
||||||
use crate::{core::admin::*, services::api, types::api::admin};
|
use crate::{
|
||||||
|
core::admin::*,
|
||||||
|
services::{api, authentication as auth},
|
||||||
|
types::api::admin,
|
||||||
|
};
|
||||||
|
|
||||||
/// Merchant Account - Create
|
/// Merchant Account - Create
|
||||||
///
|
///
|
||||||
@ -28,7 +32,7 @@ pub async fn merchant_account_create(
|
|||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
json_payload.into_inner(),
|
||||||
|state, _, req| create_merchant_account(&*state.store, req),
|
|state, _, req| create_merchant_account(&*state.store, req),
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -49,7 +53,7 @@ pub async fn retrieve_merchant_account(
|
|||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
|state, _, req| get_merchant_account(&*state.store, req),
|
|state, _, req| get_merchant_account(&*state.store, req),
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -68,7 +72,7 @@ pub async fn update_merchant_account(
|
|||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
json_payload.into_inner(),
|
||||||
|state, _, req| merchant_account_update(&*state.store, &merchant_id, req),
|
|state, _, req| merchant_account_update(&*state.store, &merchant_id, req),
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -89,7 +93,7 @@ pub async fn delete_merchant_account(
|
|||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
|state, _, req| merchant_account_delete(&*state.store, req.merchant_id),
|
|state, _, req| merchant_account_delete(&*state.store, req.merchant_id),
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -109,7 +113,7 @@ pub async fn payment_connector_create(
|
|||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
json_payload.into_inner(),
|
||||||
|state, _, req| create_payment_connector(&*state.store, req, &merchant_id),
|
|state, _, req| create_payment_connector(&*state.store, req, &merchant_id),
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -134,7 +138,7 @@ pub async fn payment_connector_retrieve(
|
|||||||
|state, _, req| {
|
|state, _, req| {
|
||||||
retrieve_payment_connector(&*state.store, req.merchant_id, req.merchant_connector_id)
|
retrieve_payment_connector(&*state.store, req.merchant_id, req.merchant_connector_id)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -152,7 +156,7 @@ pub async fn payment_connector_list(
|
|||||||
&req,
|
&req,
|
||||||
merchant_id,
|
merchant_id,
|
||||||
|state, _, merchant_id| list_payment_connectors(&*state.store, merchant_id),
|
|state, _, merchant_id| list_payment_connectors(&*state.store, merchant_id),
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -173,7 +177,7 @@ pub async fn payment_connector_update(
|
|||||||
|state, _, req| {
|
|state, _, req| {
|
||||||
update_payment_connector(&*state.store, &merchant_id, merchant_connector_id, req)
|
update_payment_connector(&*state.store, &merchant_id, merchant_connector_id, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -198,7 +202,7 @@ pub async fn payment_connector_delete(
|
|||||||
|state, _, req| {
|
|state, _, req| {
|
||||||
delete_payment_connector(&*state.store, req.merchant_id, req.merchant_connector_id)
|
delete_payment_connector(&*state.store, req.merchant_id, req.merchant_connector_id)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::AdminApiKey,
|
&auth::AdminApiAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use router_env::{instrument, tracing, Flow};
|
|||||||
use super::app::AppState;
|
use super::app::AppState;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::customers::*,
|
core::customers::*,
|
||||||
services::{self, api},
|
services::{api, authentication as auth},
|
||||||
types::api::customers,
|
types::api::customers,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ pub async fn customers_create(
|
|||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
json_payload.into_inner(),
|
||||||
|state, merchant_account, req| create_customer(&*state.store, merchant_account, req),
|
|state, merchant_account, req| create_customer(&*state.store, merchant_account, req),
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -36,22 +36,19 @@ pub async fn customers_retrieve(
|
|||||||
customer_id: path.into_inner(),
|
customer_id: path.into_inner(),
|
||||||
})
|
})
|
||||||
.into_inner();
|
.into_inner();
|
||||||
let auth_type = match services::authenticate_eph_key(
|
|
||||||
&req,
|
let auth =
|
||||||
&*state.store,
|
match auth::is_ephemeral_auth(req.headers(), &*state.store, &payload.customer_id).await {
|
||||||
payload.customer_id.clone(),
|
Ok(auth) => auth,
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(auth_type) => auth_type,
|
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
&state,
|
&state,
|
||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
|state, merchant_account, req| retrieve_customer(&*state.store, merchant_account, req),
|
|state, merchant_account, req| retrieve_customer(&*state.store, merchant_account, req),
|
||||||
auth_type,
|
&*auth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -71,7 +68,7 @@ pub async fn customers_update(
|
|||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
json_payload.into_inner(),
|
||||||
|state, merchant_account, req| update_customer(&*state.store, merchant_account, req),
|
|state, merchant_account, req| update_customer(&*state.store, merchant_account, req),
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -87,14 +84,7 @@ pub async fn customers_delete(
|
|||||||
customer_id: path.into_inner(),
|
customer_id: path.into_inner(),
|
||||||
})
|
})
|
||||||
.into_inner();
|
.into_inner();
|
||||||
api::server_wrap(
|
api::server_wrap(&state, &req, payload, delete_customer, &auth::ApiKeyAuth).await
|
||||||
&state,
|
|
||||||
&req,
|
|
||||||
payload,
|
|
||||||
delete_customer,
|
|
||||||
api::MerchantAuthentication::ApiKey,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all, fields(flow = ?Flow::CustomersGetMandates))]
|
#[instrument(skip_all, fields(flow = ?Flow::CustomersGetMandates))]
|
||||||
@ -115,7 +105,7 @@ pub async fn get_customer_mandates(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
crate::core::mandate::get_customer_mandates(state, merchant_account, req)
|
crate::core::mandate::get_customer_mandates(state, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,11 @@ use actix_web::{web, HttpRequest, HttpResponse};
|
|||||||
use router_env::{instrument, tracing, Flow};
|
use router_env::{instrument, tracing, Flow};
|
||||||
|
|
||||||
use super::AppState;
|
use super::AppState;
|
||||||
use crate::{core::payments::helpers, services::api, types::api::customers};
|
use crate::{
|
||||||
|
core::payments::helpers,
|
||||||
|
services::{api, authentication as auth},
|
||||||
|
types::api::customers,
|
||||||
|
};
|
||||||
|
|
||||||
#[instrument(skip_all, fields(flow = ?Flow::EphemeralKeyCreate))]
|
#[instrument(skip_all, fields(flow = ?Flow::EphemeralKeyCreate))]
|
||||||
pub async fn ephemeral_key_create(
|
pub async fn ephemeral_key_create(
|
||||||
@ -18,7 +22,7 @@ pub async fn ephemeral_key_create(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
helpers::make_ephemeral_key(state, req.customer_id, merchant_account.merchant_id)
|
helpers::make_ephemeral_key(state, req.customer_id, merchant_account.merchant_id)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -35,7 +39,7 @@ pub async fn ephemeral_key_delete(
|
|||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
|state, _, req| helpers::delete_ephemeral_key(&*state.store, req),
|
|state, _, req| helpers::delete_ephemeral_key(&*state.store, req),
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,11 @@ use actix_web::{web, HttpRequest, HttpResponse};
|
|||||||
use router_env::{instrument, tracing, Flow};
|
use router_env::{instrument, tracing, Flow};
|
||||||
|
|
||||||
use super::app::AppState;
|
use super::app::AppState;
|
||||||
use crate::{core::mandate, services::api, types::api::mandates};
|
use crate::{
|
||||||
|
core::mandate,
|
||||||
|
services::{api, authentication as auth},
|
||||||
|
types::api::mandates,
|
||||||
|
};
|
||||||
|
|
||||||
#[instrument(skip_all, fields(flow = ?Flow::MandatesRetrieve))]
|
#[instrument(skip_all, fields(flow = ?Flow::MandatesRetrieve))]
|
||||||
// #[get("/{id}")]
|
// #[get("/{id}")]
|
||||||
@ -19,7 +23,7 @@ pub async fn get_mandate(
|
|||||||
&req,
|
&req,
|
||||||
mandate_id,
|
mandate_id,
|
||||||
mandate::get_mandate,
|
mandate::get_mandate,
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -41,7 +45,7 @@ pub async fn revoke_mandate(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
mandate::revoke_mandate(&*state.store, merchant_account, req)
|
mandate::revoke_mandate(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,7 @@ use router_env::{instrument, tracing, Flow};
|
|||||||
use super::app::AppState;
|
use super::app::AppState;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::payment_methods::cards,
|
core::payment_methods::cards,
|
||||||
services,
|
services::{api, authentication as auth},
|
||||||
services::api,
|
|
||||||
types::api::payment_methods::{self, PaymentMethodId},
|
types::api::payment_methods::{self, PaymentMethodId},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ pub async fn create_payment_method_api(
|
|||||||
|state, merchant_account, req| async move {
|
|state, merchant_account, req| async move {
|
||||||
cards::add_payment_method(state, req, &merchant_account).await
|
cards::add_payment_method(state, req, &merchant_account).await
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -36,11 +35,11 @@ pub async fn list_payment_method_api(
|
|||||||
_merchant_id: web::Path<String>,
|
_merchant_id: web::Path<String>,
|
||||||
json_payload: web::Query<payment_methods::ListPaymentMethodRequest>,
|
json_payload: web::Query<payment_methods::ListPaymentMethodRequest>,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
//let merchant_id = merchant_id.into_inner();
|
let payload = json_payload.into_inner();
|
||||||
let (payload, auth_type) =
|
|
||||||
match api::get_auth_type_and_check_client_secret(&req, json_payload.into_inner()) {
|
let (auth, _) = match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
|
||||||
Ok(values) => values,
|
Ok((auth, _auth_flow)) => (auth, _auth_flow),
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(e) => return api::log_and_return_error_response(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
@ -50,7 +49,7 @@ pub async fn list_payment_method_api(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
cards::list_payment_methods(&*state.store, merchant_account, req)
|
cards::list_payment_methods(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -65,8 +64,8 @@ pub async fn list_customer_payment_method_api(
|
|||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let customer_id = customer_id.into_inner().0;
|
let customer_id = customer_id.into_inner().0;
|
||||||
|
|
||||||
let auth_type =
|
let auth_type = match auth::is_ephemeral_auth(req.headers(), &*state.store, &customer_id).await
|
||||||
match services::authenticate_eph_key(&req, &*state.store, customer_id.clone()).await {
|
{
|
||||||
Ok(auth_type) => auth_type,
|
Ok(auth_type) => auth_type,
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
};
|
};
|
||||||
@ -78,7 +77,7 @@ pub async fn list_customer_payment_method_api(
|
|||||||
|state, merchant_account, _| {
|
|state, merchant_account, _| {
|
||||||
cards::list_customer_payment_method(state, merchant_account, &customer_id)
|
cards::list_customer_payment_method(state, merchant_account, &customer_id)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -100,7 +99,7 @@ pub async fn payment_method_retrieve_api(
|
|||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
|state, merchant_account, pm| cards::retrieve_payment_method(state, pm, merchant_account),
|
|state, merchant_account, pm| cards::retrieve_payment_method(state, pm, merchant_account),
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -126,7 +125,7 @@ pub async fn payment_method_update_api(
|
|||||||
&payment_method_id,
|
&payment_method_id,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -146,7 +145,7 @@ pub async fn payment_method_delete_api(
|
|||||||
&req,
|
&req,
|
||||||
pm,
|
pm,
|
||||||
cards::delete_payment_method,
|
cards::delete_payment_method,
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use actix_web::{web, Responder};
|
use actix_web::{web, Responder};
|
||||||
use error_stack::report;
|
use error_stack::report;
|
||||||
use router_env::{instrument, tracing, Flow};
|
use router_env::{instrument, tracing, Flow};
|
||||||
@ -7,7 +5,7 @@ use router_env::{instrument, tracing, Flow};
|
|||||||
use crate::{
|
use crate::{
|
||||||
self as app,
|
self as app,
|
||||||
core::{errors::http_not_implemented, payments},
|
core::{errors::http_not_implemented, payments},
|
||||||
services::api,
|
services::{api, authentication as auth},
|
||||||
types::api::{self as api_types, enums as api_enums, payments as payment_types},
|
types::api::{self as api_types, enums as api_enums, payments as payment_types},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,7 +35,7 @@ pub async fn payments_create(
|
|||||||
api::AuthFlow::Merchant,
|
api::AuthFlow::Merchant,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -69,7 +67,7 @@ pub async fn payments_start(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::MerchantId(Cow::Borrowed(&merchant_id)),
|
&auth::MerchantIdAuth(merchant_id),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -89,11 +87,10 @@ pub async fn payments_retrieve(
|
|||||||
param: None,
|
param: None,
|
||||||
connector: None,
|
connector: None,
|
||||||
};
|
};
|
||||||
let auth_type = match api::get_auth_type(&req) {
|
let (auth_type, _auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||||
Ok(auth_type) => auth_type,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(report!(err)),
|
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||||
};
|
};
|
||||||
let _auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
&state,
|
&state,
|
||||||
@ -110,7 +107,7 @@ pub async fn payments_retrieve(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -133,14 +130,11 @@ pub async fn payments_update(
|
|||||||
|
|
||||||
payload.payment_id = Some(payment_types::PaymentIdType::PaymentIntentId(payment_id));
|
payload.payment_id = Some(payment_types::PaymentIdType::PaymentIntentId(payment_id));
|
||||||
|
|
||||||
let auth_type;
|
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||||
(payload, auth_type) = match api::get_auth_type_and_check_client_secret(&req, payload) {
|
Ok(auth) => auth,
|
||||||
Ok(values) => values,
|
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
|
||||||
};
|
};
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
|
|
||||||
// return http_not_implemented();
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
&state,
|
&state,
|
||||||
&req,
|
&req,
|
||||||
@ -154,7 +148,7 @@ pub async fn payments_update(
|
|||||||
auth_flow,
|
auth_flow,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -177,13 +171,12 @@ pub async fn payments_confirm(
|
|||||||
payload.payment_id = Some(payment_types::PaymentIdType::PaymentIntentId(payment_id));
|
payload.payment_id = Some(payment_types::PaymentIdType::PaymentIntentId(payment_id));
|
||||||
payload.confirm = Some(true);
|
payload.confirm = Some(true);
|
||||||
|
|
||||||
let auth_type;
|
let (auth_type, auth_flow) =
|
||||||
(payload, auth_type) = match api::get_auth_type_and_check_client_secret(&req, payload) {
|
match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
|
||||||
Ok(values) => values,
|
Ok(auth) => auth,
|
||||||
Err(err) => return api::log_and_return_error_response(err),
|
Err(e) => return api::log_and_return_error_response(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_flow = api::get_auth_flow(&auth_type);
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
&state,
|
&state,
|
||||||
&req,
|
&req,
|
||||||
@ -197,7 +190,7 @@ pub async fn payments_confirm(
|
|||||||
auth_flow,
|
auth_flow,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth_type,
|
&*auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -230,7 +223,7 @@ pub async fn payments_capture(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -264,7 +257,7 @@ pub async fn payments_connector_session(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::PublishableKey,
|
&auth::PublishableKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -296,7 +289,7 @@ pub async fn payments_response(
|
|||||||
req,
|
req,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::MerchantId(Cow::Borrowed(&merchant_id)),
|
&auth::MerchantIdAuth(merchant_id),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -328,7 +321,7 @@ pub async fn payments_cancel(
|
|||||||
payments::CallConnectorAction::Trigger,
|
payments::CallConnectorAction::Trigger,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -348,7 +341,7 @@ pub async fn payments_list(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
payments::list_payments(&*state.store, merchant_account, req)
|
payments::list_payments(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,11 @@ use actix_web::{web, HttpRequest, HttpResponse};
|
|||||||
use router_env::{instrument, tracing, Flow};
|
use router_env::{instrument, tracing, Flow};
|
||||||
|
|
||||||
use super::app::AppState;
|
use super::app::AppState;
|
||||||
use crate::{core::refunds::*, services::api, types::api::refunds};
|
use crate::{
|
||||||
|
core::refunds::*,
|
||||||
|
services::{api, authentication as auth},
|
||||||
|
types::api::refunds,
|
||||||
|
};
|
||||||
|
|
||||||
/// Refunds - Create
|
/// Refunds - Create
|
||||||
///
|
///
|
||||||
@ -28,7 +32,7 @@ pub async fn refunds_create(
|
|||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
json_payload.into_inner(),
|
||||||
refund_create_core,
|
refund_create_core,
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -49,7 +53,7 @@ pub async fn refunds_retrieve(
|
|||||||
|state, merchant_account, refund_id| {
|
|state, merchant_account, refund_id| {
|
||||||
refund_response_wrapper(state, merchant_account, refund_id, refund_retrieve_core)
|
refund_response_wrapper(state, merchant_account, refund_id, refund_retrieve_core)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -70,7 +74,7 @@ pub async fn refunds_update(
|
|||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
refund_update_core(&*state.store, merchant_account, &refund_id, req)
|
refund_update_core(&*state.store, merchant_account, &refund_id, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -87,7 +91,7 @@ pub async fn refunds_list(
|
|||||||
&req,
|
&req,
|
||||||
payload.into_inner(),
|
payload.into_inner(),
|
||||||
|state, merchant_account, req| refund_list(&*state.store, merchant_account, req),
|
|state, merchant_account, req| refund_list(&*state.store, merchant_account, req),
|
||||||
api::MerchantAuthentication::ApiKey,
|
&auth::ApiKeyAuth,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,10 @@ use actix_web::{web, HttpRequest, Responder};
|
|||||||
use router_env::{instrument, tracing, Flow};
|
use router_env::{instrument, tracing, Flow};
|
||||||
|
|
||||||
use super::app::AppState;
|
use super::app::AppState;
|
||||||
use crate::{core::webhooks, services::api};
|
use crate::{
|
||||||
|
core::webhooks,
|
||||||
|
services::{api, authentication as auth},
|
||||||
|
};
|
||||||
|
|
||||||
#[instrument(skip_all, fields(flow = ?Flow::IncomingWebhookReceive))]
|
#[instrument(skip_all, fields(flow = ?Flow::IncomingWebhookReceive))]
|
||||||
pub async fn receive_incoming_webhook(
|
pub async fn receive_incoming_webhook(
|
||||||
@ -20,7 +23,7 @@ pub async fn receive_incoming_webhook(
|
|||||||
|state, merchant_account, body| {
|
|state, merchant_account, body| {
|
||||||
webhooks::webhooks_core(state, &req, merchant_account, &connector_name, body)
|
webhooks::webhooks_core(state, &req, merchant_account, &connector_name, body)
|
||||||
},
|
},
|
||||||
api::ConnectorAuthentication::MerchantId(&merchant_id),
|
&auth::MerchantIdAuth(merchant_id),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
pub mod api;
|
pub mod api;
|
||||||
|
pub mod authentication;
|
||||||
pub mod encryption;
|
pub mod encryption;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
mod client;
|
mod client;
|
||||||
pub(crate) mod request;
|
pub(crate) mod request;
|
||||||
|
|
||||||
use std::{borrow::Cow, collections::HashMap, fmt::Debug, future::Future, str, time::Instant};
|
use std::{collections::HashMap, fmt::Debug, future::Future, str, time::Instant};
|
||||||
|
|
||||||
use actix_web::{body, HttpRequest, HttpResponse, Responder};
|
use actix_web::{body, HttpRequest, HttpResponse, Responder};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
@ -15,18 +15,18 @@ pub use self::request::{Method, Request, RequestBuilder};
|
|||||||
use crate::{
|
use crate::{
|
||||||
configs::settings::Connectors,
|
configs::settings::Connectors,
|
||||||
core::{
|
core::{
|
||||||
errors::{self, CustomResult, RouterResponse, RouterResult, StorageErrorExt},
|
errors::{self, CustomResult, RouterResponse, RouterResult},
|
||||||
payments,
|
payments,
|
||||||
},
|
},
|
||||||
db::StorageInterface,
|
db::StorageInterface,
|
||||||
logger,
|
logger,
|
||||||
routes::AppState,
|
routes::AppState,
|
||||||
|
services::authentication as auth,
|
||||||
types::{
|
types::{
|
||||||
self, api,
|
self, api,
|
||||||
storage::{self, enums},
|
storage::{self},
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
},
|
},
|
||||||
utils::{self, OptionExt},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type BoxedConnectorIntegration<'a, T, Req, Resp> =
|
pub type BoxedConnectorIntegration<'a, T, Req, Resp> =
|
||||||
@ -363,104 +363,49 @@ impl RedirectForm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum ApiAuthentication<'a> {
|
|
||||||
Merchant(MerchantAuthentication<'a>),
|
|
||||||
Connector(ConnectorAuthentication<'a>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum MerchantAuthentication<'a> {
|
|
||||||
ApiKey,
|
|
||||||
MerchantId(Cow<'a, str>),
|
|
||||||
AdminApiKey,
|
|
||||||
PublishableKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum ConnectorAuthentication<'a> {
|
|
||||||
MerchantId(&'a str),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<MerchantAuthentication<'a>> for ApiAuthentication<'a> {
|
|
||||||
fn from(merchant_auth: MerchantAuthentication<'a>) -> Self {
|
|
||||||
ApiAuthentication::Merchant(merchant_auth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<ConnectorAuthentication<'a>> for ApiAuthentication<'a> {
|
|
||||||
fn from(connector_auth: ConnectorAuthentication<'a>) -> Self {
|
|
||||||
ApiAuthentication::Connector(connector_auth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum AuthFlow {
|
pub enum AuthFlow {
|
||||||
Client,
|
Client,
|
||||||
Merchant,
|
Merchant,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_auth_flow(auth_type: &MerchantAuthentication<'_>) -> AuthFlow {
|
#[instrument(skip(request, payload, state, func, api_auth))]
|
||||||
match auth_type {
|
pub async fn server_wrap_util<'a, 'b, U, T, Q, F, Fut>(
|
||||||
MerchantAuthentication::ApiKey => AuthFlow::Merchant,
|
|
||||||
_ => AuthFlow::Client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_auth_type(request: &HttpRequest) -> RouterResult<MerchantAuthentication<'_>> {
|
|
||||||
let api_key = get_api_key(request).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
|
||||||
if api_key.starts_with("pk_") {
|
|
||||||
Ok(MerchantAuthentication::PublishableKey)
|
|
||||||
} else {
|
|
||||||
Ok(MerchantAuthentication::ApiKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(request, payload, state, func))]
|
|
||||||
pub async fn server_wrap_util<'a, 'b, T, Q, F, Fut>(
|
|
||||||
state: &'b AppState,
|
state: &'b AppState,
|
||||||
request: &'a HttpRequest,
|
request: &'a HttpRequest,
|
||||||
payload: T,
|
payload: T,
|
||||||
func: F,
|
func: F,
|
||||||
api_authentication: ApiAuthentication<'a>,
|
api_auth: &dyn auth::AuthenticateAndFetch<U>,
|
||||||
) -> RouterResult<BachResponse<Q>>
|
) -> RouterResult<BachResponse<Q>>
|
||||||
where
|
where
|
||||||
F: Fn(&'b AppState, storage::MerchantAccount, T) -> Fut,
|
F: Fn(&'b AppState, U, T) -> Fut,
|
||||||
Fut: Future<Output = RouterResponse<Q>>,
|
Fut: Future<Output = RouterResponse<Q>>,
|
||||||
Q: Serialize + Debug + 'a,
|
Q: Serialize + Debug + 'a,
|
||||||
T: Debug,
|
T: Debug,
|
||||||
{
|
{
|
||||||
let merchant_account = match api_authentication {
|
let auth_out = api_auth
|
||||||
ApiAuthentication::Merchant(merchant_auth) => {
|
.authenticate_and_fetch(request.headers(), state)
|
||||||
authenticate_merchant(request, state, merchant_auth).await?
|
.await?;
|
||||||
}
|
func(state, auth_out, payload).await
|
||||||
ApiAuthentication::Connector(connector_auth) => {
|
|
||||||
authenticate_connector(request, &*state.store, connector_auth).await?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
logger::debug!(request=?payload);
|
|
||||||
func(state, merchant_account, payload).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(
|
#[instrument(
|
||||||
skip(request, payload, state, func),
|
skip(request, payload, state, func, api_auth),
|
||||||
fields(request_method, request_url_path)
|
fields(request_method, request_url_path)
|
||||||
)]
|
)]
|
||||||
pub async fn server_wrap<'a, 'b, A, T, Q, F, Fut>(
|
pub async fn server_wrap<'a, 'b, T, U, Q, F, Fut>(
|
||||||
state: &'b AppState,
|
state: &'b AppState,
|
||||||
request: &'a HttpRequest,
|
request: &'a HttpRequest,
|
||||||
payload: T,
|
payload: T,
|
||||||
func: F,
|
func: F,
|
||||||
api_authentication: A,
|
api_auth: &dyn auth::AuthenticateAndFetch<U>,
|
||||||
) -> HttpResponse
|
) -> HttpResponse
|
||||||
where
|
where
|
||||||
A: Into<ApiAuthentication<'a>> + Debug,
|
F: Fn(&'b AppState, U, T) -> Fut,
|
||||||
F: Fn(&'b AppState, storage::MerchantAccount, T) -> Fut,
|
|
||||||
Fut: Future<Output = RouterResult<BachResponse<Q>>>,
|
Fut: Future<Output = RouterResult<BachResponse<Q>>>,
|
||||||
Q: Serialize + Debug + 'a,
|
Q: Serialize + Debug + 'a,
|
||||||
T: Debug,
|
T: Debug,
|
||||||
{
|
{
|
||||||
let api_authentication = api_authentication.into();
|
|
||||||
let request_method = request.method().as_str();
|
let request_method = request.method().as_str();
|
||||||
let url_path = request.path();
|
let url_path = request.path();
|
||||||
tracing::Span::current().record("request_method", request_method);
|
tracing::Span::current().record("request_method", request_method);
|
||||||
@ -469,7 +414,7 @@ where
|
|||||||
let start_instant = Instant::now();
|
let start_instant = Instant::now();
|
||||||
logger::info!(tag = ?Tag::BeginRequest);
|
logger::info!(tag = ?Tag::BeginRequest);
|
||||||
|
|
||||||
let res = match server_wrap_util(state, request, payload, func, api_authentication).await {
|
let res = match server_wrap_util(state, request, payload, func, api_auth).await {
|
||||||
Ok(BachResponse::Json(response)) => match serde_json::to_string(&response) {
|
Ok(BachResponse::Json(response)) => match serde_json::to_string(&response) {
|
||||||
Ok(res) => http_response_json(res),
|
Ok(res) => http_response_json(res),
|
||||||
Err(_) => http_response_err(
|
Err(_) => http_response_err(
|
||||||
@ -519,120 +464,6 @@ where
|
|||||||
error.current_context().error_response()
|
error.current_context().error_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn authenticate_merchant<'a>(
|
|
||||||
request: &HttpRequest,
|
|
||||||
state: &AppState,
|
|
||||||
merchant_authentication: MerchantAuthentication<'a>,
|
|
||||||
) -> RouterResult<storage::MerchantAccount> {
|
|
||||||
match merchant_authentication {
|
|
||||||
MerchantAuthentication::ApiKey => {
|
|
||||||
let api_key =
|
|
||||||
get_api_key(request).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
|
||||||
authenticate_by_api_key(&*state.store, api_key).await
|
|
||||||
}
|
|
||||||
|
|
||||||
MerchantAuthentication::MerchantId(merchant_id) => (*state.store)
|
|
||||||
.find_merchant_account_by_merchant_id(&merchant_id)
|
|
||||||
.await
|
|
||||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::Unauthorized)),
|
|
||||||
|
|
||||||
MerchantAuthentication::AdminApiKey => {
|
|
||||||
let admin_api_key =
|
|
||||||
get_api_key(request).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
|
||||||
utils::when(admin_api_key != state.conf.keys.admin_api_key, || {
|
|
||||||
Err(errors::ApiErrorResponse::Unauthorized)
|
|
||||||
.into_report()
|
|
||||||
.attach_printable("Admin Authentication Failure")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(storage::MerchantAccount {
|
|
||||||
id: -1,
|
|
||||||
merchant_id: String::from("juspay"),
|
|
||||||
merchant_name: None,
|
|
||||||
api_key: None,
|
|
||||||
merchant_details: None,
|
|
||||||
return_url: None,
|
|
||||||
webhook_details: None,
|
|
||||||
routing_algorithm: None,
|
|
||||||
custom_routing_rules: None,
|
|
||||||
sub_merchants_enabled: None,
|
|
||||||
parent_merchant_id: None,
|
|
||||||
enable_payment_response_hash: false,
|
|
||||||
payment_response_hash_key: None,
|
|
||||||
redirect_to_merchant_with_http_post: false,
|
|
||||||
publishable_key: None,
|
|
||||||
storage_scheme: enums::MerchantStorageScheme::PostgresOnly,
|
|
||||||
locker_id: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
MerchantAuthentication::PublishableKey => {
|
|
||||||
let api_key =
|
|
||||||
get_api_key(request).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
|
||||||
authenticate_by_publishable_key(&*state.store, api_key).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn authenticate_connector<'a>(
|
|
||||||
_request: &HttpRequest,
|
|
||||||
store: &dyn StorageInterface,
|
|
||||||
connector_authentication: ConnectorAuthentication<'a>,
|
|
||||||
) -> RouterResult<storage::MerchantAccount> {
|
|
||||||
match connector_authentication {
|
|
||||||
ConnectorAuthentication::MerchantId(merchant_id) => store
|
|
||||||
.find_merchant_account_by_merchant_id(merchant_id)
|
|
||||||
.await
|
|
||||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::Unauthorized)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_auth_type_and_check_client_secret<P>(
|
|
||||||
req: &HttpRequest,
|
|
||||||
payload: P,
|
|
||||||
) -> RouterResult<(P, MerchantAuthentication<'_>)>
|
|
||||||
where
|
|
||||||
P: Authenticate,
|
|
||||||
{
|
|
||||||
let auth_type = get_auth_type(req)?;
|
|
||||||
Ok((
|
|
||||||
payments::helpers::client_secret_auth(payload, &auth_type)?,
|
|
||||||
auth_type,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn authenticate_eph_key<'a>(
|
|
||||||
req: &'a HttpRequest,
|
|
||||||
store: &dyn StorageInterface,
|
|
||||||
customer_id: String,
|
|
||||||
) -> RouterResult<MerchantAuthentication<'a>> {
|
|
||||||
let api_key = get_api_key(req)?;
|
|
||||||
if api_key.starts_with("epk") {
|
|
||||||
let ek = store
|
|
||||||
.get_ephemeral_key(api_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::ApiErrorResponse::Unauthorized)?;
|
|
||||||
utils::when(ek.customer_id.ne(&customer_id), || {
|
|
||||||
Err(report!(errors::ApiErrorResponse::InvalidEphermeralKey))
|
|
||||||
})?;
|
|
||||||
Ok(MerchantAuthentication::MerchantId(Cow::Owned(
|
|
||||||
ek.merchant_id,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Ok(MerchantAuthentication::ApiKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_api_key(req: &HttpRequest) -> RouterResult<&str> {
|
|
||||||
req.headers()
|
|
||||||
.get("api-key")
|
|
||||||
.get_required_value("api-key")?
|
|
||||||
.to_str()
|
|
||||||
.into_report()
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Failed to convert API key to string")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn authenticate_by_api_key(
|
pub async fn authenticate_by_api_key(
|
||||||
store: &dyn StorageInterface,
|
store: &dyn StorageInterface,
|
||||||
api_key: &str,
|
api_key: &str,
|
||||||
@ -644,17 +475,6 @@ pub async fn authenticate_by_api_key(
|
|||||||
.attach_printable("Merchant not authenticated")
|
.attach_printable("Merchant not authenticated")
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn authenticate_by_publishable_key(
|
|
||||||
store: &dyn StorageInterface,
|
|
||||||
publishable_key: &str,
|
|
||||||
) -> RouterResult<storage::MerchantAccount> {
|
|
||||||
store
|
|
||||||
.find_merchant_account_by_publishable_key(publishable_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::ApiErrorResponse::Unauthorized)
|
|
||||||
.attach_printable("Merchant not authenticated")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn http_response_json<T: body::MessageBody + 'static>(response: T) -> HttpResponse {
|
pub fn http_response_json<T: body::MessageBody + 'static>(response: T) -> HttpResponse {
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.content_type("application/json")
|
.content_type("application/json")
|
||||||
|
|||||||
194
crates/router/src/services/authentication.rs
Normal file
194
crates/router/src/services/authentication.rs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
use actix_web::http::header::HeaderMap;
|
||||||
|
use api_models::{payment_methods::ListPaymentMethodRequest, payments::PaymentsRequest};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use error_stack::{report, IntoReport, ResultExt};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
core::errors::{self, RouterResult, StorageErrorExt},
|
||||||
|
db::StorageInterface,
|
||||||
|
routes::AppState,
|
||||||
|
services::api,
|
||||||
|
types::storage,
|
||||||
|
utils::OptionExt,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait AuthenticateAndFetch<T> {
|
||||||
|
async fn authenticate_and_fetch(
|
||||||
|
&self,
|
||||||
|
request_headers: &HeaderMap,
|
||||||
|
state: &AppState,
|
||||||
|
) -> RouterResult<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ApiKeyAuth;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AuthenticateAndFetch<storage::MerchantAccount> for ApiKeyAuth {
|
||||||
|
async fn authenticate_and_fetch(
|
||||||
|
&self,
|
||||||
|
request_headers: &HeaderMap,
|
||||||
|
state: &AppState,
|
||||||
|
) -> RouterResult<storage::MerchantAccount> {
|
||||||
|
let api_key =
|
||||||
|
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
||||||
|
state
|
||||||
|
.store
|
||||||
|
.find_merchant_account_by_api_key(api_key)
|
||||||
|
.await
|
||||||
|
.change_context(errors::ApiErrorResponse::Unauthorized)
|
||||||
|
.attach_printable("Merchant not authenticated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AdminApiAuth;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AuthenticateAndFetch<()> for AdminApiAuth {
|
||||||
|
async fn authenticate_and_fetch(
|
||||||
|
&self,
|
||||||
|
request_headers: &HeaderMap,
|
||||||
|
state: &AppState,
|
||||||
|
) -> RouterResult<()> {
|
||||||
|
let admin_api_key =
|
||||||
|
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
||||||
|
if admin_api_key != state.conf.keys.admin_api_key {
|
||||||
|
Err(report!(errors::ApiErrorResponse::Unauthorized)
|
||||||
|
.attach_printable("Admin Authentication Failure"))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MerchantIdAuth(pub String);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AuthenticateAndFetch<storage::MerchantAccount> for MerchantIdAuth {
|
||||||
|
async fn authenticate_and_fetch(
|
||||||
|
&self,
|
||||||
|
_request_headers: &HeaderMap,
|
||||||
|
state: &AppState,
|
||||||
|
) -> RouterResult<storage::MerchantAccount> {
|
||||||
|
state
|
||||||
|
.store
|
||||||
|
.find_merchant_account_by_merchant_id(self.0.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::Unauthorized))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PublishableKeyAuth;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AuthenticateAndFetch<storage::MerchantAccount> for PublishableKeyAuth {
|
||||||
|
async fn authenticate_and_fetch(
|
||||||
|
&self,
|
||||||
|
request_headers: &HeaderMap,
|
||||||
|
state: &AppState,
|
||||||
|
) -> RouterResult<storage::MerchantAccount> {
|
||||||
|
let publishable_key =
|
||||||
|
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
||||||
|
state
|
||||||
|
.store
|
||||||
|
.find_merchant_account_by_publishable_key(publishable_key)
|
||||||
|
.await
|
||||||
|
.change_context(errors::ApiErrorResponse::Unauthorized)
|
||||||
|
.attach_printable("Merchant not authenticated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ClientSecretFetch {
|
||||||
|
fn get_client_secret(&self) -> Option<&String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientSecretFetch for PaymentsRequest {
|
||||||
|
fn get_client_secret(&self) -> Option<&String> {
|
||||||
|
self.client_secret.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientSecretFetch for ListPaymentMethodRequest {
|
||||||
|
fn get_client_secret(&self) -> Option<&String> {
|
||||||
|
self.client_secret.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_auth_type_and_flow(
|
||||||
|
headers: &HeaderMap,
|
||||||
|
) -> RouterResult<(
|
||||||
|
Box<dyn AuthenticateAndFetch<storage::MerchantAccount>>,
|
||||||
|
api::AuthFlow,
|
||||||
|
)> {
|
||||||
|
let api_key = get_api_key(headers)?;
|
||||||
|
|
||||||
|
if api_key.starts_with("pk_") {
|
||||||
|
return Ok((Box::new(PublishableKeyAuth), api::AuthFlow::Client));
|
||||||
|
}
|
||||||
|
Ok((Box::new(PublishableKeyAuth), api::AuthFlow::Merchant))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_client_secret_and_get_auth(
|
||||||
|
headers: &HeaderMap,
|
||||||
|
payload: &impl ClientSecretFetch,
|
||||||
|
) -> RouterResult<(
|
||||||
|
Box<dyn AuthenticateAndFetch<storage::MerchantAccount>>,
|
||||||
|
api::AuthFlow,
|
||||||
|
)> {
|
||||||
|
let api_key = get_api_key(headers)?;
|
||||||
|
|
||||||
|
if api_key.starts_with("pk_") {
|
||||||
|
payload
|
||||||
|
.get_client_secret()
|
||||||
|
.check_value_present("client_secret")
|
||||||
|
.map_err(|_| errors::ApiErrorResponse::MissingRequiredField {
|
||||||
|
field_name: "client_secret".to_owned(),
|
||||||
|
})?;
|
||||||
|
return Ok((Box::new(PublishableKeyAuth), api::AuthFlow::Client));
|
||||||
|
}
|
||||||
|
|
||||||
|
if payload.get_client_secret().is_some() {
|
||||||
|
return Err(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
|
message: "client_secret is not a valid parameter".to_owned(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((Box::new(ApiKeyAuth), api::AuthFlow::Merchant))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn is_ephemeral_auth(
|
||||||
|
headers: &HeaderMap,
|
||||||
|
db: &dyn StorageInterface,
|
||||||
|
customer_id: &str,
|
||||||
|
) -> RouterResult<Box<dyn AuthenticateAndFetch<storage::MerchantAccount>>> {
|
||||||
|
let api_key = get_api_key(headers)?;
|
||||||
|
|
||||||
|
if !api_key.starts_with("epk") {
|
||||||
|
return Ok(Box::new(ApiKeyAuth));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ephemeral_key = db
|
||||||
|
.get_ephemeral_key(api_key)
|
||||||
|
.await
|
||||||
|
.change_context(errors::ApiErrorResponse::Unauthorized)?;
|
||||||
|
|
||||||
|
if ephemeral_key.customer_id.ne(customer_id) {
|
||||||
|
return Err(report!(errors::ApiErrorResponse::InvalidEphermeralKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Box::new(MerchantIdAuth(ephemeral_key.merchant_id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_api_key(headers: &HeaderMap) -> RouterResult<&str> {
|
||||||
|
headers
|
||||||
|
.get("api-key")
|
||||||
|
.get_required_value("api-key")?
|
||||||
|
.to_str()
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("Failed to convert API key to string")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user