diff --git a/requirements-base.txt b/requirements-base.txt index cac8a7c3a8d3..f36012d0736a 100644 --- a/requirements-base.txt +++ b/requirements-base.txt @@ -124,7 +124,7 @@ frozenlist==1.4.1 # aiosignal google-api-core==2.15.0 # via google-api-python-client -google-api-python-client==2.119.0 +google-api-python-client==2.120.0 # via -r requirements-base.in google-auth==2.26.1 # via @@ -320,7 +320,7 @@ pytest==7.4.4 # schemathesis pytest-subtests==0.7.0 # via schemathesis -python-dateutil==2.8.2 +python-dateutil==2.9.0.post0 # via # -r requirements-base.in # botocore diff --git a/requirements-dev.txt b/requirements-dev.txt index 4577c556386b..012a624561e4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -42,7 +42,7 @@ identify==2.5.33 # via pre-commit iniconfig==2.0.0 # via pytest -ipython==8.22.1 +ipython==8.22.2 # via -r requirements-dev.in jedi==0.19.1 # via ipython @@ -82,11 +82,11 @@ pygments==2.17.2 # ipython pytest==7.4.4 # via -r requirements-dev.in -python-dateutil==2.8.2 +python-dateutil==2.9.0.post0 # via faker pyyaml==6.0.1 # via pre-commit -ruff==0.2.2 +ruff==0.3.0 # via -r requirements-dev.in six==1.16.0 # via diff --git a/src/dispatch/plugins/dispatch_slack/case/enums.py b/src/dispatch/plugins/dispatch_slack/case/enums.py index 85afe463393f..0ff18ffa1ecc 100644 --- a/src/dispatch/plugins/dispatch_slack/case/enums.py +++ b/src/dispatch/plugins/dispatch_slack/case/enums.py @@ -39,7 +39,6 @@ class CaseShortcutCallbacks(DispatchEnum): class SignalNotificationActions(DispatchEnum): snooze = "signal-notification-snooze" - view = "signal-notification-view" class SignalSnoozeActions(DispatchEnum): diff --git a/src/dispatch/plugins/dispatch_slack/case/interactive.py b/src/dispatch/plugins/dispatch_slack/case/interactive.py index ca8f5cb77a42..1ecae9e23858 100644 --- a/src/dispatch/plugins/dispatch_slack/case/interactive.py +++ b/src/dispatch/plugins/dispatch_slack/case/interactive.py @@ -1473,35 +1473,6 @@ def handle_report_submission_event( ) -@app.action(SignalNotificationActions.view, middleware=[button_context_middleware, db_middleware]) -def signal_button_click( - ack: Ack, body: dict, db_session: Session, context: BoltContext, client: WebClient -): - ack() - signal = signal_service.get_signal_instance( - db_session=db_session, signal_instance_id=UUID(context["subject"].id) - ) - - # truncate text and redirect to ui - raw_text = json.dumps(signal.raw, indent=2) - if len(raw_text) > 2900: - blocks = [ - Section( - text="The alert data exceeds Slack's viewing limit. Please go to the Dispatch Web UI for full details.\n" - ), - Section(text=f"```{raw_text[:2750]}...```"), - ] - else: - blocks = [Section(text=f"```{raw_text}```")] - - modal = Modal( - title="Raw Signal", - blocks=blocks, - close="Close", - ).build() - client.views_open(trigger_id=body["trigger_id"], view=modal) - - @app.action( SignalEngagementActions.approve, middleware=[ diff --git a/src/dispatch/plugins/dispatch_slack/case/messages.py b/src/dispatch/plugins/dispatch_slack/case/messages.py index b87363390606..0d6e0990ca75 100644 --- a/src/dispatch/plugins/dispatch_slack/case/messages.py +++ b/src/dispatch/plugins/dispatch_slack/case/messages.py @@ -193,11 +193,6 @@ 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="Raw Data", - action_id=SignalNotificationActions.view, - value=button_metadata, - ), Button( text="Snooze", action_id=SignalNotificationActions.snooze, diff --git a/src/dispatch/plugins/dispatch_slack/enums.py b/src/dispatch/plugins/dispatch_slack/enums.py index 3f71ac513f82..a322480a8806 100644 --- a/src/dispatch/plugins/dispatch_slack/enums.py +++ b/src/dispatch/plugins/dispatch_slack/enums.py @@ -38,3 +38,4 @@ class SlackAPIErrorCode(DispatchEnum): VIEW_NOT_FOUND = "not_found" # Could not find corresponding view for the provided view_id VIEW_EXPIRED = "expired_trigger_id" # The provided trigger_id is no longer valid IS_ARCHIVED = "is_archived" # Channel is archived + MISSING_SCOPE = "missing_scope" diff --git a/src/dispatch/plugins/dispatch_slack/plugin.py b/src/dispatch/plugins/dispatch_slack/plugin.py index aa0c96feffd2..55d13c3a5bc3 100644 --- a/src/dispatch/plugins/dispatch_slack/plugin.py +++ b/src/dispatch/plugins/dispatch_slack/plugin.py @@ -5,7 +5,10 @@ :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ + from blockkit import Message +import io +import json import logging from typing import List, Optional, Any from slack_sdk.errors import SlackApiError @@ -13,6 +16,7 @@ from dispatch.auth.models import DispatchUser from dispatch.case.models import Case +from dispatch.config import DISPATCH_UI_URL from dispatch.conversation.enums import ConversationCommands from dispatch.decorators import apply, counter, timer from dispatch.plugin import service as plugin_service @@ -97,6 +101,23 @@ def create_threaded(self, case: Case, conversation_id: str, db_session: Session) blocks=message, ) case.signal_thread_ts = signal_response.get("timestamp") + try: + client.files_upload( + channels=conversation_id, + thread_ts=case.signal_thread_ts, + initial_comment=f"First alert in `{case.name}` (see all in <{DISPATCH_UI_URL}/{case.project.organization.slug}/cases/{case.name}|Dispatch UI>):", + filetype="json", + file=io.BytesIO(json.dumps(case.signal_instances[0].raw, indent=4).encode()), + ) + except SlackApiError as e: + if e.response["error"] == SlackAPIErrorCode.MISSING_SCOPE: + logger.exception( + f"Error uploading alert JSON to the Case thread due to missing scope: {e}" + ) + else: + logger.exception(f"Error uploading alert JSON to the Case thread: {e}") + except Exception as e: + logger.exception(f"Error uploading alert JSON to the Case thread: {e}") db_session.commit() return response diff --git a/src/dispatch/static/dispatch/package-lock.json b/src/dispatch/static/dispatch/package-lock.json index 7fb8eef002ab..d77036b124d4 100644 --- a/src/dispatch/static/dispatch/package-lock.json +++ b/src/dispatch/static/dispatch/package-lock.json @@ -923,12 +923,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0.tgz", - "integrity": "sha512-2k1HzC28Fs+HiwbJOQDUwrWMttqSLUVdjCqitBOjdCD0svWOMQUVqrXX6iFD7POps6xXAojsX/dGBpKnjZctLA==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz", + "integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==", "dev": true, "dependencies": { - "playwright": "1.42.0" + "playwright": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -1302,21 +1302,21 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.24.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.24.1.tgz", - "integrity": "sha512-DZ6Nx9p7BhjkG50ayJ+MKPgff+lMeol7QYXkvuU5jr2ryW/4ok5eanaS9W5eooA4xN0A/GPHdLGOZGzArgf5Cg==", + "version": "5.24.8", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.24.8.tgz", + "integrity": "sha512-yH7KnfXMf10p1U5GffTQzFi2Miiw6WJZImGYGdV7eqa5ZbKO8qVx9lOA9SfhIaJXomrMp1Yz5w/CBhVM3yWeTA==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/vue-query": { - "version": "5.24.1", - "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.24.1.tgz", - "integrity": "sha512-nynAGshOSIdeMWnIO/kq7FkxSv9hJEIOve1wrLlt03n9dV7JQ8YX9pSaqLezRlAXgWL9v0AesXlBtiOhxIdA0A==", + "version": "5.24.8", + "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.24.8.tgz", + "integrity": "sha512-JPPq57iS55J0ELnXgPaB387j9rZZ/zGyvUW3L4K9/Qx/jQVp0uo/E/sW7c0djCxBJ49beI+pNU2rPRFVvoxn9A==", "dependencies": { "@tanstack/match-sorter-utils": "^8.11.8", - "@tanstack/query-core": "5.24.1", + "@tanstack/query-core": "5.24.8", "@vue/devtools-api": "^6.5.1", "vue-demi": "^0.14.6" }, @@ -2140,9 +2140,9 @@ } }, "node_modules/@vue-flow/core": { - "version": "1.33.1", - "resolved": "https://registry.npmjs.org/@vue-flow/core/-/core-1.33.1.tgz", - "integrity": "sha512-Mg6uS1egUwWRls/EvSGwDdpDuQEEJV8e1WriL7TOpFg7YjgwNODFiVbyrjApauC7k05Fwajf7jASWds60Inr5g==", + "version": "1.33.2", + "resolved": "https://registry.npmjs.org/@vue-flow/core/-/core-1.33.2.tgz", + "integrity": "sha512-tart1LPzjXdQUjjnTcUnhgoCfD7VWquhdBzJYO1F0gEdlc0eo72SKSoQ6gYBaWfFnHw0nqJXDy8NZU9EA4IP7g==", "dependencies": { "@vueuse/core": "^10.5.0", "d3-drag": "^3.0.0", @@ -5492,12 +5492,12 @@ } }, "node_modules/playwright": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz", - "integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", + "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", "dev": true, "dependencies": { - "playwright-core": "1.42.0" + "playwright-core": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -5510,9 +5510,9 @@ } }, "node_modules/playwright-core": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz", - "integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", + "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -7011,9 +7011,9 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/vuetify": { - "version": "3.5.6", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.5.6.tgz", - "integrity": "sha512-PfKSnHaSEGoz1QNHZ2sutOYwmYxtBbxAaeRy0L0qtMWLkKtxheg0he/NX+lsP11I2LevQBj2AgeBYDMZ/oPkPQ==", + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.5.7.tgz", + "integrity": "sha512-BFj/puY8odRwY50pRfE1gpawnxreY8PtPb/tDw3oumxSLXhoXw8q6YLA6QUvqZrYEzcYpojxZIYhNWUky2KN1w==", "engines": { "node": "^12.20 || >=14.13" },