budibase/packages/server/src/middleware/currentapp.js

131 lines
3.8 KiB
JavaScript
Raw Normal View History

const {
getAppId,
setCookie,
getCookie,
clearCookie,
} = require("@budibase/backend-core/utils")
const { Cookies } = require("@budibase/backend-core/constants")
const { getRole } = require("@budibase/backend-core/roles")
const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
const { generateUserMetadataID, isDevAppID } = require("../db/utils")
const { dbExists } = require("@budibase/backend-core/db")
const { isUserInAppTenant } = require("@budibase/backend-core/tenancy")
2021-07-06 19:10:04 +02:00
const { getCachedSelf } = require("../utilities/global")
2021-10-06 23:16:50 +02:00
const env = require("../environment")
const { isWebhookEndpoint } = require("./utils")
const { doInAppContext } = require("@budibase/backend-core/context")
2021-10-06 23:16:50 +02:00
module.exports = async (ctx, next) => {
// try to get the appID from the request
let requestAppId = getAppId(ctx)
// get app cookie if it exists
let appCookie = null
try {
appCookie = getCookie(ctx, Cookies.CurrentApp)
} catch (err) {
clearCookie(ctx, Cookies.CurrentApp)
}
if (!appCookie && !requestAppId) {
return next()
}
// check the app exists referenced in cookie
if (appCookie) {
const appId = appCookie.appId
const exists = await dbExists(appId)
if (!exists) {
clearCookie(ctx, Cookies.CurrentApp)
return next()
}
// if the request app ID wasn't set, update it with the cookie
requestAppId = requestAppId || appId
}
// deny access to application preview
if (!env.isTest()) {
if (
isDevAppID(requestAppId) &&
!isWebhookEndpoint(ctx) &&
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
) {
clearCookie(ctx, Cookies.CurrentApp)
return ctx.redirect("/")
}
}
let appId,
roleId = BUILTIN_ROLE_IDS.PUBLIC
if (!ctx.user) {
// not logged in, try to set a cookie for public apps
appId = requestAppId
2021-07-06 19:10:04 +02:00
} else if (requestAppId != null) {
// Different App ID means cookie needs reset, or if the same public user has logged in
2021-07-06 19:10:04 +02:00
const globalUser = await getCachedSelf(ctx, requestAppId)
appId = requestAppId
// retrieving global user gets the right role
2021-10-12 15:03:47 +02:00
roleId = globalUser.roleId || roleId
// Allow builders to specify their role via a header
const isBuilder =
globalUser && globalUser.builder && globalUser.builder.global
const isDevApp = appId && isDevAppID(appId)
const roleHeader = ctx.request.headers[Headers.PREVIEW_ROLE]
if (isBuilder && isDevApp && roleHeader) {
// Ensure the role is valid ensuring a definition exists
try {
await getRole(appId, roleHeader)
roleId = roleHeader
} catch (error) {
// Swallow error and do nothing
}
}
}
2021-10-06 23:16:50 +02:00
// nothing more to do
if (!appId) {
return next()
}
return doInAppContext(appId, async () => {
let noCookieSet = false
// if the user not in the right tenant then make sure they have no permissions
// need to judge this only based on the request app ID,
if (
env.MULTI_TENANCY &&
ctx.user &&
requestAppId &&
!isUserInAppTenant(requestAppId)
) {
// don't error, simply remove the users rights (they are a public user)
delete ctx.user.builder
delete ctx.user.admin
delete ctx.user.roles
roleId = BUILTIN_ROLE_IDS.PUBLIC
noCookieSet = true
}
ctx.appId = appId
if (roleId) {
ctx.roleId = roleId
const userId = ctx.user ? generateUserMetadataID(ctx.user._id) : null
ctx.user = {
...ctx.user,
// override userID with metadata one
_id: userId,
userId,
roleId,
role: await getRole(roleId),
}
}
if (
(requestAppId !== appId ||
appCookie == null ||
appCookie.appId !== requestAppId) &&
!noCookieSet
) {
setCookie(ctx, { appId }, Cookies.CurrentApp)
}
return next()
})
}