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;
|
proxy_pass http://{{ address }}:4001;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /app/ {
|
location /app {
|
||||||
proxy_pass http://{{ address }}:4001;
|
proxy_pass http://{{ address }}:4001;
|
||||||
rewrite ^/app/(.*)$ /$1 break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
location /builder {
|
location /builder {
|
||||||
|
|
|
@ -62,7 +62,6 @@ http {
|
||||||
|
|
||||||
location /app {
|
location /app {
|
||||||
proxy_pass http://$apps:4002;
|
proxy_pass http://$apps:4002;
|
||||||
rewrite ^/app/(.*)$ /$1 break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
location = / {
|
location = / {
|
||||||
|
|
|
@ -3,6 +3,7 @@ const {
|
||||||
SEPARATOR,
|
SEPARATOR,
|
||||||
ViewNames,
|
ViewNames,
|
||||||
generateGlobalUserID,
|
generateGlobalUserID,
|
||||||
|
getAllApps,
|
||||||
} = require("./db/utils")
|
} = require("./db/utils")
|
||||||
const jwt = require("jsonwebtoken")
|
const jwt = require("jsonwebtoken")
|
||||||
const { options } = require("./middleware/passport/jwt")
|
const { options } = require("./middleware/passport/jwt")
|
||||||
|
@ -20,8 +21,10 @@ const { hash } = require("./hashing")
|
||||||
const userCache = require("./cache/user")
|
const userCache = require("./cache/user")
|
||||||
const env = require("./environment")
|
const env = require("./environment")
|
||||||
const { getUserSessions, invalidateSessions } = require("./security/sessions")
|
const { getUserSessions, invalidateSessions } = require("./security/sessions")
|
||||||
|
const tenancy = require("./tenancy")
|
||||||
|
|
||||||
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
||||||
|
const PROD_APP_PREFIX = "/app/"
|
||||||
|
|
||||||
function confirmAppId(possibleAppId) {
|
function confirmAppId(possibleAppId) {
|
||||||
return possibleAppId && possibleAppId.startsWith(APP_PREFIX)
|
return possibleAppId && possibleAppId.startsWith(APP_PREFIX)
|
||||||
|
@ -29,16 +32,35 @@ function confirmAppId(possibleAppId) {
|
||||||
: undefined
|
: 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
|
* 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.
|
* @param {object} ctx The main request body to look through.
|
||||||
* @returns {string|undefined} If an appId was found it will be returned.
|
* @returns {string|undefined} If an appId was found it will be returned.
|
||||||
*/
|
*/
|
||||||
exports.getAppId = ctx => {
|
exports.getAppIdFromCtx = async ctx => {
|
||||||
const options = [ctx.headers[Headers.APP_ID], ctx.params.appId]
|
// look in headers
|
||||||
if (ctx.subdomains) {
|
const options = [ctx.headers[Headers.APP_ID]]
|
||||||
options.push(ctx.subdomains[1])
|
|
||||||
}
|
|
||||||
let appId
|
let appId
|
||||||
for (let option of options) {
|
for (let option of options) {
|
||||||
appId = confirmAppId(option)
|
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) {
|
if (!appId && ctx.request.body && ctx.request.body.appId) {
|
||||||
appId = confirmAppId(ctx.request.body.appId)
|
appId = confirmAppId(ctx.request.body.appId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// look in the url - dev app
|
||||||
let appPath =
|
let appPath =
|
||||||
ctx.request.headers.referrer ||
|
ctx.request.headers.referrer ||
|
||||||
ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX))
|
ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX))
|
||||||
if (!appId && appPath.length !== 0) {
|
if (!appId && appPath.length) {
|
||||||
appId = confirmAppId(appPath[0])
|
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
|
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 uuid = require("uuid")
|
||||||
const { ObjectStoreBuckets } = require("../../../constants")
|
const { ObjectStoreBuckets } = require("../../../constants")
|
||||||
const { processString } = require("@budibase/string-templates")
|
const { processString } = require("@budibase/string-templates")
|
||||||
const { getAllApps } = require("@budibase/backend-core/db")
|
|
||||||
const {
|
const {
|
||||||
loadHandlebarsFile,
|
loadHandlebarsFile,
|
||||||
NODE_MODULES_PATH,
|
NODE_MODULES_PATH,
|
||||||
|
@ -16,7 +15,7 @@ const { clientLibraryPath } = require("../../../utilities")
|
||||||
const { upload } = require("../../../utilities/fileSystem")
|
const { upload } = require("../../../utilities/fileSystem")
|
||||||
const { attachmentsRelativeURL } = require("../../../utilities")
|
const { attachmentsRelativeURL } = require("../../../utilities")
|
||||||
const { DocumentTypes } = require("../../../db/utils")
|
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 = require("aws-sdk")
|
||||||
const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
|
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) {
|
exports.serveBuilder = async function (ctx) {
|
||||||
let builderPath = resolve(TOP_LEVEL_PATH, "builder")
|
let builderPath = resolve(TOP_LEVEL_PATH, "builder")
|
||||||
await send(ctx, ctx.file, { root: builderPath })
|
await send(ctx, ctx.file, { root: builderPath })
|
||||||
|
@ -81,10 +65,10 @@ exports.uploadFile = async function (ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.serveApp = async function (ctx) {
|
exports.serveApp = async function (ctx) {
|
||||||
let appId = await getAppIdFromUrl(ctx)
|
|
||||||
const App = require("./templates/BudibaseApp.svelte").default
|
const App = require("./templates/BudibaseApp.svelte").default
|
||||||
const db = getAppDB({ skip_setup: true })
|
const db = getAppDB({ skip_setup: true })
|
||||||
const appInfo = await db.get(DocumentTypes.APP_METADATA)
|
const appInfo = await db.get(DocumentTypes.APP_METADATA)
|
||||||
|
let appId = getAppId()
|
||||||
|
|
||||||
const { head, html, css } = App.render({
|
const { head, html, css } = App.render({
|
||||||
title: appInfo.name,
|
title: appInfo.name,
|
||||||
|
|
|
@ -44,8 +44,7 @@ router
|
||||||
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
||||||
controller.uploadFile
|
controller.uploadFile
|
||||||
)
|
)
|
||||||
// TODO: this likely needs to be secured in some way
|
.get("/app/:appUrl/:path*", controller.serveApp)
|
||||||
.get("/:appId/:path*", controller.serveApp)
|
|
||||||
.post(
|
.post(
|
||||||
"/api/attachments/:datasourceId/url",
|
"/api/attachments/:datasourceId/url",
|
||||||
authorized(PermissionTypes.TABLE, PermissionLevels.READ),
|
authorized(PermissionTypes.TABLE, PermissionLevels.READ),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
const {
|
const {
|
||||||
getAppId,
|
getAppIdFromCtx,
|
||||||
setCookie,
|
setCookie,
|
||||||
getCookie,
|
getCookie,
|
||||||
clearCookie,
|
clearCookie,
|
||||||
|
@ -17,7 +17,7 @@ const { doInAppContext } = require("@budibase/backend-core/context")
|
||||||
|
|
||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
// try to get the appID from the request
|
// try to get the appID from the request
|
||||||
let requestAppId = getAppId(ctx)
|
let requestAppId = await getAppIdFromCtx(ctx)
|
||||||
// get app cookie if it exists
|
// get app cookie if it exists
|
||||||
let appCookie = null
|
let appCookie = null
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const { Headers } = require("@budibase/backend-core/constants")
|
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 } = {}) {
|
module.exports = function ({ requiresAppId } = {}) {
|
||||||
return async (ctx, next) => {
|
return async (ctx, next) => {
|
||||||
const appId = getAppId(ctx)
|
const appId = await getAppIdFromCtx(ctx)
|
||||||
if (requiresAppId && !appId) {
|
if (requiresAppId && !appId) {
|
||||||
ctx.throw(
|
ctx.throw(
|
||||||
400,
|
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