Fixes for datasource authentication parsing. Mapping UX updates

This commit is contained in:
Dean 2022-07-01 17:27:24 +01:00
parent ac8513bd4c
commit 31b51e1ecf
8 changed files with 165 additions and 59 deletions

View File

@ -40,5 +40,6 @@
on:change={onChange}
on:pick
on:type
on:blur
/>
</Field>

View File

@ -52,7 +52,10 @@
{id}
type="text"
on:focus={() => (focus = true)}
on:blur={() => (focus = false)}
on:blur={() => {
focus = false
dispatch("blur")
}}
on:change={onType}
value={value || ""}
placeholder={placeholder || ""}

View File

@ -54,7 +54,56 @@ export const getBindableProperties = (asset, componentId) => {
*/
export const getRestBindings = () => {
const userBindings = getUserBindings()
return [...userBindings]
return [...userBindings, ...getAuthBindings()]
}
/**
* Gets all rest bindable auth fields
*/
export const getAuthBindings = () => {
let bindings = []
const safeUser = makePropSafe("user")
const safeOAuth2 = makePropSafe("oauth2")
const safeAccessToken = makePropSafe("accessToken")
const authBindings = [
{
runtime: `${safeUser}.${safeOAuth2}.${safeAccessToken}`,
readable: `Current User.OAuthToken`,
key: "accessToken",
},
]
bindings = Object.keys(authBindings).map(key => {
const fieldBinding = authBindings[key]
return {
type: "context",
runtimeBinding: fieldBinding.runtime,
readableBinding: fieldBinding.readable,
fieldSchema: { type: "string", name: fieldBinding.key },
providerId: "user",
}
})
return bindings
}
/**
* Utility - convert a key/value map to an array of custom 'context' bindings
* @param {object} valueMap Key/value pairings
* @param {string} prefix A contextual string prefix/path for a user readable binding
* @return {object[]} An array containing readable/runtime binding objects
*/
export const toBindingsArray = (valueMap, prefix) => {
if (!valueMap) {
return []
}
return Object.keys(valueMap).map(binding => {
return {
type: "context",
runtimeBinding: binding,
readableBinding: `${prefix}.${binding}`,
}
})
}
/**

View File

@ -2,6 +2,8 @@
import { onMount } from "svelte"
import { ModalContent, Layout, Select, Body, Input } from "@budibase/bbui"
import { AUTH_TYPE_LABELS, AUTH_TYPES } from "./authTypes"
import DrawerBindableCombobox from "components/common/bindings/DrawerBindableCombobox.svelte"
import { getAuthBindings } from "builderStore/dataBinding"
export let configs
export let currentConfig
@ -203,11 +205,23 @@
/>
{/if}
{#if form.type === AUTH_TYPES.BEARER}
<Input
<DrawerBindableCombobox
label="Token"
bind:value={form.bearer.token}
on:change={onFieldChange}
on:blur={() => (blurred.bearer.token = true)}
value={form.bearer.token}
bindings={getAuthBindings()}
on:change={e => {
form.bearer.token = e.detail
console.log(e.detail)
onFieldChange()
}}
on:blur={() => {
blurred.bearer.token = true
onFieldChange()
}}
allowJS={false}
placeholder="Token"
appendBindingsAsOptions={true}
drawerEnabled={false}
error={blurred.bearer.token ? errors.bearer.token : null}
/>
{/if}

View File

@ -18,6 +18,8 @@
export let options
export let allowJS = true
export let appendBindingsAsOptions = true
export let drawerEnabled = false
export let error
const dispatch = createEventDispatcher()
let bindingDrawer
@ -59,10 +61,12 @@
value={isJS ? "(JavaScript function)" : readableValue}
on:type={e => onChange(e.detail, false)}
on:pick={e => onChange(e.detail, true)}
on:blur={() => dispatch("blur")}
{placeholder}
options={allOptions}
{error}
/>
{#if !disabled}
{#if !disabled && drawerEnabled}
<div
class="icon"
on:click={bindingDrawer.show}
@ -72,6 +76,7 @@
</div>
{/if}
</div>
{#if !drawerEnabled}
<Drawer bind:this={bindingDrawer} {title}>
<svelte:fragment slot="description">
Add the objects on the left to enrich your text.
@ -87,6 +92,7 @@
{allowJS}
/>
</Drawer>
{/if}
<style>
.control {

View File

@ -11,6 +11,7 @@
} from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import { lowercase } from "helpers"
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
let dispatch = createEventDispatcher()
@ -30,6 +31,7 @@
export let tooltip
export let menuItems
export let showMenu = false
export let bindings = []
let fields = Object.entries(object || {}).map(([name, value]) => ({
name,
@ -108,6 +110,16 @@
/>
{#if options}
<Select bind:value={field.value} on:change={changed} {options} />
{:else if bindings && bindings.length}
<DrawerBindableInput
{bindings}
placeholder="Value"
on:change={e => (field.value = e.detail)}
disabled={readOnly}
value={field.value}
allowJS={false}
fillWidth={true}
/>
{:else}
<Input
placeholder={valuePlaceholder}

View File

@ -42,8 +42,9 @@
import {
getRestBindings,
readableToRuntimeBinding,
toBindingsArray,
runtimeToReadableBinding,
readableToRuntimeBinding,
runtimeToReadableMap,
readableToRuntimeMap,
} from "builderStore/dataBinding"
@ -57,6 +58,25 @@
let dynamicVariables, addVariableModal, varBinding
let restBindings = getRestBindings()
$: staticVariables = datasource?.config?.staticVariables || {}
$: customRequestBindings = toBindingsArray(requestBindings, "Binding")
$: dynamicRequestBindings = toBindingsArray(dynamicVariables, "Dynamic")
$: dataSourceStaticBindings = toBindingsArray(
staticVariables,
"Datasource.Static"
)
$: mergedBindings = [
...restBindings,
...customRequestBindings,
...dynamicRequestBindings,
...dataSourceStaticBindings,
]
$: mergedAndCompleteBindings = mergedBindings.filter(binding => {
return binding.runtimeBinding && binding.readableBinding
})
$: datasourceType = datasource?.source
$: integrationInfo = $integrations[datasourceType]
$: queryConfig = integrationInfo?.query
@ -72,7 +92,10 @@
Object.keys(schema || {}).length !== 0 ||
Object.keys(query?.schema || {}).length !== 0
$: runtimeUrlQueries = readableToRuntimeMap(restBindings, breakQs)
$: runtimeUrlQueries = readableToRuntimeMap(
mergedAndCompleteBindings,
breakQs
)
function getSelectedQuery() {
const cloneQuery = cloneDeep(
@ -87,32 +110,18 @@
queryVerb: "read",
}
)
if (cloneQuery?.fields?.headers) {
cloneQuery.fields.headers = runtimeToReadableMap(
restBindings,
cloneQuery.fields.headers
)
}
if (cloneQuery?.fields?.requestBody) {
cloneQuery.fields.requestBody =
typeof cloneQuery.fields.requestBody === "object"
? runtimeToReadableMap(restBindings, cloneQuery.fields.requestBody)
? runtimeToReadableMap(
mergedAndCompleteBindings,
cloneQuery.fields.requestBody
)
: runtimeToReadableBinding(
restBindings,
mergedAndCompleteBindings,
cloneQuery.fields.requestBody
)
}
if (cloneQuery?.parameters) {
const flatParams = restUtils.queryParametersToKeyValue(
cloneQuery.parameters
)
const updatedParams = runtimeToReadableMap(restBindings, flatParams)
cloneQuery.parameters = restUtils.keyValueToQueryParameters(updatedParams)
}
return cloneQuery
}
@ -128,7 +137,7 @@
return base
}
const qs = restUtils.buildQueryString(
runtimeToReadableMap(restBindings, qsObj)
runtimeToReadableMap(mergedAndCompleteBindings, qsObj)
)
let newUrl = base
if (base.includes("?")) {
@ -140,14 +149,17 @@
function buildQuery() {
const newQuery = cloneDeep(query)
const queryString = restUtils.buildQueryString(runtimeUrlQueries)
newQuery.fields.headers = readableToRuntimeMap(
restBindings,
newQuery.fields.headers
)
newQuery.fields.requestBody =
typeof newQuery.fields.requestBody === "object"
? readableToRuntimeMap(restBindings, newQuery.fields.requestBody)
: readableToRuntimeBinding(restBindings, newQuery.fields.requestBody)
? readableToRuntimeMap(
mergedAndCompleteBindings,
newQuery.fields.requestBody
)
: readableToRuntimeBinding(
mergedAndCompleteBindings,
newQuery.fields.requestBody
)
newQuery.fields.path = url.split("?")[0]
newQuery.fields.queryString = queryString
@ -155,14 +167,6 @@
newQuery.fields.disabledHeaders = restUtils.flipHeaderState(enabledHeaders)
newQuery.schema = restUtils.fieldsToSchema(schema)
const parsedRequestBindings = readableToRuntimeMap(
restBindings,
requestBindings
)
newQuery.parameters = restUtils.keyValueToQueryParameters(
parsedRequestBindings
)
return newQuery
}
@ -409,10 +413,20 @@
headings
keyPlaceholder="Binding name"
valuePlaceholder="Default"
bindings={[
...restBindings,
...dynamicRequestBindings,
...dataSourceStaticBindings,
]}
/>
</Tab>
<Tab title="Params">
<KeyValueBuilder bind:object={breakQs} name="param" headings />
<KeyValueBuilder
bind:object={breakQs}
name="param"
headings
bindings={mergedAndCompleteBindings}
/>
</Tab>
<Tab title="Headers">
<KeyValueBuilder
@ -421,6 +435,7 @@
toggle
name="header"
headings
bindings={mergedAndCompleteBindings}
/>
</Tab>
<Tab title="Body">

View File

@ -36,6 +36,12 @@ class QueryRunner {
if (!Integration) {
throw "Integration type does not exist."
}
datasource.config.authConfigs = enrichQueryFields(
datasource.config.authConfigs,
this.ctx
)
const integration = new Integration(datasource.config)
// pre-query, make sure datasource variables are added to parameters