mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 03:13:56 +08:00
refac: customer address db alter for gdpr compliance (#105)
This commit is contained in:
@ -2,7 +2,6 @@ use std::{convert::From, default::Default};
|
||||
|
||||
use masking::{Secret, WithType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{pii::Email, types::api};
|
||||
|
||||
@ -39,7 +38,6 @@ pub(crate) struct CustomerUpdateRequest {
|
||||
pub(crate) struct CreateCustomerResponse {
|
||||
id: String,
|
||||
object: String,
|
||||
address: Option<Secret<serde_json::Value>>,
|
||||
created: u64,
|
||||
description: Option<String>,
|
||||
email: Option<Secret<String, Email>>,
|
||||
@ -65,16 +63,6 @@ impl From<CreateCustomerRequest> for api::CustomerRequest {
|
||||
phone: req.phone,
|
||||
email: req.email,
|
||||
description: req.invoice_prefix,
|
||||
address: req.address.map(|addr| {
|
||||
Secret::new(json!({
|
||||
"city": addr.city,
|
||||
"country": addr.country,
|
||||
"line1": addr.line1,
|
||||
"line2": addr.line2,
|
||||
"postal_code": addr.postal_code,
|
||||
"state": addr.state
|
||||
}))
|
||||
}),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@ -87,17 +75,6 @@ impl From<CustomerUpdateRequest> for api::CustomerRequest {
|
||||
phone: req.phone,
|
||||
email: req.email,
|
||||
description: req.description,
|
||||
address: req.address.map(|addr| {
|
||||
Secret::new(json!({
|
||||
"city": addr.city,
|
||||
"country": addr.country,
|
||||
"line1": addr.line1,
|
||||
"line2": addr.line2,
|
||||
"postal_code": addr.postal_code,
|
||||
"state": addr.state
|
||||
}))
|
||||
}),
|
||||
|
||||
metadata: req
|
||||
.metadata
|
||||
.map(|v| serde_json::from_str(&v).ok())
|
||||
@ -112,7 +89,6 @@ impl From<api::CustomerResponse> for CreateCustomerResponse {
|
||||
Self {
|
||||
id: cust.customer_id,
|
||||
object: "customer".to_owned(),
|
||||
address: cust.address,
|
||||
created: cust.created_at.assume_utc().unix_timestamp() as u64,
|
||||
description: cust.description,
|
||||
email: cust.email,
|
||||
|
||||
@ -27,7 +27,6 @@ pub async fn create_customer(
|
||||
phone: customer_data.phone,
|
||||
description: customer_data.description,
|
||||
phone_country_code: customer_data.phone_country_code,
|
||||
address: customer_data.address,
|
||||
metadata: customer_data.metadata,
|
||||
};
|
||||
|
||||
@ -92,7 +91,6 @@ pub async fn update_customer(
|
||||
email: update_customer.email,
|
||||
phone: update_customer.phone,
|
||||
phone_country_code: update_customer.phone_country_code,
|
||||
address: update_customer.address,
|
||||
metadata: update_customer.metadata,
|
||||
description: update_customer.description,
|
||||
},
|
||||
|
||||
@ -36,6 +36,8 @@ pub async fn get_address_for_payment_request(
|
||||
db: &dyn StorageInterface,
|
||||
req_address: Option<&api::Address>,
|
||||
address_id: Option<&str>,
|
||||
merchant_id: &str,
|
||||
customer_id: &Option<String>,
|
||||
) -> CustomResult<Option<storage::Address>, errors::ApiErrorResponse> {
|
||||
// TODO: Refactor this function for more readability (TryFrom)
|
||||
Ok(match req_address {
|
||||
@ -50,6 +52,10 @@ pub async fn get_address_for_payment_request(
|
||||
),
|
||||
None => {
|
||||
// generate a new address here
|
||||
let customer_id = customer_id
|
||||
.as_deref()
|
||||
.get_required_value("customer_id")
|
||||
.change_context(errors::ApiErrorResponse::CustomerNotFound)?;
|
||||
Some(
|
||||
db.insert_address(storage::AddressNew {
|
||||
city: address.address.as_ref().and_then(|a| a.city.clone()),
|
||||
@ -66,6 +72,8 @@ pub async fn get_address_for_payment_request(
|
||||
.phone
|
||||
.as_ref()
|
||||
.and_then(|a| a.country_code.clone()),
|
||||
customer_id: customer_id.to_string(),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
..storage::AddressNew::default()
|
||||
})
|
||||
.await
|
||||
|
||||
@ -101,6 +101,8 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -108,6 +110,8 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -109,12 +109,16 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -61,11 +61,23 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
helpers::get_token_pm_type_mandate_details(state, request, mandate_type, merchant_id)
|
||||
.await?;
|
||||
|
||||
let shipping_address =
|
||||
helpers::get_address_for_payment_request(db, request.shipping.as_ref(), None).await?;
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
None,
|
||||
merchant_id,
|
||||
&request.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_address =
|
||||
helpers::get_address_for_payment_request(db, request.billing.as_ref(), None).await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
None,
|
||||
merchant_id,
|
||||
&request.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let browser_info = request
|
||||
.browser_info
|
||||
|
||||
@ -82,6 +82,8 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -89,6 +91,8 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -72,12 +72,16 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -96,12 +96,16 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
&payment_intent.customer_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -136,7 +136,6 @@ impl CustomerInterface for MockDb {
|
||||
phone: customer_data.phone,
|
||||
phone_country_code: customer_data.phone_country_code,
|
||||
description: customer_data.description,
|
||||
address: customer_data.address,
|
||||
created_at: common_utils::date_time::now(),
|
||||
metadata: customer_data.metadata,
|
||||
};
|
||||
|
||||
@ -20,6 +20,8 @@ diesel::table! {
|
||||
country_code -> Nullable<Varchar>,
|
||||
created_at -> Timestamp,
|
||||
modified_at -> Timestamp,
|
||||
customer_id -> Varchar,
|
||||
merchant_id -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +67,6 @@ diesel::table! {
|
||||
phone -> Nullable<Varchar>,
|
||||
phone_country_code -> Nullable<Varchar>,
|
||||
description -> Nullable<Varchar>,
|
||||
address -> Nullable<Json>,
|
||||
created_at -> Timestamp,
|
||||
metadata -> Nullable<Json>,
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@ pub struct CustomerRequest {
|
||||
pub phone: Option<Secret<String>>,
|
||||
pub description: Option<String>,
|
||||
pub phone_country_code: Option<String>,
|
||||
pub address: Option<Secret<serde_json::Value>>,
|
||||
pub metadata: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
@ -35,14 +34,6 @@ impl CustomerRequest {
|
||||
expected_format: "valid email address".to_string(),
|
||||
})?;
|
||||
|
||||
self.address
|
||||
.as_ref()
|
||||
.validate_opt(|addr| utils::validate_address(addr.peek()))
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
|
||||
field_name: "address".to_string(),
|
||||
expected_format: "valid address".to_string(),
|
||||
})?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
@ -55,7 +46,6 @@ pub struct CustomerResponse {
|
||||
pub phone: Option<Secret<String>>,
|
||||
pub phone_country_code: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub address: Option<Secret<serde_json::Value>>,
|
||||
#[serde(with = "custom_serde::iso8601")]
|
||||
pub created_at: time::PrimitiveDateTime,
|
||||
pub metadata: Option<serde_json::Value>,
|
||||
@ -70,7 +60,6 @@ impl From<storage::Customer> for CustomerResponse {
|
||||
phone: cust.phone,
|
||||
phone_country_code: cust.phone_country_code,
|
||||
description: cust.description,
|
||||
address: cust.address,
|
||||
created_at: cust.created_at,
|
||||
metadata: cust.metadata,
|
||||
}
|
||||
|
||||
@ -22,6 +22,8 @@ pub struct AddressNew {
|
||||
pub last_name: Option<Secret<String>>,
|
||||
pub phone_number: Option<Secret<String>>,
|
||||
pub country_code: Option<String>,
|
||||
pub customer_id: String,
|
||||
pub merchant_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)]
|
||||
@ -48,6 +50,8 @@ pub struct Address {
|
||||
#[serde(skip_serializing)]
|
||||
#[serde(with = "custom_serde::iso8601")]
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub customer_id: String,
|
||||
pub merchant_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -177,6 +181,8 @@ impl Default for AddressNew {
|
||||
last_name: None,
|
||||
phone_number: None,
|
||||
country_code: None,
|
||||
customer_id: String::default(),
|
||||
merchant_id: String::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ pub struct CustomerNew {
|
||||
pub phone: Option<Secret<String>>,
|
||||
pub description: Option<String>,
|
||||
pub phone_country_code: Option<String>,
|
||||
pub address: Option<Secret<serde_json::Value>>,
|
||||
pub metadata: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
@ -31,7 +30,6 @@ pub struct Customer {
|
||||
pub phone: Option<Secret<String>>,
|
||||
pub phone_country_code: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub address: Option<Secret<serde_json::Value>>,
|
||||
pub created_at: PrimitiveDateTime,
|
||||
pub metadata: Option<serde_json::Value>,
|
||||
}
|
||||
@ -44,7 +42,6 @@ pub enum CustomerUpdate {
|
||||
phone: Option<Secret<String>>,
|
||||
description: Option<String>,
|
||||
phone_country_code: Option<String>,
|
||||
address: Option<Secret<serde_json::Value>>,
|
||||
metadata: Option<serde_json::Value>,
|
||||
},
|
||||
}
|
||||
@ -57,7 +54,6 @@ pub(super) struct CustomerUpdateInternal {
|
||||
phone: Option<Secret<String>>,
|
||||
description: Option<String>,
|
||||
phone_country_code: Option<String>,
|
||||
address: Option<Secret<serde_json::Value>>,
|
||||
metadata: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
@ -70,7 +66,6 @@ impl From<CustomerUpdate> for CustomerUpdateInternal {
|
||||
phone,
|
||||
description,
|
||||
phone_country_code,
|
||||
address,
|
||||
metadata,
|
||||
} => Self {
|
||||
name,
|
||||
@ -78,7 +73,6 @@ impl From<CustomerUpdate> for CustomerUpdateInternal {
|
||||
phone,
|
||||
description,
|
||||
phone_country_code,
|
||||
address,
|
||||
metadata,
|
||||
},
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ pub(crate) use common_utils::{
|
||||
use nanoid::nanoid;
|
||||
|
||||
pub(crate) use self::{
|
||||
ext_traits::{validate_address, OptionExt, ValidateCall},
|
||||
ext_traits::{OptionExt, ValidateCall},
|
||||
fp_utils::when,
|
||||
};
|
||||
use crate::consts;
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
use common_utils::ext_traits::ValueExt;
|
||||
use error_stack::{report, IntoReport, Report, ResultExt};
|
||||
use error_stack::{IntoReport, Report, ResultExt};
|
||||
|
||||
use crate::{
|
||||
core::errors::{self, ApiErrorResponse, CustomResult, RouterResult},
|
||||
types::api::AddressDetails,
|
||||
utils::when,
|
||||
};
|
||||
|
||||
@ -129,11 +128,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_address(address: &serde_json::Value) -> CustomResult<(), errors::ValidationError> {
|
||||
if let Err(err) = serde_json::from_value::<AddressDetails>(address.clone()) {
|
||||
return Err(report!(errors::ValidationError::InvalidValue {
|
||||
message: format!("Invalid address: {err}")
|
||||
}));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// pub fn validate_address(address: &serde_json::Value) -> CustomResult<(), errors::ValidationError> {
|
||||
// if let Err(err) = serde_json::from_value::<AddressDetails>(address.clone()) {
|
||||
// return Err(report!(errors::ValidationError::InvalidValue {
|
||||
// message: format!("Invalid address: {err}")
|
||||
// }));
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE address
|
||||
DROP COLUMN customer_id,
|
||||
DROP COLUMN merchant_id;
|
||||
|
||||
ALTER TABLE customers ADD COLUMN address JSON;
|
||||
@ -0,0 +1,8 @@
|
||||
-- Your SQL goes here
|
||||
ALTER TABLE address
|
||||
ADD COLUMN customer_id VARCHAR(255) NOT NULL,
|
||||
ADD COLUMN merchant_id VARCHAR(255) NOT NULL;
|
||||
|
||||
CREATE INDEX address_customer_id_merchant_id_index ON address (customer_id, merchant_id);
|
||||
|
||||
ALTER TABLE customers DROP COLUMN address;
|
||||
Reference in New Issue
Block a user