More work on API permissions
This commit is contained in:
parent
79b0adf81a
commit
c9a21c64bf
14 changed files with 318 additions and 85 deletions
|
@ -4,5 +4,36 @@
|
|||
<p>
|
||||
<img class="inline-block w-16 mr-4" style="vertical-align: -20px" src="../../img/squint.png"> Or here
|
||||
</p>
|
||||
<permission-tree :tree="tree" :granted-permissions="grantedPermissions" :on-change="onChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ApiPermissions, permissionHierarchy } from "@shared/apiPermissions";
|
||||
import PermissionTree from "./PermissionTree.vue";
|
||||
import { applyStateToPermissionHierarchy } from "./permissionTreeUtils";
|
||||
|
||||
export default {
|
||||
components: {PermissionTree},
|
||||
data() {
|
||||
return {
|
||||
tree: [],
|
||||
grantedPermissions: new Set([ApiPermissions.EditConfig]),
|
||||
managerPermissions: new Set([ApiPermissions.ManageAccess])
|
||||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.tree = applyStateToPermissionHierarchy(permissionHierarchy, this.grantedPermissions, this.managerPermissions);
|
||||
},
|
||||
methods: {
|
||||
updateTreeState() {
|
||||
this.tree = applyStateToPermissionHierarchy(permissionHierarchy, this.grantedPermissions, this.managerPermissions);
|
||||
},
|
||||
|
||||
onChange() {
|
||||
console.log('changed!', this.grantedPermissions);
|
||||
this.updateTreeState();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
62
dashboard/src/components/dashboard/PermissionTree.vue
Normal file
62
dashboard/src/components/dashboard/PermissionTree.vue
Normal file
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<ul class="nostyles">
|
||||
<li v-for="[permission, treeState, subTree] in tree" :class="{locked: treeState.locked}">
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
:checked="grantedPermissions.has(permission) || treeState.redundant"
|
||||
v-on:input="togglePermission(permission)"
|
||||
:disabled="treeState.locked || treeState.redundant">
|
||||
<span>{{ permissionNames[permission] }}</span>
|
||||
</label>
|
||||
<permission-tree v-if="subTree && subTree.length"
|
||||
:tree="subTree"
|
||||
:granted-permissions="grantedPermissions"
|
||||
:on-change="onChange" />
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
ul {
|
||||
list-style: none;
|
||||
|
||||
& ul {
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.locked > label {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { ApiPermissions, permissionNames } from "@shared/apiPermissions";
|
||||
import { PropType } from "vue";
|
||||
import { TPermissionHierarchyWithState } from "./permissionTreeUtils";
|
||||
|
||||
export default {
|
||||
name: 'permission-tree',
|
||||
props: {
|
||||
tree: Array as PropType<TPermissionHierarchyWithState>,
|
||||
grantedPermissions: Set as PropType<Set<ApiPermissions>>,
|
||||
onChange: Function
|
||||
},
|
||||
data() {
|
||||
return { permissionNames };
|
||||
},
|
||||
methods: {
|
||||
togglePermission(permission) {
|
||||
if (this.grantedPermissions.has(permission)) {
|
||||
this.grantedPermissions.delete(permission);
|
||||
} else {
|
||||
this.grantedPermissions.add(permission);
|
||||
}
|
||||
|
||||
if (this.onChange) {
|
||||
this.onChange();
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
43
dashboard/src/components/dashboard/permissionTreeUtils.ts
Normal file
43
dashboard/src/components/dashboard/permissionTreeUtils.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { ApiPermissions, hasPermission, TPermissionHierarchy } from "@shared/apiPermissions";
|
||||
|
||||
export type TPermissionHierarchyState = {
|
||||
locked: boolean;
|
||||
redundant: boolean;
|
||||
};
|
||||
|
||||
export type TApiPermissionWithState = [ApiPermissions, TPermissionHierarchyState, TPermissionHierarchyWithState?];
|
||||
export type TPermissionHierarchyWithState = TApiPermissionWithState[];
|
||||
|
||||
/**
|
||||
* @param tree
|
||||
* @param grantedPermissions Permissions granted to the user being edited
|
||||
* @param managerPermissions Permissions granted to the user who's editing the other user's permissions
|
||||
* @param entireTreeIsGranted
|
||||
*/
|
||||
export function applyStateToPermissionHierarchy(
|
||||
tree: TPermissionHierarchy,
|
||||
grantedPermissions: Set<ApiPermissions>,
|
||||
managerPermissions: Set<ApiPermissions> = new Set(),
|
||||
entireTreeIsGranted = false,
|
||||
): TPermissionHierarchyWithState {
|
||||
const result: TPermissionHierarchyWithState = [];
|
||||
|
||||
for (const item of tree) {
|
||||
const [perm, nested] = Array.isArray(item) ? item : [item];
|
||||
|
||||
// Can't edit permissions you don't have yourself
|
||||
const locked = !hasPermission(managerPermissions, perm);
|
||||
const permissionWithState: TApiPermissionWithState = [perm, { locked, redundant: entireTreeIsGranted }];
|
||||
|
||||
if (nested) {
|
||||
const subTreeGranted = entireTreeIsGranted || grantedPermissions.has(perm);
|
||||
permissionWithState.push(
|
||||
applyStateToPermissionHierarchy(nested, grantedPermissions, managerPermissions, subTreeGranted),
|
||||
);
|
||||
}
|
||||
|
||||
result.push(permissionWithState);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue