Repository navigation
feat(seer-slack): Check channel type for correct history scope before API call #112371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9260c79
be4faf2
0bfe302
99699e3
b0f7e2c
df63ce0
6b2065e
7d4484c
08a1c38
e01f3c1
78f49b6
efe4857
fed458f
68ea1ea
693fb1c
727e078
db819cf
58aa620
6a28028
6f4a9d9
a3e0075
2b6828c
e0a5532
be64318
e8fe855
475285a
5a2238f
8c39193
ed6579f
e9476fe
bf83740
eb603bd
d0b0951
f9d824d
48ab446
555218e
aedb432
4911b68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -261,6 +261,71 @@ def has_scope(self, scope: SlackScope) -> bool: | |||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return has_scope | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def has_history_scope(self, channel_id: str) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns whether this integration is allowed to access the history in the channel. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Checks if channels:history is installed for public channels, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| and check groups:history for private channels. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| The type of channel is determined by the conversations.info API call. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| history_scopes = [SlackScope.CHANNELS_HISTORY, SlackScope.GROUPS_HISTORY] | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah the bots got a point, I think you need
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh it's handled below, then maybe just slot this all under the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The bots were right, even if someone doesn't have neither Removed the early exit if neither of those history scopes are available |
||||||||||||||||||||||||||||||||||||||||||||||||||
| installed_scope_set = frozenset(self.model.metadata.get("scopes", [])) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| installed_history_scopes = [s in installed_scope_set for s in history_scopes] | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if all(installed_history_scopes): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
cursor[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| conversation_data = self.get_conversations_info(channel_id=channel_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd try/catch this in case this ever gets used somewhere else where users control what
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It already is try/catched in sentry/src/sentry/integrations/slack/integration.py Lines 300 to 323 in f9d824d
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| channel_info = conversation_data.get("channel", {}) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| is_channel = channel_info.get("is_channel", False) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| is_private = channel_info.get("is_private", False) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| is_im = channel_info.get("is_im", False) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # DMs and assistant threads: the bot is a participant and can | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # always read its own conversation history. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if is_im: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if is_private: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return SlackScope.GROUPS_HISTORY in installed_scope_set | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if is_channel: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return SlackScope.CHANNELS_HISTORY in installed_scope_set | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
cursor[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # Shouldn't reach here unless channel_info is empty (most likely | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+273
to
+297
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's worthwhile to add a
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a logger warning: |
||||||||||||||||||||||||||||||||||||||||||||||||||
| # an API error or an unrecognized conversation type). | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _logger.warning( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "slack.has_history_scope.unrecognized_channel_type", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| extra={"channel_id": channel_id, "channel_info": channel_info}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_conversations_info( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| channel_id: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> dict: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Fetch conversations info from Slack API. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| client = self.get_client() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| conversations = client.conversations_info( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| channel=channel_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| assert isinstance(conversations.data, dict) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
sentry[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return conversations.data | ||||||||||||||||||||||||||||||||||||||||||||||||||
| except (SlackApiError, AssertionError) as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _logger.warning( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "slack.get_conversations_info.error", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| extra={"channel_id": channel_id, "error": str(e)}, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return {} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_thread_history( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -271,7 +336,7 @@ def get_thread_history( | |||||||||||||||||||||||||||||||||||||||||||||||||
| Fetch thread replies using the conversations.replies API. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns a list of message dicts, or an empty list on error. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if not self.has_scope(SlackScope.CHANNELS_HISTORY): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if not self.has_history_scope(channel_id): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| client = self.get_client() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth adding the detail here that the check is different depending on the type of channel. And that type of channel will be determined by an API call in the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, added more detail in:
48ab446