mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 02:17:46 +08:00
feat(gateway): add reversible chat pii redaction
This commit is contained in:
@@ -129,6 +129,28 @@ pub(crate) fn normalize_pool_advanced_config(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalize_chat_pii_redaction_config(
|
||||
value: Option<serde_json::Value>,
|
||||
) -> Result<Option<serde_json::Value>, String> {
|
||||
let Some(value) = value else {
|
||||
return Ok(None);
|
||||
};
|
||||
match value {
|
||||
serde_json::Value::Null => Ok(None),
|
||||
serde_json::Value::Object(mut map) => {
|
||||
if map.len() != 1 || !map.contains_key("enabled") {
|
||||
return Err("chat_pii_redaction 仅支持 enabled 布尔配置".to_string());
|
||||
}
|
||||
let enabled = map
|
||||
.remove("enabled")
|
||||
.and_then(|value| value.as_bool())
|
||||
.ok_or_else(|| "chat_pii_redaction.enabled 必须是布尔值".to_string())?;
|
||||
Ok(Some(serde_json::json!({ "enabled": enabled })))
|
||||
}
|
||||
_ => Err("chat_pii_redaction 必须是 JSON 对象".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn validate_vertex_api_formats(
|
||||
provider_type: &str,
|
||||
auth_type: &str,
|
||||
@@ -177,7 +199,8 @@ mod tests {
|
||||
use super::{
|
||||
normalize_allow_auth_channel_mismatch_formats, normalize_api_format_json_object_keys,
|
||||
normalize_api_format_list, normalize_auth_type, normalize_auth_type_by_format,
|
||||
normalize_pool_advanced_config, normalize_provider_type_input, validate_vertex_api_formats,
|
||||
normalize_chat_pii_redaction_config, normalize_pool_advanced_config,
|
||||
normalize_provider_type_input, validate_vertex_api_formats,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
@@ -201,6 +224,26 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_chat_pii_redaction_requires_enabled_boolean_only() {
|
||||
assert_eq!(
|
||||
normalize_chat_pii_redaction_config(Some(json!({ "enabled": true })))
|
||||
.expect("chat pii redaction should normalize"),
|
||||
Some(json!({ "enabled": true }))
|
||||
);
|
||||
assert_eq!(
|
||||
normalize_chat_pii_redaction_config(Some(
|
||||
json!({ "enabled": true, "entities": ["email"] })
|
||||
))
|
||||
.unwrap_err(),
|
||||
"chat_pii_redaction 仅支持 enabled 布尔配置"
|
||||
);
|
||||
assert_eq!(
|
||||
normalize_chat_pii_redaction_config(Some(json!({ "enabled": "yes" }))).unwrap_err(),
|
||||
"chat_pii_redaction.enabled 必须是布尔值"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_auth_type_supports_bearer() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::handlers::admin::provider::shared::payloads::AdminProviderCreateReque
|
||||
use crate::handlers::admin::provider::shared::support::{
|
||||
normalize_provider_billing_type, parse_optional_rfc3339_unix_secs,
|
||||
};
|
||||
use crate::handlers::admin::provider::write::normalize::normalize_chat_pii_redaction_config;
|
||||
use crate::handlers::admin::provider::write::normalize::normalize_pool_advanced_config;
|
||||
use crate::handlers::admin::provider::write::normalize::normalize_provider_type_input;
|
||||
use crate::handlers::admin::request::AdminAppState;
|
||||
@@ -134,6 +135,12 @@ pub(crate) async fn build_admin_create_provider_record(
|
||||
}
|
||||
config_map.insert("claude_code_advanced".to_string(), value);
|
||||
}
|
||||
if config_map.contains_key("chat_pii_redaction") {
|
||||
let value = normalize_chat_pii_redaction_config(config_map.remove("chat_pii_redaction"))?;
|
||||
if let Some(value) = value {
|
||||
config_map.insert("chat_pii_redaction".to_string(), value);
|
||||
}
|
||||
}
|
||||
let config = (!config_map.is_empty()).then_some(serde_json::Value::Object(config_map));
|
||||
|
||||
let now_unix_secs = SystemTime::now()
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::handlers::admin::provider::shared::payloads::AdminProviderUpdatePatch
|
||||
use crate::handlers::admin::provider::shared::support::{
|
||||
normalize_provider_billing_type, parse_optional_rfc3339_unix_secs,
|
||||
};
|
||||
use crate::handlers::admin::provider::write::normalize::normalize_chat_pii_redaction_config;
|
||||
use crate::handlers::admin::provider::write::normalize::normalize_pool_advanced_config;
|
||||
use crate::handlers::admin::provider::write::normalize::normalize_provider_type_input;
|
||||
use crate::handlers::admin::request::AdminAppState;
|
||||
@@ -225,14 +226,29 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
updated.enable_format_conversion = enable_format_conversion;
|
||||
}
|
||||
|
||||
let config_seed = if fields.contains("config") {
|
||||
normalize_json_object(payload.config, "config")?
|
||||
} else {
|
||||
updated.config.clone()
|
||||
};
|
||||
let mut config_map = config_seed
|
||||
let mut config_map = updated
|
||||
.config
|
||||
.clone()
|
||||
.and_then(|value| value.as_object().cloned())
|
||||
.unwrap_or_default();
|
||||
if fields.contains("config") {
|
||||
if fields.is_null("config") {
|
||||
config_map.clear();
|
||||
} else {
|
||||
let value = normalize_json_object(payload.config, "config")?
|
||||
.ok_or_else(|| "config 必须是 JSON 对象".to_string())?;
|
||||
let serde_json::Value::Object(patch_map) = value else {
|
||||
return Err("config 必须是 JSON 对象".to_string());
|
||||
};
|
||||
for (key, value) in patch_map {
|
||||
if value.is_null() {
|
||||
config_map.remove(&key);
|
||||
} else {
|
||||
config_map.insert(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if fields.contains("claude_code_advanced") {
|
||||
if fields.is_null("claude_code_advanced") {
|
||||
@@ -270,6 +286,13 @@ pub(crate) async fn build_admin_update_provider_record(
|
||||
}
|
||||
}
|
||||
|
||||
if config_map.contains_key("chat_pii_redaction") {
|
||||
let value = normalize_chat_pii_redaction_config(config_map.remove("chat_pii_redaction"))?;
|
||||
if let Some(value) = value {
|
||||
config_map.insert("chat_pii_redaction".to_string(), value);
|
||||
}
|
||||
}
|
||||
|
||||
updated.config = (!config_map.is_empty()).then_some(serde_json::Value::Object(config_map));
|
||||
updated.updated_at_unix_secs = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
||||
Reference in New Issue
Block a user