Move some role logic to frontend core and enable client library to preferentially route to home screens

This commit is contained in:
Andrew Kingston 2022-04-28 15:13:33 +01:00
parent 5b5208dfc0
commit 3e8192552d
8 changed files with 92 additions and 65 deletions

View File

@ -1,7 +1,7 @@
<script> <script>
import { Label, notifications, Select } from "@budibase/bbui" import { Label, notifications, Select } from "@budibase/bbui"
import { permissions, roles } from "stores/backend" import { permissions, roles } from "stores/backend"
import { Roles } from "constants/backend" import { Constants } from "@budibase/frontend-core"
export let query export let query
export let label export let label
@ -35,14 +35,14 @@
} }
fetched = queryToFetch fetched = queryToFetch
if (!queryToFetch || !queryToFetch._id) { if (!queryToFetch || !queryToFetch._id) {
roleId = Roles.BASIC roleId = Constants.Roles.BASIC
loaded = true loaded = true
return return
} }
try { try {
roleId = (await permissions.forResource(queryToFetch._id))["read"] roleId = (await permissions.forResource(queryToFetch._id))["read"]
} catch (err) { } catch (err) {
roleId = Roles.BASIC roleId = Constants.Roles.BASIC
} }
loaded = true loaded = true
} }

View File

@ -1,23 +1,7 @@
import { Roles } from "./backend"
export const TableNames = { export const TableNames = {
USERS: "ta_users", USERS: "ta_users",
} }
export const RoleColours = {
[Roles.ADMIN]: "var(--spectrum-global-color-static-seafoam-400)",
[Roles.POWER]: "var(--spectrum-global-color-static-purple-400)",
[Roles.BASIC]: "var(--spectrum-global-color-static-magenta-400)",
[Roles.PUBLIC]: "var(--spectrum-global-color-static-yellow-400)",
}
export const RolePriorities = {
[Roles.ADMIN]: 4,
[Roles.POWER]: 3,
[Roles.BASIC]: 2,
[Roles.PUBLIC]: 1,
}
export const FrontendTypes = { export const FrontendTypes = {
PAGE: "page", PAGE: "page",
SCREEN: "screen", SCREEN: "screen",

View File

@ -3,17 +3,13 @@
import AppPreview from "./AppPreview.svelte" import AppPreview from "./AppPreview.svelte"
import { store, selectedScreen } from "builderStore" import { store, selectedScreen } from "builderStore"
import { Button, Select, StatusLight, Body } from "@budibase/bbui" import { Button, Select, StatusLight, Body } from "@budibase/bbui"
import { RoleColours } from "constants" import { RoleUtils } from "@budibase/frontend-core"
import { roles } from "stores/backend" import { roles } from "stores/backend"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
$: roleId = $selectedScreen?.routing.roleId $: roleId = $selectedScreen?.routing.roleId
$: roleColor = getRoleColor(roleId) $: roleColor = RoleUtils.getRoleColour(roleId)
$: roleName = $roles.find(x => x._id === roleId)?.name || "Unknown" $: roleName = $roles.find(x => x._id === roleId)?.name || "Unknown"
const getRoleColor = roleId => {
return RoleColours[roleId] || "#ff6500"
}
</script> </script>
<div class="app-panel"> <div class="app-panel">

View File

@ -5,8 +5,9 @@
import { store } from "builderStore" import { store } from "builderStore"
import NavItem from "components/common/NavItem.svelte" import NavItem from "components/common/NavItem.svelte"
import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte" import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte"
import { RoleColours, RolePriorities } from "constants"
import ScreenWizard from "./ScreenWizard.svelte" import ScreenWizard from "./ScreenWizard.svelte"
import { RoleUtils } from "@budibase/frontend-core"
let searchString let searchString
let accessRole = "all" let accessRole = "all"
let showNewScreenModal let showNewScreenModal
@ -28,8 +29,8 @@
.slice() .slice()
.sort((a, b) => { .sort((a, b) => {
// Sort by role first // Sort by role first
const roleA = RolePriorities[a.routing.roleId] ?? 0 const roleA = RoleUtils.getRolePriority(a.routing.roleId)
const roleB = RolePriorities[b.routing.roleId] ?? 0 const roleB = RoleUtils.getRolePriority(b.routing.roleId)
if (roleA !== roleB) { if (roleA !== roleB) {
return roleA > roleB ? -1 : 1 return roleA > roleB ? -1 : 1
} }
@ -43,10 +44,6 @@
return a.routing.route < b.routing.route ? -1 : 1 return a.routing.route < b.routing.route ? -1 : 1
}) })
} }
const getRoleColor = roleId => {
return RoleColours[roleId] || "#ff6500"
}
</script> </script>
<NavigationPanel <NavigationPanel
@ -75,7 +72,7 @@
selected={$store.selectedScreenId === screen._id} selected={$store.selectedScreenId === screen._id}
text={screen.routing.route} text={screen.routing.route}
on:click={() => ($store.selectedScreenId = screen._id)} on:click={() => ($store.selectedScreenId = screen._id)}
color={getRoleColor(screen.routing.roleId)} color={RoleUtils.getRoleColour(screen.routing.roleId)}
> >
<ScreenDropdownMenu screenId={screen._id} /> <ScreenDropdownMenu screenId={screen._id} />
</NavItem> </NavItem>

View File

