mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-03 05:17:02 +08:00
feat(users): add support for profile user delete (#5541)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -3085,6 +3085,8 @@ pub enum ApiVersion {
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
@ -3095,10 +3097,10 @@ pub enum ApiVersion {
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum EntityType {
|
||||
Internal,
|
||||
Organization,
|
||||
Merchant,
|
||||
Profile,
|
||||
Internal = 3,
|
||||
Organization = 2,
|
||||
Merchant = 1,
|
||||
Profile = 0,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
|
||||
@ -82,22 +82,6 @@ impl UserRole {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_by_user_id_merchant_id(
|
||||
conn: &PgPooledConn,
|
||||
user_id: String,
|
||||
merchant_id: id_type::MerchantId,
|
||||
version: UserRoleVersion,
|
||||
) -> StorageResult<Self> {
|
||||
generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
|
||||
conn,
|
||||
dsl::user_id
|
||||
.eq(user_id)
|
||||
.and(dsl::merchant_id.eq(merchant_id))
|
||||
.and(dsl::version.eq(version)),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_by_user_id(
|
||||
conn: &PgPooledConn,
|
||||
user_id: String,
|
||||
@ -129,4 +113,71 @@ impl UserRole {
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_by_user_id_org_id_merchant_id_profile_id(
|
||||
conn: &PgPooledConn,
|
||||
user_id: String,
|
||||
org_id: id_type::OrganizationId,
|
||||
merchant_id: id_type::MerchantId,
|
||||
profile_id: Option<String>,
|
||||
version: UserRoleVersion,
|
||||
) -> StorageResult<Self> {
|
||||
// Checking in user roles, for a user in token hierarchy, only one of the relation will be true, either org level, merchant level or profile level
|
||||
// (org_id = ? && merchant_id = null && profile_id = null) || (org_id = ? && merchant_id = ? && profile_id = null) || (org_id = ? && merchant_id = ? && profile_id = ?)
|
||||
let check_lineage = dsl::org_id
|
||||
.eq(org_id.clone())
|
||||
.and(dsl::merchant_id.is_null().and(dsl::profile_id.is_null()))
|
||||
.or(dsl::org_id.eq(org_id.clone()).and(
|
||||
dsl::merchant_id
|
||||
.eq(merchant_id.clone())
|
||||
.and(dsl::profile_id.is_null()),
|
||||
))
|
||||
.or(dsl::org_id.eq(org_id).and(
|
||||
dsl::merchant_id
|
||||
.eq(merchant_id)
|
||||
//TODO: In case of None, profile_id = NULL its unexpected behaviour, after V1 profile id will not be option
|
||||
.and(dsl::profile_id.eq(profile_id)),
|
||||
));
|
||||
|
||||
let predicate = dsl::user_id
|
||||
.eq(user_id)
|
||||
.and(check_lineage)
|
||||
.and(dsl::version.eq(version));
|
||||
|
||||
generics::generic_find_one::<<Self as HasTable>::Table, _, _>(conn, predicate).await
|
||||
}
|
||||
|
||||
pub async fn delete_by_user_id_org_id_merchant_id_profile_id(
|
||||
conn: &PgPooledConn,
|
||||
user_id: String,
|
||||
org_id: id_type::OrganizationId,
|
||||
merchant_id: id_type::MerchantId,
|
||||
profile_id: Option<String>,
|
||||
version: UserRoleVersion,
|
||||
) -> StorageResult<Self> {
|
||||
// Checking in user roles, for a user in token hierarchy, only one of the relation will be true, either org level, merchant level or profile level
|
||||
// (org_id = ? && merchant_id = null && profile_id = null) || (org_id = ? && merchant_id = ? && profile_id = null) || (org_id = ? && merchant_id = ? && profile_id = ?)
|
||||
let check_lineage = dsl::org_id
|
||||
.eq(org_id.clone())
|
||||
.and(dsl::merchant_id.is_null().and(dsl::profile_id.is_null()))
|
||||
.or(dsl::org_id.eq(org_id.clone()).and(
|
||||
dsl::merchant_id
|
||||
.eq(merchant_id.clone())
|
||||
.and(dsl::profile_id.is_null()),
|
||||
))
|
||||
.or(dsl::org_id.eq(org_id).and(
|
||||
dsl::merchant_id
|
||||
.eq(merchant_id)
|
||||
//TODO: In case of None, profile_id = NULL its unexpected behaviour, after V1 profile id will not be option
|
||||
.and(dsl::profile_id.eq(profile_id)),
|
||||
));
|
||||
|
||||
let predicate = dsl::user_id
|
||||
.eq(user_id)
|
||||
.and(check_lineage)
|
||||
.and(dsl::version.eq(version));
|
||||
|
||||
generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(conn, predicate)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,68 +342,169 @@ pub async fn delete_user_role(
|
||||
.attach_printable("User deleting himself");
|
||||
}
|
||||
|
||||
let user_roles = state
|
||||
let deletion_requestor_role_info = roles::RoleInfo::from_role_id(
|
||||
&state,
|
||||
&user_from_token.role_id,
|
||||
&user_from_token.merchant_id,
|
||||
&user_from_token.org_id,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
let mut user_role_deleted_flag = false;
|
||||
|
||||
// Find in V2
|
||||
let user_role_v2 = match state
|
||||
.store
|
||||
.find_user_role_by_user_id_and_lineage(
|
||||
user_from_db.get_user_id(),
|
||||
&user_from_token.org_id,
|
||||
&user_from_token.merchant_id,
|
||||
user_from_token.profile_id.as_ref(),
|
||||
UserRoleVersion::V2,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(user_role) => Some(user_role),
|
||||
Err(e) => {
|
||||
if e.current_context().is_db_not_found() {
|
||||
None
|
||||
} else {
|
||||
return Err(UserErrors::InternalServerError.into());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(role_to_be_deleted) = user_role_v2 {
|
||||
let target_role_info = roles::RoleInfo::from_role_id(
|
||||
&state,
|
||||
&role_to_be_deleted.role_id,
|
||||
&user_from_token.merchant_id,
|
||||
&user_from_token.org_id,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
if !target_role_info.is_deletable() {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation)).attach_printable(format!(
|
||||
"Invalid operation, role_id = {} is not deletable",
|
||||
role_to_be_deleted.role_id
|
||||
));
|
||||
}
|
||||
|
||||
if deletion_requestor_role_info.get_entity_type() < target_role_info.get_entity_type() {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation)).attach_printable(format!(
|
||||
"Invalid operation, deletion requestor = {} cannot delete target = {}",
|
||||
deletion_requestor_role_info.get_entity_type(),
|
||||
target_role_info.get_entity_type()
|
||||
));
|
||||
}
|
||||
|
||||
user_role_deleted_flag = true;
|
||||
state
|
||||
.store
|
||||
.delete_user_role_by_user_id_and_lineage(
|
||||
user_from_db.get_user_id(),
|
||||
&user_from_token.org_id,
|
||||
&user_from_token.merchant_id,
|
||||
user_from_token.profile_id.as_ref(),
|
||||
UserRoleVersion::V2,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)
|
||||
.attach_printable("Error while deleting user role")?;
|
||||
}
|
||||
|
||||
// Find in V1
|
||||
let user_role_v1 = match state
|
||||
.store
|
||||
.find_user_role_by_user_id_and_lineage(
|
||||
user_from_db.get_user_id(),
|
||||
&user_from_token.org_id,
|
||||
&user_from_token.merchant_id,
|
||||
user_from_token.profile_id.as_ref(),
|
||||
UserRoleVersion::V1,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(user_role) => Some(user_role),
|
||||
Err(e) => {
|
||||
if e.current_context().is_db_not_found() {
|
||||
None
|
||||
} else {
|
||||
return Err(UserErrors::InternalServerError.into());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(role_to_be_deleted) = user_role_v1 {
|
||||
let target_role_info = roles::RoleInfo::from_role_id(
|
||||
&state,
|
||||
&role_to_be_deleted.role_id,
|
||||
&user_from_token.merchant_id,
|
||||
&user_from_token.org_id,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
if !target_role_info.is_deletable() {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation)).attach_printable(format!(
|
||||
"Invalid operation, role_id = {} is not deletable",
|
||||
role_to_be_deleted.role_id
|
||||
));
|
||||
}
|
||||
|
||||
if deletion_requestor_role_info.get_entity_type() < target_role_info.get_entity_type() {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation)).attach_printable(format!(
|
||||
"Invalid operation, deletion requestor = {} cannot delete target = {}",
|
||||
deletion_requestor_role_info.get_entity_type(),
|
||||
target_role_info.get_entity_type()
|
||||
));
|
||||
}
|
||||
|
||||
user_role_deleted_flag = true;
|
||||
state
|
||||
.store
|
||||
.delete_user_role_by_user_id_and_lineage(
|
||||
user_from_db.get_user_id(),
|
||||
&user_from_token.org_id,
|
||||
&user_from_token.merchant_id,
|
||||
user_from_token.profile_id.as_ref(),
|
||||
UserRoleVersion::V1,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)
|
||||
.attach_printable("Error while deleting user role")?;
|
||||
}
|
||||
|
||||
if !user_role_deleted_flag {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation))
|
||||
.attach_printable("User is not associated with the merchant");
|
||||
}
|
||||
|
||||
// Check if user has any more role associations
|
||||
let user_roles_v2 = state
|
||||
.store
|
||||
.list_user_roles_by_user_id(user_from_db.get_user_id(), UserRoleVersion::V2)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
let user_roles_v1 = state
|
||||
.store
|
||||
.list_user_roles_by_user_id(user_from_db.get_user_id(), UserRoleVersion::V1)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
for user_role in user_roles.iter() {
|
||||
let Some(merchant_id) = user_role.merchant_id.as_ref() else {
|
||||
return Err(report!(UserErrors::InternalServerError))
|
||||
.attach_printable("merchant_id not found for user_role");
|
||||
};
|
||||
|
||||
if merchant_id == &user_from_token.merchant_id {
|
||||
let role_info = roles::RoleInfo::from_role_id(
|
||||
&state,
|
||||
&user_role.role_id,
|
||||
&user_from_token.merchant_id,
|
||||
&user_from_token.org_id,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
if !role_info.is_deletable() {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation))
|
||||
.attach_printable(format!("role_id = {} is not deletable", user_role.role_id));
|
||||
}
|
||||
} else {
|
||||
return Err(report!(UserErrors::InvalidDeleteOperation))
|
||||
.attach_printable("User is not associated with the merchant");
|
||||
}
|
||||
}
|
||||
|
||||
let deleted_user_role = if user_roles.len() > 1 {
|
||||
state
|
||||
.store
|
||||
.delete_user_role_by_user_id_merchant_id(
|
||||
user_from_db.get_user_id(),
|
||||
&user_from_token.merchant_id,
|
||||
UserRoleVersion::V1,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)
|
||||
.attach_printable("Error while deleting user role")?
|
||||
} else {
|
||||
// If user has no more role associated with him then deleting user
|
||||
if user_roles_v2.is_empty() && user_roles_v1.is_empty() {
|
||||
state
|
||||
.global_store
|
||||
.delete_user_by_user_id(user_from_db.get_user_id())
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)
|
||||
.attach_printable("Error while deleting user entry")?;
|
||||
}
|
||||
|
||||
state
|
||||
.store
|
||||
.delete_user_role_by_user_id_merchant_id(
|
||||
user_from_db.get_user_id(),
|
||||
&user_from_token.merchant_id,
|
||||
UserRoleVersion::V1,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)
|
||||
.attach_printable("Error while deleting user role")?
|
||||
};
|
||||
|
||||
auth::blacklist::insert_user_in_blacklist(&state, &deleted_user_role.user_id).await?;
|
||||
auth::blacklist::insert_user_in_blacklist(&state, user_from_db.get_user_id()).await?;
|
||||
Ok(ApplicationResponse::StatusOk)
|
||||
}
|
||||
|
||||
@ -2761,17 +2761,6 @@ impl UserRoleInterface for KafkaStore {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_user_role_by_user_id_merchant_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<user_storage::UserRole, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.delete_user_role_by_user_id_merchant_id(user_id, merchant_id, version)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_user_roles_by_user_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
@ -2782,6 +2771,44 @@ impl UserRoleInterface for KafkaStore {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn find_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.find_user_role_by_user_id_and_lineage(
|
||||
user_id,
|
||||
org_id,
|
||||
merchant_id,
|
||||
profile_id,
|
||||
version,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.delete_user_role_by_user_id_and_lineage(
|
||||
user_id,
|
||||
org_id,
|
||||
merchant_id,
|
||||
profile_id,
|
||||
version,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn transfer_org_ownership_between_users(
|
||||
&self,
|
||||
from_user_id: &str,
|
||||
|
||||
@ -49,13 +49,6 @@ pub trait UserRoleInterface {
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<Vec<storage::UserRole>, errors::StorageError>;
|
||||
|
||||
async fn delete_user_role_by_user_id_merchant_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError>;
|
||||
|
||||
async fn list_user_roles_by_user_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
@ -68,6 +61,24 @@ pub trait UserRoleInterface {
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<Vec<storage::UserRole>, errors::StorageError>;
|
||||
|
||||
async fn find_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError>;
|
||||
|
||||
async fn delete_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError>;
|
||||
|
||||
async fn transfer_org_ownership_between_users(
|
||||
&self,
|
||||
from_user_id: &str,
|
||||
@ -161,25 +172,6 @@ impl UserRoleInterface for Store {
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn delete_user_role_by_user_id_merchant_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> 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(),
|
||||
merchant_id.to_owned(),
|
||||
version,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn list_user_roles_by_user_id(
|
||||
&self,
|
||||
@ -204,6 +196,50 @@ impl UserRoleInterface for Store {
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn find_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
storage::UserRole::find_by_user_id_org_id_merchant_id_profile_id(
|
||||
&conn,
|
||||
user_id.to_owned(),
|
||||
org_id.to_owned(),
|
||||
merchant_id.to_owned(),
|
||||
profile_id.cloned(),
|
||||
version,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn delete_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
storage::UserRole::delete_by_user_id_org_id_merchant_id_profile_id(
|
||||
&conn,
|
||||
user_id.to_owned(),
|
||||
org_id.to_owned(),
|
||||
merchant_id.to_owned(),
|
||||
profile_id.cloned(),
|
||||
version,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn transfer_org_ownership_between_users(
|
||||
&self,
|
||||
@ -565,32 +601,6 @@ impl UserRoleInterface for MockDb {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_user_role_by_user_id_merchant_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
let mut user_roles = self.user_roles.lock().await;
|
||||
|
||||
let index = user_roles.iter().position(|role| {
|
||||
role.user_id == user_id
|
||||
&& role.version == version
|
||||
&& match role.merchant_id {
|
||||
Some(ref mid) => mid == merchant_id,
|
||||
None => false,
|
||||
}
|
||||
});
|
||||
|
||||
match index {
|
||||
Some(idx) => Ok(user_roles.remove(idx)),
|
||||
None => Err(errors::StorageError::ValueNotFound(
|
||||
"Cannot find user role to delete".to_string(),
|
||||
)
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_user_roles_by_user_id(
|
||||
&self,
|
||||
user_id: &str,
|
||||
@ -634,4 +644,83 @@ impl UserRoleInterface for MockDb {
|
||||
|
||||
Ok(filtered_roles)
|
||||
}
|
||||
|
||||
async fn find_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
let user_roles = self.user_roles.lock().await;
|
||||
|
||||
for user_role in user_roles.iter() {
|
||||
let org_level_check = user_role.org_id.as_ref() == Some(org_id)
|
||||
&& user_role.merchant_id.is_none()
|
||||
&& user_role.profile_id.is_none();
|
||||
|
||||
let merchant_level_check = user_role.org_id.as_ref() == Some(org_id)
|
||||
&& user_role.merchant_id.as_ref() == Some(merchant_id)
|
||||
&& user_role.profile_id.is_none();
|
||||
|
||||
let profile_level_check = user_role.org_id.as_ref() == Some(org_id)
|
||||
&& user_role.merchant_id.as_ref() == Some(merchant_id)
|
||||
&& user_role.profile_id.as_ref() == profile_id;
|
||||
|
||||
// Check if any condition matches and the version matches
|
||||
if user_role.user_id == user_id
|
||||
&& (org_level_check || merchant_level_check || profile_level_check)
|
||||
&& user_role.version == version
|
||||
{
|
||||
return Ok(user_role.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Err(errors::StorageError::ValueNotFound(format!(
|
||||
"No user role available for user_id = {} in the current token hierarchy",
|
||||
user_id
|
||||
))
|
||||
.into())
|
||||
}
|
||||
|
||||
async fn delete_user_role_by_user_id_and_lineage(
|
||||
&self,
|
||||
user_id: &str,
|
||||
org_id: &id_type::OrganizationId,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
profile_id: Option<&String>,
|
||||
version: enums::UserRoleVersion,
|
||||
) -> CustomResult<storage::UserRole, errors::StorageError> {
|
||||
let mut user_roles = self.user_roles.lock().await;
|
||||
|
||||
// Find the position of the user role to delete
|
||||
let index = user_roles.iter().position(|role| {
|
||||
let org_level_check = role.org_id.as_ref() == Some(org_id)
|
||||
&& role.merchant_id.is_none()
|
||||
&& role.profile_id.is_none();
|
||||
|
||||
let merchant_level_check = role.org_id.as_ref() == Some(org_id)
|
||||
&& role.merchant_id.as_ref() == Some(merchant_id)
|
||||
&& role.profile_id.is_none();
|
||||
|
||||
let profile_level_check = role.org_id.as_ref() == Some(org_id)
|
||||
&& role.merchant_id.as_ref() == Some(merchant_id)
|
||||
&& role.profile_id.as_ref() == profile_id;
|
||||
|
||||
// Check if the user role matches the conditions and the version matches
|
||||
role.user_id == user_id
|
||||
&& (org_level_check || merchant_level_check || profile_level_check)
|
||||
&& role.version == version
|
||||
});
|
||||
|
||||
// Remove and return the user role if found
|
||||
match index {
|
||||
Some(idx) => Ok(user_roles.remove(idx)),
|
||||
None => Err(errors::StorageError::ValueNotFound(
|
||||
"Cannot find user role to delete".to_string(),
|
||||
)
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user