2026-04-09 00:10:38 +08:00
|
|
|
use crate::handlers::admin::request::AdminAppState;
|
|
|
|
|
use crate::handlers::shared::unix_secs_to_rfc3339;
|
|
|
|
|
use crate::GatewayError;
|
|
|
|
|
use aether_admin::system::{
|
|
|
|
|
admin_system_config_default_value as admin_system_config_default_value_pure,
|
|
|
|
|
admin_system_config_delete_keys as admin_system_config_delete_keys_pure,
|
|
|
|
|
build_admin_system_config_deleted_payload,
|
|
|
|
|
build_admin_system_config_detail_payload as build_admin_system_config_detail_payload_pure,
|
|
|
|
|
build_admin_system_config_updated_payload,
|
|
|
|
|
build_admin_system_configs_payload as build_admin_system_configs_payload_pure,
|
|
|
|
|
is_sensitive_admin_system_config_key as is_sensitive_admin_system_config_key_pure,
|
|
|
|
|
normalize_admin_system_config_key as normalize_admin_system_config_key_pure,
|
|
|
|
|
parse_admin_system_config_update,
|
2026-04-07 02:50:19 +08:00
|
|
|
};
|
2026-04-09 00:10:38 +08:00
|
|
|
use aether_crypto::encrypt_python_fernet_plaintext;
|
2026-04-07 02:50:19 +08:00
|
|
|
use axum::body::Bytes;
|
|
|
|
|
use axum::http;
|
|
|
|
|
use serde_json::json;
|
|
|
|
|
|
|
|
|
|
fn normalize_admin_system_config_key(requested_key: &str) -> String {
|
2026-04-09 00:10:38 +08:00
|
|
|
normalize_admin_system_config_key_pure(requested_key)
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn admin_system_config_delete_keys(requested_key: &str) -> Vec<String> {
|
2026-04-09 00:10:38 +08:00
|
|
|
admin_system_config_delete_keys_pure(requested_key)
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-09 00:10:38 +08:00
|
|
|
pub(crate) fn is_sensitive_admin_system_config_key(key: &str) -> bool {
|
|
|
|
|
is_sensitive_admin_system_config_key_pure(key)
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn admin_system_config_default_value(key: &str) -> Option<serde_json::Value> {
|
2026-04-09 00:10:38 +08:00
|
|
|
admin_system_config_default_value_pure(key)
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn build_admin_system_configs_payload(
|
|
|
|
|
entries: &[aether_data::repository::system::StoredSystemConfigEntry],
|
|
|
|
|
) -> serde_json::Value {
|
2026-04-09 00:10:38 +08:00
|
|
|
build_admin_system_configs_payload_pure(entries)
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) async fn build_admin_system_config_detail_payload(
|
2026-04-09 00:10:38 +08:00
|
|
|
state: &AdminAppState<'_>,
|
2026-04-07 02:50:19 +08:00
|
|
|
requested_key: &str,
|
|
|
|
|
) -> Result<Result<serde_json::Value, (http::StatusCode, serde_json::Value)>, GatewayError> {
|
|
|
|
|
let requested_key = requested_key.trim();
|
|
|
|
|
let value = state
|
2026-04-09 00:10:38 +08:00
|
|
|
.read_system_config_json_value(&normalize_admin_system_config_key(requested_key))
|
2026-04-07 02:50:19 +08:00
|
|
|
.await?
|
2026-04-09 00:10:38 +08:00
|
|
|
.or_else(|| {
|
|
|
|
|
admin_system_config_default_value(&normalize_admin_system_config_key(requested_key))
|
|
|
|
|
});
|
|
|
|
|
Ok(build_admin_system_config_detail_payload_pure(
|
|
|
|
|
requested_key,
|
|
|
|
|
value,
|
|
|
|
|
))
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) async fn apply_admin_system_config_update(
|
2026-04-09 00:10:38 +08:00
|
|
|
state: &AdminAppState<'_>,
|
2026-04-07 02:50:19 +08:00
|
|
|
requested_key: &str,
|
|
|
|
|
request_body: &Bytes,
|
|
|
|
|
) -> Result<Result<serde_json::Value, (http::StatusCode, serde_json::Value)>, GatewayError> {
|
2026-04-09 00:10:38 +08:00
|
|
|
let update = match parse_admin_system_config_update(requested_key, request_body) {
|
|
|
|
|
Ok(update) => update,
|
|
|
|
|
Err(err) => return Ok(Err(err)),
|
2026-04-07 02:50:19 +08:00
|
|
|
};
|
2026-04-09 00:10:38 +08:00
|
|
|
let mut value = update.value;
|
|
|
|
|
let normalized_key = update.normalized_key;
|
|
|
|
|
let description = update.description;
|
2026-04-07 02:50:19 +08:00
|
|
|
|
|
|
|
|
if is_sensitive_admin_system_config_key(&normalized_key)
|
|
|
|
|
&& value.as_str().is_some_and(|raw| !raw.is_empty())
|
|
|
|
|
{
|
|
|
|
|
let Some(encryption_key) = state
|
|
|
|
|
.encryption_key()
|
|
|
|
|
.filter(|value| !value.trim().is_empty())
|
|
|
|
|
else {
|
|
|
|
|
return Ok(Err((
|
|
|
|
|
http::StatusCode::SERVICE_UNAVAILABLE,
|
|
|
|
|
json!({ "detail": "系统配置写入需要可用的加密密钥" }),
|
|
|
|
|
)));
|
|
|
|
|
};
|
|
|
|
|
let plaintext = value.as_str().unwrap();
|
|
|
|
|
value = json!(encrypt_python_fernet_plaintext(encryption_key, plaintext)
|
|
|
|
|
.map_err(|err| GatewayError::Internal(err.to_string()))?);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let updated = state
|
|
|
|
|
.upsert_system_config_entry(&normalized_key, &value, description.as_deref())
|
|
|
|
|
.await?;
|
|
|
|
|
let display_value = if is_sensitive_admin_system_config_key(&normalized_key) {
|
|
|
|
|
json!("********")
|
|
|
|
|
} else {
|
|
|
|
|
updated.value.clone()
|
|
|
|
|
};
|
2026-04-09 00:10:38 +08:00
|
|
|
Ok(Ok(build_admin_system_config_updated_payload(
|
|
|
|
|
updated.key,
|
|
|
|
|
display_value,
|
|
|
|
|
updated.description,
|
|
|
|
|
updated.updated_at_unix_secs,
|
|
|
|
|
)))
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) async fn delete_admin_system_config(
|
2026-04-09 00:10:38 +08:00
|
|
|
state: &AdminAppState<'_>,
|
2026-04-07 02:50:19 +08:00
|
|
|
requested_key: &str,
|
|
|
|
|
) -> Result<Result<serde_json::Value, (http::StatusCode, serde_json::Value)>, GatewayError> {
|
|
|
|
|
let delete_keys = admin_system_config_delete_keys(requested_key);
|
|
|
|
|
let mut deleted = false;
|
|
|
|
|
for key in &delete_keys {
|
|
|
|
|
deleted |= state.delete_system_config_value(key).await?;
|
|
|
|
|
}
|
|
|
|
|
if !deleted {
|
|
|
|
|
return Ok(Err((
|
|
|
|
|
http::StatusCode::NOT_FOUND,
|
|
|
|
|
json!({ "detail": format!("配置项 '{requested_key}' 不存在") }),
|
|
|
|
|
)));
|
|
|
|
|
}
|
2026-04-09 00:10:38 +08:00
|
|
|
Ok(Ok(build_admin_system_config_deleted_payload(requested_key)))
|
2026-04-07 02:50:19 +08:00
|
|
|
}
|