Add full/none permissions toggles

This commit is contained in:
rijkvanzanten
2020-08-27 15:03:01 -04:00
parent 4b5aaaa1ff
commit 7121c42beb
4 changed files with 179 additions and 15 deletions

View File

@@ -4,16 +4,36 @@
{{ collection.name }}
</span>
<permissions-overview-toggle :collection="collection" :role="role" action="create" />
<permissions-overview-toggle :collection="collection" :role="role" action="read" />
<permissions-overview-toggle :collection="collection" :role="role" action="update" />
<permissions-overview-toggle :collection="collection" :role="role" action="delete" />
<permissions-overview-toggle
:collection="collection"
:role="role"
action="create"
:permission="getPermission('create')"
/>
<permissions-overview-toggle
:collection="collection"
:role="role"
action="read"
:permission="getPermission('read')"
/>
<permissions-overview-toggle
:collection="collection"
:role="role"
action="update"
:permission="getPermission('update')"
/>
<permissions-overview-toggle
:collection="collection"
:role="role"
action="delete"
:permission="getPermission('delete')"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from '@vue/composition-api';
import { Collection } from '@/types';
import { Collection, Permission } from '@/types';
import PermissionsOverviewToggle from './permissions-overview-toggle.vue';
export default defineComponent({
@@ -27,6 +47,17 @@ export default defineComponent({
type: Object as PropType<Collection>,
required: true,
},
permissions: {
type: Array as PropType<Permission[]>,
required: true,
},
},
setup(props) {
return { getPermission };
function getPermission(action: string) {
return props.permissions.find((permission) => permission.action === action);
}
},
});
</script>

View File

@@ -2,11 +2,15 @@
<div class="permissions-overview-toggle">
<v-menu show-arrow>
<template #activator="{ toggle }">
<v-icon @click="toggle" name="check" />
<div>
<v-icon v-if="permissionLevel === 'all'" @click="toggle" name="check" class="all" />
<v-icon v-else-if="permissionLevel === 'custom'" @click="toggle" name="rule" class="custom" />
<v-icon v-else-if="permissionLevel === 'none'" @click="toggle" name="block" class="none" />
</div>
</template>
<v-list dense>
<v-list-item>
<v-list-item @click="setFullAccess">
<v-list-item-icon>
<v-icon name="check" />
</v-list-item-icon>
@@ -15,7 +19,7 @@
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item @click="setNoAccess">
<v-list-item-icon>
<v-icon name="block" />
</v-list-item-icon>
@@ -43,8 +47,9 @@
</template>
<script lang="ts">
import { defineComponent, PropType } from '@vue/composition-api';
import { Collection } from '@/types';
import { defineComponent, PropType, computed, inject, ref } from '@vue/composition-api';
import { Collection, Permission } from '@/types';
import api from '@/api';
export default defineComponent({
props: {
@@ -60,14 +65,99 @@ export default defineComponent({
type: String,
required: true,
},
permission: {
type: Object as PropType<Permission>,
default: null,
},
},
setup(props) {
const permissionLevel = computed<'all' | 'none' | 'custom'>(() => {
if (props.permission === null) return 'none';
if (hasAll() === true) return 'all';
return 'custom';
function hasAll() {
if (!props.permission) return false;
if (props.permission.fields !== '*') return false;
if (Object.keys(props.permission.permissions || {}).length > 0) return false;
if (Object.keys(props.permission.validation || {}).length > 0) return false;
return true;
}
});
const loading = ref(false);
const refresh = inject<() => Promise<void>>('refresh-permissions');
return { permissionLevel, loading, setFullAccess, setNoAccess };
async function setFullAccess() {
loading.value = true;
if (props.permission) {
try {
await api.patch(`/permissions/${props.permission.id}`, {
fields: '*',
permissions: null,
validation: null,
});
} catch (err) {
console.error(err);
} finally {
await refresh?.();
loading.value = false;
}
} else {
try {
await api.post('/permissions/', {
role: props.role,
collection: props.collection.collection,
action: props.action,
fields: '*',
});
} catch (err) {
console.error(err);
} finally {
await refresh?.();
loading.value = false;
}
}
}
async function setNoAccess() {
if (!props.permission) return;
loading.value = true;
try {
await api.delete(`/permissions/${props.permission.id}`);
} catch (err) {
console.error(err);
} finally {
await refresh();
loading.value = false;
}
}
},
});
</script>
<style lang="scss" scoped>
.permissions-overview-toggle {
--v-icon-color: var(--success);
position: relative;
}
.all {
--v-icon-color: var(--success);
}
.custom {
--v-icon-color: var(--warning);
}
.none {
--v-icon-color: var(--danger);
}
</style>

View File

@@ -7,21 +7,25 @@
<div class="table">
<permissions-overview-header />
<permissions-overview-row
v-for="collection in regularCollections"
:key="collection.collection"
:collection="collection"
:role="role"
:permissions="permissions.filter((p) => p.collection === collection.collection)"
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from '@vue/composition-api';
import { defineComponent, computed, ref, provide } from '@vue/composition-api';
import { useCollectionsStore } from '@/stores';
import PermissionsOverviewHeader from './permissions-overview-header.vue';
import PermissionsOverviewRow from './permissions-overview-row.vue';
import { Permission } from '@/types';
import api from '@/api';
export default defineComponent({
components: { PermissionsOverviewHeader, PermissionsOverviewRow },
@@ -39,13 +43,51 @@ export default defineComponent({
(collection) => collection.collection.startsWith('directus_') === false
)
);
const systemCollections = computed(() =>
collectionsStore.state.collections.filter(
(collection) => collection.collection.startsWith('directus_') === false
)
);
return { regularCollections, systemCollections };
const { permissions, loading, error, fetchPermissions } = usePermissions();
fetchPermissions();
provide('refresh-permissions', fetchPermissions);
return { regularCollections, systemCollections, permissions, loading, error };
function usePermissions() {
const permissions = ref<Permission[]>([]);
const loading = ref(false);
const error = ref();
return { permissions, loading, error, fetchPermissions };
async function fetchPermissions() {
error.value = null;
loading.value = true;
try {
const response = await api.get('/permissions', {
params: {
filter: {
role: {
_eq: props.role,
},
},
},
});
permissions.value = response.data.data;
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
}
},
});
</script>

View File

@@ -2,8 +2,9 @@ export type Permission = {
id: number;
role: string | null;
collection: string;
operation: 'create' | 'read' | 'update' | 'validate' | 'delete';
action: 'create' | 'read' | 'update' | 'delete';
permissions: Record<string, any> | null;
validation: Record<string, any> | null;
presets: Record<string, any> | null;
fields: string | null;
limit: number | null;