diff --git a/packages/backend-core/src/redis/redlockImpl.ts b/packages/backend-core/src/redis/redlockImpl.ts index a7b2e2b4c6..4de2516ab2 100644 --- a/packages/backend-core/src/redis/redlockImpl.ts +++ b/packages/backend-core/src/redis/redlockImpl.ts @@ -109,7 +109,7 @@ export async function doWithLock( ): Promise> { const redlock = await getClient(opts.type, opts.customOptions) let lock: Redlock.Lock | undefined - let timeout: NodeJS.Timeout | undefined + let timeout try { const name = getLockName(opts) diff --git a/packages/backend-core/src/tenancy/tenancy.ts b/packages/backend-core/src/tenancy/tenancy.ts index 7b17bdbe18..3603ef3462 100644 --- a/packages/backend-core/src/tenancy/tenancy.ts +++ b/packages/backend-core/src/tenancy/tenancy.ts @@ -93,11 +93,19 @@ export const getTenantIDFromCtx = ( // subdomain if (isAllowed(TenantResolutionStrategy.SUBDOMAIN)) { // e.g. budibase.app or local.com:10000 - const platformHost = new URL(getPlatformURL()).host.split(":")[0] + let platformHost + try { + platformHost = new URL(getPlatformURL()).host.split(":")[0] + } catch (err: any) { + // if invalid URL, just don't try to process subdomain + if (err.code !== "ERR_INVALID_URL") { + throw err + } + } // e.g. tenant.budibase.app or tenant.local.com const requestHost = ctx.host // parse the tenant id from the difference - if (requestHost.includes(platformHost)) { + if (platformHost && requestHost.includes(platformHost)) { const tenantId = requestHost.substring( 0, requestHost.indexOf(`.${platformHost}`) diff --git a/packages/server/src/middleware/currentapp.ts b/packages/server/src/middleware/currentapp.ts index 800d43e69c..984dd8e5e9 100644 --- a/packages/server/src/middleware/currentapp.ts +++ b/packages/server/src/middleware/currentapp.ts @@ -5,6 +5,7 @@ import { tenancy, context, users, + auth, } from "@budibase/backend-core" import { generateUserMetadataID, isDevAppID } from "../db/utils" import { getCachedSelf } from "../utilities/global" @@ -69,28 +70,34 @@ export default async (ctx: UserCtx, next: any) => { return next() } - return context.doInAppContext(appId, async () => { - // 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?._id && - requestAppId && - !tenancy.isUserInAppTenant(requestAppId, ctx.user) - ) { - // don't error, simply remove the users rights (they are a public user) - ctx.user = users.cleanseUserObject(ctx.user) as ContextUser - ctx.isAuthenticated = false - roleId = roles.BUILTIN_ROLE_IDS.PUBLIC - } + const userId = ctx.user ? generateUserMetadataID(ctx.user._id!) : undefined + // if the user is not in the right tenant then make sure to wipe their cookie + // 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 () => { ctx.appId = appId if (roleId) { ctx.roleId = roleId const globalId = ctx.user ? ctx.user._id : undefined - const userId = ctx.user - ? generateUserMetadataID(ctx.user._id!) - : undefined ctx.user = { ...ctx.user!, // override userID with metadata one