feat: 审计日志搜索从用户ID改为用户名模糊匹配

Closes #104

Co-authored-by: AAEE86 <ppk0227@hotmail.com>
This commit is contained in:
fawney19
2026-01-17 20:40:21 +08:00
parent 8053cbd854
commit 4fa0201b7e
3 changed files with 18 additions and 16 deletions

View File

@@ -26,7 +26,7 @@ export interface AuditLogsResponse {
}
export interface AuditFilters {
user_id?: string
username?: string
event_type?: string
days?: number
limit?: number

View File

@@ -23,7 +23,7 @@
<Input
id="audit-logs-search"
v-model="searchQuery"
placeholder="搜索用户ID..."
placeholder="搜索用户..."
class="w-32 sm:w-64 h-8 text-sm pl-8"
@input="handleSearchChange"
/>
@@ -473,7 +473,7 @@ const eventTypeSelectOpen = ref(false)
const daysSelectOpen = ref(false)
const filters = ref({
userId: '',
username: '',
eventType: '__all__',
days: 7,
limit: 50
@@ -503,7 +503,7 @@ async function loadLogs() {
const offset = (currentPage.value - 1) * pageSize.value
const filterParams = {
user_id: filters.value.userId || undefined,
username: filters.value.username || undefined,
event_type: (filters.value.eventType !== '__all__' ? filters.value.eventType : undefined),
days: filters.value.days,
limit: pageSize.value,
@@ -528,14 +528,14 @@ function refreshLogs() {
// 搜索变化处理
function handleSearchChange() {
filters.value.userId = searchQuery.value
filters.value.username = searchQuery.value
debouncedLoadLogs()
}
// 重置筛选条件
function handleResetFilters() {
searchQuery.value = ''
filters.value.userId = ''
filters.value.username = ''
filters.value.eventType = '__all__'
filters.value.days = 7
filtersDaysString.value = '7'
@@ -574,7 +574,7 @@ async function exportLogs() {
while (hasMore) {
const data = await auditApi.getAuditLogs({
user_id: filters.value.userId || undefined,
username: filters.value.username || undefined,
event_type: filters.value.eventType !== '__all__' ? filters.value.eventType : undefined,
days: filters.value.days,
limit: batchSize,

View File

@@ -23,6 +23,7 @@ from src.models.database import (
from src.models.database import User as DBUser
from src.services.health.monitor import HealthMonitor
from src.services.system.audit import audit_service
from src.utils.database_helpers import escape_like_pattern
router = APIRouter(prefix="/api/admin/monitoring", tags=["Admin - Monitoring"])
@@ -32,7 +33,7 @@ pipeline = ApiRequestPipeline()
@router.get("/audit-logs")
async def get_audit_logs(
request: Request,
user_id: Optional[str] = Query(None, description="用户ID筛选 (支持UUID)"),
username: Optional[str] = Query(None, description="用户筛选 (模糊匹配)"),
event_type: Optional[str] = Query(None, description="事件类型筛选"),
days: int = Query(7, description="查询天数"),
limit: int = Query(100, description="返回数量限制"),
@@ -42,10 +43,10 @@ async def get_audit_logs(
"""
获取审计日志
获取系统审计日志列表,支持按用户、事件类型、时间范围筛选。需要管理员权限。
获取系统审计日志列表,支持按用户、事件类型、时间范围筛选。需要管理员权限。
**查询参数**:
- `user_id`: 可选,用户 ID 筛选UUID 格式
- `username`: 可选,用户名筛选(模糊匹配
- `event_type`: 可选,事件类型筛选
- `days`: 查询最近多少天的日志,默认 7 天
- `limit`: 返回数量限制,默认 100
@@ -68,7 +69,7 @@ async def get_audit_logs(
- `filters`: 筛选条件
"""
adapter = AdminGetAuditLogsAdapter(
user_id=user_id,
username=username,
event_type=event_type,
days=days,
limit=limit,
@@ -211,7 +212,7 @@ async def get_circuit_history(
@dataclass
class AdminGetAuditLogsAdapter(AdminApiAdapter):
user_id: Optional[str]
username: Optional[str]
event_type: Optional[str]
days: int
limit: int
@@ -229,8 +230,9 @@ class AdminGetAuditLogsAdapter(AdminApiAdapter):
.outerjoin(DBUser, AuditLog.user_id == DBUser.id)
.filter(AuditLog.created_at >= cutoff_time)
)
if self.user_id:
base_query = base_query.filter(AuditLog.user_id == self.user_id)
if self.username:
escaped = escape_like_pattern(self.username)
base_query = base_query.filter(DBUser.username.ilike(f"%{escaped}%", escape="\\"))
if self.event_type:
base_query = base_query.filter(AuditLog.event_type == self.event_type)
@@ -264,14 +266,14 @@ class AdminGetAuditLogsAdapter(AdminApiAdapter):
items,
meta,
filters={
"user_id": self.user_id,
"username": self.username,
"event_type": self.event_type,
"days": self.days,
},
)
context.add_audit_metadata(
action="monitor_audit_logs",
filter_user_id=self.user_id,
filter_username=self.username,
filter_event_type=self.event_type,
days=self.days,
limit=self.limit,