diff --git a/lerna.json b/lerna.json index 66fa861379..60dcddc4cb 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 5ae380b040..7f8aa6e4c7 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "description": "Budibase backend core libraries used in server and worker", "main": "src/index.js", "author": "Budibase", diff --git a/packages/backend-core/src/security/roles.js b/packages/backend-core/src/security/roles.js index 82bfbd5212..11abc70bdd 100644 --- a/packages/backend-core/src/security/roles.js +++ b/packages/backend-core/src/security/roles.js @@ -146,8 +146,9 @@ exports.getRole = async roleId => { * Simple function to get all the roles based on the top level user role ID. */ async function getAllUserRoles(userRoleId) { - if (!userRoleId) { - return [BUILTIN_IDS.BASIC] + // admins have access to all roles + if (userRoleId === BUILTIN_IDS.ADMIN) { + return exports.getAllRoles() } let currentRole = await exports.getRole(userRoleId) let roles = currentRole ? [currentRole] : [] diff --git a/packages/backend-core/src/utils.js b/packages/backend-core/src/utils.js index 6c71c51b9d..45fb4acd55 100644 --- a/packages/backend-core/src/utils.js +++ b/packages/backend-core/src/utils.js @@ -256,7 +256,7 @@ exports.saveUser = async ( exports.platformLogout = async ({ ctx, userId, keepActiveSession }) => { if (!ctx) throw new Error("Koa context must be supplied to logout.") - const currentSession = this.getCookie(ctx, Cookies.Auth) + const currentSession = exports.getCookie(ctx, Cookies.Auth) let sessions = await getUserSessions(userId) if (keepActiveSession) { @@ -265,8 +265,8 @@ exports.platformLogout = async ({ ctx, userId, keepActiveSession }) => { ) } else { // clear cookies - this.clearCookie(ctx, Cookies.Auth) - this.clearCookie(ctx, Cookies.CurrentApp) + exports.clearCookie(ctx, Cookies.Auth) + exports.clearCookie(ctx, Cookies.CurrentApp) } await invalidateSessions( diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 8422ae5b77..c9e8c8873c 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.0.49-alpha.9", + "version": "1.0.49-alpha.14", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", diff --git a/packages/bbui/src/Table/InternalRenderer.svelte b/packages/bbui/src/Table/InternalRenderer.svelte index 0f894ac853..858d51f128 100644 --- a/packages/bbui/src/Table/InternalRenderer.svelte +++ b/packages/bbui/src/Table/InternalRenderer.svelte @@ -8,10 +8,35 @@ copyToClipboard(value) } - function copyToClipboard(value) { - navigator.clipboard.writeText(value).then(() => { - notifications.success("Copied") + const copyToClipboard = value => { + return new Promise(res => { + if (navigator.clipboard && window.isSecureContext) { + // Try using the clipboard API first + navigator.clipboard.writeText(value).then(res) + } else { + // Fall back to the textarea hack + let textArea = document.createElement("textarea") + textArea.value = value + textArea.style.position = "fixed" + textArea.style.left = "-9999px" + textArea.style.top = "-9999px" + document.body.appendChild(textArea) + textArea.focus() + textArea.select() + document.execCommand("copy") + textArea.remove() + res() + } }) + .then(() => { + notifications.success("Copied to clipboard") + }) + .catch(() => { + notifications.error( + "Failed to copy to clipboard. Check the dev console for the value." + ) + console.warn("Failed to copy the value", value) + }) } diff --git a/packages/builder/package.json b/packages/builder/package.json index 0a21e41ccb..5abbca2e26 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "license": "GPL-3.0", "private": true, "scripts": { @@ -64,10 +64,10 @@ } }, "dependencies": { - "@budibase/bbui": "^1.0.49-alpha.9", - "@budibase/client": "^1.0.49-alpha.9", - "@budibase/frontend-core": "^1.0.49-alpha.9", - "@budibase/string-templates": "^1.0.49-alpha.9", + "@budibase/bbui": "^1.0.49-alpha.14", + "@budibase/client": "^1.0.49-alpha.14", + "@budibase/frontend-core": "^1.0.49-alpha.14", + "@budibase/string-templates": "^1.0.49-alpha.14", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 62bcc30f8f..9ce66db3c0 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -64,6 +64,9 @@ export const getFrontendStore = () => { const store = writable({ ...INITIAL_FRONTEND_STATE }) store.actions = { + reset: () => { + store.set({ ...INITIAL_FRONTEND_STATE }) + }, initialise: async pkg => { const { layouts, screens, application, clientLibPath } = pkg diff --git a/packages/builder/src/pages/builder/app/[application]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/_layout.svelte index 1597de414b..1003936214 100644 --- a/packages/builder/src/pages/builder/app/[application]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_layout.svelte @@ -12,7 +12,7 @@ import Logo from "assets/bb-emblem.svg" import { capitalise } from "helpers" import UpgradeModal from "components/upgrade/UpgradeModal.svelte" - import { onMount } from "svelte" + import { onMount, onDestroy } from "svelte" export let application @@ -73,6 +73,10 @@ hasSynced = true } }) + + onDestroy(() => { + store.actions.reset() + }) {#await promise} diff --git a/packages/cli/package.json b/packages/cli/package.json index 787645e045..5e909b02c6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { diff --git a/packages/cli/yarn.lock b/packages/cli/yarn.lock index b1f55618a0..7019ee169f 100644 --- a/packages/cli/yarn.lock +++ b/packages/cli/yarn.lock @@ -1583,9 +1583,9 @@ simple-concat@^1.0.0: integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== dependencies: decompress-response "^4.2.0" once "^1.3.1" diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 04ffdffa21..1b83577564 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2537,6 +2537,11 @@ "label": "Placeholder", "key": "placeholder" }, + { + "type": "text", + "label": "Default value", + "key": "defaultValue" + }, { "type": "boolean", "label": "Autocomplete", diff --git a/packages/client/package.json b/packages/client/package.json index eed1f65813..04a01f5909 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^1.0.49-alpha.9", - "@budibase/frontend-core": "^1.0.49-alpha.9", - "@budibase/string-templates": "^1.0.49-alpha.9", + "@budibase/bbui": "^1.0.49-alpha.14", + "@budibase/frontend-core": "^1.0.49-alpha.14", + "@budibase/string-templates": "^1.0.49-alpha.14", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/client/src/components/app/forms/RelationshipField.svelte b/packages/client/src/components/app/forms/RelationshipField.svelte index bd8a086dfd..6089939dcd 100644 --- a/packages/client/src/components/app/forms/RelationshipField.svelte +++ b/packages/client/src/components/app/forms/RelationshipField.svelte @@ -12,6 +12,7 @@ export let disabled = false export let validation export let autocomplete = false + export let defaultValue let fieldState let fieldApi @@ -27,6 +28,7 @@ $: singleValue = flatten(fieldState?.value)?.[0] $: multiValue = flatten(fieldState?.value) ?? [] $: component = multiselect ? CoreMultiselect : CoreSelect + $: expandedDefaultValue = expand(defaultValue) const fetchTable = async id => { if (id) { @@ -66,6 +68,16 @@ const multiHandler = e => { fieldApi.setValue(e.detail) } + + const expand = values => { + if (!values) { + return [] + } + if (Array.isArray(values)) { + return values + } + return values.split(",").map(value => value.trim()) + } {#if fieldState} a.url && a.url.toLowerCase() === possibleAppUrl )[0] - if (app && app.appId) { - return app.appId - } else { - return ctx.params.appId - } + const appId = app && app.appId ? app.appId : ctx.params.appId + updateAppId(appId) + return appId } exports.serveBuilder = async function (ctx) { diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index ca7ef24162..7d4ef65994 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -14,7 +14,7 @@ const { dbExists, } = require("@budibase/backend-core/db") const { UserStatus } = require("@budibase/backend-core/constants") -const { getAppDB } = require("@budibase/backend-core/context") +const { getAppDB, doInAppContext } = require("@budibase/backend-core/context") async function rawMetadata() { const db = getAppDB() @@ -105,34 +105,36 @@ exports.syncUser = async function (ctx) { if (!(await dbExists(appId))) { continue } - const db = getAppDB() - const metadataId = generateUserMetadataID(userId) - let metadata - try { - metadata = await db.get(metadataId) - } catch (err) { - if (deleting) { - continue - } - metadata = { - tableId: InternalTables.USER_METADATA, - } - } - // assign the roleId for the metadata doc - if (roleId) { - metadata.roleId = roleId - } - let combined = !deleting - ? combineMetadataAndUser(user, metadata) - : { - ...metadata, - status: UserStatus.INACTIVE, - metadata: BUILTIN_ROLE_IDS.PUBLIC, + await doInAppContext(appId, async () => { + const db = getAppDB() + const metadataId = generateUserMetadataID(userId) + let metadata + try { + metadata = await db.get(metadataId) + } catch (err) { + if (deleting) { + return } - // if its null then there was no updates required - if (combined) { - await db.put(combined) - } + metadata = { + tableId: InternalTables.USER_METADATA, + } + } + // assign the roleId for the metadata doc + if (roleId) { + metadata.roleId = roleId + } + let combined = !deleting + ? combineMetadataAndUser(user, metadata) + : { + ...metadata, + status: UserStatus.INACTIVE, + metadata: BUILTIN_ROLE_IDS.PUBLIC, + } + // if its null then there was no updates required + if (combined) { + await db.put(combined) + } + }) } } ctx.body = { diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 2bcb5753d6..a4220565cf 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -166,15 +166,13 @@ class InternalBuilder { addSorting(query: KnexQuery, json: QueryJson): KnexQuery { let { sort, paginate } = json - if (!sort) { - return query - } const table = json.meta?.table - for (let [key, value] of Object.entries(sort)) { - const direction = value === SortDirection.ASCENDING ? "asc" : "desc" - query = query.orderBy(`${table?.name}.${key}`, direction) - } - if (this.client === SqlClients.MS_SQL && !sort && paginate?.limit) { + if (sort) { + for (let [key, value] of Object.entries(sort)) { + const direction = value === SortDirection.ASCENDING ? "asc" : "desc" + query = query.orderBy(`${table?.name}.${key}`, direction) + } + } else if (this.client === SqlClients.MS_SQL && paginate?.limit) { // @ts-ignore query = query.orderBy(`${table?.name}.${table?.primary[0]}`) } diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index f5ab719813..40b3a81913 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/worker/package.json b/packages/worker/package.json index dc3b29263d..76ebaff106 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "1.0.49-alpha.9", + "version": "1.0.49-alpha.14", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -34,8 +34,8 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "^1.0.49-alpha.9", - "@budibase/string-templates": "^1.0.49-alpha.9", + "@budibase/backend-core": "^1.0.49-alpha.14", + "@budibase/string-templates": "^1.0.49-alpha.14", "@koa/router": "^8.0.0", "@sentry/node": "^6.0.0", "@techpass/passport-openidconnect": "^0.3.0",