From 4aa4af8ceb38088465256a9ce1eda47d41944942 Mon Sep 17 00:00:00 2001 From: Aaron Herman Date: Wed, 6 Aug 2025 14:03:20 -0500 Subject: [PATCH 1/7] Toggle Report Incident button by project, add Report Security Event to top nav --- .../versions/2025-08-06_f2bce475e71b.py | 23 +++++++++++ src/dispatch/project/models.py | 8 +++- .../dispatch/src/components/AppToolbar.vue | 7 ++++ .../static/dispatch/src/incident/Table.vue | 38 ++++++++++++++++++- .../dispatch/src/project/NewEditSheet.vue | 8 ++++ .../static/dispatch/src/project/store.js | 9 +++++ 6 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py diff --git a/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py b/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py new file mode 100644 index 000000000000..36cdc664cef8 --- /dev/null +++ b/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py @@ -0,0 +1,23 @@ +"""Adds support for configuring the reporting security incidents in the project model. + +Revision ID: f2bce475e71b +Revises: 408118048599 +Create Date: 2025-08-06 09:48:16.045362 + +""" +from alembic import op +import sqlalchemy as sa + + +revision = 'f2bce475e71b' +down_revision = '408118048599' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column('project', sa.Column('show_report_incident_button', sa.Boolean(), server_default='t', nullable=True)) + + +def downgrade(): + op.drop_column('project', 'show_report_incident_button') diff --git a/src/dispatch/project/models.py b/src/dispatch/project/models.py index 4adcece43fc7..f3fffa992a11 100644 --- a/src/dispatch/project/models.py +++ b/src/dispatch/project/models.py @@ -67,6 +67,9 @@ class Project(Base): report_incident_title_hint = Column(String, nullable=True) report_incident_description_hint = Column(String, nullable=True) + # controls visibility of the "Report Incident" button + show_report_incident_button = Column(Boolean, default=True, server_default="t") + snooze_extension_oncall_service_id = Column(Integer, nullable=True) snooze_extension_oncall_service = relationship( "Service", @@ -116,6 +119,7 @@ class ProjectBase(DispatchBase): report_incident_instructions: str | None = None report_incident_title_hint: str | None = None report_incident_description_hint: str | None = None + show_report_incident_button: bool | None = Field(True) snooze_extension_oncall_service: Service | None = None @@ -127,8 +131,8 @@ class ProjectUpdate(ProjectBase): send_daily_reports: bool | None = Field(True) send_weekly_reports: bool | None = Field(False) weekly_report_notification_id: int | None = None - stable_priority_id: int | None - snooze_extension_oncall_service_id: int | None + stable_priority_id: int | None = None + snooze_extension_oncall_service_id: int | None = None class ProjectRead(ProjectBase): diff --git a/src/dispatch/static/dispatch/src/components/AppToolbar.vue b/src/dispatch/static/dispatch/src/components/AppToolbar.vue index 82e46655f446..6472420251d6 100644 --- a/src/dispatch/static/dispatch/src/components/AppToolbar.vue +++ b/src/dispatch/static/dispatch/src/components/AppToolbar.vue @@ -23,6 +23,10 @@ /> + + mdi-shield-search + Report Security Event + @@ -224,6 +228,9 @@ export default { localStorage.setItem("dark_theme", this.$vuetify.theme.global.current.dark.toString()) this.dark_theme = !this.dark_theme }, + navigateToEventReport() { + this.$router.push({ name: "eventReport" }) + }, switchOrganizations(slug) { this.$router.push({ params: { organization: slug } }).then(() => { this.$router.go() diff --git a/src/dispatch/static/dispatch/src/incident/Table.vue b/src/dispatch/static/dispatch/src/incident/Table.vue index 63ee2f04f060..0fb2e76d48a4 100644 --- a/src/dispatch/static/dispatch/src/incident/Table.vue +++ b/src/dispatch/static/dispatch/src/incident/Table.vue @@ -14,7 +14,15 @@ - + mdi-fire Report incident @@ -246,11 +254,32 @@ export default { return d }, }, + + shouldShowReportButton() { + // Return false if projects haven't loaded yet + if (!this.defaultUserProjects || this.defaultUserProjects.length === 0) { + return false + } + + // Check if any of the default projects have the report button enabled + const hasEnabledProject = this.defaultUserProjects.some( + (project) => project.show_report_incident_button !== false + ) + + // If projects have the button enabled, show it + if (hasEnabledProject) { + return true + } + + // If no projects have the button enabled, only show for admin/owner users + return this.userAdminOrAbove(this.current_user_role) + }, }, methods: { ...mapActions("incident", ["getAll", "showNewSheet", "showDeleteDialog", "showReportDialog"]), ...mapActions("workflow", ["showRun"]), + ...mapActions("auth", ["refreshCurrentUser"]), showIncidentEditSheet(e, { item }) { this.$router.push({ name: "IncidentTableEdit", params: { name: item.name } }) }, @@ -270,6 +299,13 @@ export default { }, created() { + // Fetch user projects if they're not loaded + if (!this.projects || this.projects.length === 0) { + this.refreshCurrentUser().catch((error) => { + console.error("Failed to refresh user projects:", error) + }) + } + this.filters = { ...this.filters, ...RouterUtils.deserializeFilters(this.$route.query), diff --git a/src/dispatch/static/dispatch/src/project/NewEditSheet.vue b/src/dispatch/static/dispatch/src/project/NewEditSheet.vue index 30a93c5a9f15..68313b87a5f3 100644 --- a/src/dispatch/static/dispatch/src/project/NewEditSheet.vue +++ b/src/dispatch/static/dispatch/src/project/NewEditSheet.vue @@ -182,6 +182,13 @@ /> Report incident card settings + + + { storage_use_title: false, allow_self_join: null, select_commander_visibility: null, + show_report_incident_button: null, + stable_priority_id: null, + snooze_extension_oncall_service_id: null, + report_incident_instructions: null, + report_incident_title_hint: null, + report_incident_description_hint: null, + send_daily_reports: null, + send_weekly_reports: null, + weekly_report_notification_id: null, } } From 36e3dbf8051d06ea8725fc60c2ba3de0969322f2 Mon Sep 17 00:00:00 2001 From: Aaron Herman Date: Fri, 8 Aug 2025 15:05:28 -0500 Subject: [PATCH 2/7] Switch to adding a footnote suggestion on Incident page Instead of hiding the Report Incident button --- .../versions/2025-08-06_f2bce475e71b.py | 6 +-- src/dispatch/project/models.py | 6 +-- .../src/incident/ReportSubmissionCard.vue | 48 ++++++++++++++----- .../static/dispatch/src/incident/Table.vue | 38 +-------------- .../dispatch/src/project/NewEditSheet.vue | 8 ++-- .../static/dispatch/src/project/store.js | 2 +- 6 files changed, 47 insertions(+), 61 deletions(-) diff --git a/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py b/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py index 36cdc664cef8..4b1f14c887b0 100644 --- a/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py +++ b/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py @@ -1,4 +1,4 @@ -"""Adds support for configuring the reporting security incidents in the project model. +"""Adds support for configuring security event suggestions in the project model. Revision ID: f2bce475e71b Revises: 408118048599 @@ -16,8 +16,8 @@ def upgrade(): - op.add_column('project', sa.Column('show_report_incident_button', sa.Boolean(), server_default='t', nullable=True)) + op.add_column('project', sa.Column('suggest_security_event_over_incident', sa.Boolean(), server_default='t', nullable=True)) def downgrade(): - op.drop_column('project', 'show_report_incident_button') + op.drop_column('project', 'suggest_security_event_over_incident') diff --git a/src/dispatch/project/models.py b/src/dispatch/project/models.py index f3fffa992a11..34591b737d66 100644 --- a/src/dispatch/project/models.py +++ b/src/dispatch/project/models.py @@ -67,8 +67,8 @@ class Project(Base): report_incident_title_hint = Column(String, nullable=True) report_incident_description_hint = Column(String, nullable=True) - # controls visibility of the "Report Incident" button - show_report_incident_button = Column(Boolean, default=True, server_default="t") + # controls whether to suggest security events over incidents + suggest_security_event_over_incident = Column(Boolean, default=True, server_default="t") snooze_extension_oncall_service_id = Column(Integer, nullable=True) snooze_extension_oncall_service = relationship( @@ -119,7 +119,7 @@ class ProjectBase(DispatchBase): report_incident_instructions: str | None = None report_incident_title_hint: str | None = None report_incident_description_hint: str | None = None - show_report_incident_button: bool | None = Field(True) + suggest_security_event_over_incident: bool | None = Field(True) snooze_extension_oncall_service: Service | None = None diff --git a/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue b/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue index 0ecae04b9f79..aad1bd90b12c 100644 --- a/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue +++ b/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue @@ -100,19 +100,41 @@ - - Submit - - +
+ + +
+ Consider reporting as a Security Event instead +
+ If this is a security-related event for SIRT, please consider using the + + Security Event reporting page + + for better handling and response. +
+
+ + Submit + + +
diff --git a/src/dispatch/static/dispatch/src/incident/Table.vue b/src/dispatch/static/dispatch/src/incident/Table.vue index 0fb2e76d48a4..63ee2f04f060 100644 --- a/src/dispatch/static/dispatch/src/incident/Table.vue +++ b/src/dispatch/static/dispatch/src/incident/Table.vue @@ -14,15 +14,7 @@ - + mdi-fire Report incident @@ -254,32 +246,11 @@ export default { return d }, }, - - shouldShowReportButton() { - // Return false if projects haven't loaded yet - if (!this.defaultUserProjects || this.defaultUserProjects.length === 0) { - return false - } - - // Check if any of the default projects have the report button enabled - const hasEnabledProject = this.defaultUserProjects.some( - (project) => project.show_report_incident_button !== false - ) - - // If projects have the button enabled, show it - if (hasEnabledProject) { - return true - } - - // If no projects have the button enabled, only show for admin/owner users - return this.userAdminOrAbove(this.current_user_role) - }, }, methods: { ...mapActions("incident", ["getAll", "showNewSheet", "showDeleteDialog", "showReportDialog"]), ...mapActions("workflow", ["showRun"]), - ...mapActions("auth", ["refreshCurrentUser"]), showIncidentEditSheet(e, { item }) { this.$router.push({ name: "IncidentTableEdit", params: { name: item.name } }) }, @@ -299,13 +270,6 @@ export default { }, created() { - // Fetch user projects if they're not loaded - if (!this.projects || this.projects.length === 0) { - this.refreshCurrentUser().catch((error) => { - console.error("Failed to refresh user projects:", error) - }) - } - this.filters = { ...this.filters, ...RouterUtils.deserializeFilters(this.$route.query), diff --git a/src/dispatch/static/dispatch/src/project/NewEditSheet.vue b/src/dispatch/static/dispatch/src/project/NewEditSheet.vue index 68313b87a5f3..b1f9053da88d 100644 --- a/src/dispatch/static/dispatch/src/project/NewEditSheet.vue +++ b/src/dispatch/static/dispatch/src/project/NewEditSheet.vue @@ -184,9 +184,9 @@ Report incident card settings @@ -271,7 +271,7 @@ export default { "selected.report_incident_instructions", "selected.report_incident_title_hint", "selected.report_incident_description_hint", - "selected.show_report_incident_button", + "selected.suggest_security_event_over_incident", "selected.snooze_extension_oncall_service", "dialogs.showCreateEdit", ]), diff --git a/src/dispatch/static/dispatch/src/project/store.js b/src/dispatch/static/dispatch/src/project/store.js index 2c0797ab202c..0872ec441994 100644 --- a/src/dispatch/static/dispatch/src/project/store.js +++ b/src/dispatch/static/dispatch/src/project/store.js @@ -22,7 +22,7 @@ const getDefaultSelectedState = () => { storage_use_title: false, allow_self_join: null, select_commander_visibility: null, - show_report_incident_button: null, + suggest_security_event_over_incident: null, stable_priority_id: null, snooze_extension_oncall_service_id: null, report_incident_instructions: null, From 7f0e39df740194336f2c94ef24f4d9f0172f0552 Mon Sep 17 00:00:00 2001 From: Aaron Herman <12768929+aaronherman@users.noreply.github.com> Date: Fri, 8 Aug 2025 15:12:39 -0500 Subject: [PATCH 3/7] Update src/dispatch/project/models.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Aaron Herman <12768929+aaronherman@users.noreply.github.com> --- src/dispatch/project/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dispatch/project/models.py b/src/dispatch/project/models.py index 34591b737d66..4278858d2a46 100644 --- a/src/dispatch/project/models.py +++ b/src/dispatch/project/models.py @@ -68,7 +68,7 @@ class Project(Base): report_incident_description_hint = Column(String, nullable=True) # controls whether to suggest security events over incidents - suggest_security_event_over_incident = Column(Boolean, default=True, server_default="t") + suggest_security_event_over_incident = Column(Boolean, default=False, server_default="f") snooze_extension_oncall_service_id = Column(Integer, nullable=True) snooze_extension_oncall_service = relationship( From c6d9640ce654bf5dd7c5edd58a33d42378175721 Mon Sep 17 00:00:00 2001 From: Aaron Herman Date: Mon, 11 Aug 2025 11:36:27 -0500 Subject: [PATCH 4/7] Only show "Report Security Event" if a project prefers security events --- .../dispatch/src/components/AppToolbar.vue | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/dispatch/static/dispatch/src/components/AppToolbar.vue b/src/dispatch/static/dispatch/src/components/AppToolbar.vue index 6472420251d6..b00899c9b723 100644 --- a/src/dispatch/static/dispatch/src/components/AppToolbar.vue +++ b/src/dispatch/static/dispatch/src/components/AppToolbar.vue @@ -23,7 +23,14 @@ /> - + mdi-shield-search Report Security Event @@ -151,6 +158,7 @@ import OrganizationApi from "@/organization/api" import OrganizationCreateEditDialog from "@/organization/CreateEditDialog.vue" import UserApi from "@/auth/api" import CurrentUserAvatar from "@/atomics/CurrentUserAvatar.vue" +import { mapFields } from "vuex-map-fields" export default { name: "AppToolbar", @@ -167,6 +175,7 @@ export default { CurrentUserAvatar, }, computed: { + ...mapFields("auth", ["currentUser.projects"]), queryString: { set(query) { this.$store.dispatch("search/setQuery", query) @@ -196,6 +205,18 @@ export default { }) }, }, + defaultUserProjects() { + if (!this.projects || this.projects.length === 0) { + return [] + } + return this.projects.filter((v) => v.default === true).map((v) => v.project) + }, + shouldShowSecurityEventButton() { + // Check if any of the default projects have the security event suggestion enabled + return this.defaultUserProjects.some( + (project) => project.suggest_security_event_over_incident === true + ) + }, }, methods: { updateExperimentalFeatures() { @@ -238,7 +259,7 @@ export default { }, ...mapState("auth", ["currentUser"]), ...mapState("app", ["currentVersion"]), - ...mapActions("auth", ["logout", "getExperimentalFeatures"]), + ...mapActions("auth", ["logout", "getExperimentalFeatures", "refreshCurrentUser"]), ...mapActions("search", ["setQuery"]), ...mapActions("organization", ["showCreateEditDialog"]), ...mapActions("app", ["showCommitMessage"]), @@ -273,6 +294,13 @@ export default { this.loading = false }) + // Fetch user projects if they're not loaded + if (!this.projects || this.projects.length === 0) { + this.refreshCurrentUser().catch((error) => { + console.error("Failed to refresh user projects:", error) + }) + } + this.getExperimentalFeatures() }, } From 586d669d7c0350a0912305590078169d300c387a Mon Sep 17 00:00:00 2001 From: Aaron Herman Date: Mon, 11 Aug 2025 13:21:47 -0500 Subject: [PATCH 5/7] Update AppToolbar.vue --- src/dispatch/static/dispatch/src/components/AppToolbar.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dispatch/static/dispatch/src/components/AppToolbar.vue b/src/dispatch/static/dispatch/src/components/AppToolbar.vue index b00899c9b723..bc9e6a53c4a8 100644 --- a/src/dispatch/static/dispatch/src/components/AppToolbar.vue +++ b/src/dispatch/static/dispatch/src/components/AppToolbar.vue @@ -258,7 +258,7 @@ export default { }) }, ...mapState("auth", ["currentUser"]), - ...mapState("app", ["currentVersion"]), + ...mapState("app", ["currentVersion", "currentVersionDate"]), ...mapActions("auth", ["logout", "getExperimentalFeatures", "refreshCurrentUser"]), ...mapActions("search", ["setQuery"]), ...mapActions("organization", ["showCreateEditDialog"]), From 8d745fcc0ee225787de91184c86bf7c6ecad2c51 Mon Sep 17 00:00:00 2001 From: Aaron Herman Date: Thu, 14 Aug 2025 11:54:25 -0500 Subject: [PATCH 6/7] Update ReportSubmissionCard.vue --- .../static/dispatch/src/incident/ReportSubmissionCard.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue b/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue index aad1bd90b12c..18a8b2412c4c 100644 --- a/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue +++ b/src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue @@ -114,7 +114,7 @@
Consider reporting as a Security Event instead
- If this is a security-related event for SIRT, please consider using the + Please consider using the Security Event reporting page From 68cd8fe84caf3a0744daee539152d201ba5e44e3 Mon Sep 17 00:00:00 2001 From: Aaron Herman Date: Thu, 14 Aug 2025 12:03:26 -0500 Subject: [PATCH 7/7] Update 2025-08-06_f2bce475e71b.py --- .../revisions/tenant/versions/2025-08-06_f2bce475e71b.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py b/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py index 4b1f14c887b0..6e04bd650e4d 100644 --- a/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py +++ b/src/dispatch/database/revisions/tenant/versions/2025-08-06_f2bce475e71b.py @@ -10,7 +10,7 @@ revision = 'f2bce475e71b' -down_revision = '408118048599' +down_revision = '4649b11b683f' branch_labels = None depends_on = None