commit
da08ec73c8
|
@ -49,7 +49,7 @@ http {
|
||||||
add_header X-Frame-Options SAMEORIGIN always;
|
add_header X-Frame-Options SAMEORIGIN always;
|
||||||
add_header X-Content-Type-Options nosniff always;
|
add_header X-Content-Type-Options nosniff always;
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.budi.live https://js.intercomcdn.com https://widget.intercom.io; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com https://rsms.me https://maxcdn.bootstrapcdn.com; object-src 'none'; base-uri 'self'; connect-src 'self' https://api-iam.intercom.io https://app.posthog.com wss://nexus-websocket-a.intercom.io; font-src 'self' data https://cdn.jsdelivr.net https://fonts.gstatic.com https://rsms.me https://maxcdn.bootstrapcdn.com; frame-src 'self' https:; img-src http: https: data; manifest-src 'self'; media-src 'self'; worker-src 'none';" always;
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.budi.live https://js.intercomcdn.com https://widget.intercom.io; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com https://rsms.me https://maxcdn.bootstrapcdn.com; object-src 'none'; base-uri 'self'; connect-src 'self' https://api-iam.intercom.io https://app.posthog.com wss://nexus-websocket-a.intercom.io ; font-src 'self' data https://cdn.jsdelivr.net https://fonts.gstatic.com https://rsms.me https://maxcdn.bootstrapcdn.com; frame-src 'self' https:; img-src http: https: data; manifest-src 'self'; media-src 'self'; worker-src 'none';" always;
|
||||||
|
|
||||||
# upstreams
|
# upstreams
|
||||||
set $apps {{ apps }};
|
set $apps {{ apps }};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
|
|
|
@ -22,3 +22,18 @@ exports.getAccount = async email => {
|
||||||
|
|
||||||
return json[0]
|
return json[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getStatus = async () => {
|
||||||
|
const response = await api.get(`/api/status`, {
|
||||||
|
headers: {
|
||||||
|
[Headers.API_KEY]: env.ACCOUNT_PORTAL_API_KEY,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const json = await response.json()
|
||||||
|
|
||||||
|
if (response.status !== 200) {
|
||||||
|
throw new Error(`Error getting status`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
|
@ -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": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
||||||
"@budibase/string-templates": "^1.0.80-alpha.5",
|
"@budibase/string-templates": "^1.0.81-alpha.6",
|
||||||
"@spectrum-css/actionbutton": "^1.0.1",
|
"@spectrum-css/actionbutton": "^1.0.1",
|
||||||
"@spectrum-css/actiongroup": "^1.0.1",
|
"@spectrum-css/actiongroup": "^1.0.1",
|
||||||
"@spectrum-css/avatar": "^3.0.2",
|
"@spectrum-css/avatar": "^3.0.2",
|
||||||
|
|
|
@ -57,3 +57,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.spectrum-Toast {
|
||||||
|
pointer-events: all;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<script>
|
||||||
|
import "@spectrum-css/toast/dist/index-vars.css"
|
||||||
|
import Portal from "svelte-portal"
|
||||||
|
import { banner } from "../Stores/banner"
|
||||||
|
import Banner from "./Banner.svelte"
|
||||||
|
import { fly } from "svelte/transition"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Portal target=".banner-container">
|
||||||
|
<div class="banner">
|
||||||
|
{#if $banner.message}
|
||||||
|
<div transition:fly={{ y: -30 }}>
|
||||||
|
<Banner
|
||||||
|
type={$banner.type}
|
||||||
|
extraButtonText={$banner.extraButtonText}
|
||||||
|
extraButtonAction={$banner.extraButtonAction}
|
||||||
|
on:change={$banner.onChange}
|
||||||
|
>
|
||||||
|
{$banner.message}
|
||||||
|
</Banner>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</Portal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.banner {
|
||||||
|
pointer-events: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
|
export function createBannerStore() {
|
||||||
|
const DEFAULT_CONFIG = {}
|
||||||
|
|
||||||
|
const banner = writable(DEFAULT_CONFIG)
|
||||||
|
|
||||||
|
const show = async (
|
||||||
|
// eslint-disable-next-line
|
||||||
|
config = { message, type, extraButtonText, extraButtonAction, onChange }
|
||||||
|
) => {
|
||||||
|
banner.update(store => {
|
||||||
|
return {
|
||||||
|
...store,
|
||||||
|
...config,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const showStatus = async () => {
|
||||||
|
const config = {
|
||||||
|
message: "Some systems are experiencing issues",
|
||||||
|
type: "negative",
|
||||||
|
extraButtonText: "View Status",
|
||||||
|
extraButtonAction: () => window.open("https://status.budibase.com/"),
|
||||||
|
}
|
||||||
|
|
||||||
|
await show(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe: banner.subscribe,
|
||||||
|
showStatus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const banner = createBannerStore()
|
|
@ -60,6 +60,7 @@ export { default as StatusLight } from "./StatusLight/StatusLight.svelte"
|
||||||
export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
|
export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
|
||||||
export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte"
|
export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte"
|
||||||
export { default as Banner } from "./Banner/Banner.svelte"
|
export { default as Banner } from "./Banner/Banner.svelte"
|
||||||
|
export { default as BannerDisplay } from "./Banner/BannerDisplay.svelte"
|
||||||
export { default as MarkdownEditor } from "./Markdown/MarkdownEditor.svelte"
|
export { default as MarkdownEditor } from "./Markdown/MarkdownEditor.svelte"
|
||||||
export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte"
|
export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte"
|
||||||
export { default as RichTextField } from "./Form/RichTextField.svelte"
|
export { default as RichTextField } from "./Form/RichTextField.svelte"
|
||||||
|
@ -84,6 +85,7 @@ export { default as clickOutside } from "./Actions/click_outside"
|
||||||
|
|
||||||
// Stores
|
// Stores
|
||||||
export { notifications, createNotificationStore } from "./Stores/notifications"
|
export { notifications, createNotificationStore } from "./Stores/notifications"
|
||||||
|
export { banner } from "./Stores/banner"
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
export * as Helpers from "./helpers"
|
export * as Helpers from "./helpers"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.80-alpha.5",
|
"@budibase/bbui": "^1.0.81-alpha.6",
|
||||||
"@budibase/client": "^1.0.80-alpha.5",
|
"@budibase/client": "^1.0.81-alpha.6",
|
||||||
"@budibase/frontend-core": "^1.0.80-alpha.5",
|
"@budibase/frontend-core": "^1.0.81-alpha.6",
|
||||||
"@budibase/string-templates": "^1.0.80-alpha.5",
|
"@budibase/string-templates": "^1.0.81-alpha.6",
|
||||||
"@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",
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { Router } from "@roxi/routify"
|
import { Router } from "@roxi/routify"
|
||||||
import { routes } from "../.routify/routes"
|
import { routes } from "../.routify/routes"
|
||||||
import { NotificationDisplay } from "@budibase/bbui"
|
import { NotificationDisplay, BannerDisplay } from "@budibase/bbui"
|
||||||
import { parse, stringify } from "qs"
|
import { parse, stringify } from "qs"
|
||||||
import HelpIcon from "components/common/HelpIcon.svelte"
|
import HelpIcon from "components/common/HelpIcon.svelte"
|
||||||
|
|
||||||
const queryHandler = { parse, stringify }
|
const queryHandler = { parse, stringify }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div class="banner-container" />
|
||||||
|
<BannerDisplay />
|
||||||
|
|
||||||
<NotificationDisplay />
|
<NotificationDisplay />
|
||||||
<Router {routes} config={{ queryHandler }} />
|
<Router {routes} config={{ queryHandler }} />
|
||||||
<div class="modal-container" />
|
<div class="modal-container" />
|
||||||
|
|
|
@ -331,7 +331,9 @@ const getSelectedRowsBindings = asset => {
|
||||||
bindings = bindings.concat(
|
bindings = bindings.concat(
|
||||||
tables.map(table => ({
|
tables.map(table => ({
|
||||||
type: "context",
|
type: "context",
|
||||||
runtimeBinding: `${safeState}.${makePropSafe(table._id)}`,
|
runtimeBinding: `${safeState}.${makePropSafe(table._id)}.${makePropSafe(
|
||||||
|
"selectedRows"
|
||||||
|
)}`,
|
||||||
readableBinding: `${table._instanceName}.Selected rows`,
|
readableBinding: `${table._instanceName}.Selected rows`,
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
@ -343,7 +345,9 @@ const getSelectedRowsBindings = asset => {
|
||||||
bindings = bindings.concat(
|
bindings = bindings.concat(
|
||||||
tableBlocks.map(block => ({
|
tableBlocks.map(block => ({
|
||||||
type: "context",
|
type: "context",
|
||||||
runtimeBinding: `${safeState}.${makePropSafe(block._id + "-table")}`,
|
runtimeBinding: `${safeState}.${makePropSafe(
|
||||||
|
block._id + "-table"
|
||||||
|
)}.${makePropSafe("selectedRows")}`,
|
||||||
readableBinding: `${block._instanceName}.Selected rows`,
|
readableBinding: `${block._instanceName}.Selected rows`,
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
|
@ -134,8 +134,9 @@
|
||||||
|
|
||||||
// Remove all iframe event listeners on component destroy
|
// Remove all iframe event listeners on component destroy
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
window.removeEventListener("message", receiveMessage)
|
||||||
|
|
||||||
if (iframe.contentWindow) {
|
if (iframe.contentWindow) {
|
||||||
window.removeEventListener("message", receiveMessage)
|
|
||||||
if (!$store.clientFeatures.messagePassing) {
|
if (!$store.clientFeatures.messagePassing) {
|
||||||
// Legacy - remove in later versions of BB
|
// Legacy - remove in later versions of BB
|
||||||
iframe.contentWindow.removeEventListener(
|
iframe.contentWindow.removeEventListener(
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<script>
|
||||||
|
import { Label, Select, Body } from "@budibase/bbui"
|
||||||
|
import { findAllMatchingComponents } from "builderStore/componentUtils"
|
||||||
|
import { currentAsset } from "builderStore"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
export let parameters
|
||||||
|
|
||||||
|
$: tables = findAllMatchingComponents($currentAsset?.props, component =>
|
||||||
|
component._component.endsWith("table")
|
||||||
|
).map(table => ({
|
||||||
|
label: table._instanceName,
|
||||||
|
value: table._id,
|
||||||
|
}))
|
||||||
|
|
||||||
|
$: tableBlocks = findAllMatchingComponents($currentAsset?.props, component =>
|
||||||
|
component._component.endsWith("tableblock")
|
||||||
|
).map(block => ({
|
||||||
|
label: block._instanceName,
|
||||||
|
value: `${block._id}-table`,
|
||||||
|
}))
|
||||||
|
|
||||||
|
$: componentOptions = tables.concat(tableBlocks)
|
||||||
|
|
||||||
|
const FORMATS = [
|
||||||
|
{
|
||||||
|
label: "CSV",
|
||||||
|
value: "csv",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "JSON",
|
||||||
|
value: "json",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (!parameters.type) {
|
||||||
|
parameters.type = "csv"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<Body size="S">
|
||||||
|
Choose the table component that you would like to export your row selection
|
||||||
|
from.
|
||||||
|
<br />
|
||||||
|
Please ensure you have enabled row selection in the table settings.
|
||||||
|
</Body>
|
||||||
|
|
||||||
|
<div class="params">
|
||||||
|
<Label small>Table</Label>
|
||||||
|
<Select
|
||||||
|
bind:value={parameters.tableComponentId}
|
||||||
|
options={componentOptions}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label small>Export as</Label>
|
||||||
|
<Select bind:value={parameters.type} options={FORMATS} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(p) {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params {
|
||||||
|
display: grid;
|
||||||
|
column-gap: var(--spacing-xs);
|
||||||
|
row-gap: var(--spacing-s);
|
||||||
|
grid-template-columns: 70px 1fr;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -12,3 +12,4 @@ export { default as UpdateState } from "./UpdateState.svelte"
|
||||||
export { default as RefreshDataProvider } from "./RefreshDataProvider.svelte"
|
export { default as RefreshDataProvider } from "./RefreshDataProvider.svelte"
|
||||||
export { default as DuplicateRow } from "./DuplicateRow.svelte"
|
export { default as DuplicateRow } from "./DuplicateRow.svelte"
|
||||||
export { default as S3Upload } from "./S3Upload.svelte"
|
export { default as S3Upload } from "./S3Upload.svelte"
|
||||||
|
export { default as ExportData } from "./ExportData.svelte"
|
||||||
|
|
|
@ -80,6 +80,10 @@
|
||||||
"value": "publicUrl"
|
"value": "publicUrl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Export Data",
|
||||||
|
"component": "ExportData"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -14,6 +14,7 @@ export function createTablesStore() {
|
||||||
...state,
|
...state,
|
||||||
list: tables,
|
list: tables,
|
||||||
}))
|
}))
|
||||||
|
return tables
|
||||||
}
|
}
|
||||||
|
|
||||||
async function select(table) {
|
async function select(table) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { writable, get } from "svelte/store"
|
import { writable, get } from "svelte/store"
|
||||||
import { API } from "api"
|
import { API } from "api"
|
||||||
import { auth } from "stores/portal"
|
import { auth } from "stores/portal"
|
||||||
|
import { banner } from "@budibase/bbui"
|
||||||
|
|
||||||
export function createAdminStore() {
|
export function createAdminStore() {
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG = {
|
||||||
|
@ -30,6 +31,13 @@ export function createAdminStore() {
|
||||||
x => x?.checked
|
x => x?.checked
|
||||||
).length
|
).length
|
||||||
await getEnvironment()
|
await getEnvironment()
|
||||||
|
|
||||||
|
// enable system status checks in the cloud
|
||||||
|
if (get(admin).cloud) {
|
||||||
|
await getSystemStatus()
|
||||||
|
checkStatus()
|
||||||
|
}
|
||||||
|
|
||||||
admin.update(store => {
|
admin.update(store => {
|
||||||
store.loaded = true
|
store.loaded = true
|
||||||
store.checklist = checklist
|
store.checklist = checklist
|
||||||
|
@ -58,6 +66,21 @@ export function createAdminStore() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkStatus = async () => {
|
||||||
|
const health = get(admin)?.status?.health
|
||||||
|
if (!health?.passing) {
|
||||||
|
await banner.showStatus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getSystemStatus() {
|
||||||
|
const status = await API.getSystemStatus()
|
||||||
|
admin.update(store => {
|
||||||
|
store.status = status
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function unload() {
|
function unload() {
|
||||||
admin.update(store => {
|
admin.update(store => {
|
||||||
store.loaded = false
|
store.loaded = false
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"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": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"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",
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.80-alpha.5",
|
"@budibase/bbui": "^1.0.81-alpha.6",
|
||||||
"@budibase/frontend-core": "^1.0.80-alpha.5",
|
"@budibase/frontend-core": "^1.0.81-alpha.6",
|
||||||
"@budibase/string-templates": "^1.0.80-alpha.5",
|
"@budibase/string-templates": "^1.0.81-alpha.6",
|
||||||
"@spectrum-css/button": "^3.0.3",
|
"@spectrum-css/button": "^3.0.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",
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
"@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",
|
||||||
|
"downloadjs": "1.4.7",
|
||||||
"regexparam": "^1.3.0",
|
"regexparam": "^1.3.0",
|
||||||
"rollup-plugin-polyfill-node": "^0.8.0",
|
"rollup-plugin-polyfill-node": "^0.8.0",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
|
|
|
@ -81,7 +81,10 @@
|
||||||
loading = false
|
loading = false
|
||||||
return res
|
return res
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notificationStore.actions.error(`Error uploading file: ${error}`)
|
notificationStore.actions.error(
|
||||||
|
`Error uploading file: ${error?.message || error}`
|
||||||
|
)
|
||||||
|
loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
$: {
|
$: {
|
||||||
rowSelectionStore.actions.updateSelection(
|
rowSelectionStore.actions.updateSelection(
|
||||||
$component.id,
|
$component.id,
|
||||||
|
selectedRows.length ? selectedRows[0].tableId : "",
|
||||||
selectedRows.map(row => row._id)
|
selectedRows.map(row => row._id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,29 @@
|
||||||
import { writable } from "svelte/store"
|
import { get, writable } from "svelte/store"
|
||||||
|
|
||||||
const createRowSelectionStore = () => {
|
const createRowSelectionStore = () => {
|
||||||
const store = writable({})
|
const store = writable({})
|
||||||
|
|
||||||
function updateSelection(componentId, selectedRows) {
|
function updateSelection(componentId, tableId, selectedRows) {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state[componentId] = [...selectedRows]
|
state[componentId] = { tableId: tableId, selectedRows: selectedRows }
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSelection(tableComponentId) {
|
||||||
|
const selection = get(store)
|
||||||
|
const componentId = Object.keys(selection).find(
|
||||||
|
componentId => componentId === tableComponentId
|
||||||
|
)
|
||||||
|
return selection[componentId] || {}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe: store.subscribe,
|
subscribe: store.subscribe,
|
||||||
set: store.set,
|
set: store.set,
|
||||||
actions: {
|
actions: {
|
||||||
updateSelection,
|
updateSelection,
|
||||||
|
getSelection,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
|
import download from "downloadjs"
|
||||||
import {
|
import {
|
||||||
routeStore,
|
routeStore,
|
||||||
builderStore,
|
builderStore,
|
||||||
|
@ -8,6 +9,7 @@ import {
|
||||||
notificationStore,
|
notificationStore,
|
||||||
dataSourceStore,
|
dataSourceStore,
|
||||||
uploadStore,
|
uploadStore,
|
||||||
|
rowSelectionStore,
|
||||||
} from "stores"
|
} from "stores"
|
||||||
import { API } from "api"
|
import { API } from "api"
|
||||||
import { ActionTypes } from "constants"
|
import { ActionTypes } from "constants"
|
||||||
|
@ -239,6 +241,26 @@ const s3UploadHandler = async action => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const exportDataHandler = async action => {
|
||||||
|
let selection = rowSelectionStore.actions.getSelection(
|
||||||
|
action.parameters.tableComponentId
|
||||||
|
)
|
||||||
|
if (selection.selectedRows && selection.selectedRows.length > 0) {
|
||||||
|
try {
|
||||||
|
const data = await API.exportRows({
|
||||||
|
tableId: selection.tableId,
|
||||||
|
rows: selection.selectedRows,
|
||||||
|
})
|
||||||
|
|
||||||
|
download(JSON.stringify(data), `export.${action.parameters.type}`)
|
||||||
|
} catch (error) {
|
||||||
|
notificationStore.actions.error("There was an error exporting the data")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notificationStore.actions.error("Please select at least one row")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handlerMap = {
|
const handlerMap = {
|
||||||
["Save Row"]: saveRowHandler,
|
["Save Row"]: saveRowHandler,
|
||||||
["Duplicate Row"]: duplicateRowHandler,
|
["Duplicate Row"]: duplicateRowHandler,
|
||||||
|
@ -254,6 +276,7 @@ const handlerMap = {
|
||||||
["Change Form Step"]: changeFormStepHandler,
|
["Change Form Step"]: changeFormStepHandler,
|
||||||
["Update State"]: updateStateHandler,
|
["Update State"]: updateStateHandler,
|
||||||
["Upload File to S3"]: s3UploadHandler,
|
["Upload File to S3"]: s3UploadHandler,
|
||||||
|
["Export Data"]: exportDataHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmTextMap = {
|
const confirmTextMap = {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"description": "Budibase frontend core libraries used in builder and client",
|
"description": "Budibase frontend core libraries used in builder and client",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.80-alpha.5",
|
"@budibase/bbui": "^1.0.81-alpha.6",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,66 @@
|
||||||
export const buildAttachmentEndpoints = API => ({
|
export const buildAttachmentEndpoints = API => {
|
||||||
/**
|
|
||||||
* Uploads an attachment to the server.
|
|
||||||
* @param data the attachment to upload
|
|
||||||
* @param tableId the table ID to upload to
|
|
||||||
*/
|
|
||||||
uploadAttachment: async ({ data, tableId }) => {
|
|
||||||
return await API.post({
|
|
||||||
url: `/api/attachments/${tableId}/upload`,
|
|
||||||
body: data,
|
|
||||||
json: false,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads an attachment to the server as a builder user from the builder.
|
|
||||||
* @param data the data to upload
|
|
||||||
*/
|
|
||||||
uploadBuilderAttachment: async data => {
|
|
||||||
return await API.post({
|
|
||||||
url: "/api/attachments/process",
|
|
||||||
body: data,
|
|
||||||
json: false,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a signed URL to upload a file to an external datasource.
|
* Generates a signed URL to upload a file to an external datasource.
|
||||||
* @param datasourceId the ID of the datasource to upload to
|
* @param datasourceId the ID of the datasource to upload to
|
||||||
* @param bucket the name of the bucket to upload to
|
* @param bucket the name of the bucket to upload to
|
||||||
* @param key the name of the file to upload to
|
* @param key the name of the file to upload to
|
||||||
*/
|
*/
|
||||||
getSignedDatasourceURL: async ({ datasourceId, bucket, key }) => {
|
const getSignedDatasourceURL = async ({ datasourceId, bucket, key }) => {
|
||||||
return await API.post({
|
return await API.post({
|
||||||
url: `/api/attachments/${datasourceId}/url`,
|
url: `/api/attachments/${datasourceId}/url`,
|
||||||
body: { bucket, key },
|
body: { bucket, key },
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
return {
|
||||||
* Uploads a file to an external datasource.
|
getSignedDatasourceURL,
|
||||||
* @param datasourceId the ID of the datasource to upload to
|
|
||||||
* @param bucket the name of the bucket to upload to
|
/**
|
||||||
* @param key the name of the file to upload to
|
* Uploads an attachment to the server.
|
||||||
* @param data the file to upload
|
* @param data the attachment to upload
|
||||||
*/
|
* @param tableId the table ID to upload to
|
||||||
externalUpload: async ({ datasourceId, bucket, key, data }) => {
|
*/
|
||||||
const { signedUrl, publicUrl } = await API.getSignedDatasourceURL({
|
uploadAttachment: async ({ data, tableId }) => {
|
||||||
datasourceId,
|
return await API.post({
|
||||||
bucket,
|
url: `/api/attachments/${tableId}/upload`,
|
||||||
key,
|
body: data,
|
||||||
})
|
json: false,
|
||||||
await API.put({
|
})
|
||||||
url: signedUrl,
|
},
|
||||||
body: data,
|
|
||||||
json: false,
|
/**
|
||||||
external: true,
|
* Uploads an attachment to the server as a builder user from the builder.
|
||||||
})
|
* @param data the data to upload
|
||||||
return { publicUrl }
|
*/
|
||||||
},
|
uploadBuilderAttachment: async data => {
|
||||||
})
|
return await API.post({
|
||||||
|
url: "/api/attachments/process",
|
||||||
|
body: data,
|
||||||
|
json: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads a file to an external datasource.
|
||||||
|
* @param datasourceId the ID of the datasource to upload to
|
||||||
|
* @param bucket the name of the bucket to upload to
|
||||||
|
* @param key the name of the file to upload to
|
||||||
|
* @param data the file to upload
|
||||||
|
*/
|
||||||
|
externalUpload: async ({ datasourceId, bucket, key, data }) => {
|
||||||
|
console.log(API)
|
||||||
|
const { signedUrl, publicUrl } = await getSignedDatasourceURL({
|
||||||
|
datasourceId,
|
||||||
|
bucket,
|
||||||
|
key,
|
||||||
|
})
|
||||||
|
await API.put({
|
||||||
|
url: signedUrl,
|
||||||
|
body: data,
|
||||||
|
json: false,
|
||||||
|
external: true,
|
||||||
|
})
|
||||||
|
return { publicUrl }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,15 @@ export const buildOtherEndpoints = API => ({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current system status.
|
||||||
|
*/
|
||||||
|
getSystemStatus: async () => {
|
||||||
|
return await API.get({
|
||||||
|
url: "/api/system/status",
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the list of available integrations.
|
* Gets the list of available integrations.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,4 +60,18 @@ export const buildRowEndpoints = API => ({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports rows.
|
||||||
|
* @param tableId the table ID to export the rows from
|
||||||
|
* @param rows the array of rows to export
|
||||||
|
*/
|
||||||
|
exportRows: async ({ tableId, rows }) => {
|
||||||
|
return await API.post({
|
||||||
|
url: `/api/${tableId}/rows/exportRows`,
|
||||||
|
body: {
|
||||||
|
rows,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -71,9 +71,9 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "^10.0.3",
|
"@apidevtools/swagger-parser": "^10.0.3",
|
||||||
"@budibase/backend-core": "^1.0.80-alpha.5",
|
"@budibase/backend-core": "^1.0.81-alpha.6",
|
||||||
"@budibase/client": "^1.0.80-alpha.5",
|
"@budibase/client": "^1.0.81-alpha.6",
|
||||||
"@budibase/string-templates": "^1.0.80-alpha.5",
|
"@budibase/string-templates": "^1.0.81-alpha.6",
|
||||||
"@bull-board/api": "^3.7.0",
|
"@bull-board/api": "^3.7.0",
|
||||||
"@bull-board/koa": "^3.7.0",
|
"@bull-board/koa": "^3.7.0",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
|
|
@ -503,6 +503,71 @@
|
||||||
"data"
|
"data"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"applicationSearch": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "The name of the app.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"description": "The URL by which the app is accessed, this must be URL encoded.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"_id": {
|
||||||
|
"description": "The ID of the app.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "The status of the app, stating it if is the development or published version.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"development",
|
||||||
|
"published"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"description": "States when the app was created, will be constant. Stored in ISO format.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"description": "States the last time the app was updated - stored in ISO format.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"description": "States the version of the Budibase client this app is currently based on.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tenantId": {
|
||||||
|
"description": "In a multi-tenant environment this will state the tenant this app is within.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lockedBy": {
|
||||||
|
"description": "The user this app is currently being built by.",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"_id",
|
||||||
|
"name",
|
||||||
|
"url",
|
||||||
|
"status",
|
||||||
|
"createdAt",
|
||||||
|
"updatedAt",
|
||||||
|
"version"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data"
|
||||||
|
]
|
||||||
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"description": "The row to be created/updated, based on the table schema.",
|
"description": "The row to be created/updated, based on the table schema.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -980,6 +1045,221 @@
|
||||||
"data"
|
"data"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"tableSearch": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"description": "The table to be created/updated.",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"schema",
|
||||||
|
"_id"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "The name of the table.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"primaryDisplay": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the column which should be used in relationship tags when relating to this table."
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"link"
|
||||||
|
],
|
||||||
|
"description": "A relationship column."
|
||||||
|
},
|
||||||
|
"constraints": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "A constraint can be applied to the column which will be validated against when a row is saved.",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"object",
|
||||||
|
"boolean"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"presence": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defines whether the column is required or not."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the column."
|
||||||
|
},
|
||||||
|
"autocolumn": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defines whether the column is automatically generated."
|
||||||
|
},
|
||||||
|
"fieldName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the column which a relationship column is related to in another table."
|
||||||
|
},
|
||||||
|
"tableId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The ID of the table which a relationship column is related to."
|
||||||
|
},
|
||||||
|
"relationshipType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"one-to-many",
|
||||||
|
"many-to-one",
|
||||||
|
"many-to-many"
|
||||||
|
],
|
||||||
|
"description": "Defines the type of relationship that this column will be used for."
|
||||||
|
},
|
||||||
|
"through": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "When using a SQL table that contains many to many relationships this defines the table the relationships are linked through."
|
||||||
|
},
|
||||||
|
"foreignKey": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "When using a SQL table that contains a one to many relationship this defines the foreign key."
|
||||||
|
},
|
||||||
|
"throughFrom": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "When using a SQL table that utilises a through table, this defines the primary key in the through table for this table."
|
||||||
|
},
|
||||||
|
"throughTo": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"formula"
|
||||||
|
],
|
||||||
|
"description": "A formula column."
|
||||||
|
},
|
||||||
|
"constraints": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "A constraint can be applied to the column which will be validated against when a row is saved.",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"object",
|
||||||
|
"boolean"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"presence": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defines whether the column is required or not."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the column."
|
||||||
|
},
|
||||||
|
"autocolumn": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defines whether the column is automatically generated."
|
||||||
|
},
|
||||||
|
"formula": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format."
|
||||||
|
},
|
||||||
|
"formulaType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"static",
|
||||||
|
"dynamic"
|
||||||
|
],
|
||||||
|
"description": "Defines whether this is a static or dynamic formula."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"string",
|
||||||
|
"longform",
|
||||||
|
"options",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"array",
|
||||||
|
"datetime",
|
||||||
|
"attachment",
|
||||||
|
"link",
|
||||||
|
"formula",
|
||||||
|
"auto",
|
||||||
|
"json",
|
||||||
|
"internal"
|
||||||
|
],
|
||||||
|
"description": "Defines the type of the column, most explain themselves, a link column is a relationship."
|
||||||
|
},
|
||||||
|
"constraints": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "A constraint can be applied to the column which will be validated against when a row is saved.",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"object",
|
||||||
|
"boolean"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"presence": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defines whether the column is required or not."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the column."
|
||||||
|
},
|
||||||
|
"autocolumn": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defines whether the column is automatically generated."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_id": {
|
||||||
|
"description": "The ID of the table.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data"
|
||||||
|
]
|
||||||
|
},
|
||||||
"executeQuery": {
|
"executeQuery": {
|
||||||
"description": "The query body must contain the required parameters for the query, this depends on query type, setup and bindings.",
|
"description": "The query body must contain the required parameters for the query, this depends on query type, setup and bindings.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -1074,6 +1354,71 @@
|
||||||
"_id"
|
"_id"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"querySearch": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"_id": {
|
||||||
|
"description": "The ID of the query.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"datasourceId": {
|
||||||
|
"description": "The ID of the data source the query belongs to.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"description": "The bindings which are required to perform this query.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"description": "The fields that are used to perform this query, e.g. the sql statement",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"queryVerb": {
|
||||||
|
"description": "The verb that describes this query.",
|
||||||
|
"enum": [
|
||||||
|
"create",
|
||||||
|
"read",
|
||||||
|
"update",
|
||||||
|
"delete"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "The name of the query.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"description": "The schema of the data returned when the query is executed.",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"transformer": {
|
||||||
|
"description": "The JavaScript transformer function, applied after the query responds with data.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"readable": {
|
||||||
|
"description": "Whether the query has readable data.",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"schema",
|
||||||
|
"_id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data"
|
||||||
|
]
|
||||||
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -1215,6 +1560,86 @@
|
||||||
"data"
|
"data"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"userSearch": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"email": {
|
||||||
|
"description": "The email address of the user, this must be unique.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"description": "The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"description": "The status of the user, if they are active.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"active"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"firstName": {
|
||||||
|
"description": "The first name of the user",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"description": "The last name of the user",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"forceResetPassword": {
|
||||||
|
"description": "If set to true forces the user to reset their password on first login.",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"builder": {
|
||||||
|
"description": "Describes if the user is a builder user or not.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"global": {
|
||||||
|
"description": "If set to true the user will be able to build any app in the system.",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"description": "Describes if the user is an admin user or not.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"global": {
|
||||||
|
"description": "If set to true the user will be able to administrate the system.",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"description": "Contains the roles of the user per app (assuming they are not a builder user).",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_id": {
|
||||||
|
"description": "The ID of the user.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"email",
|
||||||
|
"roles",
|
||||||
|
"_id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"data"
|
||||||
|
]
|
||||||
|
},
|
||||||
"nameSearch": {
|
"nameSearch": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -1399,18 +1824,7 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"$ref": "#/components/schemas/applicationSearch"
|
||||||
"required": [
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"data": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/application"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"applications": {
|
"applications": {
|
||||||
|
@ -1498,18 +1912,7 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"$ref": "#/components/schemas/querySearch"
|
||||||
"required": [
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"data": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/query"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"queries": {
|
"queries": {
|
||||||
|
@ -2025,18 +2428,7 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"$ref": "#/components/schemas/tableSearch"
|
||||||
"required": [
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"data": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/table"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"tables": {
|
"tables": {
|
||||||
|
@ -2203,18 +2595,7 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"$ref": "#/components/schemas/userSearch"
|
||||||
"required": [
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"data": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/user"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"users": {
|
"users": {
|
||||||
|
|
|
@ -360,6 +360,58 @@ components:
|
||||||
- version
|
- version
|
||||||
required:
|
required:
|
||||||
- data
|
- data
|
||||||
|
applicationSearch:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: The name of the app.
|
||||||
|
type: string
|
||||||
|
url:
|
||||||
|
description: The URL by which the app is accessed, this must be URL encoded.
|
||||||
|
type: string
|
||||||
|
_id:
|
||||||
|
description: The ID of the app.
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: The status of the app, stating it if is the development or
|
||||||
|
published version.
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- development
|
||||||
|
- published
|
||||||
|
createdAt:
|
||||||
|
description: States when the app was created, will be constant. Stored in ISO
|
||||||
|
format.
|
||||||
|
type: string
|
||||||
|
updatedAt:
|
||||||
|
description: States the last time the app was updated - stored in ISO format.
|
||||||
|
type: string
|
||||||
|
version:
|
||||||
|
description: States the version of the Budibase client this app is currently
|
||||||
|
based on.
|
||||||
|
type: string
|
||||||
|
tenantId:
|
||||||
|
description: In a multi-tenant environment this will state the tenant this app
|
||||||
|
is within.
|
||||||
|
type: string
|
||||||
|
lockedBy:
|
||||||
|
description: The user this app is currently being built by.
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- _id
|
||||||
|
- name
|
||||||
|
- url
|
||||||
|
- status
|
||||||
|
- createdAt
|
||||||
|
- updatedAt
|
||||||
|
- version
|
||||||
|
required:
|
||||||
|
- data
|
||||||
row:
|
row:
|
||||||
description: The row to be created/updated, based on the table schema.
|
description: The row to be created/updated, based on the table schema.
|
||||||
type: object
|
type: object
|
||||||
|
@ -730,6 +782,175 @@ components:
|
||||||
type: string
|
type: string
|
||||||
required:
|
required:
|
||||||
- data
|
- data
|
||||||
|
tableSearch:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
description: The table to be created/updated.
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- schema
|
||||||
|
- _id
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: The name of the table.
|
||||||
|
type: string
|
||||||
|
primaryDisplay:
|
||||||
|
type: string
|
||||||
|
description: The name of the column which should be used in relationship tags
|
||||||
|
when relating to this table.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
oneOf:
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- link
|
||||||
|
description: A relationship column.
|
||||||
|
constraints:
|
||||||
|
type: object
|
||||||
|
description: A constraint can be applied to the column which will be validated
|
||||||
|
against when a row is saved.
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- string
|
||||||
|
- number
|
||||||
|
- object
|
||||||
|
- boolean
|
||||||
|
presence:
|
||||||
|
type: boolean
|
||||||
|
description: Defines whether the column is required or not.
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The name of the column.
|
||||||
|
autocolumn:
|
||||||
|
type: boolean
|
||||||
|
description: Defines whether the column is automatically generated.
|
||||||
|
fieldName:
|
||||||
|
type: string
|
||||||
|
description: The name of the column which a relationship column is related to in
|
||||||
|
another table.
|
||||||
|
tableId:
|
||||||
|
type: string
|
||||||
|
description: The ID of the table which a relationship column is related to.
|
||||||
|
relationshipType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- one-to-many
|
||||||
|
- many-to-one
|
||||||
|
- many-to-many
|
||||||
|
description: Defines the type of relationship that this column will be used for.
|
||||||
|
through:
|
||||||
|
type: string
|
||||||
|
description: When using a SQL table that contains many to many relationships
|
||||||
|
this defines the table the relationships are linked
|
||||||
|
through.
|
||||||
|
foreignKey:
|
||||||
|
type: string
|
||||||
|
description: When using a SQL table that contains a one to many relationship
|
||||||
|
this defines the foreign key.
|
||||||
|
throughFrom:
|
||||||
|
type: string
|
||||||
|
description: When using a SQL table that utilises a through table, this defines
|
||||||
|
the primary key in the through table for this table.
|
||||||
|
throughTo:
|
||||||
|
type: string
|
||||||
|
description: When using a SQL table that utilises a through table, this defines
|
||||||
|
the primary key in the through table for the related
|
||||||
|
table.
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- formula
|
||||||
|
description: A formula column.
|
||||||
|
constraints:
|
||||||
|
type: object
|
||||||
|
description: A constraint can be applied to the column which will be validated
|
||||||
|
against when a row is saved.
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- string
|
||||||
|
- number
|
||||||
|
- object
|
||||||
|
- boolean
|
||||||
|
presence:
|
||||||
|
type: boolean
|
||||||
|
description: Defines whether the column is required or not.
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The name of the column.
|
||||||
|
autocolumn:
|
||||||
|
type: boolean
|
||||||
|
description: Defines whether the column is automatically generated.
|
||||||
|
formula:
|
||||||
|
type: string
|
||||||
|
description: Defines a Handlebars or JavaScript formula to use, note that
|
||||||
|
Javascript formulas are expected to be provided in
|
||||||
|
the base64 format.
|
||||||
|
formulaType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- static
|
||||||
|
- dynamic
|
||||||
|
description: Defines whether this is a static or dynamic formula.
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- string
|
||||||
|
- longform
|
||||||
|
- options
|
||||||
|
- number
|
||||||
|
- boolean
|
||||||
|
- array
|
||||||
|
- datetime
|
||||||
|
- attachment
|
||||||
|
- link
|
||||||
|
- formula
|
||||||
|
- auto
|
||||||
|
- json
|
||||||
|
- internal
|
||||||
|
description: Defines the type of the column, most explain themselves, a link
|
||||||
|
column is a relationship.
|
||||||
|
constraints:
|
||||||
|
type: object
|
||||||
|
description: A constraint can be applied to the column which will be validated
|
||||||
|
against when a row is saved.
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- string
|
||||||
|
- number
|
||||||
|
- object
|
||||||
|
- boolean
|
||||||
|
presence:
|
||||||
|
type: boolean
|
||||||
|
description: Defines whether the column is required or not.
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The name of the column.
|
||||||
|
autocolumn:
|
||||||
|
type: boolean
|
||||||
|
description: Defines whether the column is automatically generated.
|
||||||
|
_id:
|
||||||
|
description: The ID of the table.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- data
|
||||||
executeQuery:
|
executeQuery:
|
||||||
description: The query body must contain the required parameters for the query,
|
description: The query body must contain the required parameters for the query,
|
||||||
this depends on query type, setup and bindings.
|
this depends on query type, setup and bindings.
|
||||||
|
@ -803,6 +1024,55 @@ components:
|
||||||
- name
|
- name
|
||||||
- schema
|
- schema
|
||||||
- _id
|
- _id
|
||||||
|
querySearch:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
_id:
|
||||||
|
description: The ID of the query.
|
||||||
|
type: string
|
||||||
|
datasourceId:
|
||||||
|
description: The ID of the data source the query belongs to.
|
||||||
|
type: string
|
||||||
|
parameters:
|
||||||
|
description: The bindings which are required to perform this query.
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
fields:
|
||||||
|
description: The fields that are used to perform this query, e.g. the sql
|
||||||
|
statement
|
||||||
|
type: object
|
||||||
|
queryVerb:
|
||||||
|
description: The verb that describes this query.
|
||||||
|
enum:
|
||||||
|
- create
|
||||||
|
- read
|
||||||
|
- update
|
||||||
|
- delete
|
||||||
|
name:
|
||||||
|
description: The name of the query.
|
||||||
|
type: string
|
||||||
|
schema:
|
||||||
|
description: The schema of the data returned when the query is executed.
|
||||||
|
type: object
|
||||||
|
transformer:
|
||||||
|
description: The JavaScript transformer function, applied after the query
|
||||||
|
responds with data.
|
||||||
|
type: string
|
||||||
|
readable:
|
||||||
|
description: Whether the query has readable data.
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- schema
|
||||||
|
- _id
|
||||||
|
required:
|
||||||
|
- data
|
||||||
user:
|
user:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -916,6 +1186,69 @@ components:
|
||||||
- _id
|
- _id
|
||||||
required:
|
required:
|
||||||
- data
|
- data
|
||||||
|
userSearch:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
description: The email address of the user, this must be unique.
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
description: The password of the user if using password based login - this will
|
||||||
|
never be returned. This can be left out of subsequent requests
|
||||||
|
(updates) and will be enriched back into the user structure.
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: The status of the user, if they are active.
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- active
|
||||||
|
firstName:
|
||||||
|
description: The first name of the user
|
||||||
|
type: string
|
||||||
|
lastName:
|
||||||
|
description: The last name of the user
|
||||||
|
type: string
|
||||||
|
forceResetPassword:
|
||||||
|
description: If set to true forces the user to reset their password on first
|
||||||
|
login.
|
||||||
|
type: boolean
|
||||||
|
builder:
|
||||||
|
description: Describes if the user is a builder user or not.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
global:
|
||||||
|
description: If set to true the user will be able to build any app in the
|
||||||
|
system.
|
||||||
|
type: boolean
|
||||||
|
admin:
|
||||||
|
description: Describes if the user is an admin user or not.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
global:
|
||||||
|
description: If set to true the user will be able to administrate the system.
|
||||||
|
type: boolean
|
||||||
|
roles:
|
||||||
|
description: Contains the roles of the user per app (assuming they are not a
|
||||||
|
builder user).
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: A map of app ID (production app ID, minus the _dev component) to a
|
||||||
|
role ID, e.g. ADMIN.
|
||||||
|
_id:
|
||||||
|
description: The ID of the user.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- email
|
||||||
|
- roles
|
||||||
|
- _id
|
||||||
|
required:
|
||||||
|
- data
|
||||||
nameSearch:
|
nameSearch:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1028,14 +1361,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: "#/components/schemas/applicationSearch"
|
||||||
required:
|
|
||||||
- data
|
|
||||||
properties:
|
|
||||||
data:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/application"
|
|
||||||
examples:
|
examples:
|
||||||
applications:
|
applications:
|
||||||
$ref: "#/components/examples/applications"
|
$ref: "#/components/examples/applications"
|
||||||
|
@ -1087,14 +1413,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: "#/components/schemas/querySearch"
|
||||||
required:
|
|
||||||
- data
|
|
||||||
properties:
|
|
||||||
data:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/query"
|
|
||||||
examples:
|
examples:
|
||||||
queries:
|
queries:
|
||||||
$ref: "#/components/examples/queries"
|
$ref: "#/components/examples/queries"
|
||||||
|
@ -1419,14 +1738,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: "#/components/schemas/tableSearch"
|
||||||
required:
|
|
||||||
- data
|
|
||||||
properties:
|
|
||||||
data:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/table"
|
|
||||||
examples:
|
examples:
|
||||||
tables:
|
tables:
|
||||||
$ref: "#/components/examples/tables"
|
$ref: "#/components/examples/tables"
|
||||||
|
@ -1524,14 +1836,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: "#/components/schemas/userSearch"
|
||||||
required:
|
|
||||||
- data
|
|
||||||
properties:
|
|
||||||
data:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/user"
|
|
||||||
examples:
|
examples:
|
||||||
users:
|
users:
|
||||||
$ref: "#/components/examples/users"
|
$ref: "#/components/examples/users"
|
||||||
|
|
|
@ -98,4 +98,10 @@ module.exports = new Resource()
|
||||||
applicationOutput: object({
|
applicationOutput: object({
|
||||||
data: applicationOutputSchema,
|
data: applicationOutputSchema,
|
||||||
}),
|
}),
|
||||||
|
applicationSearch: object({
|
||||||
|
data: {
|
||||||
|
type: "array",
|
||||||
|
items: applicationOutputSchema,
|
||||||
|
},
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
|
@ -186,4 +186,10 @@ module.exports = new Resource()
|
||||||
executeQuery: executeQuerySchema,
|
executeQuery: executeQuerySchema,
|
||||||
executeQueryOutput: executeQueryOutputSchema,
|
executeQueryOutput: executeQueryOutputSchema,
|
||||||
query: querySchema,
|
query: querySchema,
|
||||||
|
querySearch: object({
|
||||||
|
data: {
|
||||||
|
type: "array",
|
||||||
|
items: querySchema,
|
||||||
|
},
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
|
@ -188,4 +188,10 @@ module.exports = new Resource()
|
||||||
tableOutput: object({
|
tableOutput: object({
|
||||||
data: tableOutputSchema,
|
data: tableOutputSchema,
|
||||||
}),
|
}),
|
||||||
|
tableSearch: object({
|
||||||
|
data: {
|
||||||
|
type: "array",
|
||||||
|
items: tableOutputSchema,
|
||||||
|
},
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
|
@ -123,4 +123,10 @@ module.exports = new Resource()
|
||||||
userOutput: object({
|
userOutput: object({
|
||||||
data: userOutputSchema,
|
data: userOutputSchema,
|
||||||
}),
|
}),
|
||||||
|
userSearch: object({
|
||||||
|
data: {
|
||||||
|
type: "array",
|
||||||
|
items: userOutputSchema,
|
||||||
|
},
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { default as rowController } from "../row"
|
import { default as rowController } from "../row"
|
||||||
import { addRev } from "./utils"
|
import { addRev } from "./utils"
|
||||||
import { Row } from "../../../definitions/common"
|
import { Row } from "../../../definitions/common"
|
||||||
|
import { convertBookmark } from "../../../utilities"
|
||||||
|
|
||||||
// makes sure that the user doesn't need to pass in the type, tableId or _id params for
|
// makes sure that the user doesn't need to pass in the type, tableId or _id params for
|
||||||
// the call to be correct
|
// the call to be correct
|
||||||
|
@ -30,7 +31,7 @@ export async function search(ctx: any, next: any) {
|
||||||
sort: sort.column,
|
sort: sort.column,
|
||||||
sortType: sort.type,
|
sortType: sort.type,
|
||||||
sortOrder: sort.order,
|
sortOrder: sort.order,
|
||||||
bookmark,
|
bookmark: convertBookmark(bookmark),
|
||||||
paginate,
|
paginate,
|
||||||
limit,
|
limit,
|
||||||
query,
|
query,
|
||||||
|
|
|
@ -33,11 +33,11 @@ exports.handleRequest = handleRequest
|
||||||
exports.patch = async ctx => {
|
exports.patch = async ctx => {
|
||||||
const inputs = ctx.request.body
|
const inputs = ctx.request.body
|
||||||
const tableId = ctx.params.tableId
|
const tableId = ctx.params.tableId
|
||||||
const id = breakRowIdField(inputs._id)
|
const id = inputs._id
|
||||||
// don't save the ID to db
|
// don't save the ID to db
|
||||||
delete inputs._id
|
delete inputs._id
|
||||||
return handleRequest(DataSourceOperation.UPDATE, tableId, {
|
return handleRequest(DataSourceOperation.UPDATE, tableId, {
|
||||||
id,
|
id: breakRowIdField(id),
|
||||||
row: inputs,
|
row: inputs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ exports.find = async ctx => {
|
||||||
const id = ctx.params.rowId
|
const id = ctx.params.rowId
|
||||||
const tableId = ctx.params.tableId
|
const tableId = ctx.params.tableId
|
||||||
const response = await handleRequest(DataSourceOperation.READ, tableId, {
|
const response = await handleRequest(DataSourceOperation.READ, tableId, {
|
||||||
id,
|
id: breakRowIdField(id),
|
||||||
})
|
})
|
||||||
return response ? response[0] : response
|
return response ? response[0] : response
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ exports.destroy = async ctx => {
|
||||||
const tableId = ctx.params.tableId
|
const tableId = ctx.params.tableId
|
||||||
const id = ctx.request.body._id
|
const id = ctx.request.body._id
|
||||||
const { row } = await handleRequest(DataSourceOperation.DELETE, tableId, {
|
const { row } = await handleRequest(DataSourceOperation.DELETE, tableId, {
|
||||||
id,
|
id: breakRowIdField(id),
|
||||||
})
|
})
|
||||||
return { response: { ok: true }, row }
|
return { response: { ok: true }, row }
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,27 @@ exports.validate = async () => {
|
||||||
return { valid: true }
|
return { valid: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.exportRows = async ctx => {
|
||||||
|
const { datasourceId, tableName } = breakExternalTableId(ctx.params.tableId)
|
||||||
|
const db = getAppDB()
|
||||||
|
const datasource = await db.get(datasourceId)
|
||||||
|
if (!datasource || !datasource.entities) {
|
||||||
|
ctx.throw(400, "Datasource has not been configured for plus API.")
|
||||||
|
}
|
||||||
|
const tables = datasource.entities
|
||||||
|
const table = tables[tableName]
|
||||||
|
ctx.request.body = {
|
||||||
|
query: {
|
||||||
|
oneOf: {
|
||||||
|
[table.primaryDisplay]: ctx.request.body.map(
|
||||||
|
id => breakRowIdField(id)[0]
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return exports.search(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
exports.fetchEnrichedRow = async ctx => {
|
exports.fetchEnrichedRow = async ctx => {
|
||||||
const id = ctx.params.rowId
|
const id = ctx.params.rowId
|
||||||
const tableId = ctx.params.tableId
|
const tableId = ctx.params.tableId
|
||||||
|
|
|
@ -137,3 +137,12 @@ exports.fetchEnrichedRow = async function (ctx) {
|
||||||
ctx.throw(400, err)
|
ctx.throw(400, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.export = async function (ctx) {
|
||||||
|
const tableId = getTableId(ctx)
|
||||||
|
try {
|
||||||
|
ctx.body = await pickApi(tableId).exportRows(ctx)
|
||||||
|
} catch (err) {
|
||||||
|
ctx.throw(400, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -362,6 +362,22 @@ exports.validate = async ctx => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.exportRows = async ctx => {
|
||||||
|
const db = getAppDB()
|
||||||
|
const table = await db.get(ctx.params.tableId)
|
||||||
|
const rowIds = ctx.request.body.rows
|
||||||
|
let response = (
|
||||||
|
await db.allDocs({
|
||||||
|
include_docs: true,
|
||||||
|
keys: rowIds,
|
||||||
|
})
|
||||||
|
).rows.map(row => row.doc)
|
||||||
|
|
||||||
|
let rows = await outputProcessing(table, response)
|
||||||
|
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
exports.fetchEnrichedRow = async ctx => {
|
exports.fetchEnrichedRow = async ctx => {
|
||||||
const db = getAppDB()
|
const db = getAppDB()
|
||||||
const tableId = ctx.params.tableId
|
const tableId = ctx.params.tableId
|
||||||
|
|
|
@ -135,14 +135,7 @@ read.push(new Endpoint("get", "/applications/:appId", controller.read))
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* type: object
|
* $ref: '#/components/schemas/applicationSearch'
|
||||||
* required:
|
|
||||||
* - data
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: '#/components/schemas/application'
|
|
||||||
* examples:
|
* examples:
|
||||||
* applications:
|
* applications:
|
||||||
* $ref: '#/components/examples/applications'
|
* $ref: '#/components/examples/applications'
|
||||||
|
|
|
@ -60,14 +60,7 @@ write.push(new Endpoint("post", "/queries/:queryId", controller.execute))
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* type: object
|
* $ref: '#/components/schemas/querySearch'
|
||||||
* required:
|
|
||||||
* - data
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: '#/components/schemas/query'
|
|
||||||
* examples:
|
* examples:
|
||||||
* queries:
|
* queries:
|
||||||
* $ref: '#/components/examples/queries'
|
* $ref: '#/components/examples/queries'
|
||||||
|
|
|
@ -148,14 +148,7 @@ read.push(new Endpoint("get", "/tables/:tableId", controller.read))
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* type: object
|
* $ref: '#/components/schemas/tableSearch'
|
||||||
* required:
|
|
||||||
* - data
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: '#/components/schemas/table'
|
|
||||||
* examples:
|
* examples:
|
||||||
* tables:
|
* tables:
|
||||||
* $ref: '#/components/examples/tables'
|
* $ref: '#/components/examples/tables'
|
||||||
|
|
|
@ -123,14 +123,7 @@ read.push(new Endpoint("get", "/users/:userId", controller.read))
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* type: object
|
* $ref: '#/components/schemas/userSearch'
|
||||||
* required:
|
|
||||||
* - data
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: '#/components/schemas/user'
|
|
||||||
* examples:
|
* examples:
|
||||||
* users:
|
* users:
|
||||||
* $ref: '#/components/examples/users'
|
* $ref: '#/components/examples/users'
|
||||||
|
|
|
@ -252,4 +252,25 @@ router
|
||||||
rowController.destroy
|
rowController.destroy
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {post} /api/:tableId/rows/exportRows Export Rows
|
||||||
|
* @apiName Export rows
|
||||||
|
* @apiGroup rows
|
||||||
|
* @apiPermission table write access
|
||||||
|
* @apiDescription This API can export a number of provided rows
|
||||||
|
*
|
||||||
|
* @apiParam {string} tableId The ID of the table the row is to be deleted from.
|
||||||
|
*
|
||||||
|
* @apiParam (Body) {object[]} [rows] The row IDs which are to be exported
|
||||||
|
*
|
||||||
|
* @apiSuccess {object[]|object}
|
||||||
|
*/
|
||||||
|
.post(
|
||||||
|
"/api/:tableId/rows/exportRows",
|
||||||
|
paramResource("tableId"),
|
||||||
|
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
||||||
|
usage,
|
||||||
|
rowController.export
|
||||||
|
)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -95,9 +95,7 @@ export interface paths {
|
||||||
/** Returns the applications that were found based on the search parameters. */
|
/** Returns the applications that were found based on the search parameters. */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": components["schemas"]["applicationSearch"]
|
||||||
data: components["schemas"]["application"][]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,9 +147,7 @@ export interface paths {
|
||||||
/** Returns the queries found based on the search parameters. */
|
/** Returns the queries found based on the search parameters. */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": components["schemas"]["querySearch"]
|
||||||
data: components["schemas"]["query"][]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,9 +445,7 @@ export interface paths {
|
||||||
/** Returns the found tables, based on the search parameters. */
|
/** Returns the found tables, based on the search parameters. */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": components["schemas"]["tableSearch"]
|
||||||
data: components["schemas"]["table"][]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,9 +535,7 @@ export interface paths {
|
||||||
/** Returns the found users based on search parameters. */
|
/** Returns the found users based on search parameters. */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": components["schemas"]["userSearch"]
|
||||||
data: components["schemas"]["user"][]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,6 +581,31 @@ export interface components {
|
||||||
lockedBy?: { [key: string]: unknown }
|
lockedBy?: { [key: string]: unknown }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
applicationSearch: {
|
||||||
|
data: {
|
||||||
|
/** @description The name of the app. */
|
||||||
|
name: string
|
||||||
|
/** @description The URL by which the app is accessed, this must be URL encoded. */
|
||||||
|
url: string
|
||||||
|
/** @description The ID of the app. */
|
||||||
|
_id: string
|
||||||
|
/**
|
||||||
|
* @description The status of the app, stating it if is the development or published version.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
status: "development" | "published"
|
||||||
|
/** @description States when the app was created, will be constant. Stored in ISO format. */
|
||||||
|
createdAt: string
|
||||||
|
/** @description States the last time the app was updated - stored in ISO format. */
|
||||||
|
updatedAt: string
|
||||||
|
/** @description States the version of the Budibase client this app is currently based on. */
|
||||||
|
version: string
|
||||||
|
/** @description In a multi-tenant environment this will state the tenant this app is within. */
|
||||||
|
tenantId?: string
|
||||||
|
/** @description The user this app is currently being built by. */
|
||||||
|
lockedBy?: { [key: string]: unknown }
|
||||||
|
}[]
|
||||||
|
}
|
||||||
/** @description The row to be created/updated, based on the table schema. */
|
/** @description The row to be created/updated, based on the table schema. */
|
||||||
row: { [key: string]: unknown }
|
row: { [key: string]: unknown }
|
||||||
searchOutput: {
|
searchOutput: {
|
||||||
|
@ -817,6 +834,113 @@ export interface components {
|
||||||
_id: string
|
_id: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tableSearch: {
|
||||||
|
data: {
|
||||||
|
/** @description The name of the table. */
|
||||||
|
name: string
|
||||||
|
/** @description The name of the column which should be used in relationship tags when relating to this table. */
|
||||||
|
primaryDisplay?: string
|
||||||
|
schema: {
|
||||||
|
[key: string]:
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* @description A relationship column.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
type?: "link"
|
||||||
|
/** @description A constraint can be applied to the column which will be validated against when a row is saved. */
|
||||||
|
constraints?: {
|
||||||
|
/** @enum {string} */
|
||||||
|
type?: "string" | "number" | "object" | "boolean"
|
||||||
|
/** @description Defines whether the column is required or not. */
|
||||||
|
presence?: boolean
|
||||||
|
}
|
||||||
|
/** @description The name of the column. */
|
||||||
|
name?: string
|
||||||
|
/** @description Defines whether the column is automatically generated. */
|
||||||
|
autocolumn?: boolean
|
||||||
|
/** @description The name of the column which a relationship column is related to in another table. */
|
||||||
|
fieldName?: string
|
||||||
|
/** @description The ID of the table which a relationship column is related to. */
|
||||||
|
tableId?: string
|
||||||
|
/**
|
||||||
|
* @description Defines the type of relationship that this column will be used for.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
relationshipType?:
|
||||||
|
| "one-to-many"
|
||||||
|
| "many-to-one"
|
||||||
|
| "many-to-many"
|
||||||
|
/** @description When using a SQL table that contains many to many relationships this defines the table the relationships are linked through. */
|
||||||
|
through?: string
|
||||||
|
/** @description When using a SQL table that contains a one to many relationship this defines the foreign key. */
|
||||||
|
foreignKey?: string
|
||||||
|
/** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for this table. */
|
||||||
|
throughFrom?: string
|
||||||
|
/** @description When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table. */
|
||||||
|
throughTo?: string
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* @description A formula column.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
type?: "formula"
|
||||||
|
/** @description A constraint can be applied to the column which will be validated against when a row is saved. */
|
||||||
|
constraints?: {
|
||||||
|
/** @enum {string} */
|
||||||
|
type?: "string" | "number" | "object" | "boolean"
|
||||||
|
/** @description Defines whether the column is required or not. */
|
||||||
|
presence?: boolean
|
||||||
|
}
|
||||||
|
/** @description The name of the column. */
|
||||||
|
name?: string
|
||||||
|
/** @description Defines whether the column is automatically generated. */
|
||||||
|
autocolumn?: boolean
|
||||||
|
/** @description Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format. */
|
||||||
|
formula?: string
|
||||||
|
/**
|
||||||
|
* @description Defines whether this is a static or dynamic formula.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
formulaType?: "static" | "dynamic"
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* @description Defines the type of the column, most explain themselves, a link column is a relationship.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
type?:
|
||||||
|
| "string"
|
||||||
|
| "longform"
|
||||||
|
| "options"
|
||||||
|
| "number"
|
||||||
|
| "boolean"
|
||||||
|
| "array"
|
||||||
|
| "datetime"
|
||||||
|
| "attachment"
|
||||||
|
| "link"
|
||||||
|
| "formula"
|
||||||
|
| "auto"
|
||||||
|
| "json"
|
||||||
|
| "internal"
|
||||||
|
/** @description A constraint can be applied to the column which will be validated against when a row is saved. */
|
||||||
|
constraints?: {
|
||||||
|
/** @enum {string} */
|
||||||
|
type?: "string" | "number" | "object" | "boolean"
|
||||||
|
/** @description Defines whether the column is required or not. */
|
||||||
|
presence?: boolean
|
||||||
|
}
|
||||||
|
/** @description The name of the column. */
|
||||||
|
name?: string
|
||||||
|
/** @description Defines whether the column is automatically generated. */
|
||||||
|
autocolumn?: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** @description The ID of the table. */
|
||||||
|
_id: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
/** @description The query body must contain the required parameters for the query, this depends on query type, setup and bindings. */
|
/** @description The query body must contain the required parameters for the query, this depends on query type, setup and bindings. */
|
||||||
executeQuery: { [key: string]: unknown }
|
executeQuery: { [key: string]: unknown }
|
||||||
executeQueryOutput: {
|
executeQueryOutput: {
|
||||||
|
@ -855,6 +979,31 @@ export interface components {
|
||||||
/** @description Whether the query has readable data. */
|
/** @description Whether the query has readable data. */
|
||||||
readable?: boolean
|
readable?: boolean
|
||||||
}
|
}
|
||||||
|
querySearch: {
|
||||||
|
data: {
|
||||||
|
/** @description The ID of the query. */
|
||||||
|
_id: string
|
||||||
|
/** @description The ID of the data source the query belongs to. */
|
||||||
|
datasourceId?: string
|
||||||
|
/** @description The bindings which are required to perform this query. */
|
||||||
|
parameters?: string[]
|
||||||
|
/** @description The fields that are used to perform this query, e.g. the sql statement */
|
||||||
|
fields?: { [key: string]: unknown }
|
||||||
|
/**
|
||||||
|
* @description The verb that describes this query.
|
||||||
|
* @enum {undefined}
|
||||||
|
*/
|
||||||
|
queryVerb?: "create" | "read" | "update" | "delete"
|
||||||
|
/** @description The name of the query. */
|
||||||
|
name: string
|
||||||
|
/** @description The schema of the data returned when the query is executed. */
|
||||||
|
schema: { [key: string]: unknown }
|
||||||
|
/** @description The JavaScript transformer function, applied after the query responds with data. */
|
||||||
|
transformer?: string
|
||||||
|
/** @description Whether the query has readable data. */
|
||||||
|
readable?: boolean
|
||||||
|
}[]
|
||||||
|
}
|
||||||
user: {
|
user: {
|
||||||
/** @description The email address of the user, this must be unique. */
|
/** @description The email address of the user, this must be unique. */
|
||||||
email: string
|
email: string
|
||||||
|
@ -917,6 +1066,39 @@ export interface components {
|
||||||
_id: string
|
_id: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
userSearch: {
|
||||||
|
data: {
|
||||||
|
/** @description The email address of the user, this must be unique. */
|
||||||
|
email: string
|
||||||
|
/** @description The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure. */
|
||||||
|
password?: string
|
||||||
|
/**
|
||||||
|
* @description The status of the user, if they are active.
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
status?: "active"
|
||||||
|
/** @description The first name of the user */
|
||||||
|
firstName?: string
|
||||||
|
/** @description The last name of the user */
|
||||||
|
lastName?: string
|
||||||
|
/** @description If set to true forces the user to reset their password on first login. */
|
||||||
|
forceResetPassword?: boolean
|
||||||
|
/** @description Describes if the user is a builder user or not. */
|
||||||
|
builder?: {
|
||||||
|
/** @description If set to true the user will be able to build any app in the system. */
|
||||||
|
global?: boolean
|
||||||
|
}
|
||||||
|
/** @description Describes if the user is an admin user or not. */
|
||||||
|
admin?: {
|
||||||
|
/** @description If set to true the user will be able to administrate the system. */
|
||||||
|
global?: boolean
|
||||||
|
}
|
||||||
|
/** @description Contains the roles of the user per app (assuming they are not a builder user). */
|
||||||
|
roles: { [key: string]: string }
|
||||||
|
/** @description The ID of the user. */
|
||||||
|
_id: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
nameSearch: {
|
nameSearch: {
|
||||||
/** @description The name to be used when searching - this will be used in a case insensitive starts with match. */
|
/** @description The name to be used when searching - this will be used in a case insensitive starts with match. */
|
||||||
name: string
|
name: string
|
||||||
|
|
|
@ -151,3 +151,11 @@ exports.formatBytes = bytes => {
|
||||||
}
|
}
|
||||||
return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`
|
return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.convertBookmark = bookmark => {
|
||||||
|
const IS_NUMBER = /^\d+\.?\d*$/
|
||||||
|
if (typeof bookmark === "string" && bookmark.match(IS_NUMBER)) {
|
||||||
|
return parseFloat(bookmark)
|
||||||
|
}
|
||||||
|
return bookmark
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"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",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.0.80-alpha.5",
|
"version": "1.0.81-alpha.6",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "^1.0.80-alpha.5",
|
"@budibase/backend-core": "^1.0.81-alpha.6",
|
||||||
"@budibase/string-templates": "^1.0.80-alpha.5",
|
"@budibase/string-templates": "^1.0.81-alpha.6",
|
||||||
"@koa/router": "^8.0.0",
|
"@koa/router": "^8.0.0",
|
||||||
"@sentry/node": "^6.0.0",
|
"@sentry/node": "^6.0.0",
|
||||||
"@techpass/passport-openidconnect": "^0.3.0",
|
"@techpass/passport-openidconnect": "^0.3.0",
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
const {
|
||||||
|
getGlobalDB,
|
||||||
|
getTenantId,
|
||||||
|
isUserInAppTenant,
|
||||||
|
} = require("@budibase/backend-core/tenancy")
|
||||||
const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db")
|
const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db")
|
||||||
const { user: userCache } = require("@budibase/backend-core/cache")
|
const { user: userCache } = require("@budibase/backend-core/cache")
|
||||||
const { hash, platformLogout } = require("@budibase/backend-core/utils")
|
const {
|
||||||
|
hash,
|
||||||
|
platformLogout,
|
||||||
|
getCookie,
|
||||||
|
clearCookie,
|
||||||
|
} = require("@budibase/backend-core/utils")
|
||||||
const { encrypt } = require("@budibase/backend-core/encryption")
|
const { encrypt } = require("@budibase/backend-core/encryption")
|
||||||
const { newid } = require("@budibase/backend-core/utils")
|
const { newid } = require("@budibase/backend-core/utils")
|
||||||
const { getUser } = require("../../utilities")
|
const { getUser } = require("../../utilities")
|
||||||
|
const { Cookies } = require("@budibase/backend-core/constants")
|
||||||
|
|
||||||
function newApiKey() {
|
function newApiKey() {
|
||||||
return encrypt(`${getTenantId()}${SEPARATOR}${newid()}`)
|
return encrypt(`${getTenantId()}${SEPARATOR}${newid()}`)
|
||||||
|
@ -48,6 +58,16 @@ exports.fetchAPIKey = async ctx => {
|
||||||
ctx.body = cleanupDevInfo(devInfo)
|
ctx.body = cleanupDevInfo(devInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkCurrentApp = ctx => {
|
||||||
|
const appCookie = getCookie(ctx, Cookies.CurrentApp)
|
||||||
|
if (appCookie && !isUserInAppTenant(appCookie.appId)) {
|
||||||
|
// there is a currentapp cookie from another tenant
|
||||||
|
// remove the cookie as this is incompatible with the builder
|
||||||
|
// due to builder and admin permissions being removed
|
||||||
|
clearCookie(ctx, Cookies.CurrentApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exports.getSelf = async ctx => {
|
exports.getSelf = async ctx => {
|
||||||
if (!ctx.user) {
|
if (!ctx.user) {
|
||||||
ctx.throw(403, "User not logged in")
|
ctx.throw(403, "User not logged in")
|
||||||
|
@ -56,6 +76,9 @@ exports.getSelf = async ctx => {
|
||||||
ctx.params = {
|
ctx.params = {
|
||||||
id: userId,
|
id: userId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkCurrentApp(ctx)
|
||||||
|
|
||||||
// get the main body of the user
|
// get the main body of the user
|
||||||
ctx.body = await getUser(userId)
|
ctx.body = await getUser(userId)
|
||||||
// forward session information not found in db
|
// forward session information not found in db
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
const accounts = require("@budibase/backend-core/accounts")
|
||||||
|
const env = require("../../../environment")
|
||||||
|
|
||||||
|
exports.fetch = async ctx => {
|
||||||
|
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
||||||
|
const status = await accounts.getStatus()
|
||||||
|
ctx.body = status
|
||||||
|
} else {
|
||||||
|
ctx.body = {
|
||||||
|
health: {
|
||||||
|
passing: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,6 @@ const PUBLIC_ENDPOINTS = [
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// TODO: Add an provisioning API key to this endpoint in the cloud
|
|
||||||
route: "/api/global/users/init",
|
route: "/api/global/users/init",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
@ -51,6 +50,10 @@ const PUBLIC_ENDPOINTS = [
|
||||||
route: "api/system/environment",
|
route: "api/system/environment",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
route: "api/system/status",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
route: "/api/global/users/tenant/:id",
|
route: "/api/global/users/tenant/:id",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
@ -8,6 +8,7 @@ const roleRoutes = require("./global/roles")
|
||||||
const sessionRoutes = require("./global/sessions")
|
const sessionRoutes = require("./global/sessions")
|
||||||
const environmentRoutes = require("./system/environment")
|
const environmentRoutes = require("./system/environment")
|
||||||
const tenantsRoutes = require("./system/tenants")
|
const tenantsRoutes = require("./system/tenants")
|
||||||
|
const statusRoutes = require("./system/status")
|
||||||
const selfRoutes = require("./global/self")
|
const selfRoutes = require("./global/self")
|
||||||
|
|
||||||
exports.routes = [
|
exports.routes = [
|
||||||
|
@ -21,5 +22,6 @@ exports.routes = [
|
||||||
sessionRoutes,
|
sessionRoutes,
|
||||||
roleRoutes,
|
roleRoutes,
|
||||||
environmentRoutes,
|
environmentRoutes,
|
||||||
|
statusRoutes,
|
||||||
selfRoutes,
|
selfRoutes,
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
const Router = require("@koa/router")
|
||||||
|
const controller = require("../../controllers/system/status")
|
||||||
|
|
||||||
|
const router = Router()
|
||||||
|
|
||||||
|
router.get("/api/system/status", controller.fetch)
|
||||||
|
|
||||||
|
module.exports = router
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue