Changes in Rights and Roles

This commit is contained in:
2024-12-21 18:53:53 +01:00
parent c8521ad1f6
commit 813944fc23
10 changed files with 447 additions and 324 deletions

View File

@@ -71,12 +71,26 @@ const filteredRows = computed(() => {
if(selectedFilters.value.length > 0) {
selectedFilters.value.forEach(filterName => {
let filter = dataType.filters.find(i => i.name === filterName)
tempItems = tempItems.filter(filter.filterFunction)
})
}
if(!useRole().generalAvailableRights.value[type].showToAllUsers) {
if(useRole().checkRight(`${type}-viewAll`)){
console.log("Right to Show All")
} else if(useRole().checkRight(type)){
console.log("Only Righty to show Own")
console.log(tempItems)
tempItems = tempItems.filter(item => item.profiles.includes(dataStore.activeProfile.id))
} else {
console.log("No Right to Show")
tempItems = []
}
}
return useSearch(searchString.value, tempItems)
})
@@ -139,7 +153,7 @@ const filteredRows = computed(() => {
:columns="columns"
class="w-full"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
@select="(i) => router.push(`/projects/show/${i.id}`) "
@select="(i) => router.push(`/${type}/show/${i.id}`) "
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: `Keine ${dataType.label} anzuzeigen` }"
>
<template #name-data="{row}">
@@ -175,29 +189,6 @@ const filteredRows = computed(() => {
<component v-if="column.component" :is="column.component" :row="row"></component>
<span v-else>{{row[column.key]}}</span>
</template>
<!-- <template #name-data="{row}">
<span class="text-primary-500 font-bold" v-if="row === filteredRows[selectedItem]">{{row.name}}</span>
<span v-else>{{row.name}}</span>
</template>
<template #projecttype-data="{row}">
{{row.projecttype ? row.projecttype.name : ""}}
</template>
<template #phase-data="{row}">
{{getActivePhaseLabel(row)}}
</template>
<template #customer-data="{row}">
{{row.customer ? row.customer.name : ""}}
</template>
<template #plant-data="{row}">
{{row.plant ? row.plant.name : ""}}
</template>
<template #users-data="{row}">
{{row.users.map(i => dataStore.getProfileById(i).fullName).join(", ")}}
</template>-->
</UTable>
</template>

View File

@@ -73,21 +73,21 @@ const links = computed(() => {
defaultOpen: false,
icon: "i-heroicons-user-group",
children: [
{
... role.checkRight("customers") ? [{
label: "Kunden",
to: "/customers",
icon: "i-heroicons-user-group"
},
{
}] : [],
... role.checkRight("vendors") ? [{
label: "Lieferanten",
to: "/vendors",
icon: "i-heroicons-truck"
},
{
}] : [],
... role.checkRight("contacts") ? [{
label: "Ansprechpartner",
to: "/contacts",
icon: "i-heroicons-user-group"
},
}] : [],
]
},] : [],
{
@@ -95,7 +95,7 @@ const links = computed(() => {
defaultOpen:false,
icon: "i-heroicons-user-group",
children: [
... dataStore.ownTenant.features.timeTracking ? [{
... dataStore.ownTenant.features.timeTracking ? [{
label: "Zeiterfassung",
to: "/employees/timetracking",
icon: "i-heroicons-clock"
@@ -137,7 +137,7 @@ const links = computed(() => {
},
]
},] : [],
... dataStore.ownTenant.features.inventory ? [{
... role.checkRight("inventory") ? [{
label: "Lager",
icon: "i-heroicons-puzzle-piece",
defaultOpen: false,
@@ -151,28 +151,28 @@ const links = computed(() => {
to: "/inventory/stocks",
icon: "i-heroicons-square-3-stack-3d"
},
{
... role.checkRight("spaces") ? [{
label: "Lagerplätze",
to: "/spaces",
icon: "i-heroicons-square-3-stack-3d"
},
{
}] : [],
... role.checkRight("inventoryitems") ? [{
label: "Inventar",
to: "/inventoryitems",
icon: "i-heroicons-puzzle-piece"
},
}] : [],
]
},] : [],
... dataStore.ownTenant.features.vehicles ? [{
... role.checkRight("vehicles") ? [{
label: "Fuhrpark",
defaultOpen: false,
icon: "i-heroicons-truck",
children: [
{
... role.checkRight("vehicles") ? [{
label: "Fahrzeuge",
to: "/vehicles",
icon: "i-heroicons-truck"
},{
}] : [],{
label: "Fahrten",
to: "/trackingTrips",
icon: "i-heroicons-map"
@@ -184,23 +184,26 @@ const links = computed(() => {
defaultOpen: false,
icon: "i-heroicons-clipboard-document",
children: [
{
... role.checkRight("products") ? [{
label: "Artikel",
to: "/products",
icon: "i-heroicons-puzzle-piece"
},{
}] : [],
... role.checkRight("productcategories") ? [{
label: "Artikelkategorien",
to: "/productcategories",
icon: "i-heroicons-puzzle-piece"
},{
}] : [],
... role.checkRight("services") ? [{
label: "Leistungen",
to: "/services",
icon: "i-heroicons-puzzle-piece"
},{
}] : [],
... role.checkRight("servicecategories") ? [{
label: "Leistungskategorien",
to: "/servicecategories",
icon: "i-heroicons-puzzle-piece"
},
}] : [],
]
},
... role.checkRight("checks") ? [{
@@ -208,17 +211,17 @@ const links = computed(() => {
to: "/checks",
icon: "i-heroicons-magnifying-glass"
},] : [],
... (role.checkRight("projects") && dataStore.ownTenant.features.projects) ? [{
... role.checkRight("projects") ? [{
label: "Projekte",
to: "/projects",
icon: "i-heroicons-clipboard-document-check"
},] : [],
... (role.checkRight("contracts") && dataStore.ownTenant.features.contracts) ? [{
... role.checkRight("contracts") ? [{
label: "Verträge",
to: "/contracts",
icon: "i-heroicons-clipboard-document"
}] : [],
... (role.checkRight("plants") && dataStore.ownTenant.features.objects) ? [{
... role.checkRight("plants") ? [{
label: "Objekte",
to: "/plants",
icon: "i-heroicons-clipboard-document"
@@ -237,6 +240,10 @@ const links = computed(() => {
label: "Mitarbeiter",
to: "/profiles",
icon: "i-heroicons-clipboard-document-list"
},{
label: "Rollen",
to: "/roles",
icon: "i-heroicons-clipboard-document-list"
},{
label: "E-Mail Konten",
to: "/settings/emailAccounts",

View File

@@ -4,63 +4,186 @@
export const useRole = () => {
const supabase = useSupabaseClient()
const dataStore = useDataStore()
const rights = ref({
const generalAvailableRights = ref({
projects: {
label: "Projekte"
label: "Projekte",
showToAllUsers: false
},
"projects-viewAll": {
label: "Alle Projekte einsehen",
parent: "projects"
},
"projects-viewOwn": {
label: "Eigene Projekte einsehen",
parent: "projects"
},
"projects-create": {
label: "Projekte erstellen",
parent: "projects"
},
contracts: {
label: "Verträge"
label: "Verträge",
showToAllUsers: false
},
objects: {
label: "Objekte"
"contracts-viewAll": {
label: "Alle Verträge einsehen",
parent: "contracts"
},
"contracts-create": {
label: "Verträge erstellen",
parent: "contracts"
},
plants: {
label: "Objekte",
showToAllUsers: false
},
"plants-viewAll": {
label: "Alle Objekte einsehen",
parent: "plants"
},
"plants-create": {
label: "Objekte erstellen",
parent: "plants"
},
products: {
label: "Artikel",
showToAllUsers: true
},
"products-create": {
label: "Artikel erstellen",
parent: "products"
},
productcategories: {
label: "Artikelkategorie",
showToAllUsers: true
},
"productcategories-create": {
label: "Artikelkategorie erstellen",
parent: "productcategories"
},
services: {
label: "Leistungen",
showToAllUsers: true
},
"services-create": {
label: "Leistungen erstellen",
parent: "services"
},
servicecategories: {
label: "Leistungskategorien",
showToAllUsers: true
},
"servicecategories-create": {
label: "Leistungskategorien erstellen",
parent: "servicecategories"
},
customers: {
label: "Kunden",
showToAllUsers: false
},
"customers-viewAll": {
label: "Alle Kunden einsehen",
parent: "customers"
},
"customers-create": {
label: "Kunden erstellen",
parent: "customers"
},
contacts: {
label: "Kontakte",
showToAllUsers: false
},
"contacts-viewAll": {
label: "Alle Kontakte einsehen",
parent: "contacts"
},
"contacts-create": {
label: "Kontakte erstellen",
parent: "contacts"
},
vendors: {
label: "Lieferanten",
showToAllUsers: false
},
"vendors-viewAll": {
label: "Alle Lieferanten einsehen",
parent: "vendors"
},
"vendors-create": {
label: "Lieferanten erstellen",
parent: "vendors"
},
checks: {
label: "Überprüfungen"
label: "Überprüfungen",
showToAllUsers: false
},
"checks-viewAll": {
label: "Alle Überprüfungen einsehen",
parent: "checks"
},
"checks-create": {
label: "Überprüfungen erstellen",
parent: "checks"
},
vehicles: {
label: "Fahrzeuge",
showToAllUsers: false
},
"vehicles-viewAll": {
label: "Alle Fahrzeuge einsehen",
parent: "vehicles"
},
"vehicles-create": {
label: "Fahrzeuge erstellen",
parent: "vehicles"
},
inventoryitems: {
label: "Inventarartikel",
showToAllUsers: false
},
"inventoryitems-viewAll": {
label: "Alle Inventarartikel einsehen",
parent: "inventoryitems"
},
"inventoryitems-create": {
label: "Inventarartikel erstellen",
parent: "inventoryitems"
},
spaces: {
label: "Lagerplätze",
showToAllUsers: false
},
"spaces-viewAll": {
label: "Alle Lagerplätze einsehen",
parent: "spaces"
},
"spaces-create": {
label: "Lagerplätze erstellen",
parent: "spaces"
},
roles: {
label: "Rollen",
showToAllUsers: false
},
"roles-viewAll": {
label: "Alle Rollen einsehen",
parent: "roles"
},
"roles-create": {
label: "Rollen erstellen",
parent: "roles"
},
"inventory": {
label: "Lager",
},
})
let role = dataStore.activeProfile.role
/*const checkRight = (right) => {
let rightsToCheck = [right]
if(rights.value[right].parent) {
rightsToCheck.push(rights.value[right].parent)
}
let hasAllNeccessaryRights = false
rightsToCheck.forEach(i => {
if(role.rights.includes(i)){
hasAllNeccessaryRights = true
} else {
hasAllNeccessaryRights = false
}
})
return hasAllNeccessaryRights
}*/
const checkRight = (right) => {
let rightsToCheck = [right]
//console.log(right.split("-"))
if(right.split("-").length > 1) {
@@ -78,13 +201,12 @@ export const useRole = () => {
}
})
//console.log(hasAllNeccessaryRights)
return hasAllNeccessaryRights
}
return {
role,
generalAvailableRights,
checkRight
}

View File

@@ -3,67 +3,6 @@
type="contacts"
:items="items"
></EntityList>
<!-- <UDashboardNavbar title="Ansprechpartner" :badge="filteredRows.length">
<template #right>
<UInput
id="searchinput"
v-model="searchString"
icon="i-heroicons-funnel"
autocomplete="off"
placeholder="Suche..."
class="hidden lg:block"
@keydown.esc="$event.target.blur()"
>
<template #trailing>
<UKbd value="/" />
</template>
</UInput>
<UButton @click="router.push(`/contacts/create`)">+ Kontakt</UButton>
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #right>
<USelectMenu
v-model="selectedColumns"
icon="i-heroicons-adjustments-horizontal-solid"
:options="templateColumns"
multiple
class="hidden lg:block"
by="key"
>
<template #label>
Spalten
</template>
</USelectMenu>
</template>
</UDashboardToolbar>
<UTable
:rows="filteredRows"
:columns="columns"
class="w-full"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
@select="(i) => router.push(`/contacts/show/${i.id}`)"
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Ansprechpartner anzuzeigen' }"
>
<template #fullName-data="{row}">
<span v-if="row === filteredRows[selectedItem]" class="text-primary-500 font-bold">{{row.fullName}}</span>
<span v-else>{{row.fullName}}</span>
</template>
<template #active-data="{row}">
<span v-if="row.active" class="text-primary-500">Aktiv</span>
<span v-else class="text-rose">Gesperrt</span>
</template>
<template #customer-data="{row}">
{{row.customer ? row.customer.name : ""}}
</template>
<template #vendor-data="{row}">
{{row.vendor ? row.vendor.name : ""}}
</template>
</UTable>-->
</template>
<script setup>
@@ -80,32 +19,6 @@ const setupPage = async () => {
}
setupPage()
const templateColumns = [
]
const selectedColumns = ref(templateColumns)
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
const searchString = ref('')
/*const filteredRows = computed(() => {
if(!searchString.value) {
return dataStore.contacts
}
return dataStore.contacts.filter(item => {
return Object.values(item).some((value) => {
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
})
})
})*/
const filteredRows = computed(() => {
return useSearch(searchString.value, items.value)
})
</script>
<style scoped>

View File

@@ -3,96 +3,6 @@
:items="items"
type="products"
/>
<!-- <UDashboardNavbar title="Artikel" :badge="filteredRows.length">
<template #right>
<UInput
id="searchinput"
v-model="searchString"
icon="i-heroicons-funnel"
autocomplete="off"
placeholder="Suche..."
class="hidden lg:block"
@keydown.esc="$event.target.blur()"
>
<template #trailing>
<UKbd value="/" />
</template>
</UInput>
<UButton @click="router.push(`/products/create`)">+ Artikel</UButton>
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #left>
<USelectMenu
v-model="selectedTags"
icon="i-heroicons-adjustments-horizontal-solid"
:options="templateTags"
multiple
class="hidden lg:block"
>
<template #label>
Tags
</template>
</USelectMenu>
</template>
<template #right>
<USelectMenu
v-model="selectedColumns"
icon="i-heroicons-adjustments-horizontal-solid"
:options="templateColumns"
multiple
class="hidden lg:block"
by="key"
>
<template #label>
Spalten
</template>
</USelectMenu>
</template>
</UDashboardToolbar>
<UTable
:rows="filteredRows"
:columns="columns"
class="w-full"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
@select="(i) => router.push(`/products/show/${i.id}`) "
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Artikel anzuzeigen' }"
>
<template #name-data="{row}">
<span
v-if="row === filteredRows[selectedItem]"
class="text-primary-500 font-bold">{{row.name}}</span>
<span v-else>
{{row.name}}
</span>
</template>
<template #stock-data="{row}">
{{`${dataStore.getStockByProductId(row.id)} ${(dataStore.units.find(unit => unit.id === row.unit) ? dataStore.units.find(unit => unit.id === row.unit).name : "")}`}}
</template>
<template #sellingPrice-data="{row}">
{{row.sellingPrice ? (Number(row.sellingPrice).toFixed(2) + " €").replace(".",",") : ""}}
</template>
<template #tags-data="{row}">
<UBadge
v-if="row.tags.length > 0"
v-for="tag in row.tags"
class="mr-2"
>
{{tag}}
</UBadge>
<span v-else>-</span>
</template>
<template #unit-data="{row}">
{{dataStore.units.find(unit => unit.id === row.unit) ? dataStore.units.find(unit => unit.id === row.unit).name : row.unit}}
</template>
<template #productcategories-data="{row}">
{{row.productcategories.map(i => productcategories.find(x => x.id === i).name).join(", ")}}
</template>
</UTable>-->
</template>
<script setup>

View File

@@ -19,7 +19,7 @@ const setupPage = async () => {
items.value = (await useSupabaseSelect("projects","*, customer (name), plant(name), projecttype(name, id)","projectNumber")).map(project => {
return {
...project,
profiles: project.profiles.map(x => profiles.find(z => z.id === x).fullName).join(", "),
//profiles: project.profiles.map(x => profiles.find(z => z.id === x).fullName).join(", "),
phase: getActivePhaseLabel(project)
}
})

View File

@@ -0,0 +1,203 @@
<script setup>
import HistoryDisplay from "~/components/HistoryDisplay.vue";
import DocumentList from "~/components/DocumentList.vue";
import DocumentUpload from "~/components/DocumentUpload.vue";
import {useSupabaseSelect} from "~/composables/useSupabase.js";
definePageMeta({
middleware: "auth"
})
defineShortcuts({
'backspace': () => {
router.push("/roles")
},
'arrowleft': () => {
if(openTab.value > 0){
openTab.value -= 1
}
},
'arrowright': () => {
if(openTab.value < 3) {
openTab.value += 1
}
},
})
const dataStore = useDataStore()
const supabase = useSupabaseClient()
const route = useRoute()
const router = useRouter()
const toast = useToast()
const id = ref(route.params.id ? route.params.id : null )
const role = useRole()
//Working
const mode = ref(route.params.mode || "show")
const itemInfo = ref({
rights: []
})
const openTab = ref(0)
//Functions
const setupPage = async () => {
if(mode.value === "show" || mode.value === "edit"){
itemInfo.value = await useSupabaseSelectSingle("roles",route.params.id,"*")
}
}
const rightOptions = computed(() => {
console.log(Object.keys(useRole().generalAvailableRights.value))
return Object.keys(useRole().generalAvailableRights.value).map(i => {
return {
key: i,
label: role.generalAvailableRights.value[i].label
}
})
})
const rightList = computed(() => {
console.log(rightOptions.value)
return itemInfo.value.rights.map(i => {
if(rightOptions.value.find(x => x.key === i)) {
return rightOptions.value.find(x => x.key === i).label
} else {
return i
}
}).join(", ")
})
setupPage()
</script>
<template>
<UDashboardNavbar
:ui="{center: 'flex items-stretch gap-1.5 min-w-0'}"
>
<template #left>
<UButton
icon="i-heroicons-chevron-left"
variant="outline"
@click="router.push(`/roles`)"
>
Artikel
</UButton>
</template>
<template #center>
<h1
v-if="itemInfo"
class="text-xl font-medium"
>{{itemInfo.name ? `Rolle: ${itemInfo.name}` : (mode === 'create' ? 'Rolle erstellen' : 'Rolle bearbeiten')}}</h1>
</template>
<template #right>
<UButton
v-if="mode === 'edit'"
@click="dataStore.updateItem('roles',itemInfo)"
>
Speichern
</UButton>
<UButton
v-else-if="mode === 'create'"
@click="dataStore.createNewItem('roles',itemInfo)"
>
Erstellen
</UButton>
<UButton
@click="router.push(itemInfo.id ? `/roles/show/${itemInfo.value.id}` : `/products/`)"
color="red"
class="ml-2"
v-if="mode === 'edit' || mode === 'create'"
>
Abbrechen
</UButton>
<UButton
v-if="mode === 'show'"
@click=" router.push(`/roles/edit/${itemInfo.id}`)"
>
Bearbeiten
</UButton>
</template>
</UDashboardNavbar>
<UTabs
:items="[{label: 'Informationen'}]"
v-if="mode === 'show' && itemInfo"
class="p-5"
v-model="openTab"
>
<template #item="{item}">
<div v-if="item.label === 'Informationen'" class="mt-5 flex flex-row">
<div class="w-1/2 mr-5">
<UCard>
<table class="w-full">
<tr>
<td>Name:</td>
<td>{{itemInfo.name}}</td>
</tr>
<tr>
<td>Rechte:</td>
<td>{{rightList}}</td>
</tr>
<tr>
<td>Beschreibung:</td>
<td>{{itemInfo.description}}</td>
</tr>
</table>
</UCard>
</div>
<div class="w-1/2">
<UCard>
<HistoryDisplay
type="role"
v-if="itemInfo"
:element-id="id"
render-headline
/>
</UCard>
</div>
</div>
</template>
</UTabs>
<UForm
v-else-if="mode == 'edit' || mode == 'create'"
class="p-5"
>
<UFormGroup
label="Name:"
>
<UInput
v-model="itemInfo.name"
autofocus
/>
</UFormGroup>
<UFormGroup
label="Rechte:"
>
<USelectMenu
:options="rightOptions"
value-attribute="key"
option-attribute="label"
v-model="itemInfo.rights"
multiple
>
</USelectMenu>
</UFormGroup>
<UFormGroup
label="Beschreibung:"
>
<UTextarea
v-model="itemInfo.description"
/>
</UFormGroup>
</UForm>
</template>
<style scoped>
td {
border-bottom: 1px solid lightgrey;
vertical-align: top;
padding-bottom: 0.15em;
padding-top: 0.15em;
}
</style>

24
pages/roles/index.vue Normal file
View File

@@ -0,0 +1,24 @@
<script setup>
definePageMeta({
middleware: "auth"
})
const items = ref([])
const setup = async () => {
items.value = await useSupabaseSelect("roles","*")
}
setup()
</script>
<template>
<EntityList
:items="items"
type="roles"
/>
</template>
<style scoped>
</style>

View File

@@ -3,64 +3,6 @@
:items="items"
type="vendors"
/>
<!-- <UDashboardNavbar title="Lieferanten" :badge="filteredRows.length">
<template #right>
<UInput
id="searchinput"
name="searchinput"
v-model="searchString"
icon="i-heroicons-funnel"
autocomplete="off"
placeholder="Suche..."
class="hidden lg:block"
@keydown.esc="$event.target.blur()"
>
<template #trailing>
<UKbd value="/" />
</template>
</UInput>
<UButton @click="router.push(`/vendors/create/`)">+ Lieferant</UButton>
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #right>
<USelectMenu
v-model="selectedColumns"
icon="i-heroicons-adjustments-horizontal-solid"
:options="templateColumns"
multiple
class="hidden lg:block"
by="key"
>
<template #label>
Spalten
</template>
</USelectMenu>
</template>
</UDashboardToolbar>
<UTable
:rows="filteredRows"
:columns="columns"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
class="w-full"
@select="(i) => router.push(`/vendors/show/${i.id}`)"
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Lieferanten anzuzeigen' }"
>
<template #name-data="{row}">
<span v-if="row === filteredRows[selectedItem]" class="text-primary-500 font-bold">{{row.name}}</span>
<span v-else>{{row.name}}</span>
</template>
<template #address-data="{row}">
{{row.infoData.street ? `${row.infoData.street}, ` : ''}}{{row.infoData.special ? `${row.infoData.special},` : ''}} {{(row.infoData.zip || row.infoData.city) ? `${row.infoData.zip} ${row.infoData.city}, ` : ''}} {{row.infoData.country}}
</template>
</UTable>-->
</template>
<script setup>
@@ -75,11 +17,6 @@ const setupPage = async () => {
}
setupPage()
const templateColumns = [
]
</script>
<style scoped>

View File

@@ -429,7 +429,23 @@ export const useDataStore = defineStore('data', () => {
labelSingle: "Überprüfung",
redirect: true,
historyItemHolder: "check"
}
},
roles: {
label: "Rollen",
labelSingle: "Rolle",
redirect:true,
historyItemHolder: "role",
filters: [],
templateColumns: [
{
key: "name",
label: "Name"
}, {
key: "description",
label: "Beschreibung"
}
]
},
}
const documentTypesForCreation = ref({