Skip to content
Clone
main
47 lines 1.5 KB Rust
//! 统一的用户事件审计写入:手拼 ActiveModel 的调用点都收口到这里。
use sea_orm::ActiveModelTrait;
use serde_json::Value;
use crate::db::DbConn;
use crate::models::users::user_events::{self, UserEventType};
use crate::errors::AuthResult;
pub fn current_request_id() -> String {
envelope::context::request_id().unwrap_or_else(envelope::new_request_id)
}
/// 写一条用户事件;事件总线之外的持久审计兜底。
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all, fields(user_id = user_id, request_id = tracing::field::Empty))]
pub async fn entry(
db: &DbConn,
user_id: i64,
actor_user_id: Option<i64>,
event_type: UserEventType,
details: Option<Value>,
request_id: Option<&str>,
client_ip: Option<String>,
user_agent: Option<String>,
) -> AuthResult<()> {
let request_id = request_id
.filter(|value| !value.is_empty())
.map(str::to_owned)
.or_else(envelope::context::request_id);
tracing::Span::current().record("request_id", request_id.as_deref().unwrap_or_default());
user_events::ActiveModel {
user_id: sea_orm::Set(user_id),
actor_user_id: sea_orm::Set(actor_user_id),
event_type: sea_orm::Set(event_type),
occurred_at: sea_orm::Set(chrono::Utc::now()),
ip_address: sea_orm::Set(client_ip),
user_agent: sea_orm::Set(user_agent),
details: sea_orm::Set(details),
trace_id: sea_orm::Set(request_id),
..Default::default()
}
.insert(db.write())
.await?;
Ok(())
}