Skip to content

Commit 0cb7bbb

Browse files
committed
Add more fields to context for Bolt JS compatibility
1 parent afec102 commit 0cb7bbb

File tree

11 files changed

+232
-31
lines changed

11 files changed

+232
-31
lines changed

slack_bolt/authorization/authorize_result.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,22 @@ def from_auth_test_response(
5353
user_token: Optional[str] = None,
5454
auth_test_response: SlackResponse,
5555
) -> "AuthorizeResult":
56+
bot_user_id: Optional[str] = ( # type:ignore
57+
auth_test_response.get("user_id")
58+
if auth_test_response.get("bot_id") is not None
59+
else None
60+
)
61+
user_id: Optional[str] = ( # type:ignore
62+
auth_test_response.get("user_id")
63+
if auth_test_response.get("bot_id") is None
64+
else None
65+
)
5666
return AuthorizeResult(
5767
enterprise_id=auth_test_response.get("enterprise_id"),
5868
team_id=auth_test_response.get("team_id"),
59-
bot_user_id=auth_test_response.get("user_id"),
6069
bot_id=auth_test_response.get("bot_id"),
61-
user_id=auth_test_response.get("user_id"),
70+
bot_user_id=bot_user_id,
71+
user_id=user_id,
6272
bot_token=bot_token,
6373
user_token=user_token,
6474
)

slack_bolt/context/base_context.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55

66

77
class BaseContext(dict):
8-
@property
9-
def authorize_result(self) -> Optional[AuthorizeResult]:
10-
return self.get("authorize_result")
11-
128
@property
139
def logger(self) -> Logger:
1410
return self["logger"]
@@ -41,3 +37,38 @@ def response_url(self) -> Optional[str]:
4137
def matches(self) -> Optional[Tuple]:
4238
"""Returns all the matched parts in message listener's regexp"""
4339
return self.get("matches")
40+
41+
# --------------------------------
42+
43+
@property
44+
def authorize_result(self) -> Optional[AuthorizeResult]:
45+
return self.get("authorize_result")
46+
47+
@property
48+
def bot_token(self) -> Optional[str]:
49+
return self.get("bot_token")
50+
51+
@property
52+
def bot_id(self) -> Optional[str]:
53+
return self.get("bot_id")
54+
55+
@property
56+
def bot_user_id(self) -> Optional[str]:
57+
return self.get("bot_user_id")
58+
59+
@property
60+
def user_token(self) -> Optional[str]:
61+
return self.get("user_token")
62+
63+
def set_authorize_result(self, authorize_result: AuthorizeResult):
64+
self["authorize_result"] = authorize_result
65+
if authorize_result.bot_id is not None:
66+
self["bot_id"] = authorize_result.bot_id
67+
if authorize_result.bot_user_id is not None:
68+
self["bot_user_id"] = authorize_result.bot_user_id
69+
if authorize_result.bot_token is not None:
70+
self["bot_token"] = authorize_result.bot_token
71+
if authorize_result.user_id is not None:
72+
self["user_id"] = authorize_result.user_id
73+
if authorize_result.user_token is not None:
74+
self["user_token"] = authorize_result.user_token

slack_bolt/middleware/authorization/async_multi_teams_authorization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ async def async_process(
3939
user_id=req.context.user_id,
4040
)
4141
if auth_result:
42-
req.context["authorize_result"] = auth_result
42+
req.context.set_authorize_result(auth_result)
4343
token = auth_result.bot_token or auth_result.user_token
4444
req.context["token"] = token
4545
req.context["client"] = create_async_web_client(token)

slack_bolt/middleware/authorization/async_single_team_authorization.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class AsyncSingleTeamAuthorization(AsyncAuthorization):
1414
def __init__(self):
1515
"""Single-workspace authorization."""
16-
self.auth_result: Optional[AsyncSlackResponse] = None
16+
self.auth_test_result: Optional[AsyncSlackResponse] = None
1717
self.logger = get_bolt_logger(AsyncSingleTeamAuthorization)
1818

