2022-11-10 18:38:26 +01:00
|
|
|
import {
|
|
|
|
utils,
|
|
|
|
constants,
|
|
|
|
roles,
|
|
|
|
tenancy,
|
|
|
|
context,
|
2023-07-18 17:57:48 +02:00
|
|
|
users,
|
2023-12-04 17:47:41 +01:00
|
|
|
auth,
|
2022-11-10 18:38:26 +01:00
|
|
|
} from "@budibase/backend-core"
|
|
|
|
import { generateUserMetadataID, isDevAppID } from "../db/utils"
|
|
|
|
import { getCachedSelf } from "../utilities/global"
|
|
|
|
import env from "../environment"
|
|
|
|
import { isWebhookEndpoint } from "./utils"
|
2023-07-18 17:57:48 +02:00
|
|
|
import { UserCtx, ContextUser } from "@budibase/types"
|
2021-10-06 23:16:50 +02:00
|
|
|
|
2023-03-22 18:46:37 +01:00
|
|
|
export default async (ctx: UserCtx, next: any) => {
|
2021-04-12 19:31:58 +02:00
|
|
|
// try to get the appID from the request
|
2022-11-10 18:38:26 +01:00
|
|
|
let requestAppId = await utils.getAppIdFromCtx(ctx)
|
2023-03-30 14:11:42 +02:00
|
|
|
if (!requestAppId) {
|
2021-04-12 19:31:58 +02:00
|
|
|
return next()
|
|
|
|
}
|
2023-01-12 16:38:22 +01: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) &&
|
2023-07-19 17:19:34 +02:00
|
|
|
!users.isBuilder(ctx.user, requestAppId)
|
2022-01-28 16:43:51 +01:00
|
|
|
) {
|
|
|
|
return ctx.redirect("/")
|
|
|
|
}
|
2021-10-25 17:59:09 +02:00
|
|
|
}
|
|
|
|
|
2022-11-10 18:38:26 +01:00
|
|
|
let appId: string | undefined,
|
|
|
|
roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
|
2023-01-12 16:38:22 +01:00
|
|
|
if (!ctx.user?._id) {
|
2021-04-12 19:31:58 +02:00
|
|
|
// 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
|
2023-07-18 17:57:48 +02:00
|
|
|
const isBuilder = users.isBuilder(globalUser, appId)
|
2022-02-24 15:03:29 +01:00
|
|
|
const isDevApp = appId && isDevAppID(appId)
|
2022-11-10 18:38:26 +01:00
|
|
|
const roleHeader =
|
|
|
|
ctx.request &&
|
2022-11-16 18:23:12 +01:00
|
|
|
(ctx.request.headers[constants.Header.PREVIEW_ROLE] as string)
|
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-11-10 18:38:26 +01:00
|
|
|
if (roleHeader) {
|
|
|
|
await roles.getRole(roleHeader)
|
|
|
|
roleId = roleHeader
|
2022-06-09 15:26:56 +02:00
|
|
|
|
2022-11-10 18:38:26 +01:00
|
|
|
// Delete admin and builder flags so that the specified role is honoured
|
2023-07-18 17:57:48 +02:00
|
|
|
ctx.user = users.removePortalUserPermissions(ctx.user) as ContextUser
|
2022-11-10 18:38:26 +01:00
|
|
|
}
|
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()
|
|
|
|
}
|
|
|
|
|
2023-12-04 17:47:41 +01:00
|
|
|
const userId = ctx.user ? generateUserMetadataID(ctx.user._id!) : undefined
|
2021-11-26 14:25:02 +01:00
|
|
|
|
2023-12-04 18:10:19 +01:00
|
|
|
// if the user is not in the right tenant then make sure to wipe their cookie
|
2023-12-04 17:47:41 +01:00
|
|
|
// also cleanse any information about them that has been allocated
|
|
|
|
// this avoids apps making calls to say the worker which are cross tenant,
|
|
|
|
// we simply remove the authentication
|
|
|
|
if (
|
|
|
|
env.MULTI_TENANCY &&
|
|
|
|
userId &&
|
|
|
|
requestAppId &&
|
|
|
|
!tenancy.isUserInAppTenant(requestAppId, ctx.user)
|
|
|
|
) {
|
|
|
|
// clear out the user
|
|
|
|
ctx.user = users.cleanseUserObject(ctx.user) as ContextUser
|
|
|
|
ctx.isAuthenticated = false
|
|
|
|
roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
|
|
|
|
// remove the cookie, so future calls are public
|
|
|
|
await auth.platformLogout({
|
|
|
|
ctx,
|
|
|
|
userId,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return context.doInAppContext(appId, async () => {
|
2022-01-28 16:43:51 +01:00
|
|
|
ctx.appId = appId
|
|
|
|
if (roleId) {
|
|
|
|
ctx.roleId = roleId
|
2022-08-19 15:08:03 +02:00
|
|
|
const globalId = ctx.user ? ctx.user._id : undefined
|
2023-06-13 15:45:33 +02:00
|
|
|
ctx.user = {
|
2022-11-10 18:38:26 +01:00
|
|
|
...ctx.user!,
|
2022-01-28 16:43:51 +01:00
|
|
|
// override userID with metadata one
|
|
|
|
_id: userId,
|
|
|
|
userId,
|
2022-07-18 22:11:52 +02:00
|
|
|
globalId,
|
2022-01-28 16:43:51 +01:00
|
|
|
roleId,
|
2023-06-12 19:39:30 +02:00
|
|
|
role: await roles.getRole(roleId, { defaultPublic: true }),
|
2023-06-13 15:45:33 +02:00
|
|
|
}
|
2022-01-28 16:43:51 +01: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
|
|
|
}
|