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

145 lines
4.3 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-09-16 13:18:47 +02:00
const uuid = require("uuid")
const { ObjectStoreBuckets } = require("../../../constants")
const { processString } = require("@budibase/string-templates")
const { getDeployedApps } = require("../../../utilities/workerRequests")
const CouchDB = require("../../../db")
const {
loadHandlebarsFile,
NODE_MODULES_PATH,
2021-04-01 17:36:27 +02:00
TOP_LEVEL_PATH,
} = require("../../../utilities/fileSystem")
const env = require("../../../environment")
const { clientLibraryPath } = require("../../../utilities")
2021-05-11 18:53:54 +02:00
const { upload } = require("../../../utilities/fileSystem")
const { attachmentsRelativeURL } = require("../../../utilities")
2021-05-16 22:25:37 +02:00
const { DocumentTypes } = require("../../../db/utils")
const AWS = require("aws-sdk")
const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
2021-05-11 18:53:54 +02:00
async function prepareUpload({ s3Key, bucket, metadata, file }) {
const response = await upload({
bucket,
metadata,
filename: s3Key,
path: file.path,
type: file.type,
})
// don't store a URL, work this out on the way out as the URL could change
return {
size: file.size,
name: file.name,
url: attachmentsRelativeURL(response.Key),
extension: [...file.name.split(".")].pop(),
key: response.Key,
}
}
2020-09-17 17:36:39 +02:00
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
}
}
2021-05-03 09:31:09 +02:00
exports.serveBuilder = async function (ctx) {
2021-04-01 17:36:27 +02:00
let builderPath = resolve(TOP_LEVEL_PATH, "builder")
await send(ctx, ctx.file, { root: builderPath })
}
2021-05-03 09:31:09 +02:00
exports.uploadFile = async function (ctx) {
let files =
2020-09-23 17:15:09 +02:00
ctx.request.files.file.length > 1
? Array.from(ctx.request.files.file)
: [ctx.request.files.file]
2021-05-04 12:32:22 +02:00
const uploads = files.map(async file => {
2020-09-23 18:02:06 +02:00
const fileExtension = [...file.name.split(".")].pop()
// filenames converted to UUIDs so they are unique
2020-09-23 17:15:09 +02:00
const processedFileName = `${uuid.v4()}.${fileExtension}`
return prepareUpload({
file,
2021-06-10 12:34:37 +02:00
s3Key: `${ctx.appId}/attachments/${processedFileName}`,
bucket: ObjectStoreBuckets.APPS,
})
})
ctx.body = await Promise.all(uploads)
2020-09-23 18:02:06 +02:00
}
2021-05-03 09:31:09 +02: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 })
2021-05-16 22:25:37 +02:00
const appInfo = await db.get(DocumentTypes.APP_METADATA)
2020-11-09 16:24:29 +01:00
const { head, html, css } = App.render({
title: appInfo.name,
production: env.isProd(),
appId,
clientLibPath: clientLibraryPath(appId, appInfo.version),
})
2020-11-09 16:24:29 +01:00
const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
ctx.body = await processString(appHbs, {
head,
body: html,
style: css.code,
appId,
})
2020-11-09 16:24:29 +01:00
}
2021-05-03 09:31:09 +02:00
exports.serveClientLibrary = async function (ctx) {
return send(ctx, "budibase-client.js", {
2021-04-01 17:36:27 +02:00
root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
})
}
exports.getSignedUploadURL = async function (ctx) {
// Ensure datasource is valid
const { datasourceId } = ctx.params
const database = new CouchDB(ctx.appId)
const datasource = await database.get(datasourceId)
if (!datasource) {
ctx.throw(400, "The specified datasource could not be found")
return
}
// Determine type of datasource and generate signed URL
let signedUrl
if (datasource.source === "S3") {
const { bucket, key } = ctx.request.body || {}
if (!bucket || !key) {
ctx.throw(400, "datasourceId, bucket and key must be specified")
return
}
try {
const s3 = new AWS.S3({
region: AWS_REGION,
accessKeyId: datasource?.config?.accessKeyId,
secretAccessKey: datasource?.config?.secretAccessKey,
apiVersion: "2006-03-01",
signatureVersion: "v4",
})
const params = { Bucket: bucket, Key: key }
signedUrl = s3.getSignedUrl("putObject", params)
} catch (error) {
ctx.throw(400, error)
}
}
ctx.body = { signedUrl }
}