refactor(audit): 移除旧格式兼容,user_id 统一走列字段
- audit_log 查询去掉 detail->>'user_id' 回退分支 - login_detail 不再冗余写入 user_id 到 detail JSON - 迁移 SQL 去掉多余的 ALTER TABLE ADD COLUMN Made-with: Cursor
This commit is contained in:
@@ -10,14 +10,8 @@ pub fn current_actor() -> String {
|
|||||||
std::env::var("USER").unwrap_or_default()
|
std::env::var("USER").unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn login_detail(
|
fn login_detail(provider: &str, client_ip: Option<&str>, user_agent: Option<&str>) -> Value {
|
||||||
user_id: Uuid,
|
|
||||||
provider: &str,
|
|
||||||
client_ip: Option<&str>,
|
|
||||||
user_agent: Option<&str>,
|
|
||||||
) -> Value {
|
|
||||||
json!({
|
json!({
|
||||||
"user_id": user_id,
|
|
||||||
"provider": provider,
|
"provider": provider,
|
||||||
"client_ip": client_ip,
|
"client_ip": client_ip,
|
||||||
"user_agent": user_agent,
|
"user_agent": user_agent,
|
||||||
@@ -34,7 +28,7 @@ pub async fn log_login(
|
|||||||
user_agent: Option<&str>,
|
user_agent: Option<&str>,
|
||||||
) {
|
) {
|
||||||
let actor = current_actor();
|
let actor = current_actor();
|
||||||
let detail = login_detail(user_id, provider, client_ip, user_agent);
|
let detail = login_detail(provider, client_ip, user_agent);
|
||||||
let result: Result<_, sqlx::Error> = sqlx::query(
|
let result: Result<_, sqlx::Error> = sqlx::query(
|
||||||
"INSERT INTO audit_log (user_id, action, namespace, kind, name, detail, actor) \
|
"INSERT INTO audit_log (user_id, action, namespace, kind, name, detail, actor) \
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||||
@@ -94,10 +88,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn login_detail_includes_expected_fields() {
|
fn login_detail_includes_expected_fields() {
|
||||||
let user_id = Uuid::nil();
|
let detail = login_detail("google", Some("127.0.0.1"), Some("Mozilla/5.0"));
|
||||||
let detail = login_detail(user_id, "google", Some("127.0.0.1"), Some("Mozilla/5.0"));
|
|
||||||
|
|
||||||
assert_eq!(detail["user_id"], json!(user_id));
|
|
||||||
assert_eq!(detail["provider"], "google");
|
assert_eq!(detail["provider"], "google");
|
||||||
assert_eq!(detail["client_ip"], "127.0.0.1");
|
assert_eq!(detail["client_ip"], "127.0.0.1");
|
||||||
assert_eq!(detail["user_agent"], "Mozilla/5.0");
|
assert_eq!(detail["user_agent"], "Mozilla/5.0");
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ pub async fn migrate(pool: &PgPool) -> Result<()> {
|
|||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
);
|
);
|
||||||
|
|
||||||
ALTER TABLE audit_log ADD COLUMN IF NOT EXISTS user_id UUID;
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at DESC);
|
CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at DESC);
|
||||||
CREATE INDEX IF NOT EXISTS idx_audit_log_ns_kind ON audit_log(namespace, kind);
|
CREATE INDEX IF NOT EXISTS idx_audit_log_ns_kind ON audit_log(namespace, kind);
|
||||||
CREATE INDEX IF NOT EXISTS idx_audit_log_user_id ON audit_log(user_id) WHERE user_id IS NOT NULL;
|
CREATE INDEX IF NOT EXISTS idx_audit_log_user_id ON audit_log(user_id) WHERE user_id IS NOT NULL;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ pub async fn list_for_user(pool: &PgPool, user_id: Uuid, limit: i64) -> Result<V
|
|||||||
let rows = sqlx::query_as(
|
let rows = sqlx::query_as(
|
||||||
"SELECT id, user_id, action, namespace, kind, name, detail, actor, created_at \
|
"SELECT id, user_id, action, namespace, kind, name, detail, actor, created_at \
|
||||||
FROM audit_log \
|
FROM audit_log \
|
||||||
WHERE user_id = $1 OR (user_id IS NULL AND detail->>'user_id' = $1::text) \
|
WHERE user_id = $1 \
|
||||||
ORDER BY created_at DESC, id DESC \
|
ORDER BY created_at DESC, id DESC \
|
||||||
LIMIT $2",
|
LIMIT $2",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user