Skip to content

Commit

Permalink
Fix context.team_id for view interactions in a Slack Connect channel (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
seratch authored Oct 5, 2022
1 parent 0ca2874 commit 4c22a28
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 7 deletions.
6 changes: 6 additions & 0 deletions slack_bolt/request/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ def extract_enterprise_id(payload: Dict[str, Any]) -> Optional[str]:


def extract_team_id(payload: Dict[str, Any]) -> Optional[str]:
if payload.get("view", {}).get("app_installed_team_id") is not None:
# view_submission payloads can have `view.app_installed_team_id` when a modal view that was opened
# in a different workspace via some operations inside a Slack Connect channel.
# Note that the same for enterprise_id does not exist. When you need to know the enterprise_id as well,
# you have to run some query toward your InstallationStore to know the org where the team_id belongs to.
return payload.get("view")["app_installed_team_id"]
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
Expand Down
66 changes: 65 additions & 1 deletion tests/scenario_tests/test_view_submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from slack_sdk import WebClient
from slack_sdk.signature import SignatureVerifier

from slack_bolt import BoltRequest
from slack_bolt import BoltRequest, BoltContext
from slack_bolt.app import App
from tests.mock_web_api_server import (
setup_mock_web_api_server,
Expand Down Expand Up @@ -140,6 +140,58 @@ def simple_listener(ack, body, payload, view):
raw_response_url_body = f"payload={quote(json.dumps(response_url_payload_body))}"


connect_channel_payload = {
"type": "view_submission",
"team": {
"id": "T-other-side",
"domain": "other-side",
"enterprise_id": "E-other-side",
"enterprise_name": "Kaz Sandbox Org",
},
"user": {"id": "W111", "username": "kaz", "name": "kaz", "team_id": "T-other-side"},
"api_app_id": "A1111",
"token": "legacy-fixed-token",
"trigger_id": "111.222.xxx",
"view": {
"id": "V11111",
"team_id": "T-other-side",
"type": "modal",
"blocks": [
{
"type": "input",
"block_id": "zniAM",
"label": {"type": "plain_text", "text": "Label"},
"element": {
"type": "plain_text_input",
"dispatch_action_config": {"trigger_actions_on": ["on_enter_pressed"]},
"action_id": "qEJr",
},
}
],
"private_metadata": "",
"callback_id": "view-id",
"state": {"values": {"zniAM": {"qEJr": {"type": "plain_text_input", "value": "Hi there!"}}}},
"hash": "1664950703.CmTS8F7U",
"title": {"type": "plain_text", "text": "My App"},
"close": {"type": "plain_text", "text": "Cancel"},
"submit": {"type": "plain_text", "text": "Submit"},
"root_view_id": "V00000",
"app_id": "A1111",
"external_id": "",
"app_installed_team_id": "T-installed-workspace",
"bot_id": "B1111",
},
"enterprise": {"id": "E-other-side", "name": "Kaz Sandbox Org"},
}

connect_channel_body = f"payload={quote(json.dumps(connect_channel_payload))}"


def verify_connected_channel(ack, context: BoltContext):
assert context.team_id == "T-installed-workspace"
ack()


class TestViewSubmission:
signing_secret = "secret"
valid_token = "xoxb-valid"
Expand Down Expand Up @@ -261,3 +313,15 @@ def check(ack, respond):
response = app.dispatch(request)
assert response.status == 200
assert_auth_test_count(self, 1)

def test_connected_channels(self):
app = App(
client=self.web_client,
signing_secret=self.signing_secret,
)
app.view("view-id")(verify_connected_channel)

request = self.build_valid_request(body=connect_channel_body)
response = app.dispatch(request)
assert response.status == 200
assert_auth_test_count(self, 1)
65 changes: 65 additions & 0 deletions tests/scenario_tests_async/test_view_submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,53 @@ def simple_listener(ack, body, payload, view):
raw_response_url_body = f"payload={quote(json.dumps(response_url_payload_body))}"


connect_channel_payload = {
"type": "view_submission",
"team": {
"id": "T-other-side",
"domain": "other-side",
"enterprise_id": "E-other-side",
"enterprise_name": "Kaz Sandbox Org",
},
"user": {"id": "W111", "username": "kaz", "name": "kaz", "team_id": "T-other-side"},
"api_app_id": "A1111",
"token": "legacy-fixed-token",
"trigger_id": "111.222.xxx",
"view": {
"id": "V11111",
"team_id": "T-other-side",
"type": "modal",
"blocks": [
{
"type": "input",
"block_id": "zniAM",
"label": {"type": "plain_text", "text": "Label"},
"element": {
"type": "plain_text_input",
"dispatch_action_config": {"trigger_actions_on": ["on_enter_pressed"]},
"action_id": "qEJr",
},
}
],
"private_metadata": "",
"callback_id": "view-id",
"state": {"values": {"zniAM": {"qEJr": {"type": "plain_text_input", "value": "Hi there!"}}}},
"hash": "1664950703.CmTS8F7U",
"title": {"type": "plain_text", "text": "My App"},
"close": {"type": "plain_text", "text": "Cancel"},
"submit": {"type": "plain_text", "text": "Submit"},
"root_view_id": "V00000",
"app_id": "A1111",
"external_id": "",
"app_installed_team_id": "T-installed-workspace",
"bot_id": "B1111",
},
"enterprise": {"id": "E-other-side", "name": "Kaz Sandbox Org"},
}

connect_channel_body = f"payload={quote(json.dumps(connect_channel_payload))}"


class TestAsyncViewSubmission:
signing_secret = "secret"
valid_token = "xoxb-valid"
Expand Down Expand Up @@ -275,10 +322,28 @@ async def check(ack, respond):
assert response.status == 200
await assert_auth_test_count_async(self, 1)

@pytest.mark.asyncio
async def test_connected_channels(self):
app = AsyncApp(
client=self.web_client,
signing_secret=self.signing_secret,
)
app.view("view-id")(verify_connected_channel)

request = self.build_valid_request(body=connect_channel_body)
response = await app.async_dispatch(request)
assert response.status == 200
await assert_auth_test_count_async(self, 1)


async def simple_listener(ack, body, payload, view):
assert body["trigger_id"] == "111.222.valid"
assert body["view"] == payload
assert payload == view
assert view["private_metadata"] == "This is for you!"
await ack()


async def verify_connected_channel(ack, context):
assert context.team_id == "T-installed-workspace"
await ack()
12 changes: 6 additions & 6 deletions tests/slack_bolt/request/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ def test_org_wide_installations_view_submission(self):
"id": "W111",
"username": "primary-owner",
"name": "primary-owner",
"team_id": "T_expected"
"team_id": "T_unexpected"
},
"api_app_id": "A111",
"token": "fixed-value",
"trigger_id": "1111.222.xxx",
"view": {
"id": "V111",
"team_id": "T_expected",
"team_id": "T_unexpected",
"type": "modal",
"blocks": [
{
Expand Down Expand Up @@ -147,7 +147,7 @@ def test_org_wide_installations_view_submission(self):
"root_view_id": "V111",
"app_id": "A111",
"external_id": "",
"app_installed_team_id": "E111",
"app_installed_team_id": "T_expected",
"bot_id": "B111"
},
"response_urls": [],
Expand All @@ -172,13 +172,13 @@ def test_org_wide_installations_view_closed(self):
"id": "W111",
"username": "primary-owner",
"name": "primary-owner",
"team_id": "T_expected"
"team_id": "T_unexpected"
},
"api_app_id": "A111",
"token": "fixed-value",
"view": {
"id": "V111",
"team_id": "T_expected",
"team_id": "T_unexpected",
"type": "modal",
"blocks": [
{
Expand Down Expand Up @@ -225,7 +225,7 @@ def test_org_wide_installations_view_closed(self):
"root_view_id": "V111",
"app_id": "A111",
"external_id": "",
"app_installed_team_id": "E111",
"app_installed_team_id": "T_expected",
"bot_id": "B0302M47727"
},
"is_cleared": false,
Expand Down

0 comments on commit 4c22a28

Please sign in to comment.