# app_audit audit.dspy - 审计日志 API # 查看/备份/删除 仅 owner.audit 角色(审计独立性:superuser 也无权访问) # action: list / backup / delete _dbname = get_module_dbname('app_audit') 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, _dbname) 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.audit(superuser 也不行) async with get_sor_context(request._run_ns, _dbname) 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', ''), } page = (params_kw or {}).get('page', 1) rows = (params_kw or {}).get('rows', 60) try: async with get_sor_context(request._run_ns, _dbname) as sor: r = await list_audit_logs(sor, filters, page, rows) return json.dumps(r, ensure_ascii=False) except Exception as e: return json.dumps({'ok': False, 'error': str(e)}, ensure_ascii=False) 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: async with get_sor_context(request._run_ns, _dbname) as sor: r = await backup_audit_logs(sor, user_id, username, bfilters, blimit, 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, _dbname) 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)