Fix cross tenant apps with session
This commit is contained in:
parent
4ee5256ad3
commit
a68abf2730
|
@ -52,9 +52,8 @@ http {
|
|||
proxy_pass http://{{ address }}:4001;
|
||||
}
|
||||
|
||||
location /app/ {
|
||||
location /app {
|
||||
proxy_pass http://{{ address }}:4001;
|
||||
rewrite ^/app/(.*)$ /$1 break;
|
||||
}
|
||||
|
||||
location /builder {
|
||||
|
|
|
@ -62,7 +62,6 @@ http {
|
|||
|
||||
location /app {
|
||||
proxy_pass http://$apps:4002;
|
||||
rewrite ^/app/(.*)$ /$1 break;
|
||||
}
|
||||
|
||||
location = / {
|
||||
|
|
|
@ -3,6 +3,7 @@ const {
|
|||
SEPARATOR,
|
||||
ViewNames,
|
||||
generateGlobalUserID,
|
||||
getAllApps,
|
||||
} = require("./db/utils")
|
||||
const jwt = require("jsonwebtoken")
|
||||
const { options } = require("./middleware/passport/jwt")
|
||||
|
@ -20,8 +21,10 @@ const { hash } = require("./hashing")
|
|||
const userCache = require("./cache/user")
|
||||
const env = require("./environment")
|
||||
const { getUserSessions, invalidateSessions } = require("./security/sessions")
|
||||
const tenancy = require("./tenancy")
|
||||
|
||||
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
||||
const PROD_APP_PREFIX = "/app/"
|
||||
|
||||
function confirmAppId(possibleAppId) {
|
||||
return possibleAppId && possibleAppId.startsWith(APP_PREFIX)
|
||||
|
@ -29,16 +32,35 @@ function confirmAppId(possibleAppId) {
|
|||
: undefined
|
||||
}
|
||||
|
||||
async function resolveAppUrl(ctx) {
|
||||
const appUrl = ctx.path.split("/")[2]
|
||||
let possibleAppUrl = `/${appUrl.toLowerCase()}`
|
||||
|
||||
let tenantId = tenancy.getTenantId()
|
||||
if (!env.SELF_HOSTED && ctx.subdomains.length) {
|
||||
// always use the tenant id from the url in cloud
|
||||
tenantId = ctx.subdomains[0]
|
||||
}
|
||||
|
||||
// search prod apps for a url that matches
|
||||
const apps = await tenancy.doInTenant(tenantId, () =>
|
||||
getAllApps({ dev: false })
|
||||
)
|
||||
const app = apps.filter(
|
||||
a => a.url && a.url.toLowerCase() === possibleAppUrl
|
||||
)[0]
|
||||
|
||||
return app && app.appId ? app.appId : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a request tries to find the appId, which can be located in various places
|
||||
* @param {object} ctx The main request body to look through.
|
||||
* @returns {string|undefined} If an appId was found it will be returned.
|
||||
*/
|
||||
exports.getAppId = ctx => {
|
||||
const options = [ctx.headers[Headers.APP_ID], ctx.params.appId]
|
||||
if (ctx.subdomains) {
|
||||
options.push(ctx.subdomains[1])
|
||||
}
|
||||
exports.getAppIdFromCtx = async ctx => {
|
||||
// look in headers
|
||||
const options = [ctx.headers[Headers.APP_ID]]
|
||||
let appId
|
||||
for (let option of options) {
|
||||
appId = confirmAppId(option)
|
||||
|
@ -47,16 +69,24 @@ exports.getAppId = ctx => {
|
|||
}
|
||||
}
|
||||
|
||||
// look in body if can't find it in subdomain
|
||||
// look in body
|
||||
if (!appId && ctx.request.body && ctx.request.body.appId) {
|
||||
appId = confirmAppId(ctx.request.body.appId)
|
||||
}
|
||||
|
||||
// look in the url - dev app
|
||||
let appPath =
|
||||
ctx.request.headers.referrer ||
|
||||
ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX))
|
||||
if (!appId && appPath.length !== 0) {
|
||||
if (!appId && appPath.length) {
|
||||
appId = confirmAppId(appPath[0])
|
||||
}
|
||||
|
||||
// look in the url - prod app
|
||||
if (!appId && ctx.path.startsWith(PROD_APP_PREFIX)) {
|
||||
appId = confirmAppId(await resolveAppUrl(ctx))
|
||||
}
|
||||
|
||||
return appId
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,7 +5,6 @@ const { resolve, join } = require("../../../utilities/centralPath")
|
|||
const uuid = require("uuid")
|
||||
const { ObjectStoreBuckets } = require("../../../constants")
|
||||
const { processString } = require("@budibase/string-templates")
|
||||
const { getAllApps } = require("@budibase/backend-core/db")
|
||||
const {
|
||||
loadHandlebarsFile,
|
||||
NODE_MODULES_PATH,
|
||||
|
@ -16,7 +15,7 @@ const { clientLibraryPath } = require("../../../utilities")
|
|||
const { upload } = require("../../../utilities/fileSystem")
|
||||
const { attachmentsRelativeURL } = require("../../../utilities")
|
||||
const { DocumentTypes } = require("../../../db/utils")
|
||||
const { getAppDB, updateAppId } = require("@budibase/backend-core/context")
|
||||
const { getAppDB, getAppId } = require("@budibase/backend-core/context")
|
||||
const AWS = require("aws-sdk")
|
||||
const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
|
||||
|
||||
|
@ -39,21 +38,6 @@ async function prepareUpload({ s3Key, bucket, metadata, file }) {
|
|||
}
|
||||
}
|
||||
|
||||
async function getAppIdFromUrl(ctx) {
|
||||
// the "appId" component of the URL can be the id or the custom url
|
||||
let possibleAppUrl = `/${encodeURI(ctx.params.appId).toLowerCase()}`
|
||||
|
||||
// search prod apps for a url that matches, exclude dev where id is always used
|
||||
const apps = await getAllApps({ dev: false })
|
||||
const app = apps.filter(
|
||||
a => a.url && a.url.toLowerCase() === possibleAppUrl
|
||||
)[0]
|
||||
|
||||
const appId = app && app.appId ? app.appId : ctx.params.appId
|
||||
updateAppId(appId)
|
||||
return appId
|
||||
}
|
||||
|
||||
exports.serveBuilder = async function (ctx) {
|
||||
let builderPath = resolve(TOP_LEVEL_PATH, "builder")
|
||||
await send(ctx, ctx.file, { root: builderPath })
|
||||
|
@ -81,10 +65,10 @@ exports.uploadFile = async function (ctx) {
|
|||
}
|
||||
|
||||
exports.serveApp = async function (ctx) {
|
||||
let appId = await getAppIdFromUrl(ctx)
|
||||
const App = require("./templates/BudibaseApp.svelte").default
|
||||
const db = getAppDB({ skip_setup: true })
|
||||
const appInfo = await db.get(DocumentTypes.APP_METADATA)
|
||||
let appId = getAppId()
|
||||
|
||||
const { head, html, css } = App.render({
|
||||
title: appInfo.name,
|
||||
|
|
|
@ -44,8 +44,7 @@ router
|
|||
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
||||
controller.uploadFile
|
||||
)
|
||||
// TODO: this likely needs to be secured in some way
|
||||
.get("/:appId/:path*", controller.serveApp)
|
||||
.get("/app/:appUrl/:path*", controller.serveApp)
|
||||
.post(
|
||||
"/api/attachments/:datasourceId/url",
|
||||
authorized(PermissionTypes.TABLE, PermissionLevels.READ),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
const {
|
||||
getAppId,
|
||||
getAppIdFromCtx,
|
||||
setCookie,
|
||||
getCookie,
|
||||
clearCookie,
|
||||
|
@ -17,7 +17,7 @@ const { doInAppContext } = require("@budibase/backend-core/context")
|
|||
|
||||
module.exports = async (ctx, next) => {
|
||||
// try to get the appID from the request
|
||||
let requestAppId = getAppId(ctx)
|
||||
let requestAppId = await getAppIdFromCtx(ctx)
|
||||
// get app cookie if it exists
|
||||
let appCookie = null
|
||||
try {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
const { Headers } = require("@budibase/backend-core/constants")
|
||||
const { getAppId } = require("@budibase/backend-core/utils")
|
||||
const { getAppIdFromCtx } = require("@budibase/backend-core/utils")
|
||||
|
||||
module.exports = function ({ requiresAppId } = {}) {
|
||||
return async (ctx, next) => {
|
||||
const appId = getAppId(ctx)
|
||||
const appId = await getAppIdFromCtx(ctx)
|
||||
if (requiresAppId && !appId) {
|
||||
ctx.throw(
|
||||
400,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue