Bug: Blacking token after delete user role



Even after deleting the user role, the logged in user is able to perform the JWT operations. Hence these need to be prohibited by adding the token in blacklist.
diff --git a/crates/diesel_models/src/query/user_role.rs b/crates/diesel_models/src/query/user_role.rs
index 4cce0d3f800..09a0bbfe300 100644
--- a/crates/diesel_models/src/query/user_role.rs
+++ b/crates/diesel_models/src/query/user_role.rs
@@ -70,8 +70,8 @@ impl UserRole {
         conn: &PgPooledConn,
         user_id: String,
         merchant_id: String,
-    ) -> StorageResult<bool> {
-        generics::generic_delete::<<Self as HasTable>::Table, _>(
+    ) -> StorageResult<Self> {
+        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
             conn,
             dsl::user_id
                 .eq(user_id)
diff --git a/crates/router/src/core/user_role.rs b/crates/router/src/core/user_role.rs
index 6ddab570aed..43d6b1c6483 100644
--- a/crates/router/src/core/user_role.rs
+++ b/crates/router/src/core/user_role.rs
@@ -282,7 +282,7 @@ pub async fn delete_user_role(
         }
     };
 
-    if user_roles.len() > 1 {
+    let deleted_user_role = if user_roles.len() > 1 {
         state
             .store
             .delete_user_role_by_user_id_merchant_id(
@@ -291,9 +291,7 @@ pub async fn delete_user_role(
             )
             .await
             .change_context(UserErrors::InternalServerError)
-            .attach_printable("Error while deleting user role")?;
-
-        Ok(ApplicationResponse::StatusOk)
+            .attach_printable("Error while deleting user role")?
     } else {
         state
             .store
@@ -310,8 +308,9 @@ pub async fn delete_user_role(
             )
             .await
             .change_context(UserErrors::InternalServerError)
-            .attach_printable("Error while deleting user role")?;
+            .attach_printable("Error while deleting user role")?
+    };
 
-        Ok(ApplicationResponse::StatusOk)
-    }
+    auth::blacklist::insert_user_in_blacklist(&state, &deleted_user_role.user_id).await?;
+    Ok(ApplicationResponse::StatusOk)
 }
diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs
index 73b519e5449..b094d1447e0 100644
--- a/crates/router/src/db/kafka_store.rs
+++ b/crates/router/src/db/kafka_store.rs
@@ -2376,7 +2376,7 @@ impl UserRoleInterface for KafkaStore {
         &self,
         user_id: &str,
         merchant_id: &str,
-    ) -> CustomResult<bool, errors::StorageError> {
+    ) -> CustomResult<user_storage::UserRole, errors::StorageError> {
         self.diesel_store
             .delete_user_role_by_user_id_merchant_id(user_id, merchant_id)
             .await
diff --git a/crates/router/src/db/user_role.rs b/crates/router/src/db/user_role.rs
index 2f61f70b2a8..e31a2663354 100644
--- a/crates/router/src/db/user_role.rs
+++ b/crates/router/src/db/user_role.rs
@@ -48,7 +48,7 @@ pub trait UserRoleInterface {
         &self,
         user_id: &str,
         merchant_id: &str,
-    ) -> CustomResult<bool, errors::StorageError>;
+    ) -> CustomResult<storage::UserRole, errors::StorageError>;
 
     async fn list_user_roles_by_user_id(
         &self,
@@ -145,8 +145,9 @@ impl UserRoleInterface for Store {
         &self,
         user_id: &str,
         merchant_id: &str,
-    ) -> CustomResult<bool, errors::StorageError> {
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
         let conn = connection::pg_connection_write(self).await?;
+
         storage::UserRole::delete_by_user_id_merchant_id(
             &conn,
             user_id.to_owned(),
@@ -459,18 +460,19 @@ impl UserRoleInterface for MockDb {
         &self,
         user_id: &str,
         merchant_id: &str,
-    ) -> CustomResult<bool, errors::StorageError> {
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
         let mut user_roles = self.user_roles.lock().await;
-        let user_role_index = user_roles
+
+        match user_roles
             .iter()
-            .position(|user_role| {
-                user_role.user_id == user_id && user_role.merchant_id == merchant_id
-            })
-            .ok_or(errors::StorageError::ValueNotFound(format!(
-                "No user available for user_id = {user_id}"
-            )))?;
-        user_roles.remove(user_role_index);
-        Ok(true)
+            .position(|role| role.user_id == user_id && role.merchant_id == merchant_id)
+        {
+            Some(index) => Ok(user_roles.remove(index)),
+            None => Err(errors::StorageError::ValueNotFound(
+                "Cannot find user role to delete".to_string(),
+            )
+            .into()),
+        }
     }
 
     async fn list_user_roles_by_user_id(
@@ -521,7 +523,7 @@ impl UserRoleInterface for super::KafkaStore {
         &self,
         user_id: &str,
         merchant_id: &str,
-    ) -> CustomResult<bool, errors::StorageError> {
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
         self.diesel_store
             .delete_user_role_by_user_id_merchant_id(user_id, merchant_id)
             .await

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

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

## Description
The PR add support to blocklist JWT token of the deleted user/user role. After delete signined user won't be able to perform any operation as token is blocklisted.

### Additional Changes

- [ ] 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 #4427 


## How did you test it?
SignIn/Signup
```
curl --location 'http://localhost:8080/user/signup' \
--header 'Content-Type: application/json' \
--header 'api-key: test_admin' \
--data-raw '{
    "email": "test1@gmail.com",
    "password": "t"
}'
```

Invite another user
```
curl --location 'http://localhost:8080/user/user/invite' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer JWT' \
--data-raw '{
    "email": "test3@gmail.com",
    "name": "test3",
    "role_id": "merchant_view_only"
}'
```

Sign in to this new user account and perform some operations JWT based, like listing payments etc.

Sing in  again into account from which this user was invited.

Delete this new user
```
curl --location --request DELETE 'http://localhost:8080/user/user/delete' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer JWT' \
--data-raw '{
  "email": "test3@gmail.com"
}'
```
Response 200 Ok

Try performing same operations for the newly invited user now, it should give response:
```
{
    "error": {
        "type": "invalid_request",
        "message": "Access forbidden, invalid JWT token was used",
        "code": "IR_17"
    }
}
```
This means the previous token is blacklisted sucessfully.
## 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
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
