fix: 审计覆盖 + 备份过滤 + unknown action 保留
- unknown action 在 detail 保留原始值 - backup 支持过滤 + limit 上限(防大响应) - 提取 _build_filter 公共过滤函数
This commit is contained in:
parent
55e4ce30b8
commit
d38e26ffff
@ -41,6 +41,8 @@ async def audit_log(sor, user_id: str, username: str, action: str,
|
|||||||
审计写入失败不应阻断主流程,返回 False 由调用方决定是否处理。
|
审计写入失败不应阻断主流程,返回 False 由调用方决定是否处理。
|
||||||
"""
|
"""
|
||||||
if action not in VALID_ACTIONS:
|
if action not in VALID_ACTIONS:
|
||||||
|
# 保留原始 action,避免排查时丢失是哪个模块拼错了
|
||||||
|
detail = (detail or "") + " [原始action:" + str(action) + "]"
|
||||||
action = "unknown"
|
action = "unknown"
|
||||||
try:
|
try:
|
||||||
from appPublic.uniqueID import getID
|
from appPublic.uniqueID import getID
|
||||||
@ -87,8 +89,8 @@ def _row_to_dict(row) -> dict:
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
async def list_audit_logs(sor, filters: dict = None, page: int = 1, rows: int = 60):
|
def _build_filter(filters: dict):
|
||||||
"""查询审计日志(分页,DataGrid 兼容),返回 {rows, total}。"""
|
"""构造 WHERE 子句 + 参数(list/backup/delete 共用)。返回 (wsql, ns)。"""
|
||||||
filters = filters or {}
|
filters = filters or {}
|
||||||
where = []
|
where = []
|
||||||
ns = {}
|
ns = {}
|
||||||
@ -108,6 +110,12 @@ async def list_audit_logs(sor, filters: dict = None, page: int = 1, rows: int =
|
|||||||
where.append("created_at<=${t}$")
|
where.append("created_at<=${t}$")
|
||||||
ns["t"] = filters["to"]
|
ns["t"] = filters["to"]
|
||||||
wsql = (" WHERE " + " AND ".join(where)) if where else ""
|
wsql = (" WHERE " + " AND ".join(where)) if where else ""
|
||||||
|
return wsql, ns
|
||||||
|
|
||||||
|
|
||||||
|
async def list_audit_logs(sor, filters: dict = None, page: int = 1, rows: int = 60):
|
||||||
|
"""查询审计日志(分页,DataGrid 兼容),返回 {rows, total}。"""
|
||||||
|
wsql, ns = _build_filter(filters)
|
||||||
try:
|
try:
|
||||||
page = max(1, int(page or 1))
|
page = max(1, int(page or 1))
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
@ -127,11 +135,16 @@ async def list_audit_logs(sor, filters: dict = None, page: int = 1, rows: int =
|
|||||||
|
|
||||||
|
|
||||||
async def backup_audit_logs(sor, user_id: str, username: str, filters: dict = None,
|
async def backup_audit_logs(sor, user_id: str, username: str, filters: dict = None,
|
||||||
client_ip: str = "") -> dict:
|
limit: int = 10000, client_ip: str = "") -> dict:
|
||||||
"""导出审计日志(仅 owner.audit),返回 JSON 内容供下载。"""
|
"""导出审计日志(仅 owner.audit),支持过滤 + 上限,返回 JSON 内容供下载。"""
|
||||||
# 查最近 10000 条(备份上限,避免一次拉全表拖垮内存)
|
wsql, ns = _build_filter(filters)
|
||||||
|
try:
|
||||||
|
limit = max(1, min(int(limit or 10000), 50000))
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
limit = 10000
|
||||||
recs = await sor.sqlExe(
|
recs = await sor.sqlExe(
|
||||||
"SELECT * FROM sd_audit_logs ORDER BY created_at DESC LIMIT 10000", {})
|
"SELECT * FROM sd_audit_logs" + wsql + " ORDER BY created_at DESC LIMIT "
|
||||||
|
+ str(limit), ns)
|
||||||
rows = [_row_to_dict(r) for r in recs]
|
rows = [_row_to_dict(r) for r in recs]
|
||||||
# 备份操作本身也审计
|
# 备份操作本身也审计
|
||||||
await audit_log(sor, user_id, username, "audit_backup",
|
await audit_log(sor, user_id, username, "audit_backup",
|
||||||
|
|||||||
@ -51,9 +51,17 @@ if action == 'list':
|
|||||||
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
|
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
|
||||||
|
|
||||||
elif action == 'backup':
|
elif action == 'backup':
|
||||||
|
bfilters = {
|
||||||
|
'user_id': (params_kw or {}).get('user_id', ''),
|
||||||
|
'username': (params_kw or {}).get('username', ''),
|
||||||
|
'action': (params_kw or {}).get('act', ''),
|
||||||
|
'from': (params_kw or {}).get('from', ''),
|
||||||
|
'to': (params_kw or {}).get('to', ''),
|
||||||
|
}
|
||||||
|
blimit = (params_kw or {}).get('limit', 10000)
|
||||||
try:
|
try:
|
||||||
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
async with get_sor_context(request._run_ns, 'pipeline') as sor:
|
||||||
r = await backup_audit_logs(sor, user_id, username, None, client_ip)
|
r = await backup_audit_logs(sor, user_id, username, bfilters, blimit, client_ip)
|
||||||
return json.dumps(r, ensure_ascii=False)
|
return json.dumps(r, ensure_ascii=False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
|
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user