mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-10 11:19:50 +08:00
Redesign sensitive info protection settings
This commit is contained in:
@@ -44,6 +44,7 @@ pub(super) fn build_admin_user_api_key_detail_payload(
|
||||
"total_cost_usd": record.total_cost_usd,
|
||||
"rate_limit": record.rate_limit,
|
||||
"concurrent_limit": record.concurrent_limit,
|
||||
"feature_settings": record.feature_settings,
|
||||
"expires_at": format_optional_unix_secs_iso8601(record.expires_at_unix_secs),
|
||||
"last_used_at": format_optional_unix_secs_iso8601(record.last_used_at_unix_secs),
|
||||
"created_at": format_optional_unix_secs_iso8601(record.created_at_unix_secs),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::super::super::{
|
||||
build_admin_users_bad_request_response, build_admin_users_data_unavailable_response,
|
||||
build_admin_users_read_only_response, AdminCreateUserApiKeyRequest,
|
||||
build_admin_users_read_only_response, normalize_admin_feature_settings,
|
||||
AdminCreateUserApiKeyRequest,
|
||||
};
|
||||
use super::super::helpers::{
|
||||
attach_audit_response, default_admin_user_api_key_name, format_optional_unix_secs_iso8601,
|
||||
@@ -74,6 +75,16 @@ pub(crate) async fn build_admin_create_user_api_key_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 name = match normalize_admin_optional_api_key_name(payload.name) {
|
||||
Ok(Some(value)) => value,
|
||||
@@ -161,6 +172,21 @@ pub(crate) async fn build_admin_create_user_api_key_response(
|
||||
} else {
|
||||
created
|
||||
};
|
||||
let created = if feature_settings.is_some() {
|
||||
match state
|
||||
.set_user_api_key_feature_settings(
|
||||
&user_id,
|
||||
&created.api_key_id,
|
||||
feature_settings.clone(),
|
||||
)
|
||||
.await?
|
||||
{
|
||||
Some(updated) => updated,
|
||||
None => created,
|
||||
}
|
||||
} else {
|
||||
created
|
||||
};
|
||||
|
||||
Ok(attach_audit_response(
|
||||
Json(json!({
|
||||
@@ -173,6 +199,7 @@ pub(crate) async fn build_admin_create_user_api_key_response(
|
||||
"expires_at": format_optional_unix_secs_iso8601(created.expires_at_unix_secs),
|
||||
"last_used_at": format_optional_unix_secs_iso8601(created.last_used_at_unix_secs),
|
||||
"created_at": format_optional_unix_secs_iso8601(created.created_at_unix_secs),
|
||||
"feature_settings": created.feature_settings,
|
||||
"message": "API Key创建成功,请妥善保存完整密钥",
|
||||
}))
|
||||
.into_response(),
|
||||
|
||||
@@ -63,6 +63,7 @@ pub(crate) async fn build_admin_list_user_api_keys_response(
|
||||
"total_cost_usd": record.total_cost_usd,
|
||||
"rate_limit": record.rate_limit,
|
||||
"concurrent_limit": record.concurrent_limit,
|
||||
"feature_settings": record.feature_settings,
|
||||
"expires_at": format_optional_unix_secs_iso8601(record.expires_at_unix_secs),
|
||||
"last_used_at": format_optional_unix_secs_iso8601(record.last_used_at_unix_secs),
|
||||
"created_at": format_optional_unix_secs_iso8601(record.created_at_unix_secs),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::super::super::{
|
||||
build_admin_users_bad_request_response, build_admin_users_read_only_response,
|
||||
AdminUpdateUserApiKeyRequest,
|
||||
normalize_admin_feature_settings, AdminUpdateUserApiKeyRequest,
|
||||
};
|
||||
use super::super::helpers::{
|
||||
attach_audit_response, build_admin_user_api_key_detail_payload,
|
||||
@@ -52,6 +52,20 @@ pub(crate) async fn build_admin_update_user_api_key_response(
|
||||
.into_response());
|
||||
}
|
||||
};
|
||||
let feature_settings = if let Some(feature_settings) = payload.feature_settings {
|
||||
match normalize_admin_feature_settings(feature_settings) {
|
||||
Ok(value) => Some(value),
|
||||
Err(detail) => {
|
||||
return Ok((
|
||||
http::StatusCode::BAD_REQUEST,
|
||||
Json(json!({ "detail": detail })),
|
||||
)
|
||||
.into_response());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let name = match normalize_admin_optional_api_key_name(payload.name) {
|
||||
Ok(value) => value,
|
||||
Err(detail) => {
|
||||
@@ -83,7 +97,7 @@ pub(crate) async fn build_admin_update_user_api_key_response(
|
||||
|
||||
let Some(updated) = state
|
||||
.update_user_api_key_basic(aether_data::repository::auth::UpdateUserApiKeyBasicRecord {
|
||||
user_id,
|
||||
user_id: user_id.clone(),
|
||||
api_key_id: api_key_id.clone(),
|
||||
name,
|
||||
rate_limit: payload.rate_limit,
|
||||
@@ -97,6 +111,14 @@ pub(crate) async fn build_admin_update_user_api_key_response(
|
||||
)
|
||||
.into_response());
|
||||
};
|
||||
let updated = if let Some(feature_settings) = feature_settings {
|
||||
state
|
||||
.set_user_api_key_feature_settings(&user_id, &api_key_id, feature_settings)
|
||||
.await?
|
||||
.unwrap_or(updated)
|
||||
} else {
|
||||
updated
|
||||
};
|
||||
|
||||
let is_locked = state
|
||||
.list_auth_api_key_snapshots_by_ids(std::slice::from_ref(&api_key_id))
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -53,6 +53,7 @@ pub(crate) use self::shared::{
|
||||
normalize_admin_list_policy_mode, normalize_admin_rate_limit_policy_mode,
|
||||
normalize_admin_user_api_formats, normalize_admin_user_string_list,
|
||||
};
|
||||
pub(crate) use crate::handlers::shared::normalize_feature_settings as normalize_admin_feature_settings;
|
||||
|
||||
pub(crate) async fn maybe_build_local_admin_users_response(
|
||||
request: AdminRouteRequest<'_>,
|
||||
|
||||
@@ -7,7 +7,7 @@ use axum::{
|
||||
Json,
|
||||
};
|
||||
use regex::Regex;
|
||||
use serde_json::json;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub(super) struct AdminCreateUserApiKeyRequest {
|
||||
@@ -35,6 +35,8 @@ pub(super) struct AdminCreateUserApiKeyRequest {
|
||||
pub(super) is_standalone: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(super) auto_delete_on_expiry: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(super) feature_settings: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
@@ -45,6 +47,8 @@ pub(super) struct AdminUpdateUserApiKeyRequest {
|
||||
pub(super) rate_limit: Option<i32>,
|
||||
#[serde(default)]
|
||||
pub(super) concurrent_limit: Option<i32>,
|
||||
#[serde(default)]
|
||||
pub(super) feature_settings: Option<Option<Value>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
@@ -67,6 +71,8 @@ pub(super) struct AdminCreateUserRequest {
|
||||
pub(super) unlimited: bool,
|
||||
#[serde(default)]
|
||||
pub(super) group_ids: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub(super) feature_settings: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
@@ -85,6 +91,8 @@ pub(super) struct AdminUpdateUserRequest {
|
||||
pub(super) group_ids: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub(super) is_active: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub(super) feature_settings: Option<Option<Value>>,
|
||||
}
|
||||
|
||||
pub(super) type AdminUpdateUserPatch = AdminTypedObjectPatch<AdminUpdateUserRequest>;
|
||||
|
||||
Reference in New Issue
Block a user