Skip to content

Commit bf428d0

Browse files
committed
Fix #118 by adding allowlist of events in ignore self middleware
1 parent d2c1947 commit bf428d0

File tree

3 files changed

+358
-2
lines changed

3 files changed

+358
-2
lines changed

slack_bolt/middleware/ignoring_self_events/ignoring_self_events.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,20 @@ def process(
2525

2626
# -----------------------------------------
2727

28-
@staticmethod
28+
# Its an Events API event that isn't of type message,
29+
# but the user ID might match our own app. Filter these out.
30+
# However, some events still must be fired, because they can make sense.
31+
events_that_should_be_kept = ["member_joined_channel", "member_left_channel"]
32+
33+
@classmethod
2934
def _is_self_event(
30-
auth_result: AuthorizeResult, user_id: str, body: Dict[str, Any]
35+
cls, auth_result: AuthorizeResult, user_id: str, body: Dict[str, Any]
3136
):
3237
return (
3338
auth_result is not None
3439
and user_id == auth_result.bot_user_id
3540
and body.get("event") is not None
41+
and body.get("event").get("type") not in cls.events_that_should_be_kept
3642
)
3743

3844
def _debug_log(self, body: dict):

tests/scenario_tests/test_events.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,177 @@ def handle_app_mention():
161161
)
162162
response = app.dispatch(request)
163163
assert response.status == 200
164+
165+
def test_self_events(self):
166+
app = App(client=self.web_client, signing_secret=self.signing_secret)
167+
168+
event_body = {
169+
"token": "verification_token",
170+
"team_id": "T111",
171+
"enterprise_id": "E111",
172+
"api_app_id": "A111",
173+
"event": {
174+
"type": "reaction_added",
175+
"user": "W23456789", # bot_user_id
176+
"item": {
177+
"type": "message",
178+
"channel": "C111",
179+
"ts": "1599529504.000400",
180+
},
181+
"reaction": "heart_eyes",
182+
"item_user": "W111",
183+
"event_ts": "1599616881.000800",
184+
},
185+
"type": "event_callback",
186+
"event_id": "Ev111",
187+
"event_time": 1599616881,
188+
"authed_users": ["W111"],
189+
}
190+
191+
@app.event("reaction_added")
192+
def handle_app_mention(say):
193+
say("What's up?")
194+
195+
timestamp, body = str(int(time())), json.dumps(event_body)
196+
request: BoltRequest = BoltRequest(
197+
body=body, headers=self.build_headers(timestamp, body)
198+
)
199+
response = app.dispatch(request)
200+
assert response.status == 200
201+
assert self.mock_received_requests["/auth.test"] == 1
202+
sleep(1) # wait a bit after auto ack()
203+
# The listener should not be executed
204+
assert self.mock_received_requests.get("/chat.postMessage") is None
205+
206+
def test_self_member_join_left_events(self):
207+
app = App(client=self.web_client, signing_secret=self.signing_secret)
208+
209+
join_event_body = {
210+
"token": "verification_token",
211+
"team_id": "T111",
212+
"enterprise_id": "E111",
213+
"api_app_id": "A111",
214+
"event": {
215+
"type": "member_joined_channel",
216+
"user": "W23456789", # bot_user_id
217+
"channel": "C111",
218+
"channel_type": "C",
219+
"team": "T111",
220+
"inviter": "U222",
221+
},
222+
"type": "event_callback",
223+
"event_id": "Ev111",
224+
"event_time": 1599616881,
225+
"authed_users": ["W111"],
226+
}
227+
228+
left_event_body = {
229+
"token": "verification_token",
230+
"team_id": "T111",
231+
"enterprise_id": "E111",
232+
"api_app_id": "A111",
233+
"event": {
234+
"type": "member_left_channel",
235+
"user": "W23456789", # bot_user_id
236+
"channel": "C111",
237+
"channel_type": "C",
238+
"team": "T111",
239+
},
240+
"type": "event_callback",
241+
"event_id": "Ev111",
242+
"event_time": 1599616881,
243+
"authed_users": ["W111"],
244+
}
245+
246+
@app.event("member_joined_channel")
247+
def handle_member_joined_channel(say):
248+
say("What's up?")
249+
250+
@app.event("member_left_channel")
251+
def handle_member_left_channel(say):
252+
say("What's up?")
253+
254+
timestamp, body = str(int(time())), json.dumps(join_event_body)
255+
request: BoltRequest = BoltRequest(
256+
body=body, headers=self.build_headers(timestamp, body)
257+
)
258+
response = app.dispatch(request)
259+
assert response.status == 200
260+
assert self.mock_received_requests["/auth.test"] == 1
261+
262+
timestamp, body = str(int(time())), json.dumps(left_event_body)
263+
request: BoltRequest = BoltRequest(
264+
body=body, headers=self.build_headers(timestamp, body)
265+
)
266+
response = app.dispatch(request)
267+
assert response.status == 200
268+
269+
sleep(1) # wait a bit after auto ack()
270+
assert self.mock_received_requests["/chat.postMessage"] == 2
271+
272+
def test_member_join_left_events(self):
273+
app = App(client=self.web_client, signing_secret=self.signing_secret)
274+
275+
join_event_body = {
276+
"token": "verification_token",
277+
"team_id": "T111",
278+
"enterprise_id": "E111",
279+
"api_app_id": "A111",
280+
"event": {
281+
"type": "member_joined_channel",
282+
"user": "U999", # not self
283+
"channel": "C111",
284+
"channel_type": "C",
285+
"team": "T111",
286+
"inviter": "U222",
287+
},
288+
"type": "event_callback",
289+
"event_id": "Ev111",
290+
"event_time": 1599616881,
291+
"authed_users": ["W111"],
292+
}
293+
294+
left_event_body = {
295+
"token": "verification_token",
296+
"team_id": "T111",
297+
"enterprise_id": "E111",
298+
"api_app_id": "A111",
299+
"event": {
300+
"type": "member_left_channel",
301+
"user": "U999", # not self
302+
"channel": "C111",
303+
"channel_type": "C",
304+
"team": "T111",
305+
},
306+
"type": "event_callback",
307+
"event_id": "Ev111",
308+
"event_time": 1599616881,
309+
"authed_users": ["W111"],
310+
}
311+
312+
@app.event("member_joined_channel")
313+
def handle_app_mention(say):
314+
say("What's up?")
315+
316+
@app.event("member_left_channel")
317+
def handle_app_mention(say):
318+
say("What's up?")
319+
320+
timestamp, body = str(int(time())), json.dumps(join_event_body)
321+
request: BoltRequest = BoltRequest(
322+
body=body, headers=self.build_headers(timestamp, body)
323+
)
324+
response = app.dispatch(request)
325+
assert response.status == 200
326+
assert self.mock_received_requests["/auth.test"] == 1
327+
328+
timestamp, body = str(int(time())), json.dumps(left_event_body)
329+
request: BoltRequest = BoltRequest(
330+
body=body, headers=self.build_headers(timestamp, body)
331+
)
332+
response = app.dispatch(request)
333+
assert response.status == 200
334+
335+
sleep(1) # wait a bit after auto ack()
336+
# the listeners should not be executed
337+
assert self.mock_received_requests["/chat.postMessage"] == 2

