From fa8ac94d563ea99859a601d121e62fde9ed105af Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Tue, 6 Dec 2022 13:02:52 +0800 Subject: [PATCH 1/4] refactor(nocodb): move convertAttachmentType to extractRawQueryAndExec --- .../sql-data-mapper/lib/sql/BaseModelSqlv2.ts | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts index 429252ae59..89610b8d1a 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts @@ -103,7 +103,6 @@ class BaseModelSqlv2 { let data = (await this.extractRawQueryAndExec(qb))?.[0]; if (data) { - data = this.convertAttachmentType(data); const proto = await this.getProto(); data.__proto__ = proto; } @@ -162,7 +161,6 @@ class BaseModelSqlv2 { let data = await qb.first(); if (data) { - data = this.convertAttachmentType(data); const proto = await this.getProto(); data.__proto__ = proto; } @@ -255,7 +253,6 @@ class BaseModelSqlv2 { if (!ignoreViewFilterAndSort) applyPaginate(qb, rest); const proto = await this.getProto(); let data = await this.extractRawQueryAndExec(qb); - data = this.convertAttachmentType(data); return data?.map((d) => { d.__proto__ = proto; @@ -367,7 +364,7 @@ class BaseModelSqlv2 { qb.groupBy(args.column_name); if (sorts) await sortV2(sorts, qb, this.dbDriver); applyPaginate(qb, rest); - return this.convertAttachmentType(await qb); + return await qb; } async multipleHmList({ colId, ids }, args: { limit?; offset? } = {}) { @@ -427,7 +424,6 @@ class BaseModelSqlv2 { ); let children = await this.extractRawQueryAndExec(childQb); - children = this.convertAttachmentType(children); const proto = await ( await Model.getBaseModelSQL({ id: childTable.id, @@ -555,7 +551,6 @@ class BaseModelSqlv2 { await childModel.selectObject({ qb }); let children = await this.extractRawQueryAndExec(qb); - children = this.convertAttachmentType(children); const proto = await ( await Model.getBaseModelSQL({ @@ -676,7 +671,6 @@ class BaseModelSqlv2 { if (this.isMySQL) { children = children[0]; } - children = this.convertAttachmentType(children); const proto = await ( await Model.getBaseModelSQL({ id: rtnId, @@ -742,7 +736,6 @@ class BaseModelSqlv2 { qb.offset(+rest?.offset || 0); let children = await this.extractRawQueryAndExec(qb); - children = this.convertAttachmentType(children); const proto = await ( await Model.getBaseModelSQL({ id: rtnId, dbDriver: this.dbDriver }) ).getProto(); @@ -969,7 +962,6 @@ class BaseModelSqlv2 { const proto = await childModel.getProto(); let data = await qb; - data = this.convertAttachmentType(data); return data.map((c) => { c.__proto__ = proto; return c; @@ -1084,7 +1076,6 @@ class BaseModelSqlv2 { const proto = await childModel.getProto(); let data = await this.extractRawQueryAndExec(qb); - data = this.convertAttachmentType(data); return data.map((c) => { c.__proto__ = proto; @@ -1203,7 +1194,6 @@ class BaseModelSqlv2 { const proto = await parentModel.getProto(); let data = await this.extractRawQueryAndExec(qb); - data = this.convertAttachmentType(data); return data.map((c) => { c.__proto__ = proto; @@ -2663,7 +2653,6 @@ class BaseModelSqlv2 { const proto = await this.getProto(); let data = await groupedQb; - data = this.convertAttachmentType(data); const result = data?.map((d) => { d.__proto__ = proto; return d; @@ -2773,21 +2762,25 @@ class BaseModelSqlv2 { } else { query = sanitize(query); } - return this.isPg - ? (await this.dbDriver.raw(query))?.rows - : query.slice(0, 6) === 'select' && !this.isMssql - ? await this.dbDriver.from( - this.dbDriver.raw(query).wrap('(', ') __nc_alias') - ) - : await this.dbDriver.raw(query); + return this.convertAttachmentType( + this.isPg + ? (await this.dbDriver.raw(query))?.rows + : query.slice(0, 6) === 'select' && !this.isMssql + ? await this.dbDriver.from( + this.dbDriver.raw(query).wrap('(', ') __nc_alias') + ) + : await this.dbDriver.raw(query) + ); } private _convertAttachmentType(attachmentColumns, d) { - attachmentColumns.forEach((col) => { - if (d[col.title] && typeof d[col.title] === 'string') { - d[col.title] = JSON.parse(d[col.title]); - } - }); + if (d) { + attachmentColumns.forEach((col) => { + if (d[col.title] && typeof d[col.title] === 'string') { + d[col.title] = JSON.parse(d[col.title]); + } + }); + } return d; } From 7403f07c2c0d1081c5058bf202b24309e83462fb Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 8 Dec 2022 19:44:02 +0800 Subject: [PATCH 2/4] fix(nocodb): add try catch and handle LTAR case --- .../sql-data-mapper/lib/sql/BaseModelSqlv2.ts | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts index 89610b8d1a..f6771498a6 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts @@ -423,7 +423,7 @@ class BaseModelSqlv2 { .as('list') ); - let children = await this.extractRawQueryAndExec(childQb); + let children = await this.extractRawQueryAndExec(childQb, childTable); const proto = await ( await Model.getBaseModelSQL({ id: childTable.id, @@ -550,7 +550,7 @@ class BaseModelSqlv2 { await childModel.selectObject({ qb }); - let children = await this.extractRawQueryAndExec(qb); + let children = await this.extractRawQueryAndExec(qb, childTable); const proto = await ( await Model.getBaseModelSQL({ @@ -667,7 +667,7 @@ class BaseModelSqlv2 { !this.isSqlite ); - let children = await this.extractRawQueryAndExec(finalQb); + let children = await this.extractRawQueryAndExec(finalQb, childTable); if (this.isMySQL) { children = children[0]; } @@ -735,7 +735,7 @@ class BaseModelSqlv2 { qb.limit(+rest?.limit || 25); qb.offset(+rest?.offset || 0); - let children = await this.extractRawQueryAndExec(qb); + let children = await this.extractRawQueryAndExec(qb, childTable); const proto = await ( await Model.getBaseModelSQL({ id: rtnId, dbDriver: this.dbDriver }) ).getProto(); @@ -1075,7 +1075,7 @@ class BaseModelSqlv2 { applyPaginate(qb, rest); const proto = await childModel.getProto(); - let data = await this.extractRawQueryAndExec(qb); + let data = await this.extractRawQueryAndExec(qb, childTable); return data.map((c) => { c.__proto__ = proto; @@ -1193,7 +1193,7 @@ class BaseModelSqlv2 { applyPaginate(qb, rest); const proto = await parentModel.getProto(); - let data = await this.extractRawQueryAndExec(qb); + let data = await this.extractRawQueryAndExec(qb, childTable); return data.map((c) => { c.__proto__ = proto; @@ -2755,7 +2755,10 @@ class BaseModelSqlv2 { return await qb; } - private async extractRawQueryAndExec(qb: Knex.QueryBuilder) { + private async extractRawQueryAndExec( + qb: Knex.QueryBuilder, + childTable?: Model + ) { let query = qb.toQuery(); if (!this.isPg && !this.isMssql) { query = unsanitize(qb.toQuery()); @@ -2769,28 +2772,34 @@ class BaseModelSqlv2 { ? await this.dbDriver.from( this.dbDriver.raw(query).wrap('(', ') __nc_alias') ) - : await this.dbDriver.raw(query) + : await this.dbDriver.raw(query), + childTable ); } - private _convertAttachmentType(attachmentColumns, d) { - if (d) { - attachmentColumns.forEach((col) => { - if (d[col.title] && typeof d[col.title] === 'string') { - d[col.title] = JSON.parse(d[col.title]); - } - }); - } + private _convertAttachmentType( + attachmentColumns: Record[], + d: Record + ) { + try { + if (d) { + attachmentColumns.forEach((col) => { + if (d[col.title] && typeof d[col.title] === 'string') { + d[col.title] = JSON.parse(d[col.title]); + } + }); + } + } catch {} return d; } - private convertAttachmentType(data) { + private convertAttachmentType(data: Record, childTable?: Model) { // attachment is stored in text and parse in UI // convertAttachmentType is used to convert the response in string to array of object in API response if (data) { - const attachmentColumns = this.model.columns.filter( - (c) => c.uidt === UITypes.Attachment - ); + const attachmentColumns = ( + childTable ? childTable.columns : this.model.columns + ).filter((c) => c.uidt === UITypes.Attachment); if (attachmentColumns.length) { if (Array.isArray(data)) { data = data.map((d) => From addb773fa25de1f921672f3f63d1f3760d295848 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 21 Dec 2022 21:39:01 +0800 Subject: [PATCH 3/4] refactor(nocodb): rename extractRawQueryAndExec to execAndParse --- .../sql-data-mapper/lib/sql/BaseModelSqlv2.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts index f6771498a6..6554e721a0 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts @@ -100,7 +100,7 @@ class BaseModelSqlv2 { qb.where(_wherePk(this.model.primaryKeys, id)); - let data = (await this.extractRawQueryAndExec(qb))?.[0]; + let data = (await this.execAndParse(qb))?.[0]; if (data) { const proto = await this.getProto(); @@ -252,7 +252,7 @@ class BaseModelSqlv2 { if (!ignoreViewFilterAndSort) applyPaginate(qb, rest); const proto = await this.getProto(); - let data = await this.extractRawQueryAndExec(qb); + let data = await this.execAndParse(qb); return data?.map((d) => { d.__proto__ = proto; @@ -423,7 +423,7 @@ class BaseModelSqlv2 { .as('list') ); - let children = await this.extractRawQueryAndExec(childQb, childTable); + let children = await this.execAndParse(childQb, childTable); const proto = await ( await Model.getBaseModelSQL({ id: childTable.id, @@ -550,7 +550,7 @@ class BaseModelSqlv2 { await childModel.selectObject({ qb }); - let children = await this.extractRawQueryAndExec(qb, childTable); + let children = await this.execAndParse(qb, childTable); const proto = await ( await Model.getBaseModelSQL({ @@ -667,7 +667,7 @@ class BaseModelSqlv2 { !this.isSqlite ); - let children = await this.extractRawQueryAndExec(finalQb, childTable); + let children = await this.execAndParse(finalQb, childTable); if (this.isMySQL) { children = children[0]; } @@ -735,7 +735,7 @@ class BaseModelSqlv2 { qb.limit(+rest?.limit || 25); qb.offset(+rest?.offset || 0); - let children = await this.extractRawQueryAndExec(qb, childTable); + let children = await this.execAndParse(qb, childTable); const proto = await ( await Model.getBaseModelSQL({ id: rtnId, dbDriver: this.dbDriver }) ).getProto(); @@ -1075,7 +1075,7 @@ class BaseModelSqlv2 { applyPaginate(qb, rest); const proto = await childModel.getProto(); - let data = await this.extractRawQueryAndExec(qb, childTable); + let data = await this.execAndParse(qb, childTable); return data.map((c) => { c.__proto__ = proto; @@ -1193,7 +1193,7 @@ class BaseModelSqlv2 { applyPaginate(qb, rest); const proto = await parentModel.getProto(); - let data = await this.extractRawQueryAndExec(qb, childTable); + let data = await this.execAndParse(qb, childTable); return data.map((c) => { c.__proto__ = proto; @@ -1525,7 +1525,7 @@ class BaseModelSqlv2 { query.returning( `${this.model.primaryKey.column_name} as ${this.model.primaryKey.title}` ); - response = await this.extractRawQueryAndExec(query); + response = await this.execAndParse(query); } const ai = this.model.columns.find((c) => c.ai); @@ -1535,7 +1535,7 @@ class BaseModelSqlv2 { // handle if autogenerated primary key is used if (ag) { - if (!response) await this.extractRawQueryAndExec(query); + if (!response) await this.execAndParse(query); response = await this.readByPk(data[ag.title]); } else if ( !response || @@ -1545,7 +1545,7 @@ class BaseModelSqlv2 { if (response?.length) { id = response[0]; } else { - const res = await this.extractRawQueryAndExec(query); + const res = await this.execAndParse(query); id = res?.id ?? res[0]?.insertId; } @@ -1650,7 +1650,7 @@ class BaseModelSqlv2 { .update(updateObj) .where(await this._wherePk(id)); - await this.extractRawQueryAndExec(query); + await this.execAndParse(query); const response = await this.readByPk(id); await this.afterUpdate(response, trx, cookie); @@ -2755,7 +2755,7 @@ class BaseModelSqlv2 { return await qb; } - private async extractRawQueryAndExec( + private async execAndParse( qb: Knex.QueryBuilder, childTable?: Model ) { From f51458b73b26cc96f3c288a9d58d816183cd54eb Mon Sep 17 00:00:00 2001 From: Vijay Rathore Date: Wed, 21 Dec 2022 20:09:35 +0530 Subject: [PATCH 4/4] Correct parameter in delete token --- packages/nocodb/src/lib/meta/api/apiTokenApis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/meta/api/apiTokenApis.ts b/packages/nocodb/src/lib/meta/api/apiTokenApis.ts index 11b9b3627c..dea013346d 100644 --- a/packages/nocodb/src/lib/meta/api/apiTokenApis.ts +++ b/packages/nocodb/src/lib/meta/api/apiTokenApis.ts @@ -14,7 +14,7 @@ export async function apiTokenCreate(req: Request, res: Response) { res.json(await ApiToken.insert({ ...req.body, fk_user_id: req['user'].id })); } export async function apiTokenDelete(req: Request, res: Response) { - const apiToken = await ApiToken.getByToken(req.params.apiTokenId); + const apiToken = await ApiToken.getByToken(req.params.token); if ( !req['user'].roles.includes(OrgUserRoles.SUPER_ADMIN) && apiToken.fk_user_id !== req['user'].id