Handle auth in top level routes and redirect as required. Change default route to be portal
This commit is contained in:
parent
3530d46583
commit
735c724a0d
|
@ -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>
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<script>
|
||||||
|
import { goto } from "@roxi/routify"
|
||||||
|
$goto("./login")
|
||||||
|
</script>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script>
|
||||||
|
import LoginForm from "components/login/LoginForm.svelte"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<LoginForm />
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
Index route
|
<script>
|
||||||
|
import { goto } from "@roxi/routify"
|
||||||
|
$goto("./portal")
|
||||||
|
</script>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue