mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-03 21:37:41 +08:00
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:
@ -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 {}
|
||||||
|
|||||||
@ -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
|
||||||
)),
|
)),
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user