Adding mechanism for lookup of userId/email to tenantId.

This commit is contained in:
mike12345567 2021-07-23 19:22:04 +01:00
parent bd301cf972
commit 9a9c552629
2 changed files with 57 additions and 11 deletions

View File

@ -7,33 +7,55 @@ const {
} = require("@budibase/auth/db") } = require("@budibase/auth/db")
const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils
const { UserStatus, EmailTemplatePurpose } = require("../../../constants") const { UserStatus, EmailTemplatePurpose } = require("../../../constants")
const { DEFAULT_TENANT_ID } = require("@budibase/auth/constants")
const { checkInviteCode } = require("../../../utilities/redis") const { checkInviteCode } = require("../../../utilities/redis")
const { sendEmail } = require("../../../utilities/email") const { sendEmail } = require("../../../utilities/email")
const { user: userCache } = require("@budibase/auth/cache") const { user: userCache } = require("@budibase/auth/cache")
const { invalidateSessions } = require("@budibase/auth/sessions") const { invalidateSessions } = require("@budibase/auth/sessions")
const CouchDB = require("../../../db") const CouchDB = require("../../../db")
const env = require("../../../environment")
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants 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) const db = new CouchDB(PLATFORM_INFO_DB)
let tenants const getDoc = async id => {
try { if (!id) {
tenants = await db.get(TENANT_DOC) return null
} catch (err) {
// if theres an error don't worry, we'll just write it in
} }
if (!tenants || !Array.isArray(tenants.tenantIds)) { try {
return await db.get(id)
} catch (err) {
return { _id: id }
}
}
let [tenants, userIdDoc, emailDoc] = await Promise.all([
getDoc(TENANT_DOC),
getDoc(userId),
getDoc(email),
])
if (!Array.isArray(tenants.tenantIds)) {
tenants = { tenants = {
_id: TENANT_DOC, _id: TENANT_DOC,
tenantIds: [], 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) { if (tenants.tenantIds.indexOf(tenantId) === -1) {
tenants.tenantIds.push(tenantId) tenants.tenantIds.push(tenantId)
await db.put(tenants) promises.push(db.put(tenants))
} }
await Promise.all(promises)
} }
async function doesTenantExist(tenantId) { async function doesTenantExist(tenantId) {
@ -67,8 +89,7 @@ async function saveUser(user, tenantId) {
throw "No tenancy specified." throw "No tenancy specified."
} }
const db = getGlobalDB(tenantId) const db = getGlobalDB(tenantId)
await tryAddTenant(tenantId) let { email, password, _id } = user
const { email, password, _id } = user
// make sure another user isn't using the same email // make sure another user isn't using the same email
let dbUser let dbUser
if (email) { if (email) {
@ -90,10 +111,11 @@ async function saveUser(user, tenantId) {
throw "Password must be specified." throw "Password must be specified."
} }
_id = _id || generateGlobalUserID()
user = { user = {
...dbUser, ...dbUser,
...user, ...user,
_id: _id || generateGlobalUserID(), _id,
password: hashedPassword, password: hashedPassword,
tenantId, tenantId,
} }
@ -110,6 +132,7 @@ async function saveUser(user, tenantId) {
password: hashedPassword, password: hashedPassword,
...user, ...user,
}) })
await tryAddTenant(tenantId, _id, email)
await userCache.invalidateUser(response.id) await userCache.invalidateUser(response.id)
return { return {
_id: response.id, _id: response.id,
@ -264,6 +287,28 @@ exports.find = async ctx => {
ctx.body = user 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 => { exports.invite = async ctx => {
let { email, userInfo } = ctx.request.body let { email, userInfo } = ctx.request.body
const tenantId = ctx.user.tenantId const tenantId = ctx.user.tenantId

View File

@ -94,6 +94,7 @@ router
controller.adminUser controller.adminUser
) )
.get("/api/global/users/self", controller.getSelf) .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) // global endpoint but needs to come at end (blocks other endpoints otherwise)
.get("/api/global/users/:id", adminOnly, controller.find) .get("/api/global/users/:id", adminOnly, controller.find)