Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gateway/platforms/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1734,8 +1734,8 @@ def message_len_fn(self) -> Callable[[str], int]:
def enforces_own_access_policy(self) -> bool:
"""Whether this adapter gates inbound access before dispatch.

Some adapters (WeCom, Weixin, Yuanbao, QQBot) implement a documented
config-driven access surface — ``dm_policy`` / ``group_policy`` /
Some adapters (WeCom, Weixin, Yuanbao, QQBot, WhatsApp) implement a
documented config-driven access surface — ``dm_policy`` / ``group_policy`` /
``allow_from`` / ``group_allow_from`` in ``PlatformConfig.extra`` — and
enforce it at intake: a message is dropped inside the adapter and never
reaches the gateway unless it already passed that policy.
Expand Down
5 changes: 5 additions & 0 deletions gateway/platforms/whatsapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ def _is_broadcast_chat(chat_id: str) -> bool:
return True
return False

@property
def enforces_own_access_policy(self) -> bool:
"""WhatsApp gates DM/group access at intake via dm_policy/group_policy."""
return True

def _is_dm_allowed(self, sender_id: str) -> bool:
"""Check whether a DM from the given sender should be processed."""
if self._dm_policy == "disabled":
Expand Down
4 changes: 2 additions & 2 deletions gateway/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -6820,8 +6820,8 @@ def _adapter_enforces_own_access_policy(self, platform: Optional[Platform]) -> b
"""Whether the adapter for *platform* gates access at intake itself.

Mirrors ``BasePlatformAdapter.enforces_own_access_policy``. Adapters
such as WeCom, Weixin, Yuanbao, and QQBot evaluate their documented
``dm_policy`` / ``group_policy`` / ``allow_from`` config before a
such as WeCom, Weixin, Yuanbao, QQBot, and WhatsApp evaluate their
documented ``dm_policy`` / ``group_policy`` / ``allow_from`` config before a
message is dispatched to the gateway, so a message that reaches
``_is_user_authorized`` has already been authorized by the adapter.
Defaults to ``False`` when the adapter is unknown or doesn't expose
Expand Down
13 changes: 9 additions & 4 deletions tests/gateway/test_config_driven_access_policy.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Tests for config-driven platform access policies at the gateway layer.

Background (#34515): WeCom, Weixin, Yuanbao, and QQBot expose a documented
config-driven access surface (``dm_policy`` / ``group_policy`` / ``allow_from``
/ ``group_allow_from`` in ``PlatformConfig.extra``) and enforce it at intake —
Background (#34515): WeCom, Weixin, Yuanbao, QQBot, and WhatsApp expose a
documented config-driven access surface (``dm_policy`` / ``group_policy`` /
``allow_from`` / ``group_allow_from`` in ``PlatformConfig.extra``) and enforce
it at intake —
a message is dropped inside the adapter and never reaches the gateway unless it
already passed that policy.

Expand Down Expand Up @@ -34,6 +35,7 @@
Platform.WEIXIN,
Platform.YUANBAO,
Platform.QQBOT,
Platform.WHATSAPP,
]


Expand All @@ -44,13 +46,15 @@ def _clear_auth_env(monkeypatch) -> None:
"YUANBAO_ALLOWED_USERS",
"QQ_ALLOWED_USERS",
"QQ_GROUP_ALLOWED_USERS",
"WHATSAPP_ALLOWED_USERS",
"TELEGRAM_ALLOWED_USERS",
"GATEWAY_ALLOWED_USERS",
"GATEWAY_ALLOW_ALL_USERS",
"WECOM_ALLOW_ALL_USERS",
"WEIXIN_ALLOW_ALL_USERS",
"YUANBAO_ALLOW_ALL_USERS",
"QQ_ALLOW_ALL_USERS",
"WHATSAPP_ALLOW_ALL_USERS",
):
monkeypatch.delenv(key, raising=False)

Expand Down Expand Up @@ -103,10 +107,11 @@ def test_base_adapter_defaults_to_not_owning_access_policy():
("gateway.platforms.weixin", "WeixinAdapter"),
("gateway.platforms.yuanbao", "YuanbaoAdapter"),
("gateway.platforms.qqbot.adapter", "QQAdapter"),
("gateway.platforms.whatsapp", "WhatsAppAdapter"),
],
)
def test_own_policy_adapters_declare_the_flag(module_path, class_name):
"""The four config-policy adapters override the flag to True."""
"""The config-policy adapters override the flag to True."""
import importlib

module = importlib.import_module(module_path)
Expand Down
Loading