实现了 GitLab 全功能集成,包含 Webhook 处理、API 客户端、消息收发、会话管理、安全校验、限流器等完整模块,支持 Issues、Merge Requests、流水线等事件监听与交互。
58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
POLICY_OPEN = "open"
|
|
POLICY_PAIRING = "pairing"
|
|
POLICY_ALLOWLIST = "allowlist"
|
|
POLICY_DISABLED = "disabled"
|
|
|
|
VALID_POLICIES = {POLICY_OPEN, POLICY_PAIRING, POLICY_ALLOWLIST, POLICY_DISABLED}
|
|
|
|
|
|
class GitLabSecurity:
|
|
@staticmethod
|
|
def resolve_dm_policy(account: dict) -> str:
|
|
policy = account.get("dm_policy", POLICY_OPEN)
|
|
if policy not in VALID_POLICIES:
|
|
logger.warning("gitlab invalid dm_policy '%s', defaulting to open", policy)
|
|
return POLICY_OPEN
|
|
return policy
|
|
|
|
@staticmethod
|
|
def is_allowed(account: dict, username: str) -> tuple[bool, str | None]:
|
|
policy = account.get("dm_policy", POLICY_OPEN)
|
|
if policy == POLICY_DISABLED:
|
|
return False, "gitlab-disabled"
|
|
if policy == POLICY_OPEN:
|
|
return True, None
|
|
if policy == POLICY_ALLOWLIST:
|
|
allow_from: list = account.get("allow_from", [])
|
|
if username in allow_from or "*" in allow_from:
|
|
return True, None
|
|
return False, f"gitlab-not-in-allowlist:{username}"
|
|
if policy == POLICY_PAIRING:
|
|
allow_from: list = account.get("allow_from", [])
|
|
if username in allow_from:
|
|
return True, "gitlab-paired"
|
|
return True, "gitlab-pairing-required"
|
|
return False, "gitlab-unknown-policy"
|
|
|
|
@staticmethod
|
|
def collect_warnings(config: dict, account_id: str | None = None, account: dict | None = None) -> list[str]:
|
|
warnings = []
|
|
if not account:
|
|
return warnings
|
|
if account.get("dm_policy") == "open" and not account.get("allow_from"):
|
|
warnings.append("gitlab dmPolicy is 'open' without allowFrom — anyone can interact with the bot")
|
|
if not account.get("ssl_verify"):
|
|
warnings.append("gitlab ssl verification disabled — only use in trusted internal networks")
|
|
return warnings
|
|
|
|
@staticmethod
|
|
def is_bot_own_message(payload: dict, bot_username: str) -> bool:
|
|
user = payload.get("user", {})
|
|
return user.get("username", "") == bot_username
|