From 8c0532dbbbd0c1f3035fa22c5c08903ee02b8826 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Tue, 25 Jan 2022 22:22:18 +0900 Subject: [PATCH] Add org-wide installation test patterns (#578) --- slack_bolt/request/internals.py | 4 + tests/slack_bolt/request/test_request.py | 221 +++++++++++++++++++++++ 2 files changed, 225 insertions(+) diff --git a/slack_bolt/request/internals.py b/slack_bolt/request/internals.py index 2fd0c430e..b520cb821 100644 --- a/slack_bolt/request/internals.py +++ b/slack_bolt/request/internals.py @@ -78,6 +78,8 @@ def extract_enterprise_id(payload: Dict[str, Any]) -> Optional[str]: def extract_team_id(payload: Dict[str, Any]) -> Optional[str]: if payload.get("team") is not None: + # With org-wide installations, payload.team in interactivity payloads can be None + # You need to extract either payload.user.team_id or payload.view.team_id as below team = payload.get("team") if isinstance(team, str): return team @@ -93,6 +95,8 @@ def extract_team_id(payload: Dict[str, Any]) -> Optional[str]: return extract_team_id(payload["event"]) if payload.get("user") is not None: return payload.get("user")["team_id"] + if payload.get("view") is not None: + return payload.get("view")["team_id"] return None diff --git a/tests/slack_bolt/request/test_request.py b/tests/slack_bolt/request/test_request.py index b6a81ecca..70ce98e3c 100644 --- a/tests/slack_bolt/request/test_request.py +++ b/tests/slack_bolt/request/test_request.py @@ -1,3 +1,5 @@ +from urllib.parse import quote + from slack_bolt.request.request import BoltRequest @@ -21,3 +23,222 @@ def test_all_none_inputs_socket_mode(self): assert req is not None assert req.raw_body == "" assert req.body == {} + + def test_org_wide_installations_block_actions(self): + payload = """ +{ + "type": "block_actions", + "user": { + "id": "W111", + "username": "primary-owner", + "name": "primary-owner", + "team_id": "T_expected" + }, + "api_app_id": "A111", + "token": "fixed-value", + "container": { + "type": "message", + "message_ts": "1643113871.000700", + "channel_id": "C111", + "is_ephemeral": true + }, + "trigger_id": "111.222.xxx", + "team": null, + "enterprise": { + "id": "E111", + "name": "Sandbox Org" + }, + "is_enterprise_install": true, + "channel": { + "id": "C111", + "name": "random" + }, + "state": { + "values": {} + }, + "response_url": "https://hooks.slack.com/actions/E111/111/xxx", + "actions": [ + { + "action_id": "a", + "block_id": "b", + "text": { + "type": "plain_text", + "text": "Button" + }, + "value": "click_me_123", + "type": "button", + "action_ts": "1643113877.645417" + } + ] +} +""" + req = BoltRequest(body=f"payload={quote(payload)}") + assert req is not None + assert req.context.team_id == "T_expected" + assert req.context.user_id == "W111" + + def test_org_wide_installations_view_submission(self): + payload = """ +{ + "type": "view_submission", + "team": null, + "user": { + "id": "W111", + "username": "primary-owner", + "name": "primary-owner", + "team_id": "T_expected" + }, + "api_app_id": "A111", + "token": "fixed-value", + "trigger_id": "1111.222.xxx", + "view": { + "id": "V111", + "team_id": "T_expected", + "type": "modal", + "blocks": [ + { + "type": "input", + "block_id": "+5B", + "label": { + "type": "plain_text", + "text": "Label", + "emoji": true + }, + "optional": false, + "dispatch_action": false, + "element": { + "type": "plain_text_input", + "dispatch_action_config": { + "trigger_actions_on": [ + "on_enter_pressed" + ] + }, + "action_id": "MMKH" + } + } + ], + "private_metadata": "", + "callback_id": "view-id", + "state": { + "values": { + "+5B": { + "MMKH": { + "type": "plain_text_input", + "value": "test" + } + } + } + }, + "hash": "111.xxx", + "title": { + "type": "plain_text", + "text": "My App" + }, + "clear_on_close": false, + "notify_on_close": false, + "close": { + "type": "plain_text", + "text": "Cancel" + }, + "submit": { + "type": "plain_text", + "text": "Submit", + "emoji": true + }, + "previous_view_id": null, + "root_view_id": "V111", + "app_id": "A111", + "external_id": "", + "app_installed_team_id": "E111", + "bot_id": "B111" + }, + "response_urls": [], + "is_enterprise_install": true, + "enterprise": { + "id": "E111", + "name": "Sandbox Org" + } +} +""" + req = BoltRequest(body=f"payload={quote(payload)}") + assert req is not None + assert req.context.team_id == "T_expected" + assert req.context.user_id == "W111" + + def test_org_wide_installations_view_closed(self): + payload = """ +{ + "type": "view_closed", + "team": null, + "user": { + "id": "W111", + "username": "primary-owner", + "name": "primary-owner", + "team_id": "T_expected" + }, + "api_app_id": "A111", + "token": "fixed-value", + "view": { + "id": "V111", + "team_id": "T_expected", + "type": "modal", + "blocks": [ + { + "type": "input", + "block_id": "M2r2p", + "label": { + "type": "plain_text", + "text": "Label" + }, + "optional": false, + "dispatch_action": false, + "element": { + "type": "plain_text_input", + "dispatch_action_config": { + "trigger_actions_on": [ + "on_enter_pressed" + ] + }, + "action_id": "xB+" + } + } + ], + "private_metadata": "", + "callback_id": "view-id", + "state": { + "values": {} + }, + "hash": "1643113987.gRY6ROtt", + "title": { + "type": "plain_text", + "text": "My App" + }, + "clear_on_close": false, + "notify_on_close": true, + "close": { + "type": "plain_text", + "text": "Cancel" + }, + "submit": { + "type": "plain_text", + "text": "Submit" + }, + "previous_view_id": null, + "root_view_id": "V111", + "app_id": "A111", + "external_id": "", + "app_installed_team_id": "E111", + "bot_id": "B0302M47727" + }, + "is_cleared": false, + "is_enterprise_install": true, + "enterprise": { + "id": "E111", + "name": "Sandbox Org" + } +} +""" + req = BoltRequest(body=f"payload={quote(payload)}") + assert req is not None + assert req.context.team_id == "T_expected" + assert req.context.user_id == "W111"