From 752a0f350e99740540fc06c0fbf79fcc794020f0 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 30 Mar 2022 14:41:39 +0100 Subject: [PATCH 1/2] Make sure that ethereal tests don't fail on jest timeout. --- packages/worker/src/api/routes/tests/realEmail.spec.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/worker/src/api/routes/tests/realEmail.spec.js b/packages/worker/src/api/routes/tests/realEmail.spec.js index d0cfd24010..28d0151284 100644 --- a/packages/worker/src/api/routes/tests/realEmail.spec.js +++ b/packages/worker/src/api/routes/tests/realEmail.spec.js @@ -3,6 +3,9 @@ const { EmailTemplatePurpose } = require("../../../constants") const nodemailer = require("nodemailer") const fetch = require("node-fetch") +// for the real email tests give them a long time to try complete/fail +jest.setTimeout(30000) + describe("/api/global/email", () => { let request = setup.getRequest() let config = setup.getConfig() @@ -27,6 +30,7 @@ describe("/api/global/email", () => { userId: user._id, }) .set(config.defaultHeaders()) + .timeout(20000) // ethereal hiccup, can't test right now if (res.status >= 300) { return @@ -39,7 +43,7 @@ describe("/api/global/email", () => { text = await response.text() } catch (err) { // ethereal hiccup, can't test right now - if (parseInt(err.status) >= 300) { + if (parseInt(err.status) >= 300 || (err && err.errno === "ETIME")) { return } else { throw err From 258434b3ed50df36290ca4207c361a603c9c2330 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 30 Mar 2022 14:31:17 +0100 Subject: [PATCH 2/2] Fix for #5153 - doing it at the mysql level as it seems to be affected by incorrect types in a way that other SQL databases aren't - limits the possible damage this can do. --- packages/server/src/definitions/datasource.ts | 6 +----- packages/server/src/integrations/mysql.ts | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts index 2e2ad25f58..77239da261 100644 --- a/packages/server/src/definitions/datasource.ts +++ b/packages/server/src/definitions/datasource.ts @@ -181,11 +181,7 @@ export interface QueryJson { export interface SqlQuery { sql: string - bindings?: - | string[] - | { - [key: string]: any - } + bindings?: string[] } export interface QueryOptions { diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index 8b2c9ac944..6f009bbd4a 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -80,6 +80,20 @@ module MySQLModule { }, } + function bindingTypeCoerce(bindings: any[]) { + for (let i = 0; i < bindings.length; i++) { + const binding = bindings[i] + if (typeof binding !== "string") { + continue + } + const matches = binding.match(/^\d*/g) + if (matches && matches[0] !== "" && !isNaN(Number(matches[0]))) { + bindings[i] = parseFloat(binding) + } + } + return bindings + } + class MySQLIntegration extends Sql implements DatasourcePlus { private config: MySQLConfig private client: any @@ -122,7 +136,7 @@ module MySQLModule { // Node MySQL is callback based, so we must wrap our call in a promise const response = await this.client.query( query.sql, - query.bindings || [] + bindingTypeCoerce(query.bindings || []) ) return response[0] } finally {