mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 18:17:13 +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(()) | ||||
| // } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Manoj Ghorela
					Manoj Ghorela