budibase/packages/server/src/api/controllers/static/index.js

224 lines
6.1 KiB
JavaScript
Raw Normal View History

2020-11-09 16:24:29 +01:00
require("svelte/register")
2020-05-07 11:53:34 +02:00
const send = require("koa-send")
const { resolve, join } = require("../../../utilities/centralPath")
2020-06-29 11:27:38 +02:00
const fetch = require("node-fetch")
2020-09-28 18:04:08 +02:00
const fs = require("fs-extra")
2020-09-16 13:18:47 +02:00
const uuid = require("uuid")
const { processString } = require("@budibase/string-templates")
2020-09-17 17:36:39 +02:00
const {
budibaseAppsDir,
budibaseTempDir,
} = require("../../../utilities/budibaseDir")
const { getDeployedApps } = require("../../../utilities/builder/hosting")
const CouchDB = require("../../../db")
const setBuilderToken = require("../../../utilities/builder/setBuilderToken")
const fileProcessor = require("../../../utilities/fileProcessor")
const env = require("../../../environment")
const { OBJ_STORE_DIRECTORY } = require("../../../constants")
2020-09-17 17:36:39 +02:00
function objectStoreUrl() {
if (env.SELF_HOSTED) {
// can use a relative url for this as all goes through the proxy (this is hosted in minio)
return OBJ_STORE_DIRECTORY
} else {
return "https://cdn.app.budi.live/assets"
}
}
async function checkForSelfHostedURL(ctx) {
// the "appId" component of the URL may actually be a specific self hosted URL
let possibleAppUrl = `/${encodeURI(ctx.params.appId).toLowerCase()}`
const apps = await getDeployedApps()
if (apps[possibleAppUrl] && apps[possibleAppUrl].appId) {
return apps[possibleAppUrl].appId
} else {
return ctx.params.appId
}
}
// this was the version before we started versioning the component library
const COMP_LIB_BASE_APP_VERSION = "0.2.5"
exports.serveBuilder = async function(ctx) {
let builderPath = resolve(__dirname, "../../../../builder")
2020-06-19 17:59:46 +02:00
if (ctx.file === "index.html") {
2020-11-02 16:46:08 +01:00
await setBuilderToken(ctx)
2020-06-19 17:59:46 +02:00
}
2020-05-06 13:17:15 +02:00
await send(ctx, ctx.file, { root: ctx.devPath || builderPath })
}
exports.serveSelfHostPage = async function(ctx) {
const logo = fs.readFileSync(resolve(__dirname, "selfhost/logo.svg"), "utf8")
const hostingHbs = fs.readFileSync(
resolve(__dirname, "selfhost/index.hbs"),
"utf8"
)
ctx.body = await processString(hostingHbs, {
logo,
})
}
2020-09-23 17:15:09 +02:00
exports.uploadFile = async function(ctx) {
let files
files =
ctx.request.files.file.length > 1
? Array.from(ctx.request.files.file)
: [ctx.request.files.file]
const attachmentsPath = resolve(
budibaseAppsDir(),
ctx.user.appId,
"attachments"
)
ctx.body = await processLocalFileUploads({
files,
outputPath: attachmentsPath,
appId: ctx.user.appId,
})
2020-09-23 17:15:09 +02:00
}
async function processLocalFileUploads({ files, outputPath, appId }) {
// create attachments dir if it doesnt exist
!fs.existsSync(outputPath) && fs.mkdirSync(outputPath, { recursive: true })
2020-09-16 13:18:47 +02:00
const filesToProcess = files.map(file => {
2020-09-23 18:02:06 +02:00
const fileExtension = [...file.name.split(".")].pop()
2020-09-16 13:18:47 +02:00
// filenames converted to UUIDs so they are unique
2020-09-23 17:15:09 +02:00
const processedFileName = `${uuid.v4()}.${fileExtension}`
2020-09-16 13:18:47 +02:00
return {
2020-09-23 21:23:40 +02:00
name: file.name,
path: file.path,
size: file.size,
type: file.type,
2020-09-23 17:15:09 +02:00
processedFileName,
2020-09-23 22:03:13 +02:00
extension: fileExtension,
outputPath: join(outputPath, processedFileName),
2020-09-23 17:15:09 +02:00
url: join("/attachments", processedFileName),
2020-09-16 13:18:47 +02:00
}
})
const fileProcessOperations = filesToProcess.map(fileProcessor.process)
const processedFiles = await Promise.all(fileProcessOperations)
let pendingFileUploads
// local document used to track which files need to be uploaded
// db.get throws an error if the document doesn't exist
// need to use a promise to default
const db = new CouchDB(appId)
await db
.get("_local/fileuploads")
.then(data => {
pendingFileUploads = data
})
.catch(() => {
pendingFileUploads = { _id: "_local/fileuploads", uploads: [] }
})
pendingFileUploads.uploads = [
...processedFiles,
...pendingFileUploads.uploads,
]
await db.put(pendingFileUploads)
return processedFiles
2020-09-23 18:02:06 +02:00
}
2020-11-12 11:41:49 +01:00
exports.serveApp = async function(ctx) {
let appId = ctx.params.appId
if (env.SELF_HOSTED) {
appId = await checkForSelfHostedURL(ctx)
}
2020-11-09 16:24:29 +01:00
const App = require("./templates/BudibaseApp.svelte").default
const db = new CouchDB(appId, { skip_setup: true })
const appInfo = await db.get(appId)
2020-11-09 16:24:29 +01:00
const { head, html, css } = App.render({
title: appInfo.name,
production: env.CLOUD,
appId,
objectStoreUrl: objectStoreUrl(),
})
2020-11-09 16:24:29 +01:00
const appHbs = fs.readFileSync(`${__dirname}/templates/app.hbs`, "utf8")
ctx.body = await processString(appHbs, {
head,
body: html,
style: css.code,
appId,
})
2020-11-09 16:24:29 +01:00
}
exports.serveAttachment = async function(ctx) {
2020-09-17 17:36:39 +02:00
const appId = ctx.user.appId
const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments")
// Serve from object store
if (env.CLOUD) {
const S3_URL = join(objectStoreUrl(), appId, "attachments", ctx.file)
const response = await fetch(S3_URL)
const body = await response.text()
ctx.set("Content-Type", response.headers.get("Content-Type"))
ctx.body = body
return
}
await send(ctx, ctx.file, { root: attachmentsPath })
}
exports.serveAppAsset = async function(ctx) {
// default to homedir
2020-12-02 18:42:59 +01:00
const appPath = resolve(budibaseAppsDir(), ctx.user.appId, "public")
2020-05-03 12:33:20 +02:00
2020-07-06 20:43:40 +02:00
await send(ctx, ctx.file, { root: ctx.devPath || appPath })
}
exports.serveComponentLibrary = async function(ctx) {
const appId = ctx.query.appId || ctx.appId
2020-05-06 13:17:15 +02:00
// default to homedir
let componentLibraryPath = resolve(
2020-05-11 16:42:42 +02:00
budibaseAppsDir(),
appId,
2020-05-07 11:53:34 +02:00
"node_modules",
decodeURI(ctx.query.library),
"package",
"dist"
2020-05-07 11:53:34 +02:00
)
2020-05-06 13:17:15 +02:00
if (ctx.isDev) {
componentLibraryPath = join(
2020-05-11 16:42:42 +02:00
budibaseTempDir(),
decodeURI(ctx.query.library),
"dist"
2020-05-07 11:53:34 +02:00
)
}
if (env.CLOUD) {
let componentLib = "componentlibrary"
if (ctx.user.version) {
componentLib += `-${ctx.user.version}`
} else {
componentLib += `-${COMP_LIB_BASE_APP_VERSION}`
}
2020-07-07 22:29:20 +02:00
const S3_URL = encodeURI(
join(
objectStoreUrl(appId),
componentLib,
ctx.query.library,
"dist",
"index.js"
)
2020-07-07 22:29:20 +02:00
)
2020-07-06 20:43:40 +02:00
const response = await fetch(S3_URL)
const body = await response.text()
2020-07-07 22:29:20 +02:00
ctx.type = "application/javascript"
ctx.body = body
2020-07-06 20:43:40 +02:00
return
}
2020-06-29 11:27:38 +02:00
await send(ctx, "/awsDeploy.js", { root: componentLibraryPath })
}