From 33f7792522906e3dd326bafd59ee669cb0771ff8 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Fri, 11 Oct 2024 15:33:33 +0100 Subject: [PATCH] Potential fix for view search problem. --- .../server/src/api/controllers/row/views.ts | 1 + packages/server/src/sdk/app/rows/search.ts | 19 +++---- .../server/src/sdk/app/rows/search/utils.ts | 54 ++++++++++--------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/packages/server/src/api/controllers/row/views.ts b/packages/server/src/api/controllers/row/views.ts index 622688deb6..9163c401df 100644 --- a/packages/server/src/api/controllers/row/views.ts +++ b/packages/server/src/api/controllers/row/views.ts @@ -8,6 +8,7 @@ import { } from "@budibase/types" import sdk from "../../../sdk" import { context } from "@budibase/backend-core" +import * as utils from "./utils" export async function searchView( ctx: UserCtx diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index f68f78f0bc..ee40f6f4e6 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -16,7 +16,7 @@ import * as external from "./search/external" import { ExportRowsParams, ExportRowsResult } from "./search/types" import { dataFilters } from "@budibase/shared-core" import sdk from "../../index" -import { searchInputMapping } from "./search/utils" +import { checkFilters, searchInputMapping } from "./search/utils" import { db, features } from "@budibase/backend-core" import tracer from "dd-trace" import { getQueryableFields, removeInvalidFilters } from "./queryUtils" @@ -92,8 +92,10 @@ export async function search( // Enrich saved query with ephemeral query params. // We prevent searching on any fields that are saved as part of the query, as // that could let users find rows they should not be allowed to access. - let viewQuery = dataFilters.buildQueryLegacy(view.query) || {} - delete viewQuery?.onEmptyFilter + let query = await enrichSearchContext(view.query || {}, context) + query = dataFilters.buildQueryLegacy(query) || {} + query = checkFilters(table, query) + delete query?.onEmptyFilter const sqsEnabled = await features.flags.isEnabled("SQS") const supportsLogicalOperators = @@ -113,26 +115,25 @@ export async function search( ?.filter(filter => filter.field) .map(filter => db.removeKeyNumbering(filter.field)) || [] - viewQuery ??= {} // Carry over filters for unused fields Object.keys(options.query).forEach(key => { const operator = key as Exclude Object.keys(options.query[operator] || {}).forEach(field => { if (!existingFields.includes(db.removeKeyNumbering(field))) { - viewQuery![operator]![field] = options.query[operator]![field] + query[operator]![field] = options.query[operator]![field] } }) }) - options.query = viewQuery + options.query = query } else { - const conditions = viewQuery ? [viewQuery] : [] + const conditions = query ? [query] : [] options.query = { $and: { conditions: [...conditions, options.query], }, } - if (viewQuery.onEmptyFilter) { - options.query.onEmptyFilter = viewQuery.onEmptyFilter + if (query.onEmptyFilter) { + options.query.onEmptyFilter = query.onEmptyFilter } } } diff --git a/packages/server/src/sdk/app/rows/search/utils.ts b/packages/server/src/sdk/app/rows/search/utils.ts index 90303a6ca7..c7de7eef37 100644 --- a/packages/server/src/sdk/app/rows/search/utils.ts +++ b/packages/server/src/sdk/app/rows/search/utils.ts @@ -80,35 +80,41 @@ function userColumnMapping(column: string, filters: SearchFilters) { }) } +export function checkFilters( + table: Table, + filters: SearchFilters +): SearchFilters { + for (let [key, column] of Object.entries(table.schema || {})) { + switch (column.type) { + case FieldType.BB_REFERENCE_SINGLE: { + const subtype = column.subtype + switch (subtype) { + case BBReferenceFieldSubType.USER: + userColumnMapping(key, filters) + break + + default: + utils.unreachable(subtype) + } + break + } + case FieldType.BB_REFERENCE: { + userColumnMapping(key, filters) + break + } + } + } + return dataFilters.recurseLogicalOperators(filters, filters => + checkFilters(table, filters) + ) +} + // maps through the search parameters to check if any of the inputs are invalid // based on the table schema, converts them to something that is valid. export function searchInputMapping(table: Table, options: RowSearchParams) { // need an internal function to loop over filters, because this takes the full options - function checkFilters(filters: SearchFilters) { - for (let [key, column] of Object.entries(table.schema || {})) { - switch (column.type) { - case FieldType.BB_REFERENCE_SINGLE: { - const subtype = column.subtype - switch (subtype) { - case BBReferenceFieldSubType.USER: - userColumnMapping(key, filters) - break - - default: - utils.unreachable(subtype) - } - break - } - case FieldType.BB_REFERENCE: { - userColumnMapping(key, filters) - break - } - } - } - return dataFilters.recurseLogicalOperators(filters, checkFilters) - } if (options.query) { - options.query = checkFilters(options.query) + options.query = checkFilters(table, options.query) } return options }