Updating with a tested and functional API for uploading files for configs.
This commit is contained in:
parent
1d435013b8
commit
4e3bc326b4
|
@ -38,6 +38,9 @@ static_resources:
|
||||||
route:
|
route:
|
||||||
cluster: server-dev
|
cluster: server-dev
|
||||||
|
|
||||||
|
# the below three cases are needed to make sure
|
||||||
|
# all traffic prefixed for the builder is passed through
|
||||||
|
# correctly.
|
||||||
- match: { path: "/" }
|
- match: { path: "/" }
|
||||||
route:
|
route:
|
||||||
cluster: builder-dev
|
cluster: builder-dev
|
||||||
|
|
|
@ -9,7 +9,7 @@ const { join } = require("path")
|
||||||
const fs = require("fs")
|
const fs = require("fs")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
const { budibaseTempDir, ObjectStoreBuckets } = require("./utils")
|
const { budibaseTempDir, ObjectStoreBuckets } = require("./utils")
|
||||||
const uuid = require("uuid/v4")
|
const { v4 } = require("uuid")
|
||||||
|
|
||||||
const streamPipeline = promisify(stream.pipeline)
|
const streamPipeline = promisify(stream.pipeline)
|
||||||
// use this as a temporary store of buckets that are being created
|
// use this as a temporary store of buckets that are being created
|
||||||
|
@ -44,7 +44,7 @@ function publicPolicy(bucketName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PUBLIC_BUCKETS = [ObjectStoreBuckets.APPS]
|
const PUBLIC_BUCKETS = [ObjectStoreBuckets.APPS, ObjectStoreBuckets.GLOBAL]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a connection to the object store using the S3 SDK.
|
* Gets a connection to the object store using the S3 SDK.
|
||||||
|
@ -173,7 +173,7 @@ exports.retrieve = async (bucket, filepath) => {
|
||||||
*/
|
*/
|
||||||
exports.retrieveToTmp = async (bucket, filepath) => {
|
exports.retrieveToTmp = async (bucket, filepath) => {
|
||||||
const data = await exports.retrieve(bucket, filepath)
|
const data = await exports.retrieve(bucket, filepath)
|
||||||
const outputPath = join(budibaseTempDir(), uuid())
|
const outputPath = join(budibaseTempDir(), v4())
|
||||||
fs.writeFileSync(outputPath, data)
|
fs.writeFileSync(outputPath, data)
|
||||||
return outputPath
|
return outputPath
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ exports.ObjectStoreBuckets = {
|
||||||
BACKUPS: "backups",
|
BACKUPS: "backups",
|
||||||
APPS: "prod-budi-app-assets",
|
APPS: "prod-budi-app-assets",
|
||||||
TEMPLATES: "templates",
|
TEMPLATES: "templates",
|
||||||
|
GLOBAL: "global",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.budibaseTempDir = function () {
|
exports.budibaseTempDir = function () {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@ const send = require("koa-send")
|
||||||
const { resolve, join } = require("../../../utilities/centralPath")
|
const { resolve, join } = require("../../../utilities/centralPath")
|
||||||
const fetch = require("node-fetch")
|
const fetch = require("node-fetch")
|
||||||
const uuid = require("uuid")
|
const uuid = require("uuid")
|
||||||
|
const { ObjectStoreBuckets } = require("@budibase/auth").objectStore
|
||||||
const { prepareUpload } = require("../deploy/utils")
|
const { prepareUpload } = require("../deploy/utils")
|
||||||
const { processString } = require("@budibase/string-templates")
|
const { processString } = require("@budibase/string-templates")
|
||||||
const { budibaseTempDir } = require("../../../utilities/budibaseDir")
|
const { budibaseTempDir } = require("../../../utilities/budibaseDir")
|
||||||
|
@ -15,7 +16,6 @@ const {
|
||||||
TOP_LEVEL_PATH,
|
TOP_LEVEL_PATH,
|
||||||
} = require("../../../utilities/fileSystem")
|
} = require("../../../utilities/fileSystem")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
// const fileProcessor = require("../../../utilities/fileSystem/processor")
|
|
||||||
const { objectStoreUrl, clientLibraryPath } = require("../../../utilities")
|
const { objectStoreUrl, clientLibraryPath } = require("../../../utilities")
|
||||||
|
|
||||||
async function checkForSelfHostedURL(ctx) {
|
async function checkForSelfHostedURL(ctx) {
|
||||||
|
@ -48,17 +48,10 @@ exports.uploadFile = async function (ctx) {
|
||||||
// filenames converted to UUIDs so they are unique
|
// filenames converted to UUIDs so they are unique
|
||||||
const processedFileName = `${uuid.v4()}.${fileExtension}`
|
const processedFileName = `${uuid.v4()}.${fileExtension}`
|
||||||
|
|
||||||
// need to handle image processing
|
|
||||||
// TODO either offer this as an option, or don't do it at all
|
|
||||||
// await fileProcessor.process({
|
|
||||||
// ...file,
|
|
||||||
// extension: fileExtension,
|
|
||||||
// })
|
|
||||||
|
|
||||||
return prepareUpload({
|
return prepareUpload({
|
||||||
file,
|
file,
|
||||||
s3Key: `assets/${ctx.appId}/attachments/${processedFileName}`,
|
s3Key: `assets/${ctx.appId}/attachments/${processedFileName}`,
|
||||||
bucket: "prod-budi-app-assets",
|
bucket: ObjectStoreBuckets.APPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ const fetch = require("node-fetch")
|
||||||
const { Configs } = require("../../../constants")
|
const { Configs } = require("../../../constants")
|
||||||
const email = require("../../../utilities/email")
|
const email = require("../../../utilities/email")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
|
const { upload, ObjectStoreBuckets } = require("@budibase/auth").objectStore
|
||||||
|
|
||||||
const APP_PREFIX = "app_"
|
const APP_PREFIX = "app_"
|
||||||
|
|
||||||
|
@ -94,6 +95,46 @@ exports.find = async function (ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.upload = async function (ctx) {
|
||||||
|
if (ctx.request.files == null || ctx.request.files.file.length > 1) {
|
||||||
|
ctx.throw(400, "One file must be uploaded.")
|
||||||
|
}
|
||||||
|
const file = ctx.request.files.file
|
||||||
|
const { type, name } = ctx.params
|
||||||
|
|
||||||
|
const fileExtension = [...file.name.split(".")].pop()
|
||||||
|
// filenames converted to UUIDs so they are unique
|
||||||
|
const processedFileName = `${name}.${fileExtension}`
|
||||||
|
|
||||||
|
const bucket = ObjectStoreBuckets.GLOBAL
|
||||||
|
const key = `${type}/${processedFileName}`
|
||||||
|
await upload({
|
||||||
|
bucket,
|
||||||
|
filename: key,
|
||||||
|
path: file.path,
|
||||||
|
type: file.type,
|
||||||
|
})
|
||||||
|
|
||||||
|
// add to configuration structure
|
||||||
|
// TODO: right now this only does a global level
|
||||||
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
|
let config = await getScopedFullConfig(db, { type })
|
||||||
|
if (!config) {
|
||||||
|
config = {
|
||||||
|
_id: generateConfigID({ type }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const url = `/${bucket}/${key}`
|
||||||
|
config[`${name}Url`] = url
|
||||||
|
// write back to db with url updated
|
||||||
|
await db.put(config)
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
message: "File has been uploaded and url stored to config.",
|
||||||
|
url,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exports.destroy = async function (ctx) {
|
exports.destroy = async function (ctx) {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
const { id, rev } = ctx.params
|
const { id, rev } = ctx.params
|
||||||
|
|
|
@ -2,7 +2,7 @@ const Router = require("@koa/router")
|
||||||
const controller = require("../../controllers/admin/configs")
|
const controller = require("../../controllers/admin/configs")
|
||||||
const joiValidator = require("../../../middleware/joi-validator")
|
const joiValidator = require("../../../middleware/joi-validator")
|
||||||
const Joi = require("joi")
|
const Joi = require("joi")
|
||||||
const { Configs } = require("../../../constants")
|
const { Configs, ConfigUploads } = require("../../../constants")
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
|
@ -61,6 +61,14 @@ function buildConfigSaveValidation() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildUploadValidation() {
|
||||||
|
// prettier-ignore
|
||||||
|
return joiValidator.params(Joi.object({
|
||||||
|
type: Joi.string().valid(...Object.values(Configs)).required(),
|
||||||
|
name: Joi.string().valid(...Object.values(ConfigUploads)).required(),
|
||||||
|
}).required())
|
||||||
|
}
|
||||||
|
|
||||||
function buildConfigGetValidation() {
|
function buildConfigGetValidation() {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return joiValidator.params(Joi.object({
|
return joiValidator.params(Joi.object({
|
||||||
|
@ -79,5 +87,10 @@ router
|
||||||
controller.fetch
|
controller.fetch
|
||||||
)
|
)
|
||||||
.get("/api/admin/configs/:type", buildConfigGetValidation(), controller.find)
|
.get("/api/admin/configs/:type", buildConfigGetValidation(), controller.find)
|
||||||
|
.post(
|
||||||
|
"/api/admin/configs/upload/:type/:name",
|
||||||
|
buildUploadValidation(),
|
||||||
|
controller.upload
|
||||||
|
)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -17,6 +17,10 @@ exports.Configs = {
|
||||||
GOOGLE: "google",
|
GOOGLE: "google",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.ConfigUploads = {
|
||||||
|
LOGO: "logo",
|
||||||
|
}
|
||||||
|
|
||||||
const TemplateTypes = {
|
const TemplateTypes = {
|
||||||
EMAIL: "email",
|
EMAIL: "email",
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue