fix(jira): support Jira Server/Data Center Bearer auth alongside Cloud Basic auth

Jira Server self-hosted instances (e.g. insight.fsoft.com.vn) reject
Basic Auth with email+API token (403). Auto-detect by hostname:
- *.atlassian.net → Basic Auth (email + API token)
- everything else → Bearer header with Personal Access Token

User pastes PAT into the same 'API token' field in UI Connectors.
This commit is contained in:
thanhnv
2026-09-07 00:53:26 +09:00
parent 4cdd4fc98e
commit 1caded98e9
+27 -5
View File
@@ -83,18 +83,40 @@ def get_issue_by_url(config: Dict[str, Any] | None, url: str) -> str:
return get_issue(config, key)
def _is_cloud(base_url: str) -> bool:
"""True when the base URL points at Atlassian Cloud (*.atlassian.net)."""
try:
host = (urlparse(base_url).hostname or "").lower()
except ValueError:
return False
return host.endswith(".atlassian.net")
def _get(config: Dict[str, Any], path: str, params: dict = None):
"""Gọi Jira REST API bằng xác thực cơ bản, qua lớp TLS có ghim chứng chỉ nội bộ."""
"""Gọi Jira REST API, tự chọn mode xác thực theo loại server.
Jira Cloud (*.atlassian.net) → Basic Auth (email + API token).
Jira Server / Data Center → Bearer token (Personal Access Token).
Cả hai đều đi qua lớp TLS có ghim chứng chỉ nội bộ (tls_trust).
"""
from . import tls_trust
c = _conf(config)
url = c["base_url"].rstrip("/") + path
# Same TLS auto-recovery the LLM provider calls get (core/tls_trust.py) —
# a corporate gateway that terminates TLS with its own certificate used to
# break this outright with SSLCertVerificationError.
headers = {"Accept": "application/json"}
if _is_cloud(c["base_url"]):
# Cloud: Basic Auth với email + API token từ id.atlassian.com
resp = tls_trust.request("get", url, params=params or {}, timeout=_TIMEOUT,
auth=(c["email"], c["api_token"]),
headers={"Accept": "application/json"})
headers=headers)
else:
# Server / Data Center: Personal Access Token qua Bearer header.
# Người dùng dán PAT vào trường "API token" trong UI Connectors.
headers["Authorization"] = f"Bearer {c['api_token']}"
resp = tls_trust.request("get", url, params=params or {}, timeout=_TIMEOUT,
headers=headers)
resp.raise_for_status()
return resp.json()