2022-01-12 12:32:14 +01:00
|
|
|
const {
|
2022-03-23 17:45:06 +01:00
|
|
|
getAppIdFromCtx,
|
2022-01-12 12:32:14 +01:00
|
|
|
setCookie,
|
|
|
|
getCookie,
|
|
|
|
clearCookie,
|
|
|
|
} = require("@budibase/backend-core/utils")
|
2022-02-24 15:14:39 +01:00
|
|
|
const { Cookies, Headers } = require("@budibase/backend-core/constants")
|
2022-01-10 20:33:00 +01:00
|
|
|
const { getRole } = require("@budibase/backend-core/roles")
|
|
|
|
const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
|
2021-10-25 17:59:09 +02:00
|
|
|
const { generateUserMetadataID, isDevAppID } = require("../db/utils")
|
2022-01-10 20:33:00 +01:00
|
|
|
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")
|
2021-11-03 15:08:47 +01:00
|
|
|
const { isWebhookEndpoint } = require("./utils")
|
2022-01-28 16:43:51 +01:00
|
|
|
const { doInAppContext } = require("@budibase/backend-core/context")
|
2021-10-06 23:16:50 +02:00
|
|
|
|
2021-04-12 19:31:58 +02:00
|
|
|
module.exports = async (ctx, next) => {
|
|
|
|
// try to get the appID from the request
|
2022-03-23 17:45:06 +01:00
|
|
|
let requestAppId = await getAppIdFromCtx(ctx)
|
2021-04-12 19:31:58 +02:00
|
|
|
// get app cookie if it exists
|
2021-07-23 14:29:50 +02:00
|
|
|
let appCookie = null
|
|
|
|
try {
|
|
|
|
appCookie = getCookie(ctx, Cookies.CurrentApp)
|
|
|
|
} catch (err) {
|
|
|
|
clearCookie(ctx, Cookies.CurrentApp)
|
|
|
|
}
|
2021-04-12 19:31:58 +02:00
|
|
|
if (!appCookie && !requestAppId) {
|
|
|
|
return next()
|
|
|
|
}
|
2021-06-08 19:06:16 +02:00
|
|
|
// check the app exists referenced in cookie
|
|
|
|
if (appCookie) {
|
|
|
|
const appId = appCookie.appId
|
2022-01-27 19:18:31 +01:00
|
|
|
const exists = await dbExists(appId)
|
2021-06-08 19:06:16 +02:00
|
|
|
if (!exists) {
|
|
|
|
clearCookie(ctx, Cookies.CurrentApp)
|
|
|
|
return next()
|
|
|
|
}
|
2021-08-04 19:20:51 +02:00
|
|
|
// if the request app ID wasn't set, update it with the cookie
|
|
|
|
requestAppId = requestAppId || appId
|
2021-06-08 19:06:16 +02:00
|
|
|
}
|
2021-04-12 19:31:58 +02:00
|
|
|
|
2021-10-25 17:59:09 +02:00
|
|
|
// deny access to application preview
|
2022-01-28 16:43:51 +01:00
|
|
|
if (!env.isTest()) {
|
|
|
|
if (
|
|
|
|
isDevAppID(requestAppId) &&
|
|
|
|
!isWebhookEndpoint(ctx) &&
|
|
|
|
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
|
|
|
|
) {
|
|
|
|
clearCookie(ctx, Cookies.CurrentApp)
|
|
|
|
return ctx.redirect("/")
|
|
|
|
}
|
2021-10-25 17:59:09 +02:00
|
|
|
}
|
|
|
|
|
2021-07-07 18:15:53 +02:00
|
|
|
let appId,
|
|
|
|
roleId = BUILTIN_ROLE_IDS.PUBLIC
|
2021-04-12 19:31:58 +02:00
|
|
|
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) {
|
2021-04-13 17:56:45 +02:00
|
|
|
// 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)
|
2021-04-12 19:31:58 +02:00
|
|
|
appId = requestAppId
|
2021-05-13 19:10:09 +02:00
|
|
|
// retrieving global user gets the right role
|
2021-10-12 15:03:47 +02:00
|
|
|
roleId = globalUser.roleId || roleId
|
2022-02-24 15:03:29 +01:00
|
|
|
|
|
|
|
// Allow builders to specify their role via a header
|
|
|
|
const isBuilder =
|
|
|
|
globalUser && globalUser.builder && globalUser.builder.global
|
|
|
|
const isDevApp = appId && isDevAppID(appId)
|
2022-04-06 15:11:05 +02:00
|
|
|
const roleHeader = ctx.request && ctx.request.headers[Headers.PREVIEW_ROLE]
|
2022-02-24 15:03:29 +01:00
|
|
|
if (isBuilder && isDevApp && roleHeader) {
|
2022-04-06 14:40:07 +02:00
|
|
|
// Ensure the role is valid by ensuring a definition exists
|
2022-02-24 15:03:29 +01:00
|
|
|
try {
|
2022-02-24 16:36:21 +01:00
|
|
|
await getRole(roleHeader)
|
2022-02-24 15:03:29 +01:00
|
|
|
roleId = roleHeader
|
2022-06-09 15:26:56 +02:00
|
|
|
|
|
|
|
// Delete admin and builder flags so that the specified role is honoured
|
|
|
|
delete ctx.user.builder
|
|
|
|
delete ctx.user.admin
|
2022-02-24 15:03:29 +01:00
|
|
|
} catch (error) {
|
|
|
|
// Swallow error and do nothing
|
|
|
|
}
|
|
|
|
}
|
2021-04-12 19:31:58 +02:00
|
|
|
}
|
2021-10-06 23:16:50 +02:00
|
|
|
|
2021-04-20 18:17:44 +02:00
|
|
|
// nothing more to do
|
|
|
|
if (!appId) {
|
|
|
|
return next()
|
|
|
|
}
|
|
|
|
|
2022-01-28 16:43:51 +01:00
|
|
|
return doInAppContext(appId, async () => {
|
2022-03-24 14:04:49 +01:00
|
|
|
let skipCookie = false
|
2022-01-28 16:43:51 +01:00
|
|
|
// 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 &&
|
2022-03-24 14:04:49 +01:00
|
|
|
!isUserInAppTenant(requestAppId, ctx.user)
|
2022-01-28 16:43:51 +01:00
|
|
|
) {
|
|
|
|
// 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
|
2022-03-24 14:04:49 +01:00
|
|
|
ctx.isAuthenticated = false
|
2022-01-28 16:43:51 +01:00
|
|
|
roleId = BUILTIN_ROLE_IDS.PUBLIC
|
2022-03-24 14:04:49 +01:00
|
|
|
skipCookie = true
|
2021-11-26 14:25:02 +01:00
|
|
|
}
|
|
|
|
|
2022-01-28 16:43:51 +01:00
|
|
|
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) &&
|
2022-03-24 14:04:49 +01:00
|
|
|
!skipCookie
|
2022-01-28 16:43:51 +01:00
|
|
|
) {
|
|
|
|
setCookie(ctx, { appId }, Cookies.CurrentApp)
|
2021-04-13 15:35:00 +02:00
|
|
|
}
|
2021-08-05 10:59:08 +02:00
|
|
|
|
2022-01-28 16:43:51 +01:00
|
|
|
return next()
|
|
|
|
})
|
2021-04-12 19:31:58 +02:00
|
|
|
}
|