Files
secrets/crates/secrets-core/src/service/history.rs
voson f720983328
Some checks failed
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been cancelled
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Has started running
refactor(db): 移除无意义 actor,修复 history 多租户与模型
- 删除 entries_history / audit_log / secrets_history 的 actor 列及写入逻辑
- MCP secrets_history 透传当前 user_id
- Entry 增加 user_id,search 查询不再用伪 UUID
- 迁移:保留 users.api_key,从 api_keys 表回退时生成新明文 key 并删表
- 文档:audit_log auth 语义、API Key 存储说明

Made-with: Cursor
2026-03-21 16:45:50 +08:00

76 lines
1.8 KiB
Rust

use anyhow::Result;
use serde_json::Value;
use sqlx::PgPool;
use uuid::Uuid;
#[derive(Debug, serde::Serialize)]
pub struct HistoryEntry {
pub version: i64,
pub action: String,
pub created_at: String,
}
pub async fn run(
pool: &PgPool,
namespace: &str,
kind: &str,
name: &str,
limit: u32,
user_id: Option<Uuid>,
) -> Result<Vec<HistoryEntry>> {
#[derive(sqlx::FromRow)]
struct Row {
version: i64,
action: String,
created_at: chrono::DateTime<chrono::Utc>,
}
let rows: Vec<Row> = if let Some(uid) = user_id {
sqlx::query_as(
"SELECT version, action, created_at FROM entries_history \
WHERE namespace = $1 AND kind = $2 AND name = $3 AND user_id = $4 \
ORDER BY id DESC LIMIT $5",
)
.bind(namespace)
.bind(kind)
.bind(name)
.bind(uid)
.bind(limit as i64)
.fetch_all(pool)
.await?
} else {
sqlx::query_as(
"SELECT version, action, created_at FROM entries_history \
WHERE namespace = $1 AND kind = $2 AND name = $3 AND user_id IS NULL \
ORDER BY id DESC LIMIT $4",
)
.bind(namespace)
.bind(kind)
.bind(name)
.bind(limit as i64)
.fetch_all(pool)
.await?
};
Ok(rows
.into_iter()
.map(|r| HistoryEntry {
version: r.version,
action: r.action,
created_at: r.created_at.format("%Y-%m-%dT%H:%M:%SZ").to_string(),
})
.collect())
}
pub async fn run_json(
pool: &PgPool,
namespace: &str,
kind: &str,
name: &str,
limit: u32,
user_id: Option<Uuid>,
) -> Result<Value> {
let entries = run(pool, namespace, kind, name, limit, user_id).await?;
Ok(serde_json::to_value(entries)?)
}