Bug: refactor: Home and Sign out API changes for 2FA Phase - II



As we are having the reset TOTP and regenerate recovery codes flows in the Phase - II, we need to let FE know whether the user has completed the 2FA or not and also number of recovery codes left for the user, so that FE can show a warning if there are less.

And also redis needs to be cleaned up if user signs out.
diff --git a/crates/api_models/src/user.rs b/crates/api_models/src/user.rs
index ee9498cfeee..a61b9fd7dff 100644
--- a/crates/api_models/src/user.rs
+++ b/crates/api_models/src/user.rs
@@ -165,7 +165,10 @@ pub struct GetUserDetailsResponse {
     #[serde(skip_serializing)]
     pub user_id: String,
     pub org_id: String,
+    pub is_two_factor_auth_setup: bool,
+    pub recovery_codes_left: Option<usize>,
 }
+
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct GetUserRoleDetailsRequest {
     pub email: pii::Email,
diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs
index c259e87c93d..f7ef79bb7d6 100644
--- a/crates/router/src/core/user.rs
+++ b/crates/router/src/core/user.rs
@@ -94,6 +94,8 @@ pub async fn get_user_details(
             verification_days_left,
             role_id: user_from_token.role_id,
             org_id: user_from_token.org_id,
+            is_two_factor_auth_setup: user.get_totp_status() == TotpStatus::Set,
+            recovery_codes_left: user.get_recovery_codes().map(|codes| codes.len()),
         },
     ))
 }
@@ -328,6 +330,10 @@ pub async fn signout(
     state: SessionState,
     user_from_token: auth::UserFromToken,
 ) -> UserResponse<()> {
+    tfa_utils::delete_totp_from_redis(&state, &user_from_token.user_id).await?;
+    tfa_utils::delete_recovery_code_from_redis(&state, &user_from_token.user_id).await?;
+    tfa_utils::delete_totp_secret_from_redis(&state, &user_from_token.user_id).await?;
+
     auth::blacklist::insert_user_in_blacklist(&state, &user_from_token.user_id).await?;
     auth::cookies::remove_cookie_response()
 }
diff --git a/crates/router/src/utils/user/two_factor_auth.rs b/crates/router/src/utils/user/two_factor_auth.rs
index a0915f3ed86..aa0077e00ae 100644
--- a/crates/router/src/utils/user/two_factor_auth.rs
+++ b/crates/router/src/utils/user/two_factor_auth.rs
@@ -115,3 +115,26 @@ pub async fn insert_recovery_code_in_redis(state: &SessionState, user_id: &str)
         .await
         .change_context(UserErrors::InternalServerError)
 }
+
+pub async fn delete_totp_from_redis(state: &SessionState, user_id: &str) -> UserResult<()> {
+    let redis_conn = super::get_redis_connection(state)?;
+    let key = format!("{}{}", consts::user::REDIS_TOTP_PREFIX, user_id);
+    redis_conn
+        .delete_key(&key)
+        .await
+        .change_context(UserErrors::InternalServerError)
+        .map(|_| ())
+}
+
+pub async fn delete_recovery_code_from_redis(
+    state: &SessionState,
+    user_id: &str,
+) -> UserResult<()> {
+    let redis_conn = super::get_redis_connection(state)?;
+    let key = format!("{}{}", consts::user::REDIS_RECOVERY_CODE_PREFIX, user_id);
+    redis_conn
+        .delete_key(&key)
+        .await
+        .change_context(UserErrors::InternalServerError)
+        .map(|_| ())
+}

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

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

## Description
<!-- Describe your changes in detail -->
After this PR, Home API will send the details about the user's 2FA, specifically weather user has completed 2FA setup and number of recovery codes left for him.

### 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
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
Closes #4848 

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
1. Home API
	```
	curl --location 'http://localhost:8080/user' \
	--header 'Authorization: Bearer Login Token'
	```
	
	```json
	{
	    "merchant_id": "company_name",
	    "name": "name",
	    "email": "email",
	    "verification_days_left": null,
	    "role_id": "org_admin",
	    "org_id": "org_lbZlm2cx4j2LgVo7bUwq",
	    "is_two_factor_auth_setup": true,
	    "recovery_codes_left": 8
	}
	```

2. Signout
	1. Hit Signout API
		```
		curl --location --request POST 'http://localhost:8080/user/signout' \
		--header 'Content-Type: application/json' \
		--header 'Authorization: Bearer Login Token'
		```
		200 OK
	
	2. Signin with the same user again
		```
		curl --location 'http://localhost:8080/user/v2/signin' \
		--header 'Content-Type: application/json' \
		--data-raw '{
		    "email": "email",
		    "password": "password"
		}'
		```
		```
		{
		    "flow_type": "dashboard_entry",
		    "token": "Login Token",
		    "merchant_id": "company_name",
		    "name": "name",
		    "email": "email",
		    "verification_days_left": null,
		    "user_role": "org_admin"
		}
		```
	3. Take the token from the above response and hit 2FA status API
		```
		curl --location 'http://localhost:8080/user/2fa' \
		--header 'Authorization: Bearer Login Token'
		```
		```
		{
		    "totp": false,
		    "recovery_code": false
		}
		```

## 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
