From 5dff2f30173a32cf122b20b96dd40635577c4bd5 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 26 Apr 2023 14:16:36 +0100 Subject: [PATCH 001/171] Added pending users to user portal screen --- .../builder/portal/users/users/index.svelte | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) 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 984ecd46ff..0c69e2c213 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -110,6 +110,27 @@ } }) } + let invitesLoaded = false + let pendingInvites = [] + let parsedInvites = [] + + const invitesToSchema = invites => { + return invites.map(invite => { + const { admin, builder, userGroups, apps } = invite.info + + return { + email: invite.email, + builder, + admin, + userGroups: userGroups, + apps: apps ? [...new Set(Object.keys(apps))] : undefined, + } + }) + } + $: parsedInvites = invitesToSchema(pendingInvites) + $: console.log("parsed invites ", parsedInvites) + // $: console.log(pendingInvites) + $: console.log(enrichedUsers) const updateFetch = email => { fetch.update({ @@ -232,6 +253,9 @@ try { await groups.actions.init() groupsLoaded = true + + pendingInvites = await users.getInvites() + invitesLoaded = true } catch (error) { notifications.error("Error fetching user group data") } @@ -326,6 +350,23 @@ + + + Pending invitations + A list of all pending user invitations + + + + + + From 785b6f50ae7619bf9fcc82389e7635697ae7c399 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 26 Apr 2023 14:53:31 +0100 Subject: [PATCH 002/171] Removed console debugging --- .../builder/src/pages/builder/portal/users/users/index.svelte | 3 --- 1 file changed, 3 deletions(-) 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 0c69e2c213..19beb67773 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -128,9 +128,6 @@ }) } $: parsedInvites = invitesToSchema(pendingInvites) - $: console.log("parsed invites ", parsedInvites) - // $: console.log(pendingInvites) - $: console.log(enrichedUsers) const updateFetch = email => { fetch.update({ From 4f8e293dc9dec147d66de0fb4e0703f52c472346 Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 26 Apr 2023 16:42:27 +0100 Subject: [PATCH 003/171] Refresh pending invites after inviting a new user in the portal user menu --- .../builder/src/pages/builder/portal/users/users/index.svelte | 1 + 1 file changed, 1 insertion(+) 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 19beb67773..ff5ad2356e 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -162,6 +162,7 @@ })) try { inviteUsersResponse = await users.invite(payload) + pendingInvites = await users.getInvites() inviteConfirmationModal.show() } catch (error) { notifications.error("Error inviting user") From 4093516a0db895c684e448ee9b4ae420b972dbb0 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 27 Apr 2023 12:46:40 +0100 Subject: [PATCH 004/171] Initial commit of filter UX behaviour --- .../_components/BuilderSidePanel.svelte | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) 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 9a6d9ea1d3..b31488e492 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,6 +28,10 @@ let inviting = false let searchFocus = false + //Or searching = true? + let filtered = true + $: console.log("filtering enabled ", filtered) + let appInvites = [] let filteredInvites = [] let filteredUsers = [] @@ -52,15 +56,31 @@ } const filterInvites = async query => { - appInvites = await getInvites() - if (!query || query == "") { - filteredInvites = appInvites + if (!prodAppId) { return } - filteredInvites = appInvites.filter(invite => invite.email.includes(query)) + + appInvites = await getInvites() + + //On Focus behaviour + if (!filtered && (!query || query == "")) { + filteredInvites = [...appInvites] + return + } + + filteredInvites = appInvites.filter(invite => { + const inviteInfo = invite.info?.apps + if ((!query || query == "") && inviteInfo && prodAppId) { + return Object.keys(inviteInfo).includes(prodAppId) + } + return invite.email.includes(query) + }) } - $: filterInvites(query) + $: filtered, prodAppId, filterInvites(query) + $: if (searchFocus === true) { + filtered = false + } const usersFetch = fetchData({ API, @@ -351,7 +371,7 @@ onMount(() => { rendered = true - searchFocus = true + // searchFocus = true }) function handleKeyDown(evt) { @@ -417,7 +437,6 @@ autocomplete="off" disabled={inviting} value={query} - autofocus on:input={e => { query = e.target.value.trim() }} @@ -428,16 +447,20 @@ { + if (!filtered) { + filtered = true + } if (!query) { return } query = null userOnboardResponse = null + filtered = true }} > - + @@ -481,6 +504,8 @@
+ + +
{/each} From bb981603174bfc4f79b3e85b0bd703c1bb7965f9 Mon Sep 17 00:00:00 2001 From: Dean Date: Tue, 2 May 2023 14:35:15 +0100 Subject: [PATCH 005/171] On focus search behaviour renders to 100 invites, all groups and the first page of current users --- .../_components/BuilderSidePanel.svelte | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) 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 b31488e492..7341dcd35c 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,9 +28,9 @@ let inviting = false let searchFocus = false - //Or searching = true? - let filtered = true - $: console.log("filtering enabled ", filtered) + // Initially filter entities without app access + // Show all when false + let filterByAppAccess = true let appInvites = [] let filteredInvites = [] @@ -38,7 +38,6 @@ let filteredGroups = [] let selectedGroup let userOnboardResponse = null - let userLimitReachedModal $: queryIsEmail = emailValidator(query) === true @@ -63,8 +62,9 @@ appInvites = await getInvites() //On Focus behaviour - if (!filtered && (!query || query == "")) { - filteredInvites = [...appInvites] + if (!filterByAppAccess && (!query || query == "")) { + filteredInvites = + appInvites.length > 100 ? appInvites.slice(0, 100) : [...appInvites] return } @@ -77,9 +77,9 @@ }) } - $: filtered, prodAppId, filterInvites(query) + $: filterByAppAccess, prodAppId, filterInvites(query) $: if (searchFocus === true) { - filtered = false + filterByAppAccess = false } const usersFetch = fetchData({ @@ -99,9 +99,9 @@ } await usersFetch.update({ query: { - appId: query ? null : prodAppId, + appId: query || !filterByAppAccess ? null : prodAppId, email: query, - paginated: query ? null : false, + paginated: query || !filterByAppAccess ? null : false, }, }) await usersFetch.refresh() @@ -127,7 +127,12 @@ } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) - $: debouncedUpdateFetch(query, $store.builderSidePanel, loaded) + $: debouncedUpdateFetch( + query, + $store.builderSidePanel, + loaded, + filterByAppAccess + ) const updateAppUser = async (user, role) => { if (!prodAppId) { @@ -202,9 +207,10 @@ } const searchGroups = (userGroups, query) => { - let filterGroups = query?.length - ? userGroups - : getAppGroups(userGroups, prodAppId) + let filterGroups = + query?.length || !filterByAppAccess + ? userGroups + : getAppGroups(userGroups, prodAppId) return filterGroups .filter(group => { if (!query?.length) { @@ -234,7 +240,7 @@ } // Adds the 'role' attribute and sets it to the current app. - $: enrichedGroups = getEnrichedGroups($groups) + $: enrichedGroups = getEnrichedGroups($groups, filterByAppAccess) $: filteredGroups = searchGroups(enrichedGroups, query) $: groupUsers = buildGroupUsers(filteredGroups, filteredUsers) $: allUsers = [...filteredUsers, ...groupUsers] @@ -246,7 +252,7 @@ specific roles for the app. */ const buildGroupUsers = (userGroups, filteredUsers) => { - if (query) { + if (query || !filterByAppAccess) { return [] } // Must exclude users who have explicit privileges @@ -371,7 +377,6 @@ onMount(() => { rendered = true - // searchFocus = true }) function handleKeyDown(evt) { @@ -447,20 +452,20 @@ { - if (!filtered) { - filtered = true + if (!filterByAppAccess) { + filterByAppAccess = true } if (!query) { return } query = null userOnboardResponse = null - filtered = true + filterByAppAccess = true }} > - + @@ -581,7 +586,7 @@ {#if filteredUsers?.length}
-
+
Users
Access
From 19ed0ec3f59270c6c7418e0ea7870e9055f1bbbe Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 3 May 2023 11:22:38 +0100 Subject: [PATCH 006/171] Feedback updates and a fix for z-index issue in user side panel --- .../components/backend/DataTable/Table.svelte | 2 ++ .../_components/BuilderSidePanel.svelte | 4 ++-- .../builder/portal/users/users/index.svelte | 22 ++++++++++--------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index 4df6e9a306..460a02a9b1 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -22,6 +22,7 @@ export let rowCount export let disableSorting = false export let customPlaceholder = false + export let allowClickRows const dispatch = createEventDispatcher() @@ -110,6 +111,7 @@ {disableSorting} {customPlaceholder} showAutoColumns={!hideAutocolumns} + {allowClickRows} on:clickrelationship={e => selectRelationship(e.detail)} on:sort > 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 9a6d9ea1d3..be8237f616 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -555,7 +555,7 @@ {#if filteredUsers?.length}
-
+
Users
Access
@@ -696,7 +696,7 @@ max-width: calc(100vw - 40px); background: var(--background); border-left: var(--border-light); - z-index: 3; + z-index: 999; display: flex; flex-direction: column; overflow-y: auto; 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 ff5ad2356e..4053ef5ff3 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -88,6 +88,16 @@ }, } + const getPendingSchema = tblSchema => { + if (!tblSchema) { + return {} + } + let pendingSchema = JSON.parse(JSON.stringify(tblSchema)) + pendingSchema.email.displayName = "Pending Invites" + return pendingSchema + } + + $: pendingSchema = getPendingSchema(schema) $: userData = [] $: inviteUsersResponse = { successful: [], unsuccessful: [] } $: { @@ -346,22 +356,14 @@ goToNextPage={fetch.nextPage} />
- - - - - Pending invitations - A list of all pending user invitations - - -
From 20885a708d56969502c4c4505f95a32f3c8eeabd Mon Sep 17 00:00:00 2001 From: Dean Date: Wed, 3 May 2023 12:23:21 +0100 Subject: [PATCH 007/171] Feedback updates --- .../_components/BuilderSidePanel.svelte | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) 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 7341dcd35c..5b35e65ed9 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,10 +28,6 @@ let inviting = false let searchFocus = false - // Initially filter entities without app access - // Show all when false - let filterByAppAccess = true - let appInvites = [] let filteredInvites = [] let filteredUsers = [] @@ -62,7 +58,7 @@ appInvites = await getInvites() //On Focus behaviour - if (!filterByAppAccess && (!query || query == "")) { + if (searchFocus && !query) { filteredInvites = appInvites.length > 100 ? appInvites.slice(0, 100) : [...appInvites] return @@ -77,10 +73,7 @@ }) } - $: filterByAppAccess, prodAppId, filterInvites(query) - $: if (searchFocus === true) { - filterByAppAccess = false - } + $: searchFocus, prodAppId, filterInvites(query) const usersFetch = fetchData({ API, @@ -99,9 +92,9 @@ } await usersFetch.update({ query: { - appId: query || !filterByAppAccess ? null : prodAppId, + appId: query || searchFocus ? null : prodAppId, email: query, - paginated: query || !filterByAppAccess ? null : false, + paginated: query || searchFocus ? null : false, }, }) await usersFetch.refresh() @@ -127,12 +120,7 @@ } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) - $: debouncedUpdateFetch( - query, - $store.builderSidePanel, - loaded, - filterByAppAccess - ) + $: debouncedUpdateFetch(query, $store.builderSidePanel, loaded, searchFocus) const updateAppUser = async (user, role) => { if (!prodAppId) { @@ -208,7 +196,7 @@ const searchGroups = (userGroups, query) => { let filterGroups = - query?.length || !filterByAppAccess + query?.length || searchFocus ? userGroups : getAppGroups(userGroups, prodAppId) return filterGroups @@ -240,7 +228,7 @@ } // Adds the 'role' attribute and sets it to the current app. - $: enrichedGroups = getEnrichedGroups($groups, filterByAppAccess) + $: enrichedGroups = getEnrichedGroups($groups, searchFocus) $: filteredGroups = searchGroups(enrichedGroups, query) $: groupUsers = buildGroupUsers(filteredGroups, filteredUsers) $: allUsers = [...filteredUsers, ...groupUsers] @@ -252,7 +240,7 @@ specific roles for the app. */ const buildGroupUsers = (userGroups, filteredUsers) => { - if (query || !filterByAppAccess) { + if (query || searchFocus) { return [] } // Must exclude users who have explicit privileges @@ -452,20 +440,19 @@ { - if (!filterByAppAccess) { - filterByAppAccess = true + if (searchFocus) { + searchFocus = false } if (!query) { return } query = null userOnboardResponse = null - filterByAppAccess = true }} > - + @@ -509,8 +496,6 @@
- - -
{/each} From 98963c1505105f2aaf122a25695fe46803de23c5 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 4 May 2023 11:21:24 +0100 Subject: [PATCH 008/171] Fix for inclusion parsing for arrays and options. View table fix to hide edit button --- .../components/backend/DataTable/Table.svelte | 2 ++ .../backend/DataTable/ViewDataTable.svelte | 1 + .../server/src/api/controllers/table/utils.ts | 16 ++++++++++------ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index 4df6e9a306..bf14bdfc0c 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -22,6 +22,7 @@ export let rowCount export let disableSorting = false export let customPlaceholder = false + export let allowEditing = true const dispatch = createEventDispatcher() @@ -109,6 +110,7 @@ {rowCount} {disableSorting} {customPlaceholder} + allowEditRows={allowEditing} showAutoColumns={!hideAutocolumns} on:clickrelationship={e => selectRelationship(e.detail)} on:sort diff --git a/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte b/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte index 056bc33994..d239cabd59 100644 --- a/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte @@ -58,6 +58,7 @@ {loading} {type} rowCount={10} + allowEditing={false} bind:hideAutocolumns > diff --git a/packages/server/src/api/controllers/table/utils.ts b/packages/server/src/api/controllers/table/utils.ts index 1a3eda683b..e57da7ae2d 100644 --- a/packages/server/src/api/controllers/table/utils.ts +++ b/packages/server/src/api/controllers/table/utils.ts @@ -129,17 +129,21 @@ export function importToRows( // the real schema of the table passed in, not the clone used for // incrementing auto IDs for (const [fieldName, schema] of Object.entries(originalTable.schema)) { + const rowVal = Array.isArray(row[fieldName]) ? row[fieldName] : [row[fieldName]] if ( (schema.type === FieldTypes.OPTIONS || - schema.type === FieldTypes.ARRAY) && - row[fieldName] && - (!schema.constraints!.inclusion || - schema.constraints!.inclusion.indexOf(row[fieldName]) === -1) + schema.type === FieldTypes.ARRAY) && + row[fieldName] ) { - schema.constraints!.inclusion = [ + + let merged = [ ...schema.constraints!.inclusion!, - row[fieldName], + ...rowVal ] + + let superSet = new Set(merged); + schema.constraints!.inclusion = Array.from(superSet); + schema.constraints!.inclusion.sort() } } From f8da7a9f2853c2b40cd95c1b59595ba82a8d5225 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 4 May 2023 12:12:47 +0100 Subject: [PATCH 009/171] Linting --- .../server/src/api/controllers/table/utils.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/server/src/api/controllers/table/utils.ts b/packages/server/src/api/controllers/table/utils.ts index e57da7ae2d..5681095df7 100644 --- a/packages/server/src/api/controllers/table/utils.ts +++ b/packages/server/src/api/controllers/table/utils.ts @@ -129,20 +129,18 @@ export function importToRows( // the real schema of the table passed in, not the clone used for // incrementing auto IDs for (const [fieldName, schema] of Object.entries(originalTable.schema)) { - const rowVal = Array.isArray(row[fieldName]) ? row[fieldName] : [row[fieldName]] + const rowVal = Array.isArray(row[fieldName]) + ? row[fieldName] + : [row[fieldName]] if ( (schema.type === FieldTypes.OPTIONS || - schema.type === FieldTypes.ARRAY) && + schema.type === FieldTypes.ARRAY) && row[fieldName] ) { - - let merged = [ - ...schema.constraints!.inclusion!, - ...rowVal - ] - - let superSet = new Set(merged); - schema.constraints!.inclusion = Array.from(superSet); + let merged = [...schema.constraints!.inclusion!, ...rowVal] + + let superSet = new Set(merged) + schema.constraints!.inclusion = Array.from(superSet) schema.constraints!.inclusion.sort() } From 5cf0e57eec977074c1c7e804b56d85ad2465f405 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 4 May 2023 16:01:34 +0100 Subject: [PATCH 010/171] Feedback updates and a fix pass the current query after updating a user invite --- .../_components/BuilderSidePanel.svelte | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) 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 5b35e65ed9..9dce1fdf9b 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -28,6 +28,10 @@ let inviting = false let searchFocus = false + // Initially filter entities without app access + // Show all when false + let filterByAppAccess = true + let appInvites = [] let filteredInvites = [] let filteredUsers = [] @@ -58,7 +62,7 @@ appInvites = await getInvites() //On Focus behaviour - if (searchFocus && !query) { + if (!filterByAppAccess && !query) { filteredInvites = appInvites.length > 100 ? appInvites.slice(0, 100) : [...appInvites] return @@ -66,14 +70,17 @@ filteredInvites = appInvites.filter(invite => { const inviteInfo = invite.info?.apps - if ((!query || query == "") && inviteInfo && prodAppId) { + if (!query && inviteInfo && prodAppId) { return Object.keys(inviteInfo).includes(prodAppId) } return invite.email.includes(query) }) } - $: searchFocus, prodAppId, filterInvites(query) + $: filterByAppAccess, prodAppId, filterInvites(query) + $: if (searchFocus === true) { + filterByAppAccess = false + } const usersFetch = fetchData({ API, @@ -92,9 +99,9 @@ } await usersFetch.update({ query: { - appId: query || searchFocus ? null : prodAppId, + appId: query || !filterByAppAccess ? null : prodAppId, email: query, - paginated: query || searchFocus ? null : false, + paginated: query || !filterByAppAccess ? null : false, }, }) await usersFetch.refresh() @@ -120,7 +127,12 @@ } const debouncedUpdateFetch = Utils.debounce(searchUsers, 250) - $: debouncedUpdateFetch(query, $store.builderSidePanel, loaded, searchFocus) + $: debouncedUpdateFetch( + query, + $store.builderSidePanel, + loaded, + filterByAppAccess + ) const updateAppUser = async (user, role) => { if (!prodAppId) { @@ -196,7 +208,7 @@ const searchGroups = (userGroups, query) => { let filterGroups = - query?.length || searchFocus + query?.length || !filterByAppAccess ? userGroups : getAppGroups(userGroups, prodAppId) return filterGroups @@ -228,7 +240,7 @@ } // Adds the 'role' attribute and sets it to the current app. - $: enrichedGroups = getEnrichedGroups($groups, searchFocus) + $: enrichedGroups = getEnrichedGroups($groups, filterByAppAccess) $: filteredGroups = searchGroups(enrichedGroups, query) $: groupUsers = buildGroupUsers(filteredGroups, filteredUsers) $: allUsers = [...filteredUsers, ...groupUsers] @@ -240,7 +252,7 @@ specific roles for the app. */ const buildGroupUsers = (userGroups, filteredUsers) => { - if (query || searchFocus) { + if (query || !filterByAppAccess) { return [] } // Must exclude users who have explicit privileges @@ -335,12 +347,12 @@ [prodAppId]: role, }, }) - await filterInvites() + await filterInvites(query) } const onUninviteAppUser = async invite => { await uninviteAppUser(invite) - await filterInvites() + await filterInvites(query) } // Purge only the app from the invite or recind the invite if only 1 app remains? @@ -440,19 +452,20 @@ { - if (searchFocus) { - searchFocus = false + if (!filterByAppAccess) { + filterByAppAccess = true } if (!query) { return } query = null userOnboardResponse = null + filterByAppAccess = true }} > - + From 0aeb06bb2b4da2eaaa97b24bab712eb05fad63d1 Mon Sep 17 00:00:00 2001 From: Dean Date: Fri, 5 May 2023 13:39:59 +0100 Subject: [PATCH 011/171] Merge commit --- packages/server/src/api/controllers/table/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/server/src/api/controllers/table/index.ts b/packages/server/src/api/controllers/table/index.ts index bc967a90f4..8e248d57ea 100644 --- a/packages/server/src/api/controllers/table/index.ts +++ b/packages/server/src/api/controllers/table/index.ts @@ -97,6 +97,9 @@ export async function bulkImport(ctx: UserCtx) { // right now we don't trigger anything for bulk import because it // can only be done in the builder, but in the future we may need to // think about events for bulk items + + //const resp = pickApi({ tableId }).save(ctx) + ctx.status = 200 ctx.body = { message: `Bulk rows created.` } } From ce6c5bfa683ad1124ed513b7e4dca6c7982e812c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 5 May 2023 15:47:55 +0100 Subject: [PATCH 012/171] Base connection work - extending the base integration to include the option of a connection check function. --- packages/server/src/integrations/airtable.ts | 10 ++++++++-- packages/server/src/integrations/arangodb.ts | 6 ++++++ packages/server/src/integrations/couchdb.ts | 6 ++++++ packages/server/src/integrations/dynamodb.ts | 2 ++ packages/server/src/integrations/elasticsearch.ts | 2 ++ packages/server/src/integrations/firebase.ts | 2 ++ packages/server/src/integrations/googlesheets.ts | 2 ++ .../server/src/integrations/microsoftSqlServer.ts | 2 ++ packages/server/src/integrations/mongodb.ts | 2 ++ packages/server/src/integrations/mysql.ts | 2 ++ packages/server/src/integrations/oracle.ts | 2 ++ packages/server/src/integrations/postgres.ts | 2 ++ packages/server/src/integrations/redis.ts | 11 +++++++++-- packages/server/src/integrations/s3.ts | 2 ++ packages/server/src/integrations/snowflake.ts | 8 +++++++- packages/types/src/sdk/datasources.ts | 10 ++++++++++ 16 files changed, 66 insertions(+), 5 deletions(-) diff --git a/packages/server/src/integrations/airtable.ts b/packages/server/src/integrations/airtable.ts index 1f56f0619b..58232ad56c 100644 --- a/packages/server/src/integrations/airtable.ts +++ b/packages/server/src/integrations/airtable.ts @@ -1,8 +1,9 @@ import { - Integration, + DatasourceFeature, DatasourceFieldType, - QueryType, + Integration, IntegrationBase, + QueryType, } from "@budibase/types" const Airtable = require("airtable") @@ -18,6 +19,7 @@ const SCHEMA: Integration = { "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.", friendlyName: "Airtable", type: "Spreadsheet", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { apiKey: { type: DatasourceFieldType.PASSWORD, @@ -88,6 +90,10 @@ class AirtableIntegration implements IntegrationBase { this.client = new Airtable(config).base(config.base) } + async connection() { + return { connected: true } + } + async create(query: { table: any; json: any }) { const { table, json } = query diff --git a/packages/server/src/integrations/arangodb.ts b/packages/server/src/integrations/arangodb.ts index e28940f36e..3a61193577 100644 --- a/packages/server/src/integrations/arangodb.ts +++ b/packages/server/src/integrations/arangodb.ts @@ -3,6 +3,7 @@ import { DatasourceFieldType, QueryType, IntegrationBase, + DatasourceFeature, } from "@budibase/types" const { Database, aql } = require("arangojs") @@ -21,6 +22,7 @@ const SCHEMA: Integration = { type: "Non-relational", description: "ArangoDB is a scalable open-source multi-model database natively supporting graph, document and search. All supported data models & access patterns can be combined in queries allowing for maximal flexibility. ", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { url: { type: DatasourceFieldType.STRING, @@ -74,6 +76,10 @@ class ArangoDBIntegration implements IntegrationBase { this.client = new Database(newConfig) } + async connection() { + return { connected: true } + } + async read(query: { sql: any }) { try { const result = await this.client.query(query.sql) diff --git a/packages/server/src/integrations/couchdb.ts b/packages/server/src/integrations/couchdb.ts index 257b84ca13..dfb0daa2e8 100644 --- a/packages/server/src/integrations/couchdb.ts +++ b/packages/server/src/integrations/couchdb.ts @@ -1,4 +1,5 @@ import { + DatasourceFeature, DatasourceFieldType, Document, Integration, @@ -18,6 +19,7 @@ const SCHEMA: Integration = { type: "Non-relational", description: "Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { url: { type: DatasourceFieldType.STRING, @@ -69,6 +71,10 @@ class CouchDBIntegration implements IntegrationBase { this.client = dbCore.DatabaseWithConnection(config.database, config.url) } + async connection() { + return { connected: true } + } + async query( command: string, errorMsg: string, diff --git a/packages/server/src/integrations/dynamodb.ts b/packages/server/src/integrations/dynamodb.ts index 28c1c7b52b..c682f355f9 100644 --- a/packages/server/src/integrations/dynamodb.ts +++ b/packages/server/src/integrations/dynamodb.ts @@ -3,6 +3,7 @@ import { DatasourceFieldType, QueryType, IntegrationBase, + DatasourceFeature, } from "@budibase/types" import AWS from "aws-sdk" @@ -22,6 +23,7 @@ const SCHEMA: Integration = { "Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.", friendlyName: "DynamoDB", type: "Non-relational", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { region: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/elasticsearch.ts b/packages/server/src/integrations/elasticsearch.ts index aeba628d30..475ddc0bd1 100644 --- a/packages/server/src/integrations/elasticsearch.ts +++ b/packages/server/src/integrations/elasticsearch.ts @@ -3,6 +3,7 @@ import { DatasourceFieldType, QueryType, IntegrationBase, + DatasourceFeature, } from "@budibase/types" import { Client, ClientOptions } from "@elastic/elasticsearch" @@ -20,6 +21,7 @@ const SCHEMA: Integration = { "Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents.", friendlyName: "ElasticSearch", type: "Non-relational", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { url: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/firebase.ts b/packages/server/src/integrations/firebase.ts index a82b3be782..0646c98eba 100644 --- a/packages/server/src/integrations/firebase.ts +++ b/packages/server/src/integrations/firebase.ts @@ -3,6 +3,7 @@ import { Integration, QueryType, IntegrationBase, + DatasourceFeature, } from "@budibase/types" import { Firestore, WhereFilterOp } from "@google-cloud/firestore" @@ -18,6 +19,7 @@ const SCHEMA: Integration = { type: "Non-relational", description: "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { email: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index 476a6511e9..8884c8de13 100644 --- a/packages/server/src/integrations/googlesheets.ts +++ b/packages/server/src/integrations/googlesheets.ts @@ -1,4 +1,5 @@ import { + DatasourceFeature, DatasourceFieldType, DatasourcePlus, FieldType, @@ -64,6 +65,7 @@ const SCHEMA: Integration = { "Create and collaborate on online spreadsheets in real-time and from any device. ", friendlyName: "Google Sheets", type: "Spreadsheet", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { spreadsheetId: { display: "Google Sheet URL", diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index eb87c1ccf1..b6f360ce32 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -8,6 +8,7 @@ import { QueryType, SqlQuery, DatasourcePlus, + DatasourceFeature, } from "@budibase/types" import { getSqlQuery, @@ -39,6 +40,7 @@ const SCHEMA: Integration = { "Microsoft SQL Server is a relational database management system developed by Microsoft. ", friendlyName: "MS SQL Server", type: "Relational", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { user: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index 38b3891fe4..20ba2acada 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -3,6 +3,7 @@ import { DatasourceFieldType, QueryType, IntegrationBase, + DatasourceFeature, } from "@budibase/types" import { MongoClient, @@ -38,6 +39,7 @@ const getSchema = () => { type: "Non-relational", description: "MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { connectionString: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index 8d984ed402..6083223042 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -7,6 +7,7 @@ import { Table, TableSchema, DatasourcePlus, + DatasourceFeature, } from "@budibase/types" import { getSqlQuery, @@ -41,6 +42,7 @@ const SCHEMA: Integration = { type: "Relational", description: "MySQL Database Service is a fully managed database service to deploy cloud-native applications. ", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { host: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/oracle.ts b/packages/server/src/integrations/oracle.ts index 65e0829905..bbe2189bdc 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -7,6 +7,7 @@ import { SqlQuery, Table, DatasourcePlus, + DatasourceFeature, } from "@budibase/types" import { buildExternalTableId, @@ -53,6 +54,7 @@ const SCHEMA: Integration = { type: "Relational", description: "Oracle Database is an object-relational database management system developed by Oracle Corporation", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { host: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/postgres.ts b/packages/server/src/integrations/postgres.ts index c981c3acc5..a968b71064 100644 --- a/packages/server/src/integrations/postgres.ts +++ b/packages/server/src/integrations/postgres.ts @@ -6,6 +6,7 @@ import { SqlQuery, Table, DatasourcePlus, + DatasourceFeature, } from "@budibase/types" import { getSqlQuery, @@ -50,6 +51,7 @@ const SCHEMA: Integration = { type: "Relational", description: "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { host: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/redis.ts b/packages/server/src/integrations/redis.ts index 73ef2bb55c..f596b6eb0d 100644 --- a/packages/server/src/integrations/redis.ts +++ b/packages/server/src/integrations/redis.ts @@ -1,4 +1,9 @@ -import { DatasourceFieldType, Integration, QueryType } from "@budibase/types" +import { + DatasourceFeature, + DatasourceFieldType, + Integration, + QueryType, +} from "@budibase/types" import Redis from "ioredis" interface RedisConfig { @@ -11,9 +16,11 @@ interface RedisConfig { const SCHEMA: Integration = { docs: "https://redis.io/docs/", - description: "", + description: + "Redis is a caching tool, providing powerful key-value store capabilities.", friendlyName: "Redis", type: "Non-relational", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { host: { type: "string", diff --git a/packages/server/src/integrations/s3.ts b/packages/server/src/integrations/s3.ts index ad3bb09109..cc368760f8 100644 --- a/packages/server/src/integrations/s3.ts +++ b/packages/server/src/integrations/s3.ts @@ -3,6 +3,7 @@ import { QueryType, IntegrationBase, DatasourceFieldType, + DatasourceFeature, } from "@budibase/types" const AWS = require("aws-sdk") @@ -22,6 +23,7 @@ const SCHEMA: Integration = { "Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance.", friendlyName: "Amazon S3", type: "Object store", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { region: { type: "string", diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index db702520f9..877405d447 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -1,4 +1,9 @@ -import { Integration, QueryType, SqlQuery } from "@budibase/types" +import { + DatasourceFeature, + Integration, + QueryType, + SqlQuery, +} from "@budibase/types" import { Snowflake } from "snowflake-promise" interface SnowflakeConfig { @@ -16,6 +21,7 @@ const SCHEMA: Integration = { "Snowflake is a solution for data warehousing, data lakes, data engineering, data science, data application development, and securely sharing and consuming shared data.", friendlyName: "Snowflake", type: "Relational", + features: [DatasourceFeature.CONNECTION_CHECKING], datasource: { account: { type: "string", diff --git a/packages/types/src/sdk/datasources.ts b/packages/types/src/sdk/datasources.ts index 605b431d9e..ccd6f7b9c6 100644 --- a/packages/types/src/sdk/datasources.ts +++ b/packages/types/src/sdk/datasources.ts @@ -74,6 +74,10 @@ export enum FilterType { ONE_OF = "oneOf", } +export enum DatasourceFeature { + CONNECTION_CHECKING = "connection", +} + export interface StepDefinition { key: string template: string @@ -112,6 +116,7 @@ export interface Integration { docs: string plus?: boolean auth?: { type: string } + features?: DatasourceFeature[] relationships?: boolean description: string friendlyName: string @@ -124,11 +129,16 @@ export interface Integration { extra?: ExtraQueryConfig } +export interface ConnectionInformation { + connected: boolean +} + export interface IntegrationBase { create?(query: any): Promise read?(query: any): Promise update?(query: any): Promise delete?(query: any): Promise + connection?(): Promise } export interface DatasourcePlus extends IntegrationBase { From 57a633b926f5fbcedc53e549bd63314a1e8d6870 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 5 May 2023 17:40:39 +0100 Subject: [PATCH 013/171] Implementing main body of connection verification endpoint. --- .../server/src/api/controllers/datasource.ts | 121 +++++++++++------- packages/server/src/api/routes/datasource.ts | 5 + packages/types/src/api/web/app/datasource.ts | 8 ++ 3 files changed, 85 insertions(+), 49 deletions(-) diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts index b61b168980..e6866d528c 100644 --- a/packages/server/src/api/controllers/datasource.ts +++ b/packages/server/src/api/controllers/datasource.ts @@ -18,11 +18,68 @@ import { Row, CreateDatasourceResponse, UpdateDatasourceResponse, - UpdateDatasourceRequest, CreateDatasourceRequest, + VerifyDatasourceRequest, + VerifyDatasourceResponse, + IntegrationBase, + DatasourcePlus, } from "@budibase/types" import sdk from "../../sdk" +function getErrorTables(errors: any, errorType: string) { + return Object.entries(errors) + .filter(entry => entry[1] === errorType) + .map(([name]) => name) +} + +function updateError(error: any, newError: any, tables: string[]) { + if (!error) { + error = "" + } + if (error.length > 0) { + error += "\n" + } + error += `${newError} ${tables.join(", ")}` + return error +} + +async function getConnector( + datasource: Datasource +): Promise { + const Connector = await getIntegration(datasource.source) + datasource = await sdk.datasources.enrich(datasource) + // Connect to the DB and build the schema + return new Connector(datasource.config) +} + +async function buildSchemaHelper(datasource: Datasource) { + const connector = (await getConnector(datasource)) as DatasourcePlus + await connector.buildSchema(datasource._id!, datasource.entities!) + + const errors = connector.schemaErrors + let error = null + if (errors && Object.keys(errors).length > 0) { + const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY) + const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN) + if (noKey.length) { + error = updateError( + error, + "No primary key constraint found for the following:", + noKey + ) + } + if (invalidCol.length) { + const invalidCols = Object.values(InvalidColumns).join(", ") + error = updateError( + error, + `Cannot use columns ${invalidCols} found in following:`, + invalidCol + ) + } + } + return { tables: connector.tables, error } +} + export async function fetch(ctx: UserCtx) { // Get internal tables const db = context.getAppDB() @@ -66,6 +123,20 @@ export async function fetch(ctx: UserCtx) { ctx.body = [bbInternalDb, ...datasources] } +export async function verify( + ctx: UserCtx +) { + const datasource = ctx.request.body.datasource + const connector = (await getConnector(datasource)) as IntegrationBase + if (!connector.connection) { + ctx.throw(400, "Connection information verification not supported") + } + const connectionInfo = await connector.connection() + ctx.body = { + connected: connectionInfo.connected, + } +} + export async function buildSchemaFromDb(ctx: UserCtx) { const db = context.getAppDB() const datasource = await sdk.datasources.get(ctx.params.datasourceId) @@ -311,51 +382,3 @@ export async function query(ctx: UserCtx) { ctx.throw(400, err) } } - -function getErrorTables(errors: any, errorType: string) { - return Object.entries(errors) - .filter(entry => entry[1] === errorType) - .map(([name]) => name) -} - -function updateError(error: any, newError: any, tables: string[]) { - if (!error) { - error = "" - } - if (error.length > 0) { - error += "\n" - } - error += `${newError} ${tables.join(", ")}` - return error -} - -async function buildSchemaHelper(datasource: Datasource) { - const Connector = await getIntegration(datasource.source) - datasource = await sdk.datasources.enrich(datasource) - // Connect to the DB and build the schema - const connector = new Connector(datasource.config) - await connector.buildSchema(datasource._id, datasource.entities) - - const errors = connector.schemaErrors - let error = null - if (errors && Object.keys(errors).length > 0) { - const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY) - const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN) - if (noKey.length) { - error = updateError( - error, - "No primary key constraint found for the following:", - noKey - ) - } - if (invalidCol.length) { - const invalidCols = Object.values(InvalidColumns).join(", ") - error = updateError( - error, - `Cannot use columns ${invalidCols} found in following:`, - invalidCol - ) - } - } - return { tables: connector.tables, error } -} diff --git a/packages/server/src/api/routes/datasource.ts b/packages/server/src/api/routes/datasource.ts index 85929d2180..654fb794e3 100644 --- a/packages/server/src/api/routes/datasource.ts +++ b/packages/server/src/api/routes/datasource.ts @@ -15,6 +15,11 @@ router authorized(permissions.BUILDER), datasourceController.fetch ) + .post( + "/api/datasources/verify", + authorized(permissions.BUILDER), + datasourceController.verify + ) .get( "/api/datasources/:datasourceId", authorized( diff --git a/packages/types/src/api/web/app/datasource.ts b/packages/types/src/api/web/app/datasource.ts index d54259eab5..36e081d9f6 100644 --- a/packages/types/src/api/web/app/datasource.ts +++ b/packages/types/src/api/web/app/datasource.ts @@ -14,6 +14,14 @@ export interface CreateDatasourceRequest { fetchSchema?: boolean } +export interface VerifyDatasourceRequest { + datasource: Datasource +} + +export interface VerifyDatasourceResponse { + connected: boolean +} + export interface UpdateDatasourceRequest extends Datasource { datasource: Datasource } From 80d3b99b90dba2d1e7b4c3bd16a573c63b814f78 Mon Sep 17 00:00:00 2001 From: jvcalderon Date: Mon, 8 May 2023 13:26:00 +0200 Subject: [PATCH 014/171] Provide some functions to check the path in the context --- .../src/utils/tests/utils.spec.ts | 77 +++++++++++++++++++ packages/backend-core/src/utils/utils.ts | 19 ++++- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/packages/backend-core/src/utils/tests/utils.spec.ts b/packages/backend-core/src/utils/tests/utils.spec.ts index ededa48628..bea0bfa52b 100644 --- a/packages/backend-core/src/utils/tests/utils.spec.ts +++ b/packages/backend-core/src/utils/tests/utils.spec.ts @@ -5,6 +5,8 @@ import * as db from "../../db" import { Header } from "../../constants" import { newid } from "../../utils" import env from "../../environment" +import { beforeEach } from "@jest/globals" +import { BBContext } from "@budibase/types" describe("utils", () => { const config = new DBTestConfiguration() @@ -106,4 +108,79 @@ describe("utils", () => { expect(actual).toBe(undefined) }) }) + + describe("isServingBuilder", () => { + let ctx: BBContext + + const expectResult = (result: boolean) => + expect(utils.isServingBuilder(ctx)).toBe(result) + + beforeEach(() => { + ctx = structures.koa.newContext() + }) + + it("returns true if current path is in builder", async () => { + ctx.path = "/builder/app/app_" + expectResult(true) + }) + + it("returns false if current path is not in builder", async () => { + ctx.path = "/builder/app" + expectResult(false) + + ctx.path = "/xx" + expectResult(false) + }) + }) + + describe("isServingBuilderPreview", () => { + let ctx: BBContext + + const expectResult = (result: boolean) => + expect(utils.isServingBuilderPreview(ctx)).toBe(result) + + beforeEach(() => { + ctx = structures.koa.newContext() + }) + + it("returns true if current path is in builder preview", async () => { + ctx.path = "/app/preview/xx" + expectResult(true) + }) + + it("returns false if current path is not in builder preview", async () => { + ctx.path = "/builder" + expectResult(false) + + ctx.path = "/xx" + expectResult(false) + }) + }) + + describe("isPublicAPIRequest", () => { + let ctx: BBContext + + const expectResult = (result: boolean) => + expect(utils.isPublicApiRequest(ctx)).toBe(result) + + beforeEach(() => { + ctx = structures.koa.newContext() + }) + + it("returns true if current path remains to public API", async () => { + ctx.path = "/api/public/v1/invoices" + expectResult(true) + + ctx.path = "/api/public/v1" + expectResult(true) + }) + + it("returns false if current path doesn't remain to public API", async () => { + ctx.path = "/api/public" + expectResult(false) + + ctx.path = "/xx" + expectResult(false) + }) + }) }) diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index 75b098093b..6cbd1fc406 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -1,10 +1,9 @@ -import { getAllApps, queryGlobalView } from "../db" +import { getAllApps } from "../db" import { Header, MAX_VALID_DATE, DocumentType, SEPARATOR, - ViewName, } from "../constants" import env from "../environment" import * as tenancy from "../tenancy" @@ -23,7 +22,9 @@ const APP_PREFIX = DocumentType.APP + SEPARATOR const PROD_APP_PREFIX = "/app/" const BUILDER_PREVIEW_PATH = "/app/preview" -const BUILDER_REFERER_PREFIX = "/builder/app/" +const BUILDER_PREFIX = "/builder" +const BUILDER_REFERER_PREFIX = `${BUILDER_PREFIX}/app/` +const PUBLIC_API_PREFIX = "/api/public/v1" function confirmAppId(possibleAppId: string | undefined) { return possibleAppId && possibleAppId.startsWith(APP_PREFIX) @@ -69,6 +70,18 @@ export function isServingApp(ctx: Ctx) { return false } +export function isServingBuilder(ctx: Ctx): boolean { + return ctx.path.startsWith(BUILDER_REFERER_PREFIX) +} + +export function isServingBuilderPreview(ctx: Ctx): boolean { + return ctx.path.startsWith(BUILDER_PREVIEW_PATH) +} + +export function isPublicApiRequest(ctx: Ctx): boolean { + return ctx.path.startsWith(PUBLIC_API_PREFIX) +} + /** * Given a request tries to find the appId, which can be located in various places * @param {object} ctx The main request body to look through. From d4d1bc03b31324c530b7f589cbd1ec402fdf739f Mon Sep 17 00:00:00 2001 From: jvcalderon Date: Mon, 8 May 2023 13:42:26 +0200 Subject: [PATCH 015/171] Fix ESLint --- packages/backend-core/src/utils/utils.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index 6cbd1fc406..aee672042b 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -1,10 +1,5 @@ import { getAllApps } from "../db" -import { - Header, - MAX_VALID_DATE, - DocumentType, - SEPARATOR, -} from "../constants" +import { Header, MAX_VALID_DATE, DocumentType, SEPARATOR } from "../constants" import env from "../environment" import * as tenancy from "../tenancy" import * as context from "../context" From b387f969d92c7e60cb0902124c56d8591b3f7155 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 8 May 2023 15:59:12 +0100 Subject: [PATCH 016/171] allow passwordless redis --- packages/backend-core/src/environment.ts | 2 +- packages/server/src/api/routes/public/index.ts | 9 ++++++--- yarn.lock | 12 ++++++------ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/backend-core/src/environment.ts b/packages/backend-core/src/environment.ts index 155f09e6d9..72cd1a4af0 100644 --- a/packages/backend-core/src/environment.ts +++ b/packages/backend-core/src/environment.ts @@ -95,7 +95,7 @@ const environment = { GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET, SALT_ROUNDS: process.env.SALT_ROUNDS, REDIS_URL: process.env.REDIS_URL || "localhost:6379", - REDIS_PASSWORD: process.env.REDIS_PASSWORD || "budibase", + REDIS_PASSWORD: process.env.REDIS_PASSWORD, REDIS_CLUSTERED: process.env.REDIS_CLUSTERED, MOCK_REDIS: process.env.MOCK_REDIS, MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, diff --git a/packages/server/src/api/routes/public/index.ts b/packages/server/src/api/routes/public/index.ts index bed798f75b..287f6c11de 100644 --- a/packages/server/src/api/routes/public/index.ts +++ b/packages/server/src/api/routes/public/index.ts @@ -42,13 +42,16 @@ if (!env.isTest()) { host: REDIS_OPTS.host, port: REDIS_OPTS.port, }, - password: - REDIS_OPTS.opts.password || REDIS_OPTS.opts.redisOptions.password, + } + + if (REDIS_OPTS.opts?.password || REDIS_OPTS.opts.redisOptions?.password) { + // @ts-ignore + options.password = REDIS_OPTS.opts.password || REDIS_OPTS.opts.redisOptions.password } if (!env.REDIS_CLUSTERED) { - // Can't set direct redis db in clustered env // @ts-ignore + // Can't set direct redis db in clustered env options.database = 1 } } diff --git a/yarn.lock b/yarn.lock index d293366bb3..4b2bab4ec2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1486,15 +1486,15 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@2.6.6": - version "2.6.6" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.6.6.tgz#337027168d17a44717c2648b3209a0e2daddcf7d" - integrity sha512-RldUn/WjN7eaYRxL4KBufK1yhVIycJOzoncD+BPgRKstuuuYzPultGZcpNsQQiJkAhNR6QXhG+ovvCUiA+AX6g== +"@budibase/pro@2.6.7": + version "2.6.7" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.6.7.tgz#884b33f3a3e3f2e548fd7519d32b40dc98803400" + integrity sha512-f7g+0So7hr7tHHEF28cz550imYpq/CqRNzhMQpUwmzgbdTlOdVej3PWPNK9+MuBlNea3J9b2WQsjS9TkGZfTlA== dependencies: - "@budibase/backend-core" "2.6.6" + "@budibase/backend-core" "2.6.7" "@budibase/shared-core" "2.5.9" "@budibase/string-templates" "2.5.9" - "@budibase/types" "2.6.6" + "@budibase/types" "2.6.7" "@koa/router" "8.0.8" bull "4.10.1" joi "17.6.0" From eb37dacc733642a4b59bdfaafde5abfeeb01ef94 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 8 May 2023 16:23:49 +0100 Subject: [PATCH 017/171] lint --- packages/server/src/api/routes/public/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/server/src/api/routes/public/index.ts b/packages/server/src/api/routes/public/index.ts index 287f6c11de..6852778e68 100644 --- a/packages/server/src/api/routes/public/index.ts +++ b/packages/server/src/api/routes/public/index.ts @@ -46,7 +46,8 @@ if (!env.isTest()) { if (REDIS_OPTS.opts?.password || REDIS_OPTS.opts.redisOptions?.password) { // @ts-ignore - options.password = REDIS_OPTS.opts.password || REDIS_OPTS.opts.redisOptions.password + options.password = + REDIS_OPTS.opts.password || REDIS_OPTS.opts.redisOptions.password } if (!env.REDIS_CLUSTERED) { From 86f0cd8353aefc899f8acdf5f961cd9f6c8315b7 Mon Sep 17 00:00:00 2001 From: Budibase Release Bot <> Date: Mon, 8 May 2023 15:52:34 +0000 Subject: [PATCH 018/171] v2.6.8 --- lerna.json | 2 +- packages/backend-core/package.json | 4 ++-- packages/bbui/package.json | 6 +++--- packages/builder/package.json | 10 +++++----- packages/cli/package.json | 8 ++++---- packages/client/package.json | 12 ++++++------ packages/frontend-core/package.json | 6 +++--- packages/sdk/package.json | 2 +- packages/server/package.json | 12 ++++++------ packages/shared-core/package.json | 4 ++-- packages/string-templates/package.json | 2 +- packages/types/package.json | 2 +- packages/worker/package.json | 8 ++++---- 13 files changed, 39 insertions(+), 39 deletions(-) diff --git a/lerna.json b/lerna.json index 85c77624b8..202e1c6f49 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.6.7", + "version": "2.6.8", "npmClient": "yarn", "useWorkspaces": true, "packages": ["packages/*"], diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 4e186dd705..03dae9feca 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -24,7 +24,7 @@ "dependencies": { "@budibase/nano": "10.1.2", "@budibase/pouchdb-replication-stream": "1.2.10", - "@budibase/types": "^2.6.7", + "@budibase/types": "^2.6.8", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-cloudfront-sign": "2.2.0", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 23a145e7c5..f0fe559705 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.6.7", + "version": "2.6.8", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,8 +38,8 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "1.2.1", - "@budibase/shared-core": "^2.6.7", - "@budibase/string-templates": "^2.6.7", + "@budibase/shared-core": "^2.6.8", + "@budibase/string-templates": "^2.6.8", "@spectrum-css/accordion": "3.0.24", "@spectrum-css/actionbutton": "1.0.1", "@spectrum-css/actiongroup": "1.0.1", diff --git a/packages/builder/package.json b/packages/builder/package.json index b32d660471..1b69c7aaac 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.6.7", + "version": "2.6.8", "license": "GPL-3.0", "private": true, "scripts": { @@ -58,10 +58,10 @@ } }, "dependencies": { - "@budibase/bbui": "^2.6.7", - "@budibase/frontend-core": "^2.6.7", - "@budibase/shared-core": "^2.6.7", - "@budibase/string-templates": "^2.6.7", + "@budibase/bbui": "^2.6.8", + "@budibase/frontend-core": "^2.6.8", + "@budibase/shared-core": "^2.6.8", + "@budibase/string-templates": "^2.6.8", "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/free-brands-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index c80530f716..a28c66fe65 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "dist/index.js", "bin": { @@ -29,9 +29,9 @@ "outputPath": "build" }, "dependencies": { - "@budibase/backend-core": "^2.6.7", - "@budibase/string-templates": "^2.6.7", - "@budibase/types": "^2.6.7", + "@budibase/backend-core": "^2.6.8", + "@budibase/string-templates": "^2.6.8", + "@budibase/types": "^2.6.8", "axios": "0.21.2", "chalk": "4.1.0", "cli-progress": "3.11.2", diff --git a/packages/client/package.json b/packages/client/package.json index c4d3c1b13b..46f365de5d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "2.6.7", + "version": "2.6.8", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,11 +19,11 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "^2.6.7", - "@budibase/frontend-core": "^2.6.7", - "@budibase/shared-core": "^2.6.7", - "@budibase/string-templates": "^2.6.7", - "@budibase/types": "^2.6.7", + "@budibase/bbui": "^2.6.8", + "@budibase/frontend-core": "^2.6.8", + "@budibase/shared-core": "^2.6.8", + "@budibase/string-templates": "^2.6.8", + "@budibase/types": "^2.6.8", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index 6d917cb863..e701687d10 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,13 +1,13 @@ { "name": "@budibase/frontend-core", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase frontend core libraries used in builder and client", "author": "Budibase", "license": "MPL-2.0", "svelte": "src/index.js", "dependencies": { - "@budibase/bbui": "^2.6.7", - "@budibase/shared-core": "^2.6.7", + "@budibase/bbui": "^2.6.8", + "@budibase/shared-core": "^2.6.8", "dayjs": "^1.11.7", "lodash": "^4.17.21", "socket.io-client": "^4.6.1", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 3df72d79fb..5b528a145a 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/sdk", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase Public API SDK", "author": "Budibase", "license": "MPL-2.0", diff --git a/packages/server/package.json b/packages/server/package.json index a8c04bf14e..4e47134947 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -45,12 +45,12 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", - "@budibase/backend-core": "^2.6.7", - "@budibase/client": "^2.6.7", + "@budibase/backend-core": "^2.6.8", + "@budibase/client": "^2.6.8", "@budibase/pro": "2.6.7", - "@budibase/shared-core": "^2.6.7", - "@budibase/string-templates": "^2.6.7", - "@budibase/types": "^2.6.7", + "@budibase/shared-core": "^2.6.8", + "@budibase/string-templates": "^2.6.8", + "@budibase/types": "^2.6.8", "@bull-board/api": "3.7.0", "@bull-board/koa": "3.9.4", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/shared-core/package.json b/packages/shared-core/package.json index e1e4a01f52..68d9824126 100644 --- a/packages/shared-core/package.json +++ b/packages/shared-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/shared-core", - "version": "2.6.7", + "version": "2.6.8", "description": "Shared data utils", "main": "dist/cjs/src/index.js", "types": "dist/mjs/src/index.d.ts", @@ -20,7 +20,7 @@ "dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\"" }, "dependencies": { - "@budibase/types": "^2.6.7" + "@budibase/types": "^2.6.8" }, "devDependencies": { "concurrently": "^7.6.0", diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index a02d13b3b6..105cb98472 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "2.6.7", + "version": "2.6.8", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/types/package.json b/packages/types/package.json index a39114a76d..1e8e46c44d 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/types", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase types", "main": "dist/cjs/index.js", "types": "dist/mjs/index.d.ts", diff --git a/packages/worker/package.json b/packages/worker/package.json index 59e7f18d76..6e44e82649 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "2.6.7", + "version": "2.6.8", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -37,10 +37,10 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "^2.6.7", + "@budibase/backend-core": "^2.6.8", "@budibase/pro": "2.6.7", - "@budibase/string-templates": "^2.6.7", - "@budibase/types": "^2.6.7", + "@budibase/string-templates": "^2.6.8", + "@budibase/types": "^2.6.8", "@koa/router": "8.0.8", "@sentry/node": "6.17.7", "@techpass/passport-openidconnect": "0.3.2", From bd13a2d186819e4159b076c92e23b9852a5e49db Mon Sep 17 00:00:00 2001 From: Budibase Release Bot <> Date: Mon, 8 May 2023 15:54:09 +0000 Subject: [PATCH 019/171] Update pro version to 2.6.8 --- packages/server/package.json | 2 +- packages/worker/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 4e47134947..7be437535e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -47,7 +47,7 @@ "@apidevtools/swagger-parser": "10.0.3", "@budibase/backend-core": "^2.6.8", "@budibase/client": "^2.6.8", - "@budibase/pro": "2.6.7", + "@budibase/pro": "2.6.8", "@budibase/shared-core": "^2.6.8", "@budibase/string-templates": "^2.6.8", "@budibase/types": "^2.6.8", diff --git a/packages/worker/package.json b/packages/worker/package.json index 6e44e82649..ebbe5d62bd 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -38,7 +38,7 @@ "license": "GPL-3.0", "dependencies": { "@budibase/backend-core": "^2.6.8", - "@budibase/pro": "2.6.7", + "@budibase/pro": "2.6.8", "@budibase/string-templates": "^2.6.8", "@budibase/types": "^2.6.8", "@koa/router": "8.0.8", From bbf271961f95cf1d7997eb9d13bb84a8a4d00b23 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 9 May 2023 11:48:49 +0100 Subject: [PATCH 020/171] adding healthcheck to proxy service --- hosting/proxy/nginx.prod.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hosting/proxy/nginx.prod.conf b/hosting/proxy/nginx.prod.conf index dce1a71918..1a4415395b 100644 --- a/hosting/proxy/nginx.prod.conf +++ b/hosting/proxy/nginx.prod.conf @@ -82,6 +82,12 @@ http { set $couchdb ${COUCHDB_UPSTREAM_URL}; set $watchtower ${WATCHTOWER_UPSTREAM_URL}; + location /health { + access_log off; + add_header 'Content-Type' 'application/json'; + return 200 '{ "status": "OK" }'; + } + location /app { proxy_pass $apps; } From d33a06c89c810e0348e44d71084c39a8aa73901a Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 8 May 2023 14:54:43 +0200 Subject: [PATCH 021/171] Send search term to api call --- .../groups/_components/GroupUsers.svelte | 21 +++++++++++++++++-- packages/frontend-core/src/api/groups.js | 7 +++++-- .../frontend-core/src/fetch/GroupUserFetch.js | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte b/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte index 9c18008e44..fbc3dd5ac1 100644 --- a/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte +++ b/packages/builder/src/pages/builder/portal/users/groups/_components/GroupUsers.svelte @@ -1,7 +1,7 @@
- Users {#if !scimEnabled} {:else} {/if} -
-
- +
+ +
Date: Thu, 11 May 2023 08:20:52 +0200 Subject: [PATCH 036/171] Adds account locking if user limit is exceeded --- .../licensing/AccountLockedModal.svelte | 31 +++++++++++++++++++ .../portal/licensing/licensingBanners.js | 15 +++------ .../src/components/start/AppRow.svelte | 11 +++++-- .../src/pages/builder/apps/index.svelte | 2 +- .../pages/builder/portal/apps/index.svelte | 28 ++++++++++++++--- .../users/_components/AddUserModal.svelte | 4 +-- .../users/_components/ImportUsersModal.svelte | 6 ++-- .../builder/portal/users/users/index.svelte | 12 +++---- .../builder/src/stores/portal/licensing.js | 22 ++++++------- 9 files changed, 89 insertions(+), 42 deletions(-) create mode 100644 packages/builder/src/components/portal/licensing/AccountLockedModal.svelte diff --git a/packages/builder/src/components/portal/licensing/AccountLockedModal.svelte b/packages/builder/src/components/portal/licensing/AccountLockedModal.svelte new file mode 100644 index 0000000000..63bb6dcfd9 --- /dev/null +++ b/packages/builder/src/components/portal/licensing/AccountLockedModal.svelte @@ -0,0 +1,31 @@ + + + + + Due to the free plan user limit being exceeded, your account has been + de-activated. Upgrade your plan to re-activate your account. + + diff --git a/packages/builder/src/components/portal/licensing/licensingBanners.js b/packages/builder/src/components/portal/licensing/licensingBanners.js index dafa8cfaed..ea4a1bb946 100644 --- a/packages/builder/src/components/portal/licensing/licensingBanners.js +++ b/packages/builder/src/components/portal/licensing/licensingBanners.js @@ -3,7 +3,6 @@ import { temporalStore } from "builderStore" import { admin, auth, licensing } from "stores/portal" import { get } from "svelte/store" import { BANNER_TYPES } from "@budibase/bbui" -import { capitalise } from "helpers" const oneDayInSeconds = 86400 @@ -146,23 +145,19 @@ const buildUsersAboveLimitBanner = EXPIRY_KEY => { const userLicensing = get(licensing) return { key: EXPIRY_KEY, - type: BANNER_TYPES.WARNING, + type: BANNER_TYPES.NEGATIVE, onChange: () => { defaultCacheFn(EXPIRY_KEY) }, criteria: () => { - return userLicensing.warnUserLimit + return userLicensing.errUserLimit }, - message: `${capitalise( - userLicensing.license.plan.type - )} plan changes - Users will be limited to ${ - userLicensing.userLimit - } users in ${userLicensing.userLimitDays}`, + message: "Your Budibase account is de-activated. Upgrade your plan", ...{ - extraButtonText: "Find out more", + extraButtonText: "View plans", extraButtonAction: () => { defaultCacheFn(ExpiringKeys.LICENSING_USERS_ABOVE_LIMIT_BANNER) - window.location.href = "/builder/portal/users/users" + window.location.href = "https://budibase.com/pricing/" }, }, showCloseButton: true, diff --git a/packages/builder/src/components/start/AppRow.svelte b/packages/builder/src/components/start/AppRow.svelte index 34d083a096..194f897fdc 100644 --- a/packages/builder/src/components/start/AppRow.svelte +++ b/packages/builder/src/components/start/AppRow.svelte @@ -6,6 +6,8 @@ export let app + export let lockedAction + const handleDefaultClick = () => { if (window.innerWidth < 640) { goToOverview() @@ -29,7 +31,7 @@ } -
+
@@ -58,8 +60,11 @@
- - + +
diff --git a/packages/builder/src/pages/builder/apps/index.svelte b/packages/builder/src/pages/builder/apps/index.svelte index 23f4df5bb5..4b77671345 100644 --- a/packages/builder/src/pages/builder/apps/index.svelte +++ b/packages/builder/src/pages/builder/apps/index.svelte @@ -133,7 +133,7 @@ - {#if $licensing.usageMetrics?.dayPasses >= 100} + {#if $licensing.usageMetrics?.dayPasses >= 100 || $licensing.errUserLimit}
spaceman diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index 783cac49d7..edd308f382 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -14,6 +14,7 @@ import Spinner from "components/common/Spinner.svelte" import CreateAppModal from "components/start/CreateAppModal.svelte" import AppLimitModal from "components/portal/licensing/AppLimitModal.svelte" + import AccountLockedModal from "components/portal/licensing/AccountLockedModal.svelte" import { store, automationStore } from "builderStore" import { API } from "api" @@ -28,6 +29,7 @@ let template let creationModal let appLimitModal + let accountLockedModal let creatingApp = false let searchTerm = "" let creatingFromTemplate = false @@ -49,6 +51,10 @@ ) $: automationErrors = getAutomationErrors(enrichedApps) + const usersLimitLockAction = $licensing?.errUserLimit + ? () => accountLockedModal.show() + : null + const enrichApps = (apps, user, sortBy) => { const enrichedApps = apps.map(app => ({ ...app, @@ -189,6 +195,9 @@ creatingFromTemplate = true createAppFromTemplateUrl(initInfo.init_template) } + if (usersLimitLockAction) { + usersLimitLockAction() + } } catch (error) { notifications.error("Error getting init info") } @@ -230,20 +239,30 @@
- {#if $apps?.length > 0} {/if} {#if !$apps?.length} - {/if} @@ -267,7 +286,7 @@
{#each filteredApps as app (app.appId)} - + {/each}
@@ -294,6 +313,7 @@ + diff --git a/packages/bbui/src/FancyForm/FancyField.svelte b/packages/bbui/src/FancyForm/FancyField.svelte index 89f2dec7d0..0c99394599 100644 --- a/packages/bbui/src/FancyForm/FancyField.svelte +++ b/packages/bbui/src/FancyForm/FancyField.svelte @@ -1,7 +1,7 @@ + +
+ + a-happy-budibase-user +
+ "{testimonial.text}" +
+
+
{testimonial.name}
+
{testimonial.role}
+
+
+
+ + diff --git a/packages/frontend-core/src/components/TestimonialPage.svelte b/packages/frontend-core/src/components/TestimonialPage.svelte index bbb61d2276..94983384a8 100644 --- a/packages/frontend-core/src/components/TestimonialPage.svelte +++ b/packages/frontend-core/src/components/TestimonialPage.svelte @@ -1,58 +1,15 @@
{#if enabled} -
- - a-happy-budibase-user -
- "{testimonial.text}" -
-
-
{testimonial.name}
-
{testimonial.role}
-
-
-
+ {/if}
@@ -64,20 +21,4 @@ display: grid; place-items: center; } - .testimonial { - width: 380px; - padding: 40px; - } - .text { - font-size: var(--font-size-l); - font-style: italic; - } - .name { - font-weight: bold; - color: var(--spectrum-global-color-gray-900); - font-size: var(--font-size-l); - } - .company { - color: var(--spectrum-global-color-gray-700); - } diff --git a/packages/frontend-core/src/components/index.js b/packages/frontend-core/src/components/index.js index 2b7033ad8f..88107da535 100644 --- a/packages/frontend-core/src/components/index.js +++ b/packages/frontend-core/src/components/index.js @@ -1,3 +1,4 @@ export { default as SplitPage } from "./SplitPage.svelte" export { default as TestimonialPage } from "./TestimonialPage.svelte" +export { default as Testimonial } from "./Testimonial.svelte" export { Grid } from "./grid" From 00cbe5a2d574a1cdc52b7f72f2af9531430bf59a Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 17 May 2023 10:00:25 +0000 Subject: [PATCH 166/171] Bump version to 2.6.16-alpha.3 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index e56d307592..5253871cbc 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.6.16-alpha.2", + "version": "2.6.16-alpha.3", "npmClient": "yarn", "packages": [ "packages/backend-core", From 79bc2afeca550368f5495e53183c56723080c5aa Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 17 May 2023 12:04:06 +0200 Subject: [PATCH 167/171] Run validators nightly --- .../validators/{arango.spec.ts => arango.nightly.spec.ts} | 0 .../validators/{couch.spec.ts => couch.nightly.spec.ts} | 0 .../validators/{dynamodb.spec.ts => dynamodb.nightly.spec.ts} | 0 .../validators/{elastic.spec.ts => elastic.nightly.spec.ts} | 0 .../validators/{mongo.spec.ts => mongo.nightly.spec.ts} | 0 .../validators/{mssql.spec.ts => mssql.nightly.spec.ts} | 0 .../validators/{mysql.spec.ts => mysql.nightly.spec.ts} | 0 .../validators/{postgres.spec.ts => postgres.nightly.spec.ts} | 0 .../validators/{redis.spec.ts => redis.nightly.spec.ts} | 0 .../integrations/validators/{s3.spec.ts => s3.nightly.spec.ts} | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename qa-core/src/integrations/validators/{arango.spec.ts => arango.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{couch.spec.ts => couch.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{dynamodb.spec.ts => dynamodb.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{elastic.spec.ts => elastic.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{mongo.spec.ts => mongo.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{mssql.spec.ts => mssql.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{mysql.spec.ts => mysql.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{postgres.spec.ts => postgres.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{redis.spec.ts => redis.nightly.spec.ts} (100%) rename qa-core/src/integrations/validators/{s3.spec.ts => s3.nightly.spec.ts} (100%) diff --git a/qa-core/src/integrations/validators/arango.spec.ts b/qa-core/src/integrations/validators/arango.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/arango.spec.ts rename to qa-core/src/integrations/validators/arango.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/couch.spec.ts b/qa-core/src/integrations/validators/couch.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/couch.spec.ts rename to qa-core/src/integrations/validators/couch.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/dynamodb.spec.ts b/qa-core/src/integrations/validators/dynamodb.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/dynamodb.spec.ts rename to qa-core/src/integrations/validators/dynamodb.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/elastic.spec.ts b/qa-core/src/integrations/validators/elastic.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/elastic.spec.ts rename to qa-core/src/integrations/validators/elastic.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/mongo.spec.ts b/qa-core/src/integrations/validators/mongo.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/mongo.spec.ts rename to qa-core/src/integrations/validators/mongo.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/mssql.spec.ts b/qa-core/src/integrations/validators/mssql.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/mssql.spec.ts rename to qa-core/src/integrations/validators/mssql.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/mysql.spec.ts b/qa-core/src/integrations/validators/mysql.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/mysql.spec.ts rename to qa-core/src/integrations/validators/mysql.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/postgres.spec.ts b/qa-core/src/integrations/validators/postgres.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/postgres.spec.ts rename to qa-core/src/integrations/validators/postgres.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/redis.spec.ts b/qa-core/src/integrations/validators/redis.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/redis.spec.ts rename to qa-core/src/integrations/validators/redis.nightly.spec.ts diff --git a/qa-core/src/integrations/validators/s3.spec.ts b/qa-core/src/integrations/validators/s3.nightly.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/s3.spec.ts rename to qa-core/src/integrations/validators/s3.nightly.spec.ts From b2109e6160f1422bc81a3ce246fa8fef1d80cce9 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 17 May 2023 10:20:20 +0000 Subject: [PATCH 168/171] Bump version to 2.6.16-alpha.4 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 5253871cbc..45abc9671f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.6.16-alpha.3", + "version": "2.6.16-alpha.4", "npmClient": "yarn", "packages": [ "packages/backend-core", From eb46037344e512fe1a9614ba01f65c3b669747ee Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 17 May 2023 12:59:20 +0200 Subject: [PATCH 169/171] Rename validator integration tests --- .../{arango.nightly.spec.ts => arango.integration.spec.ts} | 0 .../{couch.nightly.spec.ts => couch.integration.spec.ts} | 0 .../{dynamodb.nightly.spec.ts => dynamodb.integration.spec.ts} | 0 .../{elastic.nightly.spec.ts => elastic.integration.spec.ts} | 0 .../{mongo.nightly.spec.ts => mongo.integration.spec.ts} | 0 .../{mssql.nightly.spec.ts => mssql.integration.spec.ts} | 0 .../{mysql.nightly.spec.ts => mysql.integration.spec.ts} | 0 .../{postgres.nightly.spec.ts => postgres.integration.spec.ts} | 1 - .../{redis.nightly.spec.ts => redis.integration.spec.ts} | 0 .../validators/{s3.nightly.spec.ts => s3.integration.spec.ts} | 0 10 files changed, 1 deletion(-) rename qa-core/src/integrations/validators/{arango.nightly.spec.ts => arango.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{couch.nightly.spec.ts => couch.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{dynamodb.nightly.spec.ts => dynamodb.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{elastic.nightly.spec.ts => elastic.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{mongo.nightly.spec.ts => mongo.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{mssql.nightly.spec.ts => mssql.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{mysql.nightly.spec.ts => mysql.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{postgres.nightly.spec.ts => postgres.integration.spec.ts} (94%) rename qa-core/src/integrations/validators/{redis.nightly.spec.ts => redis.integration.spec.ts} (100%) rename qa-core/src/integrations/validators/{s3.nightly.spec.ts => s3.integration.spec.ts} (100%) diff --git a/qa-core/src/integrations/validators/arango.nightly.spec.ts b/qa-core/src/integrations/validators/arango.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/arango.nightly.spec.ts rename to qa-core/src/integrations/validators/arango.integration.spec.ts diff --git a/qa-core/src/integrations/validators/couch.nightly.spec.ts b/qa-core/src/integrations/validators/couch.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/couch.nightly.spec.ts rename to qa-core/src/integrations/validators/couch.integration.spec.ts diff --git a/qa-core/src/integrations/validators/dynamodb.nightly.spec.ts b/qa-core/src/integrations/validators/dynamodb.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/dynamodb.nightly.spec.ts rename to qa-core/src/integrations/validators/dynamodb.integration.spec.ts diff --git a/qa-core/src/integrations/validators/elastic.nightly.spec.ts b/qa-core/src/integrations/validators/elastic.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/elastic.nightly.spec.ts rename to qa-core/src/integrations/validators/elastic.integration.spec.ts diff --git a/qa-core/src/integrations/validators/mongo.nightly.spec.ts b/qa-core/src/integrations/validators/mongo.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/mongo.nightly.spec.ts rename to qa-core/src/integrations/validators/mongo.integration.spec.ts diff --git a/qa-core/src/integrations/validators/mssql.nightly.spec.ts b/qa-core/src/integrations/validators/mssql.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/mssql.nightly.spec.ts rename to qa-core/src/integrations/validators/mssql.integration.spec.ts diff --git a/qa-core/src/integrations/validators/mysql.nightly.spec.ts b/qa-core/src/integrations/validators/mysql.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/mysql.nightly.spec.ts rename to qa-core/src/integrations/validators/mysql.integration.spec.ts diff --git a/qa-core/src/integrations/validators/postgres.nightly.spec.ts b/qa-core/src/integrations/validators/postgres.integration.spec.ts similarity index 94% rename from qa-core/src/integrations/validators/postgres.nightly.spec.ts rename to qa-core/src/integrations/validators/postgres.integration.spec.ts index 5101cf1d2d..029d929df0 100644 --- a/qa-core/src/integrations/validators/postgres.nightly.spec.ts +++ b/qa-core/src/integrations/validators/postgres.integration.spec.ts @@ -1,5 +1,4 @@ import { GenericContainer } from "testcontainers" -import postgres from "../../../../packages/server/src/integrations/postgres" jest.unmock("pg") diff --git a/qa-core/src/integrations/validators/redis.nightly.spec.ts b/qa-core/src/integrations/validators/redis.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/redis.nightly.spec.ts rename to qa-core/src/integrations/validators/redis.integration.spec.ts diff --git a/qa-core/src/integrations/validators/s3.nightly.spec.ts b/qa-core/src/integrations/validators/s3.integration.spec.ts similarity index 100% rename from qa-core/src/integrations/validators/s3.nightly.spec.ts rename to qa-core/src/integrations/validators/s3.integration.spec.ts From 02fc795d982b3b57129b811f65d8f1ac4332311f Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 17 May 2023 13:00:08 +0200 Subject: [PATCH 170/171] Rename nightly.spec to integration.spec --- qa-core/package.json | 2 +- .../{mariaDB.nightly.spec.ts => mariaDB.integration.spec.ts} | 0 .../{mongoDB.nightly.spec.ts => mongoDB.integration.spec.ts} | 0 ...tgresSQL.nightly.spec.ts => postgresSQL.integration.spec.ts} | 0 .../{restAPI.nightly.spec.ts => restAPI.integration.spec.ts} | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename qa-core/src/internal-api/tests/dataSources/{mariaDB.nightly.spec.ts => mariaDB.integration.spec.ts} (100%) rename qa-core/src/internal-api/tests/dataSources/{mongoDB.nightly.spec.ts => mongoDB.integration.spec.ts} (100%) rename qa-core/src/internal-api/tests/dataSources/{postgresSQL.nightly.spec.ts => postgresSQL.integration.spec.ts} (100%) rename qa-core/src/internal-api/tests/dataSources/{restAPI.nightly.spec.ts => restAPI.integration.spec.ts} (100%) diff --git a/qa-core/package.json b/qa-core/package.json index a6f9537d0f..2cfc8e2865 100644 --- a/qa-core/package.json +++ b/qa-core/package.json @@ -14,7 +14,7 @@ "test:watch": "yarn run test --watch", "test:debug": "DEBUG=1 yarn run test", "test:notify": "node scripts/testResultsWebhook", - "test:smoke": "yarn run test --testPathIgnorePatterns=/.+\\.nightly\\.spec\\.ts", + "test:smoke": "yarn run test --testPathIgnorePatterns=/.+\\.integration\\.spec\\.ts", "test:ci": "start-server-and-test dev:built http://localhost:4001/health test:smoke", "dev:built": "cd ../ && yarn dev:built" }, diff --git a/qa-core/src/internal-api/tests/dataSources/mariaDB.nightly.spec.ts b/qa-core/src/internal-api/tests/dataSources/mariaDB.integration.spec.ts similarity index 100% rename from qa-core/src/internal-api/tests/dataSources/mariaDB.nightly.spec.ts rename to qa-core/src/internal-api/tests/dataSources/mariaDB.integration.spec.ts diff --git a/qa-core/src/internal-api/tests/dataSources/mongoDB.nightly.spec.ts b/qa-core/src/internal-api/tests/dataSources/mongoDB.integration.spec.ts similarity index 100% rename from qa-core/src/internal-api/tests/dataSources/mongoDB.nightly.spec.ts rename to qa-core/src/internal-api/tests/dataSources/mongoDB.integration.spec.ts diff --git a/qa-core/src/internal-api/tests/dataSources/postgresSQL.nightly.spec.ts b/qa-core/src/internal-api/tests/dataSources/postgresSQL.integration.spec.ts similarity index 100% rename from qa-core/src/internal-api/tests/dataSources/postgresSQL.nightly.spec.ts rename to qa-core/src/internal-api/tests/dataSources/postgresSQL.integration.spec.ts diff --git a/qa-core/src/internal-api/tests/dataSources/restAPI.nightly.spec.ts b/qa-core/src/internal-api/tests/dataSources/restAPI.integration.spec.ts similarity index 100% rename from qa-core/src/internal-api/tests/dataSources/restAPI.nightly.spec.ts rename to qa-core/src/internal-api/tests/dataSources/restAPI.integration.spec.ts From d5439e1fb6961003d3523d2734442835556e6b1d Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 17 May 2023 13:51:09 +0000 Subject: [PATCH 171/171] Bump version to 2.6.16-alpha.5 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 45abc9671f..c9f5201e0d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.6.16-alpha.4", + "version": "2.6.16-alpha.5", "npmClient": "yarn", "packages": [ "packages/backend-core",