feat(usage-query): decouple credentials from provider config
Add independent credential fields for usage query to support different query endpoints and authentication methods. Changes: - Add `apiKey` and `baseUrl` fields to UsageScript struct - Remove dependency on provider config credentials in query_usage - Update test_usage_script to accept independent credential parameters - Add credential input fields in UsageScriptModal based on template: * General: apiKey + baseUrl * NewAPI: baseUrl + accessToken + userId * Custom: no additional fields (full freedom) - Auto-clear irrelevant fields when switching templates - Add i18n text for "credentialsConfig" Benefits: - Query API can use different endpoint/key than provider config - Better separation of concerns - More flexible for various usage query scenarios
This commit is contained in:
@@ -802,7 +802,7 @@ impl ProviderService {
|
||||
app_type: AppType,
|
||||
provider_id: &str,
|
||||
) -> Result<UsageResult, AppError> {
|
||||
let (provider, script_code, timeout, access_token, user_id) = {
|
||||
let (script_code, timeout, api_key, base_url, access_token, user_id) = {
|
||||
let config = state.config.read().map_err(AppError::from)?;
|
||||
let manager = config
|
||||
.get_manager(&app_type)
|
||||
@@ -814,38 +814,37 @@ impl ProviderService {
|
||||
format!("Provider not found: {}", provider_id),
|
||||
)
|
||||
})?;
|
||||
let (script_code, timeout, access_token, user_id) = {
|
||||
let usage_script = provider
|
||||
.meta
|
||||
.as_ref()
|
||||
.and_then(|m| m.usage_script.as_ref())
|
||||
.ok_or_else(|| {
|
||||
AppError::localized(
|
||||
"provider.usage.script.missing",
|
||||
"未配置用量查询脚本",
|
||||
"Usage script is not configured",
|
||||
)
|
||||
})?;
|
||||
if !usage_script.enabled {
|
||||
return Err(AppError::localized(
|
||||
"provider.usage.disabled",
|
||||
"用量查询未启用",
|
||||
"Usage query is disabled",
|
||||
));
|
||||
}
|
||||
(
|
||||
usage_script.code.clone(),
|
||||
usage_script.timeout.unwrap_or(10),
|
||||
usage_script.access_token.clone(),
|
||||
usage_script.user_id.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
(provider, script_code, timeout, access_token, user_id)
|
||||
let usage_script = provider
|
||||
.meta
|
||||
.as_ref()
|
||||
.and_then(|m| m.usage_script.as_ref())
|
||||
.ok_or_else(|| {
|
||||
AppError::localized(
|
||||
"provider.usage.script.missing",
|
||||
"未配置用量查询脚本",
|
||||
"Usage script is not configured",
|
||||
)
|
||||
})?;
|
||||
if !usage_script.enabled {
|
||||
return Err(AppError::localized(
|
||||
"provider.usage.disabled",
|
||||
"用量查询未启用",
|
||||
"Usage query is disabled",
|
||||
));
|
||||
}
|
||||
|
||||
// 直接从 UsageScript 中获取凭证,不再从供应商配置提取
|
||||
(
|
||||
usage_script.code.clone(),
|
||||
usage_script.timeout.unwrap_or(10),
|
||||
usage_script.api_key.clone().unwrap_or_default(),
|
||||
usage_script.base_url.clone().unwrap_or_default(),
|
||||
usage_script.access_token.clone(),
|
||||
usage_script.user_id.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
let (api_key, base_url) = Self::extract_credentials(&provider, &app_type)?;
|
||||
|
||||
Self::execute_and_format_usage_result(
|
||||
&script_code,
|
||||
&api_key,
|
||||
@@ -858,36 +857,23 @@ impl ProviderService {
|
||||
}
|
||||
|
||||
/// 测试用量脚本(使用临时脚本内容,不保存)
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn test_usage_script(
|
||||
state: &AppState,
|
||||
app_type: AppType,
|
||||
provider_id: &str,
|
||||
_state: &AppState,
|
||||
_app_type: AppType,
|
||||
_provider_id: &str,
|
||||
script_code: &str,
|
||||
timeout: u64,
|
||||
api_key: Option<&str>,
|
||||
base_url: Option<&str>,
|
||||
access_token: Option<&str>,
|
||||
user_id: Option<&str>,
|
||||
) -> Result<UsageResult, AppError> {
|
||||
// 获取 provider 的 API 凭证
|
||||
let provider = {
|
||||
let config = state.config.read().map_err(AppError::from)?;
|
||||
let manager = config
|
||||
.get_manager(&app_type)
|
||||
.ok_or_else(|| Self::app_not_found(&app_type))?;
|
||||
manager.providers.get(provider_id).cloned().ok_or_else(|| {
|
||||
AppError::localized(
|
||||
"provider.not_found",
|
||||
format!("供应商不存在: {}", provider_id),
|
||||
format!("Provider not found: {}", provider_id),
|
||||
)
|
||||
})?
|
||||
};
|
||||
|
||||
let (api_key, base_url) = Self::extract_credentials(&provider, &app_type)?;
|
||||
|
||||
// 直接使用传入的凭证参数进行测试
|
||||
Self::execute_and_format_usage_result(
|
||||
script_code,
|
||||
&api_key,
|
||||
&base_url,
|
||||
api_key.unwrap_or(""),
|
||||
base_url.unwrap_or(""),
|
||||
timeout,
|
||||
access_token,
|
||||
user_id,
|
||||
@@ -1137,6 +1123,7 @@ impl ProviderService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn extract_credentials(
|
||||
provider: &Provider,
|
||||
app_type: &AppType,
|
||||
|
||||
Reference in New Issue
Block a user