RBAC popover complete
This commit is contained in:
parent
63e0e187a6
commit
20bf34d53c
|
@ -30,6 +30,7 @@ export const getBackendUiStore = () => {
|
|||
const queries = await queriesResponse.json()
|
||||
const integrationsResponse = await api.get("/api/integrations")
|
||||
const integrations = await integrationsResponse.json()
|
||||
const permissionLevels = await store.actions.permissions.fetchLevels()
|
||||
|
||||
store.update(state => {
|
||||
state.selectedDatabase = db
|
||||
|
@ -37,6 +38,7 @@ export const getBackendUiStore = () => {
|
|||
state.datasources = datasources
|
||||
state.queries = queries
|
||||
state.integrations = integrations
|
||||
state.permissionLevels = permissionLevels
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
@ -351,6 +353,13 @@ export const getBackendUiStore = () => {
|
|||
const json = await response.json()
|
||||
return json
|
||||
},
|
||||
delete: async ({ role, resource, level }) => {
|
||||
const response = await api.delete(
|
||||
`/api/permission/${role}/${resource}/${level}`
|
||||
)
|
||||
const json = await response.json()
|
||||
return json
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
title={isUsersTable ? 'Create New User' : 'Create New Row'}
|
||||
modalContentComponent={isUsersTable ? CreateEditUser : CreateEditRow} />
|
||||
<CreateViewButton />
|
||||
<ExportButton view={tableView} />
|
||||
<ManageAccessButton resourceId={$backendUiStore.selectedTable?._id} />
|
||||
<ExportButton view={tableView} />
|
||||
{/if}
|
||||
{#if isUsersTable}
|
||||
<EditRolesButton />
|
||||
|
|
|
@ -54,6 +54,6 @@
|
|||
{#if view.calculation}
|
||||
<GroupByButton {view} />
|
||||
{/if}
|
||||
<ExportButton {view} />
|
||||
<ManageAccessButton resourceId={decodeURI(name)} />
|
||||
<ExportButton {view} />
|
||||
</Table>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<script>
|
||||
import { TextButton, Icon, Popover } from "@budibase/bbui"
|
||||
import { backendUiStore } from "builderStore"
|
||||
import { Roles } from "constants/backend"
|
||||
import api from "builderStore/api"
|
||||
import ManageAccessPopover from "../popovers/ManageAccessPopover.svelte"
|
||||
|
||||
|
@ -7,16 +9,30 @@
|
|||
|
||||
let anchor
|
||||
let dropdown
|
||||
let levels
|
||||
let permissions
|
||||
|
||||
async function openDropdown() {
|
||||
permissions = await backendUiStore.actions.permissions.forResource(
|
||||
resourceId
|
||||
)
|
||||
levels = await backendUiStore.actions.permissions.fetchLevels()
|
||||
dropdown.show()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div bind:this={anchor}>
|
||||
<TextButton text small on:click={dropdown.show}>
|
||||
<TextButton text small on:click={openDropdown}>
|
||||
<i class="ri-lock-line" />
|
||||
Manage Access
|
||||
</TextButton>
|
||||
</div>
|
||||
<Popover bind:this={dropdown} {anchor} align="left">
|
||||
<ManageAccessPopover {resourceId} onClosed={dropdown.hide} />
|
||||
<ManageAccessPopover
|
||||
{resourceId}
|
||||
{levels}
|
||||
{permissions}
|
||||
onClosed={dropdown.hide} />
|
||||
</Popover>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
thin
|
||||
text="Use as table display column" />
|
||||
|
||||
<Label gray small>Search Indexes</Label>
|
||||
<Label grey small>Search Indexes</Label>
|
||||
<Toggle
|
||||
checked={indexes[0] === field.name}
|
||||
disabled={indexes[1] === field.name}
|
||||
|
|
|
@ -1,73 +1,94 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { backendUiStore } from "builderStore"
|
||||
import { Roles } from "constants/backend"
|
||||
import api from "builderStore/api"
|
||||
import { notifier } from "builderStore/store/notifications"
|
||||
import { Button, Select } from "@budibase/bbui"
|
||||
|
||||
const FORMATS = [
|
||||
{
|
||||
name: "CSV",
|
||||
key: "csv",
|
||||
},
|
||||
{
|
||||
name: "JSON",
|
||||
key: "json",
|
||||
},
|
||||
]
|
||||
import { Button, Label, Select, Spacer } from "@budibase/bbui"
|
||||
|
||||
export let resourceId
|
||||
export let permissions
|
||||
export let levels
|
||||
export let onClosed
|
||||
|
||||
let permissions = {}
|
||||
let levels = []
|
||||
// Draft level and role for editing
|
||||
let level = levels[0]
|
||||
let role = Roles.BASIC
|
||||
|
||||
async function exportView() {
|
||||
onClosed()
|
||||
}
|
||||
$: permissionKeys = Object.keys(permissions)
|
||||
|
||||
async function changePermission(level, role) {
|
||||
console.log({ role, resourceId, level })
|
||||
async function addPermission() {
|
||||
await backendUiStore.actions.permissions.save({
|
||||
level,
|
||||
role,
|
||||
resource: resourceId,
|
||||
level,
|
||||
})
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
// TODO: possibly cleaner
|
||||
// Show updated permissions in UI
|
||||
permissions = await backendUiStore.actions.permissions.forResource(
|
||||
resourceId
|
||||
)
|
||||
levels = await backendUiStore.actions.permissions.fetchLevels()
|
||||
})
|
||||
notifier.success("Access rule saved.")
|
||||
|
||||
// Reset the draft permissions
|
||||
level = levels[0]
|
||||
role = Roles.BASIC
|
||||
}
|
||||
|
||||
async function deletePermission(level, role) {
|
||||
await backendUiStore.actions.permissions.delete({ level, role, resourceId })
|
||||
delete permissions[role]
|
||||
notifier.danger("Removed access rule.")
|
||||
permissions = permissions
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="popover">
|
||||
<h5>Manage Access</h5>
|
||||
<h5>Who Can Access This Data?</h5>
|
||||
<Spacer large />
|
||||
<div class="row">
|
||||
<Label extraSmall grey>Level</Label>
|
||||
<Label extraSmall grey>Role</Label>
|
||||
<div />
|
||||
{#if permissionKeys.length === 0}
|
||||
<Label extraSmall>Default Access Rules Applied.</Label>
|
||||
{/if}
|
||||
{#each permissionKeys as role}
|
||||
<Label small>{permissions[role]}</Label>
|
||||
<Label small>{role}</Label>
|
||||
<i
|
||||
class="ri-close-circle-line delete"
|
||||
on:click={() => deletePermission(permissions[role], role)} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<Spacer large />
|
||||
|
||||
<hr />
|
||||
<Label small>Add Rule</Label>
|
||||
<Spacer small />
|
||||
<div class="draft-permission">
|
||||
<Select label="Level" secondary thin bind:value={level}>
|
||||
{#each levels as level}
|
||||
<Select
|
||||
label={level}
|
||||
secondary
|
||||
thin
|
||||
value={permissions[level]}
|
||||
on:change={e => changePermission(level, e.target.value)}>
|
||||
<option value={level}>{level}</option>
|
||||
{/each}
|
||||
</Select>
|
||||
<Select label="Role" secondary thin bind:value={role}>
|
||||
{#each $backendUiStore.roles as role}
|
||||
<option value={role._id}>{role.name}</option>
|
||||
{/each}
|
||||
</Select>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="footer">
|
||||
<Button secondary on:click={onClosed}>Cancel</Button>
|
||||
<!-- <Button primary on:click={}>Save</Button> -->
|
||||
<Button primary on:click={addPermission}>Edit Rules</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.popover {
|
||||
display: grid;
|
||||
grid-gap: var(--spacing-xl);
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
|
@ -75,9 +96,30 @@
|
|||
font-weight: 500;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: var(--spacing-s) 0 var(--spacing-m) 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--spacing-m);
|
||||
margin-top: var(--spacing-l);
|
||||
}
|
||||
|
||||
.draft-permission {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: var(--spacing-m);
|
||||
}
|
||||
|
||||
.row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 20px;
|
||||
grid-gap: var(--spacing-s);
|
||||
}
|
||||
|
||||
.delete {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -92,3 +92,11 @@ export const HostingTypes = {
|
|||
CLOUD: "cloud",
|
||||
SELF: "self",
|
||||
}
|
||||
|
||||
export const Roles = {
|
||||
ADMIN: "ADMIN",
|
||||
POWER: "POWER",
|
||||
BASIC: "BASIC",
|
||||
PUBLIC: "PUBLIC",
|
||||
BUILDER: "BUILDER",
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue