init: RAG 知识库服务初始提交
- 后端 API(Flask + Gunicorn) - RAG 引擎(混合检索 + 云端 Reranker + 引用溯源) - 文档解析(MinerU + 多格式支持) - Docker 生产部署配置 - 排除前端项目、敏感配置、模型文件
This commit is contained in:
133
api/audit_routes.py
Normal file
133
api/audit_routes.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
审计日志 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
|
||||
|
||||
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 jsonify({"logs": logs, "total": total})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e), "logs": [], "total": 0}), 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
|
||||
Reference in New Issue
Block a user