feat: add a kv switch route for merchants (#518)

This commit is contained in:
Nishant Joshi
2023-02-09 19:18:18 +05:30
committed by GitHub
parent 3292960996
commit 763620fcc7
6 changed files with 158 additions and 1 deletions

View File

@ -340,3 +340,20 @@ pub struct DeleteMcaResponse {
#[schema(example = false)]
pub deleted: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ToggleKVResponse {
/// The identifier for the Merchant Account
#[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44")]
pub merchant_id: String,
/// Status of KV for the specific merchant
#[schema(example = true)]
pub kv_enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ToggleKVRequest {
/// Status of KV for the specific merchant
#[schema(example = true)]
pub kv_enabled: bool,
}

View File

@ -1,5 +1,6 @@
use common_utils::ext_traits::ValueExt;
use error_stack::{report, FutureExt, ResultExt};
use storage_models::{enums, merchant_account};
use uuid::Uuid;
use crate::{
@ -464,3 +465,81 @@ pub async fn delete_payment_connector(
};
Ok(service_api::ApplicationResponse::Json(response))
}
pub async fn kv_for_merchant(
db: &dyn StorageInterface,
merchant_id: String,
enable: bool,
) -> RouterResponse<api_models::admin::ToggleKVResponse> {
// check if the merchant account exists
let merchant_account = db
.find_merchant_account_by_merchant_id(&merchant_id)
.await
.map_err(|error| {
error.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
})?;
let updated_merchant_account = match (enable, merchant_account.storage_scheme) {
(true, enums::MerchantStorageScheme::RedisKv)
| (false, enums::MerchantStorageScheme::PostgresOnly) => Ok(merchant_account),
(true, enums::MerchantStorageScheme::PostgresOnly) => {
db.update_merchant(
merchant_account,
merchant_account::MerchantAccountUpdate::StorageSchemeUpdate {
storage_scheme: enums::MerchantStorageScheme::RedisKv,
},
)
.await
}
(false, enums::MerchantStorageScheme::RedisKv) => {
db.update_merchant(
merchant_account,
merchant_account::MerchantAccountUpdate::StorageSchemeUpdate {
storage_scheme: enums::MerchantStorageScheme::PostgresOnly,
},
)
.await
}
}
.map_err(|error| {
error
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("failed to switch merchant_storage_scheme")
})?;
let kv_status = matches!(
updated_merchant_account.storage_scheme,
enums::MerchantStorageScheme::RedisKv
);
Ok(service_api::ApplicationResponse::Json(
api_models::admin::ToggleKVResponse {
merchant_id: updated_merchant_account.merchant_id,
kv_enabled: kv_status,
},
))
}
pub async fn check_merchant_account_kv_status(
db: &dyn StorageInterface,
merchant_id: String,
) -> RouterResponse<api_models::admin::ToggleKVResponse> {
// check if the merchant account exists
let merchant_account = db
.find_merchant_account_by_merchant_id(&merchant_id)
.await
.map_err(|error| {
error.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
})?;
let kv_status = matches!(
merchant_account.storage_scheme,
enums::MerchantStorageScheme::RedisKv
);
Ok(service_api::ApplicationResponse::Json(
api_models::admin::ToggleKVResponse {
merchant_id: merchant_account.merchant_id,
kv_enabled: kv_status,
},
))
}

View File

@ -337,3 +337,49 @@ pub async fn payment_connector_delete(
)
.await
}
// Merchant Account - Toggle KV
///
/// Toggle KV mode for the Merchant Account
#[instrument(skip_all)]
pub async fn merchant_account_toggle_kv(
state: web::Data<AppState>,
req: HttpRequest,
path: web::Path<String>,
json_payload: web::Json<admin::ToggleKVRequest>,
) -> HttpResponse {
let payload = json_payload.into_inner();
let merchant_id = path.into_inner();
api::server_wrap(
state.get_ref(),
&req,
(merchant_id, payload),
|state, _, (merchant_id, payload)| {
kv_for_merchant(&*state.store, merchant_id, payload.kv_enabled)
},
&auth::AdminApiAuth,
)
.await
}
// Merchant Account - KV Status
///
/// Toggle KV mode for the Merchant Account
#[instrument(skip_all)]
pub async fn merchant_account_kv_status(
state: web::Data<AppState>,
req: HttpRequest,
path: web::Path<String>,
) -> HttpResponse {
let merchant_id = path.into_inner();
api::server_wrap(
state.get_ref(),
&req,
merchant_id,
|state, _, req| check_merchant_account_kv_status(&*state.store, req),
&auth::AdminApiAuth,
)
.await
}

View File

@ -226,6 +226,11 @@ impl MerchantAccount {
web::scope("/accounts")
.app_data(web::Data::new(state))
.service(web::resource("").route(web::post().to(merchant_account_create)))
.service(
web::resource("/{id}/kv")
.route(web::post().to(merchant_account_toggle_kv))
.route(web::get().to(merchant_account_kv_status)),
)
.service(
web::resource("/{id}")
.route(web::get().to(retrieve_merchant_account))

View File

@ -1,7 +1,8 @@
pub use api_models::admin::{
CreateMerchantAccount, DeleteMcaResponse, DeleteMerchantAccountResponse,
MerchantAccountResponse, MerchantConnectorId, MerchantDetails, MerchantId,
PaymentConnectorCreate, PaymentMethods, RoutingAlgorithm, WebhookDetails,
PaymentConnectorCreate, PaymentMethods, RoutingAlgorithm, ToggleKVRequest, ToggleKVResponse,
WebhookDetails,
};
use crate::types::{storage, transformers::Foreign};

View File

@ -73,6 +73,9 @@ pub enum MerchantAccountUpdate {
metadata: Option<serde_json::Value>,
routing_algorithm: Option<serde_json::Value>,
},
StorageSchemeUpdate {
storage_scheme: storage_enums::MerchantStorageScheme,
},
}
#[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
@ -89,6 +92,7 @@ pub struct MerchantAccountUpdateInternal {
payment_response_hash_key: Option<String>,
redirect_to_merchant_with_http_post: Option<bool>,
publishable_key: Option<String>,
storage_scheme: Option<storage_enums::MerchantStorageScheme>,
locker_id: Option<String>,
metadata: Option<serde_json::Value>,
routing_algorithm: Option<serde_json::Value>,
@ -127,6 +131,11 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
publishable_key,
locker_id,
metadata,
..Default::default()
},
MerchantAccountUpdate::StorageSchemeUpdate { storage_scheme } => Self {
storage_scheme: Some(storage_scheme),
..Default::default()
},
}
}