feat(admin): 实现系统数据导入导出功能,支持提供商和模型批量配置

This commit is contained in:
fawney19
2026-04-11 21:39:04 +08:00
parent 801e16c988
commit a9f610fa69
36 changed files with 3247 additions and 409 deletions
@@ -33,8 +33,7 @@ use self::shared::{
admin_api_keys_parse_limit, admin_api_keys_parse_skip, build_admin_api_key_detail_payload,
build_admin_api_key_list_item_payload, build_admin_api_keys_bad_request_response,
build_admin_api_keys_data_unavailable_response, build_admin_api_keys_not_found_response,
AdminStandaloneApiKeyCreateRequest, AdminStandaloneApiKeyFieldPresence,
AdminStandaloneApiKeyToggleRequest, AdminStandaloneApiKeyUpdateRequest,
AdminStandaloneApiKeyCreateRequest, AdminStandaloneApiKeyToggleRequest,
};
pub(crate) async fn maybe_build_local_admin_api_keys_response(
@@ -2,8 +2,8 @@ use super::shared::{
admin_api_key_total_tokens_by_ids, admin_api_keys_id_from_path, admin_api_keys_operator_id,
build_admin_api_key_detail_payload, build_admin_api_keys_bad_request_response,
build_admin_api_keys_data_unavailable_response, build_admin_api_keys_not_found_response,
AdminStandaloneApiKeyCreateRequest, AdminStandaloneApiKeyFieldPresence,
AdminStandaloneApiKeyToggleRequest, AdminStandaloneApiKeyUpdateRequest,
AdminStandaloneApiKeyCreateRequest, AdminStandaloneApiKeyToggleRequest,
AdminStandaloneApiKeyUpdatePatch,
};
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
use crate::handlers::admin::shared::attach_admin_audit_response;
@@ -162,14 +162,7 @@ pub(super) async fn build_admin_update_api_key_response(
));
}
};
let field_presence = AdminStandaloneApiKeyFieldPresence {
allowed_providers: raw_payload.contains_key("allowed_providers"),
allowed_api_formats: raw_payload.contains_key("allowed_api_formats"),
allowed_models: raw_payload.contains_key("allowed_models"),
};
let payload = match serde_json::from_value::<AdminStandaloneApiKeyUpdateRequest>(
serde_json::Value::Object(raw_payload),
) {
let patch = match AdminStandaloneApiKeyUpdatePatch::from_object(raw_payload) {
Ok(value) => value,
Err(_) => {
return Ok(build_admin_api_keys_bad_request_response(
@@ -177,6 +170,7 @@ pub(super) async fn build_admin_update_api_key_response(
));
}
};
let (field_presence, payload) = patch.into_parts();
if payload.initial_balance_usd.is_some()
|| payload.unlimited_balance.is_some()
|| payload.expire_days.is_some()
@@ -197,7 +191,7 @@ pub(super) async fn build_admin_update_api_key_response(
"rate_limit 必须大于等于 0",
));
}
let allowed_providers = if field_presence.allowed_providers {
let allowed_providers = if field_presence.contains("allowed_providers") {
match normalize_admin_user_string_list(payload.allowed_providers, "allowed_providers") {
Ok(value) => Some(value),
Err(detail) => return Ok(build_admin_api_keys_bad_request_response(detail)),
@@ -205,7 +199,7 @@ pub(super) async fn build_admin_update_api_key_response(
} else {
None
};
let allowed_api_formats = if field_presence.allowed_api_formats {
let allowed_api_formats = if field_presence.contains("allowed_api_formats") {
match normalize_admin_user_api_formats(payload.allowed_api_formats) {
Ok(value) => Some(value),
Err(detail) => return Ok(build_admin_api_keys_bad_request_response(detail)),
@@ -213,7 +207,7 @@ pub(super) async fn build_admin_update_api_key_response(
} else {
None
};
let allowed_models = if field_presence.allowed_models {
let allowed_models = if field_presence.contains("allowed_models") {
match normalize_admin_user_string_list(payload.allowed_models, "allowed_models") {
Ok(value) => Some(value),
Err(detail) => return Ok(build_admin_api_keys_bad_request_response(detail)),
@@ -1,5 +1,5 @@
use crate::handlers::admin::request::{AdminAppState, AdminRequestContext};
use crate::handlers::admin::shared::query_param_value;
use crate::handlers::admin::shared::{query_param_value, AdminTypedObjectPatch};
use crate::handlers::admin::users::{
format_optional_unix_secs_iso8601, masked_user_api_key_display,
};
@@ -43,18 +43,14 @@ pub(super) struct AdminStandaloneApiKeyUpdateRequest {
pub(super) auto_delete_on_expiry: Option<bool>,
}
pub(super) type AdminStandaloneApiKeyUpdatePatch =
AdminTypedObjectPatch<AdminStandaloneApiKeyUpdateRequest>;
#[derive(Debug, Default, serde::Deserialize)]
pub(super) struct AdminStandaloneApiKeyToggleRequest {
pub(super) is_active: Option<bool>,
}
#[derive(Debug, Default)]
pub(super) struct AdminStandaloneApiKeyFieldPresence {
pub(super) allowed_providers: bool,
pub(super) allowed_api_formats: bool,
pub(super) allowed_models: bool,
}
pub(super) fn build_admin_api_keys_data_unavailable_response() -> Response<Body> {
(
http::StatusCode::SERVICE_UNAVAILABLE,