merge google accounts, improve connection pooling for RDBMS

This commit is contained in:
Martin McKeaveney 2021-06-01 15:00:28 +01:00
parent cb62d0b36a
commit 36b39ef4df
4 changed files with 54 additions and 20 deletions

View File

@ -2,20 +2,26 @@ const env = require("../../environment")
const jwt = require("jsonwebtoken") const jwt = require("jsonwebtoken")
const database = require("../../db") const database = require("../../db")
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy 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) { async function authenticate(token, tokenSecret, profile, done) {
// Check the user exists in the instance DB by email // Check the user exists in the instance DB by email
const db = database.getDB(StaticDatabases.GLOBAL.name) const db = database.getDB(StaticDatabases.GLOBAL.name)
let dbUser let dbUser
const userId = generateGlobalUserID(profile.id) const userId = generateGlobalUserID(profile.id)
try { try {
// use the google profile id // use the google profile id
dbUser = await db.get(userId) dbUser = await db.get(userId)
} catch (err) { } catch (err) {
console.error("Google user not found. Creating..") console.log("Google user not found. Creating..")
// create the user // create the user
const user = { const user = {
_id: userId, _id: userId,
@ -26,6 +32,28 @@ async function authenticate(token, tokenSecret, profile, done) {
}, },
...profile._json, ...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) const response = await db.post(user)
dbUser = user dbUser = user

View File

@ -4,6 +4,7 @@ const {
getDatasourceParams, getDatasourceParams,
getQueryParams, getQueryParams,
} = require("../../db/utils") } = require("../../db/utils")
const { integrations } = require("../../integrations")
exports.fetch = async function (ctx) { exports.fetch = async function (ctx) {
const database = new CouchDB(ctx.appId) const database = new CouchDB(ctx.appId)
@ -28,6 +29,12 @@ exports.save = async function (ctx) {
const response = await db.post(datasource) const response = await db.post(datasource)
datasource._rev = response.rev 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.status = 200
ctx.message = "Datasource saved successfully." ctx.message = "Datasource saved successfully."
ctx.body = datasource ctx.body = datasource

View File

@ -1,8 +1,6 @@
const sqlServer = require("mssql") const sqlServer = require("mssql")
const { FIELD_TYPES } = require("./Integration") const { FIELD_TYPES } = require("./Integration")
let pool
const SCHEMA = { const SCHEMA = {
docs: "https://github.com/tediousjs/node-mssql", docs: "https://github.com/tediousjs/node-mssql",
description: description:
@ -53,19 +51,21 @@ const SCHEMA = {
} }
class SqlServerIntegration { class SqlServerIntegration {
static pool
constructor(config) { constructor(config) {
this.config = config this.config = config
this.config.options = { this.config.options = {
encrypt: this.config.encrypt, encrypt: this.config.encrypt,
} }
delete this.config.encrypt delete this.config.encrypt
if (!pool) { if (!this.pool) {
pool = new sqlServer.ConnectionPool(this.config) this.pool = new sqlServer.ConnectionPool(this.config)
} }
} }
async connect() { async connect() {
const client = await pool.connect() const client = await this.pool.connect()
this.client = client.request() this.client = client.request()
} }

View File

@ -1,8 +1,6 @@
const { Pool } = require("pg") const { Pool } = require("pg")
const { FIELD_TYPES } = require("./Integration") const { FIELD_TYPES } = require("./Integration")
let pool
const SCHEMA = { const SCHEMA = {
docs: "https://node-postgres.com", docs: "https://node-postgres.com",
friendlyName: "PostgreSQL", friendlyName: "PostgreSQL",
@ -35,7 +33,8 @@ const SCHEMA = {
required: true, required: true,
}, },
ssl: { ssl: {
type: FIELD_TYPES.OBJECT, type: FIELD_TYPES.BOOLEAN,
default: false,
required: false, required: false,
}, },
}, },
@ -56,28 +55,28 @@ const SCHEMA = {
} }
class PostgresIntegration { class PostgresIntegration {
static pool
constructor(config) { constructor(config) {
this.config = config this.config = config
if (this.config.ssl && this.config.ssl.rejectUnauthorized) { if (this.config.ssl) {
this.config.ssl.rejectUnauthorized = this.config.ssl = {
this.config.ssl.rejectUnauthorized === "true" rejectUnauthorized: true,
}
} }
if (!pool) { if (!this.pool) {
pool = new Pool(this.config) this.pool = new Pool(this.config)
} }
this.client = this.pool
} }
async query(sql) { async query(sql) {
try { try {
this.client = await pool.connect()
return await this.client.query(sql) return await this.client.query(sql)
} catch (err) { } catch (err) {
throw new Error(err) throw new Error(err)
} finally {
if (this.client) {
this.client.release()
}
} }
} }