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

fix(users): Add force rotate password on first login for non-email flow #6483

Merged
merged 3 commits into from
Nov 7, 2024
Merged
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
68 changes: 53 additions & 15 deletions crates/router/src/types/domain/user.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{collections::HashSet, ops, str::FromStr};
use std::{
collections::HashSet,
ops::{Deref, Not},
str::FromStr,
};

use api_models::{
admin as admin_api, organization as api_org, user as user_api, user_role as user_role_api,
Expand Down Expand Up @@ -153,7 +157,7 @@ impl TryFrom<pii::Email> for UserEmail {
}
}

impl ops::Deref for UserEmail {
impl Deref for UserEmail {
type Target = Secret<String, pii::EmailStrategy>;

fn deref(&self) -> &Self::Target {
Expand Down Expand Up @@ -565,10 +569,24 @@ pub struct NewUser {
user_id: String,
name: UserName,
email: UserEmail,
password: Option<UserPassword>,
password: Option<NewUserPassword>,
new_merchant: NewUserMerchant,
}

#[derive(Clone)]
pub struct NewUserPassword {
password: UserPassword,
is_temporary: bool,
}

impl Deref for NewUserPassword {
type Target = UserPassword;

fn deref(&self) -> &Self::Target {
&self.password
}
}

impl NewUser {
pub fn get_user_id(&self) -> String {
self.user_id.clone()
Expand All @@ -587,7 +605,9 @@ impl NewUser {
}

pub fn get_password(&self) -> Option<UserPassword> {
self.password.clone()
self.password
.as_ref()
.map(|password| password.deref().clone())
}

pub async fn insert_user_in_db(
Expand Down Expand Up @@ -697,7 +717,9 @@ impl TryFrom<NewUser> for storage_user::UserNew {
totp_status: TotpStatus::NotSet,
totp_secret: None,
totp_recovery_codes: None,
last_password_modified_at: value.password.is_some().then_some(now),
last_password_modified_at: value
.password
.and_then(|password_inner| password_inner.is_temporary.not().then_some(now)),
})
}
}
Expand All @@ -708,7 +730,10 @@ impl TryFrom<user_api::SignUpWithMerchantIdRequest> for NewUser {
fn try_from(value: user_api::SignUpWithMerchantIdRequest) -> UserResult<Self> {
let email = value.email.clone().try_into()?;
let name = UserName::new(value.name.clone())?;
let password = UserPassword::new(value.password.clone())?;
let password = NewUserPassword {
password: UserPassword::new(value.password.clone())?,
is_temporary: false,
};
let user_id = uuid::Uuid::new_v4().to_string();
let new_merchant = NewUserMerchant::try_from(value)?;

Expand All @@ -729,7 +754,10 @@ impl TryFrom<user_api::SignUpRequest> for NewUser {
let user_id = uuid::Uuid::new_v4().to_string();
let email = value.email.clone().try_into()?;
let name = UserName::try_from(value.email.clone())?;
let password = UserPassword::new(value.password.clone())?;
let password = NewUserPassword {
password: UserPassword::new(value.password.clone())?,
is_temporary: false,
};
let new_merchant = NewUserMerchant::try_from(value)?;

Ok(Self {
Expand Down Expand Up @@ -770,7 +798,10 @@ impl TryFrom<(user_api::CreateInternalUserRequest, id_type::OrganizationId)> for
let user_id = uuid::Uuid::new_v4().to_string();
let email = value.email.clone().try_into()?;
let name = UserName::new(value.name.clone())?;
let password = UserPassword::new(value.password.clone())?;
let password = NewUserPassword {
password: UserPassword::new(value.password.clone())?,
is_temporary: false,
};
let new_merchant = NewUserMerchant::try_from((value, org_id))?;

Ok(Self {
Expand All @@ -789,16 +820,21 @@ impl TryFrom<UserMerchantCreateRequestWithToken> for NewUser {
fn try_from(value: UserMerchantCreateRequestWithToken) -> Result<Self, Self::Error> {
let user = value.0.clone();
let new_merchant = NewUserMerchant::try_from(value)?;
let password = user
.0
.password
.map(UserPassword::new_password_without_validation)
.transpose()?
.map(|password| NewUserPassword {
password,
is_temporary: false,
});

Ok(Self {
user_id: user.0.user_id,
name: UserName::new(user.0.name)?,
email: user.0.email.clone().try_into()?,
password: user
.0
.password
.map(UserPassword::new_password_without_validation)
.transpose()?,
password,
new_merchant,
})
}
Expand All @@ -810,8 +846,10 @@ impl TryFrom<InviteeUserRequestWithInvitedUserToken> for NewUser {
let user_id = uuid::Uuid::new_v4().to_string();
let email = value.0.email.clone().try_into()?;
let name = UserName::new(value.0.name.clone())?;
let password = cfg!(not(feature = "email"))
.then_some(UserPassword::new(password::get_temp_password())?);
let password = cfg!(not(feature = "email")).then_some(NewUserPassword {
password: UserPassword::new(password::get_temp_password())?,
is_temporary: true,
});
let new_merchant = NewUserMerchant::try_from(value)?;

Ok(Self {
Expand Down
Loading