mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 09:38:33 +08:00
refactor(core): move router data flow types to hyperswitch domain models crate (#4801)
This commit is contained in:
@ -6,6 +6,7 @@ pub mod payments;
|
|||||||
#[cfg(feature = "payouts")]
|
#[cfg(feature = "payouts")]
|
||||||
pub mod payouts;
|
pub mod payouts;
|
||||||
pub mod router_data;
|
pub mod router_data;
|
||||||
|
pub mod router_flow_types;
|
||||||
pub mod router_request_types;
|
pub mod router_request_types;
|
||||||
pub mod router_response_types;
|
pub mod router_response_types;
|
||||||
|
|
||||||
|
|||||||
17
crates/hyperswitch_domain_models/src/router_flow_types.rs
Normal file
17
crates/hyperswitch_domain_models/src/router_flow_types.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
pub mod access_token_auth;
|
||||||
|
pub mod dispute;
|
||||||
|
pub mod files;
|
||||||
|
pub mod fraud_check;
|
||||||
|
pub mod payments;
|
||||||
|
pub mod payouts;
|
||||||
|
pub mod refunds;
|
||||||
|
pub mod webhooks;
|
||||||
|
|
||||||
|
pub use access_token_auth::*;
|
||||||
|
pub use dispute::*;
|
||||||
|
pub use files::*;
|
||||||
|
pub use fraud_check::*;
|
||||||
|
pub use payments::*;
|
||||||
|
pub use payouts::*;
|
||||||
|
pub use refunds::*;
|
||||||
|
pub use webhooks::*;
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct AccessTokenAuth;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Accept;
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Evidence;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Defend;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Retrieve;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Upload;
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Sale;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Checkout;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Transaction;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Fulfillment;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RecordReturn;
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
// Core related api layer.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Authorize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct AuthorizeSessionToken;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CompleteAuthorize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Approve;
|
||||||
|
|
||||||
|
// Used in gift cards balance check
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Balance;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct InitPayment;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Capture;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PSync;
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Void;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Reject;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Session;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PaymentMethodToken;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CreateConnectorCustomer;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SetupMandate;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PreProcessing;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct IncrementalAuthorization;
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoCancel;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoCreate;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoEligibility;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoFulfill;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoQuote;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoRecipient;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PoRecipientAccount;
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Execute;
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RSync;
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct VerifyWebhookSource;
|
||||||
@ -15,7 +15,7 @@ use crate::{
|
|||||||
errors::api_error_response::ApiErrorResponse,
|
errors::api_error_response::ApiErrorResponse,
|
||||||
mandates, payments,
|
mandates, payments,
|
||||||
router_data::{self, RouterData},
|
router_data::{self, RouterData},
|
||||||
router_response_types as response_types,
|
router_flow_types as flows, router_response_types as response_types,
|
||||||
};
|
};
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PaymentsAuthorizeData {
|
pub struct PaymentsAuthorizeData {
|
||||||
@ -134,13 +134,19 @@ impl TryFrom<SetupMandateRequestData> for ConnectorCustomerData {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<F> TryFrom<&RouterData<F, PaymentsAuthorizeData, response_types::PaymentsResponseData>>
|
impl
|
||||||
for ConnectorCustomerData
|
TryFrom<
|
||||||
|
&RouterData<flows::Authorize, PaymentsAuthorizeData, response_types::PaymentsResponseData>,
|
||||||
|
> for ConnectorCustomerData
|
||||||
{
|
{
|
||||||
type Error = error_stack::Report<ApiErrorResponse>;
|
type Error = error_stack::Report<ApiErrorResponse>;
|
||||||
|
|
||||||
fn try_from(
|
fn try_from(
|
||||||
data: &RouterData<F, PaymentsAuthorizeData, response_types::PaymentsResponseData>,
|
data: &RouterData<
|
||||||
|
flows::Authorize,
|
||||||
|
PaymentsAuthorizeData,
|
||||||
|
response_types::PaymentsResponseData,
|
||||||
|
>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
email: data.request.email.clone(),
|
email: data.request.email.clone(),
|
||||||
|
|||||||
@ -29,6 +29,9 @@ pub mod webhooks;
|
|||||||
use std::{fmt::Debug, str::FromStr};
|
use std::{fmt::Debug, str::FromStr};
|
||||||
|
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{report, ResultExt};
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::{
|
||||||
|
access_token_auth::AccessTokenAuth, webhooks::VerifyWebhookSource,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "frm")]
|
#[cfg(feature = "frm")]
|
||||||
pub use self::fraud_check::*;
|
pub use self::fraud_check::*;
|
||||||
@ -50,10 +53,6 @@ use crate::{
|
|||||||
services::{request, ConnectorIntegration, ConnectorRedirectResponse, ConnectorValidation},
|
services::{request, ConnectorIntegration, ConnectorRedirectResponse, ConnectorValidation},
|
||||||
types::{self, api::enums as api_enums},
|
types::{self, api::enums as api_enums},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct AccessTokenAuth;
|
|
||||||
|
|
||||||
pub trait ConnectorAccessToken:
|
pub trait ConnectorAccessToken:
|
||||||
ConnectorIntegration<AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
|
ConnectorIntegration<AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
|
||||||
{
|
{
|
||||||
@ -66,9 +65,6 @@ pub enum ConnectorCallType {
|
|||||||
SessionMultiple(Vec<SessionConnectorData>),
|
SessionMultiple(Vec<SessionConnectorData>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct VerifyWebhookSource;
|
|
||||||
|
|
||||||
pub trait ConnectorVerifyWebhookSource:
|
pub trait ConnectorVerifyWebhookSource:
|
||||||
ConnectorIntegration<
|
ConnectorIntegration<
|
||||||
VerifyWebhookSource,
|
VerifyWebhookSource,
|
||||||
|
|||||||
@ -8,6 +8,8 @@ pub struct DisputeId {
|
|||||||
pub dispute_id: String,
|
pub dispute_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::dispute::{Accept, Defend, Evidence};
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct DisputePayload {
|
pub struct DisputePayload {
|
||||||
pub amount: String,
|
pub amount: String,
|
||||||
@ -58,9 +60,6 @@ pub enum EvidenceType {
|
|||||||
UncategorizedFile,
|
UncategorizedFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Accept;
|
|
||||||
|
|
||||||
pub trait AcceptDispute:
|
pub trait AcceptDispute:
|
||||||
services::ConnectorIntegration<
|
services::ConnectorIntegration<
|
||||||
Accept,
|
Accept,
|
||||||
@ -70,9 +69,6 @@ pub trait AcceptDispute:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Evidence;
|
|
||||||
|
|
||||||
pub trait SubmitEvidence:
|
pub trait SubmitEvidence:
|
||||||
services::ConnectorIntegration<
|
services::ConnectorIntegration<
|
||||||
Evidence,
|
Evidence,
|
||||||
@ -82,9 +78,6 @@ pub trait SubmitEvidence:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Defend;
|
|
||||||
|
|
||||||
pub trait DefendDispute:
|
pub trait DefendDispute:
|
||||||
services::ConnectorIntegration<
|
services::ConnectorIntegration<
|
||||||
Defend,
|
Defend,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use api_models::enums::FileUploadProvider;
|
use api_models::enums::FileUploadProvider;
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::files::{Retrieve, Upload};
|
||||||
use masking::{Deserialize, Serialize};
|
use masking::{Deserialize, Serialize};
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
|
|
||||||
@ -67,17 +68,11 @@ pub enum FilePurpose {
|
|||||||
DisputeEvidence,
|
DisputeEvidence,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Upload;
|
|
||||||
|
|
||||||
pub trait UploadFile:
|
pub trait UploadFile:
|
||||||
services::ConnectorIntegration<Upload, types::UploadFileRequestData, types::UploadFileResponse>
|
services::ConnectorIntegration<Upload, types::UploadFileRequestData, types::UploadFileResponse>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Retrieve;
|
|
||||||
|
|
||||||
pub trait RetrieveFile:
|
pub trait RetrieveFile:
|
||||||
services::ConnectorIntegration<
|
services::ConnectorIntegration<
|
||||||
Retrieve,
|
Retrieve,
|
||||||
|
|||||||
@ -3,6 +3,9 @@ use std::str::FromStr;
|
|||||||
use api_models::enums;
|
use api_models::enums;
|
||||||
use common_utils::errors::CustomResult;
|
use common_utils::errors::CustomResult;
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::fraud_check::{
|
||||||
|
Checkout, Fulfillment, RecordReturn, Sale, Transaction,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{BoxedConnector, ConnectorData, SessionConnectorData};
|
use super::{BoxedConnector, ConnectorData, SessionConnectorData};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -15,41 +18,26 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Sale;
|
|
||||||
|
|
||||||
pub trait FraudCheckSale:
|
pub trait FraudCheckSale:
|
||||||
api::ConnectorIntegration<Sale, FraudCheckSaleData, FraudCheckResponseData>
|
api::ConnectorIntegration<Sale, FraudCheckSaleData, FraudCheckResponseData>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Checkout;
|
|
||||||
|
|
||||||
pub trait FraudCheckCheckout:
|
pub trait FraudCheckCheckout:
|
||||||
api::ConnectorIntegration<Checkout, FraudCheckCheckoutData, FraudCheckResponseData>
|
api::ConnectorIntegration<Checkout, FraudCheckCheckoutData, FraudCheckResponseData>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Transaction;
|
|
||||||
|
|
||||||
pub trait FraudCheckTransaction:
|
pub trait FraudCheckTransaction:
|
||||||
api::ConnectorIntegration<Transaction, FraudCheckTransactionData, FraudCheckResponseData>
|
api::ConnectorIntegration<Transaction, FraudCheckTransactionData, FraudCheckResponseData>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Fulfillment;
|
|
||||||
|
|
||||||
pub trait FraudCheckFulfillment:
|
pub trait FraudCheckFulfillment:
|
||||||
api::ConnectorIntegration<Fulfillment, FraudCheckFulfillmentData, FraudCheckResponseData>
|
api::ConnectorIntegration<Fulfillment, FraudCheckFulfillmentData, FraudCheckResponseData>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct RecordReturn;
|
|
||||||
|
|
||||||
pub trait FraudCheckRecordReturn:
|
pub trait FraudCheckRecordReturn:
|
||||||
api::ConnectorIntegration<RecordReturn, FraudCheckRecordReturnData, FraudCheckResponseData>
|
api::ConnectorIntegration<RecordReturn, FraudCheckRecordReturnData, FraudCheckResponseData>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -15,6 +15,11 @@ pub use api_models::payments::{
|
|||||||
WalletData,
|
WalletData,
|
||||||
};
|
};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::payments::{
|
||||||
|
Approve, Authorize, AuthorizeSessionToken, Balance, Capture, CompleteAuthorize,
|
||||||
|
CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken,
|
||||||
|
PreProcessing, Reject, Session, SetupMandate, Void,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::errors,
|
core::errors,
|
||||||
@ -24,55 +29,6 @@ use crate::{
|
|||||||
|
|
||||||
impl super::Router for PaymentsRequest {}
|
impl super::Router for PaymentsRequest {}
|
||||||
|
|
||||||
// Core related api layer.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Authorize;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct AuthorizeSessionToken;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CompleteAuthorize;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Approve;
|
|
||||||
|
|
||||||
// Used in gift cards balance check
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Balance;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct InitPayment;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Capture;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PSync;
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Void;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Reject;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Session;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PaymentMethodToken;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CreateConnectorCustomer;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct SetupMandate;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PreProcessing;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct IncrementalAuthorization;
|
|
||||||
|
|
||||||
pub trait PaymentIdTypeExt {
|
pub trait PaymentIdTypeExt {
|
||||||
fn get_payment_intent_id(&self) -> errors::CustomResult<String, errors::ValidationError>;
|
fn get_payment_intent_id(&self) -> errors::CustomResult<String, errors::ValidationError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,30 +4,12 @@ pub use api_models::payouts::{
|
|||||||
PayoutListFilters, PayoutListResponse, PayoutMethodData, PayoutRequest, PayoutRetrieveBody,
|
PayoutListFilters, PayoutListResponse, PayoutMethodData, PayoutRequest, PayoutRetrieveBody,
|
||||||
PayoutRetrieveRequest, PixBankTransfer, SepaBankTransfer, Wallet as WalletPayout,
|
PayoutRetrieveRequest, PixBankTransfer, SepaBankTransfer, Wallet as WalletPayout,
|
||||||
};
|
};
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::payouts::{
|
||||||
|
PoCancel, PoCreate, PoEligibility, PoFulfill, PoQuote, PoRecipient, PoRecipientAccount,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{services::api, types};
|
use crate::{services::api, types};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoCancel;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoCreate;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoEligibility;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoFulfill;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoQuote;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoRecipient;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PoRecipientAccount;
|
|
||||||
|
|
||||||
pub trait PayoutCancel:
|
pub trait PayoutCancel:
|
||||||
api::ConnectorIntegration<PoCancel, types::PayoutsData, types::PayoutsResponseData>
|
api::ConnectorIntegration<PoCancel, types::PayoutsData, types::PayoutsResponseData>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,6 +2,7 @@ pub use api_models::refunds::{
|
|||||||
RefundRequest, RefundResponse, RefundStatus, RefundType, RefundUpdateRequest,
|
RefundRequest, RefundResponse, RefundStatus, RefundType, RefundUpdateRequest,
|
||||||
RefundsRetrieveRequest,
|
RefundsRetrieveRequest,
|
||||||
};
|
};
|
||||||
|
pub use hyperswitch_domain_models::router_flow_types::refunds::{Execute, RSync};
|
||||||
|
|
||||||
use super::ConnectorCommon;
|
use super::ConnectorCommon;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -21,11 +22,6 @@ impl ForeignFrom<storage_enums::RefundStatus> for RefundStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Execute;
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct RSync;
|
|
||||||
|
|
||||||
pub trait RefundExecute:
|
pub trait RefundExecute:
|
||||||
api::ConnectorIntegration<Execute, types::RefundsData, types::RefundsResponseData>
|
api::ConnectorIntegration<Execute, types::RefundsData, types::RefundsResponseData>
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user