Skip to content

Commit

Permalink
fix: add validation for connector authentication type during mca crea…
Browse files Browse the repository at this point in the history
…te and update operation (#4932)
  • Loading branch information
hrithikesh026 authored Jun 11, 2024
1 parent bbcf034 commit 9f2476b
Showing 1 changed file with 109 additions and 43 deletions.
152 changes: 109 additions & 43 deletions crates/router/src/core/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,27 +859,7 @@ pub async fn create_payment_connector(
expected_format: "auth_type and api_key".to_string(),
})?;

validate_auth_and_metadata_type(req.connector_name, &auth, &req.metadata).map_err(|err| {
match *err.current_context() {
errors::ConnectorError::InvalidConnectorName => {
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The connector name is invalid".to_string(),
})
}
errors::ConnectorError::InvalidConnectorConfig { config: field_name } => err
.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: format!("The {} is invalid", field_name),
}),
errors::ConnectorError::FailedToObtainAuthType => {
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The auth type is invalid for the connector".to_string(),
})
}
_ => err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The request body is invalid".to_string(),
}),
}
})?;
validate_auth_and_metadata_type(req.connector_name, &auth, &req.metadata)?;

let frm_configs = get_frm_config_as_secret(req.frm_configs);

Expand Down Expand Up @@ -1209,27 +1189,7 @@ pub async fn update_payment_connector(
field_name: "connector",
})
.attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?;
validate_auth_and_metadata_type(connector_enum, &auth, &metadata).map_err(|err| match *err
.current_context()
{
errors::ConnectorError::InvalidConnectorName => {
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The connector name is invalid".to_string(),
})
}
errors::ConnectorError::InvalidConnectorConfig { config: field_name } => err
.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: format!("The {} is invalid", field_name),
}),
errors::ConnectorError::FailedToObtainAuthType => {
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The auth type is invalid for the connector".to_string(),
})
}
_ => err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The request body is invalid".to_string(),
}),
})?;
validate_auth_and_metadata_type(connector_enum, &auth, &metadata)?;

let (connector_status, disabled) =
validate_status_and_disabled(req.status, req.disabled, auth, mca.status)?;
Expand Down Expand Up @@ -1819,7 +1779,35 @@ pub async fn connector_agnostic_mit_toggle(
))
}

pub(crate) fn validate_auth_and_metadata_type(
pub fn validate_auth_and_metadata_type(
connector_name: api_models::enums::Connector,
auth_type: &types::ConnectorAuthType,
connector_meta_data: &Option<pii::SecretSerdeValue>,
) -> Result<(), error_stack::Report<errors::ApiErrorResponse>> {
validate_connector_auth_type(auth_type)?;
validate_auth_and_metadata_type_with_connector(connector_name, auth_type, connector_meta_data)
.map_err(|err| match *err.current_context() {
errors::ConnectorError::InvalidConnectorName => {
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The connector name is invalid".to_string(),
})
}
errors::ConnectorError::InvalidConnectorConfig { config: field_name } => err
.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: format!("The {} is invalid", field_name),
}),
errors::ConnectorError::FailedToObtainAuthType => {
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The auth type is invalid for the connector".to_string(),
})
}
_ => err.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "The request body is invalid".to_string(),
}),
})
}

pub(crate) fn validate_auth_and_metadata_type_with_connector(
connector_name: api_models::enums::Connector,
val: &types::ConnectorAuthType,
connector_meta_data: &Option<pii::SecretSerdeValue>,
Expand Down Expand Up @@ -2096,6 +2084,84 @@ pub(crate) fn validate_auth_and_metadata_type(
}
}

pub(crate) fn validate_connector_auth_type(
auth_type: &types::ConnectorAuthType,
) -> Result<(), error_stack::Report<errors::ApiErrorResponse>> {
let validate_non_empty_field = |field_value: &str, field_name: &str| {
if field_value.trim().is_empty() {
Err(errors::ApiErrorResponse::InvalidDataFormat {
field_name: format!("connector_account_details.{}", field_name),
expected_format: "a non empty String".to_string(),
}
.into())
} else {
Ok(())
}
};
match auth_type {
hyperswitch_domain_models::router_data::ConnectorAuthType::TemporaryAuth => Ok(()),
hyperswitch_domain_models::router_data::ConnectorAuthType::HeaderKey { api_key } => {
validate_non_empty_field(api_key.peek(), "api_key")
}
hyperswitch_domain_models::router_data::ConnectorAuthType::BodyKey { api_key, key1 } => {
validate_non_empty_field(api_key.peek(), "api_key")?;
validate_non_empty_field(key1.peek(), "key1")
}
hyperswitch_domain_models::router_data::ConnectorAuthType::SignatureKey {
api_key,
key1,
api_secret,
} => {
validate_non_empty_field(api_key.peek(), "api_key")?;
validate_non_empty_field(key1.peek(), "key1")?;
validate_non_empty_field(api_secret.peek(), "api_secret")
}
hyperswitch_domain_models::router_data::ConnectorAuthType::MultiAuthKey {
api_key,
key1,
api_secret,
key2,
} => {
validate_non_empty_field(api_key.peek(), "api_key")?;
validate_non_empty_field(key1.peek(), "key1")?;
validate_non_empty_field(api_secret.peek(), "api_secret")?;
validate_non_empty_field(key2.peek(), "key2")
}
hyperswitch_domain_models::router_data::ConnectorAuthType::CurrencyAuthKey {
auth_key_map,
} => {
if auth_key_map.is_empty() {
Err(errors::ApiErrorResponse::InvalidDataFormat {
field_name: "connector_account_details.auth_key_map".to_string(),
expected_format: "a non empty map".to_string(),
}
.into())
} else {
Ok(())
}
}
hyperswitch_domain_models::router_data::ConnectorAuthType::CertificateAuth {
certificate,
private_key,
} => {
helpers::create_identity_from_certificate_and_key(
certificate.to_owned(),
private_key.to_owned(),
)
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
field_name:
"connector_account_details.certificate or connector_account_details.private_key"
.to_string(),
expected_format:
"a valid base64 encoded string of PEM encoded Certificate and Private Key"
.to_string(),
})?;
Ok(())
}
hyperswitch_domain_models::router_data::ConnectorAuthType::NoKey => Ok(()),
}
}

#[cfg(feature = "dummy_connector")]
pub async fn validate_dummy_connector_enabled(
state: &SessionState,
Expand Down

0 comments on commit 9f2476b

Please sign in to comment.