1919
async def async_process(
@@ -27,14 +27,16 @@ async def async_process(
2727
return await next()
2828

2929
try:
30-
if self.auth_result is None:
31-
self.auth_result = await req.context.client.auth_test()
30+
if self.auth_test_result is None:
31+
self.auth_test_result = await req.context.client.auth_test()
3232

33-
if self.auth_result:
34-
req.context["authorize_result"] = _to_authorize_result(
35-
auth_test_result=self.auth_result,
36-
token=req.context.client.token,
37-
request_user_id=req.context.user_id,
33+
if self.auth_test_result:
34+
req.context.set_authorize_result(
35+
_to_authorize_result(
36+
auth_test_result=self.auth_test_result,
37+
token=req.context.client.token,
38+
request_user_id=req.context.user_id,
39+
)
3840
)
3941
return await next()
4042
else:

slack_bolt/middleware/authorization/multi_teams_authorization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def process(
3737
user_id=req.context.user_id,
3838
)
3939
if auth_result is not None:
40-
req.context["authorize_result"] = auth_result
40+
req.context.set_authorize_result(auth_result)
4141
token = auth_result.bot_token or auth_result.user_token
4242
req.context["token"] = token
4343
req.context["client"] = create_web_client(token)

slack_bolt/middleware/authorization/single_team_authorization.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ def process(
3333
self.auth_test_result = req.context.client.auth_test()
3434

3535
if self.auth_test_result:
36-
req.context["authorize_result"] = _to_authorize_result(
37-
auth_test_result=self.auth_test_result,
38-
token=req.context.client.token,
39-
request_user_id=req.context.user_id,
36+
req.context.set_authorize_result(
37+
_to_authorize_result(
38+
auth_test_result=self.auth_test_result,
39+
token=req.context.client.token,
40+
request_user_id=req.context.user_id,
41+
)
4042
)
4143
return next()
4244
else:

tests/mock_web_api_server.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ def is_valid_token(self):
1919
self.headers["Authorization"]
2020
).startswith("Bearer xoxb-")
2121

22+
def is_valid_user_token(self):
23+
return "Authorization" in self.headers and str(
24+
self.headers["Authorization"]
25+
).startswith("Bearer xoxp-")
26+
2227
def set_common_headers(self):
2328
self.send_header("content-type", "application/json;charset=utf-8")
2429
self.send_header("connection", "close")
@@ -53,7 +58,7 @@ def set_common_headers(self):
5358
}
5459
}
5560
"""
56-
auth_test_response = """
61+
bot_auth_test_response = """
5762
{
5863
"ok": true,
5964
"url": "https://subarachnoid.slack.com/",
@@ -63,6 +68,17 @@ def set_common_headers(self):
6368
"user_id": "W23456789",
6469
"bot_id": "BZYBOTHED"
6570
}
71+
"""
72+
73+
user_auth_test_response = """
74+
{
75+
"ok": true,
76+
"url": "https://subarachnoid.slack.com/",
77+
"team": "Subarachnoid Workspace",
78+
"user": "some-user",
79+
"team_id": "T0G9PQBBK",
80+
"user_id": "W99999"
81+
}
6682
"""
6783

6884
def _handle(self):
@@ -75,13 +91,20 @@ def _handle(self):
7591
self.wfile.write(self.oauth_v2_access_response.encode("utf-8"))
7692
return
7793

94+
if self.is_valid_user_token():
95+
if self.path == "/auth.test":
96+
self.send_response(200)
97+
self.set_common_headers()
98+
self.wfile.write(self.user_auth_test_response.encode("utf-8"))
99+
return
100+
78101
if self.is_valid_token():
79102
parsed_path = urlparse(self.path)
80103

81104
if self.path == "/auth.test":
82105
self.send_response(200)
83106
self.set_common_headers()
84-
self.wfile.write(self.auth_test_response.encode("utf-8"))
107+
self.wfile.write(self.bot_auth_test_response.encode("utf-8"))
85108
return
86109

87110
len_header = self.headers.get("Content-Length") or 0

tests/scenario_tests/test_authorize.py

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,33 @@
1515
from tests.utils import remove_os_env_temporarily, restore_os_env
1616

1717
valid_token = "xoxb-valid"
18+
valid_user_token = "xoxp-valid"
1819

1920

2021
def authorize(enterprise_id, team_id, user_id, client: WebClient):
2122
assert enterprise_id == "E111"
2223
assert team_id == "T111"
23-
assert user_id == "W111"
24+
assert user_id == "W99999"
2425
auth_test = client.auth_test(token=valid_token)
2526
return AuthorizeResult.from_auth_test_response(
2627
auth_test_response=auth_test, bot_token=valid_token,
2728
)
2829

2930

31+
def user_authorize(enterprise_id, team_id, user_id, client: WebClient):
32+
assert enterprise_id == "E111"
33+
assert team_id == "T111"
34+
assert user_id == "W99999"
35+
auth_test = client.auth_test(token=valid_user_token)
36+
return AuthorizeResult.from_auth_test_response(
37+
auth_test_response=auth_test, user_token=valid_user_token,
38+
)
39+
40+
3041
def error_authorize(enterprise_id, team_id, user_id):
3142
assert enterprise_id == "E111"
3243
assert team_id == "T111"
33-
assert user_id == "W111"
44+
assert user_id == "W99999"
3445
return None
3546

3647

@@ -94,11 +105,39 @@ def test_failure(self):
94105
assert response.body == ":x: Please install this app into the workspace :bow:"
95106
assert self.mock_received_requests.get("/auth.test") == None
96107

108+
def test_bot_context_attributes(self):
109+
app = App(
110+
client=self.web_client,
111+
authorize=authorize,
112+
signing_secret=self.signing_secret,
113+
)
114+
app.action("a")(assert_bot_context_attributes)
115+
116+
request = self.build_valid_request()
117+
response = app.dispatch(request)
118+
assert response.status == 200
119+
assert response.body == ""
120+
assert self.mock_received_requests["/auth.test"] == 1
121+
122+
def test_user_context_attributes(self):
123+
app = App(
124+
client=self.web_client,
125+
authorize=user_authorize,
126+
signing_secret=self.signing_secret,
127+
)
128+
app.action("a")(assert_user_context_attributes)
129+
130+
request = self.build_valid_request()
131+
response = app.dispatch(request)
132+
assert response.status == 200
133+
assert response.body == ""
134+
assert self.mock_received_requests["/auth.test"] == 1
135+
97136

98137
body = {
99138
"type": "block_actions",
100139
"user": {
101-
"id": "W111",
140+
"id": "W99999",
102141
"username": "primary-owner",
103142
"name": "primary-owner",
104143
"team_id": "T111",
@@ -141,3 +180,23 @@ def simple_listener(ack, body, payload, action):
141180
assert payload == action
142181
assert action["action_id"] == "a"
143182
ack()
183+
184+
185+
def assert_bot_context_attributes(ack, context):
186+
assert context["bot_id"] == "BZYBOTHED"
187+
assert context["bot_user_id"] == "W23456789"
188+
assert context["bot_token"] == "xoxb-valid"
189+
assert context["token"] == "xoxb-valid"
190+
assert context["user_id"] == "W99999"
191+
assert context.get("user_token") is None
192+
ack()
193+
194+
195+
def assert_user_context_attributes(ack, context):
196+
assert context.get("bot_id") is None
197+
assert context.get("bot_user_id") is None
198+
assert context.get("bot_token") is None
199+
assert context["token"] == "xoxp-valid"
200+
assert context["user_id"] == "W99999"
201+
assert context["user_token"] == "xoxp-valid"
202+
ack()

tests/scenario_tests/test_block_actions.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from slack_sdk import WebClient
66
from slack_sdk.signature import SignatureVerifier
77

8-
from slack_bolt import BoltRequest
8+
from slack_bolt import BoltRequest, BoltContext
99
from slack_bolt.app import App
1010
from tests.mock_web_api_server import (
1111
setup_mock_web_api_server,
@@ -174,9 +174,15 @@ def test_failure_2(self):
174174
raw_body = f"payload={quote(json.dumps(body))}"
175175

176176

177-
def simple_listener(ack, body, payload, action):
177+
def simple_listener(ack, body, payload, action, context: BoltContext):
178178
assert body["trigger_id"] == "111.222.valid"
179179
assert body["actions"][0] == payload
180180
assert payload == action
181181
assert action["action_id"] == "a"
182+
assert context.bot_id == "BZYBOTHED"
183+
assert context.bot_user_id == "W23456789"
184+
assert context.bot_token == "xoxb-valid"
185+
assert context.token == "xoxb-valid"
186+
assert context.user_id == "W111"
187+
assert context.user_token is None
182188
ack()

0 commit comments

Comments
 (0)