Skip to content

Commit

Permalink
feat(email): Add auth_id in email types and send auth_id in email…
Browse files Browse the repository at this point in the history
… URLs (#5120)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
ThisIsMani and hyperswitch-bot[bot] committed Jun 26, 2024
1 parent e69a7bd commit 4ccd25d
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 28 deletions.
2 changes: 1 addition & 1 deletion config/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,6 @@ wildcard_origin = false # If true, allows any origin to make req
[email]
sender_email = "[email protected]" # Sender email
aws_region = "" # AWS region used by AWS SES
base_url = "" # Base url used when adding links that should redirect to self
allowed_unverified_days = 1 # Number of days the api calls ( with jwt token ) can be made without verifying the email
active_email_client = "SES" # The currently active email client

Expand All @@ -359,6 +358,7 @@ sts_role_session_name = "" # An identifier for the assumed role session, used to
password_validity_in_days = 90 # Number of days after which password should be updated
two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside
totp_issuer_name = "Hyperswitch" # Name of the issuer for TOTP
base_url = "" # Base url used for user specific redirects and emails

#tokenization configuration which describe token lifetime and payment method for specific connector
[tokenization]
Expand Down
1 change: 0 additions & 1 deletion config/deployments/env_specific.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ wildcard_origin = false # If true, allows any origin to make req
[email]
sender_email = "[email protected]" # Sender email
aws_region = "" # AWS region used by AWS SES
base_url = "" # Dashboard base url used when adding links that should redirect to self, say https://app.hyperswitch.io for example
allowed_unverified_days = 1 # Number of days the api calls ( with jwt token ) can be made without verifying the email
active_email_client = "SES" # The currently active email client

Expand Down
1 change: 1 addition & 0 deletions config/deployments/integration_test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Integ"
base_url = "https://integ.hyperswitch.io"

[frm]
enabled = true
Expand Down
1 change: 1 addition & 0 deletions config/deployments/production.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Production"
base_url = "https://live.hyperswitch.io"

[frm]
enabled = false
Expand Down
1 change: 1 addition & 0 deletions config/deployments/sandbox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Sandbox"
base_url = "https://app.hyperswitch.io"

[frm]
enabled = true
Expand Down
2 changes: 1 addition & 1 deletion config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ wildcard_origin = true
[email]
sender_email = "[email protected]"
aws_region = ""
base_url = "http:https://localhost:8080"
allowed_unverified_days = 1
active_email_client = "SES"

Expand All @@ -276,6 +275,7 @@ sts_role_session_name = ""
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Dev"
base_url = "http:https://localhost:8080"

[bank_config.eps]
stripe = { banks = "arzte_und_apotheker_bank,austrian_anadi_bank_ag,bank_austria,bankhaus_carl_spangler,bankhaus_schelhammer_und_schattera_ag,bawag_psk_ag,bks_bank_ag,brull_kallmus_bank_ag,btv_vier_lander_bank,capital_bank_grawe_gruppe_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_alpeadriabank_international_ag,hypo_noe_lb_fur_niederosterreich_u_wien,hypo_oberosterreich_salzburg_steiermark,hypo_tirol_bank_ag,hypo_vorarlberg_bank_ag,hypo_bank_burgenland_aktiengesellschaft,marchfelder_bank,oberbank_ag,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag,vr_bank_braunau" }
Expand Down
1 change: 1 addition & 0 deletions config/docker_compose.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ recon_admin_api_key = "recon_test_admin"
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch"
base_url = "http:https://localhost:8080"

[locker]
host = ""
Expand Down
5 changes: 5 additions & 0 deletions crates/api_models/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,8 @@ pub struct AuthMethodDetails {
pub auth_type: common_enums::UserAuthType,
pub name: Option<OpenIdProvider>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct AuthIdQueryParam {
pub auth_id: Option<String>,
}
3 changes: 0 additions & 3 deletions crates/external_services/src/email.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,6 @@ pub struct EmailSettings {
/// The AWS region to send SES requests to.
pub aws_region: String,

/// Base-url used when adding links that should redirect to self
pub base_url: String,

/// Number of days for verification of the email
pub allowed_unverified_days: i64,

Expand Down
1 change: 1 addition & 0 deletions crates/router/src/configs/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ pub struct UserSettings {
pub password_validity_in_days: u16,
pub two_factor_auth_expiry_in_secs: i64,
pub totp_issuer_name: String,
pub base_url: String,
}

#[derive(Debug, Deserialize, Clone)]
Expand Down
42 changes: 38 additions & 4 deletions crates/router/src/core/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub mod sample_data;
pub async fn signup_with_merchant_id(
state: SessionState,
request: user_api::SignUpWithMerchantIdRequest,
auth_id: Option<String>,
) -> UserResponse<user_api::SignUpWithMerchantIdResponse> {
let new_user = domain::NewUser::try_from(request.clone())?;
new_user
Expand All @@ -64,6 +65,7 @@ pub async fn signup_with_merchant_id(
user_name: domain::UserName::new(user_from_db.get_name())?,
settings: state.conf.clone(),
subject: "Get back to Hyperswitch - Reset Your Password Now",
auth_id,
};

let send_email_result = state
Expand Down Expand Up @@ -241,6 +243,7 @@ pub async fn signin_token_only_flow(
pub async fn connect_account(
state: SessionState,
request: user_api::ConnectAccountRequest,
auth_id: Option<String>,
) -> UserResponse<user_api::ConnectAccountResponse> {
let find_user = state.global_store.find_user_by_email(&request.email).await;

Expand All @@ -253,6 +256,7 @@ pub async fn connect_account(
settings: state.conf.clone(),
user_name: domain::UserName::new(user_from_db.get_name())?,
subject: "Unlock Hyperswitch: Use Your Magic Link to Sign In",
auth_id,
};

let send_email_result = state
Expand Down Expand Up @@ -303,6 +307,7 @@ pub async fn connect_account(
recipient_email: domain::UserEmail::from_pii_email(user_from_db.get_email())?,
settings: state.conf.clone(),
subject: "Welcome to the Hyperswitch community!",
auth_id,
};

let send_email_result = state
Expand Down Expand Up @@ -401,6 +406,7 @@ pub async fn change_password(
pub async fn forgot_password(
state: SessionState,
request: user_api::ForgotPasswordRequest,
auth_id: Option<String>,
) -> UserResponse<()> {
let user_email = domain::UserEmail::from_pii_email(request.email)?;

Expand All @@ -422,6 +428,7 @@ pub async fn forgot_password(
settings: state.conf.clone(),
user_name: domain::UserName::new(user_from_db.get_name())?,
subject: "Get back to Hyperswitch - Reset Your Password Now",
auth_id,
};

state
Expand Down Expand Up @@ -596,14 +603,23 @@ pub async fn invite_multiple_user(
requests: Vec<user_api::InviteUserRequest>,
req_state: ReqState,
is_token_only: Option<bool>,
auth_id: Option<String>,
) -> UserResponse<Vec<InviteMultipleUserResponse>> {
if requests.len() > 10 {
return Err(report!(UserErrors::MaxInvitationsError))
.attach_printable("Number of invite requests must not exceed 10");
}

let responses = futures::future::join_all(requests.iter().map(|request| async {
match handle_invitation(&state, &user_from_token, request, &req_state, is_token_only).await
match handle_invitation(
&state,
&user_from_token,
request,
&req_state,
is_token_only,
&auth_id,
)
.await
{
Ok(response) => response,
Err(error) => InviteMultipleUserResponse {
Expand All @@ -625,6 +641,7 @@ async fn handle_invitation(
request: &user_api::InviteUserRequest,
req_state: &ReqState,
is_token_only: Option<bool>,
auth_id: &Option<String>,
) -> UserResult<InviteMultipleUserResponse> {
let inviter_user = user_from_token.get_user_from_db(state).await?;

Expand Down Expand Up @@ -656,7 +673,14 @@ async fn handle_invitation(
.await;

if let Ok(invitee_user) = invitee_user {
handle_existing_user_invitation(state, user_from_token, request, invitee_user.into()).await
handle_existing_user_invitation(
state,
user_from_token,
request,
invitee_user.into(),
auth_id,
)
.await
} else if invitee_user
.as_ref()
.map_err(|e| e.current_context().is_db_not_found())
Expand All @@ -669,19 +693,21 @@ async fn handle_invitation(
request,
req_state.clone(),
is_token_only,
auth_id,
)
.await
} else {
Err(UserErrors::InternalServerError.into())
}
}

//TODO: send email
#[allow(unused_variables)]
async fn handle_existing_user_invitation(
state: &SessionState,
user_from_token: &auth::UserFromToken,
request: &user_api::InviteUserRequest,
invitee_user_from_db: domain::UserFromStorage,
auth_id: &Option<String>,
) -> UserResult<InviteMultipleUserResponse> {
let now = common_utils::date_time::now();
state
Expand Down Expand Up @@ -722,6 +748,7 @@ async fn handle_existing_user_invitation(
settings: state.conf.clone(),
subject: "You have been invited to join Hyperswitch Community!",
merchant_id: user_from_token.merchant_id.clone(),
auth_id: auth_id.clone(),
};

is_email_sent = state
Expand All @@ -748,12 +775,14 @@ async fn handle_existing_user_invitation(
})
}

#[allow(unused_variables)]
async fn handle_new_user_invitation(
state: &SessionState,
user_from_token: &auth::UserFromToken,
request: &user_api::InviteUserRequest,
req_state: ReqState,
is_token_only: Option<bool>,
auth_id: &Option<String>,
) -> UserResult<InviteMultipleUserResponse> {
let new_user = domain::NewUser::try_from((request.clone(), user_from_token.clone()))?;

Expand Down Expand Up @@ -809,6 +838,7 @@ async fn handle_new_user_invitation(
settings: state.conf.clone(),
subject: "You have been invited to join Hyperswitch Community!",
merchant_id: user_from_token.merchant_id.clone(),
auth_id: auth_id.clone(),
})
} else {
Box::new(email_types::InviteUser {
Expand All @@ -817,6 +847,7 @@ async fn handle_new_user_invitation(
settings: state.conf.clone(),
subject: "You have been invited to join Hyperswitch Community!",
merchant_id: user_from_token.merchant_id.clone(),
auth_id: auth_id.clone(),
})
};
let send_email_result = state
Expand Down Expand Up @@ -862,7 +893,7 @@ pub async fn resend_invite(
state: SessionState,
user_from_token: auth::UserFromToken,
request: user_api::ReInviteUserRequest,
_req_state: ReqState,
auth_id: Option<String>,
) -> UserResponse<()> {
let invitee_email = domain::UserEmail::from_pii_email(request.email)?;
let user: domain::UserFromStorage = state
Expand Down Expand Up @@ -906,6 +937,7 @@ pub async fn resend_invite(
settings: state.conf.clone(),
subject: "You have been invited to join Hyperswitch Community!",
merchant_id: user_from_token.merchant_id,
auth_id,
};
state
.email_client
Expand Down Expand Up @@ -1518,6 +1550,7 @@ pub async fn verify_email_token_only_flow(
pub async fn send_verification_mail(
state: SessionState,
req: user_api::SendVerifyEmailRequest,
auth_id: Option<String>,
) -> UserResponse<()> {
let user_email = domain::UserEmail::try_from(req.email)?;
let user = state
Expand All @@ -1540,6 +1573,7 @@ pub async fn send_verification_mail(
recipient_email: domain::UserEmail::from_pii_email(user.email)?,
settings: state.conf.clone(),
subject: "Welcome to the Hyperswitch community!",
auth_id,
};

state
Expand Down
Loading

0 comments on commit 4ccd25d

Please sign in to comment.