From 36b39ef4df872e5c122686787a6e4fe88f20e0da Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 1 Jun 2021 15:00:28 +0100 Subject: [PATCH 1/2] merge google accounts, improve connection pooling for RDBMS --- .../auth/src/middleware/passport/google.js | 32 +++++++++++++++++-- .../server/src/api/controllers/datasource.js | 7 ++++ .../src/integrations/microsoftSqlServer.js | 10 +++--- packages/server/src/integrations/postgres.js | 25 +++++++-------- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 407772ebf0..b56a19bcc3 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -2,20 +2,26 @@ const env = require("../../environment") const jwt = require("jsonwebtoken") const database = require("../../db") const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy -const { StaticDatabases, generateGlobalUserID } = require("../../db/utils") +const { + StaticDatabases, + generateGlobalUserID, + ViewNames, +} = require("../../db/utils") async function authenticate(token, tokenSecret, profile, done) { // Check the user exists in the instance DB by email const db = database.getDB(StaticDatabases.GLOBAL.name) let dbUser + const userId = generateGlobalUserID(profile.id) try { // use the google profile id dbUser = await db.get(userId) } catch (err) { - console.error("Google user not found. Creating..") + console.log("Google user not found. Creating..") + // create the user const user = { _id: userId, @@ -26,6 +32,28 @@ async function authenticate(token, tokenSecret, profile, done) { }, ...profile._json, } + + // check if an account with the google email address exists locally + const users = await db.query(`database/${ViewNames.USER_BY_EMAIL}`, { + key: profile._json.email, + include_docs: true, + }) + + // Google user already exists by email + if (users.rows.length > 0) { + const existing = users.rows[0].doc + + console.log(existing) + + // remove the local account to avoid conflicts + await db.remove(existing._id, existing._rev) + + // merge with existing account + user.roles = existing.roles + user.builder = existing.builder + user.admin = existing.admin + } + const response = await db.post(user) dbUser = user diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 4f3ebdb609..fa4bdf289b 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -4,6 +4,7 @@ const { getDatasourceParams, getQueryParams, } = require("../../db/utils") +const { integrations } = require("../../integrations") exports.fetch = async function (ctx) { const database = new CouchDB(ctx.appId) @@ -28,6 +29,12 @@ exports.save = async function (ctx) { const response = await db.post(datasource) datasource._rev = response.rev + // Drain connection pools when configuration is changed + const pool = integrations[datasource.source].pool + if (pool) { + await pool.end() + } + ctx.status = 200 ctx.message = "Datasource saved successfully." ctx.body = datasource diff --git a/packages/server/src/integrations/microsoftSqlServer.js b/packages/server/src/integrations/microsoftSqlServer.js index 05b92f1815..3dc5676e94 100644 --- a/packages/server/src/integrations/microsoftSqlServer.js +++ b/packages/server/src/integrations/microsoftSqlServer.js @@ -1,8 +1,6 @@ const sqlServer = require("mssql") const { FIELD_TYPES } = require("./Integration") -let pool - const SCHEMA = { docs: "https://github.com/tediousjs/node-mssql", description: @@ -53,19 +51,21 @@ const SCHEMA = { } class SqlServerIntegration { + static pool + constructor(config) { this.config = config this.config.options = { encrypt: this.config.encrypt, } delete this.config.encrypt - if (!pool) { - pool = new sqlServer.ConnectionPool(this.config) + if (!this.pool) { + this.pool = new sqlServer.ConnectionPool(this.config) } } async connect() { - const client = await pool.connect() + const client = await this.pool.connect() this.client = client.request() } diff --git a/packages/server/src/integrations/postgres.js b/packages/server/src/integrations/postgres.js index ed49e42f1c..ebc39a31a4 100644 --- a/packages/server/src/integrations/postgres.js +++ b/packages/server/src/integrations/postgres.js @@ -1,8 +1,6 @@ const { Pool } = require("pg") const { FIELD_TYPES } = require("./Integration") -let pool - const SCHEMA = { docs: "https://node-postgres.com", friendlyName: "PostgreSQL", @@ -35,7 +33,8 @@ const SCHEMA = { required: true, }, ssl: { - type: FIELD_TYPES.OBJECT, + type: FIELD_TYPES.BOOLEAN, + default: false, required: false, }, }, @@ -56,28 +55,28 @@ const SCHEMA = { } class PostgresIntegration { + static pool + constructor(config) { this.config = config - if (this.config.ssl && this.config.ssl.rejectUnauthorized) { - this.config.ssl.rejectUnauthorized = - this.config.ssl.rejectUnauthorized === "true" + if (this.config.ssl) { + this.config.ssl = { + rejectUnauthorized: true, + } } - if (!pool) { - pool = new Pool(this.config) + if (!this.pool) { + this.pool = new Pool(this.config) } + + this.client = this.pool } async query(sql) { try { - this.client = await pool.connect() return await this.client.query(sql) } catch (err) { throw new Error(err) - } finally { - if (this.client) { - this.client.release() - } } } From a00357838d29b6cdf13c6f9d7c719261cee2eddb Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 1 Jun 2021 15:03:19 +0100 Subject: [PATCH 2/2] remove log --- packages/auth/src/middleware/passport/google.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index b56a19bcc3..96a0907536 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -43,8 +43,6 @@ async function authenticate(token, tokenSecret, profile, done) { if (users.rows.length > 0) { const existing = users.rows[0].doc - console.log(existing) - // remove the local account to avoid conflicts await db.remove(existing._id, existing._rev)