From 19ad28a4910cfd8d4017dd2e4135bc25819df284 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Jul 2021 19:22:04 +0100 Subject: [PATCH] Adding mechanism for lookup of userId/email to tenantId. --- .../src/api/controllers/global/users.js | 67 ++++++++++++++++--- .../worker/src/api/routes/global/users.js | 1 + 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/packages/worker/src/api/controllers/global/users.js b/packages/worker/src/api/controllers/global/users.js index e0d1e6f107..9ec2922543 100644 --- a/packages/worker/src/api/controllers/global/users.js +++ b/packages/worker/src/api/controllers/global/users.js @@ -7,33 +7,55 @@ const { } = require("@budibase/auth/db") const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils const { UserStatus, EmailTemplatePurpose } = require("../../../constants") +const { DEFAULT_TENANT_ID } = require("@budibase/auth/constants") const { checkInviteCode } = require("../../../utilities/redis") const { sendEmail } = require("../../../utilities/email") const { user: userCache } = require("@budibase/auth/cache") const { invalidateSessions } = require("@budibase/auth/sessions") const CouchDB = require("../../../db") +const env = require("../../../environment") const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants -async function tryAddTenant(tenantId) { + +async function tryAddTenant(tenantId, userId, email) { const db = new CouchDB(PLATFORM_INFO_DB) - let tenants - try { - tenants = await db.get(TENANT_DOC) - } catch (err) { - // if theres an error don't worry, we'll just write it in + const getDoc = async id => { + if (!id) { + return null + } + try { + return await db.get(id) + } catch (err) { + return { _id: id } + } } - if (!tenants || !Array.isArray(tenants.tenantIds)) { + let [tenants, userIdDoc, emailDoc] = await Promise.all([ + getDoc(TENANT_DOC), + getDoc(userId), + getDoc(email), + ]) + if (!Array.isArray(tenants.tenantIds)) { tenants = { _id: TENANT_DOC, tenantIds: [], } } + let promises = [] + if (userIdDoc) { + userIdDoc.tenantId = tenantId + promises.push(db.put(userIdDoc)) + } + if (emailDoc) { + emailDoc.tenantId = tenantId + promises.push(db.put(emailDoc)) + } if (tenants.tenantIds.indexOf(tenantId) === -1) { tenants.tenantIds.push(tenantId) - await db.put(tenants) + promises.push(db.put(tenants)) } + await Promise.all(promises) } async function doesTenantExist(tenantId) { @@ -67,8 +89,7 @@ async function saveUser(user, tenantId) { throw "No tenancy specified." } const db = getGlobalDB(tenantId) - await tryAddTenant(tenantId) - const { email, password, _id } = user + let { email, password, _id } = user // make sure another user isn't using the same email let dbUser if (email) { @@ -90,10 +111,11 @@ async function saveUser(user, tenantId) { throw "Password must be specified." } + _id = _id || generateGlobalUserID() user = { ...dbUser, ...user, - _id: _id || generateGlobalUserID(), + _id, password: hashedPassword, tenantId, } @@ -110,6 +132,7 @@ async function saveUser(user, tenantId) { password: hashedPassword, ...user, }) + await tryAddTenant(tenantId, _id, email) await userCache.invalidateUser(response.id) return { _id: response.id, @@ -264,6 +287,28 @@ exports.find = async ctx => { ctx.body = user } +exports.tenantLookup = async ctx => { + const id = ctx.params.id + // lookup, could be email or userId, either will return a doc + const db = new CouchDB(PLATFORM_INFO_DB) + let tenantId = null + try { + const doc = await db.get(id) + if (doc && doc.tenantId) { + tenantId = doc.tenantId + } + } catch (err) { + if (!env.MULTI_TENANCY) { + tenantId = DEFAULT_TENANT_ID + } else { + ctx.throw(400, "No tenant found.") + } + } + ctx.body = { + tenantId, + } +} + exports.invite = async ctx => { let { email, userInfo } = ctx.request.body const tenantId = ctx.user.tenantId diff --git a/packages/worker/src/api/routes/global/users.js b/packages/worker/src/api/routes/global/users.js index 8be81c4930..8359835952 100644 --- a/packages/worker/src/api/routes/global/users.js +++ b/packages/worker/src/api/routes/global/users.js @@ -94,6 +94,7 @@ router controller.adminUser ) .get("/api/global/users/self", controller.getSelf) + .get("/api/global/users/tenant/:id", adminOnly, controller.tenantLookup) // global endpoint but needs to come at end (blocks other endpoints otherwise) .get("/api/global/users/:id", adminOnly, controller.find)