Improve handling of permission issues and routing issues, and add an error fallback message

This commit is contained in:
Andrew Kingston 2021-07-07 11:29:35 +01:00
parent ee8033e88f
commit ab4e71c1a4
1 changed files with 72 additions and 23 deletions

View File

@ -18,6 +18,8 @@
import SettingsBar from "./preview/SettingsBar.svelte" import SettingsBar from "./preview/SettingsBar.svelte"
import SelectionIndicator from "./preview/SelectionIndicator.svelte" import SelectionIndicator from "./preview/SelectionIndicator.svelte"
import HoverIndicator from "./preview/HoverIndicator.svelte" import HoverIndicator from "./preview/HoverIndicator.svelte"
import { Layout, Heading, Body } from "@budibase/bbui"
import ErrorSVG from "../../../builder/assets/error.svg"
// Provide contexts // Provide contexts
setContext("sdk", SDK) setContext("sdk", SDK)
@ -25,6 +27,7 @@
setContext("context", createContextStore()) setContext("context", createContextStore())
let dataLoaded = false let dataLoaded = false
let permissionError = false
// Load app config // Load app config
onMount(async () => { onMount(async () => {
@ -46,12 +49,21 @@
}, },
] ]
// Redirect to home layout if no matching route // Handle no matching route - this is likely a permission error
$: { $: {
if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) { if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) {
if ($authStore) { if ($authStore) {
routeStore.actions.navigate("/") // There is a logged in user, so handle them
if ($screenStore.screens.length) {
// Screens exist so navigate back to the home screen
const firstRoute = $screenStore.screens[0].routing?.route ?? "/"
routeStore.actions.navigate(firstRoute)
} else {
// No screens likely means the user has no permissions to view this app
permissionError = true
}
} else { } else {
// The user is not logged in, redirect them to login
const returnUrl = `${window.location.pathname}${window.location.hash}` const returnUrl = `${window.location.pathname}${window.location.hash}`
const encodedUrl = encodeURIComponent(returnUrl) const encodedUrl = encodeURIComponent(returnUrl)
window.location = `/builder/auth/login?returnUrl=${encodedUrl}` window.location = `/builder/auth/login?returnUrl=${encodedUrl}`
@ -60,36 +72,46 @@
} }
</script> </script>
{#if dataLoaded && $screenStore.activeLayout} {#if dataLoaded}
<div <div
id="spectrum-root" id="spectrum-root"
lang="en" lang="en"
dir="ltr" dir="ltr"
class="spectrum spectrum--medium spectrum--light" class="spectrum spectrum--medium spectrum--light"
> >
<Provider key="user" data={$authStore} {actions}> {#if permissionError}
<div id="app-root"> <div class="error">
{#key $screenStore.activeLayout._id} <Layout justifyItems="center" gap="S">
<Component instance={$screenStore.activeLayout.props} /> {@html ErrorSVG}
{/key} <Heading size="L">You don't have permission to use this app</Heading>
<Body size="S">Ask your administrator to grant you access</Body>
</Layout>
</div> </div>
<NotificationDisplay /> {:else if $screenStore.activeLayout}
<ConfirmationDisplay /> <Provider key="user" data={$authStore} {actions}>
<!-- Key block needs to be outside the if statement or it breaks --> <div id="app-root">
{#key $builderStore.selectedComponentId} {#key $screenStore.activeLayout._id}
<Component instance={$screenStore.activeLayout.props} />
{/key}
</div>
<NotificationDisplay />
<ConfirmationDisplay />
<!-- Key block needs to be outside the if statement or it breaks -->
{#key $builderStore.selectedComponentId}
{#if $builderStore.inBuilder}
<SettingsBar />
{/if}
{/key}
<!--
We don't want to key these by componentID as they control their own
re-mounting to avoid flashes.
-->
{#if $builderStore.inBuilder} {#if $builderStore.inBuilder}
<SettingsBar /> <SelectionIndicator />
<HoverIndicator />
{/if} {/if}
{/key} </Provider>
<!-- {/if}
We don't want to key these by componentID as they control their own
re-mounting to avoid flashes.
-->
{#if $builderStore.inBuilder}
<SelectionIndicator />
<HoverIndicator />
{/if}
</Provider>
</div> </div>
{/if} {/if}
@ -105,4 +127,31 @@
#app-root { #app-root {
position: relative; position: relative;
} }
.error {
position: absolute;
width: 100%;
height: 100%;
display: grid;
place-items: center;
z-index: 1;
text-align: center;
padding: 20px;
}
.error :global(svg) {
fill: var(--spectrum-global-color-gray-500);
width: 80px;
height: 80px;
}
.error :global(h1),
.error :global(p) {
color: var(--spectrum-global-color-gray-800);
}
.error :global(p) {
font-style: italic;
margin-top: -0.5em;
}
.error :global(h1) {
font-weight: 400;
}
</style> </style>