mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
Fix OAuth import proxy handling
This commit is contained in:
@@ -4,11 +4,15 @@ use super::parse::{
|
||||
parse_admin_provider_oauth_batch_import_entries, AdminProviderOAuthBatchImportEntry,
|
||||
AdminProviderOAuthBatchImportOutcome,
|
||||
};
|
||||
use super::progress::{
|
||||
maybe_report_admin_provider_oauth_batch_import_progress,
|
||||
AdminProviderOAuthBatchProgressReporter,
|
||||
};
|
||||
use crate::handlers::admin::provider::oauth::duplicates::find_duplicate_provider_oauth_key;
|
||||
use crate::handlers::admin::provider::oauth::provisioning::build_provider_oauth_auth_config_from_token_payload;
|
||||
use crate::handlers::admin::provider::oauth::provisioning::{
|
||||
create_provider_oauth_catalog_key, provider_oauth_active_api_formats,
|
||||
update_existing_provider_oauth_catalog_key,
|
||||
provider_oauth_key_proxy_value, update_existing_provider_oauth_catalog_key,
|
||||
};
|
||||
use crate::handlers::admin::provider::oauth::runtime::{
|
||||
provider_oauth_runtime_endpoint_for_provider,
|
||||
@@ -41,6 +45,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import_for_provider_type(
|
||||
provider_type: &str,
|
||||
raw_credentials: &str,
|
||||
proxy_node_id: Option<&str>,
|
||||
progress: Option<&mut dyn AdminProviderOAuthBatchProgressReporter>,
|
||||
) -> Result<AdminProviderOAuthBatchImportOutcome, GatewayError> {
|
||||
if provider_type.eq_ignore_ascii_case("kiro") {
|
||||
execute_admin_provider_oauth_kiro_batch_import(
|
||||
@@ -48,6 +53,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import_for_provider_type(
|
||||
provider_id,
|
||||
raw_credentials,
|
||||
proxy_node_id,
|
||||
progress,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
@@ -58,6 +64,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import_for_provider_type(
|
||||
provider_type,
|
||||
&entries,
|
||||
proxy_node_id,
|
||||
progress,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -69,6 +76,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
provider_type: &str,
|
||||
entries: &[AdminProviderOAuthBatchImportEntry],
|
||||
proxy_node_id: Option<&str>,
|
||||
mut progress: Option<&mut dyn AdminProviderOAuthBatchProgressReporter>,
|
||||
) -> Result<AdminProviderOAuthBatchImportOutcome, GatewayError> {
|
||||
let Some(provider) = state
|
||||
.read_provider_catalog_providers_by_ids(&[provider_id.to_string()])
|
||||
@@ -131,6 +139,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
],
|
||||
)
|
||||
.await;
|
||||
let key_proxy = provider_oauth_key_proxy_value(proxy_node_id);
|
||||
let mut results = Vec::with_capacity(entries.len());
|
||||
let mut success = 0usize;
|
||||
let mut failed = 0usize;
|
||||
@@ -156,6 +165,14 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
),
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@@ -170,6 +187,14 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
"error": "Token 刷新返回缺少 access_token",
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -192,6 +217,14 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
"error": detail,
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@@ -205,7 +238,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
expires_at,
|
||||
)
|
||||
.await?
|
||||
@@ -219,6 +252,14 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
"error": "provider oauth write unavailable",
|
||||
"replaced": true,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +290,7 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
expires_at,
|
||||
)
|
||||
.await?
|
||||
@@ -263,6 +304,14 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
"error": "provider oauth write unavailable",
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -284,6 +333,14 @@ pub(super) async fn execute_admin_provider_oauth_batch_import(
|
||||
"error": serde_json::Value::Null,
|
||||
"replaced": replaced,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(AdminProviderOAuthBatchImportOutcome {
|
||||
|
||||
@@ -3,10 +3,14 @@ use super::super::kiro::{
|
||||
refresh_admin_provider_oauth_kiro_auth_config,
|
||||
};
|
||||
use super::parse::AdminProviderOAuthBatchImportOutcome;
|
||||
use super::progress::{
|
||||
maybe_report_admin_provider_oauth_batch_import_progress,
|
||||
AdminProviderOAuthBatchProgressReporter,
|
||||
};
|
||||
use crate::handlers::admin::provider::oauth::duplicates::find_duplicate_provider_oauth_key;
|
||||
use crate::handlers::admin::provider::oauth::provisioning::{
|
||||
create_provider_oauth_catalog_key, provider_oauth_active_api_formats,
|
||||
update_existing_provider_oauth_catalog_key,
|
||||
provider_oauth_key_proxy_value, update_existing_provider_oauth_catalog_key,
|
||||
};
|
||||
use crate::handlers::admin::provider::oauth::runtime::{
|
||||
provider_oauth_runtime_endpoint_for_provider,
|
||||
@@ -27,6 +31,7 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
provider_id: &str,
|
||||
raw_credentials: &str,
|
||||
proxy_node_id: Option<&str>,
|
||||
mut progress: Option<&mut dyn AdminProviderOAuthBatchProgressReporter>,
|
||||
) -> Result<AdminProviderOAuthBatchImportOutcome, GatewayError> {
|
||||
let entries = parse_admin_provider_oauth_kiro_batch_import_entries(raw_credentials);
|
||||
let Some(provider) = state
|
||||
@@ -70,6 +75,7 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
],
|
||||
)
|
||||
.await;
|
||||
let key_proxy = provider_oauth_key_proxy_value(proxy_node_id);
|
||||
let social_refresh_base_url =
|
||||
admin_provider_oauth_kiro_refresh_base_url_override(state, "kiro_social_refresh");
|
||||
let idc_refresh_base_url =
|
||||
@@ -87,6 +93,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": "未找到有效的凭据数据",
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -103,6 +117,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": "缺少可用的 Kiro refresh 凭据",
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -124,6 +146,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": format!("Token 验证失败: {err}"),
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@@ -166,6 +196,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": detail,
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@@ -184,6 +222,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": "Token 验证失败: accessToken 为空",
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -196,7 +242,7 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
refreshed_auth_config.expires_at,
|
||||
)
|
||||
.await?
|
||||
@@ -210,6 +256,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": "provider oauth write unavailable",
|
||||
"replaced": true,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -231,7 +285,7 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
refreshed_auth_config.expires_at,
|
||||
)
|
||||
.await?
|
||||
@@ -245,6 +299,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": "provider oauth write unavailable",
|
||||
"replaced": false,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -271,6 +333,14 @@ pub(super) async fn execute_admin_provider_oauth_kiro_batch_import(
|
||||
"error": serde_json::Value::Null,
|
||||
"replaced": replaced,
|
||||
}));
|
||||
maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
&mut progress,
|
||||
entries.len(),
|
||||
success,
|
||||
failed,
|
||||
&results,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(AdminProviderOAuthBatchImportOutcome {
|
||||
|
||||
@@ -2,6 +2,7 @@ mod execution;
|
||||
mod kiro_import;
|
||||
mod orchestration;
|
||||
mod parse;
|
||||
mod progress;
|
||||
mod task;
|
||||
|
||||
pub(super) use orchestration::handle_admin_provider_oauth_batch_import;
|
||||
|
||||
@@ -81,6 +81,7 @@ pub(in super::super) async fn handle_admin_provider_oauth_batch_import(
|
||||
&provider_type,
|
||||
payload.credentials.as_str(),
|
||||
payload.proxy_node_id.as_deref(),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
Ok(build_admin_provider_oauth_batch_import_response(&outcome).into_response())
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct AdminProviderOAuthBatchImportProgress {
|
||||
pub total: usize,
|
||||
pub processed: usize,
|
||||
pub success: usize,
|
||||
pub failed: usize,
|
||||
pub created_count: usize,
|
||||
pub replaced_count: usize,
|
||||
pub latest_result: Option<Value>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub(super) trait AdminProviderOAuthBatchProgressReporter: Send {
|
||||
async fn report(&mut self, progress: AdminProviderOAuthBatchImportProgress);
|
||||
}
|
||||
|
||||
pub(super) async fn maybe_report_admin_provider_oauth_batch_import_progress(
|
||||
reporter: &mut Option<&mut dyn AdminProviderOAuthBatchProgressReporter>,
|
||||
total: usize,
|
||||
success: usize,
|
||||
failed: usize,
|
||||
results: &[Value],
|
||||
) {
|
||||
let Some(reporter) = reporter.as_deref_mut() else {
|
||||
return;
|
||||
};
|
||||
let replaced_count = results
|
||||
.iter()
|
||||
.filter(|item| {
|
||||
item.get("status").and_then(Value::as_str) == Some("success")
|
||||
&& item.get("replaced").and_then(Value::as_bool) == Some(true)
|
||||
})
|
||||
.count();
|
||||
reporter
|
||||
.report(AdminProviderOAuthBatchImportProgress {
|
||||
total,
|
||||
processed: success.saturating_add(failed).min(total),
|
||||
success,
|
||||
failed,
|
||||
created_count: success.saturating_sub(replaced_count),
|
||||
replaced_count,
|
||||
latest_result: results.last().cloned(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -5,6 +5,9 @@ use super::execution::{
|
||||
use super::parse::{
|
||||
build_admin_provider_oauth_batch_task_state, parse_admin_provider_oauth_batch_import_request,
|
||||
};
|
||||
use super::progress::{
|
||||
AdminProviderOAuthBatchImportProgress, AdminProviderOAuthBatchProgressReporter,
|
||||
};
|
||||
use crate::handlers::admin::provider::oauth::errors::build_internal_control_error_response;
|
||||
use crate::handlers::admin::provider::oauth::state::{
|
||||
admin_provider_oauth_template, build_admin_provider_oauth_backend_unavailable_response,
|
||||
@@ -26,6 +29,55 @@ use uuid::Uuid;
|
||||
|
||||
const PROVIDER_OAUTH_BATCH_TASK_MAX_ERROR_SAMPLES: usize = 20;
|
||||
|
||||
struct BatchTaskProgressReporter {
|
||||
app: crate::AppState,
|
||||
task_id: String,
|
||||
provider_id: String,
|
||||
provider_type: String,
|
||||
created_at: u64,
|
||||
started_at: u64,
|
||||
error_samples: Vec<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AdminProviderOAuthBatchProgressReporter for BatchTaskProgressReporter {
|
||||
async fn report(&mut self, progress: AdminProviderOAuthBatchImportProgress) {
|
||||
if let Some(latest_result) = progress.latest_result.as_ref() {
|
||||
if latest_result
|
||||
.get("status")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
== Some("error")
|
||||
&& self.error_samples.len() < PROVIDER_OAUTH_BATCH_TASK_MAX_ERROR_SAMPLES
|
||||
{
|
||||
self.error_samples.push(latest_result.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let message = format!("处理中 {}/{}", progress.processed, progress.total);
|
||||
let progress_state = build_admin_provider_oauth_batch_task_state(
|
||||
&self.task_id,
|
||||
&self.provider_id,
|
||||
&self.provider_type,
|
||||
"processing",
|
||||
progress.total,
|
||||
progress.processed,
|
||||
progress.success,
|
||||
progress.failed,
|
||||
progress.created_count,
|
||||
progress.replaced_count,
|
||||
Some(message.as_str()),
|
||||
None,
|
||||
self.error_samples.clone(),
|
||||
self.created_at,
|
||||
Some(self.started_at),
|
||||
None,
|
||||
);
|
||||
let _ = AdminAppState::new(&self.app)
|
||||
.save_provider_oauth_batch_task_payload(&self.task_id, &progress_state)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
pub(in super::super) async fn handle_admin_provider_oauth_start_batch_import_task(
|
||||
state: &AdminAppState<'_>,
|
||||
request_context: &AdminRequestContext<'_>,
|
||||
@@ -149,12 +201,22 @@ pub(in super::super) async fn handle_admin_provider_oauth_start_batch_import_tas
|
||||
.save_provider_oauth_batch_task_payload(&task_id_for_worker, &processing_state)
|
||||
.await;
|
||||
|
||||
let mut progress_reporter = BatchTaskProgressReporter {
|
||||
app: task_state.clone(),
|
||||
task_id: task_id_for_worker.clone(),
|
||||
provider_id: provider_id_for_worker.clone(),
|
||||
provider_type: provider_type_for_worker.clone(),
|
||||
created_at,
|
||||
started_at,
|
||||
error_samples: Vec::new(),
|
||||
};
|
||||
match execute_admin_provider_oauth_batch_import_for_provider_type(
|
||||
&AdminAppState::new(&task_state),
|
||||
&provider_id_for_worker,
|
||||
&provider_type_for_worker,
|
||||
raw_credentials.as_str(),
|
||||
proxy_node_id.as_deref(),
|
||||
Some(&mut progress_reporter),
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
||||
@@ -2,7 +2,8 @@ use super::super::super::duplicates::find_duplicate_provider_oauth_key;
|
||||
use super::super::super::errors::build_internal_control_error_response;
|
||||
use super::super::super::provisioning::{
|
||||
build_provider_oauth_auth_config_from_token_payload, create_provider_oauth_catalog_key,
|
||||
provider_oauth_active_api_formats, update_existing_provider_oauth_catalog_key,
|
||||
provider_oauth_active_api_formats, provider_oauth_key_proxy_value,
|
||||
update_existing_provider_oauth_catalog_key,
|
||||
};
|
||||
use super::super::super::runtime::{
|
||||
provider_oauth_runtime_endpoint_for_provider,
|
||||
@@ -131,6 +132,7 @@ pub(super) async fn handle_admin_provider_oauth_complete_provider(
|
||||
],
|
||||
)
|
||||
.await;
|
||||
let key_proxy = provider_oauth_key_proxy_value(payload.proxy_node_id.as_deref());
|
||||
|
||||
let token_payload = match state
|
||||
.exchange_admin_provider_oauth_code(
|
||||
@@ -178,7 +180,7 @@ pub(super) async fn handle_admin_provider_oauth_complete_provider(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
expires_at,
|
||||
)
|
||||
.await?
|
||||
@@ -220,7 +222,7 @@ pub(super) async fn handle_admin_provider_oauth_complete_provider(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
expires_at,
|
||||
)
|
||||
.await?
|
||||
|
||||
@@ -2,7 +2,8 @@ use super::super::duplicates::find_duplicate_provider_oauth_key;
|
||||
use super::super::errors::build_internal_control_error_response;
|
||||
use super::super::provisioning::{
|
||||
build_provider_oauth_auth_config_from_token_payload, create_provider_oauth_catalog_key,
|
||||
provider_oauth_active_api_formats, update_existing_provider_oauth_catalog_key,
|
||||
provider_oauth_active_api_formats, provider_oauth_key_proxy_value,
|
||||
update_existing_provider_oauth_catalog_key,
|
||||
};
|
||||
use super::super::runtime::{
|
||||
provider_oauth_runtime_endpoint_for_provider,
|
||||
@@ -119,6 +120,7 @@ pub(super) async fn handle_admin_provider_oauth_import_refresh_token(
|
||||
],
|
||||
)
|
||||
.await;
|
||||
let key_proxy = provider_oauth_key_proxy_value(proxy_node_id.as_deref());
|
||||
|
||||
let token_payload = match state
|
||||
.exchange_admin_provider_oauth_refresh_token(
|
||||
@@ -170,7 +172,7 @@ pub(super) async fn handle_admin_provider_oauth_import_refresh_token(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
expires_at,
|
||||
)
|
||||
.await?
|
||||
@@ -211,7 +213,7 @@ pub(super) async fn handle_admin_provider_oauth_import_refresh_token(
|
||||
&access_token,
|
||||
&auth_config,
|
||||
&api_formats,
|
||||
None,
|
||||
key_proxy.clone(),
|
||||
expires_at,
|
||||
)
|
||||
.await?
|
||||
|
||||
Reference in New Issue
Block a user