Skip to content

Commit

Permalink
Merge branch 'main' into pm-auth-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Sarthak1799 authored Nov 30, 2023
2 parents 56a9f8a + 39f255b commit 5a51fc1
Show file tree
Hide file tree
Showing 18 changed files with 552 additions and 2 deletions.
32 changes: 32 additions & 0 deletions crates/api_models/src/admin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use common_utils::{
crypto::{Encryptable, OptionalEncryptableName},
pii,
Expand Down Expand Up @@ -614,6 +616,36 @@ pub struct MerchantConnectorCreate {
pub status: Option<api_enums::ConnectorStatus>,
}

// Different patterns of authentication.
#[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(tag = "auth_type")]
pub enum ConnectorAuthType {
TemporaryAuth,
HeaderKey {
api_key: Secret<String>,
},
BodyKey {
api_key: Secret<String>,
key1: Secret<String>,
},
SignatureKey {
api_key: Secret<String>,
key1: Secret<String>,
api_secret: Secret<String>,
},
MultiAuthKey {
api_key: Secret<String>,
key1: Secret<String>,
api_secret: Secret<String>,
key2: Secret<String>,
},
CurrencyAuthKey {
auth_key_map: HashMap<common_enums::Currency, pii::SecretSerdeValue>,
},
#[default]
NoKey,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct MerchantConnectorWebhookDetails {
Expand Down
1 change: 1 addition & 0 deletions crates/api_models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ pub mod routing;
pub mod surcharge_decision_configs;
pub mod user;
pub mod verifications;
pub mod verify_connector;
pub mod webhooks;
11 changes: 11 additions & 0 deletions crates/api_models/src/verify_connector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use common_utils::events::{ApiEventMetric, ApiEventsType};

use crate::{admin, enums};

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct VerifyConnectorRequest {
pub connector_name: enums::Connector,
pub connector_account_details: admin::ConnectorAuthType,
}

common_utils::impl_misc_api_event_type!(VerifyConnectorRequest);
5 changes: 5 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,8 @@ pub const JWT_TOKEN_TIME_IN_SECS: u64 = 60 * 60 * 24 * 2; // 2 days
#[cfg(feature = "email")]
pub const EMAIL_TOKEN_TIME_IN_SECS: u64 = 60 * 60 * 24; // 1 day
pub const ROLE_ID_ORGANIZATION_ADMIN: &str = "org_admin";

#[cfg(feature = "olap")]
pub const VERIFY_CONNECTOR_ID_PREFIX: &str = "conn_verify";
#[cfg(feature = "olap")]
pub const VERIFY_CONNECTOR_MERCHANT_ID: &str = "test_merchant";
2 changes: 2 additions & 0 deletions crates/router/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ pub mod user;
pub mod utils;
#[cfg(all(feature = "olap", feature = "kms"))]
pub mod verification;
#[cfg(feature = "olap")]
pub mod verify_connector;
pub mod webhooks;
63 changes: 63 additions & 0 deletions crates/router/src/core/verify_connector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use api_models::{enums::Connector, verify_connector::VerifyConnectorRequest};
use error_stack::{IntoReport, ResultExt};

use crate::{
connector,
core::errors,
services,
types::{
api,
api::verify_connector::{self as types, VerifyConnector},
},
utils::verify_connector as utils,
AppState,
};

pub async fn verify_connector_credentials(
state: AppState,
req: VerifyConnectorRequest,
) -> errors::RouterResponse<()> {
let boxed_connector = api::ConnectorData::get_connector_by_name(
&state.conf.connectors,
&req.connector_name.to_string(),
api::GetToken::Connector,
None,
)
.change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven)?;

let card_details = utils::get_test_card_details(req.connector_name)?
.ok_or(errors::ApiErrorResponse::FlowNotSupported {
flow: "Verify credentials".to_string(),
connector: req.connector_name.to_string(),
})
.into_report()?;

match req.connector_name {
Connector::Stripe => {
connector::Stripe::verify(
&state,
types::VerifyConnectorData {
connector: *boxed_connector.connector,
connector_auth: req.connector_account_details.into(),
card_details,
},
)
.await
}
Connector::Paypal => connector::Paypal::get_access_token(
&state,
types::VerifyConnectorData {
connector: *boxed_connector.connector,
connector_auth: req.connector_account_details.into(),
card_details,
},
)
.await
.map(|_| services::ApplicationResponse::StatusOk),
_ => Err(errors::ApiErrorResponse::FlowNotSupported {
flow: "Verify credentials".to_string(),
connector: req.connector_name.to_string(),
})
.into_report(),
}
}
2 changes: 2 additions & 0 deletions crates/router/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub mod routing;
pub mod user;
#[cfg(all(feature = "olap", feature = "kms"))]
pub mod verification;
#[cfg(feature = "olap")]
pub mod verify_connector;
pub mod webhooks;

pub mod locker_migration;
Expand Down
6 changes: 6 additions & 0 deletions crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ use super::{cache::*, health::*};
use super::{configs::*, customers::*, mandates::*, payments::*, refunds::*};
#[cfg(feature = "oltp")]
use super::{ephemeral_key::*, payment_methods::*, webhooks::*};
#[cfg(feature = "olap")]
use crate::routes::verify_connector::payment_connector_verify;
pub use crate::{
configs::settings,
db::{StorageImpl, StorageInterface},
Expand Down Expand Up @@ -548,6 +550,10 @@ impl MerchantConnectorAccount {
use super::admin::*;

route = route
.service(
web::resource("/connectors/verify")
.route(web::post().to(payment_connector_verify)),
)
.service(
web::resource("/{merchant_id}/connectors")
.route(web::post().to(payment_connector_create))
Expand Down
4 changes: 3 additions & 1 deletion crates/router/src/routes/lock_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ impl From<Flow> for ApiIdentifier {
| Flow::GsmRuleUpdate
| Flow::GsmRuleDelete => Self::Gsm,

Flow::UserConnectAccount | Flow::ChangePassword => Self::User,
Flow::UserConnectAccount | Flow::ChangePassword | Flow::VerifyPaymentConnector => {
Self::User
}
}
}
}
28 changes: 28 additions & 0 deletions crates/router/src/routes/verify_connector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use actix_web::{web, HttpRequest, HttpResponse};
use api_models::verify_connector::VerifyConnectorRequest;
use router_env::{instrument, tracing, Flow};

use super::AppState;
use crate::{
core::{api_locking, verify_connector},
services::{self, authentication as auth, authorization::permissions::Permission},
};

#[instrument(skip_all, fields(flow = ?Flow::VerifyPaymentConnector))]
pub async fn payment_connector_verify(
state: web::Data<AppState>,
req: HttpRequest,
json_payload: web::Json<VerifyConnectorRequest>,
) -> HttpResponse {
let flow = Flow::VerifyPaymentConnector;
Box::pin(services::server_wrap(
flow,
state,
&req,
json_payload.into_inner(),
|state, _: (), req| verify_connector::verify_connector_credentials(state, req),
&auth::JWTAuth(Permission::MerchantConnectorAccountWrite),
api_locking::LockAction::NotApplicable,
))
.await
}
74 changes: 73 additions & 1 deletion crates/router/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
payments::{PaymentData, RecurringMandatePaymentData},
},
services,
types::storage::payment_attempt::PaymentAttemptExt,
types::{storage::payment_attempt::PaymentAttemptExt, transformers::ForeignFrom},
utils::OptionExt,
};

Expand Down Expand Up @@ -942,6 +942,78 @@ pub enum ConnectorAuthType {
NoKey,
}

impl From<api_models::admin::ConnectorAuthType> for ConnectorAuthType {
fn from(value: api_models::admin::ConnectorAuthType) -> Self {
match value {
api_models::admin::ConnectorAuthType::TemporaryAuth => Self::TemporaryAuth,
api_models::admin::ConnectorAuthType::HeaderKey { api_key } => {
Self::HeaderKey { api_key }
}
api_models::admin::ConnectorAuthType::BodyKey { api_key, key1 } => {
Self::BodyKey { api_key, key1 }
}
api_models::admin::ConnectorAuthType::SignatureKey {
api_key,
key1,
api_secret,
} => Self::SignatureKey {
api_key,
key1,
api_secret,
},
api_models::admin::ConnectorAuthType::MultiAuthKey {
api_key,
key1,
api_secret,
key2,
} => Self::MultiAuthKey {
api_key,
key1,
api_secret,
key2,
},
api_models::admin::ConnectorAuthType::CurrencyAuthKey { auth_key_map } => {
Self::CurrencyAuthKey { auth_key_map }
}
api_models::admin::ConnectorAuthType::NoKey => Self::NoKey,
}
}
}

impl ForeignFrom<ConnectorAuthType> for api_models::admin::ConnectorAuthType {
fn foreign_from(from: ConnectorAuthType) -> Self {
match from {
ConnectorAuthType::TemporaryAuth => Self::TemporaryAuth,
ConnectorAuthType::HeaderKey { api_key } => Self::HeaderKey { api_key },
ConnectorAuthType::BodyKey { api_key, key1 } => Self::BodyKey { api_key, key1 },
ConnectorAuthType::SignatureKey {
api_key,
key1,
api_secret,
} => Self::SignatureKey {
api_key,
key1,
api_secret,
},
ConnectorAuthType::MultiAuthKey {
api_key,
key1,
api_secret,
key2,
} => Self::MultiAuthKey {
api_key,
key1,
api_secret,
key2,
},
ConnectorAuthType::CurrencyAuthKey { auth_key_map } => {
Self::CurrencyAuthKey { auth_key_map }
}
ConnectorAuthType::NoKey => Self::NoKey,
}
}
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ConnectorsList {
pub connectors: Vec<String>,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/types/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub mod payments;
pub mod payouts;
pub mod refunds;
pub mod routing;
#[cfg(feature = "olap")]
pub mod verify_connector;
pub mod webhooks;

use std::{fmt::Debug, str::FromStr};
Expand Down
Loading

0 comments on commit 5a51fc1

Please sign in to comment.