Implementing some changes to how context gets set for tenancy, after testing, as well as updating server.
This commit is contained in:
parent
75ae7ac8d6
commit
54e765a182
|
@ -1,22 +1,25 @@
|
|||
const redis = require("../redis/authRedis")
|
||||
const {
|
||||
updateTenantId,
|
||||
getTenantId,
|
||||
lookupTenantId,
|
||||
getGlobalDB,
|
||||
isTenantIdSet,
|
||||
} = require("../tenancy")
|
||||
|
||||
const EXPIRY_SECONDS = 3600
|
||||
|
||||
exports.getUser = async userId => {
|
||||
if (!isTenantIdSet()) {
|
||||
updateTenantId(await lookupTenantId(userId))
|
||||
exports.getUser = async (userId, tenantId = null) => {
|
||||
if (!tenantId) {
|
||||
try {
|
||||
tenantId = getTenantId()
|
||||
} catch (err) {
|
||||
tenantId = await lookupTenantId(userId)
|
||||
}
|
||||
}
|
||||
const client = await redis.getUserClient()
|
||||
// try cache
|
||||
let user = await client.get(userId)
|
||||
if (!user) {
|
||||
user = await getGlobalDB().get(userId)
|
||||
user = await getGlobalDB(tenantId).get(userId)
|
||||
client.store(userId, user, EXPIRY_SECONDS)
|
||||
}
|
||||
return user
|
||||
|
|
|
@ -3,7 +3,6 @@ const { getCookie, clearCookie } = require("../utils")
|
|||
const { getUser } = require("../cache/user")
|
||||
const { getSession, updateSessionTTL } = require("../security/sessions")
|
||||
const { buildMatcherRegex, matches } = require("./matchers")
|
||||
const { isTenantIdSet, updateTenantId } = require("../tenancy")
|
||||
const env = require("../environment")
|
||||
|
||||
function finalise(
|
||||
|
@ -17,6 +16,11 @@ function finalise(
|
|||
ctx.version = version
|
||||
}
|
||||
|
||||
/**
|
||||
* This middleware is tenancy aware, so that it does not depend on other middlewares being used.
|
||||
* The tenancy modules should not be used here and it should be assumed that the tenancy context
|
||||
* has not yet been populated.
|
||||
*/
|
||||
module.exports = (noAuthPatterns = [], opts = { publicAllowed: false }) => {
|
||||
const noAuthOptions = noAuthPatterns ? buildMatcherRegex(noAuthPatterns) : []
|
||||
return async (ctx, next) => {
|
||||
|
@ -42,10 +46,7 @@ module.exports = (noAuthPatterns = [], opts = { publicAllowed: false }) => {
|
|||
error = "No session found"
|
||||
} else {
|
||||
try {
|
||||
if (session.tenantId && !isTenantIdSet()) {
|
||||
updateTenantId(session.tenantId)
|
||||
}
|
||||
user = await getUser(userId)
|
||||
user = await getUser(userId, session.tenantId)
|
||||
delete user.password
|
||||
authenticated = true
|
||||
} catch (err) {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
const PARAM_REGEX = /\/:(.*?)(\/.*)?$/g
|
||||
|
||||
exports.buildMatcherRegex = patterns => {
|
||||
if (!patterns) {
|
||||
return []
|
||||
}
|
||||
return patterns.map(pattern => {
|
||||
const isObj = typeof pattern === "object" && pattern.route
|
||||
const method = isObj ? pattern.method : "GET"
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
const { createTenancyContext, setTenantId } = require("../tenancy")
|
||||
const { setTenantId } = require("../tenancy")
|
||||
const ContextFactory = require("../tenancy/FunctionContext")
|
||||
const { buildMatcherRegex, matches } = require("./matchers")
|
||||
|
||||
module.exports = (allowQueryStringPatterns, noTenancyPatterns) => {
|
||||
const allowQsOptions = buildMatcherRegex(allowQueryStringPatterns)
|
||||
const noTenancyOptions = buildMatcherRegex(noTenancyPatterns)
|
||||
|
||||
return (ctx, next) => {
|
||||
// always run in context
|
||||
return createTenancyContext().runAndReturn(() => {
|
||||
if (matches(ctx, noTenancyOptions)) {
|
||||
return next()
|
||||
}
|
||||
|
||||
const allowQs = !!matches(ctx, allowQsOptions)
|
||||
setTenantId(ctx, { allowQs })
|
||||
return next()
|
||||
})
|
||||
}
|
||||
return ContextFactory.getMiddleware(ctx => {
|
||||
const allowNoTenant = !!matches(ctx, noTenancyOptions)
|
||||
const allowQs = !!matches(ctx, allowQsOptions)
|
||||
setTenantId(ctx, { allowQs, allowNoTenant })
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
const cls = require("cls-hooked")
|
||||
const { newid } = require("../hashing")
|
||||
|
||||
const REQUEST_ID_KEY = "requestId"
|
||||
|
||||
class FunctionContext {
|
||||
static getMiddleware(updateCtxFn = null) {
|
||||
const namespace = this.createNamespace()
|
||||
|
||||
return async function(ctx, next) {
|
||||
await new Promise(namespace.bind(function(resolve, reject) {
|
||||
// store a contextual request ID that can be used anywhere (audit logs)
|
||||
namespace.set(REQUEST_ID_KEY, newid())
|
||||
namespace.bindEmitter(ctx.req)
|
||||
namespace.bindEmitter(ctx.res)
|
||||
|
||||
if (updateCtxFn) {
|
||||
updateCtxFn(ctx)
|
||||
}
|
||||
next().then(resolve).catch(reject)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
static run(callback) {
|
||||
const namespace = this.createNamespace()
|
||||
|
||||
return namespace.runAndReturn(callback)
|
||||
}
|
||||
|
||||
static setOnContext(key, value) {
|
||||
const namespace = this.createNamespace()
|
||||
namespace.set(key, value)
|
||||
}
|
||||
|
||||
static getContextStorage() {
|
||||
if (this._namespace && this._namespace.active) {
|
||||
const { id, _ns_name, ...contextData } = this._namespace.active
|
||||
return contextData
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
static getFromContext(key) {
|
||||
const context = this.getContextStorage()
|
||||
if (context) {
|
||||
return context[key]
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
static destroyNamespace() {
|
||||
if (this._namespace) {
|
||||
cls.destroyNamespace("session")
|
||||
this._namespace = null
|
||||
}
|
||||
}
|
||||
|
||||
static createNamespace() {
|
||||
if (!this._namespace) {
|
||||
this._namespace = cls.createNamespace("session")
|
||||
}
|
||||
return this._namespace
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FunctionContext
|
|
@ -1,6 +1,6 @@
|
|||
const cls = require("cls-hooked")
|
||||
const env = require("../environment")
|
||||
const { Headers } = require("../../constants")
|
||||
const cls = require("./FunctionContext")
|
||||
|
||||
exports.DEFAULT_TENANT_ID = "default"
|
||||
|
||||
|
@ -12,66 +12,61 @@ exports.isMultiTenant = () => {
|
|||
return env.MULTI_TENANCY
|
||||
}
|
||||
|
||||
// continuation local storage
|
||||
const CONTEXT_NAME = "tenancy"
|
||||
const TENANT_ID = "tenantId"
|
||||
|
||||
exports.createTenancyContext = () => {
|
||||
return cls.createNamespace(CONTEXT_NAME)
|
||||
}
|
||||
|
||||
const getTenancyContext = () => {
|
||||
return cls.getNamespace(CONTEXT_NAME)
|
||||
}
|
||||
|
||||
// used for automations, API endpoints should always be in context already
|
||||
exports.doInTenant = (tenantId, task) => {
|
||||
const context = getTenancyContext()
|
||||
return getTenancyContext().runAndReturn(() => {
|
||||
return cls.run(() => {
|
||||
// set the tenant id
|
||||
context.set(TENANT_ID, tenantId)
|
||||
cls.setOnContext(TENANT_ID, tenantId)
|
||||
|
||||
// invoke the task
|
||||
const result = task()
|
||||
|
||||
// clear down the tenant id manually for extra safety
|
||||
// this should also happen automatically when the call exits
|
||||
context.set(TENANT_ID, null)
|
||||
cls.setOnContext(TENANT_ID, null)
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
exports.updateTenantId = tenantId => {
|
||||
getTenancyContext().set(TENANT_ID, tenantId)
|
||||
cls.setOnContext(TENANT_ID, tenantId)
|
||||
}
|
||||
|
||||
exports.setTenantId = (ctx, opts = { allowQs: false }) => {
|
||||
exports.setTenantId = (ctx, opts = { allowQs: false, allowNoTenant: false }) => {
|
||||
let tenantId
|
||||
// exit early if not multi-tenant
|
||||
if (!exports.isMultiTenant()) {
|
||||
getTenancyContext().set(TENANT_ID, this.DEFAULT_TENANT_ID)
|
||||
cls.setOnContext(TENANT_ID, this.DEFAULT_TENANT_ID)
|
||||
return
|
||||
}
|
||||
|
||||
const params = ctx.request.params || {}
|
||||
const allowQs = opts && opts.allowQs
|
||||
const allowNoTenant = opts && opts.allowNoTenant
|
||||
const header = ctx.request.headers[Headers.TENANT_ID]
|
||||
const user = ctx.request.user || {}
|
||||
tenantId = user.tenantId || params.tenantId || header
|
||||
if (opts.allowQs && !tenantId) {
|
||||
const user = ctx.user || {}
|
||||
if (allowQs) {
|
||||
const query = ctx.request.query || {}
|
||||
tenantId = query.tenantId
|
||||
}
|
||||
// override query string (if allowed) by user, or header
|
||||
// URL params cannot be used in a middleware, as they are
|
||||
// processed later in the chain
|
||||
tenantId = user.tenantId || header || tenantId
|
||||
|
||||
if (!tenantId) {
|
||||
if (!tenantId && !allowNoTenant) {
|
||||
ctx.throw(403, "Tenant id not set")
|
||||
}
|
||||
|
||||
getTenancyContext().set(TENANT_ID, tenantId)
|
||||
// check tenant ID just incase no tenant was allowed
|
||||
if (tenantId) {
|
||||
cls.setOnContext(TENANT_ID, tenantId)
|
||||
}
|
||||
}
|
||||
|
||||
exports.isTenantIdSet = () => {
|
||||
const tenantId = getTenancyContext().get(TENANT_ID)
|
||||
const tenantId = cls.getFromContext(TENANT_ID)
|
||||
return !!tenantId
|
||||
}
|
||||
|
||||
|
@ -79,7 +74,7 @@ exports.getTenantId = () => {
|
|||
if (!exports.isMultiTenant()) {
|
||||
return exports.DEFAULT_TENANT_ID
|
||||
}
|
||||
const tenantId = getTenancyContext().get(TENANT_ID)
|
||||
const tenantId = cls.getFromContext(TENANT_ID)
|
||||
if (!tenantId) {
|
||||
throw Error("Tenant id not found")
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { getDB } = require("../../db")
|
||||
const { getDB } = require("../db")
|
||||
const { SEPARATOR, StaticDatabases } = require("../db/constants")
|
||||
const { getTenantId, DEFAULT_TENANT_ID, isMultiTenant } = require("./context")
|
||||
const env = require("../environment")
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
requireAuth = smtpConfig.config.auth != null
|
||||
// always attach the auth for the forms purpose -
|
||||
// this will be removed later if required
|
||||
if (!smtpDoc.config) {
|
||||
smtpDoc.config = {}
|
||||
}
|
||||
if (!smtpDoc.config.auth) {
|
||||
smtpConfig.config.auth = {
|
||||
type: "login",
|
||||
|
|
|
@ -38,6 +38,7 @@ const {
|
|||
backupClientLibrary,
|
||||
revertClientLibrary,
|
||||
} = require("../../utilities/fileSystem/clientLibrary")
|
||||
const { getTenantId, isMultiTenant } = require("@budibase/auth/tenancy")
|
||||
|
||||
const URL_REGEX_SLASH = /\/|\\/g
|
||||
|
||||
|
@ -92,8 +93,9 @@ async function getAppUrlIfNotInUse(ctx) {
|
|||
return url
|
||||
}
|
||||
|
||||
async function createInstance(tenantId, template) {
|
||||
const baseAppId = generateAppID(env.MULTI_TENANCY ? tenantId : null)
|
||||
async function createInstance(template) {
|
||||
const tenantId = isMultiTenant() ? getTenantId() : null
|
||||
const baseAppId = generateAppID(tenantId)
|
||||
const appId = generateDevAppID(baseAppId)
|
||||
|
||||
const db = new CouchDB(appId)
|
||||
|
@ -128,8 +130,7 @@ async function createInstance(tenantId, template) {
|
|||
exports.fetch = async function (ctx) {
|
||||
const dev = ctx.query && ctx.query.status === AppStatus.DEV
|
||||
const all = ctx.query && ctx.query.status === AppStatus.ALL
|
||||
const tenantId = ctx.user.tenantId
|
||||
const apps = await getAllApps(CouchDB, { tenantId, dev, all })
|
||||
const apps = await getAllApps(CouchDB, { dev, all })
|
||||
|
||||
// get the locks for all the dev apps
|
||||
if (dev || all) {
|
||||
|
@ -189,7 +190,6 @@ exports.fetchAppPackage = async function (ctx) {
|
|||
}
|
||||
|
||||
exports.create = async function (ctx) {
|
||||
const tenantId = ctx.user.tenantId
|
||||
const { useTemplate, templateKey } = ctx.request.body
|
||||
const instanceConfig = {
|
||||
useTemplate,
|
||||
|
@ -198,7 +198,7 @@ exports.create = async function (ctx) {
|
|||
if (ctx.request.files && ctx.request.files.templateFile) {
|
||||
instanceConfig.file = ctx.request.files.templateFile
|
||||
}
|
||||
const instance = await createInstance(tenantId, instanceConfig)
|
||||
const instance = await createInstance(instanceConfig)
|
||||
const appId = instance._id
|
||||
|
||||
const url = await getAppUrlIfNotInUse(ctx)
|
||||
|
@ -222,7 +222,7 @@ exports.create = async function (ctx) {
|
|||
url: url,
|
||||
template: ctx.request.body.template,
|
||||
instance: instance,
|
||||
tenantId,
|
||||
tenantId: getTenantId(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
createdAt: new Date().toISOString(),
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@ const env = require("../environment")
|
|||
|
||||
const router = new Router()
|
||||
|
||||
const NO_TENANCY_ENDPOINTS = [
|
||||
{
|
||||
route: "/api/analytics",
|
||||
method: "GET",
|
||||
},
|
||||
]
|
||||
|
||||
router
|
||||
.use(
|
||||
compress({
|
||||
|
@ -32,12 +39,13 @@ router
|
|||
})
|
||||
.use("/health", ctx => (ctx.status = 200))
|
||||
.use("/version", ctx => (ctx.body = pkg.version))
|
||||
.use(buildTenancyMiddleware())
|
||||
.use(
|
||||
buildAuthMiddleware(null, {
|
||||
publicAllowed: true,
|
||||
})
|
||||
)
|
||||
// nothing in the server should allow query string tenants
|
||||
.use(buildTenancyMiddleware(null, NO_TENANCY_ENDPOINTS))
|
||||
.use(currentApp)
|
||||
.use(auditLog)
|
||||
|
||||
|
|
|
@ -46,13 +46,13 @@ module.exports.definition = {
|
|||
},
|
||||
}
|
||||
|
||||
module.exports.run = async function ({ inputs, tenantId }) {
|
||||
module.exports.run = async function ({ inputs }) {
|
||||
let { to, from, subject, contents } = inputs
|
||||
if (!contents) {
|
||||
contents = "<h1>No content</h1>"
|
||||
}
|
||||
try {
|
||||
let response = await sendSmtpEmail(tenantId, to, from, subject, contents)
|
||||
let response = await sendSmtpEmail(to, from, subject, contents)
|
||||
return {
|
||||
success: true,
|
||||
response,
|
||||
|
|
|
@ -6,6 +6,7 @@ const { processObject } = require("@budibase/string-templates")
|
|||
const { DEFAULT_TENANT_ID } = require("@budibase/auth").constants
|
||||
const CouchDB = require("../db")
|
||||
const { DocumentTypes } = require("../db/utils")
|
||||
const { doInTenant } = require("@budibase/auth/tenancy")
|
||||
|
||||
const FILTER_STEP_ID = logic.BUILTIN_DEFINITIONS.FILTER.stepId
|
||||
|
||||
|
@ -56,7 +57,7 @@ class Orchestrator {
|
|||
|
||||
async execute() {
|
||||
let automation = this._automation
|
||||
const app = this.getApp()
|
||||
const app = await this.getApp()
|
||||
for (let step of automation.definition.steps) {
|
||||
let stepFn = await this.getStepFunctionality(step.type, step.stepId)
|
||||
step.inputs = await processObject(step.inputs, this._context)
|
||||
|
@ -66,13 +67,15 @@ class Orchestrator {
|
|||
)
|
||||
// appId is always passed
|
||||
try {
|
||||
const outputs = await stepFn({
|
||||
inputs: step.inputs,
|
||||
appId: this._appId,
|
||||
apiKey: automation.apiKey,
|
||||
emitter: this._emitter,
|
||||
context: this._context,
|
||||
tenantId: app.tenantId || DEFAULT_TENANT_ID,
|
||||
let tenantId = app.tenantId || DEFAULT_TENANT_ID
|
||||
const outputs = await doInTenant(tenantId, () => {
|
||||
return stepFn({
|
||||
inputs: step.inputs,
|
||||
appId: this._appId,
|
||||
apiKey: automation.apiKey,
|
||||
emitter: this._emitter,
|
||||
context: this._context,
|
||||
})
|
||||
})
|
||||
if (step.stepId === FILTER_STEP_ID && !outputs.success) {
|
||||
break
|
||||
|
|
|
@ -68,5 +68,6 @@ module.exports = async (ctx, next) => {
|
|||
) {
|
||||
setCookie(ctx, { appId }, Cookies.CurrentApp)
|
||||
}
|
||||
|
||||
return next()
|
||||
}
|
||||
|
|
|
@ -33,7 +33,9 @@ function processUser(appId, user) {
|
|||
}
|
||||
|
||||
exports.getCachedSelf = async (ctx, appId) => {
|
||||
const user = await userCache.getUser(ctx.user._id, ctx.user.tenantId)
|
||||
// this has to be tenant aware, can't depend on the context to find it out
|
||||
// running some middlewares before the tenancy causes context to break
|
||||
const user = await userCache.getUser(ctx.user._id)
|
||||
return processUser(appId, user)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ const { checkSlashesInUrl } = require("./index")
|
|||
const { getDeployedAppID } = require("@budibase/auth/db")
|
||||
const { updateAppRole, getGlobalUser } = require("./global")
|
||||
const { Headers } = require("@budibase/auth/constants")
|
||||
const { getTenantId, isTenantIdSet } = require("@budibase/auth/tenancy")
|
||||
|
||||
function request(ctx, request) {
|
||||
if (!request.headers) {
|
||||
|
@ -11,6 +12,9 @@ function request(ctx, request) {
|
|||
}
|
||||
if (!ctx) {
|
||||
request.headers[Headers.API_KEY] = env.INTERNAL_API_KEY
|
||||
if (isTenantIdSet()) {
|
||||
request.headers[Headers.TENANT_ID] = getTenantId()
|
||||
}
|
||||
}
|
||||
if (request.body && Object.keys(request.body).length > 0) {
|
||||
request.headers["Content-Type"] = "application/json"
|
||||
|
@ -29,13 +33,14 @@ function request(ctx, request) {
|
|||
|
||||
exports.request = request
|
||||
|
||||
exports.sendSmtpEmail = async (tenantId, to, from, subject, contents) => {
|
||||
// have to pass in the tenant ID as this could be coming from an automation
|
||||
exports.sendSmtpEmail = async (to, from, subject, contents) => {
|
||||
// tenant ID will be set in header
|
||||
const response = await fetch(
|
||||
checkSlashesInUrl(env.WORKER_URL + `/api/global/email/send`),
|
||||
request(null, {
|
||||
method: "POST",
|
||||
body: {
|
||||
tenantId,
|
||||
email: to,
|
||||
from,
|
||||
contents,
|
||||
|
|
|
@ -13,65 +13,9 @@ const { user: userCache } = require("@budibase/auth/cache")
|
|||
const { invalidateSessions } = require("@budibase/auth/sessions")
|
||||
const CouchDB = require("../../../db")
|
||||
const env = require("../../../environment")
|
||||
const { getGlobalDB, getTenantId } = require("@budibase/auth/tenancy")
|
||||
const { getGlobalDB, getTenantId, doesTenantExist, tryAddTenant, updateTenantId } = require("@budibase/auth/tenancy")
|
||||
|
||||
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name
|
||||
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants
|
||||
|
||||
async function tryAddTenant(tenantId, userId, email) {
|
||||
const db = new CouchDB(PLATFORM_INFO_DB)
|
||||
const getDoc = async id => {
|
||||
if (!id) {
|
||||
return null
|
||||
}
|
||||
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 = {
|
||||
_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)
|
||||
promises.push(db.put(tenants))
|
||||
}
|
||||
await Promise.all(promises)
|
||||
}
|
||||
|
||||
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() {
|
||||
const db = getGlobalDB()
|
||||
|
@ -87,6 +31,8 @@ async function saveUser(user, tenantId) {
|
|||
if (!tenantId) {
|
||||
throw "No tenancy specified."
|
||||
}
|
||||
// need to set the context for this request, as specified
|
||||
updateTenantId(tenantId)
|
||||
// specify the tenancy incase we're making a new admin user (public)
|
||||
const db = getGlobalDB(tenantId)
|
||||
let { email, password, _id } = user
|
||||
|
@ -162,7 +108,7 @@ exports.adminUser = async ctx => {
|
|||
ctx.throw(403, "Organisation already exists.")
|
||||
}
|
||||
|
||||
const db = getGlobalDB()
|
||||
const db = getGlobalDB(tenantId)
|
||||
const response = await db.allDocs(
|
||||
getGlobalUserParams(null, {
|
||||
include_docs: true,
|
||||
|
|
|
@ -5,17 +5,6 @@ const { routes } = require("./routes")
|
|||
const { buildAuthMiddleware, auditLog, buildTenancyMiddleware } =
|
||||
require("@budibase/auth").auth
|
||||
|
||||
const NO_TENANCY_ENDPOINTS = [
|
||||
{
|
||||
route: "/api/system",
|
||||
method: "ALL",
|
||||
},
|
||||
{
|
||||
route: "/api/global/users/self",
|
||||
method: "GET",
|
||||
},
|
||||
]
|
||||
|
||||
const PUBLIC_ENDPOINTS = [
|
||||
{
|
||||
// this covers all of the POST auth routes
|
||||
|
@ -32,10 +21,6 @@ const PUBLIC_ENDPOINTS = [
|
|||
route: "/api/global/configs/public",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
route: "api/global/flags",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
route: "/api/global/configs/checklist",
|
||||
method: "GET",
|
||||
|
@ -48,6 +33,22 @@ const PUBLIC_ENDPOINTS = [
|
|||
route: "/api/global/users/invite/accept",
|
||||
method: "POST",
|
||||
},
|
||||
{
|
||||
route: "api/system/flags",
|
||||
method: "GET",
|
||||
},
|
||||
]
|
||||
|
||||
const NO_TENANCY_ENDPOINTS = [
|
||||
...PUBLIC_ENDPOINTS,
|
||||
{
|
||||
route: "/api/system",
|
||||
method: "ALL",
|
||||
},
|
||||
{
|
||||
route: "/api/global/users/self",
|
||||
method: "GET",
|
||||
},
|
||||
]
|
||||
|
||||
const router = new Router()
|
||||
|
@ -65,8 +66,8 @@ router
|
|||
})
|
||||
)
|
||||
.use("/health", ctx => (ctx.status = 200))
|
||||
.use(buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
|
||||
.use(buildAuthMiddleware(PUBLIC_ENDPOINTS))
|
||||
.use(buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
|
||||
// for now no public access is allowed to worker (bar health check)
|
||||
.use((ctx, next) => {
|
||||
if (!ctx.isAuthenticated && !ctx.publicEndpoint) {
|
||||
|
|
|
@ -2,6 +2,7 @@ const Router = require("@koa/router")
|
|||
const authController = require("../../controllers/global/auth")
|
||||
const joiValidator = require("../../../middleware/joi-validator")
|
||||
const Joi = require("joi")
|
||||
const { updateTenantId } = require("@budibase/auth/tenancy")
|
||||
|
||||
const router = Router()
|
||||
|
||||
|
@ -28,34 +29,41 @@ function buildResetUpdateValidation() {
|
|||
}).required().unknown(false))
|
||||
}
|
||||
|
||||
function updateTenant(ctx, next) {
|
||||
updateTenantId(ctx.params.tenantId)
|
||||
return next()
|
||||
}
|
||||
|
||||
router
|
||||
.post(
|
||||
"/api/global/auth/:tenantId/login",
|
||||
buildAuthValidation(),
|
||||
updateTenant,
|
||||
authController.authenticate
|
||||
)
|
||||
.post(
|
||||
"/api/global/auth/:tenantId/reset",
|
||||
buildResetValidation(),
|
||||
updateTenant,
|
||||
authController.reset
|
||||
)
|
||||
.post(
|
||||
"/api/global/auth/:tenantId/reset/update",
|
||||
buildResetUpdateValidation(),
|
||||
updateTenant,
|
||||
authController.resetUpdate
|
||||
)
|
||||
.post("/api/global/auth/logout", authController.logout)
|
||||
.get("/api/global/auth/:tenantId/google", authController.googlePreAuth)
|
||||
.get("/api/global/auth/:tenantId/google/callback", authController.googleAuth)
|
||||
.get("/api/global/auth/:tenantId/google", updateTenant, authController.googlePreAuth)
|
||||
.get("/api/global/auth/:tenantId/google/callback", updateTenant, authController.googleAuth)
|
||||
.get(
|
||||
"/api/global/auth/:tenantId/oidc/configs/:configId",
|
||||
updateTenant,
|
||||
authController.oidcPreAuth
|
||||
)
|
||||
.get("/api/global/auth/:tenantId/oidc/callback", authController.oidcAuth)
|
||||
.get("/api/global/auth/:tenantId/oidc/callback", updateTenant, authController.oidcAuth)
|
||||
// deprecated - used by the default system before tenancy
|
||||
.get("/api/admin/auth/google/callback", authController.googleAuth)
|
||||
.get("/api/global/auth/google/callback", authController.googleAuth)
|
||||
.get("/api/admin/auth/oidc/callback", authController.oidcAuth)
|
||||
.get("/api/global/auth/oidc/callback", authController.oidcAuth)
|
||||
|
||||
module.exports = router
|
||||
|
|
Loading…
Reference in New Issue