diff --git a/lerna.json b/lerna.json index 111a13702b..67a59cb188 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.4.18-alpha.1", + "version": "2.0.14-alpha.0", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/context.js b/packages/backend-core/context.js index aaa0f56f92..c6fa87a337 100644 --- a/packages/backend-core/context.js +++ b/packages/backend-core/context.js @@ -6,6 +6,7 @@ const { updateAppId, doInAppContext, doInTenant, + doInContext, } = require("./src/context") const identity = require("./src/context/identity") @@ -19,4 +20,5 @@ module.exports = { doInAppContext, doInTenant, identity, + doInContext, } diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 146e41e2e0..0ce4ac5e44 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.4.18-alpha.1", + "version": "2.0.14-alpha.0", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -20,7 +20,7 @@ "test:watch": "jest --watchAll" }, "dependencies": { - "@budibase/types": "1.4.18-alpha.1", + "@budibase/types": "2.0.14-alpha.0", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-sdk": "2.1030.0", diff --git a/packages/backend-core/src/context/index.ts b/packages/backend-core/src/context/index.ts index 7cc90e3c67..35eeee608b 100644 --- a/packages/backend-core/src/context/index.ts +++ b/packages/backend-core/src/context/index.ts @@ -65,7 +65,16 @@ export const getTenantIDFromAppID = (appId: string) => { } } -// used for automations, API endpoints should always be in context already +export const doInContext = async (appId: string, task: any) => { + // gets the tenant ID from the app ID + const tenantId = getTenantIDFromAppID(appId) + return doInTenant(tenantId, async () => { + return doInAppContext(appId, async () => { + return task() + }) + }) +} + export const doInTenant = (tenantId: string | null, task: any) => { // make sure default always selected in single tenancy if (!env.MULTI_TENANCY) { diff --git a/packages/backend-core/src/db/constants.ts b/packages/backend-core/src/db/constants.ts index 45ca675fa6..a61e8a2af2 100644 --- a/packages/backend-core/src/db/constants.ts +++ b/packages/backend-core/src/db/constants.ts @@ -46,6 +46,9 @@ export enum DocumentType { AUTOMATION_LOG = "log_au", ACCOUNT_METADATA = "acc_metadata", PLUGIN = "plg", + TABLE = "ta", + DATASOURCE = "datasource", + DATASOURCE_PLUS = "datasource_plus", } export const StaticDatabases = { diff --git a/packages/backend-core/src/db/conversions.js b/packages/backend-core/src/db/conversions.js index 90c04e9251..5b1a785ecc 100644 --- a/packages/backend-core/src/db/conversions.js +++ b/packages/backend-core/src/db/conversions.js @@ -36,6 +36,7 @@ exports.getDevelopmentAppID = appId => { const rest = split.join(APP_PREFIX) return `${APP_DEV_PREFIX}${rest}` } +exports.getDevAppID = exports.getDevelopmentAppID /** * Convert a development app ID to a deployed app ID. diff --git a/packages/backend-core/src/db/utils.ts b/packages/backend-core/src/db/utils.ts index a12c6bed4f..1c4be7e366 100644 --- a/packages/backend-core/src/db/utils.ts +++ b/packages/backend-core/src/db/utils.ts @@ -64,6 +64,28 @@ export function getQueryIndex(viewName: ViewName) { return `database/${viewName}` } +/** + * Check if a given ID is that of a table. + * @returns {boolean} + */ +export const isTableId = (id: string) => { + // this includes datasource plus tables + return ( + id && + (id.startsWith(`${DocumentType.TABLE}${SEPARATOR}`) || + id.startsWith(`${DocumentType.DATASOURCE_PLUS}${SEPARATOR}`)) + ) +} + +/** + * Check if a given ID is that of a datasource or datasource plus. + * @returns {boolean} + */ +export const isDatasourceId = (id: string) => { + // this covers both datasources and datasource plus + return id && id.startsWith(`${DocumentType.DATASOURCE}${SEPARATOR}`) +} + /** * Generates a new workspace ID. * @returns {string} The new workspace ID which the workspace doc can be stored under. diff --git a/packages/backend-core/src/migrations/definitions.ts b/packages/backend-core/src/migrations/definitions.ts index 946fc3f364..6eba56ab43 100644 --- a/packages/backend-core/src/migrations/definitions.ts +++ b/packages/backend-core/src/migrations/definitions.ts @@ -11,7 +11,7 @@ export const DEFINITIONS: MigrationDefinition[] = [ }, { type: MigrationType.GLOBAL, - name: MigrationName.QUOTAS_1, + name: MigrationName.SYNC_QUOTAS, }, { type: MigrationType.APP, @@ -33,8 +33,4 @@ export const DEFINITIONS: MigrationDefinition[] = [ type: MigrationType.GLOBAL, name: MigrationName.GLOBAL_INFO_SYNC_USERS, }, - { - type: MigrationType.GLOBAL, - name: MigrationName.PLUGIN_COUNT, - }, ] diff --git a/packages/backend-core/src/objectStore/index.ts b/packages/backend-core/src/objectStore/index.ts index a97aa8f65d..17e002cc49 100644 --- a/packages/backend-core/src/objectStore/index.ts +++ b/packages/backend-core/src/objectStore/index.ts @@ -182,6 +182,11 @@ export const streamUpload = async ( ...extra, ContentType: "application/javascript", } + } else if (filename?.endsWith(".svg")) { + extra = { + ...extra, + ContentType: "image", + } } const params = { diff --git a/packages/backend-core/src/pkg/context.ts b/packages/backend-core/src/pkg/context.ts index 5caa82ab0c..4915cc6e41 100644 --- a/packages/backend-core/src/pkg/context.ts +++ b/packages/backend-core/src/pkg/context.ts @@ -8,6 +8,7 @@ import { updateAppId, doInAppContext, doInTenant, + doInContext, } from "../context" import * as identity from "../context/identity" @@ -20,5 +21,6 @@ export = { updateAppId, doInAppContext, doInTenant, + doInContext, identity, } diff --git a/packages/backend-core/src/plugin/utils.js b/packages/backend-core/src/plugin/utils.js index ade84bf44a..60a40f3a76 100644 --- a/packages/backend-core/src/plugin/utils.js +++ b/packages/backend-core/src/plugin/utils.js @@ -67,12 +67,8 @@ function validateDatasource(schema) { description: joi.string().required(), datasource: joi.object().pattern(joi.string(), fieldValidator).required(), query: joi - .object({ - create: queryValidator, - read: queryValidator, - update: queryValidator, - delete: queryValidator, - }) + .object() + .pattern(joi.string(), queryValidator) .unknown(true) .required(), extra: joi.object().pattern( diff --git a/packages/bbui/package.json b/packages/bbui/package.json index b081f17943..7891629de2 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "1.4.18-alpha.1", + "version": "2.0.14-alpha.0", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "^1.2.1", - "@budibase/string-templates": "1.4.18-alpha.1", + "@budibase/string-templates": "2.0.14-alpha.0", "@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/avatar": "^3.0.2", diff --git a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js index 000ca7cb54..4844a0c670 100644 --- a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js @@ -20,7 +20,9 @@ filterTests(["smoke", "all"], () => { cy.get(".spectrum-Form-itemField").eq(3).should('contain', 'App User') // User should not have app access - cy.get(interact.LIST_ITEMS, { timeout: 500 }).should("contain", "No apps") + cy.get(".spectrum-Heading").contains("Apps").parent().within(() => { + cy.get(interact.LIST_ITEMS, { timeout: 500 }).should("contain", "This user has access to no apps") + }) }) if (Cypress.env("TEST_ENV")) { diff --git a/packages/builder/cypress/integration/autoScreensUI.spec.js b/packages/builder/cypress/integration/autoScreensUI.spec.js index 0253675c5b..a22dbb0a1e 100644 --- a/packages/builder/cypress/integration/autoScreensUI.spec.js +++ b/packages/builder/cypress/integration/autoScreensUI.spec.js @@ -54,6 +54,7 @@ filterTests(['smoke', 'all'], () => { cy.createDatasourceScreen([initialTable, secondTable]) // Confirm screens have been auto generated // Previously generated tables are suffixed with numbers - as expected + cy.wait(1000) cy.get(interact.BODY).should('contain', 'cypress-tests-2') .and('contain', 'cypress-tests-2/:id') .and('contain', 'cypress-tests-2/new/row') diff --git a/packages/builder/package.json b/packages/builder/package.json index 6cfbdb9710..681fa03b69 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.4.18-alpha.1", + "version": "2.0.14-alpha.0", "license": "GPL-3.0", "private": true, "scripts": { @@ -71,10 +71,10 @@ } }, "dependencies": { - "@budibase/bbui": "1.4.18-alpha.1", - "@budibase/client": "1.4.18-alpha.1", - "@budibase/frontend-core": "1.4.18-alpha.1", - "@budibase/string-templates": "1.4.18-alpha.1", + "@budibase/bbui": "2.0.14-alpha.0", + "@budibase/client": "2.0.14-alpha.0", + "@budibase/frontend-core": "2.0.14-alpha.0", + "@budibase/string-templates": "2.0.14-alpha.0", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/builderStore/componentUtils.js b/packages/builder/src/builderStore/componentUtils.js index 2ad7e82075..e7787dea72 100644 --- a/packages/builder/src/builderStore/componentUtils.js +++ b/packages/builder/src/builderStore/componentUtils.js @@ -143,7 +143,10 @@ export const getComponentSettings = componentType => { } // Ensure whole component name is used - if (!componentType.startsWith("@budibase")) { + if ( + !componentType.startsWith("plugin/") && + !componentType.startsWith("@budibase") + ) { componentType = `@budibase/standard-components/${componentType}` } diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index ca36380077..7456ec5691 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -243,18 +243,18 @@ export const getDatasourceForProvider = (asset, component) => { return null } - // There are different types of setting which can be a datasource, for - // example an actual datasource object, or a table ID string. - // Convert the datasource setting into a proper datasource object so that - // we can use it properly - if (datasourceSetting.type === "table") { + // For legacy compatibility, we need to be able to handle datasources that are + // just strings. These are not generated any more, so could be removed in + // future. + // TODO: remove at some point + const datasource = component[datasourceSetting?.key] + if (typeof datasource === "string") { return { - tableId: component[datasourceSetting?.key], + tableId: datasource, type: "table", } - } else { - return component[datasourceSetting?.key] } + return datasource } /** diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index b74261a7e8..aefdba9fb2 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -88,27 +88,12 @@ export const getFrontendStore = () => { initialise: async pkg => { const { layouts, screens, application, clientLibPath } = pkg - // Fetch component definitions. - // Allow errors to propagate. - const components = await API.fetchComponentLibDefinitions( - application.appId - ) - - // Filter out custom component keys so we can flag them - const customComponents = Object.keys(components).filter(name => - name.startsWith("plugin/") - ) + await store.actions.components.refreshDefinitions(application.appId) // Reset store state store.update(state => ({ ...state, libraries: application.componentLibraries, - components, - customComponents, - clientFeatures: { - ...INITIAL_FRONTEND_STATE.clientFeatures, - ...components.features, - }, name: application.name, description: application.description, appId: application.appId, @@ -385,6 +370,29 @@ export const getFrontendStore = () => { }, }, components: { + refreshDefinitions: async appId => { + if (!appId) { + appId = get(store).appId + } + + // Fetch definitions and filter out custom component definitions so we + // can flag them + const components = await API.fetchComponentLibDefinitions(appId) + const customComponents = Object.keys(components).filter(name => + name.startsWith("plugin/") + ) + + // Update store + store.update(state => ({ + ...state, + components, + customComponents, + clientFeatures: { + ...INITIAL_FRONTEND_STATE.clientFeatures, + ...components.features, + }, + })) + }, getDefinition: componentName => { if (!componentName) { return null @@ -428,7 +436,7 @@ export const getFrontendStore = () => { _id: Helpers.uuid(), _component: definition.component, _styles: { normal: {}, hover: {}, active: {} }, - _instanceName: `New ${definition.name}`, + _instanceName: `New ${definition.friendlyName || definition.name}`, ...cloneDeep(props), ...extras, } diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index 19946a2386..a3531513fb 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -13,7 +13,7 @@ customQueryIconColor, customQueryText, } from "helpers/data/utils" - import { getIcon } from "./icons" + import IntegrationIcon from "./IntegrationIcon.svelte" import { notifications } from "@budibase/bbui" let openDataSources = [] @@ -123,10 +123,10 @@ on:iconClick={() => toggleNode(datasource)} >
{#if datasource._id !== BUDIBASE_INTERNAL_DB} diff --git a/packages/builder/src/components/backend/DatasourceNavigator/IntegrationIcon.svelte b/packages/builder/src/components/backend/DatasourceNavigator/IntegrationIcon.svelte new file mode 100644 index 0000000000..e6cfbf7db8 --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/IntegrationIcon.svelte @@ -0,0 +1,32 @@ + + +{#if iconInfo.icon} +