feat(saas): Phase 4 — 配置迁移模块
- 配置项 CRUD (列表/详情/创建/更新/删除) - 配置分析端点 (按类别汇总, SaaS 托管统计) - 13 个默认配置项种子数据 (server/agent/memory/llm) - 配置同步协议 (客户端→SaaS, SaaS 优先策略) - 同步日志记录和查询 - 3 个新集成测试覆盖配置迁移端点
This commit is contained in:
104
crates/zclaw-saas/src/migration/handlers.rs
Normal file
104
crates/zclaw-saas/src/migration/handlers.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
//! 配置迁移 HTTP 处理器
|
||||
|
||||
use axum::{
|
||||
extract::{Extension, Path, Query, State},
|
||||
http::StatusCode, Json,
|
||||
};
|
||||
use crate::state::AppState;
|
||||
use crate::error::SaasResult;
|
||||
use crate::auth::types::AuthContext;
|
||||
use super::{types::*, service};
|
||||
|
||||
/// GET /api/v1/config/items?category=xxx&source=xxx
|
||||
pub async fn list_config_items(
|
||||
State(state): State<AppState>,
|
||||
Query(query): Query<ConfigQuery>,
|
||||
_ctx: Extension<AuthContext>,
|
||||
) -> SaasResult<Json<Vec<ConfigItemInfo>>> {
|
||||
service::list_config_items(&state.db, &query).await.map(Json)
|
||||
}
|
||||
|
||||
/// GET /api/v1/config/items/:id
|
||||
pub async fn get_config_item(
|
||||
State(state): State<AppState>,
|
||||
Path(id): Path<String>,
|
||||
_ctx: Extension<AuthContext>,
|
||||
) -> SaasResult<Json<ConfigItemInfo>> {
|
||||
service::get_config_item(&state.db, &id).await.map(Json)
|
||||
}
|
||||
|
||||
/// POST /api/v1/config/items (admin only)
|
||||
pub async fn create_config_item(
|
||||
State(state): State<AppState>,
|
||||
Extension(ctx): Extension<AuthContext>,
|
||||
Json(req): Json<CreateConfigItemRequest>,
|
||||
) -> SaasResult<(StatusCode, Json<ConfigItemInfo>)> {
|
||||
if !ctx.permissions.contains(&"config:manage".to_string()) {
|
||||
return Err(crate::error::SaasError::Forbidden("需要 config:manage 权限".into()));
|
||||
}
|
||||
let item = service::create_config_item(&state.db, &req).await?;
|
||||
Ok((StatusCode::CREATED, Json(item)))
|
||||
}
|
||||
|
||||
/// PUT /api/v1/config/items/:id (admin only)
|
||||
pub async fn update_config_item(
|
||||
State(state): State<AppState>,
|
||||
Path(id): Path<String>,
|
||||
Extension(ctx): Extension<AuthContext>,
|
||||
Json(req): Json<UpdateConfigItemRequest>,
|
||||
) -> SaasResult<Json<ConfigItemInfo>> {
|
||||
if !ctx.permissions.contains(&"config:manage".to_string()) {
|
||||
return Err(crate::error::SaasError::Forbidden("需要 config:manage 权限".into()));
|
||||
}
|
||||
service::update_config_item(&state.db, &id, &req).await.map(Json)
|
||||
}
|
||||
|
||||
/// DELETE /api/v1/config/items/:id (admin only)
|
||||
pub async fn delete_config_item(
|
||||
State(state): State<AppState>,
|
||||
Path(id): Path<String>,
|
||||
Extension(ctx): Extension<AuthContext>,
|
||||
) -> SaasResult<Json<serde_json::Value>> {
|
||||
if !ctx.permissions.contains(&"config:manage".to_string()) {
|
||||
return Err(crate::error::SaasError::Forbidden("需要 config:manage 权限".into()));
|
||||
}
|
||||
service::delete_config_item(&state.db, &id).await?;
|
||||
Ok(Json(serde_json::json!({"ok": true})))
|
||||
}
|
||||
|
||||
/// GET /api/v1/config/analysis
|
||||
pub async fn analyze_config(
|
||||
State(state): State<AppState>,
|
||||
_ctx: Extension<AuthContext>,
|
||||
) -> SaasResult<Json<ConfigAnalysis>> {
|
||||
service::analyze_config(&state.db).await.map(Json)
|
||||
}
|
||||
|
||||
/// POST /api/v1/config/seed (admin only)
|
||||
pub async fn seed_config(
|
||||
State(state): State<AppState>,
|
||||
Extension(ctx): Extension<AuthContext>,
|
||||
) -> SaasResult<Json<serde_json::Value>> {
|
||||
if !ctx.permissions.contains(&"config:manage".to_string()) {
|
||||
return Err(crate::error::SaasError::Forbidden("需要 config:manage 权限".into()));
|
||||
}
|
||||
let count = service::seed_default_config_items(&state.db).await?;
|
||||
Ok(Json(serde_json::json!({"created": count})))
|
||||
}
|
||||
|
||||
/// POST /api/v1/config/sync
|
||||
pub async fn sync_config(
|
||||
State(state): State<AppState>,
|
||||
Extension(ctx): Extension<AuthContext>,
|
||||
Json(req): Json<SyncConfigRequest>,
|
||||
) -> SaasResult<Json<Vec<ConfigSyncLogInfo>>> {
|
||||
service::sync_config(&state.db, &ctx.account_id, &req).await.map(Json)
|
||||
}
|
||||
|
||||
/// GET /api/v1/config/sync-logs
|
||||
pub async fn list_sync_logs(
|
||||
State(state): State<AppState>,
|
||||
Extension(ctx): Extension<AuthContext>,
|
||||
) -> SaasResult<Json<Vec<ConfigSyncLogInfo>>> {
|
||||
service::list_sync_logs(&state.db, &ctx.account_id).await.map(Json)
|
||||
}
|
||||
Reference in New Issue
Block a user