feat(core): routes to toggle blocklist (#3568)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Shanks <shashank.attarde@juspay.in>
This commit is contained in:
Prajjwal Kumar
2024-02-07 17:22:48 +05:30
committed by GitHub
parent a15e7ae9b1
commit fbe84b2a33
10 changed files with 186 additions and 0 deletions

View File

@ -22,6 +22,11 @@ pub struct BlocklistResponse {
pub created_at: time::PrimitiveDateTime, pub created_at: time::PrimitiveDateTime,
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ToggleBlocklistResponse {
pub blocklist_guard_status: String,
}
pub type AddToBlocklistResponse = BlocklistResponse; pub type AddToBlocklistResponse = BlocklistResponse;
pub type DeleteFromBlocklistResponse = BlocklistResponse; pub type DeleteFromBlocklistResponse = BlocklistResponse;
@ -39,6 +44,14 @@ fn default_list_limit() -> u16 {
10 10
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ToggleBlocklistQuery {
#[schema(value_type = BlocklistDataKind)]
pub status: bool,
}
impl ApiEventMetric for BlocklistRequest {} impl ApiEventMetric for BlocklistRequest {}
impl ApiEventMetric for BlocklistResponse {} impl ApiEventMetric for BlocklistResponse {}
impl ApiEventMetric for ToggleBlocklistResponse {}
impl ApiEventMetric for ListBlocklistQuery {} impl ApiEventMetric for ListBlocklistQuery {}
impl ApiEventMetric for ToggleBlocklistQuery {}

View File

@ -151,6 +151,7 @@ Never share your secret api keys. Keep them guarded and secure.
routes::blocklist::remove_entry_from_blocklist, routes::blocklist::remove_entry_from_blocklist,
routes::blocklist::list_blocked_payment_methods, routes::blocklist::list_blocked_payment_methods,
routes::blocklist::add_entry_to_blocklist, routes::blocklist::add_entry_to_blocklist,
routes::blocklist::toggle_blocklist_guard,
// Routes for payouts // Routes for payouts
routes::payouts::payouts_create, routes::payouts::payouts_create,
@ -450,6 +451,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::PaymentLinkStatus, api_models::payments::PaymentLinkStatus,
api_models::blocklist::BlocklistRequest, api_models::blocklist::BlocklistRequest,
api_models::blocklist::BlocklistResponse, api_models::blocklist::BlocklistResponse,
api_models::blocklist::ToggleBlocklistResponse,
api_models::blocklist::ListBlocklistQuery, api_models::blocklist::ListBlocklistQuery,
api_models::enums::BlocklistDataKind api_models::enums::BlocklistDataKind
)), )),

View File

@ -1,3 +1,19 @@
#[utoipa::path(
post,
path = "/blocklist/toggle",
params (
("status" = bool, Query, description = "Boolean value to enable/disable blocklist"),
),
responses(
(status = 200, description = "Blocklist guard enabled/disabled", body = ToggleBlocklistResponse),
(status = 400, description = "Invalid Data")
),
tag = "Blocklist",
operation_id = "Toggle blocklist guard for a particular merchant",
security(("api_key" = []))
)]
pub async fn toggle_blocklist_guard() {}
#[utoipa::path( #[utoipa::path(
post, post,
path = "/blocklist", path = "/blocklist",

View File

@ -39,3 +39,13 @@ pub async fn list_blocklist_entries(
.await .await
.map(services::ApplicationResponse::Json) .map(services::ApplicationResponse::Json)
} }
pub async fn toggle_blocklist_guard(
state: AppState,
merchant_account: domain::MerchantAccount,
query: api_blocklist::ToggleBlocklistQuery,
) -> RouterResponse<api_blocklist::ToggleBlocklistResponse> {
utils::toggle_blocklist_guard_for_merchant(&state, merchant_account.merchant_id, query)
.await
.map(services::ApplicationResponse::Json)
}

View File

