147 lines
4.9 KiB
Python
147 lines
4.9 KiB
Python
from __future__ import annotations
|
||
|
||
import logging
|
||
from typing import Any
|
||
|
||
from app.integrations.seeyon import SeeyonClient
|
||
from app.jobs.base import BaseJob
|
||
|
||
|
||
logger = logging.getLogger("connecthub.extensions.sync_oa_to_didi")
|
||
|
||
|
||
def _mask_token(token: str) -> str:
|
||
token = token or ""
|
||
if len(token) <= 12:
|
||
return "***"
|
||
return f"{token[:6]}***{token[-4:]}"
|
||
|
||
|
||
class SyncOAToDidiTokenJob(BaseJob):
|
||
"""
|
||
示例 Job:演示致远 OA 的 token 获取与日志记录
|
||
|
||
public_cfg:
|
||
- base_url: "https://oa.example.com"
|
||
|
||
secret_cfg (解密后):
|
||
- rest_user
|
||
- rest_password
|
||
- loginName (可选)
|
||
"""
|
||
|
||
job_id = "sync_oa_to_didi.token_demo"
|
||
|
||
def run(self, params: dict[str, Any], secrets: dict[str, Any]) -> dict[str, Any]:
|
||
base_url = str(params.get("base_url") or "").strip()
|
||
if not base_url:
|
||
raise ValueError("public_cfg.base_url is required")
|
||
|
||
rest_user = str(secrets.get("rest_user") or "").strip()
|
||
rest_password = str(secrets.get("rest_password") or "").strip()
|
||
login_name = secrets.get("loginName")
|
||
login_name = str(login_name).strip() if login_name else None
|
||
|
||
if not rest_user or not rest_password:
|
||
raise ValueError("secret_cfg.rest_user and secret_cfg.rest_password are required")
|
||
|
||
client = SeeyonClient(base_url=base_url, rest_user=rest_user, rest_password=rest_password, loginName=login_name)
|
||
try:
|
||
token = client.authenticate()
|
||
finally:
|
||
client.close()
|
||
|
||
masked = _mask_token(token)
|
||
logger.info("Seeyon token acquired (masked) token=%s loginName=%s base_url=%s", masked, login_name, base_url)
|
||
return {"token_masked": masked, "loginName": login_name or "", "base_url": base_url}
|
||
|
||
|
||
class SyncOAToDidiExportFormJob(BaseJob):
|
||
"""
|
||
无流程表单导出(CAP4):
|
||
- 调用:POST /seeyon/rest/cap4/form/soap/export
|
||
- base_url 不包含 /seeyon/rest(例如 https://oa.example.com:8090)
|
||
|
||
public_cfg:
|
||
- base_url: "https://oa.example.com:8090"
|
||
- templateCode: "employee"
|
||
- senderLoginName: "xxx" (可选)
|
||
- rightId: "xxx" (可选)
|
||
- doTrigger: "true" (可选)
|
||
- param: "0" (可选)
|
||
- extra: {...} (可选,兜底扩展字段)
|
||
|
||
secret_cfg (解密后):
|
||
- rest_user
|
||
- rest_password
|
||
- loginName (可选)
|
||
"""
|
||
|
||
job_id = "sync_oa_to_didi.export_form_soap"
|
||
|
||
def run(self, params: dict[str, Any], secrets: dict[str, Any]) -> dict[str, Any]:
|
||
base_url = str(params.get("base_url") or "").strip()
|
||
if not base_url:
|
||
raise ValueError("public_cfg.base_url is required")
|
||
|
||
template_code = str(params.get("templateCode") or "").strip()
|
||
if not template_code:
|
||
raise ValueError("public_cfg.templateCode is required")
|
||
|
||
sender_login_name = params.get("senderLoginName")
|
||
sender_login_name = str(sender_login_name).strip() if sender_login_name else None
|
||
|
||
right_id = params.get("rightId")
|
||
right_id = str(right_id).strip() if right_id else None
|
||
|
||
do_trigger = params.get("doTrigger")
|
||
param = params.get("param")
|
||
param = str(param) if param is not None else None
|
||
|
||
extra = params.get("extra")
|
||
if extra is not None and not isinstance(extra, dict):
|
||
raise ValueError("public_cfg.extra must be a JSON object (dict) if provided")
|
||
|
||
rest_user = str(secrets.get("rest_user") or "").strip()
|
||
rest_password = str(secrets.get("rest_password") or "").strip()
|
||
login_name = secrets.get("loginName")
|
||
login_name = str(login_name).strip() if login_name else None
|
||
|
||
if not rest_user or not rest_password:
|
||
raise ValueError("secret_cfg.rest_user and secret_cfg.rest_password are required")
|
||
|
||
client = SeeyonClient(base_url=base_url, rest_user=rest_user, rest_password=rest_password, loginName=login_name)
|
||
try:
|
||
resp = client.export_cap4_form_soap(
|
||
templateCode=template_code,
|
||
senderLoginName=sender_login_name,
|
||
rightId=right_id,
|
||
doTrigger=do_trigger,
|
||
param=param,
|
||
extra=extra,
|
||
)
|
||
raw_text = resp.text or ""
|
||
content_type = resp.headers.get("content-type", "") if getattr(resp, "headers", None) else ""
|
||
finally:
|
||
client.close()
|
||
|
||
# 避免把 raw_text 打到日志或 run_log(会被截断且污染 JobLog)
|
||
logger.info(
|
||
"Seeyon export_form_soap done templateCode=%s content_length=%s content_type=%s base_url=%s",
|
||
template_code,
|
||
len(raw_text),
|
||
content_type,
|
||
base_url,
|
||
)
|
||
|
||
return {
|
||
"raw": raw_text,
|
||
"meta": {
|
||
"templateCode": template_code,
|
||
"content_length": len(raw_text),
|
||
"content_type": content_type,
|
||
},
|
||
}
|
||
|
||
|