From 94cd7b689758a71e13a3eaa655335e658d13afc8 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja <1805317@kiit.ac.in> Date: Wed, 31 Jan 2024 17:30:02 +0530 Subject: [PATCH] feat(dashboard_metadata): Add email alert for Prod Intent (#3482) Co-authored-by: Mani Chandra Dulam Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- crates/router/src/consts/user.rs | 1 + .../src/core/user/dashboard_metadata.rs | 24 ++- .../services/email/assets/bizemailprod.html | 138 ++++++++++++++++++ crates/router/src/services/email/types.rs | 84 ++++++++++- .../src/utils/user/dashboard_metadata.rs | 9 +- 5 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 crates/router/src/services/email/assets/bizemailprod.html diff --git a/crates/router/src/consts/user.rs b/crates/router/src/consts/user.rs index c570aca76038..1cda969f780e 100644 --- a/crates/router/src/consts/user.rs +++ b/crates/router/src/consts/user.rs @@ -1,2 +1,3 @@ pub const MAX_NAME_LENGTH: usize = 70; pub const MAX_COMPANY_NAME_LENGTH: usize = 70; +pub const BUSINESS_EMAIL: &str = "biz@hyperswitch.io"; diff --git a/crates/router/src/core/user/dashboard_metadata.rs b/crates/router/src/core/user/dashboard_metadata.rs index b537aa3ec732..24ff292870e5 100644 --- a/crates/router/src/core/user/dashboard_metadata.rs +++ b/crates/router/src/core/user/dashboard_metadata.rs @@ -3,7 +3,11 @@ use diesel_models::{ enums::DashboardMetadata as DBEnum, user::dashboard_metadata::DashboardMetadata, }; use error_stack::ResultExt; +#[cfg(feature = "email")] +use router_env::logger; +#[cfg(feature = "email")] +use crate::services::email::types as email_types; use crate::{ core::errors::{UserErrors, UserResponse, UserResult}, routes::AppState, @@ -434,15 +438,31 @@ async fn insert_metadata( if utils::is_update_required(&metadata) { metadata = utils::update_user_scoped_metadata( state, - user.user_id, + user.user_id.clone(), user.merchant_id, user.org_id, metadata_key, - data, + data.clone(), ) .await .change_context(UserErrors::InternalServerError); } + + #[cfg(feature = "email")] + { + if utils::is_prod_email_required(&data) { + let email_contents = email_types::BizEmailProd::new(state, data)?; + let send_email_result = state + .email_client + .compose_and_send_email( + Box::new(email_contents), + state.conf.proxy.https_url.as_ref(), + ) + .await; + logger::info!(?send_email_result); + } + } + metadata } types::MetaData::SPTestPayment(data) => { diff --git a/crates/router/src/services/email/assets/bizemailprod.html b/crates/router/src/services/email/assets/bizemailprod.html new file mode 100644 index 000000000000..c705608ec720 --- /dev/null +++ b/crates/router/src/services/email/assets/bizemailprod.html @@ -0,0 +1,138 @@ + +Welcome to HyperSwitch! + +
+ + + + + + + + + + + + + + + + + + + + +
+
+

Hi Team,

+

+ A Production Account Intent has been initiated by {username} - + please find more details below: +

+
    +
  1. Name: {username}
  2. +
  3. Point of Contact Email (POC): {poc_email}
  4. +
  5. Legal Business Name: {legal_business_name}
  6. +
  7. Business Location: {business_location}
  8. +
  9. Business Website: {business_website}
  10. +
+
+
+ Regards,
+ Hyperswitch Dashboard Team +
+
+ diff --git a/crates/router/src/services/email/types.rs b/crates/router/src/services/email/types.rs index c68907c28461..6ad1a0eb99ad 100644 --- a/crates/router/src/services/email/types.rs +++ b/crates/router/src/services/email/types.rs @@ -1,11 +1,16 @@ +use api_models::user::dashboard_metadata::ProdIntent; use common_utils::errors::CustomResult; use error_stack::ResultExt; use external_services::email::{EmailContents, EmailData, EmailError}; -use masking::{ExposeInterface, PeekInterface}; +use masking::{ExposeInterface, PeekInterface, Secret}; -use crate::{configs, consts}; +use crate::{configs, consts, routes::AppState}; #[cfg(feature = "olap")] -use crate::{core::errors::UserErrors, services::jwt, types::domain}; +use crate::{ + core::errors::{UserErrors, UserResult}, + services::jwt, + types::domain, +}; pub enum EmailBody { Verify { @@ -23,6 +28,13 @@ pub enum EmailBody { link: String, user_name: String, }, + BizEmailProd { + user_name: String, + poc_email: String, + legal_business_name: String, + business_location: String, + business_website: String, + }, ReconActivation { user_name: String, }, @@ -69,6 +81,22 @@ pub mod html { username = user_name, ) } + EmailBody::BizEmailProd { + user_name, + poc_email, + legal_business_name, + business_location, + business_website, + } => { + format!( + include_str!("assets/bizemailprod.html"), + poc_email = poc_email, + legal_business_name = legal_business_name, + business_location = business_location, + business_website = business_website, + username = user_name, + ) + } EmailBody::ProFeatureRequest { feature_name, merchant_id, @@ -275,6 +303,56 @@ impl EmailData for ReconActivation { } } +pub struct BizEmailProd { + pub recipient_email: domain::UserEmail, + pub user_name: Secret, + pub poc_email: Secret, + pub legal_business_name: String, + pub business_location: String, + pub business_website: String, + pub settings: std::sync::Arc, + pub subject: &'static str, +} + +impl BizEmailProd { + pub fn new(state: &AppState, data: ProdIntent) -> UserResult { + Ok(Self { + recipient_email: (domain::UserEmail::new( + consts::user::BUSINESS_EMAIL.to_string().into(), + ))?, + settings: state.conf.clone(), + subject: "New Prod Intent", + user_name: data.poc_name.unwrap_or_default().into(), + poc_email: data.poc_email.unwrap_or_default().into(), + legal_business_name: data.legal_business_name.unwrap_or_default(), + business_location: data + .business_location + .unwrap_or(common_enums::CountryAlpha2::AD) + .to_string(), + business_website: data.business_website.unwrap_or_default(), + }) + } +} + +#[async_trait::async_trait] +impl EmailData for BizEmailProd { + async fn get_email_data(&self) -> CustomResult { + let body = html::get_html_body(EmailBody::BizEmailProd { + user_name: self.user_name.clone().expose(), + poc_email: self.poc_email.clone().expose(), + legal_business_name: self.legal_business_name.clone(), + business_location: self.business_location.clone(), + business_website: self.business_website.clone(), + }); + + Ok(EmailContents { + subject: self.subject.to_string(), + body: external_services::email::IntermediateString::new(body), + recipient: self.recipient_email.clone().into_inner(), + }) + } +} + pub struct ProFeatureRequest { pub recipient_email: domain::UserEmail, pub feature_name: String, diff --git a/crates/router/src/utils/user/dashboard_metadata.rs b/crates/router/src/utils/user/dashboard_metadata.rs index 09fb5ccd24b4..bcf270010ea7 100644 --- a/crates/router/src/utils/user/dashboard_metadata.rs +++ b/crates/router/src/utils/user/dashboard_metadata.rs @@ -2,7 +2,7 @@ use std::{net::IpAddr, str::FromStr}; use actix_web::http::header::HeaderMap; use api_models::user::dashboard_metadata::{ - GetMetaDataRequest, GetMultipleMetaDataPayload, SetMetaDataRequest, + GetMetaDataRequest, GetMultipleMetaDataPayload, ProdIntent, SetMetaDataRequest, }; use diesel_models::{ enums::DashboardMetadata as DBEnum, @@ -276,3 +276,10 @@ pub fn parse_string_to_enums(query: String) -> UserResult bool { + !(data + .poc_email + .as_ref() + .map_or(true, |mail| mail.contains("juspay"))) +}