feat(users): implement force set and force change password (#4564)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Apoorv Dixit
2024-05-07 19:41:24 +05:30
committed by GitHub
parent d974e6e7c2
commit 59e79ff205
25 changed files with 240 additions and 34 deletions

View File

@ -349,11 +349,8 @@ pub async fn change_password(
.store
.update_user_by_user_id(
user.get_user_id(),
diesel_models::user::UserUpdate::AccountUpdate {
name: None,
diesel_models::user::UserUpdate::PasswordUpdate {
password: Some(new_password_hash),
is_verified: None,
preferred_merchant_id: None,
},
)
.await
@ -419,6 +416,98 @@ pub async fn forgot_password(
Ok(ApplicationResponse::StatusOk)
}
pub async fn rotate_password(
state: AppState,
user_token: auth::UserFromSinglePurposeToken,
request: user_api::RotatePasswordRequest,
_req_state: ReqState,
) -> UserResponse<()> {
let user: domain::UserFromStorage = state
.store
.find_user_by_id(&user_token.user_id)
.await
.change_context(UserErrors::InternalServerError)?
.into();
let password = domain::UserPassword::new(request.password.to_owned())?;
let hash_password = utils::user::password::generate_password_hash(password.get_secret())?;
if user.compare_password(request.password).is_ok() {
return Err(UserErrors::ChangePasswordError.into());
}
let user = state
.store
.update_user_by_user_id(
&user_token.user_id,
storage_user::UserUpdate::PasswordUpdate {
password: Some(hash_password),
},
)
.await
.change_context(UserErrors::InternalServerError)?;
let _ = auth::blacklist::insert_user_in_blacklist(&state, &user.user_id)
.await
.map_err(|e| logger::error!(?e));
Ok(ApplicationResponse::StatusOk)
}
#[cfg(feature = "email")]
pub async fn reset_password_token_only_flow(
state: AppState,
user_token: auth::UserFromSinglePurposeToken,
request: user_api::ResetPasswordRequest,
) -> UserResponse<()> {
let token = request.token.expose();
let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
.await
.change_context(UserErrors::LinkInvalid)?;
auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
let user_from_db: domain::UserFromStorage = state
.store
.find_user_by_email(
&email_token
.get_email()
.change_context(UserErrors::InternalServerError)?,
)
.await
.change_context(UserErrors::InternalServerError)?
.into();
if user_from_db.get_user_id() != user_token.user_id {
return Err(UserErrors::LinkInvalid.into());
}
let password = domain::UserPassword::new(request.password)?;
let hash_password = utils::user::password::generate_password_hash(password.get_secret())?;
let user = state
.store
.update_user_by_email(
&email_token
.get_email()
.change_context(UserErrors::InternalServerError)?,
storage_user::UserUpdate::PasswordUpdate {
password: Some(hash_password),
},
)
.await
.change_context(UserErrors::InternalServerError)?;
let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
.await
.map_err(|e| logger::error!(?e));
let _ = auth::blacklist::insert_user_in_blacklist(&state, &user.user_id)
.await
.map_err(|e| logger::error!(?e));
Ok(ApplicationResponse::StatusOk)
}
#[cfg(feature = "email")]
pub async fn reset_password(
state: AppState,
@ -432,7 +521,6 @@ pub async fn reset_password(
auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
let password = domain::UserPassword::new(request.password)?;
let hash_password = utils::user::password::generate_password_hash(password.get_secret())?;
let user = state
@ -441,11 +529,8 @@ pub async fn reset_password(
&email_token
.get_email()
.change_context(UserErrors::InternalServerError)?,
storage_user::UserUpdate::AccountUpdate {
name: None,
storage_user::UserUpdate::PasswordUpdate {
password: Some(hash_password),
is_verified: Some(true),
preferred_merchant_id: None,
},
)
.await
@ -1449,7 +1534,6 @@ pub async fn update_user_details(
let user_update = storage_user::UserUpdate::AccountUpdate {
name: name.map(|x| x.get_secret().expose()),
password: None,
is_verified: None,
preferred_merchant_id: req.preferred_merchant_id,
};