@ -4,6 +4,7 @@ use common_utils::{
crypto::{self, SignMessage}, crypto::{self, SignMessage},
errors::CustomResult, errors::CustomResult,
}; };
use diesel_models::configs;
use error_stack::{IntoReport, ResultExt}; use error_stack::{IntoReport, ResultExt};
#[cfg(feature = "aws_kms")] #[cfg(feature = "aws_kms")]
use external_services::aws_kms; use external_services::aws_kms;
@ -85,6 +86,56 @@ pub async fn delete_entry_from_blocklist(
Ok(blocklist_entry.foreign_into()) Ok(blocklist_entry.foreign_into())
} }
pub async fn toggle_blocklist_guard_for_merchant(
state: &AppState,
merchant_id: String,
query: api_blocklist::ToggleBlocklistQuery,
) -> CustomResult<api_blocklist::ToggleBlocklistResponse, errors::ApiErrorResponse> {
let key = get_blocklist_guard_key(merchant_id.as_str());
let maybe_guard = state.store.find_config_by_key(&key).await;
let new_config = configs::ConfigNew {
key: key.clone(),
config: query.status.to_string(),
};
match maybe_guard {
Ok(_config) => {
let updated_config = configs::ConfigUpdate::Update {
config: Some(query.status.to_string()),
};
state
.store
.update_config_by_key(&key, updated_config)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error enabling the blocklist guard")?;
}
Err(e) if e.current_context().is_db_not_found() => {
state
.store
.insert_config(new_config)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error enabling the blocklist guard")?;
}
Err(e) => {
logger::error!(error=?e);
Err(e)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error enabling the blocklist guard")?;
}
};
let guard_status = if query.status { "enabled" } else { "disabled" };
Ok(api_blocklist::ToggleBlocklistResponse {
blocklist_guard_status: guard_status.to_string(),
})
}
/// Provides the identifier for the specific merchant's blocklist guard config
#[inline(always)]
pub fn get_blocklist_guard_key(merchant_id: &str) -> String {
format!("guard_blocklist_for_{merchant_id}")
}
pub async fn list_blocklist_entries_for_merchant( pub async fn list_blocklist_entries_for_merchant(
state: &AppState, state: &AppState,
merchant_id: String, merchant_id: String,

View File

@ -658,6 +658,9 @@ impl Blocklist {
.route(web::post().to(blocklist::add_entry_to_blocklist)) .route(web::post().to(blocklist::add_entry_to_blocklist))
.route(web::delete().to(blocklist::remove_entry_from_blocklist)), .route(web::delete().to(blocklist::remove_entry_from_blocklist)),
) )
.service(
web::resource("/toggle").route(web::post().to(blocklist::toggle_blocklist_guard)),
)
} }
} }

View File

@ -117,3 +117,41 @@ pub async fn list_blocked_payment_methods(
)) ))
.await .await
} }
#[utoipa::path(
post,
path = "/blocklist/toggle",
params (
("status" = bool, Query, description = "Boolean value to enable/disable blocklist"),
),
responses(
(status = 200, description = "Blocklist guard enabled/disabled", body = ToggleBlocklistResponse),
(status = 400, description = "Invalid Data")
),
tag = "Blocklist",
operation_id = "Toggle blocklist guard for a particular merchant",
security(("api_key" = []))
)]
pub async fn toggle_blocklist_guard(
state: web::Data<AppState>,
req: HttpRequest,
query_payload: web::Query<api_blocklist::ToggleBlocklistQuery>,
) -> HttpResponse {
let flow = Flow::ListBlocklist;
Box::pin(api::server_wrap(
flow,
state,
&req,
query_payload.into_inner(),
|state, auth: auth::AuthenticationData, query| {
blocklist::toggle_blocklist_guard(state, auth.merchant_account, query)
},
auth::auth_type(
&auth::ApiKeyAuth,
&auth::JWTAuth(Permission::MerchantAccountWrite),
req.headers(),
),
api_locking::LockAction::NotApplicable,
))
.await
}

View File

@ -63,6 +63,7 @@ impl From<Flow> for ApiIdentifier {
Flow::AddToBlocklist => Self::Blocklist, Flow::AddToBlocklist => Self::Blocklist,
Flow::DeleteFromBlocklist => Self::Blocklist, Flow::DeleteFromBlocklist => Self::Blocklist,
Flow::ListBlocklist => Self::Blocklist, Flow::ListBlocklist => Self::Blocklist,
Flow::ToggleBlocklistGuard => Self::Blocklist,
Flow::MerchantConnectorsCreate Flow::MerchantConnectorsCreate
| Flow::MerchantConnectorsRetrieve | Flow::MerchantConnectorsRetrieve

View File

@ -201,6 +201,8 @@ pub enum Flow {
DeleteFromBlocklist, DeleteFromBlocklist,
/// List entries from blocklist /// List entries from blocklist
ListBlocklist, ListBlocklist,
/// Toggle blocklist for merchant
ToggleBlocklistGuard,
/// Incoming Webhook Receive /// Incoming Webhook Receive
IncomingWebhookReceive, IncomingWebhookReceive,
/// Validate payment method flow /// Validate payment method flow

View File

@ -1233,6 +1233,45 @@
] ]
} }
}, },
"/blocklist/toggle": {
"post": {
"tags": [
"Blocklist"
],
"operationId": "Toggle blocklist guard for a particular merchant",
"parameters": [
{
"name": "status",
"in": "query",
"description": "Boolean value to enable/disable blocklist",
"required": true,
"schema": {
"type": "boolean"
}
}
],
"responses": {
"200": {
"description": "Blocklist guard enabled/disabled",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ToggleBlocklistResponse"
}
}
}
},
"400": {
"description": "Invalid Data"
}
},
"security": [
{
"api_key": []
}
]
}
},
"/customers": { "/customers": {
"post": { "post": {
"tags": [ "tags": [
@ -16114,6 +16153,17 @@
} }
} }
}, },
"ToggleBlocklistResponse": {
"type": "object",
"required": [
"blocklist_guard_status"
],
"properties": {
"blocklist_guard_status": {
"type": "string"
}
}
},
"TouchNGoRedirection": { "TouchNGoRedirection": {
"type": "object" "type": "object"
}, },