feat(mca): Add new auth_type and a status field for mca (#2883)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Mani Chandra
2023-11-20 12:54:55 +05:30
committed by GitHub
parent 94897d841e
commit 25cef386b8
18 changed files with 152 additions and 8 deletions

View File

@ -609,6 +609,9 @@ pub struct MerchantConnectorCreate {
pub profile_id: Option<String>,
pub pm_auth_config: Option<serde_json::Value>,
#[schema(value_type = ConnectorStatus, example = "inactive")]
pub status: Option<api_enums::ConnectorStatus>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
@ -714,6 +717,9 @@ pub struct MerchantConnectorResponse {
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
#[schema(value_type = ConnectorStatus, example = "inactive")]
pub status: api_enums::ConnectorStatus,
}
/// Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc."
@ -788,6 +794,9 @@ pub struct MerchantConnectorUpdate {
pub connector_webhook_details: Option<MerchantConnectorWebhookDetails>,
pub pm_auth_config: Option<serde_json::Value>,
#[schema(value_type = ConnectorStatus, example = "inactive")]
pub status: Option<api_enums::ConnectorStatus>,
}
///Details of FrmConfigs are mentioned here... it should be passed in payment connector create api call, and stored in merchant_connector_table

View File

@ -1857,3 +1857,25 @@ pub enum ApplePayFlow {
Simplified,
Manual,
}
#[derive(
Clone,
Copy,
Debug,
Eq,
PartialEq,
strum::Display,
strum::EnumString,
serde::Deserialize,
serde::Serialize,
ToSchema,
Default,
)]
#[router_derive::diesel_enum(storage_type = "pg_enum")]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum ConnectorStatus {
#[default]
Inactive,
Active,
}

View File

