From 54e4cad366365ebdb9881b1eb303d0cdb6f9c46e Mon Sep 17 00:00:00 2001 From: Pranav C Date: Tue, 24 Oct 2023 18:01:13 +0530 Subject: [PATCH] feat: validate fields and filters Signed-off-by: Pranav C --- packages/nocodb/src/db/BaseModelSqlv2.ts | 10 +++++++++- packages/nocodb/src/helpers/getAst.ts | 14 ++++++++++++++ packages/nocodb/src/services/data-table.service.ts | 11 +++++++---- packages/nocodb/src/services/datas.service.ts | 3 ++- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index a6188a0612..0a1afe6b0b 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -141,9 +141,11 @@ class BaseModelSqlv2 { { ignoreView = false, getHiddenColumn = false, + throwErrorIfInvalidParams = false, }: { ignoreView?: boolean; getHiddenColumn?: boolean; + throwErrorIfInvalidParams?: boolean; } = {}, ): Promise { const qb = this.dbDriver(this.tnPath); @@ -153,6 +155,7 @@ class BaseModelSqlv2 { model: this.model, view: ignoreView ? null : this.viewId && (await View.get(this.viewId)), getHiddenColumn, + throwErrorIfInvalidParams }); await this.selectObject({ @@ -369,6 +372,7 @@ class BaseModelSqlv2 { public async count( args: { where?: string; limit?; filterArr?: Filter[] } = {}, ignoreViewFilterAndSort = false, + throwErrorIfInvalidParams = false, ): Promise { await this.model.getColumns(); const { where } = this._getListArgs(args); @@ -377,7 +381,7 @@ class BaseModelSqlv2 { // qb.xwhere(where, await this.model.getAliasColMapping()); const aliasColObjMap = await this.model.getAliasColObjMap(); - const filterObj = extractFilterFromXwhere(where, aliasColObjMap); + const filterObj = extractFilterFromXwhere(where, aliasColObjMap,throwErrorIfInvalidParams); if (!ignoreViewFilterAndSort && this.viewId) { await conditionV2( @@ -401,6 +405,8 @@ class BaseModelSqlv2 { ...(args.filterArr || []), ], qb, + undefined, + throwErrorIfInvalidParams ); } else { await conditionV2( @@ -419,6 +425,8 @@ class BaseModelSqlv2 { ...(args.filterArr || []), ], qb, + undefined, + throwErrorIfInvalidParams ); } diff --git a/packages/nocodb/src/helpers/getAst.ts b/packages/nocodb/src/helpers/getAst.ts index 429dcaea98..4085cf8b5e 100644 --- a/packages/nocodb/src/helpers/getAst.ts +++ b/packages/nocodb/src/helpers/getAst.ts @@ -5,6 +5,7 @@ import type { LookupColumn, Model, } from '~/models'; +import { NcError } from '~/helpers/catchError'; import { GalleryView, KanbanView, View } from '~/models'; const getAst = async ({ @@ -19,6 +20,7 @@ const getAst = async ({ fieldsSet: new Set(), }, getHiddenColumn = query?.['getHiddenColumn'], + throwErrorIfInvalidParams = false, }: { query?: RequestQuery; extractOnlyPrimaries?: boolean; @@ -27,6 +29,7 @@ const getAst = async ({ view?: View; dependencyFields?: DependantFields; getHiddenColumn?: boolean; + throwErrorIfInvalidParams?: boolean; }) => { // set default values of dependencyFields and nested dependencyFields.nested = dependencyFields.nested || {}; @@ -63,6 +66,15 @@ const getAst = async ({ let fields = query?.fields || query?.f; if (fields && fields !== '*') { fields = Array.isArray(fields) ? fields : fields.split(','); + if (throwErrorIfInvalidParams) { + const colAliasMap = model.getColAliasMapping(); + const invalidFields = fields.filter((f) => !colAliasMap[f]); + if (invalidFields.length) { + NcError.unprocessableEntity( + `Following fields are invalid: ${invalidFields.join(', ')}`, + ); + } + } } else { fields = null; } @@ -99,6 +111,7 @@ const getAst = async ({ nested: {}, fieldsSet: new Set(), }), + throwErrorIfInvalidParams, }); value = ast; @@ -126,6 +139,7 @@ const getAst = async ({ nested: {}, fieldsSet: new Set(), }), + throwErrorIfInvalidParams, }) ).ast; } diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index acdbba46b5..299d6d2d95 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -25,6 +25,7 @@ export class DataTableService { model, view, query: param.query, + throwErrorIfInvalidParams: true, }); } @@ -45,7 +46,9 @@ export class DataTableService { dbDriver: await NcConnectionMgrv2.get(source), }); - const row = await baseModel.readByPk(param.rowId, false, param.query); + const row = await baseModel.readByPk(param.rowId, false, param.query, { + throwErrorIfInvalidParams: true, + }); if (!row) { NcError.notFound('Row not found'); @@ -167,7 +170,7 @@ export class DataTableService { countArgs.filterArr = JSON.parse(countArgs.filterArrJson); } catch (e) {} - const count: number = await baseModel.count(countArgs); + const count: number = await baseModel.count(countArgs, false, true); return { count }; } @@ -368,7 +371,7 @@ export class DataTableService { modelId: string; columnId: string; query: any; - refRowIds: string | string[] | number | number[]| Record; + refRowIds: string | string[] | number | number[] | Record; rowId: string; }) { this.validateIds(param.refRowIds); @@ -403,7 +406,7 @@ export class DataTableService { modelId: string; columnId: string; query: any; - refRowIds: string | string[] | number | number[]| Record; + refRowIds: string | string[] | number | number[] | Record; rowId: string; }) { this.validateIds(param.refRowIds); diff --git a/packages/nocodb/src/services/datas.service.ts b/packages/nocodb/src/services/datas.service.ts index f9fb1b7539..93350bfae7 100644 --- a/packages/nocodb/src/services/datas.service.ts +++ b/packages/nocodb/src/services/datas.service.ts @@ -133,6 +133,7 @@ export class DatasService { view?: View; query: any; baseModel?: BaseModelSqlv2; + throwErrorIfInvalidParams?: boolean; }) { const { model, view, query = {} } = param; @@ -146,7 +147,7 @@ export class DatasService { dbDriver: await NcConnectionMgrv2.get(source), })); - const { ast, dependencyFields } = await getAst({ model, query, view }); + const { ast, dependencyFields } = await getAst({ model, query, view, throwErrorIfInvalidParams: param.throwErrorIfInvalidParams }); const listArgs: any = dependencyFields; try {