- Run cargo fmt on all Rust crates for consistent formatting - Update CLAUDE.md with WASM plugin commands and dev.ps1 instructions - Update wiki: add WASM plugin architecture, rewrite dev environment docs - Minor frontend cleanup (unused imports)
79 lines
2.3 KiB
Rust
79 lines
2.3 KiB
Rust
use axum::Router;
|
|
use axum::extract::{Extension, FromRef, Query, State};
|
|
use axum::response::Json;
|
|
use axum::routing::get;
|
|
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder};
|
|
use serde::Deserialize;
|
|
|
|
use erp_core::entity::audit_log;
|
|
use erp_core::error::AppError;
|
|
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
|
|
|
/// 审计日志查询参数。
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct AuditLogQuery {
|
|
pub resource_type: Option<String>,
|
|
pub user_id: Option<uuid::Uuid>,
|
|
pub page: Option<u64>,
|
|
pub page_size: Option<u64>,
|
|
}
|
|
|
|
/// GET /audit-logs
|
|
///
|
|
/// 分页查询审计日志,支持按 resource_type 和 user_id 过滤。
|
|
/// 租户隔离通过 JWT 中间件注入的 TenantContext 实现。
|
|
pub async fn list_audit_logs<S>(
|
|
State(db): State<sea_orm::DatabaseConnection>,
|
|
Extension(ctx): Extension<TenantContext>,
|
|
Query(params): Query<AuditLogQuery>,
|
|
) -> Result<Json<ApiResponse<PaginatedResponse<audit_log::Model>>>, AppError>
|
|
where
|
|
sea_orm::DatabaseConnection: FromRef<S>,
|
|
S: Clone + Send + Sync + 'static,
|
|
{
|
|
let page = params.page.unwrap_or(1).max(1);
|
|
let page_size = params.page_size.unwrap_or(20).min(100);
|
|
let tenant_id = ctx.tenant_id;
|
|
|
|
let mut q = audit_log::Entity::find().filter(audit_log::Column::TenantId.eq(tenant_id));
|
|
|
|
if let Some(rt) = ¶ms.resource_type {
|
|
q = q.filter(audit_log::Column::ResourceType.eq(rt.clone()));
|
|
}
|
|
if let Some(uid) = ¶ms.user_id {
|
|
q = q.filter(audit_log::Column::UserId.eq(*uid));
|
|
}
|
|
|
|
let paginator = q
|
|
.order_by_desc(audit_log::Column::CreatedAt)
|
|
.paginate(&db, page_size);
|
|
|
|
let total = paginator
|
|
.num_items()
|
|
.await
|
|
.map_err(|e| AppError::Internal(format!("查询审计日志失败: {e}")))?;
|
|
|
|
let items = paginator
|
|
.fetch_page(page - 1)
|
|
.await
|
|
.map_err(|e| AppError::Internal(format!("查询审计日志失败: {e}")))?;
|
|
|
|
let total_pages = total.div_ceil(page_size);
|
|
|
|
Ok(Json(ApiResponse::ok(PaginatedResponse {
|
|
data: items,
|
|
total,
|
|
page,
|
|
page_size,
|
|
total_pages,
|
|
})))
|
|
}
|
|
|
|
pub fn audit_log_router<S>() -> Router<S>
|
|
where
|
|
sea_orm::DatabaseConnection: FromRef<S>,
|
|
S: Clone + Send + Sync + 'static,
|
|
{
|
|
Router::new().route("/audit-logs", get(list_audit_logs))
|
|
}
|