@ -3,9 +3,10 @@ pub mod diesel_exports {
pub use super::{
DbAttemptStatus as AttemptStatus, DbAuthenticationType as AuthenticationType,
DbCaptureMethod as CaptureMethod, DbCaptureStatus as CaptureStatus,
DbConnectorType as ConnectorType, DbCountryAlpha2 as CountryAlpha2, DbCurrency as Currency,
DbDisputeStage as DisputeStage, DbDisputeStatus as DisputeStatus,
DbEventClass as EventClass, DbEventObjectType as EventObjectType, DbEventType as EventType,
DbConnectorStatus as ConnectorStatus, DbConnectorType as ConnectorType,
DbCountryAlpha2 as CountryAlpha2, DbCurrency as Currency, DbDisputeStage as DisputeStage,
DbDisputeStatus as DisputeStatus, DbEventClass as EventClass,
DbEventObjectType as EventObjectType, DbEventType as EventType,
DbFraudCheckStatus as FraudCheckStatus, DbFraudCheckType as FraudCheckType,
DbFutureUsage as FutureUsage, DbIntentStatus as IntentStatus,
DbMandateStatus as MandateStatus, DbMandateType as MandateType,

View File

@ -42,6 +42,7 @@ pub struct MerchantConnectorAccount {
#[diesel(deserialize_as = super::OptionalDieselArray<String>)]
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: storage_enums::ConnectorStatus,
}
#[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
@ -70,6 +71,7 @@ pub struct MerchantConnectorAccountNew {
#[diesel(deserialize_as = super::OptionalDieselArray<String>)]
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: storage_enums::ConnectorStatus,
}
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
@ -93,6 +95,7 @@ pub struct MerchantConnectorAccountUpdateInternal {
#[diesel(deserialize_as = super::OptionalDieselArray<String>)]
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: Option<storage_enums::ConnectorStatus>,
}
impl MerchantConnectorAccountUpdateInternal {
@ -115,6 +118,7 @@ impl MerchantConnectorAccountUpdateInternal {
frm_config: self.frm_config,
modified_at: self.modified_at.unwrap_or(source.modified_at),
pm_auth_config: self.pm_auth_config,
status: self.status.unwrap_or(source.status),
..source
}

View File

@ -492,6 +492,7 @@ diesel::table! {
profile_id -> Nullable<Varchar>,
applepay_verified_domains -> Nullable<Array<Nullable<Text>>>,
pm_auth_config -> Nullable<Jsonb>,
status -> ConnectorStatus,
}
}

View File

@ -65,6 +65,7 @@ fn build_test_data<'a>(total_enabled: usize, total_pm_types: usize) -> graph::Kn
profile_id: None,
applepay_verified_domains: None,
pm_auth_config: None,
status: api_enums::ConnectorStatus::Inactive,
};
kgraph_utils::mca::make_mca_graph(vec![stripe_account]).expect("Failed graph construction")

View File

@ -410,6 +410,7 @@ mod tests {
profile_id: None,
applepay_verified_domains: None,
pm_auth_config: None,
status: api_enums::ConnectorStatus::Inactive,
};
make_mca_graph(vec![stripe_account]).expect("Failed graph construction")

View File

@ -334,6 +334,7 @@ impl TryFrom<&types::ConnectorAuthType> for SquareAuthType {
| types::ConnectorAuthType::SignatureKey { .. }
| types::ConnectorAuthType::MultiAuthKey { .. }
| types::ConnectorAuthType::CurrencyAuthKey { .. }
| types::ConnectorAuthType::TemporaryAuth { .. }
| types::ConnectorAuthType::NoKey { .. } => {
Err(errors::ConnectorError::FailedToObtainAuthType.into())
}

View File

@ -868,6 +868,15 @@ pub async fn create_payment_connector(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("error updating the merchant account when creating payment connector")?;
let (connector_status, disabled) = validate_status_and_disabled(
req.status,
req.disabled,
auth,
// The validate_status_and_disabled function will use this value only
// when the status can be active. So we are passing this as fallback.
api_enums::ConnectorStatus::Active,
)?;
let merchant_connector_account = domain::MerchantConnectorAccount {
merchant_id: merchant_id.to_string(),
connector_type: req.connector_type,
@ -886,7 +895,7 @@ pub async fn create_payment_connector(
.attach_printable("Unable to encrypt connector account details")?,
payment_methods_enabled,
test_mode: req.test_mode,
disabled: req.disabled,
disabled,
metadata: req.metadata,
frm_configs,
connector_label: Some(connector_label),
@ -911,6 +920,7 @@ pub async fn create_payment_connector(
profile_id: Some(profile_id.clone()),
applepay_verified_domains: None,
pm_auth_config: req.pm_auth_config.clone(),
status: connector_status,
};
let mut default_routing_config =
@ -1083,6 +1093,19 @@ pub async fn update_payment_connector(
let frm_configs = get_frm_config_as_secret(req.frm_configs);
let auth: types::ConnectorAuthType = req
.connector_account_details
.clone()
.unwrap_or(mca.connector_account_details.clone().into_inner())
.parse_value("ConnectorAuthType")
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
field_name: "connector_account_details".to_string(),
expected_format: "auth_type and api_key".to_string(),
})?;
let (connector_status, disabled) =
validate_status_and_disabled(req.status, req.disabled, auth, mca.status)?;
let payment_connector = storage::MerchantConnectorAccountUpdate::Update {
merchant_id: None,
connector_type: Some(req.connector_type),
@ -1098,7 +1121,7 @@ pub async fn update_payment_connector(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while encrypting data")?,
test_mode: req.test_mode,
disabled: req.disabled,
disabled,
payment_methods_enabled,
metadata: req.metadata,
frm_configs,
@ -1115,6 +1138,7 @@ pub async fn update_payment_connector(
},
applepay_verified_domains: None,
pm_auth_config: req.pm_auth_config,
status: Some(connector_status),
};
let updated_mca = db
@ -1722,3 +1746,37 @@ pub async fn validate_dummy_connector_enabled(
Ok(())
}
}
pub fn validate_status_and_disabled(
status: Option<api_enums::ConnectorStatus>,
disabled: Option<bool>,
auth: types::ConnectorAuthType,
current_status: api_enums::ConnectorStatus,
) -> RouterResult<(api_enums::ConnectorStatus, Option<bool>)> {
let connector_status = match (status, auth) {
(Some(common_enums::ConnectorStatus::Active), types::ConnectorAuthType::TemporaryAuth) => {
return Err(errors::ApiErrorResponse::InvalidRequestData {
message: "Connector status cannot be active when using TemporaryAuth".to_string(),
}
.into());
}
(Some(status), _) => status,
(None, types::ConnectorAuthType::TemporaryAuth) => common_enums::ConnectorStatus::Inactive,
(None, _) => current_status,
};
let disabled = match (disabled, connector_status) {
(Some(true), common_enums::ConnectorStatus::Inactive) => {
return Err(errors::ApiErrorResponse::InvalidRequestData {
message: "Connector cannot be enabled when connector_status is inactive or when using TemporaryAuth"
.to_string(),
}
.into());
}
(Some(disabled), _) => Some(disabled),
(None, common_enums::ConnectorStatus::Inactive) => Some(true),
(None, _) => None,
};
Ok((connector_status, disabled))
}

View File

@ -60,6 +60,7 @@ pub async fn check_existence_and_add_domain_to_db(
applepay_verified_domains: Some(already_verified_domains.clone()),
pm_auth_config: None,
connector_label: None,
status: None,
};
state
.store

View File

@ -643,6 +643,7 @@ impl MerchantConnectorAccountInterface for MockDb {
profile_id: t.profile_id,
applepay_verified_domains: t.applepay_verified_domains,
pm_auth_config: t.pm_auth_config,
status: t.status,
};
accounts.push(account.clone());
account
@ -839,6 +840,7 @@ mod merchant_connector_account_cache_tests {
profile_id: Some(profile_id.to_string()),
applepay_verified_domains: None,
pm_auth_config: None,
status: common_enums::ConnectorStatus::Inactive,
};
db.insert_merchant_connector_account(mca.clone(), &merchant_key)

View File

@ -174,6 +174,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::enums::AttemptStatus,
api_models::enums::CaptureStatus,
api_models::enums::ReconStatus,
api_models::enums::ConnectorStatus,
api_models::admin::MerchantConnectorCreate,
api_models::admin::MerchantConnectorUpdate,
api_models::admin::PrimaryBusinessDetails,

View File

@ -900,6 +900,7 @@ pub struct ResponseRouterData<Flow, R, Request, Response> {
#[derive(Default, Debug, Clone, serde::Deserialize)]
#[serde(tag = "auth_type")]
pub enum ConnectorAuthType {
TemporaryAuth,
HeaderKey {
api_key: Secret<String>,
},

View File

@ -35,6 +35,7 @@ pub struct MerchantConnectorAccount {
pub profile_id: Option<String>,
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: enums::ConnectorStatus,
}
#[derive(Debug)]
@ -54,6 +55,7 @@ pub enum MerchantConnectorAccountUpdate {
applepay_verified_domains: Option<Vec<String>>,
pm_auth_config: Option<serde_json::Value>,
connector_label: Option<String>,
status: Option<enums::ConnectorStatus>,
},
}
@ -89,6 +91,7 @@ impl behaviour::Conversion for MerchantConnectorAccount {
profile_id: self.profile_id,
applepay_verified_domains: self.applepay_verified_domains,
pm_auth_config: self.pm_auth_config,
status: self.status,
},
)
}
@ -128,6 +131,7 @@ impl behaviour::Conversion for MerchantConnectorAccount {
profile_id: other.profile_id,
applepay_verified_domains: other.applepay_verified_domains,
pm_auth_config: other.pm_auth_config,
status: other.status,
})
}
@ -155,6 +159,7 @@ impl behaviour::Conversion for MerchantConnectorAccount {
profile_id: self.profile_id,
applepay_verified_domains: self.applepay_verified_domains,
pm_auth_config: self.pm_auth_config,
status: self.status,
})
}
}
@ -177,6 +182,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
applepay_verified_domains,
pm_auth_config,
connector_label,
status,
} => Self {
merchant_id,
connector_type,
@ -194,6 +200,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
applepay_verified_domains,
pm_auth_config,
connector_label,
status,
},
}
}

