diff --git a/lerna.json b/lerna.json index 830d65b92f..670546b6fc 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.20", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index f65c40dea0..273067d8fb 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.20", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -23,7 +23,7 @@ }, "dependencies": { "@budibase/nano": "10.1.1", - "@budibase/types": "2.2.12-alpha.16", + "@budibase/types": "2.2.12-alpha.20", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-cloudfront-sign": "2.2.0", diff --git a/packages/backend-core/src/context/Context.ts b/packages/backend-core/src/context/Context.ts index f0ccdb97a8..02b7713764 100644 --- a/packages/backend-core/src/context/Context.ts +++ b/packages/backend-core/src/context/Context.ts @@ -1,17 +1,14 @@ import { AsyncLocalStorage } from "async_hooks" +import { ContextMap } from "./mainContext" export default class Context { - static storage = new AsyncLocalStorage>() + static storage = new AsyncLocalStorage() - static run(context: Record, func: any) { + static run(context: ContextMap, func: any) { return Context.storage.run(context, () => func()) } - static get(): Record { - return Context.storage.getStore() as Record - } - - static set(context: Record) { - Context.storage.enterWith(context) + static get(): ContextMap { + return Context.storage.getStore() as ContextMap } } diff --git a/packages/backend-core/src/context/mainContext.ts b/packages/backend-core/src/context/mainContext.ts index c44ec4e767..9884d25d5a 100644 --- a/packages/backend-core/src/context/mainContext.ts +++ b/packages/backend-core/src/context/mainContext.ts @@ -16,6 +16,7 @@ export type ContextMap = { tenantId?: string appId?: string identity?: IdentityContext + environmentVariables?: Record } let TEST_APP_ID: string | null = null @@ -75,7 +76,7 @@ export function getTenantIDFromAppID(appId: string) { } } -function updateContext(updates: ContextMap) { +function updateContext(updates: ContextMap): ContextMap { let context: ContextMap try { context = Context.get() @@ -120,15 +121,23 @@ export async function doInTenant( return newContext(updates, task) } -export async function doInAppContext(appId: string, task: any): Promise { - if (!appId) { +export async function doInAppContext( + appId: string | null, + task: any +): Promise { + if (!appId && !env.isTest()) { throw new Error("appId is required") } - const tenantId = getTenantIDFromAppID(appId) - const updates: ContextMap = { appId } - if (tenantId) { - updates.tenantId = tenantId + let updates: ContextMap + if (!appId) { + updates = { appId: "" } + } else { + const tenantId = getTenantIDFromAppID(appId) + updates = { appId } + if (tenantId) { + updates.tenantId = tenantId + } } return newContext(updates, task) } @@ -189,25 +198,25 @@ export const getProdAppId = () => { return conversions.getProdAppID(appId) } -export function updateTenantId(tenantId?: string) { - let context: ContextMap = updateContext({ - tenantId, - }) - Context.set(context) +export function doInEnvironmentContext( + values: Record, + task: any +) { + if (!values) { + throw new Error("Must supply environment variables.") + } + const updates = { + environmentVariables: values, + } + return newContext(updates, task) } -export function updateAppId(appId: string) { - let context: ContextMap = updateContext({ - appId, - }) - try { - Context.set(context) - } catch (err) { - if (env.isTest()) { - TEST_APP_ID = appId - } else { - throw err - } +export function getEnvironmentVariables() { + const context = Context.get() + if (!context.environmentVariables) { + return null + } else { + return context.environmentVariables } } diff --git a/packages/backend-core/src/environment.ts b/packages/backend-core/src/environment.ts index 91556ddcd6..d742ca1cc9 100644 --- a/packages/backend-core/src/environment.ts +++ b/packages/backend-core/src/environment.ts @@ -37,6 +37,7 @@ const environment = { }, JS_BCRYPT: process.env.JS_BCRYPT, JWT_SECRET: process.env.JWT_SECRET, + ENCRYPTION_KEY: process.env.ENCRYPTION_KEY, COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005", COUCH_DB_USERNAME: process.env.COUCH_DB_USER, COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD, diff --git a/packages/backend-core/src/security/encryption.ts b/packages/backend-core/src/security/encryption.ts index c673263202..d0707cb850 100644 --- a/packages/backend-core/src/security/encryption.ts +++ b/packages/backend-core/src/security/encryption.ts @@ -2,19 +2,45 @@ import crypto from "crypto" import env from "../environment" const ALGO = "aes-256-ctr" -const SECRET = env.JWT_SECRET const SEPARATOR = "-" const ITERATIONS = 10000 const RANDOM_BYTES = 16 const STRETCH_LENGTH = 32 +export enum SecretOption { + JWT = "jwt", + ENCRYPTION = "encryption", +} + +function getSecret(secretOption: SecretOption): string { + let secret, secretName + switch (secretOption) { + case SecretOption.ENCRYPTION: + secret = env.ENCRYPTION_KEY + secretName = "ENCRYPTION_KEY" + break + case SecretOption.JWT: + default: + secret = env.JWT_SECRET + secretName = "JWT_SECRET" + break + } + if (!secret) { + throw new Error(`Secret "${secretName}" has not been set in environment.`) + } + return secret +} + function stretchString(string: string, salt: Buffer) { return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512") } -export function encrypt(input: string, secret: string | undefined = SECRET) { +export function encrypt( + input: string, + secretOption: SecretOption = SecretOption.JWT +) { const salt = crypto.randomBytes(RANDOM_BYTES) - const stretched = stretchString(secret!, salt) + const stretched = stretchString(getSecret(secretOption), salt) const cipher = crypto.createCipheriv(ALGO, stretched, salt) const base = cipher.update(input) const final = cipher.final() @@ -22,10 +48,13 @@ export function encrypt(input: string, secret: string | undefined = SECRET) { return `${salt.toString("hex")}${SEPARATOR}${encrypted}` } -export function decrypt(input: string, secret: string | undefined = SECRET) { +export function decrypt( + input: string, + secretOption: SecretOption = SecretOption.JWT +) { const [salt, encrypted] = input.split(SEPARATOR) const saltBuffer = Buffer.from(salt, "hex") - const stretched = stretchString(secret!, saltBuffer) + const stretched = stretchString(getSecret(secretOption), saltBuffer) const decipher = crypto.createDecipheriv(ALGO, stretched, saltBuffer) const base = decipher.update(Buffer.from(encrypted, "hex")) const final = decipher.final() diff --git a/packages/bbui/package.json b/packages/bbui/package.json index fb936c8c2a..ab64320758 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": "2.2.12-alpha.16", + "version": "2.2.12-alpha.20", "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": "2.2.12-alpha.16", + "@budibase/string-templates": "2.2.12-alpha.20", "@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/createScreen.spec.js b/packages/builder/cypress/integration/createScreen.spec.js index c4b237279d..09d8485386 100644 --- a/packages/builder/cypress/integration/createScreen.spec.js +++ b/packages/builder/cypress/integration/createScreen.spec.js @@ -2,7 +2,7 @@ import filterTests from "../support/filterTests" const interact = require('../support/interact') filterTests(["smoke", "all"], () => { - context("Screen Tests", () => { + xcontext("Screen Tests", () => { before(() => { cy.login() cy.createTestApp() @@ -25,7 +25,7 @@ filterTests(["smoke", "all"], () => { it.skip("should delete all screens then create first screen via button", () => { cy.deleteAllScreens() - + cy.contains("Create first screen").click() cy.get(interact.BODY, { timeout: 2000 }).should('contain', '/home') }) @@ -33,7 +33,7 @@ filterTests(["smoke", "all"], () => { it("Should create and filter screens by access level", () => { const accessLevels = ["Basic", "Admin", "Public", "Power"] - for (const access of accessLevels){ + for (const access of accessLevels) { // Create screen with specified access level cy.createScreen(access, access) // Filter by access level and confirm screen visible @@ -46,9 +46,9 @@ filterTests(["smoke", "all"], () => { // Filter by All screens - Confirm all screens visible cy.filterScreensAccessLevel("All screens") cy.get(interact.BODY).should('contain', accessLevels[0]) - .and('contain', accessLevels[1]) - .and('contain', accessLevels[2]) - .and('contain', accessLevels[3]) + .and('contain', accessLevels[1]) + .and('contain', accessLevels[2]) + .and('contain', accessLevels[3]) }) }) }) diff --git a/packages/builder/package.json b/packages/builder/package.json index a0f3052005..6a7071a48d 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.20", "license": "GPL-3.0", "private": true, "scripts": { @@ -71,10 +71,10 @@ } }, "dependencies": { - "@budibase/bbui": "2.2.12-alpha.16", - "@budibase/client": "2.2.12-alpha.16", - "@budibase/frontend-core": "2.2.12-alpha.16", - "@budibase/string-templates": "2.2.12-alpha.16", + "@budibase/bbui": "2.2.12-alpha.20", + "@budibase/client": "2.2.12-alpha.20", + "@budibase/frontend-core": "2.2.12-alpha.20", + "@budibase/string-templates": "2.2.12-alpha.20", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte b/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte index 4defcbafab..ec39cc6d71 100644 --- a/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte +++ b/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte @@ -340,9 +340,7 @@ {:else if isManyToOne && toTable}