From 8241df2581ebbe226491b7fb6bb2329a5641052f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 19 Jul 2021 12:57:52 +0100 Subject: [PATCH] Fixing some tenancy issues. --- packages/auth/src/utils.js | 14 ++++++++---- .../src/api/controllers/row/internal.js | 10 ++++----- .../server/src/api/routes/tests/row.spec.js | 2 +- packages/server/src/utilities/rowProcessor.js | 2 +- .../src/api/controllers/admin/tenants.js | 11 ++++++++++ .../worker/src/api/controllers/admin/users.js | 22 ++++++++++++++++--- .../worker/src/api/routes/admin/tenants.js | 15 +++++++++++++ 7 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 packages/worker/src/api/controllers/admin/tenants.js create mode 100644 packages/worker/src/api/routes/admin/tenants.js diff --git a/packages/auth/src/utils.js b/packages/auth/src/utils.js index fe9230ea29..79d299065e 100644 --- a/packages/auth/src/utils.js +++ b/packages/auth/src/utils.js @@ -9,6 +9,7 @@ const { options } = require("./middleware/passport/jwt") const { createUserEmailView } = require("./db/views") const { getDB } = require("./db") const { getGlobalDB } = require("./db/utils") +const { DEFAULT_TENANT_ID } = require("./constants") const APP_PREFIX = DocumentTypes.APP + SEPARATOR @@ -103,11 +104,16 @@ exports.isClient = ctx => { exports.lookupTenantId = async userId => { const db = getDB(StaticDatabases.PLATFORM_INFO.name) - const doc = await db.get(userId) - if (!doc || !doc.tenantId) { - throw "Unable to find tenant" + let tenantId = DEFAULT_TENANT_ID + try { + const doc = await db.get(userId) + if (doc && doc.tenantId) { + tenantId = doc.tenantId + } + } catch (err) { + // just return the default } - return doc.tenantId + return tenantId } /** diff --git a/packages/server/src/api/controllers/row/internal.js b/packages/server/src/api/controllers/row/internal.js index f0009a4413..400226719b 100644 --- a/packages/server/src/api/controllers/row/internal.js +++ b/packages/server/src/api/controllers/row/internal.js @@ -161,7 +161,7 @@ exports.fetchView = async ctx => { schema: {}, } } - rows = await outputProcessing(appId, table, response.rows) + rows = await outputProcessing(ctx, table, response.rows) } if (calculation === CALCULATION_TYPES.STATS) { @@ -204,7 +204,7 @@ exports.fetch = async ctx => { ) rows = response.rows.map(row => row.doc) } - return outputProcessing(appId, table, rows) + return outputProcessing(ctx, table, rows) } exports.find = async ctx => { @@ -212,7 +212,7 @@ exports.find = async ctx => { const db = new CouchDB(appId) const table = await db.get(ctx.params.tableId) let row = await findRow(ctx, db, ctx.params.tableId, ctx.params.rowId) - row = await outputProcessing(appId, table, row) + row = await outputProcessing(ctx, table, row) return row } @@ -290,7 +290,7 @@ exports.search = async ctx => { // Enrich search results with relationships if (response.rows && response.rows.length) { const table = await db.get(tableId) - response.rows = await outputProcessing(appId, table, response.rows) + response.rows = await outputProcessing(ctx, table, response.rows) } return response @@ -327,7 +327,7 @@ exports.fetchEnrichedRow = async ctx => { }) // need to include the IDs in these rows for any links they may have let linkedRows = await outputProcessing( - appId, + ctx, table, response.rows.map(row => row.doc) ) diff --git a/packages/server/src/api/routes/tests/row.spec.js b/packages/server/src/api/routes/tests/row.spec.js index 9515384608..d089d7775d 100644 --- a/packages/server/src/api/routes/tests/row.spec.js +++ b/packages/server/src/api/routes/tests/row.spec.js @@ -387,7 +387,7 @@ describe("/rows", () => { }) // the environment needs configured for this await setup.switchToSelfHosted(async () => { - const enriched = await outputProcessing(config.getAppId(), table, [row]) + const enriched = await outputProcessing({ appId: config.getAppId() }, table, [row]) expect(enriched[0].attachment[0].url).toBe( `/prod-budi-app-assets/${config.getAppId()}/attachments/test/thing.csv` ) diff --git a/packages/server/src/utilities/rowProcessor.js b/packages/server/src/utilities/rowProcessor.js index 2a83ae5d2b..618897383b 100644 --- a/packages/server/src/utilities/rowProcessor.js +++ b/packages/server/src/utilities/rowProcessor.js @@ -207,7 +207,7 @@ exports.outputProcessing = async (ctx, table, rows) => { wasArray = false } // attach any linked row information - let enriched = await linkRows.attachFullLinkedDocs(appId, table, rows) + let enriched = await linkRows.attachFullLinkedDocs(ctx, table, rows) // process formulas enriched = processFormulas(table, enriched) diff --git a/packages/worker/src/api/controllers/admin/tenants.js b/packages/worker/src/api/controllers/admin/tenants.js new file mode 100644 index 0000000000..76abb4510e --- /dev/null +++ b/packages/worker/src/api/controllers/admin/tenants.js @@ -0,0 +1,11 @@ +exports.multiTenancyEnabled = async ctx => { + +} + +exports.exists = async ctx => { + +} + +exports.fetch = async ctx => { + +} diff --git a/packages/worker/src/api/controllers/admin/users.js b/packages/worker/src/api/controllers/admin/users.js index a0e4e18e8d..dd10f416cc 100644 --- a/packages/worker/src/api/controllers/admin/users.js +++ b/packages/worker/src/api/controllers/admin/users.js @@ -14,19 +14,19 @@ const { invalidateSessions } = require("@budibase/auth/sessions") const CouchDB = require("../../../db") const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name -const tenantDocId = StaticDatabases.PLATFORM_INFO.docs.tenants +const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants async function tryAddTenant(tenantId) { const db = new CouchDB(PLATFORM_INFO_DB) let tenants try { - tenants = await db.get(tenantDocId) + tenants = await db.get(TENANT_DOC) } catch (err) { // if theres an error don't worry, we'll just write it in } if (!tenants || !Array.isArray(tenants.tenantIds)) { tenants = { - _id: tenantDocId, + _id: TENANT_DOC, tenantIds: [], } } @@ -36,6 +36,18 @@ async function tryAddTenant(tenantId) { } } +async function doesTenantExist(tenantId) { + const db = new CouchDB(PLATFORM_INFO_DB) + let tenants + try { + tenants = await db.get(TENANT_DOC) + } catch (err) { + // if theres an error the doc doesn't exist, no tenants exist + return false + } + return tenants && Array.isArray(tenants.tenantIds) && tenants.tenantIds.indexOf(tenantId) !== -1 +} + async function allUsers(ctx) { const db = getGlobalDBFromCtx(ctx) const response = await db.allDocs( @@ -121,6 +133,10 @@ exports.save = async ctx => { exports.adminUser = async ctx => { const { email, password, tenantId } = ctx.request.body + if (await doesTenantExist(tenantId)) { + ctx.throw(403, "Organisation already exists.") + } + const db = getGlobalDB(tenantId) const response = await db.allDocs( getGlobalUserParams(null, { diff --git a/packages/worker/src/api/routes/admin/tenants.js b/packages/worker/src/api/routes/admin/tenants.js new file mode 100644 index 0000000000..3f13d5a324 --- /dev/null +++ b/packages/worker/src/api/routes/admin/tenants.js @@ -0,0 +1,15 @@ +const Router = require("@koa/router") +const controller = require("../../controllers/admin/tenants") +const joiValidator = require("../../../middleware/joi-validator") +const Joi = require("joi") +const { TemplatePurpose, TemplateTypes } = require("../../../constants") +const adminOnly = require("../../../middleware/adminOnly") + +const router = Router() + +router + .get("/api/admin/tenants/enabled", controller.multiTenancyEnabled) + .get("/api/admin/tenants/:tenantId/exists", controller.exists) + .get("/api/admin/tenants", adminOnly, controller.fetch) + +module.exports = router \ No newline at end of file