Auth config forms
This commit is contained in:
parent
431a22aaf0
commit
77d17e143d
|
@ -21,6 +21,7 @@
|
|||
export let showSecondaryButton = false
|
||||
export let secondaryButtonText = undefined
|
||||
export let secondaryAction = undefined
|
||||
export let secondaryButtonWarning = false
|
||||
|
||||
const { hide, cancel } = getContext(Context.Modal)
|
||||
let loading = false
|
||||
|
@ -88,8 +89,11 @@
|
|||
|
||||
{#if showSecondaryButton && secondaryButtonText && secondaryAction}
|
||||
<div class="secondary-action">
|
||||
<Button group secondary on:click={secondary}
|
||||
>{secondaryButtonText}</Button
|
||||
<Button
|
||||
group
|
||||
secondary
|
||||
warning={secondaryButtonWarning}
|
||||
on:click={secondary}>{secondaryButtonText}</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<Body size="S">
|
||||
Create an authentication config that can be shared with queries.
|
||||
</Body>
|
||||
<RestAuthenticationBuilder bind:authConfigs={datasource.config.authConfigs} />
|
||||
<RestAuthenticationBuilder bind:configs={datasource.config.authConfigs} />
|
||||
|
||||
<style>
|
||||
.section-header {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
export let value
|
||||
|
||||
const renderAuthType = () => {
|
||||
const renderAuthType = value => {
|
||||
return AUTH_TYPE_LABELS.filter(type => type.value === value).map(
|
||||
type => type.label
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
{renderAuthType()}
|
||||
{renderAuthType(value)}
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
<script>
|
||||
import {
|
||||
Table,
|
||||
Modal,
|
||||
ModalContent,
|
||||
Layout,
|
||||
ActionButton,
|
||||
Select,
|
||||
Body,
|
||||
Input,
|
||||
} from "@budibase/bbui"
|
||||
import { Table, Modal, Layout, ActionButton } from "@budibase/bbui"
|
||||
import AuthTypeRenderer from "./AuthTypeRenderer.svelte"
|
||||
import { AUTH_TYPE_LABELS, AUTH_TYPES } from "./authTypes"
|
||||
import RestAuthenticationModal from "./RestAuthenticationModal.svelte"
|
||||
|
||||
export let authConfigs = []
|
||||
export let configs = []
|
||||
|
||||
let currentConfig = null
|
||||
let modal
|
||||
let currentConfig
|
||||
let isNew = false
|
||||
|
||||
const schema = {
|
||||
name: "",
|
||||
|
@ -24,73 +14,44 @@
|
|||
}
|
||||
|
||||
const openConfigModal = config => {
|
||||
if (!config) {
|
||||
currentConfig = {
|
||||
config: {},
|
||||
}
|
||||
isNew = true
|
||||
} else {
|
||||
currentConfig = { ...config }
|
||||
isNew = false
|
||||
}
|
||||
currentConfig = config
|
||||
modal.show()
|
||||
}
|
||||
|
||||
const onConfirm = () => {
|
||||
if (isNew) {
|
||||
authConfigs.push(currentConfig)
|
||||
} else {
|
||||
authConfigs = authConfigs.map(c => {
|
||||
const onConfirm = config => {
|
||||
if (currentConfig) {
|
||||
// TODO: Update with _id
|
||||
configs = configs.map(c => {
|
||||
// replace the current config with the new one
|
||||
if (c.name === currentConfig.name) {
|
||||
return currentConfig
|
||||
return config
|
||||
}
|
||||
return c
|
||||
})
|
||||
} else {
|
||||
configs.push(config)
|
||||
configs = [...configs]
|
||||
}
|
||||
}
|
||||
|
||||
const onCancel = () => {
|
||||
currentConfig = {}
|
||||
const onDelete = () => {
|
||||
// TODO: Update with _id
|
||||
configs = configs.filter(c => {
|
||||
return c.name !== currentConfig.name
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:this={modal}>
|
||||
<ModalContent
|
||||
title={isNew ? "Add Authentication" : "Update Authentication"}
|
||||
{onConfirm}
|
||||
{onCancel}
|
||||
confirmText={isNew ? "Add" : "Update"}
|
||||
cancelText="Cancel"
|
||||
size="M"
|
||||
>
|
||||
<Layout gap="S">
|
||||
<Body size="S">
|
||||
The authorization header will be automatically generated when you
|
||||
sendthe request.
|
||||
</Body>
|
||||
<Select
|
||||
label="Type"
|
||||
bind:value={currentConfig.type}
|
||||
options={AUTH_TYPE_LABELS}
|
||||
on:change={({ detail }) => (currentConfig.type = detail)}
|
||||
/>
|
||||
{#if currentConfig.type === AUTH_TYPES.BASIC}
|
||||
<Input label="Username" bind:value={currentConfig.config.username} />
|
||||
<Input label="Password" bind:value={currentConfig.config.password} />
|
||||
{/if}
|
||||
{#if currentConfig.type === AUTH_TYPES.BEARER}
|
||||
<Input label="Token" bind:value={currentConfig.config.token} />
|
||||
{/if}
|
||||
</Layout>
|
||||
</ModalContent>
|
||||
<RestAuthenticationModal {configs} {currentConfig} {onConfirm} {onDelete} />
|
||||
</Modal>
|
||||
|
||||
<Layout gap="S" noPadding>
|
||||
{#if authConfigs && authConfigs.length > 0}
|
||||
{#if configs && configs.length > 0}
|
||||
<Table
|
||||
on:click={({ detail }) => openConfigModal(detail)}
|
||||
{schema}
|
||||
data={authConfigs}
|
||||
data={configs}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
|
@ -103,6 +64,3 @@
|
|||
>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { ModalContent, Layout, Select, Body, Input } from "@budibase/bbui"
|
||||
import { AUTH_TYPE_LABELS, AUTH_TYPES } from "./authTypes"
|
||||
|
||||
export let configs
|
||||
export let currentConfig
|
||||
export let onConfirm
|
||||
export let onDelete
|
||||
|
||||
let form = {
|
||||
basic: {},
|
||||
bearer: {},
|
||||
}
|
||||
|
||||
let errors = {
|
||||
basic: {},
|
||||
bearer: {},
|
||||
}
|
||||
|
||||
let blurred = {
|
||||
basic: {},
|
||||
bearer: {},
|
||||
}
|
||||
|
||||
let hasErrors = false
|
||||
let hasChanged = false
|
||||
|
||||
onMount(() => {
|
||||
if (currentConfig) {
|
||||
deconstructConfig()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* map the current config's data into the form by type
|
||||
*/
|
||||
const deconstructConfig = () => {
|
||||
form.name = currentConfig.name
|
||||
form.type = currentConfig.type
|
||||
|
||||
if (currentConfig.type === AUTH_TYPES.BASIC) {
|
||||
form.basic = {
|
||||
...currentConfig.config,
|
||||
}
|
||||
} else if (currentConfig.type === AUTH_TYPES.BEARER) {
|
||||
form.bearer = {
|
||||
...currentConfig.config,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* map the form into a new config to save by type
|
||||
*/
|
||||
const constructConfig = () => {
|
||||
const newConfig = {
|
||||
name: form.name,
|
||||
type: form.type,
|
||||
}
|
||||
|
||||
if (form.type === AUTH_TYPES.BASIC) {
|
||||
newConfig.config = {
|
||||
...form.basic,
|
||||
}
|
||||
} else if (form.type === AUTH_TYPES.BEARER) {
|
||||
newConfig.config = {
|
||||
...form.bearer,
|
||||
}
|
||||
}
|
||||
|
||||
return newConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* compare the existing config with the new config to see if there are any changes
|
||||
*/
|
||||
const checkChanged = () => {
|
||||
if (currentConfig) {
|
||||
hasChanged =
|
||||
JSON.stringify(currentConfig) !== JSON.stringify(constructConfig())
|
||||
} else {
|
||||
hasChanged = true
|
||||
}
|
||||
}
|
||||
|
||||
const checkErrors = () => {
|
||||
hasErrors = false
|
||||
|
||||
// NAME
|
||||
const nameError = () => {
|
||||
// Unique name
|
||||
if (form.name) {
|
||||
errors.name =
|
||||
// check for duplicate excluding the current config
|
||||
configs.find(
|
||||
c => c.name === form.name && c.name !== currentConfig?.name
|
||||
) !== undefined
|
||||
? "Name must be unique"
|
||||
: null
|
||||
}
|
||||
// Name required
|
||||
else {
|
||||
errors.name = "Name is required"
|
||||
}
|
||||
return !!errors.name
|
||||
}
|
||||
|
||||
// TYPE
|
||||
const typeError = () => {
|
||||
errors.type = form.type ? null : "Type is required"
|
||||
return !!errors.type
|
||||
}
|
||||
|
||||
// BASIC AUTH
|
||||
const basicAuthErrors = () => {
|
||||
errors.basic.username = form.basic.username
|
||||
? null
|
||||
: "Username is required"
|
||||
errors.basic.password = form.basic.password
|
||||
? null
|
||||
: "Password is required"
|
||||
|
||||
return !!(errors.basic.username || errors.basic.password || commonError)
|
||||
}
|
||||
|
||||
// BEARER TOKEN
|
||||
const bearerTokenErrors = () => {
|
||||
errors.bearer.token = form.bearer.token ? null : "Token is required"
|
||||
return !!(errors.bearer.token || commonError)
|
||||
}
|
||||
|
||||
const commonError = nameError() || typeError()
|
||||
if (form.type === AUTH_TYPES.BASIC) {
|
||||
hasErrors = basicAuthErrors() || commonError
|
||||
} else if (form.type === AUTH_TYPES.BEARER) {
|
||||
hasErrors = bearerTokenErrors() || commonError
|
||||
} else {
|
||||
hasErrors = !!commonError
|
||||
}
|
||||
}
|
||||
|
||||
const onFieldChange = () => {
|
||||
checkErrors()
|
||||
checkChanged()
|
||||
}
|
||||
|
||||
const onConfirmInternal = () => {
|
||||
onConfirm(constructConfig())
|
||||
}
|
||||
</script>
|
||||
|
||||
<ModalContent
|
||||
title={currentConfig ? "Update Authentication" : "Add Authentication"}
|
||||
onConfirm={onConfirmInternal}
|
||||
confirmText={currentConfig ? "Update" : "Add"}
|
||||
disabled={hasErrors || !hasChanged}
|
||||
cancelText={"Cancel"}
|
||||
warning={true}
|
||||
size="M"
|
||||
showSecondaryButton={!!currentConfig}
|
||||
secondaryButtonText={"Delete"}
|
||||
secondaryAction={onDelete}
|
||||
secondaryButtonWarning={true}
|
||||
>
|
||||
<Layout gap="S">
|
||||
<Body size="S">
|
||||
The authorization header will be automatically generated when you send the
|
||||
request.
|
||||
</Body>
|
||||
<Input
|
||||
label="Name"
|
||||
bind:value={form.name}
|
||||
on:change={onFieldChange}
|
||||
on:blur={() => (blurred.name = true)}
|
||||
error={blurred.name ? errors.name : null}
|
||||
/>
|
||||
<Select
|
||||
label="Type"
|
||||
bind:value={form.type}
|
||||
on:change={onFieldChange}
|
||||
options={AUTH_TYPE_LABELS}
|
||||
on:blur={() => (blurred.type = true)}
|
||||
error={blurred.type ? errors.type : null}
|
||||
/>
|
||||
{#if form.type === AUTH_TYPES.BASIC}
|
||||
<Input
|
||||
label="Username"
|
||||
bind:value={form.basic.username}
|
||||
on:change={onFieldChange}
|
||||
on:blur={() => (blurred.basic.username = true)}
|
||||
error={blurred.basic.username ? errors.basic.username : null}
|
||||
/>
|
||||
<Input
|
||||
label="Password"
|
||||
bind:value={form.basic.password}
|
||||
on:change={onFieldChange}
|
||||
on:blur={() => (blurred.basic.password = true)}
|
||||
error={blurred.basic.password ? errors.basic.password : null}
|
||||
/>
|
||||
{/if}
|
||||
{#if form.type === AUTH_TYPES.BEARER}
|
||||
<Input
|
||||
label="Token"
|
||||
bind:value={form.bearer.token}
|
||||
on:change={onFieldChange}
|
||||
on:blur={() => (blurred.bearer.token = true)}
|
||||
error={blurred.bearer.token ? errors.bearer.token : null}
|
||||
/>
|
||||
{/if}
|
||||
</Layout>
|
||||
</ModalContent>
|
||||
|
||||
<style>
|
||||
</style>
|
Loading…
Reference in New Issue