From bcf431a476bffe9691824f1561aed5843bff4c04 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 8 Nov 2023 14:43:28 +0000 Subject: [PATCH 01/44] Fix a few svelte bugs with the LinkedRowSelector component to fix adding/editing relationships via a model from the data UI --- .../automation/SetupPanel/RowSelectorTypes.svelte | 2 +- .../components/backend/DataTable/RowFieldControl.svelte | 7 ++++++- .../builder/src/components/common/LinkedRowSelector.svelte | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/components/automation/SetupPanel/RowSelectorTypes.svelte b/packages/builder/src/components/automation/SetupPanel/RowSelectorTypes.svelte index 373d174541..f6cce6182c 100644 --- a/packages/builder/src/components/automation/SetupPanel/RowSelectorTypes.svelte +++ b/packages/builder/src/components/automation/SetupPanel/RowSelectorTypes.svelte @@ -64,7 +64,7 @@ {:else if schema.type === "link"} onChange(e, field)} /> diff --git a/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte b/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte index 61b706e28e..1ec32cb3fd 100644 --- a/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte +++ b/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte @@ -70,7 +70,12 @@ options={meta.constraints.inclusion} /> {:else if type === "link"} - + (value = e.detail)} + /> {:else if type === "longform"} {#if meta.useRichText} diff --git a/packages/builder/src/components/common/LinkedRowSelector.svelte b/packages/builder/src/components/common/LinkedRowSelector.svelte index d357a0a54d..c45b7be195 100644 --- a/packages/builder/src/components/common/LinkedRowSelector.svelte +++ b/packages/builder/src/components/common/LinkedRowSelector.svelte @@ -56,12 +56,12 @@ /> {:else} row._id} sort - on:change={() => dispatch("change", linkedIds)} + on:change /> {/if} From 3d39a2f77b85b56fd0c563e7ddf59ba2d91f44aa Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 09:47:07 +0000 Subject: [PATCH 02/44] Fix relationship filter setting being ignored, and debounce searches --- .../app/forms/RelationshipField.svelte | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/client/src/components/app/forms/RelationshipField.svelte b/packages/client/src/components/app/forms/RelationshipField.svelte index 41a071686e..f047b53a94 100644 --- a/packages/client/src/components/app/forms/RelationshipField.svelte +++ b/packages/client/src/components/app/forms/RelationshipField.svelte @@ -1,6 +1,6 @@
diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js index 3ee0516544..f653259e13 100644 --- a/packages/builder/src/stores/portal/users.js +++ b/packages/builder/src/stores/portal/users.js @@ -3,6 +3,7 @@ import { API } from "api" import { update } from "lodash" import { licensing } from "." import { sdk } from "@budibase/shared-core" +import { Constants } from "@budibase/frontend-core" export function createUsersStore() { const { subscribe, set } = writable({}) @@ -120,12 +121,18 @@ export function createUsersStore() { return await API.removeAppBuilder({ userId, appId }) } - const getUserRole = user => - sdk.users.isAdmin(user) - ? "admin" - : sdk.users.isBuilder(user) - ? "developer" - : "appUser" + const getUserRole = user => { + if (sdk.users.isAdmin(user)) { + return Constants.BudibaseRoles.Admin + } else if (sdk.users.isBuilder(user)) { + return Constants.BudibaseRoles.Developer + } else if (sdk.users.isCreator(user)) { + return Constants.BudibaseRoles.Creator + } else { + return Constants.BudibaseRoles.AppUser + } + } + const refreshUsage = fn => async (...args) => { diff --git a/packages/frontend-core/src/constants.js b/packages/frontend-core/src/constants.js index d8982276f2..b8e047910b 100644 --- a/packages/frontend-core/src/constants.js +++ b/packages/frontend-core/src/constants.js @@ -25,26 +25,26 @@ export const BudibaseRoles = { } export const BudibaseRoleOptionsOld = [ - { label: "Developer", value: BudibaseRoles.Developer }, - { label: "Member", value: BudibaseRoles.AppUser }, - { label: "Admin", value: BudibaseRoles.Admin }, + { + label: "Developer", + value: BudibaseRoles.Developer, + }, ] export const BudibaseRoleOptions = [ - { label: "App user", value: BudibaseRoles.AppUser }, - { label: "Creator", value: BudibaseRoles.Creator }, - { label: "Account admin", value: BudibaseRoles.Admin }, -] - -export const BudibaseRoleOptionsNew = [ { - label: "Admin", - value: "admin", + label: "Account admin", + value: BudibaseRoles.Admin, subtitle: "Has full access to all apps and settings in your account", }, { - label: "Member", - value: "appUser", - subtitle: "Can only view apps they have access to", + label: "Creator", + value: BudibaseRoles.Creator, + subtitle: "Can create and edit apps they have access to", + }, + { + label: "App user", + value: BudibaseRoles.AppUser, + subtitle: "Can only use published apps they have access to", }, ] From 820eeeafe56a22f2041a51830ec6f03b4d712d53 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 14:13:16 +0000 Subject: [PATCH 07/44] Fix button group having no spacing by default --- packages/bbui/src/ButtonGroup/ButtonGroup.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bbui/src/ButtonGroup/ButtonGroup.svelte b/packages/bbui/src/ButtonGroup/ButtonGroup.svelte index 3768fc1954..7c53f642b0 100644 --- a/packages/bbui/src/ButtonGroup/ButtonGroup.svelte +++ b/packages/bbui/src/ButtonGroup/ButtonGroup.svelte @@ -2,7 +2,7 @@ import "@spectrum-css/buttongroup/dist/index-vars.css" export let vertical = false - export let gap = "" + export let gap = "M" $: gapStyle = gap === "L" From 2cac5c9e8c2abf9a9dd62ad8415e17c3e494c31f Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 14:31:27 +0000 Subject: [PATCH 08/44] Remove duplicated constants and add creator option to user import modal --- .../users/users/_components/ImportUsersModal.svelte | 13 +++++++------ packages/frontend-core/src/constants.js | 13 ------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte index 338cc1e7c1..24f0222d14 100644 --- a/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte @@ -11,6 +11,7 @@ import { emailValidator } from "helpers/validation" import { Constants } from "@budibase/frontend-core" import { capitalise } from "helpers" + import { BudibaseRoleOptions } from "@budibase/frontend-core/src/constants" const BYTES_IN_MB = 1000000 const FILE_SIZE_LIMIT = BYTES_IN_MB * 5 @@ -22,13 +23,16 @@ let userEmails = [] let userGroups = [] let usersRole = null - $: invalidEmails = [] + $: invalidEmails = [] $: userCount = $licensing.userCount + userEmails.length $: exceed = licensing.usersLimitExceeded(userCount) - $: importDisabled = !userEmails.length || !validEmails(userEmails) || !usersRole || exceed + $: roleOptions = Constants.BudibaseRoleOptions.map(option => ({ + ...option, + label: `${option.label} - ${option.subtitle}`, + })) const validEmails = userEmails => { if ($admin.cloud && userEmails.length > MAX_USERS_UPLOAD_LIMIT) { @@ -100,10 +104,7 @@ users. Upgrade your plan to add more users
{/if} - + {#if $licensing.groupsEnabled} Date: Thu, 23 Nov 2023 15:29:34 +0000 Subject: [PATCH 09/44] Allow creators to use the builder portal --- packages/shared-core/src/sdk/documents/users.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/shared-core/src/sdk/documents/users.ts b/packages/shared-core/src/sdk/documents/users.ts index ccd88bf854..20b4b64c44 100644 --- a/packages/shared-core/src/sdk/documents/users.ts +++ b/packages/shared-core/src/sdk/documents/users.ts @@ -76,7 +76,11 @@ export function hasBuilderPermissions(user?: User | ContextUser): boolean { if (!user) { return false } - return user.builder?.global || hasAppBuilderPermissions(user) + return ( + user.builder?.global || + hasAppBuilderPermissions(user) || + hasCreatorPermissions(user) + ) } // checks if a user is capable of being an admin From c2c0012013666e66462b611e35162ccf6439d75c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 16:22:16 +0000 Subject: [PATCH 10/44] Add new permission type for creators, update app creation endpoint to allow creators and assign access to new apps --- .../backend-core/src/security/permissions.ts | 1 + .../server/src/api/controllers/application.ts | 9 +++++++++ packages/server/src/api/routes/application.ts | 2 +- packages/server/src/middleware/authorized.ts | 18 +++++++++++++----- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/backend-core/src/security/permissions.ts b/packages/backend-core/src/security/permissions.ts index fe4095d210..98704f16c6 100644 --- a/packages/backend-core/src/security/permissions.ts +++ b/packages/backend-core/src/security/permissions.ts @@ -160,4 +160,5 @@ export function isPermissionLevelHigherThanRead(level: PermissionLevel) { // utility as a lot of things need simply the builder permission export const BUILDER = PermissionType.BUILDER +export const CREATOR = PermissionType.CREATOR export const GLOBAL_BUILDER = PermissionType.GLOBAL_BUILDER diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index 4e4c66858e..0dd4d7ae7a 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -51,6 +51,8 @@ import { import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" import sdk from "../../sdk" import { builderSocket } from "../../websockets" +import * as userSdk from "../../sdk/users" +import { sdk as sharedCoreSDK } from "@budibase/shared-core" // utility function, need to do away with this async function getLayouts() { @@ -394,6 +396,13 @@ async function appPostCreate(ctx: UserCtx, app: App) { } } } + + // If the user is a creator, we need to give them access to the new app + if (sharedCoreSDK.users.hasCreatorPermissions(ctx.user)) { + let user = await users.UserDB.getUser(ctx.user._id!) + user.roles[dbCore.getProdAppID(app.appId)] = roles.BUILTIN_ROLE_IDS.ADMIN + await users.UserDB.save(user) + } } export async function create(ctx: UserCtx) { diff --git a/packages/server/src/api/routes/application.ts b/packages/server/src/api/routes/application.ts index a21d6a2153..babcb1b44b 100644 --- a/packages/server/src/api/routes/application.ts +++ b/packages/server/src/api/routes/application.ts @@ -16,7 +16,7 @@ router ) .post( "/api/applications", - authorized(permissions.GLOBAL_BUILDER), + authorized(permissions.CREATOR), applicationValidator(), controller.create ) diff --git a/packages/server/src/middleware/authorized.ts b/packages/server/src/middleware/authorized.ts index 06d7da9055..cba765a887 100644 --- a/packages/server/src/middleware/authorized.ts +++ b/packages/server/src/middleware/authorized.ts @@ -5,7 +5,7 @@ import { roles, users, } from "@budibase/backend-core" -import { PermissionLevel, PermissionType, Role, UserCtx } from "@budibase/types" +import { PermissionLevel, PermissionType, UserCtx } from "@budibase/types" import builderMiddleware from "./builder" import { isWebhookEndpoint } from "./utils" import { paramResource } from "./resourceId" @@ -31,13 +31,20 @@ const checkAuthorized = async ( ) => { const appId = context.getAppId() const isGlobalBuilderApi = permType === PermissionType.GLOBAL_BUILDER + const isCreatorApi = permType === PermissionType.CREATOR const isBuilderApi = permType === PermissionType.BUILDER - const globalBuilder = users.isGlobalBuilder(ctx.user) - let isBuilder = appId + const isGlobalBuilder = users.isGlobalBuilder(ctx.user) + const isCreator = users.isCreator(ctx.user) + const isBuilder = appId ? users.isBuilder(ctx.user, appId) : users.hasBuilderPermissions(ctx.user) - // check if this is a builder api and the user is not a builder - if ((isGlobalBuilderApi && !globalBuilder) || (isBuilderApi && !isBuilder)) { + + // check api permission type against user + if ( + (isGlobalBuilderApi && !isGlobalBuilder) || + (isCreatorApi && !isCreator) || + (isBuilderApi && !isBuilder) + ) { return ctx.throw(403, "Not Authorized") } @@ -148,6 +155,7 @@ const authorized = // to find API endpoints which are builder focused if ( permType === PermissionType.BUILDER || + permType === PermissionType.CREATOR || permType === PermissionType.GLOBAL_BUILDER ) { await builderMiddleware(ctx) From 24e6b3103d8f982062f63555c25a1646649460d1 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 16:22:42 +0000 Subject: [PATCH 11/44] Add creator permission type --- packages/types/src/sdk/permissions.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/types/src/sdk/permissions.ts b/packages/types/src/sdk/permissions.ts index c855bbd219..638de97f48 100644 --- a/packages/types/src/sdk/permissions.ts +++ b/packages/types/src/sdk/permissions.ts @@ -13,6 +13,7 @@ export enum PermissionType { AUTOMATION = "automation", WEBHOOK = "webhook", BUILDER = "builder", + CREATOR = "creator", GLOBAL_BUILDER = "globalBuilder", QUERY = "query", VIEW = "view", From 7984ecde052386f81d90434a1bd3895bd1193a18 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 16:23:05 +0000 Subject: [PATCH 12/44] Allow creators to see dev portal and use onboarding --- packages/builder/src/pages/builder/portal/_layout.svelte | 2 +- packages/builder/src/pages/builder/portal/apps/_layout.svelte | 2 +- .../src/pages/builder/portal/apps/onboarding/index.svelte | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/_layout.svelte b/packages/builder/src/pages/builder/portal/_layout.svelte index ad172e34ca..aad33f852a 100644 --- a/packages/builder/src/pages/builder/portal/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/_layout.svelte @@ -16,7 +16,7 @@ let activeTab = "Apps" $: $url(), updateActiveTab($menu) - $: isOnboarding = !$apps.length && sdk.users.isGlobalBuilder($auth.user) + $: isOnboarding = !$apps.length && sdk.users.hasBuilderPermissions($auth.user) const updateActiveTab = menu => { for (let entry of menu) { diff --git a/packages/builder/src/pages/builder/portal/apps/_layout.svelte b/packages/builder/src/pages/builder/portal/apps/_layout.svelte index 4067856bfa..38c0274eca 100644 --- a/packages/builder/src/pages/builder/portal/apps/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/apps/_layout.svelte @@ -34,7 +34,7 @@ } // Go to new app page if no apps exists - if (!$apps.length && sdk.users.isGlobalBuilder($auth.user)) { + if (!$apps.length && sdk.users.hasBuilderPermissions($auth.user)) { $redirect("./onboarding") } } catch (error) { diff --git a/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte b/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte index efc9236699..e8d4309dd5 100644 --- a/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte @@ -52,7 +52,7 @@ goToApp() } catch (e) { loading = false - notifications.error("There was a problem creating your app") + notifications.error(e.message || "There was a problem creating your app") } } From ce5d6267cce14e5df9f1c9f7415b3f015e3c18e7 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 23 Nov 2023 17:13:51 +0000 Subject: [PATCH 13/44] Move per creator utils into backend core, allow creators to create apps --- packages/backend-core/src/users/users.ts | 17 +++++++++++++++++ .../src/pages/builder/portal/apps/index.svelte | 2 +- packages/pro | 2 +- .../server/src/api/controllers/application.ts | 6 ++---- packages/shared-core/src/sdk/documents/users.ts | 4 ++++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/backend-core/src/users/users.ts b/packages/backend-core/src/users/users.ts index 6aed45371a..bdc89f1a88 100644 --- a/packages/backend-core/src/users/users.ts +++ b/packages/backend-core/src/users/users.ts @@ -25,6 +25,7 @@ import { import { getGlobalDB } from "../context" import * as context from "../context" import { isCreator } from "./utils" +import { UserDB } from "./db" type GetOpts = { cleanup?: boolean } @@ -336,3 +337,19 @@ export function cleanseUserObject(user: User | ContextUser, base?: User) { } return user } + +export async function addAppBuilder(user: User, appId: string) { + const prodAppId = getProdAppID(appId) + user.builder ??= {} + user.builder.apps ??= [] + user.builder.apps.push(prodAppId) + await UserDB.save(user, { hashPassword: false }) +} + +export async function removeAppBuilder(user: User, appId: string) { + const prodAppId = getProdAppID(appId) + if (user.builder && user.builder.apps?.includes(prodAppId)) { + user.builder.apps = user.builder.apps.filter(id => id !== prodAppId) + } + await UserDB.save(user, { hashPassword: false }) +} diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index 59267f37e7..ad0d3658ea 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -237,7 +237,7 @@ {#if enrichedApps.length}
- {#if $auth.user && sdk.users.isGlobalBuilder($auth.user)} + {#if $auth.user && sdk.users.canCreateApps($auth.user)}
@@ -695,19 +690,16 @@ allowRemove={group.role} allowPublic={false} quiet={true} - allowCreator={true} + allowCreator={group.role === Constants.Roles.CREATOR} on:change={e => { - if (e.detail === Constants.Roles.CREATOR) { - addGroupAppBuilder(group._id) - } else { - onUpdateGroup(group, e.detail) - } + onUpdateGroup(group, e.detail) }} on:remove={() => { onUpdateGroup(group) }} autoWidth align="right" + labelPrefix="Can use as" /> @@ -753,6 +745,7 @@ allowedRoles={user.isAdminOrGlobalBuilder ? [Constants.Roles.CREATOR] : null} + labelPrefix="Can use as" /> @@ -898,7 +891,6 @@ display: flex; flex-direction: column; gap: var(--spacing-s); - width: 400px; } .auth-entity-meta { @@ -927,7 +919,7 @@ .auth-entity, .auth-entity-header { display: grid; - grid-template-columns: 1fr 110px; + grid-template-columns: 1fr 180px; align-items: center; gap: var(--spacing-xl); } @@ -958,7 +950,7 @@ overflow-y: auto; overflow-x: hidden; position: absolute; - width: 400px; + width: 440px; right: 0; height: 100%; box-shadow: 0 0 40px 10px rgba(0, 0, 0, 0.1); From 295965d1d392ad3238aa776c4e0b5eaa979a122e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 15:23:22 +0000 Subject: [PATCH 18/44] Move picker subtitle to below the label --- packages/bbui/src/Form/Core/Picker.svelte | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/bbui/src/Form/Core/Picker.svelte b/packages/bbui/src/Form/Core/Picker.svelte index 6361b345d1..94fbe73cf2 100644 --- a/packages/bbui/src/Form/Core/Picker.svelte +++ b/packages/bbui/src/Form/Core/Picker.svelte @@ -224,13 +224,12 @@ {/if} - {#if getOptionSubtitle(option, idx)} - {getOptionSubtitle(option, idx)} - {/if} - {getOptionLabel(option, idx)} + {#if getOptionSubtitle(option, idx)} + + {getOptionSubtitle(option, idx)} + + {/if} {#if option.tag} @@ -275,10 +274,9 @@ font-size: 12px; line-height: 15px; font-weight: 500; - top: 10px; color: var(--spectrum-global-color-gray-600); display: block; - margin-bottom: var(--spacing-s); + margin-top: var(--spacing-s); } .spectrum-Picker-label.auto-width { From 8ee32b4353234742451aa88185d57d61025e2cb2 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Fri, 24 Nov 2023 15:31:43 +0000 Subject: [PATCH 19/44] Changes to the single image and CouchDB image builds to make them work with new Helm chart changes. --- hosting/couchdb/Dockerfile | 3 +- hosting/couchdb/build-target-paths.sh | 24 --------------- hosting/couchdb/runner.sh | 42 +++++++++++++++++++++++++-- hosting/single/Dockerfile | 2 -- hosting/single/runner.sh | 4 +-- 5 files changed, 43 insertions(+), 32 deletions(-) delete mode 100644 hosting/couchdb/build-target-paths.sh diff --git a/hosting/couchdb/Dockerfile b/hosting/couchdb/Dockerfile index 792856cac7..f83df7038b 100644 --- a/hosting/couchdb/Dockerfile +++ b/hosting/couchdb/Dockerfile @@ -29,7 +29,6 @@ WORKDIR /opt/couchdb ADD couch/vm.args couch/local.ini ./etc/ WORKDIR / -ADD build-target-paths.sh . ADD runner.sh ./bbcouch-runner.sh -RUN chmod +x ./bbcouch-runner.sh /opt/clouseau/bin/clouseau ./build-target-paths.sh +RUN chmod +x ./bbcouch-runner.sh /opt/clouseau/bin/clouseau CMD ["./bbcouch-runner.sh"] diff --git a/hosting/couchdb/build-target-paths.sh b/hosting/couchdb/build-target-paths.sh deleted file mode 100644 index 34227011f4..0000000000 --- a/hosting/couchdb/build-target-paths.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -echo ${TARGETBUILD} > /buildtarget.txt -if [[ "${TARGETBUILD}" = "aas" ]]; then - # Azure AppService uses /home for persistent data & SSH on port 2222 - DATA_DIR="${DATA_DIR:-/home}" - WEBSITES_ENABLE_APP_SERVICE_STORAGE=true - mkdir -p $DATA_DIR/{search,minio,couch} - mkdir -p $DATA_DIR/couch/{dbs,views} - chown -R couchdb:couchdb $DATA_DIR/couch/ - apt update - apt-get install -y openssh-server - echo "root:Docker!" | chpasswd - mkdir -p /tmp - chmod +x /tmp/ssh_setup.sh \ - && (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null) - cp /etc/sshd_config /etc/ssh/sshd_config - /etc/init.d/ssh restart - sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini - sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini -else - sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini - sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini -fi \ No newline at end of file diff --git a/hosting/couchdb/runner.sh b/hosting/couchdb/runner.sh index 4102d2a751..2e4d26122f 100644 --- a/hosting/couchdb/runner.sh +++ b/hosting/couchdb/runner.sh @@ -1,14 +1,52 @@ #!/bin/bash DATA_DIR=${DATA_DIR:-/data} + mkdir -p ${DATA_DIR} mkdir -p ${DATA_DIR}/couch/{dbs,views} mkdir -p ${DATA_DIR}/search chown -R couchdb:couchdb ${DATA_DIR}/couch -/build-target-paths.sh + +echo ${TARGETBUILD} > /buildtarget.txt +if [[ "${TARGETBUILD}" = "aas" ]]; then + # Azure AppService uses /home for persistent data & SSH on port 2222 + DATA_DIR="${DATA_DIR:-/home}" + WEBSITES_ENABLE_APP_SERVICE_STORAGE=true + mkdir -p $DATA_DIR/{search,minio,couch} + mkdir -p $DATA_DIR/couch/{dbs,views} + chown -R couchdb:couchdb $DATA_DIR/couch/ + apt update + apt-get install -y openssh-server + echo "root:Docker!" | chpasswd + mkdir -p /tmp + chmod +x /tmp/ssh_setup.sh \ + && (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null) + cp /etc/sshd_config /etc/ssh/sshd_config + /etc/init.d/ssh restart + sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini +elif [[ "${TARGETBUILD}" = "single" ]]; then + sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini +elif [[ -n $KUBERNETES_SERVICE_HOST ]]; then + # In Kubernetes the directory /opt/couchdb/data has a persistent volume + # mount for storing database data. + sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/couchdb/etc/local.ini + sed -i "s/^-name .*$//g" /opt/couchdb/etc/vm.args +else + sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini +fi + /opt/clouseau/bin/clouseau > /dev/stdout 2>&1 & /docker-entrypoint.sh /opt/couchdb/bin/couchdb & -sleep 10 + +while [[ $(curl -s -w "%{http_code}\n" http://localhost:5984/_up -o /dev/null) -ne 200 ]]; do + echo 'Waiting for CouchDB to start...'; + sleep 5; +done + curl -X PUT http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@localhost:5984/_users curl -X PUT http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@localhost:5984/_replicator sleep infinity \ No newline at end of file diff --git a/hosting/single/Dockerfile b/hosting/single/Dockerfile index ec03a1b5a2..e9ff6c6596 100644 --- a/hosting/single/Dockerfile +++ b/hosting/single/Dockerfile @@ -94,8 +94,6 @@ RUN chmod +x ./healthcheck.sh # For Azure App Service install SSH & point data locations to /home COPY hosting/single/ssh/sshd_config /etc/ COPY hosting/single/ssh/ssh_setup.sh /tmp -RUN /build-target-paths.sh - # setup letsencrypt certificate RUN apt-get install -y certbot python3-certbot-nginx diff --git a/hosting/single/runner.sh b/hosting/single/runner.sh index 87201c95c0..f4b2b5b127 100644 --- a/hosting/single/runner.sh +++ b/hosting/single/runner.sh @@ -22,11 +22,11 @@ declare -a DOCKER_VARS=("APP_PORT" "APPS_URL" "ARCHITECTURE" "BUDIBASE_ENVIRONME # Azure App Service customisations if [[ "${TARGETBUILD}" = "aas" ]]; then - DATA_DIR="${DATA_DIR:-/home}" + export DATA_DIR="${DATA_DIR:-/home}" WEBSITES_ENABLE_APP_SERVICE_STORAGE=true /etc/init.d/ssh start else - DATA_DIR=${DATA_DIR:-/data} + export DATA_DIR=${DATA_DIR:-/data} fi mkdir -p ${DATA_DIR} # Mount NFS or GCP Filestore if env vars exist for it From 302f6f61063ee4e370f99a26cb46408c443017f7 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 15:47:40 +0000 Subject: [PATCH 20/44] Fix footer in fancy select and allow inviting creators from side panel --- .../bbui/src/FancyForm/FancySelect.svelte | 3 + .../_components/BuilderSidePanel.svelte | 68 ++++++++++--------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/packages/bbui/src/FancyForm/FancySelect.svelte b/packages/bbui/src/FancyForm/FancySelect.svelte index e015f51570..14911f10ab 100644 --- a/packages/bbui/src/FancyForm/FancySelect.svelte +++ b/packages/bbui/src/FancyForm/FancySelect.svelte @@ -12,11 +12,13 @@ export let error = null export let validate = null export let options = [] + export let footer = null export let isOptionEnabled = () => true export let getOptionLabel = option => extractProperty(option, "label") export let getOptionValue = option => extractProperty(option, "value") export let getOptionSubtitle = option => extractProperty(option, "subtitle") export let getOptionColour = () => null + const dispatch = createEventDispatcher() let open = false @@ -100,6 +102,7 @@ {error} {disabled} {options} + {footer} {getOptionLabel} {getOptionValue} {getOptionSubtitle} diff --git a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte index adb0c985dc..726b79e23d 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -364,7 +364,10 @@ const payload = [ { email: newUserEmail, - builder: { global: creationRoleType === Constants.BudibaseRoles.Admin }, + builder: { + global: creationRoleType === Constants.BudibaseRoles.Admin, + creator: creationRoleType === Constants.BudibaseRoles.Creator, + }, admin: { global: creationRoleType === Constants.BudibaseRoles.Admin }, }, ] @@ -517,6 +520,18 @@ } return user.role } + + const checkAppAccess = e => { + // Ensure we don't get into an invalid combo of tenant role and app access + if ( + e.detail === Constants.BudibaseRoles.AppUser && + creationAccessType === Constants.Roles.CREATOR + ) { + creationAccessType = Constants.Roles.BASIC + } else if (e.detail === Constants.BudibaseRoles.Admin) { + creationAccessType = Constants.Roles.CREATOR + } + } @@ -802,28 +817,29 @@ option => option.value !== Constants.BudibaseRoles.Admin )} label="Access" + on:change={checkAppAccess} /> - {#if creationRoleType !== Constants.BudibaseRoles.Admin} - - - - {/if} + + + - {#if creationRoleType === Constants.BudibaseRoles.Admin} -
- - Admins will get full access to all apps and settings -
- {/if} - {#if open} -
-
    - {#each options as option, idx} -
  • onPick(getOptionValue(option, idx))} - > - - {getOptionLabel(option, idx)} - - -
  • - {/each} -
-
- {/if} + {#if open} +
+
    + {#each options as option, idx} +
  • onPick(getOptionValue(option, idx))} + > + + {getOptionLabel(option, idx)} + {#if getOptionSubtitle(option, idx)} + + {getOptionSubtitle(option, idx)} + + {/if} + + +
  • + {/each} +
+
+ {/if} diff --git a/packages/bbui/src/Form/InputDropdown.svelte b/packages/bbui/src/Form/InputDropdown.svelte index 93766495b8..54b07cf0d7 100644 --- a/packages/bbui/src/Form/InputDropdown.svelte +++ b/packages/bbui/src/Form/InputDropdown.svelte @@ -43,6 +43,7 @@ {quiet} {autofocus} {options} + isOptionSelected={option => option === dropdownValue} on:change={onChange} on:pick={onPick} on:click diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/AddUserModal.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/AddUserModal.svelte index 0730c31674..346b293235 100644 --- a/packages/builder/src/pages/builder/portal/users/users/_components/AddUserModal.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/_components/AddUserModal.svelte @@ -29,7 +29,6 @@ }, ] $: hasError = userData.find(x => x.error != null) - $: userCount = $licensing.userCount + userData.length $: reached = licensing.usersLimitReached(userCount) $: exceeded = licensing.usersLimitExceeded(userCount) diff --git a/packages/builder/src/pages/builder/portal/users/users/index.svelte b/packages/builder/src/pages/builder/portal/users/users/index.svelte index 744908fd14..50afd0004a 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -191,18 +191,18 @@ for (const user of userData?.users ?? []) { const { email } = user - if ( newUsers.find(x => x.email === email) || currentUserEmails.includes(email) - ) + ) { continue - + } newUsers.push(user) } - if (!newUsers.length) + if (!newUsers.length) { notifications.info("Duplicated! There is no new users to add.") + } return { ...userData, users: newUsers } } @@ -267,7 +267,6 @@ try { await groups.actions.init() groupsLoaded = true - pendingInvites = await users.getInvites() invitesLoaded = true } catch (error) { From 7f17d2f94365e0621e04b41d9d6548d5424652d5 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 16:34:58 +0000 Subject: [PATCH 25/44] Allow creating creator users via users store --- packages/builder/src/stores/portal/users.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js index f653259e13..0e64d7a6cd 100644 --- a/packages/builder/src/stores/portal/users.js +++ b/packages/builder/src/stores/portal/users.js @@ -78,6 +78,9 @@ export function createUsersStore() { case "developer": body.builder = { global: true } break + case "creator": + body.builder = { creator: true, global: false } + break case "admin": body.admin = { global: true } body.builder = { global: true } From bc48661a64638ed59059159dc8cf5ec3f70d1e57 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 16:45:37 +0000 Subject: [PATCH 26/44] Lint and update user app tables to use new copy --- .../pages/builder/portal/users/users/[userId].svelte | 1 + .../users/_components/AppRoleTableRenderer.svelte | 10 +++++++--- .../users/users/_components/ImportUsersModal.svelte | 2 +- .../users/users/_components/RoleTableRenderer.svelte | 6 ------ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/users/users/[userId].svelte b/packages/builder/src/pages/builder/portal/users/users/[userId].svelte index 8bb1ba5452..95e297e409 100644 --- a/packages/builder/src/pages/builder/portal/users/users/[userId].svelte +++ b/packages/builder/src/pages/builder/portal/users/users/[userId].svelte @@ -55,6 +55,7 @@ }, role: { width: "1fr", + displayName: "Access", }, } const customGroupTableRenderers = [ diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/AppRoleTableRenderer.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/AppRoleTableRenderer.svelte index a9f2ca6e08..e0b743cfa2 100644 --- a/packages/builder/src/pages/builder/portal/users/users/_components/AppRoleTableRenderer.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/_components/AppRoleTableRenderer.svelte @@ -14,6 +14,10 @@ } - - {getRoleLabel(value)} - +{#if value === Constants.Roles.CREATOR} + Can edit +{:else} + + Can use as {getRoleLabel(value)} + +{/if} diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte index 24f0222d14..bb03f166b3 100644 --- a/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/_components/ImportUsersModal.svelte @@ -11,11 +11,11 @@ import { emailValidator } from "helpers/validation" import { Constants } from "@budibase/frontend-core" import { capitalise } from "helpers" - import { BudibaseRoleOptions } from "@budibase/frontend-core/src/constants" const BYTES_IN_MB = 1000000 const FILE_SIZE_LIMIT = BYTES_IN_MB * 5 const MAX_USERS_UPLOAD_LIMIT = 1000 + export let createUsersFromCsv let files = [] diff --git a/packages/builder/src/pages/builder/portal/users/users/_components/RoleTableRenderer.svelte b/packages/builder/src/pages/builder/portal/users/users/_components/RoleTableRenderer.svelte index d8abacf00b..936cd12517 100644 --- a/packages/builder/src/pages/builder/portal/users/users/_components/RoleTableRenderer.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/_components/RoleTableRenderer.svelte @@ -4,12 +4,6 @@ export let row - const TooltipMap = { - appUser: "Only has access to assigned apps", - developer: "Access to the app builder", - admin: "Full access", - } - $: role = Constants.BudibaseRoleOptions.find( x => x.value === users.getUserRole(row) ) From 018d42b440bcc6ebfe43bcedf050922cebdf4d97 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 17:05:31 +0000 Subject: [PATCH 27/44] Be explicit when checking if a user is a creator or not when displaying their global role in the user table list and user details page --- packages/builder/src/stores/portal/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js index 0e64d7a6cd..5da5d4038d 100644 --- a/packages/builder/src/stores/portal/users.js +++ b/packages/builder/src/stores/portal/users.js @@ -129,7 +129,7 @@ export function createUsersStore() { return Constants.BudibaseRoles.Admin } else if (sdk.users.isBuilder(user)) { return Constants.BudibaseRoles.Developer - } else if (sdk.users.isCreator(user)) { + } else if (sdk.users.hasCreatorPermissions(user)) { return Constants.BudibaseRoles.Creator } else { return Constants.BudibaseRoles.AppUser From 168e87566294dab7ccbdd65aa403f5b8e8e443cf Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 17:27:22 +0000 Subject: [PATCH 28/44] Persist legacy creator access when promoting to creator --- .../src/pages/builder/portal/users/users/[userId].svelte | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/portal/users/users/[userId].svelte b/packages/builder/src/pages/builder/portal/users/users/[userId].svelte index 95e297e409..368e45d83c 100644 --- a/packages/builder/src/pages/builder/portal/users/users/[userId].svelte +++ b/packages/builder/src/pages/builder/portal/users/users/[userId].svelte @@ -187,7 +187,11 @@ } else if (detail === Constants.BudibaseRoles.Creator) { toggleFlags({ admin: { global: false }, - builder: { global: false, creator: true }, + builder: { + global: false, + creator: true, + apps: user?.builder?.apps || [], + }, }) } } From a8c5f626667434cc9c0ff78324584942510ac34d Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 24 Nov 2023 17:28:06 +0000 Subject: [PATCH 29/44] Fix label for tenant role when inviting users via builder side panel --- .../app/[application]/_components/BuilderSidePanel.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte index 726b79e23d..b937d69fd7 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -816,7 +816,7 @@ : Constants.BudibaseRoleOptions.filter( option => option.value !== Constants.BudibaseRoles.Admin )} - label="Access" + label="Role" on:change={checkAppAccess} /> From 1ae61eb4d668d06bd31b7437c874164a16bb29bb Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Sun, 26 Nov 2023 18:29:51 +0000 Subject: [PATCH 30/44] update pro reference --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 13b15ecb28..5e3d59fc40 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 13b15ecb28a147fe89e55314f7f8dfe837c7bdd1 +Subproject commit 5e3d59fc4060fd44b14b2599269c207753d4e5be From 3180ab76bfa223beddb1403cb3833a364daa9b95 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Mon, 27 Nov 2023 00:54:12 +0000 Subject: [PATCH 31/44] Bump version to 2.13.16 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index faba64ce90..0345af6bcf 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.13.15", + "version": "2.13.16", "npmClient": "yarn", "packages": [ "packages/*" From 1eb5dc73455760d43eca8f641afda2618c2697d3 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 27 Nov 2023 09:18:02 +0000 Subject: [PATCH 32/44] updating master ref --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 5e3d59fc40..618613f357 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 5e3d59fc4060fd44b14b2599269c207753d4e5be +Subproject commit 618613f3575b01f74940d9f58fdb53a9a5b2dc1a From bcaad6c2195423c2e67b1dcb637f67b8f4221f94 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Mon, 27 Nov 2023 09:30:02 +0000 Subject: [PATCH 33/44] Bump version to 2.13.17 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 0345af6bcf..40e167f36c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.13.16", + "version": "2.13.17", "npmClient": "yarn", "packages": [ "packages/*" From a65b29eb880f264fbc4fc78d3468f6109bc7044b Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 27 Nov 2023 18:50:44 +0000 Subject: [PATCH 34/44] banner changes for new pricing, fix for onboarding to prevent flash of UI before onboarding tutorial --- packages/backend-core/src/objectStore/objectStore.ts | 4 ++-- .../src/pages/builder/portal/apps/_layout.svelte | 2 +- .../src/pages/builder/portal/apps/index.svelte | 12 ++++++++++++ packages/pro | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index cdaf19fa55..cfd988f5e0 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -260,12 +260,12 @@ export async function listAllObjects(bucketName: string, path: string) { } /** - * Generate a presigned url with a default TTL of 1 hour + * Generate a presigned url with a default TTL of 1 day */ export function getPresignedUrl( bucketName: string, key: string, - durationSeconds: number = 3600 + durationSeconds: number = 86400 ) { const objectStore = ObjectStore(bucketName, { presigning: true }) const params = { diff --git a/packages/builder/src/pages/builder/portal/apps/_layout.svelte b/packages/builder/src/pages/builder/portal/apps/_layout.svelte index 38c0274eca..8810edca9c 100644 --- a/packages/builder/src/pages/builder/portal/apps/_layout.svelte +++ b/packages/builder/src/pages/builder/portal/apps/_layout.svelte @@ -14,7 +14,7 @@ import PortalSideBar from "./_components/PortalSideBar.svelte" // Don't block loading if we've already hydrated state - let loaded = $apps.length != null + let loaded = !!$apps?.length onMount(async () => { try { diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index ad0d3658ea..fb0ba8bc2e 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -1,5 +1,6 @@