Files
ipam/backend/app/api/v1/audit.py
T
Your Name bca0da7c7d readme
2026-07-20 13:40:05 +08:00

166 lines
5.3 KiB
Python

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from typing import Optional
from datetime import datetime
from app.core.database import get_db
from app.core.security import get_current_user, require_permission
from app.models.auth import User
from app.models.audit import AuditAction, AuditResource
from app.services.audit_service import AuditService
router = APIRouter(prefix="/audit", tags=["审计日志"])
@router.get("/logs", summary="获取审计日志列表")
def get_audit_logs(
user_id: Optional[int] = None,
action: Optional[AuditAction] = None,
resource: Optional[AuditResource] = None,
success: Optional[bool] = None,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None,
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=500),
current_user: User = Depends(require_permission("audit:view")),
db: Session = Depends(get_db)
):
"""
获取审计日志列表(需要管理员权限)
- **user_id**: 按用户ID过滤
- **action**: 按操作类型过滤 (create/read/update/delete/login/logout/scan/export)
- **resource**: 按资源类型过滤
- **success**: 按操作结果过滤
- **start_time**: 开始时间
- **end_time**: 结束时间
"""
total, items = AuditService.get_logs(
db,
user_id=user_id,
action=action,
resource=resource,
success=success,
start_time=start_time,
end_time=end_time,
skip=skip,
limit=limit
)
# 格式化返回
result_items = []
for item in items:
changed = item.changed_fields.split(',') if item.changed_fields else []
result_items.append({
"id": item.id,
"user_id": item.user_id,
"username": item.username,
"real_name": item.real_name,
"user_ip": item.user_ip,
"action": item.action.value,
"resource": item.resource.value,
"resource_id": item.resource_id,
"description": item.description,
"changed_fields": changed,
"request_method": item.request_method,
"request_path": item.request_path,
"success": bool(item.success),
"error_message": item.error_message,
"created_at": item.created_at
})
return {"total": total, "items": result_items}
@router.get("/logs/my", summary="获取当前用户的操作日志")
def get_my_logs(
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=200),
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""获取当前登录用户的操作日志"""
total, items = AuditService.get_logs(
db,
user_id=current_user.id,
skip=skip,
limit=limit
)
result_items = []
for item in items:
result_items.append({
"id": item.id,
"action": item.action.value,
"resource": item.resource.value,
"resource_id": item.resource_id,
"description": item.description,
"success": bool(item.success),
"created_at": item.created_at
})
return {"total": total, "items": result_items}
@router.get("/logs/resource/{resource_type}/{resource_id}", summary="获取资源操作历史")
def get_resource_logs(
resource_type: str,
resource_id: str,
limit: int = Query(50, ge=1, le=200),
current_user: User = Depends(require_permission("audit:view")),
db: Session = Depends(get_db)
):
"""获取指定资源的操作历史"""
try:
resource_enum = AuditResource(resource_type)
except ValueError:
return {"total": 0, "items": [], "error": "无效的资源类型"}
items = AuditService.get_resource_logs(db, resource_enum, resource_id, limit=limit)
result_items = []
for item in items:
changed = item.changed_fields.split(',') if item.changed_fields else []
result_items.append({
"id": item.id,
"username": item.username,
"real_name": item.real_name,
"action": item.action.value,
"description": item.description,
"changed_fields": changed,
"success": bool(item.success),
"created_at": item.created_at
})
return {"total": len(items), "items": result_items}
@router.get("/statistics", summary="获取审计统计信息")
def get_audit_statistics(
days: int = Query(30, ge=1, le=365),
current_user: User = Depends(require_permission("audit:view")),
db: Session = Depends(get_db)
):
"""获取审计统计信息"""
stats = AuditService.get_statistics(db, days=days)
return stats
@router.delete("/clean", summary="清理旧日志")
def clean_old_logs(
days: int = Query(90, ge=7, le=3650, description="保留天数"),
current_user: User = Depends(require_permission("system:admin")),
db: Session = Depends(get_db)
):
"""
清理指定天数之前的审计日志(需要超级管理员权限)
- **days**: 保留日志的天数,默认90天
"""
deleted_count = AuditService.clean_old_logs(db, days=days)
return {
"message": f"清理完成,已删除 {deleted_count} 条旧日志",
"deleted_count": deleted_count,
"kept_days": days
}