public_gateway.py 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import logging
  2. import uuid
  3. from constants import BIND_HINT
  4. from tools.bind_auth_code import BindAuthCodeTool
  5. from tools.query_order import QueryOrderTool
  6. from tools.query_track import QueryTrackTool
  7. from utils.security import hash_gateway_session_id
  8. logger = logging.getLogger(__name__)
  9. class PublicGatewayApp:
  10. def __init__(self, session_store, api_client, auth_client):
  11. self.session_store = session_store
  12. self.api_client = api_client
  13. self.auth_client = auth_client
  14. self._tools = {
  15. 'bind_auth_code': BindAuthCodeTool(auth_client=None),
  16. 'query_order': QueryOrderTool(api_client=None),
  17. 'query_track': QueryTrackTool(api_client=None),
  18. }
  19. def list_tools(self):
  20. return [tool.metadata() for tool in self._tools.values()]
  21. def build_request_id(self, request_id=''):
  22. request_id = str(request_id or '').strip()
  23. return request_id or 'rq_{0}'.format(uuid.uuid4().hex[:16])
  24. def bind_auth_code(self, gateway_session_id, auth_code):
  25. if self.auth_client is None:
  26. raise RuntimeError('auth client is required')
  27. session_hash = hash_gateway_session_id(gateway_session_id)[:12]
  28. logger.info(f"[AUDIT] bind_auth_code: session_hash={session_hash}, auth_code_provided={bool(auth_code)}")
  29. result = self.auth_client.exchange(gateway_session_id, auth_code)
  30. if result.get('code') == 'MCP_0000':
  31. session = self.session_store.get(gateway_session_id)
  32. admin_id = session.get('admin_id') if session else None
  33. company_id = session.get('company_id') if session else None
  34. logger.info(f"[AUDIT] bind_success: session_hash={session_hash}, admin_id={admin_id}, company_id={company_id}")
  35. else:
  36. logger.warning(f"[AUDIT] bind_failed: session_hash={session_hash}, code={result.get('code')}, msg={result.get('msg')}")
  37. return result
  38. def call_tool(self, gateway_session_id, name, arguments=None, request_id=''):
  39. if name == 'bind_auth_code':
  40. auth_code = (arguments or {}).get('auth_code', '')
  41. return self.bind_auth_code(gateway_session_id, auth_code)
  42. if name not in self._tools:
  43. raise KeyError('tool not registered: {0}'.format(name))
  44. session = self.session_store.get(gateway_session_id)
  45. if not session or not session.get('mcp_token'):
  46. raise RuntimeError(BIND_HINT)
  47. tool = self._tools[name]
  48. request_id = self.build_request_id(request_id)
  49. session_hash = hash_gateway_session_id(gateway_session_id)[:12]
  50. admin_id = session.get('admin_id')
  51. company_id = session.get('company_id')
  52. logger.info(f"[AUDIT] tool_call: session_hash={session_hash}, admin_id={admin_id}, company_id={company_id}, tool={name}, request_id={request_id}")
  53. try:
  54. result = self.api_client.call_tool(
  55. token=session['mcp_token'],
  56. tool_code=tool.name,
  57. route_path=tool.route_path,
  58. payload=arguments or {},
  59. request_id=request_id,
  60. )
  61. logger.info(f"[AUDIT] tool_success: session_hash={session_hash}, tool={name}, request_id={request_id}, code={result.get('code')}")
  62. return result
  63. except Exception as e:
  64. logger.error(f"[AUDIT] tool_error: session_hash={session_hash}, tool={name}, request_id={request_id}, error={str(e)}")
  65. raise