2020-05-07 11:53:34 +02:00
|
|
|
const send = require("koa-send")
|
2020-10-09 11:00:57 +02:00
|
|
|
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")
|
2020-09-23 17:15:09 +02:00
|
|
|
const AWS = require("aws-sdk")
|
|
|
|
const { prepareUploadForS3 } = require("./deploy/aws")
|
2020-09-17 17:36:39 +02:00
|
|
|
const {
|
|
|
|
budibaseAppsDir,
|
|
|
|
budibaseTempDir,
|
|
|
|
} = require("../../utilities/budibaseDir")
|
|
|
|
const CouchDB = require("../../db")
|
|
|
|
const setBuilderToken = require("../../utilities/builder/setBuilderToken")
|
|
|
|
const fileProcessor = require("../../utilities/fileProcessor")
|
2020-10-13 22:33:56 +02:00
|
|
|
const { AuthTypes } = require("../../constants")
|
2020-10-28 21:35:06 +01:00
|
|
|
const env = require("../../environment")
|
2020-09-17 17:36:39 +02:00
|
|
|
|
2020-10-21 16:28:30 +02:00
|
|
|
// this was the version before we started versioning the component library
|
|
|
|
const COMP_LIB_BASE_APP_VERSION = "0.2.5"
|
|
|
|
|
2020-04-14 16:14:57 +02:00
|
|
|
exports.serveBuilder = async function(ctx) {
|
2020-09-17 17:36:39 +02:00
|
|
|
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 })
|
2020-04-14 16:14:57 +02:00
|
|
|
}
|
|
|
|
|
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"
|
|
|
|
)
|
|
|
|
|
2020-10-28 21:35:06 +01:00
|
|
|
if (env.CLOUD) {
|
2020-09-23 17:15:09 +02:00
|
|
|
// remote upload
|
|
|
|
const s3 = new AWS.S3({
|
|
|
|
params: {
|
2020-09-23 18:02:06 +02:00
|
|
|
Bucket: "prod-budi-app-assets",
|
2020-09-23 17:15:09 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2020-09-23 18:29:32 +02:00
|
|
|
const uploads = files.map(file => {
|
2020-09-23 17:15:09 +02:00
|
|
|
const fileExtension = [...file.name.split(".")].pop()
|
|
|
|
const processedFileName = `${uuid.v4()}.${fileExtension}`
|
|
|
|
|
2020-09-23 18:02:06 +02:00
|
|
|
return prepareUploadForS3({
|
2020-09-23 21:23:40 +02:00
|
|
|
file,
|
2020-09-23 18:02:06 +02:00
|
|
|
s3Key: `assets/${ctx.user.appId}/attachments/${processedFileName}`,
|
|
|
|
s3,
|
2020-09-23 17:15:09 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-09-23 18:29:32 +02:00
|
|
|
ctx.body = await Promise.all(uploads)
|
|
|
|
return
|
|
|
|
}
|
2020-09-23 17:15:09 +02:00
|
|
|
|
2020-09-23 18:29:32 +02:00
|
|
|
ctx.body = await processLocalFileUploads({
|
|
|
|
files,
|
|
|
|
outputPath: attachmentsPath,
|
2020-10-29 11:28:27 +01:00
|
|
|
appId: ctx.user.appId,
|
2020-09-23 18:29:32 +02:00
|
|
|
})
|
2020-09-23 17:15:09 +02:00
|
|
|
}
|
|
|
|
|
2020-10-29 11:28:27 +01:00
|
|
|
async function processLocalFileUploads({ files, outputPath, appId }) {
|
2020-09-15 17:22:13 +02:00
|
|
|
// create attachments dir if it doesnt exist
|
2020-09-23 18:29:32 +02:00
|
|
|
!fs.existsSync(outputPath) && fs.mkdirSync(outputPath, { recursive: true })
|
2020-09-15 17:22:13 +02:00
|
|
|
|
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-15 17:22:13 +02:00
|
|
|
|
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,
|
2020-09-23 18:29:32 +02:00
|
|
|
outputPath: join(outputPath, processedFileName),
|
2020-09-23 17:15:09 +02:00
|
|
|
url: join("/attachments", processedFileName),
|
2020-09-16 13:18:47 +02:00
|
|
|
}
|
|
|
|
})
|
2020-09-15 17:22:13 +02:00
|
|
|
|
2020-09-23 18:29:32 +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
|
2020-10-29 11:28:27 +01:00
|
|
|
const db = new CouchDB(appId)
|
2020-09-23 18:29:32 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
exports.performLocalFileProcessing = async function(ctx) {
|
|
|
|
const { files } = ctx.request.body
|
|
|
|
|
|
|
|
const processedFileOutputPath = resolve(
|
|
|
|
budibaseAppsDir(),
|
|
|
|
ctx.user.appId,
|
|
|
|
"attachments"
|
2020-09-17 17:36:39 +02:00
|
|
|
)
|
|
|
|
|
2020-09-15 17:22:13 +02:00
|
|
|
try {
|
2020-09-23 18:29:32 +02:00
|
|
|
ctx.body = await processLocalFileUploads({
|
|
|
|
files,
|
|
|
|
outputPath: processedFileOutputPath,
|
2020-10-29 11:28:27 +01:00
|
|
|
appId: ctx.user.appId,
|
2020-09-23 18:29:32 +02:00
|
|
|
})
|
2020-09-15 17:22:13 +02:00
|
|
|
} catch (err) {
|
2020-09-17 17:36:39 +02:00
|
|
|
ctx.throw(500, err)
|
2020-09-15 17:22:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 16:14:57 +02:00
|
|
|
exports.serveApp = async function(ctx) {
|
2020-10-13 22:33:56 +02:00
|
|
|
const mainOrAuth =
|
|
|
|
ctx.auth.authenticated === AuthTypes.APP ? "main" : "unauthenticated"
|
2020-06-29 11:27:38 +02:00
|
|
|
|
2020-05-03 12:33:20 +02:00
|
|
|
// default to homedir
|
|
|
|
const appPath = resolve(
|
2020-05-11 16:42:42 +02:00
|
|
|
budibaseAppsDir(),
|
2020-05-03 12:33:20 +02:00
|
|
|
ctx.params.appId,
|
|
|
|
"public",
|
2020-06-29 11:27:38 +02:00
|
|
|
mainOrAuth
|
2020-05-07 11:53:34 +02:00
|
|
|
)
|
2020-07-07 18:47:18 +02:00
|
|
|
|
2020-10-13 22:33:56 +02:00
|
|
|
const appId = ctx.user.appId
|
2020-06-12 21:42:55 +02:00
|
|
|
|
2020-10-28 21:35:06 +01:00
|
|
|
if (env.CLOUD) {
|
2020-07-07 22:29:20 +02:00
|
|
|
const S3_URL = `https://${appId}.app.budi.live/assets/${appId}/${mainOrAuth}/${ctx.file ||
|
|
|
|
"index.production.html"}`
|
2020-07-08 17:31:26 +02:00
|
|
|
|
2020-07-01 22:56:53 +02:00
|
|
|
const response = await fetch(S3_URL)
|
2020-06-29 11:27:38 +02:00
|
|
|
const body = await response.text()
|
2020-07-07 22:29:20 +02:00
|
|
|
ctx.body = body
|
2020-07-01 22:56:53 +02:00
|
|
|
return
|
2020-06-29 11:27:38 +02:00
|
|
|
}
|
2020-07-01 22:56:53 +02:00
|
|
|
|
2020-07-06 20:43:40 +02:00
|
|
|
await send(ctx, ctx.file || "index.html", { root: ctx.devPath || appPath })
|
2020-06-12 21:42:55 +02:00
|
|
|
}
|
|
|
|
|
2020-09-15 17:22:13 +02:00
|
|
|
exports.serveAttachment = async function(ctx) {
|
2020-09-17 17:36:39 +02:00
|
|
|
const appId = ctx.user.appId
|
2020-09-15 17:22:13 +02:00
|
|
|
const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments")
|
|
|
|
|
|
|
|
// Serve from CloudFront
|
2020-10-28 21:35:06 +01:00
|
|
|
if (env.CLOUD) {
|
2020-09-17 17:36:39 +02:00
|
|
|
const S3_URL = `https://cdn.app.budi.live/assets/${appId}/attachments/${ctx.file}`
|
2020-09-15 17:22:13 +02:00
|
|
|
const response = await fetch(S3_URL)
|
|
|
|
const body = await response.text()
|
2020-10-21 14:00:40 +02:00
|
|
|
ctx.set("Content-Type", response.headers.get("Content-Type"))
|
2020-09-15 17:22:13 +02:00
|
|
|
ctx.body = body
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
await send(ctx, ctx.file, { root: attachmentsPath })
|
|
|
|
}
|
|
|
|
|
2020-06-12 21:42:55 +02:00
|
|
|
exports.serveAppAsset = async function(ctx) {
|
|
|
|
// default to homedir
|
2020-10-13 22:33:56 +02:00
|
|
|
const mainOrAuth =
|
|
|
|
ctx.auth.authenticated === AuthTypes.APP ? "main" : "unauthenticated"
|
2020-06-29 11:27:38 +02:00
|
|
|
|
2020-06-12 21:42:55 +02:00
|
|
|
const appPath = resolve(
|
|
|
|
budibaseAppsDir(),
|
2020-10-29 11:28:27 +01:00
|
|
|
ctx.user.appId,
|
2020-06-12 21:42:55 +02:00
|
|
|
"public",
|
2020-06-29 11:27:38 +02:00
|
|
|
mainOrAuth
|
2020-06-12 21:42:55 +02:00
|
|
|
)
|
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 })
|
2020-04-14 16:14:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.serveComponentLibrary = async function(ctx) {
|
2020-11-06 22:13:21 +01:00
|
|
|
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(),
|
2020-11-06 22:13:21 +01:00
|
|
|
appId,
|
2020-05-07 11:53:34 +02:00
|
|
|
"node_modules",
|
2020-05-02 16:29:10 +02:00
|
|
|
decodeURI(ctx.query.library),
|
2020-07-14 22:07:53 +02:00
|
|
|
"package",
|
2020-05-02 16:29:10 +02:00
|
|
|
"dist"
|
2020-05-07 11:53:34 +02:00
|
|
|
)
|
2020-05-02 16:29:10 +02:00
|
|
|
|
2020-05-06 13:17:15 +02:00
|
|
|
if (ctx.isDev) {
|
|
|
|
componentLibraryPath = join(
|
2020-05-11 16:42:42 +02:00
|
|
|
budibaseTempDir(),
|
2020-05-06 11:33:30 +02:00
|
|
|
decodeURI(ctx.query.library),
|
|
|
|
"dist"
|
2020-05-07 11:53:34 +02:00
|
|
|
)
|
2020-05-06 11:33:30 +02:00
|
|
|
}
|
|
|
|
|
2020-10-28 21:35:06 +01:00
|
|
|
if (env.CLOUD) {
|
2020-10-21 16:28:30 +02:00
|
|
|
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(
|
2020-10-21 16:28:30 +02:00
|
|
|
`https://${appId}.app.budi.live/assets/${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
|
|
|
|
2020-05-02 16:29:10 +02:00
|
|
|
await send(ctx, "/index.js", { root: componentLibraryPath })
|
2020-05-06 11:33:30 +02:00
|
|
|
}
|