@@ -30,21 +30,30 @@ def process_slack_message_text(text):
3030 return re .sub (r"<@.*>(\|)?" , "" , text ).strip ()
3131
3232
33- def get_slack_user_email (slack_user_id , slack_bot_token ):
33+ def get_slack_user (slack_user_id , slack_bot_token ):
3434 http_request = requests .get (
3535 "https://slack.com/api/users.info" ,
3636 params = {
3737 "user" : slack_user_id ,
3838 },
39- headers = {"Authorization" : f"Bearer { slack_bot_token } " },
39+ headers = {
40+ "Authorization" : f"Bearer { slack_bot_token } " ,
41+ },
4042 )
43+
44+ slack_user = None
4145 if http_request .status_code == 200 :
42- return http_request .json ()[ "user" ][ "profile" ][ "email" ]
43- else :
44- return None
46+ http_response = http_request .json ()
47+ slack_user = http_response [ "user" ][ "profile" ]
48+ return slack_user
4549
4650
4751class SlackAppRunner (AppRunner ):
52+ def __init__ (self , * args , ** kwargs ):
53+ super ().__init__ (* args , ** kwargs )
54+ self ._slack_user = {}
55+ self ._slack_user_email = ""
56+
4857 def app_init (self ):
4958 self .slack_config = (
5059 SlackIntegrationConfig ().from_dict (
@@ -60,31 +69,38 @@ def app_init(self):
6069 self .app_run_request_user = self ._get_app_request_user (
6170 self .request .data ,
6271 )
63- self .session_id = self ._get_slack_app_seession_id (self .request .data )
72+ self .session_id = self ._get_slack_app_session_id (self .request .data )
6473 self .app_session = self ._get_or_create_app_session ()
6574
6675 def _get_app_request_user (self , slack_request_payload ):
67- self ._slack_user_email = ""
76+ request_user = AnonymousUser ()
77+
6878 if "event" in slack_request_payload and "user" in slack_request_payload ["event" ]:
79+ slack_user_id = slack_request_payload ["event" ]["user" ]
6980 try :
70- slack_user_id = slack_request_payload ["event" ]["user" ]
71- slack_user_email = get_slack_user_email (
72- slack_user_id ,
73- self .slack_bot_token ,
81+ self ._slack_user = (
82+ get_slack_user (
83+ slack_user_id ,
84+ self .slack_bot_token ,
85+ )
86+ or {}
7487 )
75- if slack_user_email is not None :
76- self ._slack_user_email = slack_user_email
77- user_object = User .objects .get (email = slack_user_email )
78- return user_object if user_object is not None else AnonymousUser ()
79- except Exception :
88+ # The email address of a Slack user is not guaranteed to be available for bot users.
89+ self ._slack_user_email = self ._slack_user .get ("email" ) or ""
90+ user_object = (
91+ User .objects .filter (email = self ._slack_user_email ).first () if self ._slack_user_email else None
92+ )
93+ if user_object :
94+ request_user = user_object
95+ except Exception as e :
8096 logger .exception (
81- f"Error in fetching user object from slack payload { slack_request_payload } " ,
97+ f"Error in fetching user object from slack payload { slack_request_payload } : { e } " ,
8298 )
8399
84- return AnonymousUser ()
100+ return request_user
85101
86- def _get_slack_app_seession_id (self , slack_request_payload ):
87- if slack_request_payload [ "type" ] == "event_callback" and "event" in slack_request_payload :
102+ def _get_slack_app_session_id (self , slack_request_payload ):
103+ if slack_request_payload . get ( "type" ) == "event_callback" and "event" in slack_request_payload :
88104 thread_ts = None
89105 session_identifier = None
90106 if "thread_ts" in slack_request_payload ["event" ]:
@@ -180,28 +196,37 @@ def _is_app_accessible(self):
180196 ):
181197 raise Exception ("Invalid Slack request" )
182198
183- # Verify the request type is either url_verification or event_callback
184- if self .request .data .get ("type" ) not in [
185- "event_callback" ,
186- "url_verification" ,
187- ]:
188- raise Exception ("Invalid Slack request" )
199+ request_type = self .request .data .get ("type" )
189200
190- # Verify the request is coming from the app we expect and the event
191- # type is app_mention
192- if self .request .data .get ("type" ) == "event_callback" and (
193- self .request .data .get (
194- "api_app_id" ,
195- )
196- != self .slack_config .get ("app_id" )
197- or self .request .data .get ("event" ).get ("type" ) != "app_mention"
198- ):
201+ # the request type should be either url_verification or event_callback
202+ is_valid_request_type = request_type in ["url_verification" , "event_callback" ]
203+ is_valid_app_token = self .request .data .get ("token" ) == self .slack_config .get ("verification_token" )
204+ is_valid_app_id = self .request .data .get ("api_app_id" ) == self .slack_config .get ("app_id" )
205+
206+ # Validate that the app token, app ID and the request type are all valid.
207+ if not (is_valid_app_token and is_valid_app_id and is_valid_request_type ):
199208 raise Exception ("Invalid Slack request" )
200209
201210 # URL verification is allowed without any further checks
202- if self . request . data . get ( "type" ) == "url_verification" :
211+ if request_type == "url_verification" :
203212 return True
204213
214+ # Verify the request is coming from the app we expect and the event
215+ # type is app_mention
216+ elif request_type == "event_callback" :
217+ event_data = self .request .data .get ("event" ) or {}
218+ event_type = event_data .get ("type" )
219+ channel_type = event_data .get ("channel_type" )
220+
221+ if event_type == "app_mention" :
222+ return True
223+
224+ elif event_type == "message" :
225+ # Only allow direct messages from users and not from bots
226+ if channel_type == "im" and "subtype" not in event_data and "bot_id" not in event_data :
227+ return True
228+ raise Exception ("Invalid Slack request" )
229+
205230 return super ()._is_app_accessible ()
206231
207232 def _get_csp (self ):
0 commit comments