@ -3,7 +3,7 @@
import { setContext, onMount } from "svelte" import { setContext, onMount } from "svelte"
import { Layout, Heading, Body } from "@budibase/bbui" import { Layout, Heading, Body } from "@budibase/bbui"
import ErrorSVG from "@budibase/frontend-core/assets/error.svg" import ErrorSVG from "@budibase/frontend-core/assets/error.svg"
import { Constants, CookieUtils } from "@budibase/frontend-core" import { Constants, CookieUtils, RoleUtils } from "@budibase/frontend-core"
import Component from "./Component.svelte" import Component from "./Component.svelte"
import SDK from "sdk" import SDK from "sdk"
import { import {
@ -41,41 +41,22 @@
let dataLoaded = false let dataLoaded = false
let permissionError = false let permissionError = false
// Load app config // Determine if we should show devtools or not
onMount(async () => { $: isDevPreview = $appStore.isDevApp && !$builderStore.inBuilder
await initialise()
await authStore.actions.fetchUser()
dataLoaded = true
if (get(builderStore).inBuilder) {
builderStore.actions.notifyLoaded()
} else {
builderStore.actions.pingEndUser()
}
})
// Handle no matching route - this is likely a permission error // Handle no matching route
$: { $: {
if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) { if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) {
if ($authStore) { if ($authStore) {
// There is a logged in user, so handle them // There is a logged in user, so handle them
if ($screenStore.screens.length) { if ($screenStore.screens.length) {
let firstRoute // Find the best route to push the user to initially
const route = getBestRoute(
// If using devtools, find the first screen matching our role $authStore,
if ($devToolsStore.role) { $screenStore.screens,
const roleRoutes = $screenStore.screens.filter( $devToolsStore.role
screen => screen.routing?.roleId === $devToolsStore.role )
) routeStore.actions.navigate(route)
firstRoute = roleRoutes[0]?.routing?.route || "/"
}
// Otherwise just use the first route
else {
firstRoute = $screenStore.screens[0]?.routing?.route ?? "/"
}
// Screens exist so navigate back to the home screen
routeStore.actions.navigate(firstRoute)
} else { } else {
// No screens likely means the user has no permissions to view this app // No screens likely means the user has no permissions to view this app
permissionError = true permissionError = true
@ -89,7 +70,44 @@
} }
} }
$: isDevPreview = $appStore.isDevApp && !$builderStore.inBuilder const getBestRoute = (user, screens) => {
// Rank all screens, preferring all home screens
const rankScreen = screen => {
const roleId = screen.routing.roleId
let rank = RoleUtils.getRolePriority(roleId)
if (screen.routing.homeScreen) {
rank += 100
}
return rank
}
const enrichedScreens = screens?.map(screen => ({
...screen,
rank: rankScreen(screen),
}))
const rankedScreens = enrichedScreens?.sort((a, b) => {
// First sort by rank
if (a.rank !== b.rank) {
return a.rank > b.rank ? -1 : 1
}
// Then sort alphabetically
return a.routing.route < b.routing.route ? -1 : 1
})
// Use the best ranking screen
return rankedScreens?.[0].routing?.route || "/"
}
// Load app config
onMount(async () => {
await initialise()
await authStore.actions.fetchUser()
dataLoaded = true
if (get(builderStore).inBuilder) {
builderStore.actions.notifyLoaded()
} else {
builderStore.actions.pingEndUser()
}
})
</script> </script>
{#if dataLoaded} {#if dataLoaded}
@ -158,7 +176,7 @@
<PeekScreenDisplay /> <PeekScreenDisplay />
</CustomThemeWrapper> </CustomThemeWrapper>
{#if $appStore.isDevApp && !$builderStore.inBuilder} {#if isDevPreview}
<DevTools /> <DevTools />
{/if} {/if}
</div> </div>

View File

@ -63,3 +63,12 @@ export const TableNames = {
* - Coerce types for search endpoint * - Coerce types for search endpoint
*/ */
export const ApiVersion = "1" export const ApiVersion = "1"
// Role IDs
export const Roles = {
ADMIN: "ADMIN",
POWER: "POWER",
BASIC: "BASIC",
PUBLIC: "PUBLIC",
BUILDER: "BUILDER",
}

View File

@ -1,4 +1,5 @@
export * as LuceneUtils from "./lucene" export * as LuceneUtils from "./lucene"
export * as JSONUtils from "./json" export * as JSONUtils from "./json"
export * as CookieUtils from "./cookies" export * as CookieUtils from "./cookies"
export * as RoleUtils from "./roles"
export * as Utils from "./utils" export * as Utils from "./utils"

View File

@ -0,0 +1,22 @@
import { Roles } from "../constants"
const RolePriorities = {
[Roles.ADMIN]: 4,
[Roles.POWER]: 3,
[Roles.BASIC]: 2,
[Roles.PUBLIC]: 1,
}
const RoleColours = {
[Roles.ADMIN]: "var(--spectrum-global-color-static-seafoam-400)",
[Roles.POWER]: "var(--spectrum-global-color-static-purple-400)",
[Roles.BASIC]: "var(--spectrum-global-color-static-magenta-400)",
[Roles.PUBLIC]: "var(--spectrum-global-color-static-yellow-400)",
}
export const getRolePriority = roleId => {
return RolePriorities[roleId] ?? 0
}
export const getRoleColour = roleId => {
return RoleColours[roleId] ?? "#ffa500"
}