Bug: feat(user): get user information (home api)



Create new api to get user details. 
diff --git a/crates/api_models/src/events/user.rs b/crates/api_models/src/events/user.rs
index 9884dbc4f41..8f017ca8c20 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 9b3d7a2e654..700c27461cd 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<String>,
+    pub email: pii::Email,
+    pub verification_days_left: Option<i64>,
+    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<String>,
     pub role_id: String,
diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs
index 71d18774cb8..2e439a6eb52 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<user_api::GetUserDetailsResponse> {
+    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<user_api::GetUserDetailsResponse> {
+) -> UserResponse<user_api::GetUserRoleDetailsResponse> {
     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 595fd26f92c..4311b9b96e2 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -1160,6 +1160,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 de87f7fce53..c5a3157d817 100644
--- a/crates/router/src/routes/lock_utils.rs
+++ b/crates/router/src/routes/lock_utils.rs
@@ -197,6 +197,7 @@ impl From<Flow> 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 bf3ddbc4491..0657d781b08 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<AppState>, 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<AppState>,
@@ -295,7 +309,7 @@ pub async fn list_merchants_for_user(state: web::Data<AppState>, req: HttpReques
 pub async fn get_user_role_details(
     state: web::Data<AppState>,
     req: HttpRequest,
-    payload: web::Query<user_api::GetUserDetailsRequest>,
+    payload: web::Query<user_api::GetUserRoleDetailsRequest>,
 ) -> 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 9dfdb6a57a8..da5afbdc75c 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

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
Add support to get user details!


### Additional Changes

- [x] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
closes #4509 

## How did you test it?
Use the curl to get user info:
```
curl --location 'http://localhost:8080/user' \
--header 'Authorization: Bearer JWT' \
--data ''
```

Response will be, something like:
```
{
    "merchant_id": "merchant_1714396883",
    "name": "test1",
    "email": "apoorvdixit88+555@gmail.com",
    "verification_days_left": null,
    "role_id": "merchant_view_only",
    "org_id": "org_HomVKdwu2HGTi6jUvvnz"
}
```
## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