tests/scenario_tests_async/test_events.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,182 @@ async def test_stable_auto_ack(self):
139139
response = await app.async_dispatch(request)
140140
assert response.status == 200
141141

142+
@pytest.mark.asyncio
143+
async def test_self_events(self):
144+
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,)
145+
app.event("reaction_added")(whats_up)
146+
147+
self_event = {
148+
"token": "verification_token",
149+
"team_id": "T111",
150+
"enterprise_id": "E111",
151+
"api_app_id": "A111",
152+
"event": {
153+
"type": "reaction_added",
154+
"user": "W23456789", # bot_user_id
155+
"item": {
156+
"type": "message",
157+
"channel": "C111",
158+
"ts": "1599529504.000400",
159+
},
160+
"reaction": "heart_eyes",
161+
"item_user": "W111",
162+
"event_ts": "1599616881.000800",
163+
},
164+
"type": "event_callback",
165+
"event_id": "Ev111",
166+
"event_time": 1599616881,
167+
"authed_users": ["W111"],
168+
}
169+
timestamp, body = str(int(time())), json.dumps(self_event)
170+
request = AsyncBoltRequest(
171+
body=body, headers=self.build_headers(timestamp, body)
172+
)
173+
response = await app.async_dispatch(request)
174+
assert response.status == 200
175+
assert self.mock_received_requests["/auth.test"] == 1
176+
await asyncio.sleep(1) # wait a bit after auto ack()
177+
# The listener should not be executed
178+
assert self.mock_received_requests.get("/chat.postMessage") is None
179+
180+
@pytest.mark.asyncio
181+
async def test_self_joined_left_events(self):
182+
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,)
183+
app.event("reaction_added")(whats_up)
184+
185+
join_event_body = {
186+
"token": "verification_token",
187+
"team_id": "T111",
188+
"enterprise_id": "E111",
189+
"api_app_id": "A111",
190+
"event": {
191+
"type": "member_joined_channel",
192+
"user": "W23456789", # bot_user_id
193+
"channel": "C111",
194+
"channel_type": "C",
195+
"team": "T111",
196+
"inviter": "U222",
197+
},
198+
"type": "event_callback",
199+
"event_id": "Ev111",
200+
"event_time": 1599616881,
201+
"authed_users": ["W111"],
202+
}
203+
204+
left_event_body = {
205+
"token": "verification_token",
206+
"team_id": "T111",
207+
"enterprise_id": "E111",
208+
"api_app_id": "A111",
209+
"event": {
210+
"type": "member_left_channel",
211+
"user": "W23456789", # bot_user_id
212+
"channel": "C111",
213+
"channel_type": "C",
214+
"team": "T111",
215+
},
216+
"type": "event_callback",
217+
"event_id": "Ev111",
218+
"event_time": 1599616881,
219+
"authed_users": ["W111"],
220+
}
221+
222+
@app.event("member_joined_channel")
223+
async def handle_member_joined_channel(say):
224+
await say("What's up?")
225+
226+
@app.event("member_left_channel")
227+
async def handle_member_left_channel(say):
228+
await say("What's up?")
229+
230+
timestamp, body = str(int(time())), json.dumps(join_event_body)
231+
request = AsyncBoltRequest(
232+
body=body, headers=self.build_headers(timestamp, body)
233+
)
234+
response = await app.async_dispatch(request)
235+
assert response.status == 200
236+
assert self.mock_received_requests["/auth.test"] == 1
237+
238+
timestamp, body = str(int(time())), json.dumps(left_event_body)
239+
request = AsyncBoltRequest(
240+
body=body, headers=self.build_headers(timestamp, body)
241+
)
242+
response = await app.async_dispatch(request)
243+
assert response.status == 200
244+
245+
await asyncio.sleep(1) # wait a bit after auto ack()
246+
# The listeners should be executed
247+
assert self.mock_received_requests.get("/chat.postMessage") == 2
248+
249+
@pytest.mark.asyncio
250+
async def test_joined_left_events(self):
251+
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,)
252+
app.event("reaction_added")(whats_up)
253+
254+
join_event_body = {
255+
"token": "verification_token",
256+
"team_id": "T111",
257+
"enterprise_id": "E111",
258+
"api_app_id": "A111",
259+
"event": {
260+
"type": "member_joined_channel",
261+
"user": "W111", # other user
262+
"channel": "C111",
263+
"channel_type": "C",
264+
"team": "T111",
265+
"inviter": "U222",
266+
},
267+
"type": "event_callback",
268+
"event_id": "Ev111",
269+
"event_time": 1599616881,
270+
"authed_users": ["W111"],
271+
}
272+
273+
left_event_body = {
274+
"token": "verification_token",
275+
"team_id": "T111",
276+
"enterprise_id": "E111",
277+
"api_app_id": "A111",
278+
"event": {
279+
"type": "member_left_channel",
280+
"user": "W111", # other user
281+
"channel": "C111",
282+
"channel_type": "C",
283+
"team": "T111",
284+
},
285+
"type": "event_callback",
286+
"event_id": "Ev111",
287+
"event_time": 1599616881,
288+
"authed_users": ["W111"],
289+
}
290+
291+
@app.event("member_joined_channel")
292+
async def handle_member_joined_channel(say):
293+
await say("What's up?")
294+
295+
@app.event("member_left_channel")
296+
async def handle_member_left_channel(say):
297+
await say("What's up?")
298+
299+
timestamp, body = str(int(time())), json.dumps(join_event_body)
300+
request = AsyncBoltRequest(
301+
body=body, headers=self.build_headers(timestamp, body)
302+
)
303+
response = await app.async_dispatch(request)
304+
assert response.status == 200
305+
assert self.mock_received_requests["/auth.test"] == 1
306+
307+
timestamp, body = str(int(time())), json.dumps(left_event_body)
308+
request = AsyncBoltRequest(
309+
body=body, headers=self.build_headers(timestamp, body)
310+
)
311+
response = await app.async_dispatch(request)
312+
assert response.status == 200
313+
314+
await asyncio.sleep(1) # wait a bit after auto ack()
315+
# The listeners should be executed
316+
assert self.mock_received_requests.get("/chat.postMessage") == 2
317+
142318

143319
app_mention_body = {
144320
"token": "verification_token",

0 commit comments

Comments
 (0)