From 22814db9d30ba242e74e8f7c108ae1930c9df0a1 Mon Sep 17 00:00:00 2001 From: Michael Drury Date: Thu, 15 Jun 2023 22:49:46 +0100 Subject: [PATCH 01/12] Quick fix suggested by Rory to make use of the cached license when fetching the app package. --- packages/server/src/api/controllers/application.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index ed31615981..32cc8a96fb 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -208,7 +208,7 @@ export async function fetchAppPackage(ctx: UserCtx) { let application = await db.get(DocumentType.APP_METADATA) const layouts = await getLayouts() let screens = await getScreens() - const license = await licensing.getLicense() + const license = await licensing.getCachedLicense() // Enrich plugin URLs application.usedPlugins = objectStore.enrichPluginURLs( From f80b9003388fe8f5f4fd294f3111464d906f9601 Mon Sep 17 00:00:00 2001 From: Michael Drury Date: Thu, 15 Jun 2023 23:29:08 +0100 Subject: [PATCH 02/12] Fixing where getCachedLicense is retrieved from. --- packages/server/src/api/controllers/application.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 32cc8a96fb..451b3e366c 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -208,7 +208,7 @@ export async function fetchAppPackage(ctx: UserCtx) { let application = await db.get(DocumentType.APP_METADATA) const layouts = await getLayouts() let screens = await getScreens() - const license = await licensing.getCachedLicense() + const license = await licensing.cache.getCachedLicense() // Enrich plugin URLs application.usedPlugins = objectStore.enrichPluginURLs( From ebec885b0ac2fc66fc3a5aee3eadc86509eb7a0f Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 15 Jun 2023 23:12:57 +0000 Subject: [PATCH 03/12] Bump version to 2.7.21 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 2494a5f30c..e5c8c70105 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.7.20", + "version": "2.7.21", "npmClient": "yarn", "packages": [ "packages/backend-core", From aafb294749a6b03dd523f16fdb684479d122f42d Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 16 Jun 2023 10:08:31 +0100 Subject: [PATCH 04/12] Fix linting issues --- packages/builder/src/helpers/validation/yup/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/helpers/validation/yup/index.js b/packages/builder/src/helpers/validation/yup/index.js index b5bdf030a5..4e84975eb7 100644 --- a/packages/builder/src/helpers/validation/yup/index.js +++ b/packages/builder/src/helpers/validation/yup/index.js @@ -58,7 +58,7 @@ export const createValidationStore = () => { const observe = async (propertyName, value) => { const values = get(validation).values let fieldIsValid - if (!values.hasOwnProperty(propertyName)) { + if (!Object.prototype.hasOwnProperty.call(values, propertyName)) { // Initial setup values[propertyName] = value return From 179f06f106d7b1dc262cc744c936d3380467e15e Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Fri, 16 Jun 2023 09:10:34 +0000 Subject: [PATCH 05/12] Bump version to 2.7.22 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 84a4e5507f..29f6eae86b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.7.21", + "version": "2.7.22", "npmClient": "yarn", "packages": [ "packages/backend-core", From 5f716a62a46f6d9c47df2280fb52d1e621c3d596 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Fri, 16 Jun 2023 10:13:43 +0100 Subject: [PATCH 06/12] Revert "Merge branch 'develop' into master" This reverts commit 67fb9de7f431a5f8465f8b9be11076c71f0d154f, reversing changes made to ebec885b0ac2fc66fc3a5aee3eadc86509eb7a0f. --- lerna.json | 1 + package.json | 4 +- .../middleware/passport/datasource/google.ts | 46 +- .../backend-core/src/security/encryption.ts | 125 +- packages/backend-core/src/security/roles.ts | 9 +- .../bbui/src/FancyForm/FancyCheckbox.svelte | 20 +- .../src/FancyForm/FancyCheckboxGroup.svelte | 68 - packages/bbui/src/FancyForm/FancyField.svelte | 15 +- packages/bbui/src/FancyForm/index.js | 1 - packages/bbui/src/Form/Core/Checkbox.svelte | 2 - packages/bbui/src/Modal/Modal.svelte | 3 +- .../builder/src/builderStore/datasource.js | 16 +- .../src/builderStore/store/frontend.js | 1 - .../SetupPanel/AutomationBlockSetup.svelte | 404 +++-- .../PlusConfigForm.svelte | 36 +- .../_components/GoogleButton.svelte | 14 +- .../DatasourceNavigator/icons/index.js | 3 - .../modals/DatasourceConfigModal.svelte | 94 +- .../modals/GoogleDatasourceConfigModal.svelte | 208 +-- .../commandPalette/CommandPalette.svelte | 2 +- .../src/components/deploy/AppActions.svelte | 5 +- .../components/start/ExportAppModal.svelte | 133 +- .../src/helpers/validation/validation.js | 5 +- .../src/helpers/validation/yup/index.js | 64 - .../_components/PreviewOverlay.svelte | 91 -- .../builder/app/[application]/_layout.svelte | 11 +- .../datasource/[datasourceId]/index.svelte | 25 +- .../builder/app/[application]/data/new.svelte | 23 +- .../portal/settings/auth/google.svelte | 235 --- .../builder/portal/settings/auth/index.svelte | 154 +- .../builder/portal/users/users/index.svelte | 2 +- .../builder/src/stores/backend/datasources.js | 6 +- packages/cli/package.json | 2 +- packages/client/src/api/api.js | 10 +- .../client/src/components/ClientApp.svelte | 11 +- .../components/devtools/DevToolsHeader.svelte | 47 +- packages/client/src/index.js | 6 + .../client/src/stores/derived/currentRole.js | 7 +- .../src/stores/derived/devToolsEnabled.js | 10 - packages/client/src/stores/derived/index.js | 1 - packages/client/src/stores/devTools.js | 10 +- packages/frontend-core/src/api/datasources.js | 16 +- packages/pro | 2 +- packages/server/package.json | 6 +- packages/server/src/api/controllers/backup.ts | 30 +- .../server/src/api/controllers/datasource.ts | 65 +- packages/server/src/api/controllers/role.ts | 10 +- .../server/src/api/controllers/routing.ts | 6 +- packages/server/src/api/routes/backup.ts | 2 +- .../src/api/routes/tests/backup.spec.ts | 20 +- .../src/automations/steps/sendSmtpEmail.ts | 59 +- .../automations/tests/sendSmtpEmail.spec.js | 71 + .../automations/tests/sendSmtpEmail.spec.ts | 74 - .../server/src/events/docUpdates/syncUsers.ts | 4 - .../server/src/integrations/googlesheets.ts | 51 +- packages/server/src/integrations/mongodb.ts | 6 +- packages/server/src/integrations/postgres.ts | 24 +- packages/server/src/middleware/currentapp.ts | 2 +- .../server/src/sdk/app/backups/exports.ts | 38 +- .../server/src/sdk/app/backups/imports.ts | 22 +- .../src/sdk/app/datasources/datasources.ts | 1 - .../server/src/utilities/workerRequests.ts | 29 +- packages/shared-core/src/utils.ts | 39 - packages/types/src/api/web/app/datasource.ts | 1 - .../types/src/documents/app/automation.ts | 30 - packages/worker/package.json | 1 - .../worker/src/api/controllers/global/auth.ts | 1 + .../src/api/controllers/global/email.ts | 2 - packages/worker/src/utilities/email.ts | 41 +- qa-core/package.json | 2 +- qa-core/scripts/testResultsWebhook.js | 10 +- .../src/account-api/api/apis/AccountAPI.ts | 12 +- .../validators/mongo.integration.spec.ts | 2 +- .../validators/postgres.integration.spec.ts | 1 - qa-core/src/jest/globalTeardown.ts | 1 - yarn.lock | 1312 +++++++++-------- 76 files changed, 1423 insertions(+), 2500 deletions(-) delete mode 100644 packages/bbui/src/FancyForm/FancyCheckboxGroup.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte delete mode 100644 packages/builder/src/pages/builder/portal/settings/auth/google.svelte delete mode 100644 packages/client/src/stores/derived/devToolsEnabled.js create mode 100644 packages/server/src/automations/tests/sendSmtpEmail.spec.js delete mode 100644 packages/server/src/automations/tests/sendSmtpEmail.spec.ts diff --git a/lerna.json b/lerna.json index 84a4e5507f..e5c8c70105 100644 --- a/lerna.json +++ b/lerna.json @@ -16,6 +16,7 @@ "packages/worker", "packages/pro/packages/pro" ], + "useWorkspaces": true, "command": { "publish": { "ignoreChanges": [ diff --git a/package.json b/package.json index 49ffc5fef7..56f015f8c0 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,10 @@ "husky": "^8.0.3", "js-yaml": "^4.1.0", "kill-port": "^1.6.1", - "lerna": "^7.0.1", + "lerna": "7.0.0-alpha.0", "madge": "^6.0.0", "minimist": "^1.2.8", - "nx": "^16.3.2", + "nx": "^16.2.1", "prettier": "^2.3.1", "prettier-plugin-svelte": "^2.3.0", "rimraf": "^3.0.2", diff --git a/packages/backend-core/src/middleware/passport/datasource/google.ts b/packages/backend-core/src/middleware/passport/datasource/google.ts index ae6b3b4913..6fd4e9ff32 100644 --- a/packages/backend-core/src/middleware/passport/datasource/google.ts +++ b/packages/backend-core/src/middleware/passport/datasource/google.ts @@ -1,11 +1,10 @@ import * as google from "../sso/google" import { Cookie } from "../../../constants" +import { clearCookie, getCookie } from "../../../utils" +import { doWithDB } from "../../../db" import * as configs from "../../../configs" -import * as cache from "../../../cache" -import * as utils from "../../../utils" -import { UserCtx, SSOProfile } from "@budibase/types" +import { BBContext, Database, SSOProfile } from "@budibase/types" import { ssoSaveUserNoOp } from "../sso/sso" - const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy type Passport = { @@ -23,7 +22,7 @@ async function fetchGoogleCreds() { export async function preAuth( passport: Passport, - ctx: UserCtx, + ctx: BBContext, next: Function ) { // get the relevant config @@ -37,8 +36,8 @@ export async function preAuth( ssoSaveUserNoOp ) - if (!ctx.query.appId) { - ctx.throw(400, "appId query param not present.") + if (!ctx.query.appId || !ctx.query.datasourceId) { + ctx.throw(400, "appId and datasourceId query params not present.") } return passport.authenticate(strategy, { @@ -50,7 +49,7 @@ export async function preAuth( export async function postAuth( passport: Passport, - ctx: UserCtx, + ctx: BBContext, next: Function ) { // get the relevant config @@ -58,7 +57,7 @@ export async function postAuth( const platformUrl = await configs.getPlatformUrl({ tenantAware: false }) let callbackUrl = `${platformUrl}/api/global/auth/datasource/google/callback` - const authStateCookie = utils.getCookie(ctx, Cookie.DatasourceAuth) + const authStateCookie = getCookie(ctx, Cookie.DatasourceAuth) return passport.authenticate( new GoogleStrategy( @@ -70,26 +69,33 @@ export async function postAuth( ( accessToken: string, refreshToken: string, - _profile: SSOProfile, + profile: SSOProfile, done: Function ) => { - utils.clearCookie(ctx, Cookie.DatasourceAuth) + clearCookie(ctx, Cookie.DatasourceAuth) done(null, { accessToken, refreshToken }) } ), { successRedirect: "/", failureRedirect: "/error" }, async (err: any, tokens: string[]) => { const baseUrl = `/builder/app/${authStateCookie.appId}/data` - - const id = utils.newid() - await cache.store( - `datasource:creation:${authStateCookie.appId}:google:${id}`, - { - tokens, + // update the DB for the datasource with all the user info + await doWithDB(authStateCookie.appId, async (db: Database) => { + let datasource + try { + datasource = await db.get(authStateCookie.datasourceId) + } catch (err: any) { + if (err.status === 404) { + ctx.redirect(baseUrl) + } } - ) - - ctx.redirect(`${baseUrl}/new?continue_google_setup=${id}`) + if (!datasource.config) { + datasource.config = {} + } + datasource.config.auth = { type: "google", ...tokens } + await db.put(datasource) + ctx.redirect(`${baseUrl}/datasource/${authStateCookie.datasourceId}`) + }) } )(ctx, next) } diff --git a/packages/backend-core/src/security/encryption.ts b/packages/backend-core/src/security/encryption.ts index 7a8cfaf04a..f9adb68955 100644 --- a/packages/backend-core/src/security/encryption.ts +++ b/packages/backend-core/src/security/encryption.ts @@ -1,17 +1,12 @@ import crypto from "crypto" -import fs from "fs" -import zlib from "zlib" import env from "../environment" -import { join } from "path" const ALGO = "aes-256-ctr" const SEPARATOR = "-" const ITERATIONS = 10000 +const RANDOM_BYTES = 16 const STRETCH_LENGTH = 32 -const SALT_LENGTH = 16 -const IV_LENGTH = 16 - export enum SecretOption { API = "api", ENCRYPTION = "encryption", @@ -36,15 +31,15 @@ export function getSecret(secretOption: SecretOption): string { return secret } -function stretchString(secret: string, salt: Buffer) { - return crypto.pbkdf2Sync(secret, salt, ITERATIONS, STRETCH_LENGTH, "sha512") +function stretchString(string: string, salt: Buffer) { + return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512") } export function encrypt( input: string, secretOption: SecretOption = SecretOption.API ) { - const salt = crypto.randomBytes(SALT_LENGTH) + const salt = crypto.randomBytes(RANDOM_BYTES) const stretched = stretchString(getSecret(secretOption), salt) const cipher = crypto.createCipheriv(ALGO, stretched, salt) const base = cipher.update(input) @@ -65,115 +60,3 @@ export function decrypt( const final = decipher.final() return Buffer.concat([base, final]).toString() } - -export async function encryptFile( - { dir, filename }: { dir: string; filename: string }, - secret: string -) { - const outputFileName = `${filename}.enc` - - const filePath = join(dir, filename) - const inputFile = fs.createReadStream(filePath) - const outputFile = fs.createWriteStream(join(dir, outputFileName)) - - const salt = crypto.randomBytes(SALT_LENGTH) - const iv = crypto.randomBytes(IV_LENGTH) - const stretched = stretchString(secret, salt) - const cipher = crypto.createCipheriv(ALGO, stretched, iv) - - outputFile.write(salt) - outputFile.write(iv) - - inputFile.pipe(zlib.createGzip()).pipe(cipher).pipe(outputFile) - - return new Promise<{ filename: string; dir: string }>(r => { - outputFile.on("finish", () => { - r({ - filename: outputFileName, - dir, - }) - }) - }) -} - -async function getSaltAndIV(path: string) { - const fileStream = fs.createReadStream(path) - - const salt = await readBytes(fileStream, SALT_LENGTH) - const iv = await readBytes(fileStream, IV_LENGTH) - fileStream.close() - return { salt, iv } -} - -export async function decryptFile( - inputPath: string, - outputPath: string, - secret: string -) { - const { salt, iv } = await getSaltAndIV(inputPath) - const inputFile = fs.createReadStream(inputPath, { - start: SALT_LENGTH + IV_LENGTH, - }) - - const outputFile = fs.createWriteStream(outputPath) - - const stretched = stretchString(secret, salt) - const decipher = crypto.createDecipheriv(ALGO, stretched, iv) - - const unzip = zlib.createGunzip() - - inputFile.pipe(decipher).pipe(unzip).pipe(outputFile) - - return new Promise((res, rej) => { - outputFile.on("finish", () => { - outputFile.close() - res() - }) - - inputFile.on("error", e => { - outputFile.close() - rej(e) - }) - - decipher.on("error", e => { - outputFile.close() - rej(e) - }) - - unzip.on("error", e => { - outputFile.close() - rej(e) - }) - - outputFile.on("error", e => { - outputFile.close() - rej(e) - }) - }) -} - -function readBytes(stream: fs.ReadStream, length: number) { - return new Promise((resolve, reject) => { - let bytesRead = 0 - const data: Buffer[] = [] - - stream.on("readable", () => { - let chunk - - while ((chunk = stream.read(length - bytesRead)) !== null) { - data.push(chunk) - bytesRead += chunk.length - } - - resolve(Buffer.concat(data)) - }) - - stream.on("end", () => { - reject(new Error("Insufficient data in the stream.")) - }) - - stream.on("error", error => { - reject(error) - }) - }) -} diff --git a/packages/backend-core/src/security/roles.ts b/packages/backend-core/src/security/roles.ts index e8a3c76c0a..bdf7a38726 100644 --- a/packages/backend-core/src/security/roles.ts +++ b/packages/backend-core/src/security/roles.ts @@ -140,13 +140,9 @@ export function lowerBuiltinRoleID(roleId1?: string, roleId2?: string): string { * Gets the role object, this is mainly useful for two purposes, to check if the level exists and * to check if the role inherits any others. * @param {string|null} roleId The level ID to lookup. - * @param {object|null} opts options for the function, like whether to halt errors, instead return public. * @returns {Promise} The role object, which may contain an "inherits" property. */ -export async function getRole( - roleId?: string, - opts?: { defaultPublic?: boolean } -): Promise { +export async function getRole(roleId?: string): Promise { if (!roleId) { return undefined } @@ -165,9 +161,6 @@ export async function getRole( // finalise the ID role._id = getExternalRoleID(role._id) } catch (err) { - if (!isBuiltin(roleId) && opts?.defaultPublic) { - return cloneDeep(BUILTIN_ROLES.PUBLIC) - } // only throw an error if there is no role at all if (Object.keys(role).length === 0) { throw err diff --git a/packages/bbui/src/FancyForm/FancyCheckbox.svelte b/packages/bbui/src/FancyForm/FancyCheckbox.svelte index 0a2e5ac159..191cc79485 100644 --- a/packages/bbui/src/FancyForm/FancyCheckbox.svelte +++ b/packages/bbui/src/FancyForm/FancyCheckbox.svelte @@ -8,8 +8,6 @@ export let disabled = false export let error = null export let validate = null - export let indeterminate = false - export let compact = false const dispatch = createEventDispatcher() @@ -23,19 +21,11 @@ } - + - + -
+
{#if text} {text} {/if} @@ -57,10 +47,6 @@ line-clamp: 2; -webkit-box-orient: vertical; } - .text.compact { - font-size: 13px; - line-height: 15px; - } .text > :global(*) { font-size: inherit !important; } diff --git a/packages/bbui/src/FancyForm/FancyCheckboxGroup.svelte b/packages/bbui/src/FancyForm/FancyCheckboxGroup.svelte deleted file mode 100644 index aaea388c36..0000000000 --- a/packages/bbui/src/FancyForm/FancyCheckboxGroup.svelte +++ /dev/null @@ -1,68 +0,0 @@ - - -{#if options && Array.isArray(options)} -
- - {#if showSelectAll} - - {/if} - {#each options as option, i} - - {/each} - -
-{/if} - - diff --git a/packages/bbui/src/FancyForm/FancyField.svelte b/packages/bbui/src/FancyForm/FancyField.svelte index 455f4b38fb..0c99394599 100644 --- a/packages/bbui/src/FancyForm/FancyField.svelte +++ b/packages/bbui/src/FancyForm/FancyField.svelte @@ -11,7 +11,6 @@ export let value export let ref export let autoHeight - export let compact = false const formContext = getContext("fancy-form") const id = Math.random() @@ -43,7 +42,6 @@ class:disabled class:focused class:clickable - class:compact class:auto-height={autoHeight} >
@@ -63,6 +61,7 @@ diff --git a/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleButton.svelte b/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleButton.svelte index ceb8fd7f4b..b7d70d88b7 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleButton.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/_components/GoogleButton.svelte @@ -3,6 +3,8 @@ import { store } from "builderStore" import { auth } from "stores/portal" + export let preAuthStep + export let datasource export let disabled export let samePage @@ -13,8 +15,18 @@ class:disabled {disabled} on:click={async () => { + let ds = datasource let appId = $store.appId - const url = `/api/global/auth/${tenantId}/datasource/google?appId=${appId}` + if (!ds) { + const resp = await preAuthStep() + if (resp.datasource && resp.appId) { + ds = resp.datasource + appId = resp.appId + } else { + ds = resp + } + } + const url = `/api/global/auth/${tenantId}/datasource/google?datasourceId=${ds._id}&appId=${appId}` if (samePage) { window.location = url } else { diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js b/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js index 2486942dea..18aa361570 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js +++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js @@ -44,9 +44,6 @@ export default ICONS export function getIcon(integrationType, schema) { const integrationList = get(integrations) - if (!integrationList) { - return - } if (integrationList[integrationType]?.iconUrl) { return { url: integrationList[integrationType].iconUrl } } else if (schema?.custom || !ICONS[integrationType]) { diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index 1d84dbbe39..31a0d21cd8 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -1,19 +1,12 @@ nextStep()} - {confirmText} - cancelText={fetchTableStep ? "Cancel" : "Back"} - showSecondaryButton={datasourcePlus} + title={`Connect to ${name}`} + onConfirm={() => saveDatasource()} + confirmText={datasource.plus ? "Connect" : "Save and continue to query"} + cancelText="Back" + showSecondaryButton={datasource.plus} size="L" disabled={!isValid} > - - {#if !fetchTableStep} - Connect your database to Budibase using the config below - {:else} - Choose what tables you want to sync with Budibase - {/if} + Connect your database to Budibase using the config below. - {#if !fetchTableStep} - (isValid = e.detail)} - /> - {:else} -
- -
- {/if} + (isValid = e.detail)} + />
- - diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/GoogleDatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/GoogleDatasourceConfigModal.svelte index 14f81f915c..0783a9fe53 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/GoogleDatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/GoogleDatasourceConfigModal.svelte @@ -1,207 +1,43 @@ - {#if step === GoogleDatasouceConfigStep.AUTH} - - {#if isGoogleConfigured === true} - - Authenticate with your google account to use the {integrationName} integration. - - - {:else if isGoogleConfigured === false} + + {#if isGoogleConfigured === true} + Google authentication is not enabled, please complete Google SSO - configuration.Authenticate with your google account to use the {IntegrationNames[ + datasource.type + ]} integration. - Configure Google SSO - {/if} - {/if} - {#if step === GoogleDatasouceConfigStep.SET_URL} - - Add the URL of the sheet you want to connect. - - (isValid = e.detail)} - /> - - {/if} - {#if step === GoogleDatasouceConfigStep.SET_SHEETS} - - Select which spreadsheets you want to connect. - - - - {#if setSheetsErrorTitle || setSheetsErrorMessage} - - {/if} + save(datasource, true)} /> + {:else if isGoogleConfigured === false} + Google authentication is not enabled, please complete Google SSO + configuration. + Configure Google SSO {/if} diff --git a/packages/builder/src/components/commandPalette/CommandPalette.svelte b/packages/builder/src/components/commandPalette/CommandPalette.svelte index 3a369446a3..ae946dc10c 100644 --- a/packages/builder/src/components/commandPalette/CommandPalette.svelte +++ b/packages/builder/src/components/commandPalette/CommandPalette.svelte @@ -69,7 +69,7 @@ name: "App", description: "", icon: "Play", - action: () => store.update(state => ({ ...state, showPreview: true })), + action: () => window.open(`/${$store.appId}`), }, { type: "Preview", diff --git a/packages/builder/src/components/deploy/AppActions.svelte b/packages/builder/src/components/deploy/AppActions.svelte index a85eb5a154..9813237317 100644 --- a/packages/builder/src/components/deploy/AppActions.svelte +++ b/packages/builder/src/components/deploy/AppActions.svelte @@ -62,10 +62,7 @@ } const previewApp = () => { - store.update(state => ({ - ...state, - showPreview: true, - })) + window.open(`/${application}`) } const viewApp = () => { diff --git a/packages/builder/src/components/start/ExportAppModal.svelte b/packages/builder/src/components/start/ExportAppModal.svelte index 4a69aaef74..948416b192 100644 --- a/packages/builder/src/components/start/ExportAppModal.svelte +++ b/packages/builder/src/components/start/ExportAppModal.svelte @@ -1,128 +1,27 @@ - - {#if currentStep === Step.CONFIG} - - - - - {#if !encypt} - - {/if} - {/if} - {#if currentStep === Step.SET_PASSWORD} - - {/if} + + + Apps can be exported with or without data that is within internal tables - + select this below. + diff --git a/packages/builder/src/helpers/validation/validation.js b/packages/builder/src/helpers/validation/validation.js index f64bf56835..db5dfe4430 100644 --- a/packages/builder/src/helpers/validation/validation.js +++ b/packages/builder/src/helpers/validation/validation.js @@ -6,6 +6,7 @@ export function createValidationStore(initialValue, ...validators) { let touched = false const value = writable(initialValue || "") + const error = derived(value, $v => validate($v, validators)) const touchedStore = derived(value, () => { if (!touched) { touched = true @@ -13,10 +14,6 @@ export function createValidationStore(initialValue, ...validators) { } return touched }) - const error = derived( - [value, touchedStore], - ([$v, $t]) => $t && validate($v, validators) - ) return [value, error, touchedStore] } diff --git a/packages/builder/src/helpers/validation/yup/index.js b/packages/builder/src/helpers/validation/yup/index.js index b5bdf030a5..20ddaebb1a 100644 --- a/packages/builder/src/helpers/validation/yup/index.js +++ b/packages/builder/src/helpers/validation/yup/index.js @@ -5,7 +5,6 @@ import { notifications } from "@budibase/bbui" export const createValidationStore = () => { const DEFAULT = { - values: {}, errors: {}, touched: {}, valid: false, @@ -34,9 +33,6 @@ export const createValidationStore = () => { case "email": propertyValidator = string().email().nullable() break - case "password": - propertyValidator = string().nullable() - break default: propertyValidator = string().nullable() } @@ -45,68 +41,9 @@ export const createValidationStore = () => { propertyValidator = propertyValidator.required() } - // We want to do this after the possible required validation, to prioritise the required error - switch (type) { - case "password": - propertyValidator = propertyValidator.min(8) - break - } - validator[propertyName] = propertyValidator } - const observe = async (propertyName, value) => { - const values = get(validation).values - let fieldIsValid - if (!values.hasOwnProperty(propertyName)) { - // Initial setup - values[propertyName] = value - return - } - - if (value === values[propertyName]) { - return - } - - const obj = object().shape(validator) - try { - validation.update(store => { - store.errors[propertyName] = null - return store - }) - await obj.validateAt(propertyName, { [propertyName]: value }) - fieldIsValid = true - } catch (error) { - const [fieldError] = error.errors - if (fieldError) { - validation.update(store => { - store.errors[propertyName] = capitalise(fieldError) - store.valid = false - return store - }) - } - } - - if (fieldIsValid) { - // Validate the rest of the fields - try { - await obj.validate( - { ...values, [propertyName]: value }, - { abortEarly: false } - ) - validation.update(store => { - store.valid = true - return store - }) - } catch { - validation.update(store => { - store.valid = false - return store - }) - } - } - } - const check = async values => { const obj = object().shape(validator) // clear the previous errors @@ -150,6 +87,5 @@ export const createValidationStore = () => { check, addValidator, addValidatorType, - observe, } } diff --git a/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte b/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte deleted file mode 100644 index d069d1b4c7..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/_components/PreviewOverlay.svelte +++ /dev/null @@ -1,91 +0,0 @@ - - -
-
-
-
- -
-