1. 调整导入顺序与格式,修复重复导入 2. 替换通用异常捕获为更精准的ValueError 3. 重构持久层仓库的get_deleted/list_deleted方法,添加ORM转领域模型逻辑 4. 完善配置校验与参数合法性检查,新增缺失字段校验 5. 优化多行字符串与函数调用的换行格式 6. 修复通知服务状态判定逻辑与文档描述 7. 简化无用的TYPE_CHECKING代码块 8. 重构ServiceNow元数据发现逻辑,增加字段合法性校验 9. 修复数据库查询验证器的子查询处理逻辑 10. 完善领域模型的初始化校验与属性语义
112 lines
4.3 KiB
Python
112 lines
4.3 KiB
Python
"""ServiceNow 厂商集成元数据。
|
||
|
||
定义 ``IntegrationMetadata(key="servicenow", ...)``,由 ``__init__.py`` 自注册到
|
||
``IntegrationRegistry``。元数据为内存态,不持久化到数据库。
|
||
|
||
同时定义 ``ServiceNowConnectionConfig`` 连接配置 Schema 与
|
||
``resolve_oauth_endpoints`` OAuth 端点拼接函数,供 use_cases 层 / 前端在系统创建
|
||
与配置阶段调用(见设计文档 §3.2 / §3.3)。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||
|
||
from yuxi.external_systems.integrations.schemas import IntegrationMetadata
|
||
|
||
|
||
class ServiceNowConnectionConfig(BaseModel):
|
||
"""ServiceNow 连接配置 Schema。
|
||
|
||
``base_url`` 优先级高于 ``instance``,支持私有部署场景。OAuth 端点由
|
||
``resolve_oauth_endpoints`` 在 handler 外动态拼接,注入到 ``auth_config``
|
||
后传给框架级 OAuth2 插件。
|
||
"""
|
||
|
||
model_config = ConfigDict(populate_by_name=True, extra="ignore")
|
||
|
||
instance: str | None = Field(
|
||
default=None,
|
||
description="ServiceNow 实例名,如 acme(对应 https://acme.service-now.com)",
|
||
)
|
||
base_url: str | None = Field(
|
||
default=None,
|
||
description="完整 base_url,优先级高于 instance;用于私有部署或自定义域名",
|
||
)
|
||
api_version: str | None = Field(
|
||
default=None,
|
||
description="Table API 版本,如 v1 / v2;None 表示非版本化路径 /api/now/table/...",
|
||
)
|
||
|
||
@model_validator(mode="after")
|
||
def _ensure_url(self) -> ServiceNowConnectionConfig:
|
||
if not self.base_url and not self.instance:
|
||
raise ValueError("instance 与 base_url 至少填写一项")
|
||
if not self.base_url:
|
||
self.base_url = f"https://{self.instance}.service-now.com"
|
||
return self
|
||
|
||
|
||
def resolve_oauth_endpoints(base_url: str) -> dict[str, str]:
|
||
"""根据 base_url 拼接 ServiceNow 实例级 OAuth 端点。
|
||
|
||
由 use_cases 层 / 前端在系统创建与配置阶段调用,根据
|
||
``connection_config.base_url`` 拼接 ``token_url`` / ``authorize_url``,
|
||
写入 ``auth_config`` 后持久化。handler 执行时 token 已由 use_cases 层通过
|
||
``token_manager.get_token`` 预解析并注入到 ``system_config["_resolved_token"]``,
|
||
handler 不再调用本函数(与 dynamics365 一致)。
|
||
"""
|
||
return {
|
||
"authorize_url": f"{base_url}/oauth_auth.do",
|
||
"token_url": f"{base_url}/oauth_token.do",
|
||
}
|
||
|
||
|
||
SERVICENOW_METADATA = IntegrationMetadata(
|
||
key="servicenow",
|
||
display_name="ServiceNow",
|
||
description="ITSM / 工作流平台,基于 Table REST API 集成",
|
||
adapter_type="http",
|
||
source_types=["servicenow"],
|
||
supported_auth_types=[
|
||
"oauth2_authorization_code",
|
||
"oauth2_password",
|
||
"oauth2_client_credentials",
|
||
"basic",
|
||
],
|
||
tags=["itsm", "workflow", "ticketing"],
|
||
icon="servicenow",
|
||
docs_url="https://developer.servicenow.com/dev.do#!/learn/learning-plans/yokohama/rest_api",
|
||
connection_extra_schema={
|
||
"instance": {
|
||
"type": "string",
|
||
"description": "ServiceNow 实例名,如 acme(对应 https://acme.service-now.com)",
|
||
},
|
||
"base_url": {
|
||
"type": "string",
|
||
"description": "完整 base_url(优先级高于 instance),用于私有部署或自定义域名",
|
||
},
|
||
"api_version": {
|
||
"type": "string",
|
||
"enum": ["v1", "v2"],
|
||
"description": "Table API 版本;None 表示非版本化路径 /api/now/table/...",
|
||
},
|
||
},
|
||
example_config={
|
||
"instance": "acme",
|
||
"api_version": None,
|
||
"auth_type": "oauth2_client_credentials",
|
||
"token_url": "https://acme.service-now.com/oauth_token.do",
|
||
"client_id": "example-client-id",
|
||
"client_secret": "ref://servicenow/acme/client_secret",
|
||
"scope": None,
|
||
},
|
||
dependency_note=(
|
||
"1. 调用账号需对 sys_db_object / sys_dictionary / "
|
||
"sys_documentation / sys_choice / sys_glide_object 具备 READ 权限;"
|
||
"2. OAuth2 应用需在目标实例中注册并配置回调地址;"
|
||
"3. oauth2_client_credentials 需 Washington DC 及以上版本;"
|
||
"4. client_secret 建议使用 ref:// 密钥引用。"
|
||
),
|
||
)
|