diff --git a/src/dispatch/case/flows.py b/src/dispatch/case/flows.py index d92758f1e6cb..b794e8ce4182 100644 --- a/src/dispatch/case/flows.py +++ b/src/dispatch/case/flows.py @@ -184,19 +184,19 @@ def case_remove_participant_flow( ) # we also try to remove the user from the Slack conversation - try: - slack_conversation_plugin = plugin_service.get_active_instance( - db_session=db_session, project_id=case.project.id, plugin_type="conversation" - ) + slack_conversation_plugin = plugin_service.get_active_instance( + db_session=db_session, project_id=case.project.id, plugin_type="conversation" + ) - if not slack_conversation_plugin: - log.warning(f"{user_email} not updated. No conversation plugin enabled.") - return + if not slack_conversation_plugin: + log.warning(f"{user_email} not updated. No conversation plugin enabled.") + return - if not case.conversation: - log.warning("No conversation enabled for this case.") - return + if not case.conversation: + log.warning("No conversation enabled for this case.") + return + try: slack_conversation_plugin.instance.remove_user( conversation_id=case.conversation.channel_id, user_email=user_email diff --git a/src/dispatch/incident/flows.py b/src/dispatch/incident/flows.py index e9c63bd3fb30..76c41e14569c 100644 --- a/src/dispatch/incident/flows.py +++ b/src/dispatch/incident/flows.py @@ -1178,19 +1178,19 @@ def incident_remove_participant_flow( ) # we also try to remove the user from the Slack conversation - try: - slack_conversation_plugin = plugin_service.get_active_instance( - db_session=db_session, project_id=incident.project.id, plugin_type="conversation" - ) + slack_conversation_plugin = plugin_service.get_active_instance( + db_session=db_session, project_id=incident.project.id, plugin_type="conversation" + ) - if not slack_conversation_plugin: - log.warning(f"{user_email} not updated. No conversation plugin enabled.") - return + if not slack_conversation_plugin: + log.warning(f"{user_email} not updated. No conversation plugin enabled.") + return - if not incident.conversation: - log.warning("No conversation enabled for this incident.") - return + if not incident.conversation: + log.warning("No conversation enabled for this incident.") + return + try: slack_conversation_plugin.instance.remove_user( conversation_id=incident.conversation.channel_id, user_email=user_email diff --git a/src/dispatch/plugins/dispatch_slack/case/interactive.py b/src/dispatch/plugins/dispatch_slack/case/interactive.py index 3b63186c3fa8..f960ad509f3d 100644 --- a/src/dispatch/plugins/dispatch_slack/case/interactive.py +++ b/src/dispatch/plugins/dispatch_slack/case/interactive.py @@ -469,7 +469,23 @@ def engage( return engagement = form_data[DefaultBlockIds.description_input] - user = client.users_lookupByEmail(email=user_email) + + try: + user = client.users_lookupByEmail(email=user_email) + except SlackApiError as e: + if e.response.get("error") == SlackAPIErrorCode.USERS_NOT_FOUND: + log.warning( + f"Failed to find Slack user for email {user_email}. " + "User may have been deactivated or never had Slack access." + ) + client.chat_postMessage( + text=f"Unable to engage user {user_email} - user not found in Slack workspace.", + channel=case.conversation.channel_id, + thread_ts=case.conversation.thread_id if case.has_thread else None, + ) + return + else: + raise result = client.chat_postMessage( text="Engaging user...", @@ -1983,9 +1999,19 @@ def edit_button_click( ack() case = case_service.get(db_session=db_session, case_id=int(context["subject"].id)) - assignee_initial_user = client.users_lookupByEmail(email=case.assignee.individual.email)[ - "user" - ]["id"] + try: + assignee_initial_user = client.users_lookupByEmail(email=case.assignee.individual.email)[ + "user" + ]["id"] + except SlackApiError as e: + if e.response.get("error") == SlackAPIErrorCode.USERS_NOT_FOUND: + log.warning( + f"Assignee {case.assignee.individual.email} not found in Slack workspace. " + "Using None for initial assignee selection." + ) + assignee_initial_user = None + else: + raise blocks = [ title_input(initial_value=case.title), diff --git a/src/dispatch/plugins/dispatch_slack/plugin.py b/src/dispatch/plugins/dispatch_slack/plugin.py index 8b47fe63d15d..8436456b8304 100644 --- a/src/dispatch/plugins/dispatch_slack/plugin.py +++ b/src/dispatch/plugins/dispatch_slack/plugin.py @@ -390,13 +390,48 @@ def set_description(self, conversation_id: str, description: str): return set_conversation_description(client, conversation_id, description) def remove_user(self, conversation_id: str, user_email: str): - """Removes a user from a conversation.""" + """Removes a user from a conversation. + + Args: + conversation_id: The Slack conversation/channel ID + user_email: The email address of the user to remove + + Returns: + The API response if successful, None if user not found + + Raises: + SlackApiError: For non-recoverable Slack API errors + """ client = create_slack_client(self.configuration) - user_id = resolve_user(client, user_email).get("id") - if user_id: - return remove_member_from_channel( - client=client, conversation_id=conversation_id, user_id=user_id - ) + + try: + user_info = resolve_user(client, user_email) + user_id = user_info.get("id") + + if user_id: + return remove_member_from_channel( + client=client, conversation_id=conversation_id, user_id=user_id + ) + else: + logger.warning( + "Cannot remove user %s from conversation %s: " + "User ID not found in resolve_user response", + user_email, conversation_id + ) + return None + + except SlackApiError as e: + if e.response.get("error") == SlackAPIErrorCode.USERS_NOT_FOUND: + logger.warning( + "User %s not found in Slack workspace. " + "Cannot remove from conversation %s. " + "User may have been deactivated or never had Slack access.", + user_email, conversation_id + ) + return None + else: + # Re-raise for other Slack API errors + raise def add_bookmark(self, conversation_id: str, weblink: str, title: str): """Adds a bookmark to the conversation."""