Handle auth in top level routes and redirect as required. Change default route to be portal

This commit is contained in:
Andrew Kingston 2021-05-06 14:49:11 +01:00
parent 3530d46583
commit 735c724a0d
10 changed files with 86 additions and 170 deletions

View File

@ -1,7 +1,7 @@
<script> <script>
import { goto } from "@roxi/routify"
import { import {
notifications, notifications,
Button,
Link, Link,
Input, Input,
Modal, Modal,
@ -19,26 +19,17 @@
password, password,
}) })
notifications.success("Logged in successfully.") notifications.success("Logged in successfully.")
$goto("../portal")
} catch (err) { } catch (err) {
console.error(err) console.error(err)
notifications.error("Invalid credentials") notifications.error("Invalid credentials")
} }
} }
async function createTestUser() {
try {
await auth.firstUser()
notifications.success("Test user created")
} catch (err) {
console.error(err)
notifications.error("Could not create test user")
}
}
</script> </script>
<Modal fixed> <Modal fixed>
<ModalContent <ModalContent
size="L" size="M"
title="Log In" title="Log In"
onConfirm={login} onConfirm={login}
confirmText="Log In" confirmText="Log In"
@ -51,7 +42,6 @@
<Link target="_blank" href="/api/admin/auth/google"> <Link target="_blank" href="/api/admin/auth/google">
Sign In With Google Sign In With Google
</Link> </Link>
<Button secondary on:click={createTestUser}>Create Test User</Button>
</div> </div>
</ModalContent> </ModalContent>
</Modal> </Modal>

View File

@ -1,27 +1,26 @@
<script> <script>
import { onMount } from "svelte" import { onMount } from "svelte"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import { import { auth } from "stores/backend"
SideNavigation as Navigation,
SideNavigationItem as Item,
} from "@budibase/bbui"
import { admin } from "stores/portal" import { admin } from "stores/portal"
import LoginForm from "components/login/LoginForm.svelte"
import BuilderSettingsButton from "components/start/BuilderSettingsButton.svelte"
import LogoutButton from "components/start/LogoutButton.svelte"
import Logo from "/assets/budibase-logo.svg"
import api from "builderStore/api"
let checklist let checked = false
onMount(async () => { onMount(async () => {
await admin.init() await admin.init()
if (!$admin?.checklist?.adminUser) { if (!$admin?.checklist?.adminUser) {
$goto("./admin") $goto("./admin")
} else { } else {
$goto("./portal") await auth.checkAuth()
checked = true
} }
}) })
$: {
if (checked && !$auth.user) {
$goto("./auth/login")
}
}
</script> </script>
{#if $admin.checklist} {#if $admin.checklist}

View File

@ -0,0 +1,4 @@
<script>
import { goto } from "@roxi/routify"
$goto("./login")
</script>

View File

@ -0,0 +1,5 @@
<script>
import LoginForm from "components/login/LoginForm.svelte"
</script>
<LoginForm />

View File

@ -60,7 +60,7 @@
<img <img
src={Logo} src={Logo}
alt="budibase icon" alt="budibase icon"
on:click={() => $goto(`/builder/`)} on:click={() => $goto(`../../portal/`)}
/> />
</button> </button>

View File

@ -1,120 +1,4 @@
<script> <script>
import api from "builderStore/api" import { goto } from "@roxi/routify"
import { get } from "builderStore/api" $goto("../portal")
import CreateAppModal from "components/start/CreateAppModal.svelte"
import { Button, Heading, Modal, ButtonGroup } from "@budibase/bbui"
import TemplateList from "components/start/TemplateList.svelte"
import analytics from "analytics"
import Banner from "/assets/orange-landscape.png"
let hasKey
let template
let modal
async function getApps() {
const res = await get("/api/applications")
const json = await res.json()
if (res.ok) {
return json
} else {
throw new Error(json)
}
}
async function fetchKeys() {
const response = await api.get(`/api/keys/`)
return await response.json()
}
async function checkIfKeysAndApps() {
const keys = await fetchKeys()
const apps = await getApps()
if (keys.userId) {
hasKey = true
analytics.identify(keys.userId)
}
}
function selectTemplate(newTemplate) {
template = newTemplate
modal.show()
}
function initiateAppImport() {
template = { fromFile: true }
modal.show()
}
function closeModal() {
template = null
modal.hide()
}
checkIfKeysAndApps()
</script> </script>
<div class="container">
<div class="header">
<Heading size="M">Welcome to the Budibase Beta</Heading>
<ButtonGroup>
<Button secondary on:click={initiateAppImport}>Import Web App</Button>
<Button cta on:click={modal.show}>Create New Web App</Button>
</ButtonGroup>
</div>
<div class="banner">
<img src={Banner} alt="rocket" />
<div class="banner-content">
Every accomplishment starts with a decision to try.
</div>
</div>
<!-- <TemplateList onSelect={selectTemplate} /> -->
</div>
<Modal bind:this={modal} padding={false} width="600px" on:hide={closeModal}>
<CreateAppModal {hasKey} {template} />
</Modal>
<style>
.container {
display: grid;
gap: var(--spacing-xl);
margin: 40px 80px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.banner {
display: flex;
align-items: center;
justify-content: center;
position: relative;
text-align: center;
color: white;
border-radius: 16px;
}
.banner img {
height: 250px;
width: 100%;
border-radius: 5px;
}
.banner-content {
position: absolute;
font-size: 24px;
color: white;
font-weight: 500;
}
.button-group {
display: flex;
flex-direction: row;
}
</style>

View File

@ -1 +1,4 @@
Index route <script>
import { goto } from "@roxi/routify"
$goto("./portal")
</script>

View File

@ -1,5 +1,5 @@
<script> <script>
import { isActive } from "@roxi/routify" import { isActive, goto } from "@roxi/routify"
import { onMount } from "svelte" import { onMount } from "svelte"
import { import {
Icon, Icon,
@ -11,6 +11,8 @@
} from "@budibase/bbui" } from "@budibase/bbui"
import ConfigChecklist from "components/common/ConfigChecklist.svelte" import ConfigChecklist from "components/common/ConfigChecklist.svelte"
import { organisation, apps } from "stores/portal" import { organisation, apps } from "stores/portal"
import BuilderSettingsButton from "components/start/BuilderSettingsButton.svelte"
import LogoutButton from "components/start/LogoutButton.svelte"
organisation.init() organisation.init()
apps.load() apps.load()
@ -45,7 +47,7 @@
<div class="nav"> <div class="nav">
<Layout paddingX="L" paddingY="L"> <Layout paddingX="L" paddingY="L">
<div class="branding"> <div class="branding">
<div class="name"> <div class="name" on:click={() => $goto("./apps")}>
<img <img
src={$organisation?.logoUrl || "https://i.imgur.com/ZKyklgF.png"} src={$organisation?.logoUrl || "https://i.imgur.com/ZKyklgF.png"}
alt="Logotype" alt="Logotype"
@ -62,6 +64,8 @@
<Item selected={$isActive(href)} {href} {heading}>{title}</Item> <Item selected={$isActive(href)} {href} {heading}>{title}</Item>
{/each} {/each}
</Navigation> </Navigation>
<BuilderSettingsButton />
<LogoutButton />
</div> </div>
</Layout> </Layout>
</div> </div>
@ -106,6 +110,9 @@
grid-gap: var(--spacing-m); grid-gap: var(--spacing-m);
align-items: center; align-items: center;
} }
.name:hover {
cursor: pointer;
}
.avatar { .avatar {
display: grid; display: grid;
grid-template-columns: auto auto; grid-template-columns: auto auto;

View File

@ -5,17 +5,43 @@
Button, Button,
ActionButton, ActionButton,
ActionGroup, ActionGroup,
ButtonGroup,
Select, Select,
Modal,
} from "@budibase/bbui" } from "@budibase/bbui"
import AppList from "components/start/AppList.svelte" import AppList from "components/start/AppList.svelte"
import CreateAppModal from "components/start/CreateAppModal.svelte"
import api from "builderStore/api"
import analytics from "analytics"
import { onMount } from "svelte"
let layout = "grid" let layout = "grid"
let modal
let template
async function checkKeys() {
const response = await api.get(`/api/keys/`)
const keys = await response.json()
if (keys.userId) {
analytics.identify(keys.userId)
}
}
function initiateAppImport() {
template = { fromFile: true }
modal.show()
}
onMount(checkKeys)
</script> </script>
<Layout noPadding> <Layout noPadding>
<div class="title"> <div class="title">
<Heading>Apps</Heading> <Heading>Apps</Heading>
<Button primary>Create new app</Button> <ButtonGroup>
<Button secondary on:click={initiateAppImport}>Import app</Button>
<Button cta on:click={modal.show}>Create new app</Button>
</ButtonGroup>
</div> </div>
<div class="filter"> <div class="filter">
<div class="select"> <div class="select">
@ -42,6 +68,14 @@
Table Table
{/if} {/if}
</Layout> </Layout>
<Modal
bind:this={modal}
padding={false}
width="600px"
on:hide={() => (template = null)}
>
<CreateAppModal {template} />
</Modal>
<style> <style>
.title, .title,

