from __future__ import annotations import logging logger = logging.getLogger(__name__) DM_POLICIES = ("open", "pairing", "allowlist", "disabled") GROUP_POLICIES = ("open", "allowlist", "disabled") class GitHubSecurityAdapter: def resolve_dm_policy(self) -> dict: return {"mode": "open", "allow_from": []} def resolve_dm_policy_for_account(self, account: dict) -> dict: mode = account.get("dm_policy", "open") return {"mode": mode, "allow_from": account.get("allow_from", [])} def is_allowed_dm(self, account: dict, peer_id: str) -> tuple[bool, str | None]: mode = account.get("dm_policy", "open") if mode == "disabled": return False, "DM disabled" if mode == "open": return True, None allow_from = account.get("allow_from", []) normalized = self._normalize_peer(peer_id) if mode == "allowlist": if self._check_allowlist(allow_from, normalized): return True, None return False, "not-in-allowlist" if mode == "pairing": if self._check_allowlist(allow_from, normalized): return True, "paired" return True, "pairing-required" return False, "unknown-policy" def is_allowed_group(self, account: dict, peer_id: str, group_id: str | None = None, is_mentioned: bool = False, ) -> tuple[bool, str | None]: group_policy = account.get("group_policy", "open") if group_policy == "disabled": return False, "group-disabled" if group_policy == "open": return True, None if group_policy == "allowlist": allow_from = account.get("allow_from", []) normalized = self._normalize_peer(peer_id) if self._check_allowlist(allow_from, normalized): return True, None return False, "not-in-group-allowlist" return False, "unknown-policy" def collect_warnings(self, config: dict, account_id: str | None = None) -> list[str]: warnings: list[str] = [] gh_config = config.get("channels", {}).get("github", {}) dm_policy = gh_config.get("dmPolicy", "open") if dm_policy == "open" and not gh_config.get("allowFrom"): warnings.append("dmPolicy is 'open' without allowFrom — anyone can interact with bot in public repos") group_policy = gh_config.get("groupPolicy", "open") if group_policy == "open": warnings.append("Group policy is 'open' — any public repo Issue/Discussion can trigger the bot") return warnings @staticmethod def _normalize_peer(peer_id: str) -> str: for prefix in ("github:", "gh:"): if peer_id.startswith(prefix): return peer_id[len(prefix):] return str(peer_id) @staticmethod def _check_allowlist(allow_from: list[str], peer_id: str) -> bool: if "*" in allow_from: return True normalized = str(peer_id) for entry in allow_from: if str(entry) == normalized: return True return False