fix: prevent deletion of roles that are currently in use #194

This commit is contained in:
rustmailer
2026-04-16 15:43:55 +08:00
parent 15dd26228c
commit 18a0d52c57
3 changed files with 35 additions and 4 deletions
+13 -2
View File
@@ -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<Vec<UserModel>> {
Ok(list_all_impl::<UserModel>(DB_MANAGER.meta_db()).await?)
}
+1 -1
View File
@@ -340,7 +340,7 @@ pub struct UserUpdateRequest {
pub avatar_base64: Option<String>,
pub global_roles: Option<Vec<u64>>,
/// Scoped Access
pub account_access_map: Option<BTreeMap<u64, u64>>,
pub account_access_map: Option<BTreeMap<u64, u64>>,
pub acl: Option<AccessControl>,
pub description: Option<String>,
pub theme: Option<String>,
+21 -1
View File
@@ -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<String> = 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::<UserRole>(id)