Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Adds support for configuring security event suggestions 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 = '4649b11b683f'
branch_labels = None
depends_on = None


def upgrade():
op.add_column('project', sa.Column('suggest_security_event_over_incident', sa.Boolean(), server_default='t', nullable=True))


def downgrade():
op.drop_column('project', 'suggest_security_event_over_incident')
8 changes: 6 additions & 2 deletions src/dispatch/project/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class Project(Base):
report_incident_title_hint = Column(String, nullable=True)
report_incident_description_hint = Column(String, nullable=True)

# controls whether to suggest security events over incidents
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(
"Service",
Expand Down Expand Up @@ -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
suggest_security_event_over_incident: bool | None = Field(True)
snooze_extension_oncall_service: Service | None = None


Expand All @@ -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):
Expand Down
37 changes: 36 additions & 1 deletion src/dispatch/static/dispatch/src/components/AppToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@
/>
<v-spacer />
<v-toolbar-items>
<v-btn
v-if="shouldShowSecurityEventButton"
nav
variant="text"
@click="navigateToEventReport"
class="ml-2"
hide-details
>
<v-icon start color="error">mdi-shield-search</v-icon>
<span class="text-uppercase text-body-2 font-weight-bold">Report Security Event</span>
</v-btn>
<v-btn icon variant="text" @click="toggleDarkTheme">
<v-icon :icon="dark_theme ? 'mdi-white-balance-sunny' : 'mdi-moon-waxing-crescent'" />
<v-tooltip activator="parent" location="bottom">
Expand Down Expand Up @@ -153,6 +164,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",
Expand All @@ -169,6 +181,7 @@ export default {
CurrentUserAvatar,
},
computed: {
...mapFields("auth", ["currentUser.projects"]),
queryString: {
set(query) {
this.$store.dispatch("search/setQuery", query)
Expand Down Expand Up @@ -198,6 +211,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() {
Expand Down Expand Up @@ -230,14 +255,17 @@ 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()
})
},
...mapState("auth", ["currentUser"]),
...mapState("app", ["currentVersion", "currentVersionDate"]),
...mapActions("auth", ["logout", "getExperimentalFeatures"]),
...mapActions("auth", ["logout", "getExperimentalFeatures", "refreshCurrentUser"]),
...mapActions("search", ["setQuery"]),
...mapActions("organization", ["showCreateEditDialog"]),
...mapActions("app", ["showCommitMessage"]),
Expand Down Expand Up @@ -272,6 +300,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()
},
}
Expand Down
48 changes: 35 additions & 13 deletions src/dispatch/static/dispatch/src/incident/ReportSubmissionCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,41 @@
</v-row>
</v-card-text>
<v-card-actions>
<v-btn
color="info"
block
variant="flat"
:loading="loading"
:disabled="!isValid.value"
type="submit"
>
Submit
<template #loader>
<v-progress-linear indeterminate color="white" />
</template>
</v-btn>
<div class="w-100">
<v-alert
v-if="project?.suggest_security_event_over_incident"
type="warning"
variant="tonal"
class="mb-4"
density="compact"
>
<template #prepend>
<v-icon>mdi-security</v-icon>
</template>
<div>
<strong>Consider reporting as a Security Event instead</strong>
<br />
Please consider using the
<router-link :to="{ name: 'eventReport' }" class="text-decoration-none">
Security Event reporting page
</router-link>
for better handling and response.
</div>
</v-alert>
<v-btn
color="info"
block
variant="flat"
:loading="loading"
:disabled="!isValid.value"
type="submit"
>
Submit
<template #loader>
<v-progress-linear indeterminate color="white" />
</template>
</v-btn>
</div>
</v-card-actions>
</v-card>
</v-form>
Expand Down
8 changes: 8 additions & 0 deletions src/dispatch/static/dispatch/src/project/NewEditSheet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,13 @@
/>
</v-col>
<span class="text-body-1 text-medium-emphasis">Report incident card settings</span>
<v-col cols="12">
<v-checkbox
v-model="suggest_security_event_over_incident"
label="Suggest Security Event Over Incident"
hint="Controls whether to suggest security events over incidents for regular users. When enabled, security events are prioritized in the UI."
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="report_incident_instructions"
Expand Down Expand Up @@ -264,6 +271,7 @@ export default {
"selected.report_incident_instructions",
"selected.report_incident_title_hint",
"selected.report_incident_description_hint",
"selected.suggest_security_event_over_incident",
"selected.snooze_extension_oncall_service",
"dialogs.showCreateEdit",
]),
Expand Down
9 changes: 9 additions & 0 deletions src/dispatch/static/dispatch/src/project/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ const getDefaultSelectedState = () => {
storage_use_title: false,
allow_self_join: null,
select_commander_visibility: null,
suggest_security_event_over_incident: 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,
}
}

Expand Down
Loading