fix(telegram): address review findings from PR #67816

- Update test_observed_group_context_preserves_slash_command_text_for_dispatch
  to assert user_id is preserved for COMMAND messages (new correct behavior)
- Add _coerce_allow_set helper to handle both list and comma-separated
  string allowlist inputs (prevents character-by-character iteration bug)
- Include 'channel' in chat_type checks for group-scoped authorization
- Add _telegram_extra fallback for group_allowed_chats (consistent with
  group_allow_from fallback)
- Add AUTHOR_MAP entry for nyaruko@hermes -> tsuk1nose
This commit is contained in:
kshitijk4poor 2026-07-22 12:21:54 +05:30 committed by kshitij
parent 45fce38b9e
commit 7078430934
4 changed files with 26 additions and 7 deletions

View file

@ -0,0 +1 @@
tsuk1nose

View file

@ -43,6 +43,21 @@ def _auth_env(name: str, default: str = "") -> str:
return (os.getenv(name) or default).strip()
def _coerce_allow_set(raw) -> set[str]:
"""Parse allowlist values from config or env var into a set of strings.
Handles both list inputs (YAML sequences) and comma-separated string
inputs (env vars or scalar YAML values). A scalar string is split on
commas so ``allow_from: "123,456"`` yields ``{"123", "456"}``, not
``{"1", "2", "3", ",", ...}``.
"""
if raw is None:
return set()
if isinstance(raw, list):
return {str(part).strip() for part in raw if str(part).strip()}
return {part.strip() for part in str(raw).split(",") if part.strip()}
class GatewayAuthorizationMixin:
"""User/chat authorization methods for ``GatewayRunner``."""
@ -369,7 +384,7 @@ class GatewayAuthorizationMixin:
extra = getattr(getattr(adapter, "config", None), "extra", None) or {}
adapter_group_allowed = extra.get("group_allowed_chats")
if adapter_group_allowed:
allowed = {str(c).strip() for c in adapter_group_allowed if str(c).strip()}
allowed = _coerce_allow_set(adapter_group_allowed)
if "*" in allowed or source.chat_id in allowed:
return True
except Exception:
@ -550,12 +565,12 @@ class GatewayAuthorizationMixin:
adapter = self._adapter_for_source(source)
if adapter is not None:
extra = getattr(getattr(adapter, "config", None), "extra", None) or {}
if source.chat_type in {"group", "forum"}:
if source.chat_type in {"group", "forum", "channel"}:
adapter_allow = extra.get("group_allow_from")
else:
adapter_allow = extra.get("allow_from")
if adapter_allow:
allowed = {str(u).strip() for u in adapter_allow if str(u).strip()}
allowed = _coerce_allow_set(adapter_allow)
if user_id in allowed or "*" in allowed:
return True
# No allowlists configured -- check global allow-all flag

View file

@ -250,6 +250,7 @@ import sys
from pathlib import Path as _Path
sys.path.insert(0, str(_Path(__file__).resolve().parents[3]))
from gateway.authz_mixin import _coerce_allow_set
from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import (
BasePlatformAdapter,
@ -1016,12 +1017,12 @@ class TelegramAdapter(BasePlatformAdapter):
# Adapter-level allow_from / group_allow_from: when set, they are the
# sole authority. Group chats use group_allow_from; DMs use allow_from.
chat_type = source.chat_type or ""
if chat_type in ("group", "forum"):
if chat_type in ("group", "forum", "channel"):
adapter_allow_from = self.config.extra.get("group_allow_from")
else:
adapter_allow_from = self.config.extra.get("allow_from")
if adapter_allow_from is not None:
allowed = {str(u).strip() for u in adapter_allow_from if str(u).strip()}
allowed = _coerce_allow_set(adapter_allow_from)
return user_id in allowed or "*" in allowed
# Test/custom injection only. The class method named
@ -9410,7 +9411,7 @@ def _apply_yaml_config(yaml_cfg: dict, telegram_cfg: dict) -> dict | None:
if isinstance(group_allowed_users, list):
group_allowed_users = ",".join(str(v) for v in group_allowed_users)
os.environ["TELEGRAM_GROUP_ALLOWED_USERS"] = str(group_allowed_users)
group_allowed_chats = telegram_cfg.get("group_allowed_chats")
group_allowed_chats = telegram_cfg.get("group_allowed_chats") or _telegram_extra.get("group_allowed_chats")
if group_allowed_chats is not None and not os.getenv("TELEGRAM_GROUP_ALLOWED_CHATS"):
if isinstance(group_allowed_chats, list):
group_allowed_chats = ",".join(str(v) for v in group_allowed_chats)

View file

@ -346,7 +346,9 @@ def test_observed_group_context_preserves_slash_command_text_for_dispatch():
assert attributed.text == "/new@hermes_bot"
assert attributed.get_command() == "new"
assert attributed.source.user_id is None
# Commands preserve sender identity for slash-access control (#67816).
assert attributed.source.user_id == "111"
assert attributed.source.user_name == "Alice"
assert "observed Telegram group context" in attributed.channel_prompt