diff --git a/src/dispatch/plugins/dispatch_slack/case/interactive.py b/src/dispatch/plugins/dispatch_slack/case/interactive.py
index abf0175bf674..a4d6bf587424 100644
--- a/src/dispatch/plugins/dispatch_slack/case/interactive.py
+++ b/src/dispatch/plugins/dispatch_slack/case/interactive.py
@@ -39,7 +39,6 @@
from dispatch.participant_role import service as participant_role_service
from dispatch.participant_role.models import ParticipantRoleType
from dispatch.plugin import service as plugin_service
-from dispatch.plugins.dispatch_duo.enums import PushResponseResult
from dispatch.plugins.dispatch_slack import service as dispatch_slack_service
from dispatch.plugins.dispatch_slack.bolt import app
from dispatch.plugins.dispatch_slack.case.enums import (
@@ -860,8 +859,7 @@ def _create_snooze_filter(
db_session.commit()
# Check if last_mfa_time was within the last hour
- last_hour = datetime.now() - timedelta(hours=1)
- if (user.last_mfa_time and user.last_mfa_time > last_hour) or mfa_enabled is False:
+ if not mfa_enabled:
_create_snooze_filter(
db_session=db_session,
user=user,
@@ -874,12 +872,23 @@ def _create_snooze_filter(
message="Snooze Filter added successfully.",
)
else:
- # Send the MFA push notification
- response = mfa_plugin.instance.send_push_notification(
- username=context["user"].email,
- type="Are you creating a snooze filter in Dispatch?",
+ challenge, challenge_url = mfa_plugin.instance.create_mfa_challenge(
+ action="signal-snooze",
+ current_user=user,
+ db_session=db_session,
+ project_id=context["subject"].project_id,
+ )
+ ack_engagement_submission_event(
+ ack=ack, mfa_enabled=mfa_enabled, challenge_url=challenge_url
+ )
+
+ # wait for the mfa challenge
+ response = mfa_plugin.instance.wait_for_challenge(
+ challenge_id=challenge.challenge_id,
+ db_session=db_session,
)
- if response == PushResponseResult.allow:
+
+ if response == MfaChallengeStatus.APPROVED:
# Get the existing filters for the signal
_create_snooze_filter(
db_session=db_session,
@@ -895,10 +904,10 @@ def _create_snooze_filter(
user.last_mfa_time = datetime.now()
db_session.commit()
else:
- if response == PushResponseResult.timeout:
+ if response == MfaChallengeStatus.EXPIRED:
text = "Adding Snooze failed, the MFA request timed out."
- elif response == PushResponseResult.user_not_found:
- text = "Adding Snooze failed, user not found in MFA provider."
+ elif response == MfaChallengeStatus.DENIED:
+ text = "Adding Snooze failed, challenge did not complete succsfully."
else:
text = "Adding Snooze failed, you must accept the MFA prompt."
@@ -1735,7 +1744,7 @@ def report_issue(
Context(
elements=[
MarkdownText(
- text="Cases are meant to triage events that do not raise to the level of incidents, but can be escalated to incidents if necessary. If you suspect a security issue and need help, please fill out this form to the best of your abilities.."
+ text="Cases are meant for triaging events that do not raise to the level of incidents, but can be escalated to incidents if necessary."
)
]
),
@@ -1780,13 +1789,6 @@ def handle_report_project_select_action(
)
blocks = [
- Context(
- elements=[
- MarkdownText(
- text="Cases are meant to triage events that do not raise to the level of incidents, but can be escalated to incidents if necessary. If you suspect a security issue and need help, please fill out this form to the best of your abilities.."
- )
- ]
- ),
title_input(),
description_input(),
project_select(
@@ -1809,13 +1811,6 @@ def handle_report_project_select_action(
)
]
),
- case_priority_select(
- db_session=db_session,
- project_id=project.id,
- initial_option=None,
- optional=True,
- block_id=None, # ensures state is reset
- ),
]
modal = Modal(
@@ -1899,13 +1894,6 @@ def handle_report_case_type_select_action(
assignee_slack_id = None
blocks = [
- Context(
- elements=[
- MarkdownText(
- text="Cases are meant to triage events that do not raise to the level of incidents, but can be escalated to incidents if necessary. If you suspect a security issue and need help, please fill out this form to the best of your abilities."
- )
- ]
- ),
title_input(),
description_input(),
project_select(
@@ -1928,13 +1916,6 @@ def handle_report_case_type_select_action(
)
]
),
- case_priority_select(
- db_session=db_session,
- project_id=project.id,
- initial_option=None,
- optional=True,
- block_id=None, # ensures state is reset
- ),
]
# Create a new assignee_select block with a unique block_id
@@ -1944,7 +1925,7 @@ def handle_report_case_type_select_action(
initial_user=assignee_slack_id if assignee_slack_id else None,
action_id=CaseReportActions.assignee_select,
block_id=new_block_id,
- )
+ ),
)
# Conditionally add context blocks
@@ -1983,6 +1964,16 @@ def handle_report_case_type_select_action(
]
)
+ blocks.append(
+ case_priority_select(
+ db_session=db_session,
+ project_id=project.id,
+ initial_option=None,
+ optional=True,
+ block_id=None, # ensures state is reset
+ ),
+ )
+
modal = Modal(
title="Open a Case",
blocks=blocks,
diff --git a/src/dispatch/plugins/dispatch_slack/case/messages.py b/src/dispatch/plugins/dispatch_slack/case/messages.py
index 733e93ec4a3d..c4fd2993c601 100644
--- a/src/dispatch/plugins/dispatch_slack/case/messages.py
+++ b/src/dispatch/plugins/dispatch_slack/case/messages.py
@@ -152,19 +152,17 @@ def create_case_message(case: Case, channel_id: str) -> list[Block]:
Button(
text="Edit",
action_id=CaseNotificationActions.edit,
- style="primary",
value=button_metadata,
),
Button(
- text="Escalate",
- action_id=CaseNotificationActions.escalate,
- style="danger",
+ text=":slack: Create Channel",
+ action_id=CaseNotificationActions.migrate,
value=button_metadata,
),
Button(
- text="Create Channel",
- action_id=CaseNotificationActions.migrate,
- style="primary",
+ text="🔥 Escalate",
+ action_id=CaseNotificationActions.escalate,
+ style="danger",
value=button_metadata,
),
]
@@ -208,7 +206,7 @@ def create_signal_messages(case_id: int, channel_id: str, db_session: Session) -
# Define the initial elements with "Raw Data" and "Snooze" buttons
elements = [
Button(
- text="Snooze",
+ text="💤 Snooze",
action_id=SignalNotificationActions.snooze,
value=button_metadata,
),
@@ -219,7 +217,7 @@ def create_signal_messages(case_id: int, channel_id: str, db_session: Session) -
# If `first_instance_signal.external_url` is not empty, add the "Response Plan" button
elements.append(
Button(
- text="Response Plan",
+ text="🔖 Response Plan",
action_id="button-link",
url=first_instance_signal.external_url,
)
@@ -308,9 +306,13 @@ def create_genai_signal_summary(
instances = signal_service.get_instances_in_case(db_session=db_session, case_id=case.id)
(first_instance_id, first_instance_signal) = instances.first()
- related_cases = signal_service.get_cases_for_signal(
- db_session=db_session, signal_id=first_instance_signal.id
- ).filter(Case.id != case.id)
+ related_cases = (
+ signal_service.get_cases_for_signal(
+ db_session=db_session, signal_id=first_instance_signal.id
+ )
+ .from_self()
+ .filter(Case.id != case.id)
+ )
# Prepare historical context
historical_context = []
@@ -345,11 +347,19 @@ def create_genai_signal_summary(
genai_plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="artificial-intelligence"
)
+
if not genai_plugin:
+ log.warning("artificial-intelligence plugin not enabled, will not generate signal summary")
+ return signal_metadata_blocks
+
+ if not signal_instance.signal.genai_prompt:
+ log.warning(
+ f"artificial-intelligence plugin enabled but no prompt defined for {signal_instance.signal.name}"
+ )
return signal_metadata_blocks
response = genai_plugin.instance.chat_completion(
- prompt=f"""{first_instance_signal.prompt}
+ prompt=f"""{signal_instance.signal.genai_prompt}
Current Event:
{str(signal_instance.raw)}
diff --git a/src/dispatch/plugins/dispatch_slack/plugin.py b/src/dispatch/plugins/dispatch_slack/plugin.py
index 4907742fdb13..edf04edde695 100644
--- a/src/dispatch/plugins/dispatch_slack/plugin.py
+++ b/src/dispatch/plugins/dispatch_slack/plugin.py
@@ -122,18 +122,20 @@ def create_threaded(self, case: Case, conversation_id: str, db_session: Session)
except Exception as e:
logger.exception(f"Error uploading alert JSON to the Case thread: {e}")
- message = create_genai_signal_summary(
- case=case,
- channel_id=conversation_id,
- db_session=db_session,
- client=client,
- )
- send_message(
- client=client,
- conversation_id=conversation_id,
- ts=case.signal_thread_ts,
- blocks=message,
- )
+ try:
+ send_message(
+ client=client,
+ conversation_id=conversation_id,
+ ts=case.signal_thread_ts,
+ blocks=create_genai_signal_summary(
+ case=case,
+ channel_id=conversation_id,
+ db_session=db_session,
+ client=client,
+ ),
+ )
+ except Exception as e:
+ logger.exception(f"Error generating Gen AI response to case: {e}")
db_session.commit()
return response
diff --git a/src/dispatch/static/dispatch/src/signal/NewEditDialog.vue b/src/dispatch/static/dispatch/src/signal/NewEditDialog.vue
index adbb1cf96f72..0200e10f4f45 100644
--- a/src/dispatch/static/dispatch/src/signal/NewEditDialog.vue
+++ b/src/dispatch/static/dispatch/src/signal/NewEditDialog.vue
@@ -242,7 +242,6 @@
hint="The model to use for processing."
persistent-hint
name="model"
- readonly
/>
@@ -254,7 +253,6 @@
hint="The system message to set the behavior of the assistant"
persistent-hint
name="systemMessage"
- readonly
/>
@@ -266,7 +264,6 @@
hint="The prompt to use for the assistant."
persistent-hint
name="Prompt"
- readonly
/>