From 8e8c913dfb97d91d860d01e7c653da8c398873cb Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 6 Sep 2023 18:17:44 +0100 Subject: [PATCH 01/16] Updating the yarn dev process to not include a removal of the dist directory as part of the streamed watchers - this seems to create a problem for shared core and moving this up a level to a parallel run before the watchers massively improves stability. --- package.json | 2 +- packages/server/package.json | 2 +- packages/shared-core/package.json | 2 +- packages/types/package.json | 2 +- packages/worker/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b0c428fe70..b263fb6585 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "kill-builder": "kill-port 3000", "kill-server": "kill-port 4001 4002", "kill-all": "yarn run kill-builder && yarn run kill-server", - "dev": "yarn run kill-all && lerna run --stream dev:builder", + "dev": "yarn run kill-all && lerna run --parallel prebuild && lerna run --stream dev:builder", "dev:noserver": "yarn run kill-builder && lerna run --stream dev:stack:up && lerna run --stream dev:builder --ignore @budibase/backend-core --ignore @budibase/server --ignore @budibase/worker", "dev:server": "yarn run kill-server && lerna run --stream dev:builder --scope @budibase/worker --scope @budibase/server", "dev:built": "yarn run kill-all && cd packages/server && yarn dev:stack:up && cd ../../ && lerna run --stream dev:built", diff --git a/packages/server/package.json b/packages/server/package.json index ecf31175dc..39f52342a4 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -26,7 +26,7 @@ "dev:stack:up": "node scripts/dev/manage.js up", "dev:stack:down": "node scripts/dev/manage.js down", "dev:stack:nuke": "node scripts/dev/manage.js nuke", - "dev:builder": "yarn run dev:stack:up && rimraf dist/ && nodemon", + "dev:builder": "yarn run dev:stack:up && nodemon", "dev:built": "yarn run dev:stack:up && yarn run run:docker", "specs": "ts-node specs/generate.ts && openapi-typescript specs/openapi.yaml --output src/definitions/openapi.ts", "initialise": "node scripts/initialise.js", diff --git a/packages/shared-core/package.json b/packages/shared-core/package.json index 8edea4870a..160a42f086 100644 --- a/packages/shared-core/package.json +++ b/packages/shared-core/package.json @@ -10,7 +10,7 @@ "prebuild": "rimraf dist/", "build": "node ../../scripts/build.js && tsc -p tsconfig.build.json --emitDeclarationOnly --paths null", "build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput", - "dev:builder": "yarn prebuild && tsc -p tsconfig.json --watch --preserveWatchOutput", + "dev:builder": "tsc -p tsconfig.json --watch --preserveWatchOutput", "check:types": "tsc -p tsconfig.json --noEmit --paths null" }, "dependencies": { diff --git a/packages/types/package.json b/packages/types/package.json index bb0163ae13..919cc736fc 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -10,7 +10,7 @@ "prebuild": "rimraf dist/", "build": "node ../../scripts/build.js && tsc -p tsconfig.build.json --emitDeclarationOnly", "build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput", - "dev:builder": "yarn prebuild && tsc -p tsconfig.json --watch --preserveWatchOutput", + "dev:builder": "tsc -p tsconfig.json --watch --preserveWatchOutput", "check:types": "tsc -p tsconfig.json --noEmit --paths null" }, "jest": {}, diff --git a/packages/worker/package.json b/packages/worker/package.json index 3b66df264e..15ab1c1ff9 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -22,7 +22,7 @@ "predocker": "yarn build && cp ../../yarn.lock ./dist/", "build:docker": "yarn predocker && docker build . -t worker-service --label version=$BUDIBASE_RELEASE_VERSION", "dev:stack:init": "node ./scripts/dev/manage.js init", - "dev:builder": "npm run dev:stack:init && rimraf dist/ && nodemon", + "dev:builder": "npm run dev:stack:init && nodemon", "dev:built": "yarn run dev:stack:init && yarn run run:docker", "test": "bash scripts/test.sh", "test:watch": "jest --watch", From aeac7aaa0c0f8845bbfd187e207795c25af7237d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 12 Sep 2023 13:54:39 +0100 Subject: [PATCH 02/16] Making sure that not all falsy values are considered invalid filter inputs. --- .../server/scripts/integrations/postgres/init.sql | 3 ++- packages/server/src/api/controllers/row/external.ts | 4 ++-- packages/server/src/api/controllers/row/utils.ts | 6 ++++++ yarn.lock | 13 +++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/server/scripts/integrations/postgres/init.sql b/packages/server/scripts/integrations/postgres/init.sql index 6cb3f51269..f89ad2812d 100644 --- a/packages/server/scripts/integrations/postgres/init.sql +++ b/packages/server/scripts/integrations/postgres/init.sql @@ -1,7 +1,7 @@ SELECT 'CREATE DATABASE main' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'main')\gexec CREATE SCHEMA "test-1"; -CREATE TYPE person_job AS ENUM ('qa', 'programmer', 'designer'); +CREATE TYPE person_job AS ENUM ('qa', 'programmer', 'designer', 'support'); CREATE TABLE Persons ( PersonID SERIAL PRIMARY KEY, LastName varchar(255), @@ -51,6 +51,7 @@ CREATE TABLE CompositeTable ( ); INSERT INTO Persons (FirstName, LastName, Address, City, Type) VALUES ('Mike', 'Hughes', '123 Fake Street', 'Belfast', 'qa'); INSERT INTO Persons (FirstName, LastName, Address, City, Type) VALUES ('John', 'Smith', '64 Updown Road', 'Dublin', 'programmer'); +INSERT INTO Persons (FirstName, LastName, Address, City, Type, Age) VALUES ('Foo', 'Bar', 'Foo Street', 'Bartown', 'support', 0); INSERT INTO Tasks (ExecutorID, QaID, TaskName, Completed) VALUES (1, 2, 'assembling', TRUE); INSERT INTO Tasks (ExecutorID, QaID, TaskName, Completed) VALUES (2, 1, 'processing', FALSE); INSERT INTO Products (ProductName) VALUES ('Computers'); diff --git a/packages/server/src/api/controllers/row/external.ts b/packages/server/src/api/controllers/row/external.ts index 491cbfa8f9..44921a5114 100644 --- a/packages/server/src/api/controllers/row/external.ts +++ b/packages/server/src/api/controllers/row/external.ts @@ -32,12 +32,12 @@ export async function handleRequest( } // @ts-ignore for (let [key, value] of Object.entries(opts.filters[filterField])) { - if (!value || value === "") { + if (utils.invalidFilter(value)) { // @ts-ignore delete opts.filters[filterField][key] } } - } + } if ( diff --git a/packages/server/src/api/controllers/row/utils.ts b/packages/server/src/api/controllers/row/utils.ts index e85ec4553c..12c84bfb7b 100644 --- a/packages/server/src/api/controllers/row/utils.ts +++ b/packages/server/src/api/controllers/row/utils.ts @@ -139,3 +139,9 @@ export async function validate({ } return { valid: Object.keys(errors).length === 0, errors } } + +// don't do a pure falsy check, as 0 is included +// https://github.com/Budibase/budibase/issues/10118 +export function invalidFilter(value: any) { + return value == null || value === "" +} diff --git a/yarn.lock b/yarn.lock index ab86a87560..8c93661665 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6269,6 +6269,14 @@ "@types/tedious" "*" tarn "^3.0.1" +"@types/node-fetch@2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" + integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node-fetch@2.6.4": version "2.6.4" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" @@ -6290,6 +6298,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== +"@types/node@14.18.20": + version "14.18.20" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.20.tgz#268f028b36eaf51181c3300252f605488c4f0650" + integrity sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA== + "@types/node@16.9.1": version "16.9.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708" From aed5694ac2715dae82e5f43f314d16b5647806a7 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 12 Sep 2023 14:06:20 +0100 Subject: [PATCH 03/16] Adding dedicated function for removing empty filters. --- .../src/api/controllers/row/external.ts | 15 +------- .../server/src/api/controllers/row/utils.ts | 38 +++++++++++++++++-- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/packages/server/src/api/controllers/row/external.ts b/packages/server/src/api/controllers/row/external.ts index 44921a5114..a04584e6bd 100644 --- a/packages/server/src/api/controllers/row/external.ts +++ b/packages/server/src/api/controllers/row/external.ts @@ -18,6 +18,7 @@ import { import sdk from "../../../sdk" import * as utils from "./utils" import { dataFilters } from "@budibase/shared-core" +import { removeEmptyFilters } from "./utils" export async function handleRequest( operation: Operation, @@ -26,20 +27,8 @@ export async function handleRequest( ) { // make sure the filters are cleaned up, no empty strings for equals, fuzzy or string if (opts && opts.filters) { - for (let filterField of NoEmptyFilterStrings) { - if (!opts.filters[filterField]) { - continue - } - // @ts-ignore - for (let [key, value] of Object.entries(opts.filters[filterField])) { - if (utils.invalidFilter(value)) { - // @ts-ignore - delete opts.filters[filterField][key] - } - } - + opts.filters = utils.removeEmptyFilters(opts.filters) } - if ( !dataFilters.hasFilters(opts?.filters) && opts?.filters?.onEmptyFilter === EmptyFilterOption.RETURN_NONE diff --git a/packages/server/src/api/controllers/row/utils.ts b/packages/server/src/api/controllers/row/utils.ts index 12c84bfb7b..cc27f4c2a3 100644 --- a/packages/server/src/api/controllers/row/utils.ts +++ b/packages/server/src/api/controllers/row/utils.ts @@ -1,8 +1,15 @@ import { InternalTables } from "../../../db/utils" import * as userController from "../user" import { context } from "@budibase/backend-core" -import { Ctx, FieldType, Row, Table, UserCtx } from "@budibase/types" -import { FieldTypes } from "../../../constants" +import { + Ctx, + FieldType, + Row, + SearchFilters, + Table, + UserCtx, +} from "@budibase/types" +import { FieldTypes, NoEmptyFilterStrings } from "../../../constants" import sdk from "../../../sdk" import validateJs from "validate.js" @@ -142,6 +149,29 @@ export async function validate({ // don't do a pure falsy check, as 0 is included // https://github.com/Budibase/budibase/issues/10118 -export function invalidFilter(value: any) { - return value == null || value === "" +export function removeEmptyFilters(filters: SearchFilters) { + for (let filterField of NoEmptyFilterStrings) { + if (!filters[filterField]) { + continue + } + + for (let filterType of Object.keys(filters)) { + if (filterType !== filterField) { + continue + } + // don't know which one we're checking, type could be anything + const value = filters[filterType] as unknown + if (typeof value === "object") { + for (let [key, value] of Object.entries( + filters[filterType] as object + )) { + if (value == null || value === "") { + // @ts-ignore + delete filters[filterField][key] + } + } + } + } + } + return filters } From 80e217afda1325ccf8b23f8650eead02a26fb0d0 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 12 Sep 2023 14:23:08 +0100 Subject: [PATCH 04/16] Quick test to avoid scenario in future. --- .../api/controllers/row/tests/utils.spec.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 packages/server/src/api/controllers/row/tests/utils.spec.ts diff --git a/packages/server/src/api/controllers/row/tests/utils.spec.ts b/packages/server/src/api/controllers/row/tests/utils.spec.ts new file mode 100644 index 0000000000..e0ad637e9d --- /dev/null +++ b/packages/server/src/api/controllers/row/tests/utils.spec.ts @@ -0,0 +1,21 @@ +import * as utils from "../utils" + +describe("removeEmptyFilters", () => { + it("0 should not be removed", () => { + const filters = utils.removeEmptyFilters({ + equal: { + column: 0, + }, + }) + expect((filters.equal as any).column).toBe(0) + }) + + it("empty string should be removed", () => { + const filters = utils.removeEmptyFilters({ + equal: { + column: "", + }, + }) + expect(Object.values(filters.equal as any).length).toBe(0) + }) +}) From 2dd2dcc2cb0dabb3416157ef6d9c665943b7383c Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 12 Sep 2023 17:26:41 +0100 Subject: [PATCH 05/16] Role fixes --- .../app/[application]/_components/BuilderSidePanel.svelte | 2 +- .../src/pages/builder/portal/users/users/[userId].svelte | 2 +- 2 files changed, 2 insertions(+), 2 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 7c4d3db7ce..c93a41f541 100644 --- a/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/_components/BuilderSidePanel.svelte @@ -126,7 +126,7 @@ user, prodAppId ) - const isAppBuilder = sdk.users.hasAppBuilderPermissions(user, prodAppId) + const isAppBuilder = user.builder?.apps?.includes(prodAppId) let role if (isAdminOrGlobalBuilder) { role = Constants.Roles.ADMIN 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 2a74cd9de5..ec10ec8316 100644 --- a/packages/builder/src/pages/builder/portal/users/users/[userId].svelte +++ b/packages/builder/src/pages/builder/portal/users/users/[userId].svelte @@ -111,7 +111,7 @@ }) } return availableApps.map(app => { - const prodAppId = apps.getProdAppID(app.appId) + const prodAppId = apps.getProdAppID(app.devId) return { name: app.name, devId: app.devId, From be5e8005b2d6b2a2c0e5a8339d25e034914e506a Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 13 Sep 2023 14:06:52 +0000 Subject: [PATCH 06/16] Bump version to 2.10.7 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 63466ceedb..77f38e67ed 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.10.6", + "version": "2.10.7", "npmClient": "yarn", "packages": [ "packages/*" From 6d74bb4063bc7580bad2c822a325f291d638aa7d Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 13 Sep 2023 18:01:20 +0000 Subject: [PATCH 07/16] Bump version to 2.10.8 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 77f38e67ed..30aa2afa3c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.10.7", + "version": "2.10.8", "npmClient": "yarn", "packages": [ "packages/*" From 217d10f5fb81f7e247ed13ba381bef559eebcfd6 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 14 Sep 2023 14:00:49 +0100 Subject: [PATCH 08/16] Fix for more than/less than ranges, zeros were ignored when building up ranges, so that it simply acted like an upper limit, rather than a range. --- packages/server/src/api/controllers/row/utils.ts | 4 ++++ packages/server/src/integrations/base/sql.ts | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/controllers/row/utils.ts b/packages/server/src/api/controllers/row/utils.ts index cc27f4c2a3..92db29d303 100644 --- a/packages/server/src/api/controllers/row/utils.ts +++ b/packages/server/src/api/controllers/row/utils.ts @@ -147,6 +147,10 @@ export async function validate({ return { valid: Object.keys(errors).length === 0, errors } } +export function isValidFilter(value: any) { + return value != null && value !== "" +} + // don't do a pure falsy check, as 0 is included // https://github.com/Budibase/budibase/issues/10118 export function removeEmptyFilters(filters: SearchFilters) { diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index bf19ec9afe..3cdded69b4 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -11,6 +11,7 @@ import { QueryOptions } from "../../definitions/datasource" import { isIsoDateString, SqlClient } from "../utils" import SqlTableQueryBuilder from "./sqlTable" import environment from "../../environment" +import { isValidFilter } from "../../api/controllers/row/utils" const envLimit = environment.SQL_MAX_ROWS ? parseInt(environment.SQL_MAX_ROWS) @@ -261,15 +262,15 @@ class InternalBuilder { if (isEmptyObject(value.high)) { value.high = "" } - if (value.low && value.high) { + if (isValidFilter(value.low) && isValidFilter(value.high)) { // Use a between operator if we have 2 valid range values const fnc = allOr ? "orWhereBetween" : "whereBetween" query = query[fnc](key, [value.low, value.high]) - } else if (value.low) { + } else if (isValidFilter(value.low)) { // Use just a single greater than operator if we only have a low const fnc = allOr ? "orWhere" : "where" query = query[fnc](key, ">", value.low) - } else if (value.high) { + } else if (isValidFilter(value.high)) { // Use just a single less than operator if we only have a high const fnc = allOr ? "orWhere" : "where" query = query[fnc](key, "<", value.high) From c466f35a98a3e92ca35afd2d9037147d63dac58c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 13 Sep 2023 15:23:30 +0100 Subject: [PATCH 09/16] Found some discussion of testcontainers being problematic when nearly out of disk space, we have seen issues with the default Github runners as they have extremely limited disk space, this should help a bit removing android and dotnet, two pieces of functionality we will never need. --- .github/workflows/budibase_ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index d670e222d3..fc35575ec6 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -25,6 +25,13 @@ jobs: lint: runs-on: ubuntu-latest steps: + - name: Maximize build space + uses: easimon/maximize-build-space@master + with: + root-reserve-mb: 35000 + swap-size-mb: 1024 + remove-android: 'true' + remove-dotnet: 'true' - name: Checkout repo and submodules uses: actions/checkout@v3 if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Budibase/budibase' From 8ca3f13a1cea7171d4e6a51b547bebdf28b65d19 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 14 Sep 2023 16:53:36 +0100 Subject: [PATCH 10/16] Quick re-jig based on test failure, seems the base sql.ts is depended on fairly heavily, importing the SDK can create a lot of cycles. --- .../src/api/controllers/row/external.ts | 3 +- .../server/src/api/controllers/row/utils.ts | 33 --------------- packages/server/src/integrations/base/sql.ts | 18 ++++---- packages/server/src/integrations/utils.ts | 42 ++++++++++++++++++- packages/server/src/sdk/app/rows/search.ts | 1 + 5 files changed, 52 insertions(+), 45 deletions(-) diff --git a/packages/server/src/api/controllers/row/external.ts b/packages/server/src/api/controllers/row/external.ts index a04584e6bd..6cc6337e0d 100644 --- a/packages/server/src/api/controllers/row/external.ts +++ b/packages/server/src/api/controllers/row/external.ts @@ -18,7 +18,6 @@ import { import sdk from "../../../sdk" import * as utils from "./utils" import { dataFilters } from "@budibase/shared-core" -import { removeEmptyFilters } from "./utils" export async function handleRequest( operation: Operation, @@ -27,7 +26,7 @@ export async function handleRequest( ) { // make sure the filters are cleaned up, no empty strings for equals, fuzzy or string if (opts && opts.filters) { - opts.filters = utils.removeEmptyFilters(opts.filters) + opts.filters = sdk.rows.removeEmptyFilters(opts.filters) } if ( !dataFilters.hasFilters(opts?.filters) && diff --git a/packages/server/src/api/controllers/row/utils.ts b/packages/server/src/api/controllers/row/utils.ts index 92db29d303..82e7c7b0d8 100644 --- a/packages/server/src/api/controllers/row/utils.ts +++ b/packages/server/src/api/controllers/row/utils.ts @@ -146,36 +146,3 @@ export async function validate({ } return { valid: Object.keys(errors).length === 0, errors } } - -export function isValidFilter(value: any) { - return value != null && value !== "" -} - -// don't do a pure falsy check, as 0 is included -// https://github.com/Budibase/budibase/issues/10118 -export function removeEmptyFilters(filters: SearchFilters) { - for (let filterField of NoEmptyFilterStrings) { - if (!filters[filterField]) { - continue - } - - for (let filterType of Object.keys(filters)) { - if (filterType !== filterField) { - continue - } - // don't know which one we're checking, type could be anything - const value = filters[filterType] as unknown - if (typeof value === "object") { - for (let [key, value] of Object.entries( - filters[filterType] as object - )) { - if (value == null || value === "") { - // @ts-ignore - delete filters[filterField][key] - } - } - } - } - } - return filters -} diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 3cdded69b4..add7596165 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -1,4 +1,8 @@ import { Knex, knex } from "knex" +import { db as dbCore } from "@budibase/backend-core" +import { QueryOptions } from "../../definitions/datasource" +import { isIsoDateString, SqlClient } from "../utils" +import SqlTableQueryBuilder from "./sqlTable" import { Operation, QueryJson, @@ -6,12 +10,8 @@ import { SearchFilters, SortDirection, } from "@budibase/types" -import { db as dbCore } from "@budibase/backend-core" -import { QueryOptions } from "../../definitions/datasource" -import { isIsoDateString, SqlClient } from "../utils" -import SqlTableQueryBuilder from "./sqlTable" import environment from "../../environment" -import { isValidFilter } from "../../api/controllers/row/utils" +import { isValidFilter } from "../utils" const envLimit = environment.SQL_MAX_ROWS ? parseInt(environment.SQL_MAX_ROWS) @@ -262,15 +262,17 @@ class InternalBuilder { if (isEmptyObject(value.high)) { value.high = "" } - if (isValidFilter(value.low) && isValidFilter(value.high)) { + const lowValid = isValidFilter(value.low), + highValid = isValidFilter(value.high) + if (lowValid && highValid) { // Use a between operator if we have 2 valid range values const fnc = allOr ? "orWhereBetween" : "whereBetween" query = query[fnc](key, [value.low, value.high]) - } else if (isValidFilter(value.low)) { + } else if (lowValid) { // Use just a single greater than operator if we only have a low const fnc = allOr ? "orWhere" : "where" query = query[fnc](key, ">", value.low) - } else if (isValidFilter(value.high)) { + } else if (highValid) { // Use just a single less than operator if we only have a high const fnc = allOr ? "orWhere" : "where" query = query[fnc](key, "<", value.high) diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index 2883e4471c..75f4bcbfa1 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -1,6 +1,11 @@ -import { SourceName, SqlQuery, Datasource, Table } from "@budibase/types" +import { SqlQuery, Table, SearchFilters } from "@budibase/types" import { DocumentType, SEPARATOR } from "../db/utils" -import { FieldTypes, BuildSchemaErrors, InvalidColumns } from "../constants" +import { + FieldTypes, + BuildSchemaErrors, + InvalidColumns, + NoEmptyFilterStrings, +} from "../constants" import { helpers } from "@budibase/shared-core" const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}` @@ -343,3 +348,36 @@ export function getPrimaryDisplay(testValue: unknown): string | undefined { } return testValue as string } + +export function isValidFilter(value: any) { + return value != null && value !== "" +} + +// don't do a pure falsy check, as 0 is included +// https://github.com/Budibase/budibase/issues/10118 +export function removeEmptyFilters(filters: SearchFilters) { + for (let filterField of NoEmptyFilterStrings) { + if (!filters[filterField]) { + continue + } + + for (let filterType of Object.keys(filters)) { + if (filterType !== filterField) { + continue + } + // don't know which one we're checking, type could be anything + const value = filters[filterType] as unknown + if (typeof value === "object") { + for (let [key, value] of Object.entries( + filters[filterType] as object + )) { + if (value == null || value === "") { + // @ts-ignore + delete filters[filterField][key] + } + } + } + } + } + return filters +} diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index 4861f473ea..1d06108b67 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -3,6 +3,7 @@ import { isExternalTable } from "../../../integrations/utils" import * as internal from "./search/internal" import * as external from "./search/external" import { Format } from "../../../api/controllers/view/exporters" +export { isValidFilter, removeEmptyFilters } from "../../../integrations/utils" export interface ViewParams { calculation: string From 68f31975223a4c1a187f0281161baf4b49491980 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 14 Sep 2023 17:12:09 +0100 Subject: [PATCH 11/16] Moving test to where the functions are now. --- .../tests/utils.spec.ts => sdk/tests/rows/search.spec.ts} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename packages/server/src/{api/controllers/row/tests/utils.spec.ts => sdk/tests/rows/search.spec.ts} (71%) diff --git a/packages/server/src/api/controllers/row/tests/utils.spec.ts b/packages/server/src/sdk/tests/rows/search.spec.ts similarity index 71% rename from packages/server/src/api/controllers/row/tests/utils.spec.ts rename to packages/server/src/sdk/tests/rows/search.spec.ts index e0ad637e9d..feae5e7ee8 100644 --- a/packages/server/src/api/controllers/row/tests/utils.spec.ts +++ b/packages/server/src/sdk/tests/rows/search.spec.ts @@ -1,8 +1,8 @@ -import * as utils from "../utils" +import * as search from "../../app/rows/search" describe("removeEmptyFilters", () => { it("0 should not be removed", () => { - const filters = utils.removeEmptyFilters({ + const filters = search.removeEmptyFilters({ equal: { column: 0, }, @@ -11,7 +11,7 @@ describe("removeEmptyFilters", () => { }) it("empty string should be removed", () => { - const filters = utils.removeEmptyFilters({ + const filters = search.removeEmptyFilters({ equal: { column: "", }, From fb30be6ce4ef3652e762deda1e0631a8031c2ccd Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 14 Sep 2023 17:02:50 +0000 Subject: [PATCH 12/16] Bump version to 2.10.9 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 30aa2afa3c..77df84de36 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.10.8", + "version": "2.10.9", "npmClient": "yarn", "packages": [ "packages/*" From 7f43db09a638c47cbfbdc93b9363c72595866146 Mon Sep 17 00:00:00 2001 From: melohagan <101575380+melohagan@users.noreply.github.com> Date: Fri, 15 Sep 2023 10:45:15 +0100 Subject: [PATCH 13/16] Budi 7481 initial form step binding drawer can crash (#11751) * Type safety * Clear localFiles is fieldState is cleared --- .../src/components/common/CodeEditor/CodeEditor.svelte | 2 +- packages/client/src/components/app/forms/S3Upload.svelte | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 7ab7c5dddf..76d7a58ef1 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -235,7 +235,7 @@ const baseExtensions = buildBaseExtensions() editor = new EditorView({ - doc: value, + doc: value?.toString(), extensions: buildExtensions(baseExtensions), parent: textarea, }) diff --git a/packages/client/src/components/app/forms/S3Upload.svelte b/packages/client/src/components/app/forms/S3Upload.svelte index dfc5032de9..9985c83bb8 100644 --- a/packages/client/src/components/app/forms/S3Upload.svelte +++ b/packages/client/src/components/app/forms/S3Upload.svelte @@ -17,6 +17,13 @@ let fieldApi let localFiles = [] + $: { + // If the field state is reset, clear the local files + if (!fieldState?.value?.length) { + localFiles = [] + } + } + const { API, notificationStore, uploadStore } = getContext("sdk") const component = getContext("component") From 539fdd1d6d4bd7d3ceb44a9115971aba409036bf Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Fri, 15 Sep 2023 09:45:38 +0000 Subject: [PATCH 14/16] Bump version to 2.10.10 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 77df84de36..021c74d07c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.10.9", + "version": "2.10.10", "npmClient": "yarn", "packages": [ "packages/*" From 3f7b615d10b439b1a269f0949c0658b081f21992 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 18 Sep 2023 17:58:07 +0200 Subject: [PATCH 15/16] Populate apps from groups while fetching apps --- .../src/sdk/app/applications/applications.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/server/src/sdk/app/applications/applications.ts b/packages/server/src/sdk/app/applications/applications.ts index 865b277504..2604b59fa7 100644 --- a/packages/server/src/sdk/app/applications/applications.ts +++ b/packages/server/src/sdk/app/applications/applications.ts @@ -1,13 +1,14 @@ import { AppStatus } from "../../../db/utils" -import { App, ContextUser } from "@budibase/types" +import { App, ContextUser, User } from "@budibase/types" import { getLocksById } from "../../../utilities/redis" import { enrichApps } from "../../users/sessions" import { checkAppMetadata } from "../../../automations/logging" import { db as dbCore, users } from "@budibase/backend-core" +import { groups } from "@budibase/pro" -export function filterAppList(user: ContextUser, apps: App[]) { +export function filterAppList(user: User, apps: App[]) { let appList: string[] = [] - const roleApps = Object.keys(user.roles || {}) + const roleApps = Object.keys(user.roles) if (users.hasAppBuilderPermissions(user)) { appList = user.builder?.apps || [] appList = appList.concat(roleApps) @@ -23,7 +24,12 @@ export async function fetch(status: AppStatus, user: ContextUser) { const dev = status === AppStatus.DEV const all = status === AppStatus.ALL let apps = (await dbCore.getAllApps({ dev, all })) as App[] - apps = filterAppList(user, apps) + + const enrichedUser = await groups.enrichUserRolesFromGroups({ + ...user, + roles: user.roles || {}, + }) + apps = filterAppList(enrichedUser, apps) const appIds = apps .filter((app: any) => app.status === "development") From 225457d123d92cd09e9d59a2722c014fa99bc688 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Tue, 19 Sep 2023 10:28:33 +0000 Subject: [PATCH 16/16] Bump version to 2.10.11 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 021c74d07c..fbecff9293 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.10.10", + "version": "2.10.11", "npmClient": "yarn", "packages": [ "packages/*"