diff --git a/crates/api_models/src/user.rs b/crates/api_models/src/user.rs index 9b193a9ba1..afe55afb27 100644 --- a/crates/api_models/src/user.rs +++ b/crates/api_models/src/user.rs @@ -190,6 +190,9 @@ pub struct UserMerchantAccount { pub merchant_id: String, pub merchant_name: OptionalEncryptableName, pub is_active: bool, + pub role_id: String, + pub role_name: String, + pub org_id: String, } #[cfg(feature = "recon")] diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index 2702cec8eb..50fd094d8d 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -1173,7 +1173,7 @@ pub async fn create_merchant_account( Ok(ApplicationResponse::StatusOk) } -pub async fn list_merchant_ids_for_user( +pub async fn list_merchants_for_user( state: AppState, user_from_token: auth::UserFromToken, ) -> UserResponse> { @@ -1194,8 +1194,15 @@ pub async fn list_merchant_ids_for_user( .await .change_context(UserErrors::InternalServerError)?; + let roles = + utils::user_role::get_multiple_role_info_for_user_roles(&state, &user_roles).await?; + Ok(ApplicationResponse::Json( - utils::user::get_multiple_merchant_details_with_status(user_roles, merchant_accounts)?, + utils::user::get_multiple_merchant_details_with_status( + user_roles, + merchant_accounts, + roles, + )?, )) } diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 41893b0544..e0e3045aa8 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1135,7 +1135,9 @@ impl User { web::resource("/create_merchant") .route(web::post().to(user_merchant_account_create)), ) - .service(web::resource("/switch/list").route(web::get().to(list_merchant_ids_for_user))) + // TODO: Remove this endpoint once migration to /merchants/list is done + .service(web::resource("/switch/list").route(web::get().to(list_merchants_for_user))) + .service(web::resource("/merchants/list").route(web::get().to(list_merchants_for_user))) .service(web::resource("/permission_info").route(web::get().to(get_authorization_info))) .service(web::resource("/update").route(web::post().to(update_user_account_details))) .service( diff --git a/crates/router/src/routes/user.rs b/crates/router/src/routes/user.rs index c296d3d93b..3e5061b401 100644 --- a/crates/router/src/routes/user.rs +++ b/crates/router/src/routes/user.rs @@ -297,17 +297,14 @@ pub async fn delete_sample_data( .await } -pub async fn list_merchant_ids_for_user( - state: web::Data, - req: HttpRequest, -) -> HttpResponse { +pub async fn list_merchants_for_user(state: web::Data, req: HttpRequest) -> HttpResponse { let flow = Flow::UserMerchantAccountList; Box::pin(api::server_wrap( flow, state, &req, (), - |state, user, _| user_core::list_merchant_ids_for_user(state, user), + |state, user, _| user_core::list_merchants_for_user(state, user), &auth::DashboardNoPermissionAuth, api_locking::LockAction::NotApplicable, )) diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs index 93df373d21..bc06ffbad7 100644 --- a/crates/router/src/types/domain/user.rs +++ b/crates/router/src/types/domain/user.rs @@ -896,9 +896,14 @@ impl SignInWithMultipleRolesStrategy { .await .change_context(UserErrors::InternalServerError)?; + let roles = + utils::user_role::get_multiple_role_info_for_user_roles(state, &self.user_roles) + .await?; + let merchant_details = utils::user::get_multiple_merchant_details_with_status( self.user_roles, merchant_accounts, + roles, )?; Ok(user_api::SignInResponse::MerchantSelect( diff --git a/crates/router/src/utils/user.rs b/crates/router/src/utils/user.rs index f8b7d86c74..60b2ac4828 100644 --- a/crates/router/src/utils/user.rs +++ b/crates/router/src/utils/user.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use api_models::user as user_api; use common_utils::errors::CustomResult; use diesel_models::{enums::UserStatus, user_role::UserRole}; -use error_stack::{report, ResultExt}; +use error_stack::ResultExt; use masking::{ExposeInterface, Secret}; use crate::{ @@ -137,24 +137,38 @@ pub fn get_verification_days_left( pub fn get_multiple_merchant_details_with_status( user_roles: Vec, merchant_accounts: Vec, + roles: Vec, ) -> UserResult> { - let roles: HashMap<_, _> = user_roles + let merchant_account_map = merchant_accounts .into_iter() - .map(|user_role| (user_role.merchant_id.clone(), user_role)) - .collect(); + .map(|merchant_account| (merchant_account.merchant_id.clone(), merchant_account)) + .collect::>(); - merchant_accounts + let role_map = roles .into_iter() - .map(|merchant| { - let role = roles - .get(merchant.merchant_id.as_str()) - .ok_or(report!(UserErrors::InternalServerError)) - .attach_printable("Merchant exists but user role doesn't")?; + .map(|role_info| (role_info.get_role_id().to_string(), role_info)) + .collect::>(); + + user_roles + .into_iter() + .map(|user_role| { + let merchant_account = merchant_account_map + .get(&user_role.merchant_id) + .ok_or(UserErrors::InternalServerError) + .attach_printable("Merchant account for user role doesn't exist")?; + + let role_info = role_map + .get(&user_role.role_id) + .ok_or(UserErrors::InternalServerError) + .attach_printable("Role info for user role doesn't exist")?; Ok(user_api::UserMerchantAccount { - merchant_id: merchant.merchant_id.clone(), - merchant_name: merchant.merchant_name.clone(), - is_active: role.status == UserStatus::Active, + merchant_id: user_role.merchant_id, + merchant_name: merchant_account.merchant_name.clone(), + is_active: user_role.status == UserStatus::Active, + role_id: user_role.role_id, + role_name: role_info.get_role_name().to_string(), + org_id: user_role.org_id, }) }) .collect() diff --git a/crates/router/src/utils/user_role.rs b/crates/router/src/utils/user_role.rs index 1a52153b43..ba4c287866 100644 --- a/crates/router/src/utils/user_role.rs +++ b/crates/router/src/utils/user_role.rs @@ -8,7 +8,7 @@ use router_env::logger; use crate::{ consts, - core::errors::{UserErrors, UserResult}, + core::errors::{StorageErrorExt, UserErrors, UserResult}, routes::AppState, services::authorization::{self as authz, permissions::Permission, roles}, types::domain, @@ -141,3 +141,22 @@ pub async fn set_role_permissions_in_cache_if_required( .change_context(UserErrors::InternalServerError) .attach_printable("Error setting permissions in redis") } + +pub async fn get_multiple_role_info_for_user_roles( + state: &AppState, + user_roles: &[UserRole], +) -> UserResult> { + futures::future::try_join_all(user_roles.iter().map(|user_role| async { + let role = roles::RoleInfo::from_role_id( + state, + &user_role.role_id, + &user_role.merchant_id, + &user_role.org_id, + ) + .await + .to_not_found_response(UserErrors::InternalServerError) + .attach_printable("Role for user role doesn't exist")?; + Ok::<_, error_stack::Report>(role) + })) + .await +}