From 377aca0458348b19c47ad607ebd9f6373d1fe3e2 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 26 Jul 2022 10:53:53 +0100 Subject: [PATCH 01/10] Support ObjectId in operator blocks --- packages/server/src/integrations/mongodb.ts | 6 ++-- packages/server/yarn.lock | 35 ++++++++++++--------- packages/worker/yarn.lock | 35 ++++++++++++--------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index 802696ff40..70b4be9e14 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -92,12 +92,12 @@ module MongoDBModule { if (json[field] instanceof Object) { json[field] = self.createObjectIds(json[field]) } - if (field === "_id" && typeof json[field] === "string") { - const id = json["_id"].match( + if ((field === "_id" || field?.startsWith("$")) && typeof json[field] === "string") { + const id = json[field].match( /(?<=objectid\(['"]).*(?=['"]\))/gi )?.[0] if (id) { - json["_id"] = ObjectID.createFromHexString(id) + json[field] = ObjectID.createFromHexString(id) } } } diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 2018d4ec5a..fe229cc137 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1094,12 +1094,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.1.21": - version "1.1.21" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.21.tgz#660e0023f674189b25ca5eabbaff67aebcdf03b8" - integrity sha512-qEf9ggMX6NpVOTe1xfp6NZnbdBV0h0ls9qGGTcMjPakhatB4+3YKSTEDSYYRzY/OLNoKPhcd3aErXuFRR7WKrg== +"@budibase/backend-core@1.1.22-alpha.0": + version "1.1.22-alpha.0" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.22-alpha.0.tgz#2a090a723d35ce4a2e377ac0927fe127213bcbb3" + integrity sha512-77gxcPrjejdqaMaMkbrCS0glYA1jdGo74NpCxdadWx+suU4SMTmOt2jgnEZg20aeKcky2xTpVbjDxIq+Fb2J+g== dependencies: - "@budibase/types" "^1.1.21" + "@budibase/types" "^1.1.22-alpha.0" "@techpass/passport-openidconnect" "0.3.2" aws-sdk "2.1030.0" bcrypt "5.0.1" @@ -1177,13 +1177,13 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/pro@1.1.21": - version "1.1.21" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.21.tgz#c9d21bc82740e9407673088dc8451273368943d9" - integrity sha512-aE20qZmVg/sPp4bV++xwdUnp8+c9wq7Df34P9hYvlhklgh+fxd+2RyautOAfMADRMIZIbtP4/gal95bE/KTPNQ== +"@budibase/pro@1.1.22-alpha.0": + version "1.1.22-alpha.0" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.22-alpha.0.tgz#5718188fbc76ce3c3cf3c633c99c6e59f5846310" + integrity sha512-QL5bhT/BJnoKVV5XH5+s3jSCBzV/JGOy8YQObEjZgCrtTWUjdvMrm5pFinflFGriCfoArmvR3Q51FBpNJQfaag== dependencies: - "@budibase/backend-core" "1.1.21" - "@budibase/types" "1.1.21" + "@budibase/backend-core" "1.1.22-alpha.0" + "@budibase/types" "1.1.22-alpha.0" node-fetch "^2.6.1" "@budibase/standard-components@^0.9.139": @@ -1204,10 +1204,15 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" -"@budibase/types@1.1.21", "@budibase/types@^1.1.21": - version "1.1.21" - resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.21.tgz#4f46cd52f3e52c804e5dba06b0520825da81f84e" - integrity sha512-fR8783evr6SKZggu/QZRgcZfd8SAuG2U+xO8lL0x/pLNZI1vOeTyQXASoPLLzj6uA8bWnPIy8BGd9PK4Mw3XVQ== +"@budibase/types@1.1.22-alpha.0": + version "1.1.22-alpha.0" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.22-alpha.0.tgz#85fb7f37773c710e8232c95104095c26a8dd22ca" + integrity sha512-1gRwAtjEl7Ug1jrYwD9Iudbfgs37nndEBEB6yVdNPKA5SpjG+Fwx30zp6R961zlx1vsSu4iMdwM8IbMsCM8p1g== + +"@budibase/types@^1.1.22-alpha.0": + version "1.1.22" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.22.tgz#a73a8315ad6a04bf0709f2b51cb35058442ce723" + integrity sha512-24sun/hZ2OJZdavhiJt+S8Aip+RdlKeTyUrkf7OuRCUqbxgEIR2J9QOKBSEumuckwTcpzJHBAm4P4G3dXX5Neg== "@bull-board/api@3.7.0": version "3.7.0" diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 60bbdef6b8..1fa3281b49 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -291,12 +291,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.1.21": - version "1.1.21" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.21.tgz#660e0023f674189b25ca5eabbaff67aebcdf03b8" - integrity sha512-qEf9ggMX6NpVOTe1xfp6NZnbdBV0h0ls9qGGTcMjPakhatB4+3YKSTEDSYYRzY/OLNoKPhcd3aErXuFRR7WKrg== +"@budibase/backend-core@1.1.22-alpha.0": + version "1.1.22-alpha.0" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.22-alpha.0.tgz#2a090a723d35ce4a2e377ac0927fe127213bcbb3" + integrity sha512-77gxcPrjejdqaMaMkbrCS0glYA1jdGo74NpCxdadWx+suU4SMTmOt2jgnEZg20aeKcky2xTpVbjDxIq+Fb2J+g== dependencies: - "@budibase/types" "^1.1.21" + "@budibase/types" "^1.1.22-alpha.0" "@techpass/passport-openidconnect" "0.3.2" aws-sdk "2.1030.0" bcrypt "5.0.1" @@ -324,19 +324,24 @@ uuid "8.3.2" zlib "1.0.5" -"@budibase/pro@1.1.21": - version "1.1.21" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.21.tgz#c9d21bc82740e9407673088dc8451273368943d9" - integrity sha512-aE20qZmVg/sPp4bV++xwdUnp8+c9wq7Df34P9hYvlhklgh+fxd+2RyautOAfMADRMIZIbtP4/gal95bE/KTPNQ== +"@budibase/pro@1.1.22-alpha.0": + version "1.1.22-alpha.0" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.22-alpha.0.tgz#5718188fbc76ce3c3cf3c633c99c6e59f5846310" + integrity sha512-QL5bhT/BJnoKVV5XH5+s3jSCBzV/JGOy8YQObEjZgCrtTWUjdvMrm5pFinflFGriCfoArmvR3Q51FBpNJQfaag== dependencies: - "@budibase/backend-core" "1.1.21" - "@budibase/types" "1.1.21" + "@budibase/backend-core" "1.1.22-alpha.0" + "@budibase/types" "1.1.22-alpha.0" node-fetch "^2.6.1" -"@budibase/types@1.1.21", "@budibase/types@^1.1.21": - version "1.1.21" - resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.21.tgz#4f46cd52f3e52c804e5dba06b0520825da81f84e" - integrity sha512-fR8783evr6SKZggu/QZRgcZfd8SAuG2U+xO8lL0x/pLNZI1vOeTyQXASoPLLzj6uA8bWnPIy8BGd9PK4Mw3XVQ== +"@budibase/types@1.1.22-alpha.0": + version "1.1.22-alpha.0" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.22-alpha.0.tgz#85fb7f37773c710e8232c95104095c26a8dd22ca" + integrity sha512-1gRwAtjEl7Ug1jrYwD9Iudbfgs37nndEBEB6yVdNPKA5SpjG+Fwx30zp6R961zlx1vsSu4iMdwM8IbMsCM8p1g== + +"@budibase/types@^1.1.22-alpha.0": + version "1.1.22" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.22.tgz#a73a8315ad6a04bf0709f2b51cb35058442ce723" + integrity sha512-24sun/hZ2OJZdavhiJt+S8Aip+RdlKeTyUrkf7OuRCUqbxgEIR2J9QOKBSEumuckwTcpzJHBAm4P4G3dXX5Neg== "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" From 0ead7fca54032d7e103fec021ebc80110b767f90 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 26 Jul 2022 11:38:34 +0100 Subject: [PATCH 02/10] lint --- packages/server/src/integrations/mongodb.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index 70b4be9e14..e300715781 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -92,7 +92,10 @@ module MongoDBModule { if (json[field] instanceof Object) { json[field] = self.createObjectIds(json[field]) } - if ((field === "_id" || field?.startsWith("$")) && typeof json[field] === "string") { + if ( + (field === "_id" || field?.startsWith("$")) && + typeof json[field] === "string" + ) { const id = json[field].match( /(?<=objectid\(['"]).*(?=['"]\))/gi )?.[0] From d02e5ae87f18c21372fd17443b21d23bac5939db Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Mon, 8 Aug 2022 17:01:56 +0100 Subject: [PATCH 03/10] Add unit tests for ObjectId --- packages/server/__mocks__/mongodb.ts | 2 + .../src/integrations/tests/mongo.spec.js | 66 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/packages/server/__mocks__/mongodb.ts b/packages/server/__mocks__/mongodb.ts index 2a03dc7a7b..3b6db96b78 100644 --- a/packages/server/__mocks__/mongodb.ts +++ b/packages/server/__mocks__/mongodb.ts @@ -31,5 +31,7 @@ module MongoMock { }) } + mongodb.ObjectID = require("mongodb").ObjectID + module.exports = mongodb } diff --git a/packages/server/src/integrations/tests/mongo.spec.js b/packages/server/src/integrations/tests/mongo.spec.js index b0a49521ec..f866048e4b 100644 --- a/packages/server/src/integrations/tests/mongo.spec.js +++ b/packages/server/src/integrations/tests/mongo.spec.js @@ -102,4 +102,70 @@ describe("MongoDB Integration", () => { expect(error).toBeDefined() restore() }) + + it("creates ObjectIds if the _id fields contains a match on ObjectId", async () => { + const query = { + json: { + filter: { + _id: "ObjectId('ACBD12345678ABCD12345678')", + name: "ObjectId('name')" + }, + update: { + _id: "ObjectId('FFFF12345678ABCD12345678')", + name: "ObjectId('updatedName')", + }, + options: { + upsert: false, + }, + }, + extra: { collection: "testCollection", actionTypes: "updateOne" }, + } + await config.integration.update(query) + expect(config.integration.client.updateOne).toHaveBeenCalled() + + const args = config.integration.client.updateOne.mock.calls[0] + expect(args[0]).toEqual({ + _id: mongo.ObjectID.createFromHexString("ACBD12345678ABCD12345678"), + name: "ObjectId('name')", + }) + expect(args[1]).toEqual({ + _id: mongo.ObjectID.createFromHexString("FFFF12345678ABCD12345678"), + name: "ObjectId('updatedName')", + }) + }) + + it("creates ObjectIds if the $ operator fields contains a match on ObjectId", async () => { + const query = { + json: { + filter: { + _id: { + $eq: "ObjectId('ACBD12345678ABCD12345678')", + } + }, + update: { + $set: { + _id: "ObjectId('FFFF12345678ABCD12345678')", + }, + }, + options: { + upsert: false, + }, + }, + extra: { collection: "testCollection", actionTypes: "updateOne" }, + } + await config.integration.update(query) + expect(config.integration.client.updateOne).toHaveBeenCalled() + + const args = config.integration.client.updateOne.mock.calls[0] + expect(args[0]).toEqual({ + _id: { + $eq: mongo.ObjectID.createFromHexString("ACBD12345678ABCD12345678"), + } + }) + expect(args[1]).toEqual({ + $set: { + _id: mongo.ObjectID.createFromHexString("FFFF12345678ABCD12345678"), + } + }) + }) }) From 98d8080826e6d639e7d8c4bf7143be816b6646a8 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Mon, 8 Aug 2022 17:53:17 +0100 Subject: [PATCH 04/10] Bug fix findOneAndUpdate --- packages/server/__mocks__/mongodb.ts | 2 + packages/server/src/integrations/mongodb.ts | 5 +- .../src/integrations/tests/mongo.spec.js | 48 ++++++++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/packages/server/__mocks__/mongodb.ts b/packages/server/__mocks__/mongodb.ts index 3b6db96b78..92ec89227f 100644 --- a/packages/server/__mocks__/mongodb.ts +++ b/packages/server/__mocks__/mongodb.ts @@ -8,6 +8,7 @@ module MongoMock { this.insertMany = jest.fn(() => ({ toArray: () => [] })) this.find = jest.fn(() => ({ toArray: () => [] })) this.findOne = jest.fn() + this.findOneAndUpdate = jest.fn() this.count = jest.fn() this.deleteOne = jest.fn() this.deleteMany = jest.fn(() => ({ toArray: () => [] })) @@ -19,6 +20,7 @@ module MongoMock { find: this.find, insertMany: this.insertMany, findOne: this.findOne, + findOneAndUpdate: this.findOneAndUpdate, count: this.count, deleteOne: this.deleteOne, deleteMany: this.deleteMany, diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index e300715781..a520cdb157 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -179,7 +179,10 @@ module MongoDBModule { return await collection.findOne(json) } case "findOneAndUpdate": { - let findAndUpdateJson = json as { + if (typeof query.json === "string") { + json = this.parseQueryParams(query.json, "update") + } + let findAndUpdateJson = this.createObjectIds(json) as { filter: FilterQuery update: UpdateQuery options: FindOneAndUpdateOption diff --git a/packages/server/src/integrations/tests/mongo.spec.js b/packages/server/src/integrations/tests/mongo.spec.js index f866048e4b..555188a526 100644 --- a/packages/server/src/integrations/tests/mongo.spec.js +++ b/packages/server/src/integrations/tests/mongo.spec.js @@ -132,6 +132,9 @@ describe("MongoDB Integration", () => { _id: mongo.ObjectID.createFromHexString("FFFF12345678ABCD12345678"), name: "ObjectId('updatedName')", }) + expect(args[2]).toEqual({ + upsert: false + }) }) it("creates ObjectIds if the $ operator fields contains a match on ObjectId", async () => { @@ -148,7 +151,7 @@ describe("MongoDB Integration", () => { }, }, options: { - upsert: false, + upsert: true, }, }, extra: { collection: "testCollection", actionTypes: "updateOne" }, @@ -167,5 +170,48 @@ describe("MongoDB Integration", () => { _id: mongo.ObjectID.createFromHexString("FFFF12345678ABCD12345678"), } }) + expect(args[2]).toEqual({ + upsert: true + }) + }) + + it("supports findOneAndUpdate", async () => { + const query = { + json: { + filter: { + _id: { + $eq: "ObjectId('ACBD12345678ABCD12345678')", + } + }, + update: { + $set: { + name: "UPDATED", + age: 99 + }, + }, + options: { + upsert: false, + }, + }, + extra: { collection: "testCollection", actionTypes: "findOneAndUpdate" }, + } + await config.integration.read(query) + expect(config.integration.client.findOneAndUpdate).toHaveBeenCalled() + + const args = config.integration.client.findOneAndUpdate.mock.calls[0] + expect(args[0]).toEqual({ + _id: { + $eq: mongo.ObjectID.createFromHexString("ACBD12345678ABCD12345678"), + } + }) + expect(args[1]).toEqual({ + $set: { + name: "UPDATED", + age: 99 + } + }) + expect(args[2]).toEqual({ + upsert: false + }) }) }) From 88f06539a4d278f5a93e8438b00d88fda7b6a440 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Mon, 8 Aug 2022 21:56:55 +0100 Subject: [PATCH 05/10] Nested braces parse fix added for MongoDB --- packages/server/src/integrations/mongodb.ts | 16 ++++++ .../src/integrations/tests/mongo.spec.js | 52 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index a520cdb157..d24cb51fcc 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -118,6 +118,22 @@ module MongoDBModule { parseQueryParams(params: string, mode: string) { let queryParams = params.split(/(?<=}),[\n\s]*(?={)/g) + if (queryParams.length > 3) { + for (let i = 0; i < queryParams.length; i++) { + const openCount = queryParams[i].match(/{/g)?.length ?? 0 + const closeCount = queryParams[i].match(/}/g)?.length ?? 0 + if ((openCount + closeCount) % 2 !== 0) { + if (openCount > closeCount) { + queryParams[i] += `, ${queryParams[i+1]}` + queryParams.splice(i+1, 1) + } else { + queryParams[i-1] += `, ${queryParams[i]}` + queryParams.splice(i, 1) + i-- + } + } + } + } let group1 = queryParams[0] ? JSON.parse(queryParams[0]) : {} let group2 = queryParams[1] ? JSON.parse(queryParams[1]) : {} let group3 = queryParams[2] ? JSON.parse(queryParams[2]) : {} diff --git a/packages/server/src/integrations/tests/mongo.spec.js b/packages/server/src/integrations/tests/mongo.spec.js index 555188a526..17561723b3 100644 --- a/packages/server/src/integrations/tests/mongo.spec.js +++ b/packages/server/src/integrations/tests/mongo.spec.js @@ -214,4 +214,56 @@ describe("MongoDB Integration", () => { upsert: false }) }) + + it("can parse nested objects with arrays", async () => { + const query = { + json: `{ + "_id": { + "$eq": "ObjectId('ACBD12345678ABCD12345678')" + } + }, + { + "$set": { + "value": { + "data": [ + { "cid": 1 }, + { "cid": 2 }, + { "nested": { + "name": "test" + }} + ] + } + } + }, + { + "upsert": true + }`, + extra: { collection: "testCollection", actionTypes: "updateOne" }, + } + await config.integration.update(query) + expect(config.integration.client.updateOne).toHaveBeenCalled() + + const args = config.integration.client.updateOne.mock.calls[0] + expect(args[0]).toEqual({ + _id: { + $eq: mongo.ObjectID.createFromHexString("ACBD12345678ABCD12345678"), + } + }) + expect(args[1]).toEqual({ + $set: { + value: { + data: [ + { cid: 1 }, + { cid: 2 }, + { nested: { + name: "test" + }} + ] + }, + }, + }) + expect(args[2]).toEqual({ + upsert: true + }) + }) }) From e23d29b7efb4d21a46562594a2821cff329bd102 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Mon, 8 Aug 2022 21:57:36 +0100 Subject: [PATCH 06/10] lint --- packages/server/src/integrations/mongodb.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index d24cb51fcc..0ae9515a0e 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -124,10 +124,10 @@ module MongoDBModule { const closeCount = queryParams[i].match(/}/g)?.length ?? 0 if ((openCount + closeCount) % 2 !== 0) { if (openCount > closeCount) { - queryParams[i] += `, ${queryParams[i+1]}` - queryParams.splice(i+1, 1) + queryParams[i] += `, ${queryParams[i + 1]}` + queryParams.splice(i + 1, 1) } else { - queryParams[i-1] += `, ${queryParams[i]}` + queryParams[i - 1] += `, ${queryParams[i]}` queryParams.splice(i, 1) i-- } From 40c846ce8f44ae14e8d5cd418bd1fab16d531c6c Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 9 Aug 2022 17:27:51 +0100 Subject: [PATCH 07/10] Handle braces within quotes --- packages/server/src/integrations/mongodb.ts | 41 +++++++------- .../src/integrations/tests/mongo.spec.js | 54 +++++++++++++++++++ 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index 0ae9515a0e..9bfc105144 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -117,26 +117,31 @@ module MongoDBModule { } parseQueryParams(params: string, mode: string) { - let queryParams = params.split(/(?<=}),[\n\s]*(?={)/g) - if (queryParams.length > 3) { - for (let i = 0; i < queryParams.length; i++) { - const openCount = queryParams[i].match(/{/g)?.length ?? 0 - const closeCount = queryParams[i].match(/}/g)?.length ?? 0 - if ((openCount + closeCount) % 2 !== 0) { - if (openCount > closeCount) { - queryParams[i] += `, ${queryParams[i + 1]}` - queryParams.splice(i + 1, 1) - } else { - queryParams[i - 1] += `, ${queryParams[i]}` - queryParams.splice(i, 1) - i-- - } - } + let queryParams = [] + let openCount = 0 + let inQuotes = false + let i = 0 + let startIndex = 0 + for (let c of params) { + if (c === '"') { + inQuotes = !inQuotes } + if (c === '{' && !inQuotes) { + openCount++ + if (openCount === 1) { + startIndex = i + } + } else if (c === '}' && !inQuotes) { + if (openCount === 1) { + queryParams.push(JSON.parse(params.substring(startIndex, i+1))) + } + openCount-- + } + i++ } - let group1 = queryParams[0] ? JSON.parse(queryParams[0]) : {} - let group2 = queryParams[1] ? JSON.parse(queryParams[1]) : {} - let group3 = queryParams[2] ? JSON.parse(queryParams[2]) : {} + let group1 = queryParams[0] ?? {} + let group2 = queryParams[1] ?? {} + let group3 = queryParams[2] ?? {} if (mode === "update") { return { filter: group1, diff --git a/packages/server/src/integrations/tests/mongo.spec.js b/packages/server/src/integrations/tests/mongo.spec.js index 17561723b3..02d37b18a2 100644 --- a/packages/server/src/integrations/tests/mongo.spec.js +++ b/packages/server/src/integrations/tests/mongo.spec.js @@ -266,4 +266,58 @@ describe("MongoDB Integration", () => { upsert: true }) }) + + it("ignores braces within strings when parsing nested objects", async () => { + const query = { + json: `{ + "_id": { + "$eq": "ObjectId('ACBD12345678ABCD12345678')" + } + }, + { + "$set": { + "value": { + "data": [ + { "cid": 1 }, + { "cid": 2 }, + { "nested": { + "name": "te}st" + }} + ] + } + } + }, + { + "upsert": true, + "extra": "ad{d" + }`, + extra: { collection: "testCollection", actionTypes: "updateOne" }, + } + await config.integration.update(query) + expect(config.integration.client.updateOne).toHaveBeenCalled() + + const args = config.integration.client.updateOne.mock.calls[0] + expect(args[0]).toEqual({ + _id: { + $eq: mongo.ObjectID.createFromHexString("ACBD12345678ABCD12345678"), + } + }) + expect(args[1]).toEqual({ + $set: { + value: { + data: [ + { cid: 1 }, + { cid: 2 }, + { nested: { + name: "te}st" + }} + ] + }, + }, + }) + expect(args[2]).toEqual({ + upsert: true, + extra: "ad{d" + }) + }) }) From f7c816bce952ddf6234764d0c06296115c26202b Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Tue, 9 Aug 2022 17:28:21 +0100 Subject: [PATCH 08/10] lint --- packages/server/src/integrations/mongodb.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index 9bfc105144..f3be29e386 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -126,14 +126,14 @@ module MongoDBModule { if (c === '"') { inQuotes = !inQuotes } - if (c === '{' && !inQuotes) { + if (c === "{" && !inQuotes) { openCount++ if (openCount === 1) { startIndex = i } - } else if (c === '}' && !inQuotes) { + } else if (c === "}" && !inQuotes) { if (openCount === 1) { - queryParams.push(JSON.parse(params.substring(startIndex, i+1))) + queryParams.push(JSON.parse(params.substring(startIndex, i + 1))) } openCount-- } From 334d9a956deeea96ae0f74001d23a414cfc01b5a Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Wed, 10 Aug 2022 10:57:42 +0100 Subject: [PATCH 09/10] Ignore escaped double quotes within strings --- packages/server/src/integrations/mongodb.ts | 2 +- packages/server/src/integrations/tests/mongo.spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index f3be29e386..cdc1b581b6 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -123,7 +123,7 @@ module MongoDBModule { let i = 0 let startIndex = 0 for (let c of params) { - if (c === '"') { + if (c === '"' && (i > 0 && params[i-1] !== '\\')) { inQuotes = !inQuotes } if (c === "{" && !inQuotes) { diff --git a/packages/server/src/integrations/tests/mongo.spec.js b/packages/server/src/integrations/tests/mongo.spec.js index 02d37b18a2..9687723528 100644 --- a/packages/server/src/integrations/tests/mongo.spec.js +++ b/packages/server/src/integrations/tests/mongo.spec.js @@ -289,7 +289,7 @@ describe("MongoDB Integration", () => { }, { "upsert": true, - "extra": "ad{d" + "extra": "ad\\"{\\"d" }`, extra: { collection: "testCollection", actionTypes: "updateOne" }, } @@ -317,7 +317,7 @@ describe("MongoDB Integration", () => { }) expect(args[2]).toEqual({ upsert: true, - extra: "ad{d" + extra: "ad\"{\"d" }) }) }) From 9ce34aa4c0d46282aaecf85372899863fd1d717f Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Wed, 10 Aug 2022 10:58:11 +0100 Subject: [PATCH 10/10] lint --- packages/server/src/integrations/mongodb.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index cdc1b581b6..35420c456c 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -123,7 +123,7 @@ module MongoDBModule { let i = 0 let startIndex = 0 for (let c of params) { - if (c === '"' && (i > 0 && params[i-1] !== '\\')) { + if (c === '"' && i > 0 && params[i - 1] !== "\\") { inQuotes = !inQuotes } if (c === "{" && !inQuotes) {