diff --git a/src/modules/users/mod.rs b/src/modules/users/mod.rs index 70efac7..0b625e2 100644 --- a/src/modules/users/mod.rs +++ b/src/modules/users/mod.rs @@ -20,8 +20,8 @@ use crate::{ decrypt, encrypt, generate_token, id, modules::{ database::{ - async_find_impl, batch_delete_impl, delete_impl, list_all_impl, manager::DB_MANAGER, - async_secondary_find_impl, update_impl, with_transaction, + async_find_impl, async_secondary_find_impl, batch_delete_impl, delete_impl, + list_all_impl, manager::DB_MANAGER, update_impl, with_transaction, }, error::{code::ErrorCode, BichonResult}, token::{AccessTokenModel, AccessTokenModelKey, TokenType}, @@ -132,6 +132,17 @@ pub struct BichonUserV2 { } impl BichonUserV2 { + pub fn is_using_role(&self, role_id: u64) -> bool { + if self.global_roles.contains(&role_id) { + return true; + } + + if self.account_access_map.values().any(|&id| id == role_id) { + return true; + } + false + } + pub async fn list_all() -> BichonResult> { Ok(list_all_impl::(DB_MANAGER.meta_db()).await?) } diff --git a/src/modules/users/payload.rs b/src/modules/users/payload.rs index 6e73ba9..d73ea8d 100644 --- a/src/modules/users/payload.rs +++ b/src/modules/users/payload.rs @@ -340,7 +340,7 @@ pub struct UserUpdateRequest { pub avatar_base64: Option, pub global_roles: Option>, /// Scoped Access - pub account_access_map: Option>, + pub account_access_map: Option>, pub acl: Option, pub description: Option, pub theme: Option, diff --git a/src/modules/users/role.rs b/src/modules/users/role.rs index 0124618..b5944df 100644 --- a/src/modules/users/role.rs +++ b/src/modules/users/role.rs @@ -37,6 +37,7 @@ use crate::{ users::{ payload::{RoleCreateRequest, RoleUpdateRequest}, permissions::*, + UserModel, }, }, raise_error, utc_now, @@ -336,7 +337,7 @@ impl UserRole { .await?; Ok(()) } - + pub async fn delete(id: u64) -> BichonResult<()> { if is_builtin(id) { return Err(raise_error!( @@ -344,6 +345,25 @@ impl UserRole { ErrorCode::InvalidParameter )); } + + let all_users = UserModel::list_all().await?; + let active_users: Vec = all_users + .iter() + .filter(|user| user.is_using_role(id)) + .map(|user| user.username.clone()) + .collect(); + + if !active_users.is_empty() { + let user_list = active_users.join(", "); + return Err(raise_error!( + format!( + "Cannot delete role (ID: {}): It is still assigned to the following users: {}", + id, user_list + ), + ErrorCode::PermissionDenied + )); + } + delete_impl(DB_MANAGER.meta_db(), move |rw| { rw.get() .primary::(id)