mirror of
https://github.com/directus/directus.git
synced 2026-01-24 05:48:03 -05:00
Add full/none permissions toggles
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user