diff --git a/crates/api_models/src/events/user.rs b/crates/api_models/src/events/user.rs index 9884dbc4f4..8f017ca8c2 100644 --- a/crates/api_models/src/events/user.rs +++ b/crates/api_models/src/events/user.rs @@ -12,10 +12,11 @@ use crate::user::{ }, AcceptInviteFromEmailRequest, AuthorizeResponse, ChangePasswordRequest, ConnectAccountRequest, CreateInternalUserRequest, DashboardEntryResponse, ForgotPasswordRequest, - GetUserDetailsRequest, GetUserDetailsResponse, InviteUserRequest, ListUsersResponse, - ReInviteUserRequest, ResetPasswordRequest, SendVerifyEmailRequest, SignInResponse, - SignUpRequest, SignUpWithMerchantIdRequest, SwitchMerchantIdRequest, - UpdateUserAccountDetailsRequest, UserMerchantCreate, VerifyEmailRequest, + GetUserDetailsResponse, GetUserRoleDetailsRequest, GetUserRoleDetailsResponse, + InviteUserRequest, ListUsersResponse, ReInviteUserRequest, ResetPasswordRequest, + SendVerifyEmailRequest, SignInResponse, SignUpRequest, SignUpWithMerchantIdRequest, + SwitchMerchantIdRequest, UpdateUserAccountDetailsRequest, UserMerchantCreate, + VerifyEmailRequest, }; impl ApiEventMetric for DashboardEntryResponse { @@ -60,8 +61,9 @@ common_utils::impl_misc_api_event_type!( AcceptInviteFromEmailRequest, SignInResponse, UpdateUserAccountDetailsRequest, - GetUserDetailsRequest, - GetUserDetailsResponse + GetUserDetailsResponse, + GetUserRoleDetailsRequest, + GetUserRoleDetailsResponse ); #[cfg(feature = "dummy_connector")] diff --git a/crates/api_models/src/user.rs b/crates/api_models/src/user.rs index 9b3d7a2e65..700c27461c 100644 --- a/crates/api_models/src/user.rs +++ b/crates/api_models/src/user.rs @@ -149,13 +149,25 @@ pub struct UserDetails { pub last_modified_at: time::PrimitiveDateTime, } +#[derive(serde::Serialize, Debug, Clone)] +pub struct GetUserDetailsResponse { + pub merchant_id: String, + pub name: Secret, + pub email: pii::Email, + pub verification_days_left: Option, + pub role_id: String, + // This field is added for audit/debug reasons + #[serde(skip_serializing)] + pub user_id: String, + pub org_id: String, +} #[derive(Debug, serde::Deserialize, serde::Serialize)] -pub struct GetUserDetailsRequest { +pub struct GetUserRoleDetailsRequest { pub email: pii::Email, } #[derive(Debug, serde::Serialize)] -pub struct GetUserDetailsResponse { +pub struct GetUserRoleDetailsResponse { pub email: pii::Email, pub name: Secret, pub role_id: String, diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index 71d18774cb..2e439a6eb5 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -71,6 +71,26 @@ pub async fn signup_with_merchant_id( })) } +pub async fn get_user_details( + state: AppState, + user_from_token: auth::UserFromToken, +) -> UserResponse { + let user = user_from_token.get_user_from_db(&state).await?; + let verification_days_left = utils::user::get_verification_days_left(&state, &user)?; + + Ok(ApplicationResponse::Json( + user_api::GetUserDetailsResponse { + merchant_id: user_from_token.merchant_id, + name: user.get_name(), + email: user.get_email(), + user_id: user.get_user_id().to_string(), + verification_days_left, + role_id: user_from_token.role_id, + org_id: user_from_token.org_id, + }, + )) +} + pub async fn signup( state: AppState, request: user_api::SignUpRequest, @@ -1001,9 +1021,9 @@ pub async fn list_merchants_for_user( pub async fn get_user_details_in_merchant_account( state: AppState, user_from_token: auth::UserFromToken, - request: user_api::GetUserDetailsRequest, + request: user_api::GetUserRoleDetailsRequest, _req_state: ReqState, -) -> UserResponse { +) -> UserResponse { let required_user = utils::user::get_user_from_db_by_email(&state, request.email.try_into()?) .await .to_not_found_response(UserErrors::InvalidRoleOperation)?; @@ -1029,7 +1049,7 @@ pub async fn get_user_details_in_merchant_account( .attach_printable("User role exists but the corresponding role doesn't")?; Ok(ApplicationResponse::Json( - user_api::GetUserDetailsResponse { + user_api::GetUserRoleDetailsResponse { email: required_user.get_email(), name: required_user.get_name(), role_id: role_info.get_role_id().to_string(), diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index d42d3fe003..5b59ebb692 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1163,6 +1163,7 @@ impl User { let mut route = web::scope("/user").app_data(web::Data::new(state)); route = route + .service(web::resource("").route(web::get().to(get_user_details))) .service(web::resource("/v2/signin").route(web::post().to(user_signin))) .service(web::resource("/signout").route(web::post().to(signout))) .service(web::resource("/change_password").route(web::post().to(change_password))) diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index f8a0a6a5ff..faef85f390 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -198,6 +198,7 @@ impl From for ApiIdentifier { | Flow::DeleteSampleData | Flow::UserMerchantAccountList | Flow::GetUserDetails + | Flow::GetUserRoleDetails | Flow::ListUsersForMerchantAccount | Flow::ForgotPassword | Flow::ResetPassword diff --git a/crates/router/src/routes/user.rs b/crates/router/src/routes/user.rs index bf3ddbc449..0657d781b0 100644 --- a/crates/router/src/routes/user.rs +++ b/crates/router/src/routes/user.rs @@ -19,6 +19,20 @@ use crate::{ utils::user::dashboard_metadata::{parse_string_to_enums, set_ip_address_if_required}, }; +pub async fn get_user_details(state: web::Data, req: HttpRequest) -> HttpResponse { + let flow = Flow::GetUserDetails; + Box::pin(api::server_wrap( + flow, + state, + &req, + (), + |state, user, _, _| user_core::get_user_details(state, user), + &auth::DashboardNoPermissionAuth, + api_locking::LockAction::NotApplicable, + )) + .await +} + #[cfg(feature = "email")] pub async fn user_signup_with_merchant_id( state: web::Data, @@ -295,7 +309,7 @@ pub async fn list_merchants_for_user(state: web::Data, req: HttpReques pub async fn get_user_role_details( state: web::Data, req: HttpRequest, - payload: web::Query, + payload: web::Query, ) -> HttpResponse { let flow = Flow::GetUserDetails; Box::pin(api::server_wrap( diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs index a7aac03db5..26cb619d74 100644 --- a/crates/router_env/src/logger/types.rs +++ b/crates/router_env/src/logger/types.rs @@ -348,8 +348,10 @@ pub enum Flow { DeleteSampleData, /// List merchant accounts for user UserMerchantAccountList, - /// Get details of a user in a merchant account + /// Get details of a user GetUserDetails, + /// Get details of a user role in a merchant account + GetUserRoleDetails, /// List users for merchant account ListUsersForMerchantAccount, /// PaymentMethodAuth Link token create