fix(industry): 审计修复 — 4 CRITICAL + 5 HIGH 全部解决
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
C1: SaaS industry/service.rs SQL 注入风险 → 参数化查询 ($N 绑定) C2: INDUSTRY_CONFIGS 死链 → Kernel 共享 Arc 接通 ButlerRouter C3: IndustryListItem 缺 keywords_count → SQL 查询 + 类型补全 C4: set_account_industries 非事务性 → batch 验证 + 事务 DELETE+INSERT H8: Accounts.tsx mutate 竞态 → mutateAsync 顺序等待 H9: XML 注入未转义 → xml_escape() 辅助函数 H10: update_industry 覆盖 source → 保留原始值 H11: 面包屑缺少 /industries → 添加行业配置映射
This commit is contained in:
@@ -693,9 +693,11 @@ pub async fn viking_store_with_summaries(
|
||||
/// Load industry keywords into the ButlerRouter middleware.
|
||||
///
|
||||
/// Called from the frontend after fetching industry configs from SaaS.
|
||||
/// Updates the ButlerRouter's dynamic keyword source for routing.
|
||||
/// Updates the shared `industry_keywords` Arc on the Kernel, which the
|
||||
/// ButlerRouterMiddleware reads automatically (same Arc instance).
|
||||
#[tauri::command]
|
||||
pub async fn viking_load_industry_keywords(
|
||||
kernel_state: tauri::State<'_, crate::kernel_commands::KernelState>,
|
||||
configs: String,
|
||||
) -> Result<(), String> {
|
||||
let raw: Vec<IndustryConfigPayload> = serde_json::from_str(&configs)
|
||||
@@ -711,43 +713,25 @@ pub async fn viking_load_industry_keywords(
|
||||
})
|
||||
.collect();
|
||||
|
||||
// The ButlerRouter is in the kernel's middleware chain.
|
||||
// For now, log and store for future retrieval by the kernel.
|
||||
tracing::info!(
|
||||
"[viking_commands] Loading {} industry keyword configs",
|
||||
"[viking_commands] Loading {} industry keyword configs into Kernel",
|
||||
industry_configs.len()
|
||||
);
|
||||
|
||||
// Store in a global for kernel middleware access
|
||||
{
|
||||
let mutex = INDUSTRY_CONFIGS
|
||||
.get_or_init(|| async { std::sync::Mutex::new(Vec::new()) })
|
||||
.await;
|
||||
let mut guard = mutex.lock().map_err(|e| format!("Lock poisoned: {}", e))?;
|
||||
// Update through the Kernel's shared Arc (connected to ButlerRouterMiddleware)
|
||||
let kernel_guard = kernel_state.lock().await;
|
||||
if let Some(kernel) = kernel_guard.as_ref() {
|
||||
let shared = kernel.industry_keywords();
|
||||
let mut guard = shared.write().await;
|
||||
*guard = industry_configs;
|
||||
tracing::info!("[viking_commands] Industry keywords synced to ButlerRouter middleware");
|
||||
} else {
|
||||
tracing::warn!("[viking_commands] Kernel not initialized, industry keywords not loaded");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Global industry configs storage (accessed by kernel middleware)
|
||||
static INDUSTRY_CONFIGS: tokio::sync::OnceCell<std::sync::Mutex<Vec<zclaw_runtime::IndustryKeywordConfig>>> =
|
||||
tokio::sync::OnceCell::const_new();
|
||||
|
||||
/// Get the stored industry configs
|
||||
pub async fn get_industry_configs() -> Vec<zclaw_runtime::IndustryKeywordConfig> {
|
||||
let mutex = INDUSTRY_CONFIGS
|
||||
.get_or_init(|| async { std::sync::Mutex::new(Vec::new()) })
|
||||
.await;
|
||||
match mutex.lock() {
|
||||
Ok(guard) => guard.clone(),
|
||||
Err(e) => {
|
||||
tracing::warn!("[viking_commands] Industry configs lock poisoned: {}", e);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user