Browse Source
Merge pull request #7243 from Budibase/bug/sev2/orphaned-minio-attachment
Delete attachments on field clear from minio bucket
pull/7333/head
melohagan
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with
74 additions and
1 deletions
-
packages/bbui/src/Form/Core/Dropzone.svelte
-
packages/bbui/src/Form/Dropzone.svelte
-
packages/builder/src/components/common/Dropzone.svelte
-
packages/client/src/components/app/forms/AttachmentField.svelte
-
packages/frontend-core/src/api/attachments.js
-
packages/server/src/api/controllers/static/index.ts
-
packages/server/src/api/routes/static.ts
-
packages/server/src/utilities/fileSystem/index.js
|
|
|
@ -17,6 +17,7 @@ |
|
|
|
export let disabled = false |
|
|
|
export let fileSizeLimit = BYTES_IN_MB * 20 |
|
|
|
export let processFiles = null |
|
|
|
export let deleteAttachments = null |
|
|
|
export let handleFileTooLarge = null |
|
|
|
export let handleTooManyFiles = null |
|
|
|
export let gallery = true |
|
|
|
@ -94,6 +95,11 @@ |
|
|
|
"change", |
|
|
|
value.filter((x, idx) => idx !== selectedImageIdx) |
|
|
|
) |
|
|
|
if (deleteAttachments) { |
|
|
|
await deleteAttachments( |
|
|
|
value.filter((x, idx) => idx === selectedImageIdx).map(item => item.key) |
|
|
|
) |
|
|
|
} |
|
|
|
selectedImageIdx = 0 |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -10,6 +10,7 @@ |
|
|
|
export let error = null |
|
|
|
export let fileSizeLimit = undefined |
|
|
|
export let processFiles = undefined |
|
|
|
export let deleteAttachments = undefined |
|
|
|
export let handleFileTooLarge = undefined |
|
|
|
export let handleTooManyFiles = undefined |
|
|
|
export let gallery = true |
|
|
|
@ -30,6 +31,7 @@ |
|
|
|
{value} |
|
|
|
{fileSizeLimit} |
|
|
|
{processFiles} |
|
|
|
{deleteAttachments} |
|
|
|
{handleFileTooLarge} |
|
|
|
{handleTooManyFiles} |
|
|
|
{gallery} |
|
|
|
|
|
|
|
@ -27,6 +27,14 @@ |
|
|
|
return [] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async function deleteAttachments(fileList) { |
|
|
|
try { |
|
|
|
return await API.deleteBuilderAttachments(fileList) |
|
|
|
} catch (error) { |
|
|
|
return [] |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<Dropzone |
|
|
|
@ -34,5 +42,6 @@ |
|
|
|
{label} |
|
|
|
{...$$restProps} |
|
|
|
{processFiles} |
|
|
|
{deleteAttachments} |
|
|
|
{handleFileTooLarge} |
|
|
|
/> |
|
|
|
|
|
|
|
@ -47,6 +47,17 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const deleteAttachments = async fileList => { |
|
|
|
try { |
|
|
|
return await API.deleteAttachments({ |
|
|
|
keys: fileList, |
|
|
|
tableId: formContext?.dataSource?.tableId, |
|
|
|
}) |
|
|
|
} catch (error) { |
|
|
|
return [] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const handleChange = e => { |
|
|
|
fieldApi.setValue(e.detail) |
|
|
|
if (onChange) { |
|
|
|
@ -72,6 +83,7 @@ |
|
|
|
error={fieldState.error} |
|
|
|
on:change={handleChange} |
|
|
|
{processFiles} |
|
|
|
{deleteAttachments} |
|
|
|
{handleFileTooLarge} |
|
|
|
{handleTooManyFiles} |
|
|
|
{maximum} |
|
|
|
|
|
|
|
@ -61,5 +61,32 @@ export const buildAttachmentEndpoints = API => { |
|
|
|
}) |
|
|
|
return { publicUrl } |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Deletes attachments from the bucket. |
|
|
|
* @param keys the attachments to delete |
|
|
|
* @param tableId the associated table ID |
|
|
|
*/ |
|
|
|
deleteAttachments: async ({ keys, tableId }) => { |
|
|
|
return await API.post({ |
|
|
|
url: `/api/attachments/${tableId}/delete`, |
|
|
|
body: { |
|
|
|
keys, |
|
|
|
}, |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Deletes attachments from the builder bucket. |
|
|
|
* @param keys the attachments to delete |
|
|
|
*/ |
|
|
|
deleteBuilderAttachments: async keys => { |
|
|
|
return await API.post({ |
|
|
|
url: `/api/attachments/delete`, |
|
|
|
body: { |
|
|
|
keys, |
|
|
|
}, |
|
|
|
}) |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -12,7 +12,7 @@ const { |
|
|
|
} = require("../../../utilities/fileSystem") |
|
|
|
const env = require("../../../environment") |
|
|
|
const { clientLibraryPath } = require("../../../utilities") |
|
|
|
const { upload } = require("../../../utilities/fileSystem") |
|
|
|
const { upload, deleteFiles } = require("../../../utilities/fileSystem") |
|
|
|
const { attachmentsRelativeURL } = require("../../../utilities") |
|
|
|
const { DocumentType } = require("../../../db/utils") |
|
|
|
const { getAppDB, getAppId } = require("@budibase/backend-core/context") |
|
|
|
@ -97,6 +97,10 @@ export const uploadFile = async function (ctx: any) { |
|
|
|
ctx.body = await Promise.all(uploads) |
|
|
|
} |
|
|
|
|
|
|
|
export const deleteObjects = async function (ctx: any) { |
|
|
|
ctx.body = await deleteFiles(ObjectStoreBuckets.APPS, ctx.request.body.keys) |
|
|
|
} |
|
|
|
|
|
|
|
export const serveApp = async function (ctx: any) { |
|
|
|
const db = getAppDB({ skip_setup: true }) |
|
|
|
const appInfo = await db.get(DocumentType.APP_METADATA) |
|
|
|
|
|
|
|
@ -38,6 +38,11 @@ router |
|
|
|
// TODO: for now this builder endpoint is not authorized/secured, will need to be
|
|
|
|
.get("/builder/:file*", controller.serveBuilder) |
|
|
|
.post("/api/attachments/process", authorized(BUILDER), controller.uploadFile) |
|
|
|
.post( |
|
|
|
"/api/attachments/delete", |
|
|
|
authorized(BUILDER), |
|
|
|
controller.deleteObjects |
|
|
|
) |
|
|
|
.post("/api/beta/:feature", controller.toggleBetaUiFeature) |
|
|
|
.post( |
|
|
|
"/api/attachments/:tableId/upload", |
|
|
|
@ -45,6 +50,12 @@ router |
|
|
|
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE), |
|
|
|
controller.uploadFile |
|
|
|
) |
|
|
|
.post( |
|
|
|
"/api/attachments/:tableId/delete", |
|
|
|
paramResource("tableId"), |
|
|
|
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE), |
|
|
|
controller.deleteObjects |
|
|
|
) |
|
|
|
.get("/:appId/:path*", controller.serveApp) |
|
|
|
.get("/app/:appUrl/:path*", controller.serveApp) |
|
|
|
.post( |
|
|
|
|
|
|
|
@ -15,6 +15,7 @@ const { |
|
|
|
streamUpload, |
|
|
|
deleteFolder, |
|
|
|
downloadTarball, |
|
|
|
deleteFiles, |
|
|
|
} = require("./utilities") |
|
|
|
const { updateClientLibrary } = require("./clientLibrary") |
|
|
|
const env = require("../../environment") |
|
|
|
@ -327,5 +328,6 @@ exports.cleanup = appIds => { |
|
|
|
exports.upload = upload |
|
|
|
exports.retrieve = retrieve |
|
|
|
exports.retrieveToTmp = retrieveToTmp |
|
|
|
exports.deleteFiles = deleteFiles |
|
|
|
exports.TOP_LEVEL_PATH = TOP_LEVEL_PATH |
|
|
|
exports.NODE_MODULES_PATH = NODE_MODULES_PATH |
|
|
|
|