Merge branch 'develop' of github.com:Budibase/budibase into custom-form-validation

This commit is contained in:
Andrew Kingston 2021-08-11 15:09:04 +01:00
commit d1bc289f4b
53 changed files with 328 additions and 160 deletions

View File

@ -5,7 +5,7 @@ version: "3"
services: services:
app-service: app-service:
restart: always restart: always
image: budibase/apps image: budibase.docker.scarf.sh/budibase/apps
container_name: bbapps container_name: bbapps
ports: ports:
- "${APP_PORT}:4002" - "${APP_PORT}:4002"
@ -33,7 +33,7 @@ services:
worker-service: worker-service:
restart: always restart: always
image: budibase/worker image: budibase.docker.scarf.sh/budibase/worker
container_name: bbworker container_name: bbworker
ports: ports:
- "${WORKER_PORT}:4003" - "${WORKER_PORT}:4003"

View File

@ -1,5 +1,5 @@
{ {
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/auth", "name": "@budibase/auth",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"description": "Authentication middlewares for budibase builder and apps", "description": "Authentication middlewares for budibase builder and apps",
"main": "src/index.js", "main": "src/index.js",
"author": "Budibase", "author": "Budibase",

View File

@ -4,6 +4,8 @@ const { DEFAULT_TENANT_ID } = require("../constants")
const env = require("../environment") const env = require("../environment")
const { StaticDatabases, SEPARATOR } = require("./constants") const { StaticDatabases, SEPARATOR } = require("./constants")
const { getTenantId } = require("../tenancy") const { getTenantId } = require("../tenancy")
const fetch = require("node-fetch")
const { getCouch } = require("./index")
const UNICODE_MAX = "\ufff0" const UNICODE_MAX = "\ufff0"
@ -156,6 +158,23 @@ exports.getDeployedAppID = appId => {
return appId return appId
} }
/**
* if in production this will use the CouchDB _all_dbs call to retrieve a list of databases. If testing
* when using Pouch it will use the pouchdb-all-dbs package.
*/
exports.getAllDbs = async () => {
// specifically for testing we use the pouch package for this
if (env.isTest()) {
return getCouch().allDbs()
}
const response = await fetch(`${env.COUCH_DB_URL}/_all_dbs`)
if (response.status === 200) {
return response.json()
} else {
throw "Cannot connect to CouchDB instance"
}
}
/** /**
* Lots of different points in the system need to find the full list of apps, this will * Lots of different points in the system need to find the full list of apps, this will
* enumerate the entire CouchDB cluster and get the list of databases (every app). * enumerate the entire CouchDB cluster and get the list of databases (every app).
@ -163,13 +182,13 @@ exports.getDeployedAppID = appId => {
* different users/companies apps as there is no security around it - all apps are returned. * different users/companies apps as there is no security around it - all apps are returned.
* @return {Promise<object[]>} returns the app information document stored in each app database. * @return {Promise<object[]>} returns the app information document stored in each app database.
*/ */
exports.getAllApps = async (CouchDB, { dev, all } = {}) => { exports.getAllApps = async (CouchDB, { dev, all, idsOnly } = {}) => {
let tenantId = getTenantId() let tenantId = getTenantId()
if (!env.MULTI_TENANCY && !tenantId) { if (!env.MULTI_TENANCY && !tenantId) {
tenantId = DEFAULT_TENANT_ID tenantId = DEFAULT_TENANT_ID
} }
let allDbs = await CouchDB.allDbs() let dbs = await exports.getAllDbs()
const appDbNames = allDbs.filter(dbName => { const appDbNames = dbs.filter(dbName => {
const split = dbName.split(SEPARATOR) const split = dbName.split(SEPARATOR)
// it is an app, check the tenantId // it is an app, check the tenantId
if (split[0] === DocumentTypes.APP) { if (split[0] === DocumentTypes.APP) {
@ -183,6 +202,9 @@ exports.getAllApps = async (CouchDB, { dev, all } = {}) => {
} }
return false return false
}) })
if (idsOnly) {
return appDbNames
}
const appPromises = appDbNames.map(db => const appPromises = appDbNames.map(db =>
// skip setup otherwise databases could be re-created // skip setup otherwise databases could be re-created
new CouchDB(db, { skip_setup: true }).get(DocumentTypes.APP_METADATA) new CouchDB(db, { skip_setup: true }).get(DocumentTypes.APP_METADATA)

View File

@ -1,5 +1,4 @@
const PouchDB = require("pouchdb") const PouchDB = require("pouchdb")
const allDbs = require("pouchdb-all-dbs")
const env = require("../../../../environment") const env = require("../../../../environment")
let POUCH_DB_DEFAULTS let POUCH_DB_DEFAULTS
@ -15,6 +14,4 @@ if (env.isTest()) {
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS) const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
allDbs(Pouch)
module.exports = Pouch module.exports = Pouch

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/bbui", "name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.", "description": "A UI solution used in the different Budibase projects.",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"module": "dist/bbui.es.js", "module": "dist/bbui.es.js",

View File

@ -9,6 +9,7 @@
export let text = null export let text = null
export let disabled = false export let disabled = false
export let error = null export let error = null
export let size = "M"
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
const onChange = e => { const onChange = e => {
@ -18,5 +19,5 @@
</script> </script>
<Field {label} {labelPosition} {error}> <Field {label} {labelPosition} {error}>
<Checkbox {error} {disabled} {text} {value} on:change={onChange} /> <Checkbox {error} {disabled} {text} {value} {size} on:change={onChange} />
</Field> </Field>

View File

@ -8,6 +8,7 @@
export let id = null export let id = null
export let text = null export let text = null
export let disabled = false export let disabled = false
export let size = null
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
const onChange = event => { const onChange = event => {
@ -16,7 +17,7 @@
</script> </script>
<label <label
class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-Checkbox--emphasized" class="spectrum-Checkbox spectrum-Checkbox--size{size} spectrum-Checkbox--emphasized"
class:is-invalid={!!error} class:is-invalid={!!error}
> >
<input <input

View File

@ -30,6 +30,7 @@
on:click={onClick} on:click={onClick}
class:is-selected={$selected.title === title} class:is-selected={$selected.title === title}
class="spectrum-Tabs-item" class="spectrum-Tabs-item"
class:emphasized={$selected.title === title && $selected.emphasized}
tabindex="0" tabindex="0"
> >
{#if icon} {#if icon}
@ -49,3 +50,9 @@
<slot /> <slot />
</Portal> </Portal>
{/if} {/if}
<style>
.emphasized {
color: var(--spectrum-global-color-blue-600);
}
</style>

View File

@ -6,9 +6,11 @@
export let selected export let selected
export let vertical = false export let vertical = false
export let noPadding = false export let noPadding = false
export let quiet = false
export let emphasized = false
let _id = id() let _id = id()
const tab = writable({ title: selected, id: _id }) const tab = writable({ title: selected, id: _id, emphasized })
setContext("tab", tab) setContext("tab", tab)
let container let container
@ -56,7 +58,9 @@
<div <div
bind:this={container} bind:this={container}
class="selected-border spectrum-Tabs spectrum-Tabs--{vertical class:quiet
class="selected-border spectrum-Tabs {quiet &&
'spectrum-Tabs--quiet'} spectrum-Tabs--{vertical
? 'vertical' ? 'vertical'
: 'horizontal'}" : 'horizontal'}"
> >
@ -64,7 +68,8 @@
{#if $tab.info} {#if $tab.info}
<div <div
class="spectrum-Tabs-selectionIndicator indicator-transition" class="spectrum-Tabs-selectionIndicator indicator-transition"
style="width: {width}; height: {height}; left: {left}; top: {top};" style="{emphasized &&
'background-color: var(--spectrum-global-color-blue-400)'}; width: {width}; height: {height}; left: {left}; top: {top};"
/> />
{/if} {/if}
</div> </div>
@ -75,6 +80,10 @@
/> />
<style> <style>
.quiet {
border-bottom: none !important;
}
.spectrum-Tabs { .spectrum-Tabs {
padding-left: var(--spacing-xl); padding-left: var(--spacing-xl);
padding-right: var(--spacing-xl); padding-right: var(--spacing-xl);

View File

@ -7,5 +7,15 @@ context("Screen Tests", () => {
it("Should successfully create a screen", () => { it("Should successfully create a screen", () => {
cy.createScreen("Test Screen", "/test") cy.createScreen("Test Screen", "/test")
cy.get(".nav-items-container").within(() => {
cy.contains("/test").should("exist")
})
})
it("Should update the url", () => {
cy.createScreen("Test Screen", "test with spaces")
cy.get(".nav-items-container").within(() => {
cy.contains("/test-with-spaces").should("exist")
})
}) })
}) })

View File

@ -160,7 +160,4 @@ Cypress.Commands.add("createScreen", (screenName, route) => {
cy.get("input").eq(1).type(route) cy.get("input").eq(1).type(route)
cy.get(".spectrum-Button--cta").click() cy.get(".spectrum-Button--cta").click()
}) })
cy.get(".nav-items-container").within(() => {
cy.contains(route).should("exist")
})
}) })

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -65,10 +65,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^0.9.99-alpha.4", "@budibase/bbui": "^0.9.105-alpha.3",
"@budibase/client": "^0.9.99-alpha.4", "@budibase/client": "^0.9.105-alpha.3",
"@budibase/colorpicker": "^1.1.2", "@budibase/colorpicker": "1.1.2",
"@budibase/string-templates": "^0.9.99-alpha.4", "@budibase/string-templates": "^0.9.105-alpha.3",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View File

@ -2,6 +2,7 @@
import { Select, Label, notifications, ModalContent } from "@budibase/bbui" import { Select, Label, notifications, ModalContent } from "@budibase/bbui"
import { tables, views } from "stores/backend" import { tables, views } from "stores/backend"
import analytics from "analytics" import analytics from "analytics"
import { FIELDS } from "constants/backend"
const CALCULATIONS = [ const CALCULATIONS = [
{ {
@ -25,13 +26,16 @@
) )
$: fields = $: fields =
viewTable && viewTable &&
Object.keys(viewTable.schema).filter( Object.keys(viewTable.schema).filter(fieldName => {
field => const field = viewTable.schema[fieldName]
view.calculation === "count" || return (
// don't want to perform calculations based on auto ID field.type !== FIELDS.FORMULA.type &&
(viewTable.schema[field].type === "number" && field.type !== FIELDS.LINK.type &&
!viewTable.schema[field].autocolumn) (view.calculation === "count" ||
) // don't want to perform calculations based on auto ID
(field.type === "number" && !field.autocolumn))
)
})
function saveView() { function saveView() {
views.save(view) views.save(view)

View File

@ -18,10 +18,12 @@
let exportFormat = FORMATS[0].key let exportFormat = FORMATS[0].key
async function exportView() { async function exportView() {
const filename = `export.${exportFormat}`
download( download(
`/api/views/export?view=${encodeURIComponent( `/api/views/export?view=${encodeURIComponent(
view view
)}&format=${exportFormat}` )}&format=${exportFormat}`,
filename
) )
} }
</script> </script>

View File

@ -11,7 +11,11 @@
$: fields = $: fields =
viewTable && viewTable &&
Object.entries(viewTable.schema) Object.entries(viewTable.schema)
.filter(entry => entry[1].type !== FIELDS.LINK.type) .filter(
entry =>
entry[1].type !== FIELDS.LINK.type &&
entry[1].type !== FIELDS.FORMULA.type
)
.map(([key]) => key) .map(([key]) => key)
function saveView() { function saveView() {

View File

@ -84,6 +84,7 @@
if (!event.detail.startsWith("/")) { if (!event.detail.startsWith("/")) {
route = "/" + event.detail route = "/" + event.detail
} }
route = route.replaceAll(" ", "-")
} }
</script> </script>

View File

@ -11,7 +11,11 @@
export let componentInstance export let componentInstance
export let bindings export let bindings
function setAssetProps(name, value) { function setAssetProps(name, value, parser) {
if (parser && typeof parser === "function") {
value = parser(value)
}
const selectedAsset = get(currentAsset) const selectedAsset = get(currentAsset)
store.update(state => { store.update(state => {
if ( if (
@ -29,7 +33,12 @@
const screenSettings = [ const screenSettings = [
// { key: "description", label: "Description", control: Input }, // { key: "description", label: "Description", control: Input },
{ key: "routing.route", label: "Route", control: Input }, {
key: "routing.route",
label: "Route",
control: Input,
parser: val => val.replaceAll(" ", "-"),
},
{ key: "routing.roleId", label: "Access", control: RoleSelect }, { key: "routing.roleId", label: "Access", control: RoleSelect },
{ key: "layoutId", label: "Layout", control: LayoutSelect }, { key: "layoutId", label: "Layout", control: LayoutSelect },
] ]
@ -44,7 +53,7 @@
label={def.label} label={def.label}
key={def.key} key={def.key}
value={deepGet($currentAsset, def.key)} value={deepGet($currentAsset, def.key)}
onChange={val => setAssetProps(def.key, val)} on:change={event => setAssetProps(def.key, event.detail, def.parser)}
{bindings} {bindings}
/> />
{/each} {/each}

View File

@ -31,8 +31,8 @@
// Data to send off // Data to send off
let rating let rating
let improvements let improvements = ""
let comment let comment = ""
function selectNumber(n) { function selectNumber(n) {
rating = n rating = n
@ -106,11 +106,7 @@
<Detail size="S">STEP 2 OF 3</Detail> <Detail size="S">STEP 2 OF 3</Detail>
<ButtonGroup> <ButtonGroup>
<Button secondary on:click={() => (step -= 1)}>Previous</Button> <Button secondary on:click={() => (step -= 1)}>Previous</Button>
<Button <Button primary on:click={() => (step += 1)}>Next</Button>
disabled={!improvements}
primary
on:click={() => (step += 1)}>Next</Button
>
</ButtonGroup> </ButtonGroup>
</div> </div>
{:else} {:else}
@ -121,9 +117,7 @@
<Detail size="S">STEP 3 OF 3</Detail> <Detail size="S">STEP 3 OF 3</Detail>
<ButtonGroup> <ButtonGroup>
<Button secondary on:click={() => (step -= 1)}>Previous</Button> <Button secondary on:click={() => (step -= 1)}>Previous</Button>
<Button disabled={!comment} cta on:click={submitFeedback} <Button cta on:click={submitFeedback}>Complete</Button>
>Complete</Button
>
</ButtonGroup> </ButtonGroup>
</div> </div>
{/if} {/if}

View File

@ -9,6 +9,7 @@
Checkbox, Checkbox,
} from "@budibase/bbui" } from "@budibase/bbui"
import { store, automationStore, hostingStore } from "builderStore" import { store, automationStore, hostingStore } from "builderStore"
import { admin } from "stores/portal"
import { string, mixed, object } from "yup" import { string, mixed, object } from "yup"
import api, { get, post } from "builderStore/api" import api, { get, post } from "builderStore/api"
import analytics from "analytics" import analytics from "analytics"
@ -102,6 +103,8 @@
if (applicationPkg.ok) { if (applicationPkg.ok) {
await store.actions.initialise(pkg) await store.actions.initialise(pkg)
await automationStore.actions.fetch() await automationStore.actions.fetch()
// update checklist - incase first app
await admin.init()
} else { } else {
throw new Error(pkg) throw new Error(pkg)
} }

View File

@ -199,6 +199,9 @@
delete datasource.entities[toTable.name].schema[originalToName] delete datasource.entities[toTable.name].schema[originalToName]
} }
// store the original names so it won't cause an error
originalToName = toRelationship.name
originalFromName = fromRelationship.name
await save() await save()
await tables.fetch() await tables.fetch()
} }

View File

@ -6,7 +6,7 @@
import OktaLogo from "assets/okta-logo.png" import OktaLogo from "assets/okta-logo.png"
import OneLoginLogo from "assets/onelogin-logo.png" import OneLoginLogo from "assets/onelogin-logo.png"
import { oidc, organisation } from "stores/portal" import { oidc, organisation, auth } from "stores/portal"
import { onMount } from "svelte" import { onMount } from "svelte"
$: show = $organisation.oidc $: show = $organisation.oidc
@ -31,7 +31,10 @@
{#if show} {#if show}
<ActionButton <ActionButton
on:click={() => on:click={() =>
window.open(`/api/global/auth/oidc/configs/${$oidc.uuid}`, "_blank")} window.open(
`/api/global/auth/${$auth.tenantId}/oidc/configs/${$oidc.uuid}`,
"_blank"
)}
> >
<div class="inner"> <div class="inner">
<img {src} alt="oidc icon" /> <img {src} alt="oidc icon" />

View File

@ -18,7 +18,7 @@
import api, { del } from "builderStore/api" import api, { del } from "builderStore/api"
import analytics from "analytics" import analytics from "analytics"
import { onMount } from "svelte" import { onMount } from "svelte"
import { apps, auth } from "stores/portal" import { apps, auth, admin } from "stores/portal"
import download from "downloadjs" import download from "downloadjs"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
@ -159,6 +159,8 @@
throw json.message throw json.message
} }
await apps.load() await apps.load()
// get checklist, just in case that was the last app
await admin.init()
notifications.success("App deleted successfully") notifications.success("App deleted successfully")
} catch (err) { } catch (err) {
notifications.error(`Error deleting app: ${err}`) notifications.error(`Error deleting app: ${err}`)

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"license": "MPL-2.0", "license": "MPL-2.0",
"module": "dist/budibase-client.js", "module": "dist/budibase-client.js",
"main": "dist/budibase-client.js", "main": "dist/budibase-client.js",
@ -18,9 +18,9 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^0.9.99-alpha.4", "@budibase/bbui": "^0.9.105-alpha.3",
"@budibase/standard-components": "^0.9.99-alpha.4", "@budibase/standard-components": "^0.9.105-alpha.3",
"@budibase/string-templates": "^0.9.99-alpha.4", "@budibase/string-templates": "^0.9.105-alpha.3",
"regexparam": "^1.3.0", "regexparam": "^1.3.0",
"shortid": "^2.2.15", "shortid": "^2.2.15",
"svelte-spa-router": "^3.0.5" "svelte-spa-router": "^3.0.5"

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.js", "main": "src/index.js",
"repository": { "repository": {
@ -62,9 +62,9 @@
"author": "Budibase", "author": "Budibase",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@budibase/auth": "^0.9.99-alpha.4", "@budibase/auth": "^0.9.105-alpha.3",
"@budibase/client": "^0.9.99-alpha.4", "@budibase/client": "^0.9.105-alpha.3",
"@budibase/string-templates": "^0.9.99-alpha.4", "@budibase/string-templates": "^0.9.105-alpha.3",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",
"@koa/router": "8.0.0", "@koa/router": "8.0.0",
"@sendgrid/mail": "7.1.1", "@sendgrid/mail": "7.1.1",
@ -117,7 +117,7 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.14.3", "@babel/core": "^7.14.3",
"@babel/preset-env": "^7.14.4", "@babel/preset-env": "^7.14.4",
"@budibase/standard-components": "^0.9.99-alpha.4", "@budibase/standard-components": "^0.9.105-alpha.3",
"@jest/test-sequencer": "^24.8.0", "@jest/test-sequencer": "^24.8.0",
"@types/bull": "^3.15.1", "@types/bull": "^3.15.1",
"@types/jest": "^26.0.23", "@types/jest": "^26.0.23",

View File

@ -7,6 +7,7 @@
const CouchDB = require("../src/db") const CouchDB = require("../src/db")
const { DocumentTypes } = require("../src/db/utils") const { DocumentTypes } = require("../src/db/utils")
const { getAllDbs } = require("@budibase/auth/db")
const appName = process.argv[2].toLowerCase() const appName = process.argv[2].toLowerCase()
const remoteUrl = process.argv[3] const remoteUrl = process.argv[3]
@ -14,8 +15,8 @@ const remoteUrl = process.argv[3]
console.log(`Replicating from ${appName} to ${remoteUrl}/${appName}`) console.log(`Replicating from ${appName} to ${remoteUrl}/${appName}`)
const run = async () => { const run = async () => {
const allDbs = await CouchDB.allDbs() const dbs = await getAllDbs()
const appDbNames = allDbs.filter(dbName => dbName.startsWith("inst_app")) const appDbNames = dbs.filter(dbName => dbName.startsWith("inst_app"))
let apps = [] let apps = []
for (let dbName of appDbNames) { for (let dbName of appDbNames) {
const db = new CouchDB(dbName) const db = new CouchDB(dbName)

View File

@ -25,10 +25,10 @@ interface ManyRelationship {
interface RunConfig { interface RunConfig {
id: string id: string
row: Row
filters: SearchFilters filters: SearchFilters
sort: SortJson sort: SortJson
paginate: PaginationJson paginate: PaginationJson
row: Row
} }
module External { module External {
@ -89,8 +89,9 @@ module External {
// build id array // build id array
let idParts = [] let idParts = []
for (let field of primary) { for (let field of primary) {
if (row[field]) { const fieldValue = row[`${table.name}.${field}`]
idParts.push(row[field]) if (fieldValue) {
idParts.push(fieldValue)
} }
} }
if (idParts.length === 0) { if (idParts.length === 0) {
@ -115,7 +116,11 @@ module External {
const thisRow: { [key: string]: any } = {} const thisRow: { [key: string]: any } = {}
// filter the row down to what is actually the row (not joined) // filter the row down to what is actually the row (not joined)
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
thisRow[fieldName] = row[fieldName] const value = row[`${table.name}.${fieldName}`]
// all responses include "select col as table.col" so that overlaps are handled
if (value) {
thisRow[fieldName] = value
}
} }
thisRow._id = generateIdForRow(row, table) thisRow._id = generateIdForRow(row, table)
thisRow.tableId = table._id thisRow.tableId = table._id
@ -191,7 +196,7 @@ module External {
const isUpdate = !field.through const isUpdate = !field.through
const thisKey: string = isUpdate ? "id" : linkTablePrimary const thisKey: string = isUpdate ? "id" : linkTablePrimary
// @ts-ignore // @ts-ignore
const otherKey: string = isUpdate ? field.foreignKey : tablePrimary const otherKey: string = isUpdate ? field.fieldName : tablePrimary
row[key].map((relationship: any) => { row[key].map((relationship: any) => {
// we don't really support composite keys for relationships, this is why [0] is used // we don't really support composite keys for relationships, this is why [0] is used
manyRelationships.push({ manyRelationships.push({
@ -359,7 +364,7 @@ module External {
} }
} }
if (cache[fullKey] == null) { if (cache[fullKey] == null) {
cache[fullKey] = await makeExternalQuery(this.appId, { const response = await makeExternalQuery(this.appId, {
endpoint: getEndpoint(tableId, DataSourceOperation.READ), endpoint: getEndpoint(tableId, DataSourceOperation.READ),
filters: { filters: {
equal: { equal: {
@ -367,8 +372,12 @@ module External {
}, },
}, },
}) })
// this is the response from knex if no rows found
if (!response[0].read) {
cache[fullKey] = response
}
} }
return { rows: cache[fullKey], table } return { rows: cache[fullKey] || [], table }
} }
/** /**
@ -418,12 +427,16 @@ module External {
const { tableName } = breakExternalTableId(tableId) const { tableName } = breakExternalTableId(tableId)
const table = this.tables[tableName] const table = this.tables[tableName]
for (let row of rows) { for (let row of rows) {
promises.push( const filters = buildFilters(generateIdForRow(row, table), {}, table)
makeExternalQuery(this.appId, { // safety check, if there are no filters on deletion bad things happen
endpoint: getEndpoint(tableId, DataSourceOperation.DELETE), if (Object.keys(filters).length !== 0) {
filters: buildFilters(generateIdForRow(row, table), {}, table), promises.push(
}) makeExternalQuery(this.appId, {
) endpoint: getEndpoint(tableId, DataSourceOperation.DELETE),
filters,
})
)
}
} }
} }
await Promise.all(promises) await Promise.all(promises)
@ -442,7 +455,7 @@ module External {
.filter( .filter(
column => column =>
column[1].type !== FieldTypes.LINK && column[1].type !== FieldTypes.LINK &&
!existing.find((field: string) => field.includes(column[0])) !existing.find((field: string) => field === column[0])
) )
.map(column => `${table.name}.${column[0]}`) .map(column => `${table.name}.${column[0]}`)
} }

View File

@ -3,7 +3,11 @@ exports.csv = function (headers, rows) {
for (let row of rows) { for (let row of rows) {
csv = `${csv}\n${headers csv = `${csv}\n${headers
.map(header => `"${row[header]}"`.trim()) .map(header => {
let val = row[header]
val = typeof val === "object" ? JSON.stringify(val) : val
return `"${val}"`.trim()
})
.join(",")}` .join(",")}`
} }
return csv return csv

View File

@ -82,7 +82,7 @@ describe("/datasources", () => {
entityId: "users", entityId: "users",
}, },
resource: { resource: {
fields: ["name", "age"], fields: ["users.name", "users.age"],
}, },
filters: { filters: {
string: { string: {
@ -94,7 +94,7 @@ describe("/datasources", () => {
.expect(200) .expect(200)
// this is mock data, can't test it // this is mock data, can't test it
expect(res.body).toBeDefined() expect(res.body).toBeDefined()
expect(pg.queryMock).toHaveBeenCalledWith(`select "name", "age" from "users" where "users"."name" like $1 limit $2`, ["John%", 5000]) expect(pg.queryMock).toHaveBeenCalledWith(`select "users"."name" as "users.name", "users"."age" as "users.age" from "users" where "users"."name" like $1 limit $2`, ["John%", 5000])
}) })
}) })

View File

@ -27,6 +27,7 @@ module.exports.definition = {
requestMethod: "POST", requestMethod: "POST",
url: "http://", url: "http://",
requestBody: "{}", requestBody: "{}",
headers: "{}",
}, },
schema: { schema: {
inputs: { inputs: {
@ -45,6 +46,11 @@ module.exports.definition = {
title: "JSON Body", title: "JSON Body",
customType: "wide", customType: "wide",
}, },
headers: {
type: "string",
title: "Headers",
customType: "wide",
},
}, },
required: ["requestMethod", "url"], required: ["requestMethod", "url"],
}, },
@ -65,7 +71,7 @@ module.exports.definition = {
} }
module.exports.run = async function ({ inputs }) { module.exports.run = async function ({ inputs }) {
let { requestMethod, url, requestBody } = inputs let { requestMethod, url, requestBody, headers } = inputs
if (!url.startsWith("http")) { if (!url.startsWith("http")) {
url = `http://${url}` url = `http://${url}`
} }
@ -84,6 +90,15 @@ module.exports.run = async function ({ inputs }) {
request.headers = { request.headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
} }
if (headers && headers.length !== 0) {
try {
const customHeaders = JSON.parse(headers)
request.headers = { ...request.headers, ...customHeaders }
} catch (err) {
console.error(err)
}
}
} }
try { try {

View File

@ -24,21 +24,7 @@ if (env.isTest()) {
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS) const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
// have to still have pouch alldbs for testing
allDbs(Pouch) allDbs(Pouch)
// replicate your local levelDB pouch to a running HTTP compliant couch or pouchdb server.
/* istanbul ignore next */
// eslint-disable-next-line no-unused-vars
function replicateLocal() {
Pouch.allDbs().then(dbs => {
for (let db of dbs) {
new Pouch(db).sync(
new PouchDB(`http://127.0.0.1:5984/${db}`, { live: true })
)
}
})
}
// replicateLocal()
module.exports = Pouch module.exports = Pouch

View File

@ -322,7 +322,7 @@ class LinkController {
// remove schema from other table // remove schema from other table
let linkedTable = await this._db.get(field.tableId) let linkedTable = await this._db.get(field.tableId)
delete linkedTable.schema[field.fieldName] delete linkedTable.schema[field.fieldName]
this._db.put(linkedTable) await this._db.put(linkedTable)
} }
/** /**

View File

@ -151,7 +151,9 @@ function buildRead(knex: Knex, json: QueryJson, limit: number): KnexQuery {
} }
// handle select // handle select
if (resource.fields && resource.fields.length > 0) { if (resource.fields && resource.fields.length > 0) {
query = query.select(resource.fields) // select the resources as the format "table.columnName" - this is what is provided
// by the resource builder further up
query = query.select(resource.fields.map(field => `${field} as ${field}`))
} else { } else {
query = query.select("*") query = query.select("*")
} }

View File

@ -31,8 +31,8 @@ const INTEGRATIONS = {
[SourceNames.MONGODB]: mongodb.integration, [SourceNames.MONGODB]: mongodb.integration,
[SourceNames.ELASTICSEARCH]: elasticsearch.integration, [SourceNames.ELASTICSEARCH]: elasticsearch.integration,
[SourceNames.COUCHDB]: couchdb.integration, [SourceNames.COUCHDB]: couchdb.integration,
[SourceNames.SQL_SERVER]: s3.integration, [SourceNames.SQL_SERVER]: sqlServer.integration,
[SourceNames.S3]: sqlServer.integration, [SourceNames.S3]: s3.integration,
[SourceNames.AIRTABLE]: airtable.integration, [SourceNames.AIRTABLE]: airtable.integration,
[SourceNames.MYSQL]: mysql.integration, [SourceNames.MYSQL]: mysql.integration,
[SourceNames.ARANGODB]: arangodb.integration, [SourceNames.ARANGODB]: arangodb.integration,

View File

@ -242,7 +242,7 @@ module MySQLModule {
const input = this._query(json, { disableReturning: true }) const input = this._query(json, { disableReturning: true })
let row let row
// need to manage returning, a feature mySQL can't do // need to manage returning, a feature mySQL can't do
if (operation === "awdawd") { if (operation === operation.DELETE) {
row = this.getReturningRow(json) row = this.getReturningRow(json)
} }
const results = await internalQuery(this.client, input, false) const results = await internalQuery(this.client, input, false)

View File

@ -62,12 +62,13 @@ describe("SQL query builder", () => {
}) })
it("should test a read with specific columns", () => { it("should test a read with specific columns", () => {
const nameProp = `${TABLE_NAME}.name`, ageProp = `${TABLE_NAME}.age`
const query = sql._query(generateReadJson({ const query = sql._query(generateReadJson({
fields: ["name", "age"] fields: [nameProp, ageProp]
})) }))
expect(query).toEqual({ expect(query).toEqual({
bindings: [limit], bindings: [limit],
sql: `select "name", "age" from "${TABLE_NAME}" limit $1` sql: `select "${TABLE_NAME}"."name" as "${nameProp}", "${TABLE_NAME}"."age" as "${ageProp}" from "${TABLE_NAME}" limit $1`
}) })
}) })

View File

@ -40,8 +40,13 @@ export function breakRowIdField(_id: string): any[] {
// have to replace on the way back as we swapped out the double quotes // have to replace on the way back as we swapped out the double quotes
// when encoding, but JSON can't handle the single quotes // when encoding, but JSON can't handle the single quotes
const decoded: string = decodeURIComponent(_id).replace(/'/g, '"') const decoded: string = decodeURIComponent(_id).replace(/'/g, '"')
const parsed = JSON.parse(decoded) try {
return Array.isArray(parsed) ? parsed : [parsed] const parsed = JSON.parse(decoded)
return Array.isArray(parsed) ? parsed : [parsed]
} catch (err) {
// wasn't json - likely was handlebars for a many to many
return [_id]
}
} }
export function convertType(type: string, map: { [key: string]: any }) { export function convertType(type: string, map: { [key: string]: any }) {

View File

@ -10,7 +10,7 @@ const CouchDB = require("../db")
module.exports = async (ctx, next) => { module.exports = async (ctx, next) => {
// try to get the appID from the request // try to get the appID from the request
const requestAppId = getAppId(ctx) let requestAppId = getAppId(ctx)
// get app cookie if it exists // get app cookie if it exists
let appCookie = null let appCookie = null
try { try {
@ -29,6 +29,8 @@ module.exports = async (ctx, next) => {
clearCookie(ctx, Cookies.CurrentApp) clearCookie(ctx, Cookies.CurrentApp)
return next() return next()
} }
// if the request app ID wasn't set, update it with the cookie
requestAppId = requestAppId || appId
} }
let appId, let appId,

View File

@ -1,5 +1,5 @@
const env = require("../environment") const env = require("../environment")
const { OBJ_STORE_DIRECTORY, ObjectStoreBuckets } = require("../constants") const { OBJ_STORE_DIRECTORY } = require("../constants")
const { sanitizeKey } = require("@budibase/auth/src/objectStore") const { sanitizeKey } = require("@budibase/auth/src/objectStore")
const BB_CDN = "https://cdn.app.budi.live/assets" const BB_CDN = "https://cdn.app.budi.live/assets"
@ -52,6 +52,6 @@ exports.clientLibraryPath = appId => {
exports.attachmentsRelativeURL = attachmentKey => { exports.attachmentsRelativeURL = attachmentKey => {
return exports.checkSlashesInUrl( return exports.checkSlashesInUrl(
`/${ObjectStoreBuckets.APPS}/${attachmentKey}` `${exports.objectStoreUrl()}/${attachmentKey}`
) )
} }

View File

@ -184,7 +184,13 @@ exports.inputProcessing = (user = {}, table, row) => {
} }
continue continue
} }
clonedRow[key] = exports.coerce(value, field.type) // specific case to delete formula values if they get saved
// type coercion cannot completely remove the field, so have to do it here
if (field.type === FieldTypes.FORMULA) {
delete clonedRow[key]
} else {
clonedRow[key] = exports.coerce(value, field.type)
}
} }
// handle auto columns - this returns an object like {table, row} // handle auto columns - this returns an object like {table, row}
return processAutoColumn(user, copiedTable, clonedRow) return processAutoColumn(user, copiedTable, clonedRow)

View File

@ -1146,11 +1146,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/auth@^0.9.79-alpha.4": "@budibase/auth@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.79.tgz#416271ffc55e84116550469656bf151a7734a90f" resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.102.tgz#86bb653686a311858b6ab6a048c6a4746bd5ced4"
integrity sha512-ENh099tYeUfVExsAeoxwMh2ODioKQGPteK9LJiU5hMdM4Oi7pyImu287BgKpTIheB+WtadT4e21VpPaJ62APEw== integrity sha512-Wov1vWAkWQn2P/gVapMBDdGKE1OwbpyD+3LV9E1HqZ3AASWZztqAFfnUaF6kKsHeem8S69uZ3vBU6uuyn9Sp+w==
dependencies: dependencies:
"@techpass/passport-openidconnect" "^0.3.0"
aws-sdk "^2.901.0" aws-sdk "^2.901.0"
bcryptjs "^2.4.3" bcryptjs "^2.4.3"
ioredis "^4.27.1" ioredis "^4.27.1"
@ -1167,10 +1168,10 @@
uuid "^8.3.2" uuid "^8.3.2"
zlib "^1.0.5" zlib "^1.0.5"
"@budibase/bbui@^0.9.79": "@budibase/bbui@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.79.tgz#c033ba0af41cb584d2657a8353f9887328f6633f" resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.102.tgz#e27a1763086651c6a9832a81b3695c10b0d52079"
integrity sha512-XxUJSPGd2FZDFdbNOeMUXohhID5h3DVq9XyKTe6WhYax4m2da/2WTENJ16UFvmfA+yxLN1qSDeweq9vw2zCahQ== integrity sha512-DKtfEoUdDm7aApfMHQi53TB18Qj4+c/CYWTyWP8T7+G/h4pCDdYEsjokn1MT2pbouPzECcjelw2w3k78Ac3N2Q==
dependencies: dependencies:
"@adobe/spectrum-css-workflow-icons" "^1.2.1" "@adobe/spectrum-css-workflow-icons" "^1.2.1"
"@spectrum-css/actionbutton" "^1.0.1" "@spectrum-css/actionbutton" "^1.0.1"
@ -1215,14 +1216,14 @@
svelte-flatpickr "^3.1.0" svelte-flatpickr "^3.1.0"
svelte-portal "^1.0.0" svelte-portal "^1.0.0"
"@budibase/client@^0.9.79-alpha.4": "@budibase/client@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.79.tgz#d1c8d51e9121f81902cfb31d3b685c8061f272a2" resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.102.tgz#4f1d5f84671182ecb65c1d09f691584dbd687fd3"
integrity sha512-//Yqm5Qki6BmBe5W2Tz8GONdkFjdD1jkIU7pcLYKqdZJWEQIrX6T/xNvYvZVhw7Dx5bwSZRjFwzm7jLoiyHBIA== integrity sha512-Uu7DzFOKlIKGF4IO24kS8ANiN5rf7i90KRqLfPDh1I8vdEj5L9sYQYyyI9YwUJ48keuoGfqHHlcH48dPJU+cxQ==
dependencies: dependencies:
"@budibase/bbui" "^0.9.79" "@budibase/bbui" "^0.9.102"
"@budibase/standard-components" "^0.9.79" "@budibase/standard-components" "^0.9.102"
"@budibase/string-templates" "^0.9.79" "@budibase/string-templates" "^0.9.102"
regexparam "^1.3.0" regexparam "^1.3.0"
shortid "^2.2.15" shortid "^2.2.15"
svelte-spa-router "^3.0.5" svelte-spa-router "^3.0.5"
@ -1255,24 +1256,26 @@
to-gfm-code-block "^0.1.1" to-gfm-code-block "^0.1.1"
year "^0.2.1" year "^0.2.1"
"@budibase/standard-components@^0.9.79", "@budibase/standard-components@^0.9.79-alpha.4": "@budibase/standard-components@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.79.tgz#24206642e0cdc655ea3a99ed5e9402ec4f6b3ba8" resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.102.tgz#4158eb5e2c46a403f2968cfa6a47751f402e776f"
integrity sha512-ZWhmBZ1iG+CjGMEvT/jtugMMgA1n88UYcOfP3BSP2P3eA16DubyU9hH9OyJHbGPzDHLoBF6vuS/5ZPZCkOKppw== integrity sha512-N8PcMzktBThMOb+LLBUdVi4WI2LxhEgWEXQr6tD0wKigxL734wWxRf2QWskFSJb/YvJoSP74jR9LF5P0zt1oTw==
dependencies: dependencies:
"@budibase/bbui" "^0.9.79" "@budibase/bbui" "^0.9.102"
"@spectrum-css/card" "^3.0.3"
"@spectrum-css/link" "^3.1.3" "@spectrum-css/link" "^3.1.3"
"@spectrum-css/page" "^3.0.1" "@spectrum-css/page" "^3.0.1"
"@spectrum-css/typography" "^3.0.2"
"@spectrum-css/vars" "^3.0.1" "@spectrum-css/vars" "^3.0.1"
apexcharts "^3.22.1" apexcharts "^3.22.1"
dayjs "^1.10.5" dayjs "^1.10.5"
svelte-apexcharts "^1.0.2" svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0" svelte-flatpickr "^3.1.0"
"@budibase/string-templates@^0.9.79", "@budibase/string-templates@^0.9.79-alpha.4": "@budibase/string-templates@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.79.tgz#bb75a7433a7cfda1fc488283f35e47879b799fcc" resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.102.tgz#5beb1dac696781b404020d5ab6bb91cbe4dcd10a"
integrity sha512-hkAne5mx7mj8+osXFt45VwgLKSa94uQOGOb4R8uv9WNzvk4RzcjBfRzJxggv29FUemItrAeZpSh+Um6yugFI+w== integrity sha512-cDDh5tyGYtA2sr8VDaRMLp9Ff+icXKNZ5BredePfES5du3GOWjFeVe0h1WFsR12Yq1dH1WWKR1XKc9CNwoQ8YA==
dependencies: dependencies:
"@budibase/handlebars-helpers" "^0.11.4" "@budibase/handlebars-helpers" "^0.11.4"
dayjs "^1.10.4" dayjs "^1.10.4"
@ -2111,6 +2114,11 @@
resolved "https://registry.yarnpkg.com/@spectrum-css/buttongroup/-/buttongroup-3.0.3.tgz#719d868845ac9d2c4f939c1b9f6044507902d5aa" resolved "https://registry.yarnpkg.com/@spectrum-css/buttongroup/-/buttongroup-3.0.3.tgz#719d868845ac9d2c4f939c1b9f6044507902d5aa"
integrity sha512-eXl8U4QWMWXqyTu654FdQdEGnmczgOYlpIFSHyCMVjhtPqZp2xwnLFiGh6LKw+bLio6eeOZ0L+vpk1GcoYqgkw== integrity sha512-eXl8U4QWMWXqyTu654FdQdEGnmczgOYlpIFSHyCMVjhtPqZp2xwnLFiGh6LKw+bLio6eeOZ0L+vpk1GcoYqgkw==
"@spectrum-css/card@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/card/-/card-3.0.3.tgz#56b2e2da6b80c1583228baa279de7407383bfb6b"
integrity sha512-+oKLUI2a0QmQP9EzySeq/G4FpUkkdaDNbuEbqCj2IkPMc/2v/nwzsPhh1fj2UIghGAiiUwXfPpzax1e8fyhQUg==
"@spectrum-css/checkbox@^3.0.2": "@spectrum-css/checkbox@^3.0.2":
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/checkbox/-/checkbox-3.0.3.tgz#8577067fc8b97e4609f92bd242364937a533a7bb" resolved "https://registry.yarnpkg.com/@spectrum-css/checkbox/-/checkbox-3.0.3.tgz#8577067fc8b97e4609f92bd242364937a533a7bb"
@ -2270,7 +2278,7 @@
resolved "https://registry.yarnpkg.com/@spectrum-css/treeview/-/treeview-3.0.3.tgz#aeda5175158b9f8d7529cb2b394428eb2a428046" resolved "https://registry.yarnpkg.com/@spectrum-css/treeview/-/treeview-3.0.3.tgz#aeda5175158b9f8d7529cb2b394428eb2a428046"
integrity sha512-D5gGzZC/KtRArdx86Mesc9+99W9nTbUOeyYGqoJoAfJSOttoT6Tk5CrDvlCmAqjKf5rajemAkGri1ChqvUIwkw== integrity sha512-D5gGzZC/KtRArdx86Mesc9+99W9nTbUOeyYGqoJoAfJSOttoT6Tk5CrDvlCmAqjKf5rajemAkGri1ChqvUIwkw==
"@spectrum-css/typography@^3.0.1": "@spectrum-css/typography@^3.0.1", "@spectrum-css/typography@^3.0.2":
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/typography/-/typography-3.0.2.tgz#ea3ca0a60e18064527819d48c8c4364cab4fcd38" resolved "https://registry.yarnpkg.com/@spectrum-css/typography/-/typography-3.0.2.tgz#ea3ca0a60e18064527819d48c8c4364cab4fcd38"
integrity sha512-5ZOLmQe0edzsDMyhghUd4hBb5uxGsFrxzf+WasfcUw9klSfTsRZ09n1BsaaWbgrLjlMQ+EEHS46v5VNo0Ms2CA== integrity sha512-5ZOLmQe0edzsDMyhghUd4hBb5uxGsFrxzf+WasfcUw9klSfTsRZ09n1BsaaWbgrLjlMQ+EEHS46v5VNo0Ms2CA==
@ -2292,6 +2300,17 @@
dependencies: dependencies:
defer-to-connect "^1.0.1" defer-to-connect "^1.0.1"
"@techpass/passport-openidconnect@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.0.tgz#a60b2bbf3f262649a5a02d5d186219944acc3010"
integrity sha512-bVsPwl66s7J7GHxTPlW/RJYhZol9SshNznQsx83OOh9G+JWFGoeWxh+xbX+FTdJNoUvGIGbJnpWPY2wC6NOHPw==
dependencies:
base64url "^3.0.1"
oauth "^0.9.15"
passport-strategy "^1.0.0"
request "^2.88.0"
webfinger "^0.4.2"
"@tootallnate/once@1": "@tootallnate/once@1":
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@ -3286,7 +3305,7 @@ base64-js@^1.0.2, base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
base64url@3.x.x: base64url@3.x.x, base64url@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
@ -8707,7 +8726,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
oauth@0.9.x: oauth@0.9.x, oauth@^0.9.15:
version "0.9.15" version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE= integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
@ -10081,7 +10100,7 @@ request-promise-native@^1.0.5:
stealthy-require "^1.1.1" stealthy-require "^1.1.1"
tough-cookie "^2.3.3" tough-cookie "^2.3.3"
"request@>= 2.52.0", request@^2.72.0, request@^2.74.0, request@^2.87.0: "request@>= 2.52.0", request@^2.72.0, request@^2.74.0, request@^2.87.0, request@^2.88.0:
version "2.88.2" version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@ -10205,7 +10224,7 @@ rimraf@2.6.3:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
rimraf@^3.0.0: rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
@ -10290,7 +10309,7 @@ sax@1.2.1:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"
integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o=
sax@>=0.6.0, sax@^1.2.4: sax@>=0.1.1, sax@>=0.6.0, sax@^1.2.4:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
@ -10745,6 +10764,11 @@ stealthy-require@^1.1.1:
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
step@0.0.x:
version "0.0.6"
resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2"
integrity sha1-FD54SaXX0/SgiP4pr5SRUhbu7eI=
strict-uri-encode@^1.0.0: strict-uri-encode@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
@ -11786,6 +11810,14 @@ walker@^1.0.7, walker@~1.0.5:
dependencies: dependencies:
makeerror "1.0.x" makeerror "1.0.x"
webfinger@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d"
integrity sha1-NHem2XeZRhiWA5/P/GULc0aO520=
dependencies:
step "0.0.x"
xml2js "0.1.x"
webidl-conversions@^4.0.2: webidl-conversions@^4.0.2:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@ -11992,6 +12024,13 @@ xml-parse-from-string@^1.0.0:
resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28"
integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= integrity sha1-qQKekp09vN7RafPG4oI42VpdWig=
xml2js@0.1.x:
version "0.1.14"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c"
integrity sha1-UnTmf1pkxfkpdM2FE54DMq3GuQw=
dependencies:
sax ">=0.1.1"
xml2js@0.4.19: xml2js@0.4.19:
version "0.4.19" version "0.4.19"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"

View File

@ -1888,7 +1888,6 @@
"booleanfield": { "booleanfield": {
"name": "Checkbox", "name": "Checkbox",
"icon": "Checkmark", "icon": "Checkmark",
"styles": ["size"],
"illegalChildren": ["section"], "illegalChildren": ["section"],
"settings": [ "settings": [
{ {
@ -1906,6 +1905,30 @@
"label": "Text", "label": "Text",
"key": "text" "key": "text"
}, },
{
"type": "select",
"label": "Size",
"key": "size",
"options": [
{
"label": "Small",
"value": "S"
},
{
"label": "Medium",
"value": "M"
},
{
"label": "Large",
"value": "L"
},
{
"label": "Extra large",
"value": "XL"
}
],
"defaultValue": "M"
},
{ {
"type": "boolean", "type": "boolean",
"label": "Disabled", "label": "Disabled",

View File

@ -29,11 +29,11 @@
"keywords": [ "keywords": [
"svelte" "svelte"
], ],
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"license": "MIT", "license": "MIT",
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc", "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
"dependencies": { "dependencies": {
"@budibase/bbui": "^0.9.99-alpha.4", "@budibase/bbui": "^0.9.105-alpha.3",
"@spectrum-css/card": "^3.0.3", "@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3", "@spectrum-css/divider": "^1.0.3",
"@spectrum-css/link": "^3.1.3", "@spectrum-css/link": "^3.1.3",

View File

@ -6,6 +6,7 @@
export let label export let label
export let text export let text
export let disabled = false export let disabled = false
export let size
export let validation export let validation
let fieldState let fieldState
@ -28,6 +29,7 @@
disabled={$fieldState.disabled} disabled={$fieldState.disabled}
error={$fieldState.error} error={$fieldState.error}
id={$fieldState.fieldId} id={$fieldState.fieldId}
{size}
on:change={e => fieldApi.setValue(e.detail)} on:change={e => fieldApi.setValue(e.detail)}
{text} {text}
/> />

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"description": "Handlebars wrapper for Budibase templating.", "description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs", "main": "src/index.cjs",
"module": "dist/bundle.mjs", "module": "dist/bundle.mjs",

View File

@ -126,6 +126,7 @@ module.exports.isValid = string => {
"object", "object",
"array", "array",
"cannot read property", "cannot read property",
"undefined",
] ]
// this is a portion of a specific string always output by handlebars in the case of a syntax error // this is a portion of a specific string always output by handlebars in the case of a syntax error
const invalidCases = [`expecting '`] const invalidCases = [`expecting '`]

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "0.9.99-alpha.4", "version": "0.9.105-alpha.3",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.js", "main": "src/index.js",
"repository": { "repository": {
@ -23,8 +23,8 @@
"author": "Budibase", "author": "Budibase",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@budibase/auth": "^0.9.99-alpha.4", "@budibase/auth": "^0.9.105-alpha.3",
"@budibase/string-templates": "^0.9.99-alpha.4", "@budibase/string-templates": "^0.9.105-alpha.3",
"@koa/router": "^8.0.0", "@koa/router": "^8.0.0",
"@techpass/passport-openidconnect": "^0.3.0", "@techpass/passport-openidconnect": "^0.3.0",
"aws-sdk": "^2.811.0", "aws-sdk": "^2.811.0",

View File

@ -4,14 +4,9 @@ const CouchDB = require("../../db")
const URL_REGEX_SLASH = /\/|\\/g const URL_REGEX_SLASH = /\/|\\/g
exports.getApps = async ctx => { exports.getApps = async ctx => {
const tenantId = ctx.user.tenantId const apps = await getAllApps(CouchDB, { dev: true })
const apps = await getAllApps(CouchDB, { tenantId })
const body = {} const body = {}
for (let app of apps) { for (let app of apps) {
if (app.status !== "fulfilled") {
continue
}
app = app.value app = app.value
let url = app.url || encodeURI(`${app.name}`) let url = app.url || encodeURI(`${app.name}`)
url = `/${url.replace(URL_REGEX_SLASH, "")}` url = `/${url.replace(URL_REGEX_SLASH, "")}`

View File

@ -223,7 +223,7 @@ exports.configChecklist = async function (ctx) {
// TODO: Watch get started video // TODO: Watch get started video
// Apps exist // Apps exist
const apps = await getAllApps(CouchDB) const apps = await getAllApps(CouchDB, { idsOnly: true })
// They have set up SMTP // They have set up SMTP
const smtpConfig = await getScopedFullConfig(db, { const smtpConfig = await getScopedFullConfig(db, {

View File

@ -30,7 +30,9 @@ function buildResetUpdateValidation() {
} }
function updateTenant(ctx, next) { function updateTenant(ctx, next) {
updateTenantId(ctx.params.tenantId) if (ctx.params) {
updateTenantId(ctx.params.tenantId)
}
return next() return next()
} }

View File

@ -19,6 +19,7 @@ if (env.isTest()) {
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS) const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
// have to still have pouch alldbs for testing
allDbs(Pouch) allDbs(Pouch)
module.exports = Pouch module.exports = Pouch

View File

@ -287,11 +287,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/auth@^0.9.79-alpha.4": "@budibase/auth@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.79.tgz#416271ffc55e84116550469656bf151a7734a90f" resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.102.tgz#86bb653686a311858b6ab6a048c6a4746bd5ced4"
integrity sha512-ENh099tYeUfVExsAeoxwMh2ODioKQGPteK9LJiU5hMdM4Oi7pyImu287BgKpTIheB+WtadT4e21VpPaJ62APEw== integrity sha512-Wov1vWAkWQn2P/gVapMBDdGKE1OwbpyD+3LV9E1HqZ3AASWZztqAFfnUaF6kKsHeem8S69uZ3vBU6uuyn9Sp+w==
dependencies: dependencies:
"@techpass/passport-openidconnect" "^0.3.0"
aws-sdk "^2.901.0" aws-sdk "^2.901.0"
bcryptjs "^2.4.3" bcryptjs "^2.4.3"
ioredis "^4.27.1" ioredis "^4.27.1"
@ -336,10 +337,10 @@
to-gfm-code-block "^0.1.1" to-gfm-code-block "^0.1.1"
year "^0.2.1" year "^0.2.1"
"@budibase/string-templates@^0.9.79-alpha.4": "@budibase/string-templates@^0.9.102":
version "0.9.79" version "0.9.102"
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.79.tgz#bb75a7433a7cfda1fc488283f35e47879b799fcc" resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.102.tgz#5beb1dac696781b404020d5ab6bb91cbe4dcd10a"
integrity sha512-hkAne5mx7mj8+osXFt45VwgLKSa94uQOGOb4R8uv9WNzvk4RzcjBfRzJxggv29FUemItrAeZpSh+Um6yugFI+w== integrity sha512-cDDh5tyGYtA2sr8VDaRMLp9Ff+icXKNZ5BredePfES5du3GOWjFeVe0h1WFsR12Yq1dH1WWKR1XKc9CNwoQ8YA==
dependencies: dependencies:
"@budibase/handlebars-helpers" "^0.11.4" "@budibase/handlebars-helpers" "^0.11.4"
dayjs "^1.10.4" dayjs "^1.10.4"