Merge pull request #11609 from Budibase/BUDI-7393/dont-allow-frontend

Guard frontend view permissions
This commit is contained in:
Adria Navarro 2023-08-29 15:49:50 +02:00 committed by GitHub
commit 8269dc98cd
6 changed files with 58 additions and 29 deletions

View File

@ -5,6 +5,7 @@
export let resourceId export let resourceId
export let disabled = false export let disabled = false
export let requiresLicence
let modal let modal
let resourcePermissions let resourcePermissions
@ -21,6 +22,7 @@
<Modal bind:this={modal}> <Modal bind:this={modal}>
<ManageAccessModal <ManageAccessModal
{resourceId} {resourceId}
{requiresLicence}
levels={$permissions} levels={$permissions}
permissions={resourcePermissions} permissions={resourcePermissions}
/> />

View File

@ -1,4 +1,5 @@
<script> <script>
import { licensing, admin } from "stores/portal"
import ManageAccessButton from "../ManageAccessButton.svelte" import ManageAccessButton from "../ManageAccessButton.svelte"
import { getContext } from "svelte" import { getContext } from "svelte"
@ -12,6 +13,17 @@
} }
return datasource.type === "table" ? datasource.tableId : datasource.id return datasource.type === "table" ? datasource.tableId : datasource.id
} }
var requiresLicence
$: {
if ($datasource.type === "viewV2" && !$licensing.isViewPermissionsEnabled) {
const requiredLicense = $admin?.cloud ? "Premium" : "Business"
requiresLicence = {
tier: requiredLicense,
message: `A ${requiredLicense} subscription is required to specify access level roles for this view.`,
}
}
}
</script> </script>
<ManageAccessButton {resourceId} /> <ManageAccessButton {resourceId} {requiresLicence} />

View File

@ -7,11 +7,14 @@
notifications, notifications,
Body, Body,
ModalContent, ModalContent,
Tags,
Tag,
} from "@budibase/bbui" } from "@budibase/bbui"
import { capitalise } from "helpers" import { capitalise } from "helpers"
export let resourceId export let resourceId
export let permissions export let permissions
export let requiresLicence
async function changePermission(level, role) { async function changePermission(level, role) {
try { try {
@ -30,22 +33,36 @@
} }
</script> </script>
<ModalContent title="Manage Access" showCancelButton={false} confirmText="Done"> <ModalContent showCancelButton={false} confirmText="Done">
<Body size="S">Specify the minimum access level role for this data.</Body> <span slot="header">
<div class="row"> Manage Access
<Label extraSmall grey>Level</Label> {#if requiresLicence}
<Label extraSmall grey>Role</Label> <span class="lock-tag">
{#each Object.keys(permissions) as level} <Tags>
<Input value={capitalise(level)} disabled /> <Tag icon="LockClosed">{requiresLicence.tier}</Tag>
<Select </Tags>
value={permissions[level]} </span>
on:change={e => changePermission(level, e.detail)} {/if}
options={$roles} </span>
getOptionLabel={x => x.name} {#if requiresLicence}
getOptionValue={x => x._id} <Body size="S">{requiresLicence.message}</Body>
/> {:else}
{/each} <Body size="S">Specify the minimum access level role for this data.</Body>
</div> <div class="row">
<Label extraSmall grey>Level</Label>
<Label extraSmall grey>Role</Label>
{#each Object.keys(permissions) as level}
<Input value={capitalise(level)} disabled />
<Select
value={permissions[level]}
on:change={e => changePermission(level, e.detail)}
options={$roles}
getOptionLabel={x => x.name}
getOptionValue={x => x._id}
/>
{/each}
</div>
{/if}
</ModalContent> </ModalContent>
<style> <style>
@ -54,4 +71,8 @@
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
grid-gap: var(--spacing-s); grid-gap: var(--spacing-s);
} }
.lock-tag {
padding-left: var(--spacing-s);
}
</style> </style>

View File

@ -125,6 +125,9 @@ export const createLicensingStore = () => {
const syncAutomationsEnabled = license.features.includes( const syncAutomationsEnabled = license.features.includes(
Constants.Features.SYNC_AUTOMATIONS Constants.Features.SYNC_AUTOMATIONS
) )
const isViewPermissionsEnabled = license.features.includes(
Constants.Features.VIEW_PERMISSIONS
)
store.update(state => { store.update(state => {
return { return {
...state, ...state,
@ -140,6 +143,7 @@ export const createLicensingStore = () => {
auditLogsEnabled, auditLogsEnabled,
enforceableSSO, enforceableSSO,
syncAutomationsEnabled, syncAutomationsEnabled,
isViewPermissionsEnabled,
} }
}) })
}, },

View File

@ -2,6 +2,7 @@
* Operator options for lucene queries * Operator options for lucene queries
*/ */
export { OperatorOptions, SqlNumberTypeRangeMap } from "@budibase/shared-core" export { OperatorOptions, SqlNumberTypeRangeMap } from "@budibase/shared-core"
export { Feature as Features } from "@budibase/types"
// Cookie names // Cookie names
export const Cookies = { export const Cookies = {
@ -62,17 +63,6 @@ export const PlanType = {
*/ */
export const ApiVersion = "1" export const ApiVersion = "1"
export const Features = {
USER_GROUPS: "userGroups",
BACKUPS: "appBackups",
ENVIRONMENT_VARIABLES: "environmentVariables",
AUDIT_LOGS: "auditLogs",
ENFORCEABLE_SSO: "enforceableSSO",
BRANDING: "branding",
SCIM: "scim",
SYNC_AUTOMATIONS: "syncAutomations",
}
// Role IDs // Role IDs
export const Roles = { export const Roles = {
ADMIN: "ADMIN", ADMIN: "ADMIN",

View File

@ -12,7 +12,7 @@ export enum Feature {
APP_BUILDERS = "appBuilders", APP_BUILDERS = "appBuilders",
OFFLINE = "offline", OFFLINE = "offline",
USER_ROLE_PUBLIC_API = "userRolePublicApi", USER_ROLE_PUBLIC_API = "userRolePublicApi",
VIEW_PERMISSIONS = "viewPermission", VIEW_PERMISSIONS = "viewPermissions",
} }
export type PlanFeatures = { [key in PlanType]: Feature[] | undefined } export type PlanFeatures = { [key in PlanType]: Feature[] | undefined }