mirror of https://github.com/Budibase/budibase.git
2 changed files with 10 additions and 264 deletions
@ -1,252 +0,0 @@ |
|||
const send = require("koa-send") |
|||
const { resolve, join } = require("../../utilities/centralPath") |
|||
const jwt = require("jsonwebtoken") |
|||
const fetch = require("node-fetch") |
|||
const fs = require("fs-extra") |
|||
const uuid = require("uuid") |
|||
const AWS = require("aws-sdk") |
|||
const { prepareUploadForS3 } = require("./deploy/aws") |
|||
|
|||
const { |
|||
budibaseAppsDir, |
|||
budibaseTempDir, |
|||
} = require("../../utilities/budibaseDir") |
|||
const CouchDB = require("../../db") |
|||
const setBuilderToken = require("../../utilities/builder/setBuilderToken") |
|||
const { ANON_LEVEL_ID } = require("../../utilities/accessLevels") |
|||
const fileProcessor = require("../../utilities/fileProcessor") |
|||
|
|||
exports.serveBuilder = async function(ctx) { |
|||
let builderPath = resolve(__dirname, "../../../builder") |
|||
if (ctx.file === "index.html") { |
|||
setBuilderToken(ctx) |
|||
} |
|||
await send(ctx, ctx.file, { root: ctx.devPath || builderPath }) |
|||
} |
|||
|
|||
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" |
|||
) |
|||
|
|||
if (process.env.CLOUD) { |
|||
// remote upload
|
|||
const s3 = new AWS.S3({ |
|||
params: { |
|||
Bucket: "prod-budi-app-assets", |
|||
}, |
|||
}) |
|||
|
|||
const uploads = files.map(file => { |
|||
const fileExtension = [...file.name.split(".")].pop() |
|||
const processedFileName = `${uuid.v4()}.${fileExtension}` |
|||
|
|||
return prepareUploadForS3({ |
|||
file, |
|||
s3Key: `assets/${ctx.user.appId}/attachments/${processedFileName}`, |
|||
s3, |
|||
}) |
|||
}) |
|||
|
|||
ctx.body = await Promise.all(uploads) |
|||
return |
|||
} |
|||
|
|||
ctx.body = await processLocalFileUploads({ |
|||
files, |
|||
outputPath: attachmentsPath, |
|||
instanceId: ctx.user.instanceId, |
|||
}) |
|||
} |
|||
|
|||
async function processLocalFileUploads({ files, outputPath, instanceId }) { |
|||
// create attachments dir if it doesnt exist
|
|||
!fs.existsSync(outputPath) && fs.mkdirSync(outputPath, { recursive: true }) |
|||
|
|||
const filesToProcess = files.map(file => { |
|||
const fileExtension = [...file.name.split(".")].pop() |
|||
// filenames converted to UUIDs so they are unique
|
|||
const processedFileName = `${uuid.v4()}.${fileExtension}` |
|||
|
|||
return { |
|||
name: file.name, |
|||
path: file.path, |
|||
size: file.size, |
|||
type: file.type, |
|||
processedFileName, |
|||
extension: fileExtension, |
|||
outputPath: join(outputPath, processedFileName), |
|||
url: join("/attachments", processedFileName), |
|||
} |
|||
}) |
|||
|
|||
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(instanceId) |
|||
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 |
|||
} |
|||
|
|||
exports.performLocalFileProcessing = async function(ctx) { |
|||
const { files } = ctx.request.body |
|||
|
|||
const processedFileOutputPath = resolve( |
|||
budibaseAppsDir(), |
|||
ctx.user.appId, |
|||
"attachments" |
|||
) |
|||
|
|||
try { |
|||
ctx.body = await processLocalFileUploads({ |
|||
files, |
|||
outputPath: processedFileOutputPath, |
|||
instanceId: ctx.user.instanceId, |
|||
}) |
|||
} catch (err) { |
|||
ctx.throw(500, err) |
|||
} |
|||
} |
|||
|
|||
exports.serveApp = async function(ctx) { |
|||
const mainOrAuth = ctx.isAuthenticated ? "main" : "unauthenticated" |
|||
|
|||
// default to homedir
|
|||
const appPath = resolve( |
|||
budibaseAppsDir(), |
|||
ctx.params.appId, |
|||
"public", |
|||
mainOrAuth |
|||
) |
|||
|
|||
let appId = ctx.params.appId |
|||
if (process.env.CLOUD) { |
|||
appId = ctx.subdomains[1] |
|||
} |
|||
|
|||
// only set the appId cookie for /appId .. we COULD check for valid appIds
|
|||
// but would like to avoid that DB hit
|
|||
<<<<<<< HEAD |
|||
const looksLikeAppId = /^app_[0-9a-f]{32}$/.test(appId) |
|||
======= |
|||
const looksLikeAppId = /^(app_)?[0-9a-f]{32}$/.test(appId) |
|||
>>>>>>> origin/master |
|||
if (looksLikeAppId && !ctx.isAuthenticated) { |
|||
const anonUser = { |
|||
userId: "ANON", |
|||
accessLevelId: ANON_LEVEL_ID, |
|||
appId, |
|||
} |
|||
const anonToken = jwt.sign(anonUser, ctx.config.jwtSecret) |
|||
ctx.cookies.set("budibase:token", anonToken, { |
|||
path: "/", |
|||
httpOnly: false, |
|||
}) |
|||
} |
|||
|
|||
if (process.env.CLOUD) { |
|||
const S3_URL = `https://${appId}.app.budi.live/assets/${appId}/${mainOrAuth}/${ctx.file || |
|||
"index.production.html"}` |
|||
|
|||
const response = await fetch(S3_URL) |
|||
const body = await response.text() |
|||
ctx.body = body |
|||
return |
|||
} |
|||
|
|||
await send(ctx, ctx.file || "index.html", { root: ctx.devPath || appPath }) |
|||
} |
|||
|
|||
exports.serveAttachment = async function(ctx) { |
|||
const appId = ctx.user.appId |
|||
|
|||
const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments") |
|||
|
|||
// Serve from CloudFront
|
|||
if (process.env.CLOUD) { |
|||
const S3_URL = `https://cdn.app.budi.live/assets/${appId}/attachments/${ctx.file}` |
|||
|
|||
const response = await fetch(S3_URL) |
|||
const body = await response.text() |
|||
ctx.body = body |
|||
return |
|||
} |
|||
|
|||
await send(ctx, ctx.file, { root: attachmentsPath }) |
|||
} |
|||
|
|||
exports.serveAppAsset = async function(ctx) { |
|||
// default to homedir
|
|||
const mainOrAuth = ctx.isAuthenticated ? "main" : "unauthenticated" |
|||
|
|||
const appPath = resolve( |
|||
budibaseAppsDir(), |
|||
ctx.user.appId, |
|||
"public", |
|||
mainOrAuth |
|||
) |
|||
|
|||
await send(ctx, ctx.file, { root: ctx.devPath || appPath }) |
|||
} |
|||
|
|||
exports.serveComponentLibrary = async function(ctx) { |
|||
// default to homedir
|
|||
let componentLibraryPath = resolve( |
|||
budibaseAppsDir(), |
|||
ctx.user.appId, |
|||
"node_modules", |
|||
decodeURI(ctx.query.library), |
|||
"package", |
|||
"dist" |
|||
) |
|||
|
|||
if (ctx.isDev) { |
|||
componentLibraryPath = join( |
|||
budibaseTempDir(), |
|||
decodeURI(ctx.query.library), |
|||
"dist" |
|||
) |
|||
} |
|||
|
|||
// TODO: component libs should be versioned based on app version
|
|||
if (process.env.CLOUD) { |
|||
const appId = ctx.user.appId |
|||
const S3_URL = encodeURI( |
|||
`https://${appId}.app.budi.live/assets/componentlibrary/${ctx.query.library}/dist/index.js` |
|||
) |
|||
const response = await fetch(S3_URL) |
|||
const body = await response.text() |
|||
ctx.type = "application/javascript" |
|||
ctx.body = body |
|||
return |
|||
} |
|||
|
|||
await send(ctx, "/index.js", { root: componentLibraryPath }) |
|||
} |
|||
Loading…
Reference in new issue