Redesign sensitive info protection settings

This commit is contained in:
fawney19
2026-05-14 11:14:20 +08:00
parent 91955ad1e0
commit 509bd30252
71 changed files with 3254 additions and 884 deletions
@@ -1,8 +1,8 @@
use super::super::{
admin_default_user_initial_gift, build_admin_users_read_only_response,
disabled_user_policy_detail, disabled_user_policy_field, normalize_admin_optional_user_email,
normalize_admin_user_group_ids, normalize_admin_user_role, normalize_admin_username,
validate_admin_user_password, AdminCreateUserRequest,
disabled_user_policy_detail, disabled_user_policy_field, normalize_admin_feature_settings,
normalize_admin_optional_user_email, normalize_admin_user_group_ids, normalize_admin_user_role,
normalize_admin_username, validate_admin_user_password, AdminCreateUserRequest,
};
use super::support::{admin_user_password_policy, build_admin_user_payload_with_groups};
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
@@ -66,6 +66,16 @@ pub(in super::super) async fn build_admin_create_user_response(
.into_response())
}
};
let feature_settings = match normalize_admin_feature_settings(payload.feature_settings) {
Ok(value) => value,
Err(detail) => {
return Ok((
http::StatusCode::BAD_REQUEST,
Json(json!({ "detail": detail })),
)
.into_response())
}
};
let email = match normalize_admin_optional_user_email(payload.email.as_deref()) {
Ok(value) => value,
@@ -210,16 +220,21 @@ pub(in super::super) async fn build_admin_create_user_response(
.replace_user_groups_for_user(&user.id, &group_ids)
.await?;
}
let feature_settings = if feature_settings.is_some() {
state
.update_user_feature_settings(&user.id, feature_settings.clone())
.await?
.or(feature_settings)
} else {
None
};
let mut payload =
build_admin_user_payload_with_groups(&user, None, None, payload.unlimited, &groups);
payload["feature_settings"] = feature_settings.unwrap_or(Value::Null);
Ok(attach_admin_audit_response(
Json(build_admin_user_payload_with_groups(
&user,
None,
None,
payload.unlimited,
&groups,
))
.into_response(),
Json(payload).into_response(),
"admin_user_created",
"create_user",
"user",
@@ -144,12 +144,16 @@ pub(in super::super) async fn build_admin_get_user_response(
let unlimited = wallet
.as_ref()
.is_some_and(|wallet| wallet.limit_mode.eq_ignore_ascii_case("unlimited"));
Ok(Json(build_admin_user_payload_with_groups(
let mut payload = build_admin_user_payload_with_groups(
&user,
export_row.as_ref().and_then(|row| row.rate_limit),
export_row.as_ref().map(|row| row.rate_limit_mode.as_str()),
unlimited,
&groups,
))
.into_response())
);
payload["feature_settings"] = export_row
.as_ref()
.and_then(|row| row.feature_settings.clone())
.unwrap_or(serde_json::Value::Null);
Ok(Json(payload).into_response())
}
@@ -103,6 +103,7 @@ pub(super) fn build_admin_user_export_payload(
"allowed_models_mode": row.allowed_models_mode,
"rate_limit": row.rate_limit,
"rate_limit_mode": row.rate_limit_mode,
"feature_settings": row.feature_settings,
"unlimited": unlimited,
"is_active": row.is_active,
"created_at": format_optional_datetime_iso8601(created_at),
@@ -1,8 +1,9 @@
use super::super::{
build_admin_users_bad_request_response, build_admin_users_data_unavailable_response,
build_admin_users_read_only_response, disabled_user_policy_detail, disabled_user_policy_field,
normalize_admin_optional_user_email, normalize_admin_user_group_ids, normalize_admin_user_role,
normalize_admin_username, validate_admin_user_password, AdminUpdateUserPatch,
normalize_admin_feature_settings, normalize_admin_optional_user_email,
normalize_admin_user_group_ids, normalize_admin_user_role, normalize_admin_username,
validate_admin_user_password, AdminUpdateUserPatch,
};
use super::support::{
admin_user_id_from_detail_path, admin_user_password_policy,
@@ -17,7 +18,7 @@ use axum::{
response::{IntoResponse, Response},
Json,
};
use serde_json::json;
use serde_json::{json, Value};
pub(in super::super) async fn build_admin_update_user_response(
state: &AdminAppState<'_>,
@@ -69,6 +70,20 @@ pub(in super::super) async fn build_admin_update_user_response(
}
};
let (field_presence, payload) = patch.into_parts();
let feature_settings = if field_presence.contains("feature_settings") {
match normalize_admin_feature_settings(payload.feature_settings.flatten()) {
Ok(value) => Some(value),
Err(detail) => {
return Ok((
http::StatusCode::BAD_REQUEST,
Json(json!({ "detail": detail })),
)
.into_response())
}
}
} else {
None
};
let email = match payload.email.as_deref() {
Some(value) => match normalize_admin_optional_user_email(Some(value)) {
@@ -175,7 +190,8 @@ pub(in super::super) async fn build_admin_update_user_response(
|| payload.password.is_some()
|| role.is_some()
|| payload.is_active.is_some()
|| group_ids.is_some();
|| group_ids.is_some()
|| feature_settings.is_some();
if needs_auth_user_write && !state.has_auth_user_write_capability() {
return Ok(build_admin_users_read_only_response(
"当前为只读模式,无法更新用户",
@@ -293,6 +309,11 @@ pub(in super::super) async fn build_admin_update_user_response(
}
}
}
if let Some(feature_settings) = feature_settings {
state
.update_user_feature_settings(&user_id, feature_settings)
.await?;
}
let Some(user) = state.find_user_auth_by_id(&user_id).await? else {
return Ok((
@@ -313,15 +334,20 @@ pub(in super::super) async fn build_admin_update_user_response(
let groups = state.list_user_groups_for_user(&user_id).await?;
let rate_limit = export_row.as_ref().and_then(|row| row.rate_limit);
let mut payload = build_admin_user_payload_with_groups(
&user,
rate_limit,
export_row.as_ref().map(|row| row.rate_limit_mode.as_str()),
unlimited,
&groups,
);
payload["feature_settings"] = export_row
.as_ref()
.and_then(|row| row.feature_settings.clone())
.unwrap_or(Value::Null);
Ok(attach_admin_audit_response(
Json(build_admin_user_payload_with_groups(
&user,
rate_limit,
export_row.as_ref().map(|row| row.rate_limit_mode.as_str()),
unlimited,
&groups,
))
.into_response(),
Json(payload).into_response(),
"admin_user_updated",
"update_user",
"user",