fix(whatsapp_cloud): honor documented WHATSAPP_CLOUD_ALLOWED_USERS / ALLOW_ALL_USERS

The Cloud setup wizard and docs tell operators to set
WHATSAPP_CLOUD_ALLOWED_USERS (and WHATSAPP_CLOUD_ALLOW_ALL_USERS), but the
adapter DM intake gate only read WHATSAPP_CLOUD_ALLOW_FROM + WHATSAPP_CLOUD_DM_POLICY
(default open, opted-in only via GATEWAY_/WHATSAPP_ALLOW_ALL_USERS). So an
allowlist set via the documented var silently dropped every inbound
(_should_process_message -> None -> HTTP 200, no dispatch, no log line).

- _allow_from also reads WHATSAPP_CLOUD_ALLOWED_USERS
- dm_policy defaults to allowlist when an allowlist is present (else open)
- _open_dm_opted_in() also honors WHATSAPP_CLOUD_ALLOW_ALL_USERS

Explicit DM_POLICY / ALLOW_FROM still win -> backward compatible.
This commit is contained in:
Sahil Shubham 2026-07-04 13:07:32 +00:00 committed by Teknium
parent 132bb8a163
commit 6c7960cfa0

View file

@ -225,18 +225,35 @@ class WhatsAppCloudAdapter(WhatsAppBehaviorMixin, BasePlatformAdapter):
import os
self._reply_prefix: Optional[str] = extra.get("reply_prefix")
self._dm_policy: str = str(
extra.get("dm_policy")
or os.getenv("WHATSAPP_CLOUD_DM_POLICY")
or os.getenv("WHATSAPP_DM_POLICY", "open")
).strip().lower()
# Allowlist: honor the *documented* WHATSAPP_CLOUD_ALLOWED_USERS (the
# var the setup wizard writes) in addition to WHATSAPP_CLOUD_ALLOW_FROM.
# The adapter historically read only ALLOW_FROM, so an allowlist
# configured via the documented var silently dropped every inbound.
self._allow_from: set[str] = self._normalize_allow_ids(
self._coerce_allow_list(
extra.get("allow_from")
or extra.get("allowFrom")
or os.getenv("WHATSAPP_CLOUD_ALLOW_FROM")
or os.getenv("WHATSAPP_CLOUD_ALLOWED_USERS")
)
)
# DM policy: explicit config wins; otherwise choose a safe, working
# default -- "open" if the operator opted into allow-all, else
# "allowlist" when an allowlist is configured (so it is actually
# enforced instead of silently dropping), else "open".
_allow_all_optin = str(
os.getenv("WHATSAPP_CLOUD_ALLOW_ALL_USERS", "")
).strip().lower() in {"true", "1", "yes"}
_default_dm_policy = (
"open" if _allow_all_optin
else ("allowlist" if self._allow_from else "open")
)
self._dm_policy: str = str(
extra.get("dm_policy")
or os.getenv("WHATSAPP_CLOUD_DM_POLICY")
or os.getenv("WHATSAPP_DM_POLICY")
or _default_dm_policy
).strip().lower()
self._group_policy: str = str(
extra.get("group_policy")
or os.getenv("WHATSAPP_CLOUD_GROUP_POLICY")
@ -347,6 +364,17 @@ class WhatsAppCloudAdapter(WhatsAppBehaviorMixin, BasePlatformAdapter):
return (bare or sender_id) in self._allow_from
return super()._is_dm_allowed(sender_id)
def _open_dm_opted_in(self) -> bool:
"""Also honor the documented WHATSAPP_CLOUD_ALLOW_ALL_USERS opt-in.
The shared mixin only checks GATEWAY_ALLOW_ALL_USERS /
WHATSAPP_ALLOW_ALL_USERS; the Cloud adapter's documented open-access
opt-in is WHATSAPP_CLOUD_ALLOW_ALL_USERS, so honor it here too.
"""
if str(os.getenv("WHATSAPP_CLOUD_ALLOW_ALL_USERS", "")).strip().lower() in {"true", "1", "yes"}:
return True
return super()._open_dm_opted_in()
# ------------------------------------------------------------------ lifecycle
async def connect(self, *, is_reconnect: bool = False) -> bool:
if not check_whatsapp_cloud_requirements():