app_audit/wwwroot/api/audit.dspy
yumoqing 6bcc1469eb feat: app_audit 审计日志全局模块(独立仓库)
- audit_service.py: audit_log 写入 + is_audit_role + list/backup/delete
- init.py: load_app_audit 建 sd_audit_logs 表 + owner.audit 角色
- audit.dspy: list/backup/delete 仅 owner.audit(审计独立性)
- models + load_path.py + README
2026-08-14 12:19:38 +08:00

72 lines
2.7 KiB
Plaintext
Raw 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.

# app_audit audit.dspy - 审计日志 API
# 查看/备份/删除 仅 owner.audit 角色审计独立性superuser 也无权访问)
# action: list / backup / delete
user_id = await get_user()
if not user_id:
return json.dumps({'ok': False, 'error': '未登录'}, ensure_ascii=False)
action = (params_kw or {}).get('action', 'list')
from app_audit.audit_service import (
is_audit_role, list_audit_logs, backup_audit_logs, delete_audit_logs,
)
# 查 username 和 client_ip
username = user_id
try:
async with get_sor_context(request._run_ns, 'pipeline') as _sor:
_u = await _sor.sqlExe("SELECT username FROM users WHERE id=${u}$", {'u': user_id})
if _u:
username = getattr(_u[0], 'username', user_id) or user_id
except Exception:
pass
client_ip = ''
try:
client_ip = request.get('client_ip', '') or ''
except Exception:
pass
# 权限校验:所有 action 仅 owner.auditsuperuser 也不行)
async with get_sor_context(request._run_ns, 'pipeline') as _sor:
if not await is_audit_role(_sor, user_id):
return json.dumps({'ok': False, 'error': '仅 owner.audit 角色可访问审计日志'}, ensure_ascii=False)
if action == 'list':
filters = {
'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', ''),
}
limit = (params_kw or {}).get('limit', 100)
offset = (params_kw or {}).get('offset', 0)
try:
async with get_sor_context(request._run_ns, 'pipeline') as sor:
rows = await list_audit_logs(sor, filters, limit, offset)
return json.dumps({'ok': True, 'logs': rows}, ensure_ascii=False)
except Exception as e:
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
elif action == 'backup':
try:
async with get_sor_context(request._run_ns, 'pipeline') as sor:
r = await backup_audit_logs(sor, user_id, username, None, client_ip)
return json.dumps(r, ensure_ascii=False)
except Exception as e:
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
elif action == 'delete':
before = (params_kw or {}).get('before', '')
try:
async with get_sor_context(request._run_ns, 'pipeline') as sor:
r = await delete_audit_logs(sor, user_id, username, before, client_ip)
return json.dumps(r, ensure_ascii=False)
except Exception as e:
return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False)
else:
return json.dumps({'ok': False, 'error': '未知 action: ' + str(action)}, ensure_ascii=False)