mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
refactor: Replace Bach with Application on every naming (#292)
This commit is contained in:
@ -1,12 +1,12 @@
|
||||
use router::{
|
||||
configs::settings::{CmdLineConf, Settings, Subcommand},
|
||||
core::errors::{BachError, BachResult},
|
||||
core::errors::{ApplicationError, ApplicationResult},
|
||||
logger,
|
||||
};
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> BachResult<()> {
|
||||
async fn main() -> ApplicationResult<()> {
|
||||
// get commandline config before initializing config
|
||||
let cmd_line = CmdLineConf::from_args();
|
||||
|
||||
@ -41,7 +41,7 @@ async fn main() -> BachResult<()> {
|
||||
|
||||
state.store.close().await;
|
||||
|
||||
Err(BachError::from(std::io::Error::new(
|
||||
Err(ApplicationError::from(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"Server shut down",
|
||||
)))
|
||||
|
||||
@ -21,7 +21,7 @@ pub async fn compatibility_api_wrap<'a, 'b, U, T, Q, F, Fut, S, E>(
|
||||
) -> HttpResponse
|
||||
where
|
||||
F: Fn(&'b routes::AppState, U, T) -> Fut,
|
||||
Fut: Future<Output = RouterResult<api::BachResponse<Q>>>,
|
||||
Fut: Future<Output = RouterResult<api::ApplicationResponse<Q>>>,
|
||||
Q: Serialize + std::fmt::Debug + 'a,
|
||||
S: From<Q> + Serialize,
|
||||
E: From<errors::ApiErrorResponse> + Serialize + error_stack::Context + actix_web::ResponseError,
|
||||
@ -29,7 +29,7 @@ where
|
||||
{
|
||||
let resp = api::server_wrap_util(state, request, payload, func, api_authentication).await;
|
||||
match resp {
|
||||
Ok(api::BachResponse::Json(router_resp)) => {
|
||||
Ok(api::ApplicationResponse::Json(router_resp)) => {
|
||||
let pg_resp = S::try_from(router_resp);
|
||||
match pg_resp {
|
||||
Ok(pg_resp) => match serde_json::to_string(&pg_resp) {
|
||||
@ -51,9 +51,9 @@ where
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(api::BachResponse::StatusOk) => api::http_response_ok(),
|
||||
Ok(api::BachResponse::TextPlain(text)) => api::http_response_plaintext(text),
|
||||
Ok(api::BachResponse::JsonForRedirection(response)) => {
|
||||
Ok(api::ApplicationResponse::StatusOk) => api::http_response_ok(),
|
||||
Ok(api::ApplicationResponse::TextPlain(text)) => api::http_response_plaintext(text),
|
||||
Ok(api::ApplicationResponse::JsonForRedirection(response)) => {
|
||||
match serde_json::to_string(&response) {
|
||||
Ok(res) => api::http_redirect_response(res, response),
|
||||
Err(_) => api::http_response_err(
|
||||
@ -65,7 +65,7 @@ where
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(api::BachResponse::Form(form_data)) => api::build_redirection_form(&form_data)
|
||||
Ok(api::ApplicationResponse::Form(form_data)) => api::build_redirection_form(&form_data)
|
||||
.respond_to(request)
|
||||
.map_into_boxed_body(),
|
||||
Err(error) => {
|
||||
|
||||
@ -42,6 +42,10 @@ jwt_secret="secret"
|
||||
[eph_key]
|
||||
validity = 1
|
||||
|
||||
[refund]
|
||||
max_attempts = 10
|
||||
max_age = 365
|
||||
|
||||
[scheduler]
|
||||
stream = "SCHEDULER_STREAM"
|
||||
consumer_group = "SCHEDULER_GROUP"
|
||||
|
||||
@ -7,7 +7,7 @@ use serde::Deserialize;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use crate::{
|
||||
core::errors::{BachError, BachResult},
|
||||
core::errors::{ApplicationError, ApplicationResult},
|
||||
env::{self, logger, Env},
|
||||
};
|
||||
|
||||
@ -42,6 +42,7 @@ pub struct Settings {
|
||||
pub keys: Keys, //remove this during refactoring
|
||||
pub locker: Locker,
|
||||
pub connectors: Connectors,
|
||||
pub refund: Refund,
|
||||
pub eph_key: EphemeralConfig,
|
||||
pub scheduler: Option<SchedulerSettings>,
|
||||
#[cfg(feature = "kv_store")]
|
||||
@ -67,6 +68,12 @@ pub struct Locker {
|
||||
pub basilisk_host: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct Refund {
|
||||
pub max_attempts: usize,
|
||||
pub max_age: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct EphemeralConfig {
|
||||
pub validity: i64,
|
||||
@ -163,11 +170,11 @@ pub struct DrainerSettings {
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn new() -> BachResult<Self> {
|
||||
pub fn new() -> ApplicationResult<Self> {
|
||||
Self::with_config_path(None)
|
||||
}
|
||||
|
||||
pub fn with_config_path(config_path: Option<PathBuf>) -> BachResult<Self> {
|
||||
pub fn with_config_path(config_path: Option<PathBuf>) -> ApplicationResult<Self> {
|
||||
let environment = env::which();
|
||||
let config_path = router_env::Config::config_path(&environment.to_string(), config_path);
|
||||
|
||||
@ -199,7 +206,7 @@ impl Settings {
|
||||
serde_path_to_error::deserialize(config).map_err(|error| {
|
||||
logger::error!(%error, "Unable to deserialize application configuration");
|
||||
eprintln!("Unable to deserialize application configuration: {error}");
|
||||
BachError::from(error.into_inner())
|
||||
ApplicationError::from(error.into_inner())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,8 +720,9 @@ impl api::IncomingWebhook for Adyen {
|
||||
|
||||
fn get_webhook_api_response(
|
||||
&self,
|
||||
) -> CustomResult<services::api::BachResponse<serde_json::Value>, errors::ConnectorError> {
|
||||
Ok(services::api::BachResponse::TextPlain(
|
||||
) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
|
||||
{
|
||||
Ok(services::api::ApplicationResponse::TextPlain(
|
||||
"[accepted]".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ pub async fn create_merchant_account(
|
||||
.map_err(|error| {
|
||||
error.to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)
|
||||
})?;
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn get_merchant_account(
|
||||
@ -128,7 +128,7 @@ pub async fn get_merchant_account(
|
||||
publishable_key: merchant_account.publishable_key,
|
||||
locker_id: merchant_account.locker_id,
|
||||
};
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn merchant_account_update(
|
||||
@ -226,7 +226,7 @@ pub async fn merchant_account_update(
|
||||
db.update_merchant(merchant_account, updated_merchant_account)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn merchant_account_delete(
|
||||
@ -243,7 +243,7 @@ pub async fn merchant_account_delete(
|
||||
merchant_id,
|
||||
deleted: is_deleted,
|
||||
};
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
async fn get_parent_merchant(
|
||||
@ -340,7 +340,7 @@ pub async fn create_payment_connector(
|
||||
})?;
|
||||
|
||||
response.merchant_connector_id = Some(mca.merchant_connector_id);
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn retrieve_payment_connector(
|
||||
@ -365,7 +365,9 @@ pub async fn retrieve_payment_connector(
|
||||
error.to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound)
|
||||
})?;
|
||||
|
||||
Ok(service_api::BachResponse::Json(mca.foreign_try_into()?))
|
||||
Ok(service_api::ApplicationResponse::Json(
|
||||
mca.foreign_try_into()?,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn list_payment_connectors(
|
||||
@ -393,7 +395,7 @@ pub async fn list_payment_connectors(
|
||||
response.push(mca.foreign_try_into()?);
|
||||
}
|
||||
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn update_payment_connector(
|
||||
@ -460,7 +462,7 @@ pub async fn update_payment_connector(
|
||||
payment_methods_enabled: req.payment_methods_enabled,
|
||||
metadata: req.metadata,
|
||||
};
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn delete_payment_connector(
|
||||
@ -489,5 +491,5 @@ pub async fn delete_payment_connector(
|
||||
merchant_connector_id,
|
||||
deleted: is_deleted,
|
||||
};
|
||||
Ok(service_api::BachResponse::Json(response))
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ pub async fn create_customer(
|
||||
let mut customer_response: customers::CustomerResponse = customer.into();
|
||||
customer_response.address = customer_data.address;
|
||||
|
||||
Ok(services::BachResponse::Json(customer_response))
|
||||
Ok(services::ApplicationResponse::Json(customer_response))
|
||||
}
|
||||
|
||||
#[instrument(skip(db))]
|
||||
@ -94,7 +94,7 @@ pub async fn retrieve_customer(
|
||||
.await
|
||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::CustomerNotFound))?;
|
||||
|
||||
Ok(services::BachResponse::Json(response.into()))
|
||||
Ok(services::ApplicationResponse::Json(response.into()))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -190,7 +190,7 @@ pub async fn delete_customer(
|
||||
address_deleted: true,
|
||||
payment_methods_deleted: true,
|
||||
};
|
||||
Ok(services::BachResponse::Json(response))
|
||||
Ok(services::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
#[instrument(skip(db))]
|
||||
@ -247,5 +247,7 @@ pub async fn update_customer(
|
||||
|
||||
let mut customer_update_response: customers::CustomerResponse = response.into();
|
||||
customer_update_response.address = update_customer.address;
|
||||
Ok(services::BachResponse::Json(customer_update_response))
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
customer_update_response,
|
||||
))
|
||||
}
|
||||
|
||||
@ -16,11 +16,10 @@ pub use self::api_error_response::ApiErrorResponse;
|
||||
pub(crate) use self::utils::{ConnectorErrorExt, StorageErrorExt};
|
||||
use crate::services;
|
||||
pub type RouterResult<T> = CustomResult<T, ApiErrorResponse>;
|
||||
pub type RouterResponse<T> = CustomResult<services::BachResponse<T>, ApiErrorResponse>;
|
||||
pub type RouterResponse<T> = CustomResult<services::ApplicationResponse<T>, ApiErrorResponse>;
|
||||
|
||||
// FIXME: Phase out BachResult and BachResponse
|
||||
pub type BachResult<T> = Result<T, BachError>;
|
||||
pub type BachResponse<T> = BachResult<services::BachResponse<T>>;
|
||||
pub type ApplicationResult<T> = Result<T, ApplicationError>;
|
||||
pub type ApplicationResponse<T> = ApplicationResult<services::ApplicationResponse<T>>;
|
||||
|
||||
macro_rules! impl_error_display {
|
||||
($st: ident, $arg: tt) => {
|
||||
@ -50,7 +49,7 @@ macro_rules! impl_error_type {
|
||||
// FIXME: Make this a derive macro instead
|
||||
macro_rules! router_error_error_stack_specific {
|
||||
($($path: ident)::+ < $st: ident >, $($path2:ident)::* ($($inner_path2:ident)::+ <$st2:ident>) ) => {
|
||||
impl From<$($path)::+ <$st>> for BachError {
|
||||
impl From<$($path)::+ <$st>> for ApplicationError {
|
||||
fn from(err: $($path)::+ <$st> ) -> Self {
|
||||
$($path2)::*(err)
|
||||
}
|
||||
@ -58,7 +57,7 @@ macro_rules! router_error_error_stack_specific {
|
||||
};
|
||||
|
||||
($($path: ident)::+ <$($inner_path:ident)::+>, $($path2:ident)::* ($($inner_path2:ident)::+ <$st2:ident>) ) => {
|
||||
impl<'a> From< $($path)::+ <$($inner_path)::+> > for BachError {
|
||||
impl<'a> From< $($path)::+ <$($inner_path)::+> > for ApplicationError {
|
||||
fn from(err: $($path)::+ <$($inner_path)::+> ) -> Self {
|
||||
$($path2)::*(err)
|
||||
}
|
||||
@ -114,7 +113,7 @@ impl_error_type!(EncryptionError, "Encryption error");
|
||||
impl_error_type!(UnexpectedError, "Unexpected error");
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BachError {
|
||||
pub enum ApplicationError {
|
||||
// Display's impl can be overridden by the attribute error marco.
|
||||
// Don't use Debug here, Debug gives error stack in response.
|
||||
#[error("{{ error_description: Error while Authenticating, error_message: {0} }}")]
|
||||
@ -150,32 +149,32 @@ pub enum BachError {
|
||||
|
||||
router_error_error_stack_specific!(
|
||||
error_stack::Report<storage_errors::DatabaseError>,
|
||||
BachError::EDatabaseError(error_stack::Report<DatabaseError>)
|
||||
ApplicationError::EDatabaseError(error_stack::Report<DatabaseError>)
|
||||
);
|
||||
router_error_error_stack_specific!(
|
||||
error_stack::Report<AuthenticationError>,
|
||||
BachError::EAuthenticationError(error_stack::Report<AuthenticationError>)
|
||||
ApplicationError::EAuthenticationError(error_stack::Report<AuthenticationError>)
|
||||
);
|
||||
router_error_error_stack_specific!(
|
||||
error_stack::Report<UnexpectedError>,
|
||||
BachError::EUnexpectedError(error_stack::Report<UnexpectedError>)
|
||||
ApplicationError::EUnexpectedError(error_stack::Report<UnexpectedError>)
|
||||
);
|
||||
router_error_error_stack_specific!(
|
||||
error_stack::Report<ParsingError>,
|
||||
BachError::EParsingError(error_stack::Report<ParsingError>)
|
||||
ApplicationError::EParsingError(error_stack::Report<ParsingError>)
|
||||
);
|
||||
router_error_error_stack_specific!(
|
||||
error_stack::Report<EncryptionError>,
|
||||
BachError::EEncryptionError(error_stack::Report<EncryptionError>)
|
||||
ApplicationError::EEncryptionError(error_stack::Report<EncryptionError>)
|
||||
);
|
||||
|
||||
impl From<MetricsError> for BachError {
|
||||
impl From<MetricsError> for ApplicationError {
|
||||
fn from(err: MetricsError) -> Self {
|
||||
Self::EMetrics(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for BachError {
|
||||
impl From<std::io::Error> for ApplicationError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Self::EIo(err)
|
||||
}
|
||||
@ -187,7 +186,7 @@ impl From<ring::error::Unspecified> for EncryptionError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConfigError> for BachError {
|
||||
impl From<ConfigError> for ApplicationError {
|
||||
fn from(err: ConfigError) -> Self {
|
||||
Self::ConfigurationError(err)
|
||||
}
|
||||
@ -202,7 +201,7 @@ fn error_response<T: Display>(err: &T) -> actix_web::HttpResponse {
|
||||
))
|
||||
}
|
||||
|
||||
impl ResponseError for BachError {
|
||||
impl ResponseError for ApplicationError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
Self::EParsingError(_)
|
||||
|
||||
@ -30,7 +30,7 @@ pub async fn get_mandate(
|
||||
.find_mandate_by_merchant_id_mandate_id(&merchant_account.merchant_id, &req.mandate_id)
|
||||
.await
|
||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?;
|
||||
Ok(services::BachResponse::Json(
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
mandates::MandateResponse::from_db_mandate(state, mandate, &merchant_account).await?,
|
||||
))
|
||||
}
|
||||
@ -52,7 +52,7 @@ pub async fn revoke_mandate(
|
||||
.await
|
||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?;
|
||||
|
||||
Ok(services::BachResponse::Json(
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
mandates::MandateRevokedResponse {
|
||||
mandate_id: mandate.mandate_id,
|
||||
status: mandate.mandate_status.foreign_into(),
|
||||
@ -82,7 +82,7 @@ pub async fn get_customer_mandates(
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
Ok(services::BachResponse::Json(response_vec))
|
||||
Ok(services::ApplicationResponse::Json(response_vec))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ pub async fn add_payment_method(
|
||||
})
|
||||
}
|
||||
}
|
||||
.map(services::BachResponse::Json)
|
||||
.map(services::ApplicationResponse::Json)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -383,7 +383,7 @@ pub async fn list_payment_methods(
|
||||
response
|
||||
.is_empty()
|
||||
.then(|| Err(report!(errors::ApiErrorResponse::PaymentMethodNotFound)))
|
||||
.unwrap_or(Ok(services::BachResponse::Json(response)))
|
||||
.unwrap_or(Ok(services::ApplicationResponse::Json(response)))
|
||||
}
|
||||
|
||||
fn filter_payment_methods(
|
||||
@ -568,7 +568,7 @@ pub async fn list_customer_payment_method(
|
||||
customer_payment_methods: vec,
|
||||
};
|
||||
|
||||
Ok(services::BachResponse::Json(response))
|
||||
Ok(services::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn get_lookup_key_from_locker(
|
||||
@ -751,23 +751,27 @@ pub async fn retrieve_payment_method(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(services::BachResponse::Json(api::PaymentMethodResponse {
|
||||
merchant_id: pm.merchant_id,
|
||||
customer_id: Some(pm.customer_id),
|
||||
payment_method_id: pm.payment_method_id,
|
||||
payment_method: pm.payment_method.foreign_into(),
|
||||
payment_method_type: pm.payment_method_type.map(ForeignInto::foreign_into),
|
||||
payment_method_issuer: pm.payment_method_issuer,
|
||||
card,
|
||||
metadata: pm.metadata,
|
||||
created: Some(pm.created_at),
|
||||
payment_method_issuer_code: pm.payment_method_issuer_code.map(ForeignInto::foreign_into),
|
||||
recurring_enabled: false, //TODO
|
||||
installment_payment_enabled: false, //TODO
|
||||
payment_experience: Some(vec![
|
||||
api_models::payment_methods::PaymentExperience::RedirectToUrl,
|
||||
]), //TODO,
|
||||
}))
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
api::PaymentMethodResponse {
|
||||
merchant_id: pm.merchant_id,
|
||||
customer_id: Some(pm.customer_id),
|
||||
payment_method_id: pm.payment_method_id,
|
||||
payment_method: pm.payment_method.foreign_into(),
|
||||
payment_method_type: pm.payment_method_type.map(ForeignInto::foreign_into),
|
||||
payment_method_issuer: pm.payment_method_issuer,
|
||||
card,
|
||||
metadata: pm.metadata,
|
||||
created: Some(pm.created_at),
|
||||
payment_method_issuer_code: pm
|
||||
.payment_method_issuer_code
|
||||
.map(ForeignInto::foreign_into),
|
||||
recurring_enabled: false, //TODO
|
||||
installment_payment_enabled: false, //TODO
|
||||
payment_experience: Some(vec![
|
||||
api_models::payment_methods::PaymentExperience::RedirectToUrl,
|
||||
]), //TODO,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -801,7 +805,7 @@ pub async fn delete_payment_method(
|
||||
}
|
||||
};
|
||||
|
||||
Ok(services::BachResponse::Json(
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
api::DeletePaymentMethodResponse {
|
||||
payment_method_id: pm.payment_method_id,
|
||||
deleted: true,
|
||||
|
||||
@ -247,7 +247,7 @@ where
|
||||
|
||||
let payments_response =
|
||||
match response.change_context(errors::ApiErrorResponse::NotImplemented)? {
|
||||
services::BachResponse::Json(response) => Ok(response),
|
||||
services::ApplicationResponse::Json(response) => Ok(response),
|
||||
_ => Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable("Failed to get the response in json"),
|
||||
@ -261,7 +261,7 @@ where
|
||||
)
|
||||
.attach_printable("No redirection response")?;
|
||||
|
||||
Ok(services::BachResponse::JsonForRedirection(result))
|
||||
Ok(services::ApplicationResponse::JsonForRedirection(result))
|
||||
}
|
||||
|
||||
pub async fn payments_response_for_redirection_flows<'a>(
|
||||
@ -562,10 +562,12 @@ pub async fn list_payments(
|
||||
.into_iter()
|
||||
.map(ForeignInto::foreign_into)
|
||||
.collect();
|
||||
Ok(services::BachResponse::Json(api::PaymentListResponse {
|
||||
size: data.len(),
|
||||
data,
|
||||
}))
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
api::PaymentListResponse {
|
||||
size: data.len(),
|
||||
data,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn add_process_sync_task(
|
||||
|
||||
@ -547,7 +547,7 @@ pub(crate) async fn call_payment_method(
|
||||
.await
|
||||
.attach_printable("Error on adding payment method")?;
|
||||
match resp {
|
||||
crate::services::BachResponse::Json(payment_method) => {
|
||||
crate::services::ApplicationResponse::Json(payment_method) => {
|
||||
Ok(payment_method)
|
||||
}
|
||||
_ => Err(report!(errors::ApiErrorResponse::InternalServerError)
|
||||
@ -575,7 +575,9 @@ pub(crate) async fn call_payment_method(
|
||||
.await
|
||||
.attach_printable("Error on adding payment method")?;
|
||||
match resp {
|
||||
crate::services::BachResponse::Json(payment_method) => Ok(payment_method),
|
||||
crate::services::ApplicationResponse::Json(payment_method) => {
|
||||
Ok(payment_method)
|
||||
}
|
||||
_ => Err(report!(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error on adding payment method")),
|
||||
}
|
||||
@ -1156,7 +1158,7 @@ pub async fn make_ephemeral_key(
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Unable to create ephemeral key")?;
|
||||
Ok(services::BachResponse::Json(ek))
|
||||
Ok(services::ApplicationResponse::Json(ek))
|
||||
}
|
||||
|
||||
pub async fn delete_ephemeral_key(
|
||||
@ -1168,7 +1170,7 @@ pub async fn delete_ephemeral_key(
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Unable to delete ephemeral key")?;
|
||||
Ok(services::BachResponse::Json(ek))
|
||||
Ok(services::ApplicationResponse::Json(ek))
|
||||
}
|
||||
|
||||
pub fn make_pg_redirect_response(
|
||||
|
||||
@ -160,7 +160,7 @@ where
|
||||
_server: &Server,
|
||||
_operation: Op,
|
||||
) -> RouterResponse<Self> {
|
||||
Ok(services::BachResponse::Json(Self {
|
||||
Ok(services::ApplicationResponse::Json(Self {
|
||||
session_token: payment_data.sessions_token,
|
||||
payment_id: payment_data.payment_attempt.payment_id,
|
||||
client_secret: payment_data
|
||||
@ -186,7 +186,7 @@ where
|
||||
_server: &Server,
|
||||
_operation: Op,
|
||||
) -> RouterResponse<Self> {
|
||||
Ok(services::BachResponse::Json(Self {
|
||||
Ok(services::ApplicationResponse::Json(Self {
|
||||
verify_id: Some(data.payment_intent.payment_id),
|
||||
merchant_id: Some(data.payment_intent.merchant_id),
|
||||
client_secret: data.payment_intent.client_secret.map(masking::Secret::new),
|
||||
@ -254,7 +254,7 @@ where
|
||||
let redirection_data = redirection_data.get_required_value("redirection_data")?;
|
||||
let form: RedirectForm = serde_json::from_value(redirection_data)
|
||||
.map_err(|_| errors::ApiErrorResponse::InternalServerError)?;
|
||||
services::BachResponse::Form(form)
|
||||
services::ApplicationResponse::Form(form)
|
||||
} else {
|
||||
let mut response: api::PaymentsResponse = request
|
||||
.try_into()
|
||||
@ -271,7 +271,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
services::BachResponse::Json(
|
||||
services::ApplicationResponse::Json(
|
||||
response
|
||||
.set_payment_id(Some(payment_attempt.payment_id))
|
||||
.set_merchant_id(Some(payment_attempt.merchant_id))
|
||||
@ -341,7 +341,7 @@ where
|
||||
)
|
||||
}
|
||||
}
|
||||
None => services::BachResponse::Json(api::PaymentsResponse {
|
||||
None => services::ApplicationResponse::Json(api::PaymentsResponse {
|
||||
payment_id: Some(payment_attempt.payment_id),
|
||||
merchant_id: Some(payment_attempt.merchant_id),
|
||||
status: payment_intent.status.foreign_into(),
|
||||
|
||||
@ -2,9 +2,9 @@ pub mod validator;
|
||||
|
||||
use error_stack::{report, IntoReport, ResultExt};
|
||||
use router_env::{instrument, tracing};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
consts,
|
||||
core::{
|
||||
errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt},
|
||||
payments, utils as core_utils,
|
||||
@ -45,9 +45,9 @@ pub async fn refund_create_core(
|
||||
.change_context(errors::ApiErrorResponse::SuccessfulPaymentNotFound)?;
|
||||
|
||||
// Amount is not passed in request refer from payment attempt.
|
||||
amount = req.amount.unwrap_or(payment_attempt.amount); // FIXME: Need to that capture amount
|
||||
amount = req.amount.unwrap_or(payment_attempt.amount); // [#298]: Need to that capture amount
|
||||
|
||||
//TODO: Can we change the flow based on some workflow idea
|
||||
//[#299]: Can we change the flow based on some workflow idea
|
||||
utils::when(amount <= 0, || {
|
||||
Err(report!(errors::ApiErrorResponse::InvalidDataFormat {
|
||||
field_name: "amount".to_string(),
|
||||
@ -82,7 +82,7 @@ pub async fn refund_create_core(
|
||||
req,
|
||||
)
|
||||
.await
|
||||
.map(services::BachResponse::Json)
|
||||
.map(services::ApplicationResponse::Json)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -180,7 +180,7 @@ where
|
||||
Fut: futures::Future<Output = RouterResult<T>>,
|
||||
T: ForeignInto<refunds::RefundResponse>,
|
||||
{
|
||||
Ok(services::BachResponse::Json(
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
f(state, merchant_account, refund_id).await?.foreign_into(),
|
||||
))
|
||||
}
|
||||
@ -337,7 +337,7 @@ pub async fn refund_update_core(
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
|
||||
Ok(services::BachResponse::Json(response.foreign_into()))
|
||||
Ok(services::ApplicationResponse::Json(response.foreign_into()))
|
||||
}
|
||||
|
||||
// ********************************************** VALIDATIONS **********************************************
|
||||
@ -402,37 +402,52 @@ pub async fn validate_and_create_refund(
|
||||
.attach_printable("Failed to fetch refund")?;
|
||||
currency = payment_attempt.currency.get_required_value("currency")?;
|
||||
|
||||
// TODO: Add Connector Based Validation here.
|
||||
validator::validate_payment_order_age(&payment_intent.created_at).change_context(
|
||||
errors::ApiErrorResponse::InvalidDataFormat {
|
||||
field_name: "created_at".to_string(),
|
||||
expected_format: format!(
|
||||
"created_at not older than {} days",
|
||||
validator::REFUND_MAX_AGE
|
||||
),
|
||||
},
|
||||
)?;
|
||||
//[#249]: Add Connector Based Validation here.
|
||||
validator::validate_payment_order_age(
|
||||
&payment_intent.created_at,
|
||||
state.conf.refund.max_age,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
|
||||
field_name: "created_at".to_string(),
|
||||
expected_format: format!(
|
||||
"created_at not older than {} days",
|
||||
state.conf.refund.max_age,
|
||||
),
|
||||
})?;
|
||||
|
||||
validator::validate_refund_amount(payment_attempt.amount, &all_refunds, refund_amount)
|
||||
.change_context(errors::ApiErrorResponse::RefundAmountExceedsPaymentAmount)?;
|
||||
|
||||
validator::validate_maximum_refund_against_payment_attempt(&all_refunds)
|
||||
.change_context(errors::ApiErrorResponse::MaximumRefundCount)?;
|
||||
validator::validate_maximum_refund_against_payment_attempt(
|
||||
&all_refunds,
|
||||
state.conf.refund.max_attempts,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::MaximumRefundCount)?;
|
||||
|
||||
let connector = payment_attempt.connector.clone().ok_or_else(|| {
|
||||
report!(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("connector not populated in payment attempt.")
|
||||
})?;
|
||||
|
||||
refund_create_req = mk_new_refund(
|
||||
req,
|
||||
connector,
|
||||
payment_attempt,
|
||||
currency,
|
||||
&refund_id,
|
||||
&merchant_account.merchant_id,
|
||||
refund_amount,
|
||||
);
|
||||
refund_create_req = storage::RefundNew::default()
|
||||
.set_refund_id(refund_id.to_string())
|
||||
.set_internal_reference_id(utils::generate_id(consts::ID_LENGTH, "refid"))
|
||||
.set_external_reference_id(Some(refund_id))
|
||||
.set_payment_id(req.payment_id)
|
||||
.set_merchant_id(merchant_account.merchant_id.clone())
|
||||
.set_connector_transaction_id(connecter_transaction_id.to_string())
|
||||
.set_connector(connector)
|
||||
.set_refund_type(enums::RefundType::RegularRefund)
|
||||
.set_total_amount(refund_amount)
|
||||
.set_currency(currency)
|
||||
.set_created_at(Some(common_utils::date_time::now()))
|
||||
.set_modified_at(Some(common_utils::date_time::now()))
|
||||
.set_refund_status(enums::RefundStatus::Pending)
|
||||
.set_metadata(req.metadata)
|
||||
.set_description(req.reason.clone())
|
||||
.set_attempt_id(payment_attempt.attempt_id.clone())
|
||||
.set_refund_reason(req.reason)
|
||||
.to_owned();
|
||||
|
||||
refund = db
|
||||
.insert_refund(refund_create_req, merchant_account.storage_scheme)
|
||||
@ -484,53 +499,11 @@ pub async fn refund_list(
|
||||
utils::when(data.is_empty(), || {
|
||||
Err(errors::ApiErrorResponse::RefundNotFound)
|
||||
})?;
|
||||
Ok(services::BachResponse::Json(
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
api_models::refunds::RefundListResponse { data },
|
||||
))
|
||||
}
|
||||
|
||||
// ********************************************** UTILS **********************************************
|
||||
|
||||
// FIXME: function should not have more than 3 arguments.
|
||||
// Consider to use builder pattern.
|
||||
#[instrument]
|
||||
fn mk_new_refund(
|
||||
request: refunds::RefundRequest,
|
||||
connector: String,
|
||||
payment_attempt: &storage::PaymentAttempt,
|
||||
currency: enums::Currency,
|
||||
refund_id: &str,
|
||||
merchant_id: &str,
|
||||
refund_amount: i64,
|
||||
) -> storage::RefundNew {
|
||||
let current_time = common_utils::date_time::now();
|
||||
let connecter_transaction_id = match &payment_attempt.connector_transaction_id {
|
||||
Some(id) => id,
|
||||
None => "",
|
||||
};
|
||||
storage::RefundNew {
|
||||
refund_id: refund_id.to_string(),
|
||||
internal_reference_id: Uuid::new_v4().to_string(),
|
||||
external_reference_id: Some(refund_id.to_string()),
|
||||
payment_id: request.payment_id,
|
||||
merchant_id: merchant_id.to_string(),
|
||||
// FIXME: remove the default.
|
||||
connector_transaction_id: connecter_transaction_id.to_string(),
|
||||
connector,
|
||||
refund_type: enums::RefundType::RegularRefund,
|
||||
total_amount: refund_amount,
|
||||
currency,
|
||||
refund_amount,
|
||||
created_at: Some(current_time),
|
||||
modified_at: Some(current_time),
|
||||
refund_status: enums::RefundStatus::Pending,
|
||||
metadata: request.metadata,
|
||||
description: request.reason,
|
||||
attempt_id: payment_attempt.attempt_id.clone(),
|
||||
..storage::RefundNew::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> TryFrom<types::RefundsRouterData<F>> for refunds::RefundResponse {
|
||||
type Error = error_stack::Report<errors::ApiErrorResponse>;
|
||||
|
||||
@ -548,7 +521,7 @@ impl<F> TryFrom<types::RefundsRouterData<F>> for refunds::RefundResponse {
|
||||
refund_id,
|
||||
amount: data.request.amount / 100,
|
||||
currency: data.request.currency.to_string(),
|
||||
reason: Some("TODO: Not propagated".to_string()), // TODO: Not propagated
|
||||
reason: data.request.reason,
|
||||
status,
|
||||
metadata: None,
|
||||
error_message,
|
||||
@ -622,7 +595,7 @@ pub async fn schedule_refund_execution(
|
||||
}
|
||||
_ => {
|
||||
// Sync the refund for status check
|
||||
//TODO: return refund status response
|
||||
//[#300]: return refund status response
|
||||
match refund_type {
|
||||
api_models::refunds::RefundType::Scheduled => {
|
||||
add_refund_sync_task(db, &refund, runner)
|
||||
@ -661,25 +634,6 @@ pub async fn sync_refund_with_gateway_workflow(
|
||||
)
|
||||
})?;
|
||||
|
||||
let merchant_account = state
|
||||
.store
|
||||
.find_merchant_account_by_merchant_id(&refund_core.merchant_id)
|
||||
.await
|
||||
.map_err(|error| {
|
||||
error.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
|
||||
})?;
|
||||
|
||||
// FIXME we actually don't use this?
|
||||
let _refund = state
|
||||
.store
|
||||
.find_refund_by_internal_reference_id_merchant_id(
|
||||
&refund_core.refund_internal_reference_id,
|
||||
&refund_core.merchant_id,
|
||||
merchant_account.storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::RefundNotFound))?;
|
||||
|
||||
let merchant_account = state
|
||||
.store
|
||||
.find_merchant_account_by_merchant_id(&refund_core.merchant_id)
|
||||
@ -763,7 +717,6 @@ pub async fn trigger_refund_execute_workflow(
|
||||
.await
|
||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::RefundNotFound))?;
|
||||
match (&refund.sent_to_gateway, &refund.refund_status) {
|
||||
//FIXME: Conversion should come from trait
|
||||
(false, enums::RefundStatus::Pending) => {
|
||||
let merchant_account = db
|
||||
.find_merchant_account_by_merchant_id(&refund.merchant_id)
|
||||
|
||||
@ -10,9 +10,6 @@ use crate::{
|
||||
utils,
|
||||
};
|
||||
|
||||
pub(super) const REFUND_MAX_AGE: i64 = 365;
|
||||
pub(super) const REFUND_MAX_ATTEMPTS: usize = 10;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum RefundValidationError {
|
||||
#[error("The payment attempt was not successful")]
|
||||
@ -38,7 +35,6 @@ pub fn validate_success_transaction(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//todo: max refund request count
|
||||
#[instrument(skip_all)]
|
||||
pub fn validate_refund_amount(
|
||||
payment_attempt_amount: i64, // &storage::PaymentAttempt,
|
||||
@ -71,11 +67,12 @@ pub fn validate_refund_amount(
|
||||
#[instrument(skip_all)]
|
||||
pub fn validate_payment_order_age(
|
||||
created_at: &PrimitiveDateTime,
|
||||
refund_max_age: i64,
|
||||
) -> CustomResult<(), RefundValidationError> {
|
||||
let current_time = common_utils::date_time::now();
|
||||
|
||||
utils::when(
|
||||
(current_time - *created_at).whole_days() > REFUND_MAX_AGE,
|
||||
(current_time - *created_at).whole_days() > refund_max_age,
|
||||
|| Err(report!(RefundValidationError::OrderExpired)),
|
||||
)
|
||||
}
|
||||
@ -83,9 +80,9 @@ pub fn validate_payment_order_age(
|
||||
#[instrument(skip_all)]
|
||||
pub fn validate_maximum_refund_against_payment_attempt(
|
||||
all_refunds: &[storage::Refund],
|
||||
refund_max_attempts: usize,
|
||||
) -> CustomResult<(), RefundValidationError> {
|
||||
// TODO: Make this configurable
|
||||
utils::when(all_refunds.len() > REFUND_MAX_ATTEMPTS, || {
|
||||
utils::when(all_refunds.len() > refund_max_attempts, || {
|
||||
Err(report!(RefundValidationError::MaxRefundCountReached))
|
||||
})
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@ pub async fn construct_refund_router_data<'a, F>(
|
||||
refund: &'a storage::Refund,
|
||||
) -> RouterResult<types::RefundsRouterData<F>> {
|
||||
let db = &*state.store;
|
||||
//TODO: everytime parsing the json may have impact?
|
||||
let merchant_connector_account = db
|
||||
.find_merchant_connector_account_by_merchant_id_connector(
|
||||
&merchant_account.merchant_id,
|
||||
@ -86,6 +85,7 @@ pub async fn construct_refund_router_data<'a, F>(
|
||||
refund_amount: refund.refund_amount,
|
||||
currency,
|
||||
amount,
|
||||
reason: refund.refund_reason.clone(),
|
||||
},
|
||||
|
||||
response: Ok(types::RefundsResponseData {
|
||||
|
||||
@ -59,7 +59,7 @@ async fn payments_incoming_webhook_flow(
|
||||
.change_context(errors::WebhooksFlowError::PaymentsCoreFailed)?;
|
||||
|
||||
match payments_response {
|
||||
services::BachResponse::Json(payments_response) => {
|
||||
services::ApplicationResponse::Json(payments_response) => {
|
||||
let payment_id = payments_response
|
||||
.payment_id
|
||||
.clone()
|
||||
|
||||
@ -290,6 +290,7 @@ mod storage {
|
||||
created_at: new.created_at.unwrap_or_else(date_time::now),
|
||||
updated_at: new.created_at.unwrap_or_else(date_time::now),
|
||||
description: new.description.clone(),
|
||||
refund_reason: new.refund_reason.clone(),
|
||||
};
|
||||
|
||||
let field = format!(
|
||||
@ -640,6 +641,7 @@ impl RefundInterface for MockDb {
|
||||
created_at: new.created_at.unwrap_or(current_time),
|
||||
updated_at: current_time,
|
||||
description: new.description,
|
||||
refund_reason: new.refund_reason.clone(),
|
||||
};
|
||||
refunds.push(refund.clone());
|
||||
Ok(refund)
|
||||
|
||||
@ -32,7 +32,7 @@ use routes::AppState;
|
||||
pub use self::env::logger;
|
||||
use crate::{
|
||||
configs::settings::Settings,
|
||||
core::errors::{self, BachResult},
|
||||
core::errors::{self, ApplicationResult},
|
||||
};
|
||||
|
||||
#[cfg(feature = "mimalloc")]
|
||||
@ -110,7 +110,7 @@ pub fn mk_app(
|
||||
/// # Panics
|
||||
///
|
||||
/// Unwrap used because without the value we can't start the server
|
||||
pub async fn start_server(conf: Settings) -> BachResult<(Server, AppState)> {
|
||||
pub async fn start_server(conf: Settings) -> ApplicationResult<(Server, AppState)> {
|
||||
logger::debug!(startup_config=?conf);
|
||||
let server = conf.server.clone();
|
||||
let state = routes::AppState::new(conf).await;
|
||||
|
||||
@ -320,7 +320,7 @@ async fn handle_response(
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum BachResponse<R> {
|
||||
pub enum ApplicationResponse<R> {
|
||||
Json(R),
|
||||
StatusOk,
|
||||
TextPlain(String),
|
||||
@ -329,11 +329,11 @@ pub enum BachResponse<R> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct BachRedirectResponse {
|
||||
pub struct ApplicationRedirectResponse {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
impl From<&storage::PaymentAttempt> for BachRedirectResponse {
|
||||
impl From<&storage::PaymentAttempt> for ApplicationRedirectResponse {
|
||||
fn from(payment_attempt: &storage::PaymentAttempt) -> Self {
|
||||
Self {
|
||||
url: format!(
|
||||
@ -376,7 +376,7 @@ pub async fn server_wrap_util<'a, 'b, U, T, Q, F, Fut>(
|
||||
payload: T,
|
||||
func: F,
|
||||
api_auth: &dyn auth::AuthenticateAndFetch<U>,
|
||||
) -> RouterResult<BachResponse<Q>>
|
||||
) -> RouterResult<ApplicationResponse<Q>>
|
||||
where
|
||||
F: Fn(&'b AppState, U, T) -> Fut,
|
||||
Fut: Future<Output = RouterResponse<Q>>,
|
||||
@ -402,7 +402,7 @@ pub async fn server_wrap<'a, 'b, T, U, Q, F, Fut>(
|
||||
) -> HttpResponse
|
||||
where
|
||||
F: Fn(&'b AppState, U, T) -> Fut,
|
||||
Fut: Future<Output = RouterResult<BachResponse<Q>>>,
|
||||
Fut: Future<Output = RouterResult<ApplicationResponse<Q>>>,
|
||||
Q: Serialize + Debug + 'a,
|
||||
T: Debug,
|
||||
{
|
||||
@ -415,7 +415,7 @@ where
|
||||
logger::info!(tag = ?Tag::BeginRequest);
|
||||
|
||||
let res = match server_wrap_util(state, request, payload, func, api_auth).await {
|
||||
Ok(BachResponse::Json(response)) => match serde_json::to_string(&response) {
|
||||
Ok(ApplicationResponse::Json(response)) => match serde_json::to_string(&response) {
|
||||
Ok(res) => http_response_json(res),
|
||||
Err(_) => http_response_err(
|
||||
r#"{
|
||||
@ -425,19 +425,21 @@ where
|
||||
}"#,
|
||||
),
|
||||
},
|
||||
Ok(BachResponse::StatusOk) => http_response_ok(),
|
||||
Ok(BachResponse::TextPlain(text)) => http_response_plaintext(text),
|
||||
Ok(BachResponse::JsonForRedirection(response)) => match serde_json::to_string(&response) {
|
||||
Ok(res) => http_redirect_response(res, response),
|
||||
Err(_) => http_response_err(
|
||||
r#"{
|
||||
Ok(ApplicationResponse::StatusOk) => http_response_ok(),
|
||||
Ok(ApplicationResponse::TextPlain(text)) => http_response_plaintext(text),
|
||||
Ok(ApplicationResponse::JsonForRedirection(response)) => {
|
||||
match serde_json::to_string(&response) {
|
||||
Ok(res) => http_redirect_response(res, response),
|
||||
Err(_) => http_response_err(
|
||||
r#"{
|
||||
"error": {
|
||||
"message": "Error serializing response from connector"
|
||||
}
|
||||
}"#,
|
||||
),
|
||||
},
|
||||
Ok(BachResponse::Form(response)) => build_redirection_form(&response)
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(ApplicationResponse::Form(response)) => build_redirection_form(&response)
|
||||
.respond_to(request)
|
||||
.map_into_boxed_body(),
|
||||
|
||||
|
||||
@ -200,6 +200,7 @@ pub struct RefundsData {
|
||||
pub currency: storage_enums::Currency,
|
||||
/// Amount for the payment against which this refund is issued
|
||||
pub amount: i64,
|
||||
pub reason: Option<String>,
|
||||
/// Amount to be refunded
|
||||
pub refund_amount: i64,
|
||||
}
|
||||
|
||||
@ -136,7 +136,8 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
|
||||
|
||||
fn get_webhook_api_response(
|
||||
&self,
|
||||
) -> CustomResult<services::api::BachResponse<serde_json::Value>, errors::ConnectorError> {
|
||||
Ok(services::api::BachResponse::StatusOk)
|
||||
) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
|
||||
{
|
||||
Ok(services::api::ApplicationResponse::StatusOk)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user