mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
feat: 审计日志搜索从用户ID改为用户名模糊匹配
Closes #104 Co-authored-by: AAEE86 <ppk0227@hotmail.com>
This commit is contained in:
@@ -26,7 +26,7 @@ export interface AuditLogsResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AuditFilters {
|
export interface AuditFilters {
|
||||||
user_id?: string
|
username?: string
|
||||||
event_type?: string
|
event_type?: string
|
||||||
days?: number
|
days?: number
|
||||||
limit?: number
|
limit?: number
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<Input
|
<Input
|
||||||
id="audit-logs-search"
|
id="audit-logs-search"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
placeholder="搜索用户ID..."
|
placeholder="搜索用户名..."
|
||||||
class="w-32 sm:w-64 h-8 text-sm pl-8"
|
class="w-32 sm:w-64 h-8 text-sm pl-8"
|
||||||
@input="handleSearchChange"
|
@input="handleSearchChange"
|
||||||
/>
|
/>
|
||||||
@@ -473,7 +473,7 @@ const eventTypeSelectOpen = ref(false)
|
|||||||
const daysSelectOpen = ref(false)
|
const daysSelectOpen = ref(false)
|
||||||
|
|
||||||
const filters = ref({
|
const filters = ref({
|
||||||
userId: '',
|
username: '',
|
||||||
eventType: '__all__',
|
eventType: '__all__',
|
||||||
days: 7,
|
days: 7,
|
||||||
limit: 50
|
limit: 50
|
||||||
@@ -503,7 +503,7 @@ async function loadLogs() {
|
|||||||
const offset = (currentPage.value - 1) * pageSize.value
|
const offset = (currentPage.value - 1) * pageSize.value
|
||||||
|
|
||||||
const filterParams = {
|
const filterParams = {
|
||||||
user_id: filters.value.userId || undefined,
|
username: filters.value.username || undefined,
|
||||||
event_type: (filters.value.eventType !== '__all__' ? filters.value.eventType : undefined),
|
event_type: (filters.value.eventType !== '__all__' ? filters.value.eventType : undefined),
|
||||||
days: filters.value.days,
|
days: filters.value.days,
|
||||||
limit: pageSize.value,
|
limit: pageSize.value,
|
||||||
@@ -528,14 +528,14 @@ function refreshLogs() {
|
|||||||
|
|
||||||
// 搜索变化处理
|
// 搜索变化处理
|
||||||
function handleSearchChange() {
|
function handleSearchChange() {
|
||||||
filters.value.userId = searchQuery.value
|
filters.value.username = searchQuery.value
|
||||||
debouncedLoadLogs()
|
debouncedLoadLogs()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置筛选条件
|
// 重置筛选条件
|
||||||
function handleResetFilters() {
|
function handleResetFilters() {
|
||||||
searchQuery.value = ''
|
searchQuery.value = ''
|
||||||
filters.value.userId = ''
|
filters.value.username = ''
|
||||||
filters.value.eventType = '__all__'
|
filters.value.eventType = '__all__'
|
||||||
filters.value.days = 7
|
filters.value.days = 7
|
||||||
filtersDaysString.value = '7'
|
filtersDaysString.value = '7'
|
||||||
@@ -574,7 +574,7 @@ async function exportLogs() {
|
|||||||
|
|
||||||
while (hasMore) {
|
while (hasMore) {
|
||||||
const data = await auditApi.getAuditLogs({
|
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,
|
event_type: filters.value.eventType !== '__all__' ? filters.value.eventType : undefined,
|
||||||
days: filters.value.days,
|
days: filters.value.days,
|
||||||
limit: batchSize,
|
limit: batchSize,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from src.models.database import (
|
|||||||
from src.models.database import User as DBUser
|
from src.models.database import User as DBUser
|
||||||
from src.services.health.monitor import HealthMonitor
|
from src.services.health.monitor import HealthMonitor
|
||||||
from src.services.system.audit import audit_service
|
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"])
|
router = APIRouter(prefix="/api/admin/monitoring", tags=["Admin - Monitoring"])
|
||||||
@@ -32,7 +33,7 @@ pipeline = ApiRequestPipeline()
|
|||||||
@router.get("/audit-logs")
|
@router.get("/audit-logs")
|
||||||
async def get_audit_logs(
|
async def get_audit_logs(
|
||||||
request: Request,
|
request: Request,
|
||||||
user_id: Optional[str] = Query(None, description="用户ID筛选 (支持UUID)"),
|
username: Optional[str] = Query(None, description="用户名筛选 (模糊匹配)"),
|
||||||
event_type: Optional[str] = Query(None, description="事件类型筛选"),
|
event_type: Optional[str] = Query(None, description="事件类型筛选"),
|
||||||
days: int = Query(7, description="查询天数"),
|
days: int = Query(7, description="查询天数"),
|
||||||
limit: int = Query(100, description="返回数量限制"),
|
limit: int = Query(100, description="返回数量限制"),
|
||||||
@@ -42,10 +43,10 @@ async def get_audit_logs(
|
|||||||
"""
|
"""
|
||||||
获取审计日志
|
获取审计日志
|
||||||
|
|
||||||
获取系统审计日志列表,支持按用户、事件类型、时间范围筛选。需要管理员权限。
|
获取系统审计日志列表,支持按用户名、事件类型、时间范围筛选。需要管理员权限。
|
||||||
|
|
||||||
**查询参数**:
|
**查询参数**:
|
||||||
- `user_id`: 可选,用户 ID 筛选(UUID 格式)
|
- `username`: 可选,用户名筛选(模糊匹配)
|
||||||
- `event_type`: 可选,事件类型筛选
|
- `event_type`: 可选,事件类型筛选
|
||||||
- `days`: 查询最近多少天的日志,默认 7 天
|
- `days`: 查询最近多少天的日志,默认 7 天
|
||||||
- `limit`: 返回数量限制,默认 100
|
- `limit`: 返回数量限制,默认 100
|
||||||
@@ -68,7 +69,7 @@ async def get_audit_logs(
|
|||||||
- `filters`: 筛选条件
|
- `filters`: 筛选条件
|
||||||
"""
|
"""
|
||||||
adapter = AdminGetAuditLogsAdapter(
|
adapter = AdminGetAuditLogsAdapter(
|
||||||
user_id=user_id,
|
username=username,
|
||||||
event_type=event_type,
|
event_type=event_type,
|
||||||
days=days,
|
days=days,
|
||||||
limit=limit,
|
limit=limit,
|
||||||
@@ -211,7 +212,7 @@ async def get_circuit_history(
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class AdminGetAuditLogsAdapter(AdminApiAdapter):
|
class AdminGetAuditLogsAdapter(AdminApiAdapter):
|
||||||
user_id: Optional[str]
|
username: Optional[str]
|
||||||
event_type: Optional[str]
|
event_type: Optional[str]
|
||||||
days: int
|
days: int
|
||||||
limit: int
|
limit: int
|
||||||
@@ -229,8 +230,9 @@ class AdminGetAuditLogsAdapter(AdminApiAdapter):
|
|||||||
.outerjoin(DBUser, AuditLog.user_id == DBUser.id)
|
.outerjoin(DBUser, AuditLog.user_id == DBUser.id)
|
||||||
.filter(AuditLog.created_at >= cutoff_time)
|
.filter(AuditLog.created_at >= cutoff_time)
|
||||||
)
|
)
|
||||||
if self.user_id:
|
if self.username:
|
||||||
base_query = base_query.filter(AuditLog.user_id == self.user_id)
|
escaped = escape_like_pattern(self.username)
|
||||||
|
base_query = base_query.filter(DBUser.username.ilike(f"%{escaped}%", escape="\\"))
|
||||||
if self.event_type:
|
if self.event_type:
|
||||||
base_query = base_query.filter(AuditLog.event_type == self.event_type)
|
base_query = base_query.filter(AuditLog.event_type == self.event_type)
|
||||||
|
|
||||||
@@ -264,14 +266,14 @@ class AdminGetAuditLogsAdapter(AdminApiAdapter):
|
|||||||
items,
|
items,
|
||||||
meta,
|
meta,
|
||||||
filters={
|
filters={
|
||||||
"user_id": self.user_id,
|
"username": self.username,
|
||||||
"event_type": self.event_type,
|
"event_type": self.event_type,
|
||||||
"days": self.days,
|
"days": self.days,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
context.add_audit_metadata(
|
context.add_audit_metadata(
|
||||||
action="monitor_audit_logs",
|
action="monitor_audit_logs",
|
||||||
filter_user_id=self.user_id,
|
filter_username=self.username,
|
||||||
filter_event_type=self.event_type,
|
filter_event_type=self.event_type,
|
||||||
days=self.days,
|
days=self.days,
|
||||||
limit=self.limit,
|
limit=self.limit,
|
||||||
|
|||||||
Reference in New Issue
Block a user