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
10 changes: 10 additions & 0 deletions src/dispatch/auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,16 @@ def get_me(
return current_user


@auth_router.get("/myrole")
def get_my_role(
*,
db_session: DbSession,
current_user: CurrentUser,
organization: OrganizationSlug,
):
return current_user.get_organization_role(organization)


@auth_router.post("/login", response_model=UserLoginResponse)
def login_user(
user_in: UserLogin,
Expand Down
3 changes: 3 additions & 0 deletions src/dispatch/static/dispatch/src/auth/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export default {
getUserInfo() {
return API.get(`/auth/me`)
},
getUserRole() {
return API.get(`/auth/myrole`)
},
login(email, password) {
return API.post(`/auth/login`, { email: email, password: password })
},
Expand Down
40 changes: 39 additions & 1 deletion src/dispatch/static/dispatch/src/case/ReportSubmissionCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ import CaseTypeSelect from "@/case/type/CaseTypeSelect.vue"
import CasePrioritySelect from "@/case/priority/CasePrioritySelect.vue"
import ProjectSelect from "@/project/ProjectSelect.vue"
import DocumentApi from "@/document/api"
import ProjectApi from "@/project/api"
import AuthApi from "@/auth/api"
import TagFilterAutoComplete from "@/tag/TagPicker.vue"
import SearchUtils from "@/search/utils"
import CaseTypeApi from "@/case/type/api"
Expand Down Expand Up @@ -155,7 +157,9 @@ export default {
"selected.ticket",
"selected.project",
"selected.id",
"default_project",
]),
...mapFields("auth", ["currentUser.projects"]),
},

watch: {
Expand Down Expand Up @@ -227,7 +231,41 @@ export default {

created() {
if (this.$route.query.project) {
this.project = { name: this.$route.query.project }
let params = {
filter: { field: "name", op: "==", value: this.$route.query.project },
}
// get full project object from api
ProjectApi.getAll(params).then((response) => {
if (response.data.items.length && !this.project) {
this.project = response.data.items[0]
}
})
} else if (this.projects.length && !this.project) {
this.project = this.projects[0].project
} else {
// if no user projects stored yet, get the default project for the user
// if no default user project, then get the default project for the organization
AuthApi.getUserInfo().then((response) => {
if (this.project) {
// if the user has already selected something, exit
return
}
let default_user_project = response.data.projects.filter((v) => v.default === true)
if (default_user_project.length) {
this.project = default_user_project[0].project
} else if (this.default_project) {
this.project = this.default_project
} else {
let default_params = {
filter: { field: "default", op: "==", value: true },
}
ProjectApi.getAll(default_params).then((response) => {
if (response.data.items.length && !this.project) {
this.project = response.data.items[0]
}
})
}
})
}

if (this.$route.query.case_type) {
Expand Down
16 changes: 15 additions & 1 deletion src/dispatch/static/dispatch/src/case/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
<v-icon start color="white">mdi-shield-search</v-icon>
<span class="text-uppercase text-body-2 font-weight-bold">Report case</span>
</v-btn>
<v-btn
v-if="userAdminOrAbove(currentUserRole)"
color="info"
class="ml-2"
@click="showNewSheet()"
>
New
</v-btn>
</v-col>
</v-row>
<v-row no-gutters>
Expand Down Expand Up @@ -194,8 +202,9 @@ const defaultUserProjects = computed(() => {
})

const showRun = (data) => store.dispatch("workflow/showRun", data)
const showDeleteDialog = (item) => store.dispatch("case_management/showDeleteDialog", item)
const showEscalateDialog = (item) => store.dispatch("case_management/showEscalateDialog", item)
const showDeleteDialog = (item) => store.dispatch("case_management/showDeleteDialog", item)
const showNewSheet = () => store.dispatch("case_management/showNewSheet")

const getAll = () => {
store.dispatch("case_management/getAll", caseManagement.value.table.options)
Expand All @@ -204,6 +213,7 @@ const getAll = () => {
const items = computed(() => caseManagement.value.table.rows.items)
const total = computed(() => caseManagement.value.table.rows.total)
const loading = computed(() => caseManagement.value.table.loading)
const currentUserRole = computed(() => caseManagement.value.current_user_role)

const selected = ref([])
watch(selected, (newVal) => {
Expand All @@ -230,6 +240,10 @@ function loadItems({ page, itemsPerPage, sortBy }) {
getAll()
}

function userAdminOrAbove(role) {
return ["Admin", "Owner", "Manager"].includes(role)
}

watch(
route,
(newVal) => {
Expand Down
19 changes: 19 additions & 0 deletions src/dispatch/static/dispatch/src/case/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { debounce } from "lodash"

import SearchUtils from "@/search/utils"
import CaseApi from "@/case/api"
import ProjectApi from "@/project/api"
import PluginApi from "@/plugin/api"
import AuthApi from "@/auth/api"
import router from "@/router"

const getDefaultSelectedState = () => {
Expand Down Expand Up @@ -99,6 +101,8 @@ const state = {
loading: false,
bulkEditLoading: false,
},
default_project: null,
current_user_role: null,
}

const getters = {
Expand All @@ -112,6 +116,15 @@ const getters = {
const actions = {
getAll: debounce(({ commit, state }) => {
commit("SET_TABLE_LOADING", "primary")
let default_params = {
filter: { field: "default", op: "==", value: true },
}
ProjectApi.getAll(default_params).then((response) => {
commit("SET_DEFAULT_PROJECT", response.data.items[0])
})
AuthApi.getUserRole().then((response) => {
commit("SET_CURRENT_USER_ROLE", response.data)
})
let params = SearchUtils.createParametersFromTableOptions({ ...state.table.options }, "Case")
return CaseApi.getAll(params)
.then((response) => {
Expand Down Expand Up @@ -456,6 +469,12 @@ const mutations = {
SET_SELECTED_SAVING(state, value) {
state.selected.saving = value
},
SET_DEFAULT_PROJECT(state, value) {
state.default_project = value
},
SET_CURRENT_USER_ROLE(state, value) {
state.current_user_role = value
},
}

export default {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ import router from "@/router"

import CostModelCombobox from "@/cost_model/CostModelCombobox.vue"
import DocumentApi from "@/document/api"
import ProjectApi from "@/project/api"
import AuthApi from "@/auth/api"
import IncidentPrioritySelect from "@/incident/priority/IncidentPrioritySelect.vue"
import IncidentTypeSelect from "@/incident/type/IncidentTypeSelect.vue"
import ProjectSelect from "@/project/ProjectSelect.vue"
Expand Down Expand Up @@ -183,7 +185,9 @@ export default {
"selected.ticket",
"selected.project",
"selected.id",
"default_project",
]),
...mapFields("auth", ["currentUser.projects"]),
},

methods: {
Expand Down Expand Up @@ -241,7 +245,41 @@ export default {

created() {
if (this.$route.query.project) {
this.project = { name: this.$route.query.project }
let params = {
filter: { field: "name", op: "==", value: this.$route.query.project },
}
// get full project object from api
ProjectApi.getAll(params).then((response) => {
if (response.data.items.length && !this.project) {
this.project = response.data.items[0]
}
})
} else if (this.projects.length && !this.project) {
this.project = this.projects[0].project
} else {
// if no user projects stored yet, get the default project for the user
// if no default user project, then get the default project for the organization
AuthApi.getUserInfo().then((response) => {
if (this.project) {
// if the user has already selected something, exit
return
}
let default_user_project = response.data.projects.filter((v) => v.default === true)
if (default_user_project.length) {
this.project = default_user_project[0].project
} else if (this.default_project) {
this.project = this.default_project
} else {
let default_params = {
filter: { field: "default", op: "==", value: true },
}
ProjectApi.getAll(default_params).then((response) => {
if (response.data.items.length && !this.project) {
this.project = response.data.items[0]
}
})
}
})
}

if (this.$route.query.incident_type) {
Expand Down
15 changes: 14 additions & 1 deletion src/dispatch/static/dispatch/src/incident/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
<v-icon start color="white">mdi-fire</v-icon>
<span class="text-uppercase text-body-2 font-weight-bold">Report incident</span>
</v-btn>
<v-btn
v-if="userAdminOrAbove(current_user_role)"
color="info"
class="ml-2"
@click="showNewSheet()"
>
New
</v-btn>
</v-col>
</v-row>
<v-row no-gutters>
Expand Down Expand Up @@ -218,6 +226,7 @@ export default {
"table.rows.items",
"table.rows.selected",
"table.rows.total",
"current_user_role",
]),
...mapFields("auth", ["currentUser.projects"]),

Expand All @@ -234,11 +243,15 @@ export default {
},

methods: {
...mapActions("incident", ["getAll", "showDeleteDialog", "showReportDialog"]),
...mapActions("incident", ["getAll", "showNewSheet", "showDeleteDialog", "showReportDialog"]),
...mapActions("workflow", ["showRun"]),
showIncidentEditSheet(e, { item }) {
this.$router.push({ name: "IncidentTableEdit", params: { name: item.name } })
},

userAdminOrAbove(role) {
return ["Admin", "Owner", "Manager"].includes(role)
},
},

watch: {
Expand Down
19 changes: 19 additions & 0 deletions src/dispatch/static/dispatch/src/incident/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { debounce } from "lodash"

import SearchUtils from "@/search/utils"
import IncidentApi from "@/incident/api"
import ProjectApi from "@/project/api"
import PluginApi from "@/plugin/api"
import AuthApi from "@/auth/api"
import router from "@/router"
import moment from "moment-timezone"

Expand Down Expand Up @@ -121,6 +123,8 @@ const state = {
participant_updates: true,
other_events: true,
},
default_project: null,
current_user_role: null,
}

const getters = {
Expand All @@ -134,6 +138,15 @@ const getters = {
const actions = {
getAll: debounce(({ commit, state }) => {
commit("SET_TABLE_LOADING", "primary")
let default_params = {
filter: { field: "default", op: "==", value: true },
}
ProjectApi.getAll(default_params).then((response) => {
commit("SET_DEFAULT_PROJECT", response.data.items[0])
})
AuthApi.getUserRole().then((response) => {
commit("SET_CURRENT_USER_ROLE", response.data)
})
let params = SearchUtils.createParametersFromTableOptions(
{ ...state.table.options },
"Incident"
Expand Down Expand Up @@ -606,6 +619,12 @@ const mutations = {
SET_SELECTED_LOADING(state, value) {
state.selected.loading = value
},
SET_DEFAULT_PROJECT(state, value) {
state.default_project = value
},
SET_CURRENT_USER_ROLE(state, value) {
state.current_user_role = value
},
}

export default {
Expand Down
4 changes: 4 additions & 0 deletions tests/static/e2e/pages/report-incident-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,16 @@ export class ReportIncidentPage {
tags: string[]
) {
await this.goto()
// give time for default project to settle
await this.page.waitForTimeout(3000);
await this.addTitle(title)
await this.addDescription(description)
await this.selectProject(project)
await this.selectType(type)
await this.selectPriority(priority)
await this.selectTags(tags)
// click outside tag select to update URL
await this.page.waitForTimeout(1500);
await this.resetPageView()
await Promise.all([
await this.submitButton.click(),
Expand Down