fix(whatsapp): honor dm_policy and group_policy open at the gateway

This commit is contained in:
Zyrixtrex
2026-06-01 19:51:21 -07:00
committed by Teknium
parent d4b533de4e
commit 0cd5867bbb
4 changed files with 18 additions and 8 deletions
+2 -2
View File
@@ -1750,8 +1750,8 @@ class BasePlatformAdapter(ABC):
def enforces_own_access_policy(self) -> bool: def enforces_own_access_policy(self) -> bool:
"""Whether this adapter gates inbound access before dispatch. """Whether this adapter gates inbound access before dispatch.
Some adapters (WeCom, Weixin, Yuanbao, QQBot) implement a documented Some adapters (WeCom, Weixin, Yuanbao, QQBot, WhatsApp) implement a
config-driven access surface — ``dm_policy`` / ``group_policy`` / documented config-driven access surface — ``dm_policy`` / ``group_policy`` /
``allow_from`` / ``group_allow_from`` in ``PlatformConfig.extra`` — and ``allow_from`` / ``group_allow_from`` in ``PlatformConfig.extra`` — and
enforce it at intake: a message is dropped inside the adapter and never enforce it at intake: a message is dropped inside the adapter and never
reaches the gateway unless it already passed that policy. reaches the gateway unless it already passed that policy.
+5
View File
@@ -379,6 +379,11 @@ class WhatsAppAdapter(BasePlatformAdapter):
return True return True
return False 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: def _is_dm_allowed(self, sender_id: str) -> bool:
"""Check whether a DM from the given sender should be processed.""" """Check whether a DM from the given sender should be processed."""
if self._dm_policy == "disabled": if self._dm_policy == "disabled":
+2 -2
View File
@@ -6820,8 +6820,8 @@ class GatewayRunner:
"""Whether the adapter for *platform* gates access at intake itself. """Whether the adapter for *platform* gates access at intake itself.
Mirrors ``BasePlatformAdapter.enforces_own_access_policy``. Adapters Mirrors ``BasePlatformAdapter.enforces_own_access_policy``. Adapters
such as WeCom, Weixin, Yuanbao, and QQBot evaluate their documented such as WeCom, Weixin, Yuanbao, QQBot, and WhatsApp evaluate their
``dm_policy`` / ``group_policy`` / ``allow_from`` config before a documented ``dm_policy`` / ``group_policy`` / ``allow_from`` config before a
message is dispatched to the gateway, so a message that reaches message is dispatched to the gateway, so a message that reaches
``_is_user_authorized`` has already been authorized by the adapter. ``_is_user_authorized`` has already been authorized by the adapter.
Defaults to ``False`` when the adapter is unknown or doesn't expose Defaults to ``False`` when the adapter is unknown or doesn't expose
@@ -1,8 +1,9 @@
"""Tests for config-driven platform access policies at the gateway layer. """Tests for config-driven platform access policies at the gateway layer.
Background (#34515): WeCom, Weixin, Yuanbao, and QQBot expose a documented Background (#34515): WeCom, Weixin, Yuanbao, QQBot, and WhatsApp expose a
config-driven access surface (``dm_policy`` / ``group_policy`` / ``allow_from`` documented config-driven access surface (``dm_policy`` / ``group_policy`` /
/ ``group_allow_from`` in ``PlatformConfig.extra``) and enforce it at intake ``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 a message is dropped inside the adapter and never reaches the gateway unless it
already passed that policy. already passed that policy.
@@ -34,6 +35,7 @@ _OWN_POLICY_PLATFORMS = [
Platform.WEIXIN, Platform.WEIXIN,
Platform.YUANBAO, Platform.YUANBAO,
Platform.QQBOT, Platform.QQBOT,
Platform.WHATSAPP,
] ]
@@ -44,6 +46,7 @@ def _clear_auth_env(monkeypatch) -> None:
"YUANBAO_ALLOWED_USERS", "YUANBAO_ALLOWED_USERS",
"QQ_ALLOWED_USERS", "QQ_ALLOWED_USERS",
"QQ_GROUP_ALLOWED_USERS", "QQ_GROUP_ALLOWED_USERS",
"WHATSAPP_ALLOWED_USERS",
"TELEGRAM_ALLOWED_USERS", "TELEGRAM_ALLOWED_USERS",
"GATEWAY_ALLOWED_USERS", "GATEWAY_ALLOWED_USERS",
"GATEWAY_ALLOW_ALL_USERS", "GATEWAY_ALLOW_ALL_USERS",
@@ -51,6 +54,7 @@ def _clear_auth_env(monkeypatch) -> None:
"WEIXIN_ALLOW_ALL_USERS", "WEIXIN_ALLOW_ALL_USERS",
"YUANBAO_ALLOW_ALL_USERS", "YUANBAO_ALLOW_ALL_USERS",
"QQ_ALLOW_ALL_USERS", "QQ_ALLOW_ALL_USERS",
"WHATSAPP_ALLOW_ALL_USERS",
): ):
monkeypatch.delenv(key, raising=False) monkeypatch.delenv(key, raising=False)
@@ -103,10 +107,11 @@ def test_base_adapter_defaults_to_not_owning_access_policy():
("gateway.platforms.weixin", "WeixinAdapter"), ("gateway.platforms.weixin", "WeixinAdapter"),
("gateway.platforms.yuanbao", "YuanbaoAdapter"), ("gateway.platforms.yuanbao", "YuanbaoAdapter"),
("gateway.platforms.qqbot.adapter", "QQAdapter"), ("gateway.platforms.qqbot.adapter", "QQAdapter"),
("gateway.platforms.whatsapp", "WhatsAppAdapter"),
], ],
) )
def test_own_policy_adapters_declare_the_flag(module_path, class_name): 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 import importlib
module = importlib.import_module(module_path) module = importlib.import_module(module_path)