feat: 升级审计装饰器,支持自动抓取并记录 API 请求体作为变更明细

This commit is contained in:
DXC
2026-03-10 17:36:02 +08:00
parent cd192624b9
commit ac97c6066b

View File

@ -95,7 +95,45 @@ def audit_log(module: str, action: str = None, get_target_id_fn=None, get_target
审计日志装饰器
用法: @audit_log(module='inbound_buy', action='create')
@audit_log(module='bom', action='update', get_target_id_fn=lambda: ..., get_details_fn=lambda req, resp: ...)
升级特性:
- 自动捕获请求 Payload 作为变更明细
- 自动过滤过长的 Base64 图片数据
- 支持自定义 get_details_fn 覆盖默认行为
"""
# 需要过滤的图片字段
IMAGE_FIELDS = {'arrival_photo', 'product_photo', 'photo', 'image', 'signature', 'borrow_signature', 'return_signature'}
def _filter_payload(payload):
"""过滤 Payload 中的大字段,防止数据库膨胀"""
if not payload or not isinstance(payload, dict):
return payload
filtered = {}
for key, value in payload.items():
if key.lower() in IMAGE_FIELDS and isinstance(value, str) and len(value) > 100:
filtered[key] = '[图片数据已省略]'
elif isinstance(value, dict):
filtered[key] = _filter_payload(value)
elif isinstance(value, list):
filtered[key] = [
_filter_payload(item) if isinstance(item, dict) else item
for item in value
]
else:
filtered[key] = value
return filtered
def _get_payload():
"""自动获取请求 Payload"""
# 尝试 JSON
payload = request.get_json(silent=True)
if payload:
return payload
# 尝试 Form Data
if request.form:
return request.form.to_dict()
return None
def wrapper(fn):
@wraps(fn)
def decorator(*args, **kwargs):
@ -120,6 +158,10 @@ def audit_log(module: str, action: str = None, get_target_id_fn=None, get_target
if callable(action):
final_action = action()
# 预先获取 Payload用于后续 details 记录)
raw_payload = _get_payload()
filtered_payload = _filter_payload(raw_payload) if raw_payload else None
# 执行原函数
response = fn(*args, **kwargs)
@ -157,10 +199,14 @@ def audit_log(module: str, action: str = None, get_target_id_fn=None, get_target
# 获取 details
details = None
if get_details_fn:
# 优先使用自定义差异对比函数
try:
details = get_details_fn(request, response)
except Exception:
pass
elif filtered_payload:
# 默认:记录请求 Payload
details = {'payload': filtered_payload}
# 保存日志
log_entry = AuditLog(