feat(security): harden client IP and admin controls

This commit is contained in:
elky
2026-07-10 15:13:12 +08:00
parent 6e0dc3b59e
commit bc1da3bf3f
19 changed files with 976 additions and 378 deletions
@@ -643,7 +643,11 @@ fn count_active_admin_demotions(
mutation: &AdminUserBatchMutation,
items: &[AdminUserSelectionItem],
) -> usize {
if mutation.role.as_deref() != Some("user") {
if mutation
.role
.as_deref()
.is_none_or(crate::roles::is_full_admin_role)
{
return 0;
}
items
@@ -659,7 +663,10 @@ fn batch_role_demotion_failure_reason(
active_admin_demotions: usize,
current_admin_user_id: Option<&str>,
) -> Option<&'static str> {
if mutation.role.as_deref() != Some("user")
if mutation
.role
.as_deref()
.is_none_or(crate::roles::is_full_admin_role)
|| !item.is_active
|| !item.role.eq_ignore_ascii_case("admin")
{
@@ -150,6 +150,19 @@ pub(in super::super) async fn build_admin_update_user_response(
},
None => None,
};
if existing_user.is_active
&& crate::roles::is_full_admin_role(&existing_user.role)
&& role
.as_deref()
.is_some_and(|role| !crate::roles::is_full_admin_role(role))
&& state.count_active_admin_users().await? <= 1
{
return Ok((
http::StatusCode::BAD_REQUEST,
Json(json!({ "detail": "不能降级最后一个管理员账户" })),
)
.into_response());
}
let effective_role = role.as_deref().unwrap_or(existing_user.role.as_str());
let group_ids = if field_presence.contains("group_ids") {
Some(normalize_admin_user_group_ids(payload.group_ids))