Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(email): Add auth_id in email types and send auth_id in email URLs #5120

Merged
merged 7 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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://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://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://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
Loading