View File

@ -852,6 +852,7 @@ impl TryFrom<domain::MerchantConnectorAccount> for api_models::admin::MerchantCo
profile_id: item.profile_id,
applepay_verified_domains: item.applepay_verified_domains,
pm_auth_config: item.pm_auth_config,
status: item.status,
})
}
}

View File

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
ALTER TABLE merchant_connector_account DROP COLUMN IF EXISTS status;
DROP TYPE IF EXISTS "ConnectorStatus";

View File

@ -0,0 +1,11 @@
-- Your SQL goes here
CREATE TYPE "ConnectorStatus" AS ENUM ('active', 'inactive');
ALTER TABLE merchant_connector_account
ADD COLUMN status "ConnectorStatus";
UPDATE merchant_connector_account SET status='active';
ALTER TABLE merchant_connector_account
ALTER COLUMN status SET NOT NULL,
ALTER COLUMN status SET DEFAULT 'inactive';

View File

@ -4147,6 +4147,13 @@
}
}
},
"ConnectorStatus": {
"type": "string",
"enum": [
"inactive",
"active"
]
},
"ConnectorType": {
"type": "string",
"enum": [
@ -6871,7 +6878,8 @@
"description": "Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc.\"",
"required": [
"connector_type",
"connector_name"
"connector_name",
"status"
],
"properties": {
"connector_type": {
@ -7002,6 +7010,9 @@
},
"pm_auth_config": {
"nullable": true
},
"status": {
"$ref": "#/components/schemas/ConnectorStatus"
}
}
},
@ -7087,7 +7098,8 @@
"required": [
"connector_type",
"connector_name",
"merchant_connector_id"
"merchant_connector_id",
"status"
],
"properties": {
"connector_type": {
@ -7230,6 +7242,9 @@
},
"pm_auth_config": {
"nullable": true
},
"status": {
"$ref": "#/components/schemas/ConnectorStatus"
}
}
},
@ -7237,7 +7252,8 @@
"type": "object",
"description": "Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc.\"",
"required": [
"connector_type"
"connector_type",
"status"
],
"properties": {
"connector_type": {
@ -7335,6 +7351,9 @@
},
"pm_auth_config": {
"nullable": true
},
"status": {
"$ref": "#/components/schemas/ConnectorStatus"
}
}
},