refactor(user_roles): make org and merchant id nullable (#5353)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Mani Chandra Dulam <mani.dchandra@juspay.in>
This commit is contained in:
Apoorv Dixit
2024-07-25 16:02:58 +05:30
committed by GitHub
parent 9ca9545318
commit 0330aff958
16 changed files with 545 additions and 202 deletions

View File

@ -8,7 +8,7 @@ use common_utils::types::keymanager::Identifier;
#[cfg(feature = "email")]
use diesel_models::user_role::UserRoleUpdate;
use diesel_models::{
enums::{TotpStatus, UserStatus},
enums::{TotpStatus, UserRoleVersion, UserStatus},
user as storage_user,
user_authentication_method::{UserAuthenticationMethodNew, UserAuthenticationMethodUpdate},
user_role::UserRoleNew,
@ -81,11 +81,16 @@ pub async fn signup_with_merchant_id(
)
.await;
let Some(merchant_id) = user_role.merchant_id else {
return Err(report!(UserErrors::InternalServerError)
.attach_printable("merchant_id not found for user_role"));
};
logger::info!(?send_email_result);
Ok(ApplicationResponse::Json(user_api::AuthorizeResponse {
is_email_sent: send_email_result.is_ok(),
user_id: user_from_db.get_user_id().to_string(),
merchant_id: user_role.merchant_id,
merchant_id,
}))
}
@ -203,7 +208,7 @@ pub async fn signin(
.attach_printable("User role with preferred_merchant_id not found")?;
domain::SignInWithRoleStrategyType::SingleRole(domain::SignInWithSingleRoleStrategy {
user: user_from_db,
user_role: preferred_role,
user_role: Box::new(preferred_role),
})
} else {
let user_roles = user_from_db.get_roles_from_db(&state).await?;
@ -272,13 +277,17 @@ pub async fn connect_account(
)
.await;
let Some(merchant_id) = user_role.merchant_id else {
return Err(report!(UserErrors::InternalServerError)
.attach_printable("merchant_id not found for user_role"));
};
logger::info!(?send_email_result);
return Ok(ApplicationResponse::Json(
user_api::ConnectAccountResponse {
is_email_sent: send_email_result.is_ok(),
user_id: user_from_db.get_user_id().to_string(),
merchant_id: user_role.merchant_id,
merchant_id,
},
));
} else if find_user
@ -323,13 +332,18 @@ pub async fn connect_account(
)
.await;
let Some(merchant_id) = user_role.merchant_id else {
return Err(report!(UserErrors::InternalServerError)
.attach_printable("merchant_id not found for user_role"));
};
logger::info!(?send_email_result);
return Ok(ApplicationResponse::Json(
user_api::ConnectAccountResponse {
is_email_sent: send_email_result.is_ok(),
user_id: user_from_db.get_user_id().to_string(),
merchant_id: user_role.merchant_id,
merchant_id,
},
));
} else {
@ -587,6 +601,7 @@ pub async fn reset_password(
status: UserStatus::Active,
modified_by: user.user_id.clone(),
},
UserRoleVersion::V1,
)
.await;
logger::info!(?update_status_result);
@ -719,9 +734,9 @@ async fn handle_existing_user_invitation(
.store
.insert_user_role(UserRoleNew {
user_id: invitee_user_from_db.get_user_id().to_owned(),
merchant_id: user_from_token.merchant_id.clone(),
merchant_id: Some(user_from_token.merchant_id.clone()),
role_id: request.role_id.clone(),
org_id: user_from_token.org_id.clone(),
org_id: Some(user_from_token.org_id.clone()),
status: {
if cfg!(feature = "email") {
UserStatus::InvitationSent
@ -733,6 +748,10 @@ async fn handle_existing_user_invitation(
last_modified_by: user_from_token.user_id.clone(),
created_at: now,
last_modified: now,
profile_id: None,
entity_id: None,
entity_type: None,
version: UserRoleVersion::V1,
})
.await
.map_err(|e| {
@ -807,14 +826,18 @@ async fn handle_new_user_invitation(
.store
.insert_user_role(UserRoleNew {
user_id: new_user.get_user_id().to_owned(),
merchant_id: user_from_token.merchant_id.clone(),
merchant_id: Some(user_from_token.merchant_id.clone()),
role_id: request.role_id.clone(),
org_id: user_from_token.org_id.clone(),
org_id: Some(user_from_token.org_id.clone()),
status: invitation_status,
created_by: user_from_token.user_id.clone(),
last_modified_by: user_from_token.user_id.clone(),
created_at: now,
last_modified: now,
profile_id: None,
entity_id: None,
entity_type: None,
version: UserRoleVersion::V1,
})
.await
.map_err(|e| {
@ -916,7 +939,11 @@ pub async fn resend_invite(
.into();
let user_role = state
.store
.find_user_role_by_user_id_merchant_id(user.get_user_id(), &user_from_token.merchant_id)
.find_user_role_by_user_id_merchant_id(
user.get_user_id(),
&user_from_token.merchant_id,
UserRoleVersion::V1,
)
.await
.map_err(|e| {
if e.current_context().is_db_not_found() {
@ -993,6 +1020,7 @@ pub async fn accept_invite_from_email(
status: UserStatus::Active,
modified_by: user.get_user_id().to_string(),
},
UserRoleVersion::V1,
)
.await
.change_context(UserErrors::InternalServerError)?;
@ -1065,6 +1093,7 @@ pub async fn accept_invite_from_email_token_only_flow(
status: UserStatus::Active,
modified_by: user_from_db.get_user_id().to_string(),
},
UserRoleVersion::V1,
)
.await
.change_context(UserErrors::InternalServerError)?;
@ -1241,7 +1270,7 @@ pub async fn switch_merchant_id(
} else {
let user_roles = state
.store
.list_user_roles_by_user_id(&user_from_token.user_id)
.list_user_roles_by_user_id(&user_from_token.user_id, UserRoleVersion::V1)
.await
.change_context(UserErrors::InternalServerError)?;
@ -1252,7 +1281,17 @@ pub async fn switch_merchant_id(
let user_role = active_user_roles
.iter()
.find(|role| role.merchant_id == request.merchant_id)
.find_map(|role| {
let Some(ref merchant_id) = role.merchant_id else {
return Some(Err(report!(UserErrors::InternalServerError)));
};
if merchant_id == &request.merchant_id {
Some(Ok(role))
} else {
None
}
})
.transpose()?
.ok_or(report!(UserErrors::InvalidRoleOperation))
.attach_printable("User doesn't have access to switch")?;
@ -1312,7 +1351,7 @@ pub async fn list_merchants_for_user(
) -> UserResponse<Vec<user_api::UserMerchantAccount>> {
let user_roles = state
.store
.list_user_roles_by_user_id(user_from_token.user_id.as_str())
.list_user_roles_by_user_id(user_from_token.user_id.as_str(), UserRoleVersion::V1)
.await
.change_context(UserErrors::InternalServerError)?;
@ -1322,8 +1361,12 @@ pub async fn list_merchants_for_user(
&(&state).into(),
user_roles
.iter()
.map(|role| role.merchant_id.clone())
.collect(),
.map(|role| {
role.merchant_id
.clone()
.ok_or(UserErrors::InternalServerError)
})
.collect::<Result<Vec<_>, _>>()?,
)
.await
.change_context(UserErrors::InternalServerError)?;
@ -1355,6 +1398,7 @@ pub async fn get_user_details_in_merchant_account(
.find_user_role_by_user_id_merchant_id(
required_user.get_user_id(),
&user_from_token.merchant_id,
UserRoleVersion::V1,
)
.await
.to_not_found_response(UserErrors::InvalidRoleOperation)
@ -1390,7 +1434,7 @@ pub async fn list_users_for_merchant_account(
) -> UserResponse<user_api::ListUsersResponse> {
let user_roles: HashMap<String, _> = state
.store
.list_user_roles_by_merchant_id(&user_from_token.merchant_id)
.list_user_roles_by_merchant_id(&user_from_token.merchant_id, UserRoleVersion::V1)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("No user roles for given merchant id")?
@ -1422,8 +1466,14 @@ pub async fn list_users_for_merchant_account(
roles::RoleInfo::from_role_id(
&state,
&user_role.role_id.clone(),
&user_role.merchant_id,
&user_role.org_id,
user_role
.merchant_id
.as_ref()
.ok_or(UserErrors::InternalServerError)?,
user_role
.org_id
.as_ref()
.ok_or(UserErrors::InternalServerError)?,
)
.await
.map(|role_info| (user, user_role, role_info))
@ -1491,7 +1541,7 @@ pub async fn verify_email(
.attach_printable("User role with preferred_merchant_id not found")?;
domain::SignInWithRoleStrategyType::SingleRole(domain::SignInWithSingleRoleStrategy {
user: user_from_db,
user_role: preferred_role,
user_role: Box::new(preferred_role),
})
} else {
let user_roles = user_from_db.get_roles_from_db(&state).await?;
@ -1624,10 +1674,11 @@ pub async fn verify_token(
})?;
let merchant_id = state
.store
.find_user_role_by_user_id(&req.user_id)
.find_user_role_by_user_id(&req.user_id, UserRoleVersion::V1)
.await
.change_context(UserErrors::InternalServerError)?
.merchant_id;
.merchant_id
.ok_or(UserErrors::InternalServerError)?;
Ok(ApplicationResponse::Json(user_api::VerifyTokenResponse {
merchant_id: merchant_id.to_owned(),
@ -1653,7 +1704,11 @@ pub async fn update_user_details(
if let Some(ref preferred_merchant_id) = req.preferred_merchant_id {
let _ = state
.store
.find_user_role_by_user_id_merchant_id(user.get_user_id(), preferred_merchant_id)
.find_user_role_by_user_id_merchant_id(
user.get_user_id(),
preferred_merchant_id,
UserRoleVersion::V1,
)
.await
.map_err(|e| {
if e.current_context().is_db_not_found() {

View File

@ -1,5 +1,8 @@
use api_models::{user as user_api, user_role as user_role_api};
use diesel_models::{enums::UserStatus, user_role::UserRoleUpdate};
use diesel_models::{
enums::{UserRoleVersion, UserStatus},
user_role::UserRoleUpdate,
};
use error_stack::{report, ResultExt};
use router_env::logger;
@ -101,11 +104,15 @@ pub async fn update_user_role(
.store
.update_user_role_by_user_id_merchant_id(
user_to_be_updated.get_user_id(),
&user_role_to_be_updated.merchant_id,
&user_role_to_be_updated
.merchant_id
.ok_or(UserErrors::InternalServerError)
.attach_printable("merchant_id not found in user_role")?,
UserRoleUpdate::UpdateRole {
role_id: req.role_id.clone(),
modified_by: user_from_token.user_id,
},
UserRoleVersion::V1,
)
.await
.to_not_found_response(UserErrors::InvalidRoleOperation)
@ -146,6 +153,7 @@ pub async fn transfer_org_ownership(
&user_from_token.user_id,
user_to_be_updated.get_user_id(),
&user_from_token.org_id,
UserRoleVersion::V1,
)
.await
.change_context(UserErrors::InternalServerError)?;
@ -183,6 +191,7 @@ pub async fn accept_invitation(
status: UserStatus::Active,
modified_by: user_token.user_id.clone(),
},
UserRoleVersion::V1,
)
.await
.map_err(|e| {
@ -213,6 +222,7 @@ pub async fn merchant_select(
status: UserStatus::Active,
modified_by: user_token.user_id.clone(),
},
UserRoleVersion::V1,
)
.await
.map_err(|e| {
@ -267,6 +277,7 @@ pub async fn merchant_select_token_only_flow(
status: UserStatus::Active,
modified_by: user_token.user_id.clone(),
},
UserRoleVersion::V1,
)
.await
.map_err(|e| {
@ -329,15 +340,17 @@ pub async fn delete_user_role(
let user_roles = state
.store
.list_user_roles_by_user_id(user_from_db.get_user_id())
.list_user_roles_by_user_id(user_from_db.get_user_id(), UserRoleVersion::V1)
.await
.change_context(UserErrors::InternalServerError)?;
match user_roles
.iter()
.find(|&role| role.merchant_id == user_from_token.merchant_id)
{
Some(user_role) => {
for user_role in user_roles.iter() {
let Some(merchant_id) = user_role.merchant_id.as_ref() else {
return Err(report!(UserErrors::InternalServerError))
.attach_printable("merchant_id not found for user_role");
};
if merchant_id == &user_from_token.merchant_id {
let role_info = roles::RoleInfo::from_role_id(
&state,
&user_role.role_id,
@ -350,12 +363,11 @@ pub async fn delete_user_role(
return Err(report!(UserErrors::InvalidDeleteOperation))
.attach_printable(format!("role_id = {} is not deletable", user_role.role_id));
}
}
None => {
} else {
return Err(report!(UserErrors::InvalidDeleteOperation))
.attach_printable("User is not associated with the merchant");
}
};
}
let deleted_user_role = if user_roles.len() > 1 {
state
@ -363,6 +375,7 @@ pub async fn delete_user_role(
.delete_user_role_by_user_id_merchant_id(
user_from_db.get_user_id(),
&user_from_token.merchant_id,
UserRoleVersion::V1,
)
.await
.change_context(UserErrors::InternalServerError)
@ -380,6 +393,7 @@ pub async fn delete_user_role(
.delete_user_role_by_user_id_merchant_id(
user_from_db.get_user_id(),
&user_from_token.merchant_id,
UserRoleVersion::V1,
)
.await
.change_context(UserErrors::InternalServerError)