View File

@ -1,28 +1,25 @@
import { writable } from "svelte/store" import { writable } from "svelte/store"
import api from "../../builderStore/api" import api from "../../builderStore/api"
async function checkAuth() {
const response = await api.get("/api/self")
const user = await response.json()
if (response.status === 200) return user
return null
}
export function createAuthStore() { export function createAuthStore() {
const { subscribe, set } = writable(null) const store = writable({ user: null })
checkAuth()
.then(user => set({ user }))
.catch(() => set({ user: null }))
return { return {
subscribe, subscribe: store.subscribe,
checkAuth: async () => {
const response = await api.get("/api/self")
const user = await response.json()
if (response.status === 200) {
store.update(state => ({ ...state, user }))
} else {
store.update(state => ({ ...state, user: null }))
}
},
login: async creds => { login: async creds => {
const response = await api.post(`/api/admin/auth`, creds) const response = await api.post(`/api/admin/auth`, creds)
const json = await response.json() const json = await response.json()
if (response.status === 200) { if (response.status === 200) {
set({ user: json.user }) store.update(state => ({ ...state, user: json.user }))
} else { } else {
throw "Invalid credentials" throw "Invalid credentials"
} }
@ -34,7 +31,7 @@ export function createAuthStore() {
throw "Unable to create logout" throw "Unable to create logout"
} }
await response.json() await response.json()
set({ user: null }) store.update(state => ({ ...state, user: null }))
}, },
createUser: async user => { createUser: async user => {
const response = await api.post(`/api/admin/users`, user) const response = await api.post(`/api/admin/users`, user)
@ -43,13 +40,6 @@ export function createAuthStore() {
} }
await response.json() await response.json()
}, },
firstUser: async () => {
const response = await api.post(`/api/admin/users/first`)
if (response.status !== 200) {
throw "Unable to create test user"
}
await response.json()
},
} }
} }