Files
rag/api/audit_routes.py
lacerate551 183a57e7f1 refactor(api): 统一响应格式迁移 + 异步任务系统 + 状态码体系完善
- 将全部路由文件(12个)的 jsonify 响应迁移至 success_response/error_response 统一格式
- 修复 sync_routes.py error_response 参数错误(P0)
- 新增异步任务系统:task_registry + task_routes
- 新增状态码:TASK_NOT_FOUND(4014)、TASK_CONFLICT(4015)、REINDEX_ERROR(5040)
- 修正 task_routes/exam_pkg 中语义不匹配的状态码
- 更新 curl 测试手册、后端对接规范文档
- 添加缓存性能报告和 Redis 迁移计划
2026-06-05 22:56:00 +08:00

137 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
审计日志 API
路由:
- GET /audit/logs - 查询审计日志(管理员)
"""
from flask import Blueprint, request, jsonify
import logging
logger = logging.getLogger(__name__)
from auth.gateway import require_gateway_auth
from data.db import get_connection
from core.status_codes import SUCCESS, INTERNAL_ERROR
from api.response_utils import success_response, error_response
audit_bp = Blueprint('audit', __name__)
@audit_bp.route('/audit/logs', methods=['GET'])
@require_gateway_auth
def get_audit_logs():
"""
查询审计日志
参数:
- limit: 返回条数默认50
- days: 查询天数默认7
- action: 操作类型过滤(可选)
返回:
{
"logs": [
{
"id": 1,
"user_id": "admin001",
"username": "admin",
"action": "rag_query",
"query": "xxx",
"result_summary": "...",
"role": "admin",
"department": "管理部",
"ip_address": "127.0.0.1",
"duration_ms": 1234,
"timestamp": "2025-01-01 12:00:00"
}
],
"total": 100
}
"""
limit = request.args.get('limit', 50, type=int)
days = request.args.get('days', 7, type=int)
action_filter = request.args.get('action', '')
try:
with get_connection("session") as conn:
# 构建查询
where_clauses = ["created_at >= datetime('now', ?)"]
params = [f'-{days} days']
if action_filter:
where_clauses.append("action = ?")
params.append(action_filter)
where_sql = " AND ".join(where_clauses)
# 查询总数
count_sql = f"SELECT COUNT(*) FROM audit_logs WHERE {where_sql}"
total = conn.execute(count_sql, params).fetchone()[0]
# 查询日志
query_sql = f"""
SELECT id, user_id, username, action, query, result_summary,
role, department, ip_address, duration_ms, created_at
FROM audit_logs
WHERE {where_sql}
ORDER BY created_at DESC
LIMIT ?
"""
params.append(limit)
rows = conn.execute(query_sql, params).fetchall()
logs = []
for row in rows:
logs.append({
"id": row[0],
"user_id": row[1],
"username": row[2],
"action": row[3],
"query": row[4],
"result_summary": row[5],
"role": row[6],
"department": row[7],
"ip_address": row[8],
"duration_ms": row[9],
"timestamp": row[10]
})
return success_response(data={"logs": logs, "total": total})
except Exception as e:
logger.error(f"审计查询异常: {e}")
return error_response("QUERY_FAILED", INTERNAL_ERROR, "查询失败", http_status=500)
def log_audit_event(user_id: str, username: str, action: str,
query: str = None, result_summary: str = None,
role: str = None, department: str = None,
ip_address: str = None, duration_ms: int = None):
"""
记录审计日志(供其他模块调用)
Args:
user_id: 用户ID
username: 用户名
action: 操作类型rag_query, chat, feedback, sync 等)
query: 查询内容
result_summary: 结果摘要
role: 用户角色
department: 部门
ip_address: IP地址
duration_ms: 耗时(毫秒)
"""
try:
with get_connection("session") as conn:
conn.execute("""
INSERT INTO audit_logs
(user_id, username, action, query, result_summary,
role, department, ip_address, duration_ms)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (user_id, username, action, query, result_summary,
role, department, ip_address, duration_ms))
except Exception as e:
# 审计日志写入失败不应影响主流程
logger.debug(f"审计日志写入失败: {e}")
pass