1
0
Fork 0
mirror of synced 2024-08-15 01:51:33 +12:00

Merge pull request #7243 from Budibase/bug/sev2/orphaned-minio-attachment

Delete attachments on field clear from minio bucket
This commit is contained in:
melohagan 2022-08-17 16:48:27 +01:00 committed by GitHub
commit 5b9b071f62
8 changed files with 74 additions and 1 deletions

View file

@ -17,6 +17,7 @@
export let disabled = false export let disabled = false
export let fileSizeLimit = BYTES_IN_MB * 20 export let fileSizeLimit = BYTES_IN_MB * 20
export let processFiles = null export let processFiles = null
export let deleteAttachments = null
export let handleFileTooLarge = null export let handleFileTooLarge = null
export let handleTooManyFiles = null export let handleTooManyFiles = null
export let gallery = true export let gallery = true
@ -94,6 +95,11 @@
"change", "change",
value.filter((x, idx) => idx !== selectedImageIdx) value.filter((x, idx) => idx !== selectedImageIdx)
) )
if (deleteAttachments) {
await deleteAttachments(
value.filter((x, idx) => idx === selectedImageIdx).map(item => item.key)
)
}
selectedImageIdx = 0 selectedImageIdx = 0
} }

View file

@ -10,6 +10,7 @@
export let error = null export let error = null
export let fileSizeLimit = undefined export let fileSizeLimit = undefined
export let processFiles = undefined export let processFiles = undefined
export let deleteAttachments = undefined
export let handleFileTooLarge = undefined export let handleFileTooLarge = undefined
export let handleTooManyFiles = undefined export let handleTooManyFiles = undefined
export let gallery = true export let gallery = true
@ -30,6 +31,7 @@
{value} {value}
{fileSizeLimit} {fileSizeLimit}
{processFiles} {processFiles}
{deleteAttachments}
{handleFileTooLarge} {handleFileTooLarge}
{handleTooManyFiles} {handleTooManyFiles}
{gallery} {gallery}

View file

@ -27,6 +27,14 @@
return [] return []
} }
} }
async function deleteAttachments(fileList) {
try {
return await API.deleteBuilderAttachments(fileList)
} catch (error) {
return []
}
}
</script> </script>
<Dropzone <Dropzone
@ -34,5 +42,6 @@
{label} {label}
{...$$restProps} {...$$restProps}
{processFiles} {processFiles}
{deleteAttachments}
{handleFileTooLarge} {handleFileTooLarge}
/> />

View file

@ -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 => { const handleChange = e => {
fieldApi.setValue(e.detail) fieldApi.setValue(e.detail)
if (onChange) { if (onChange) {
@ -72,6 +83,7 @@
error={fieldState.error} error={fieldState.error}
on:change={handleChange} on:change={handleChange}
{processFiles} {processFiles}
{deleteAttachments}
{handleFileTooLarge} {handleFileTooLarge}
{handleTooManyFiles} {handleTooManyFiles}
{maximum} {maximum}

View file

@ -61,5 +61,32 @@ export const buildAttachmentEndpoints = API => {
}) })
return { publicUrl } 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,
},
})
},
} }
} }

View file

@ -12,7 +12,7 @@ const {
} = require("../../../utilities/fileSystem") } = require("../../../utilities/fileSystem")
const env = require("../../../environment") const env = require("../../../environment")
const { clientLibraryPath } = require("../../../utilities") const { clientLibraryPath } = require("../../../utilities")
const { upload } = require("../../../utilities/fileSystem") const { upload, deleteFiles } = require("../../../utilities/fileSystem")
const { attachmentsRelativeURL } = require("../../../utilities") const { attachmentsRelativeURL } = require("../../../utilities")
const { DocumentType } = require("../../../db/utils") const { DocumentType } = require("../../../db/utils")
const { getAppDB, getAppId } = require("@budibase/backend-core/context") 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) 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) { export const serveApp = async function (ctx: any) {
const db = getAppDB({ skip_setup: true }) const db = getAppDB({ skip_setup: true })
const appInfo = await db.get(DocumentType.APP_METADATA) const appInfo = await db.get(DocumentType.APP_METADATA)

View file

@ -38,6 +38,11 @@ router
// TODO: for now this builder endpoint is not authorized/secured, will need to be // TODO: for now this builder endpoint is not authorized/secured, will need to be
.get("/builder/:file*", controller.serveBuilder) .get("/builder/:file*", controller.serveBuilder)
.post("/api/attachments/process", authorized(BUILDER), controller.uploadFile) .post("/api/attachments/process", authorized(BUILDER), controller.uploadFile)
.post(
"/api/attachments/delete",
authorized(BUILDER),
controller.deleteObjects
)
.post("/api/beta/:feature", controller.toggleBetaUiFeature) .post("/api/beta/:feature", controller.toggleBetaUiFeature)
.post( .post(
"/api/attachments/:tableId/upload", "/api/attachments/:tableId/upload",
@ -45,6 +50,12 @@ router
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE), authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
controller.uploadFile controller.uploadFile
) )
.post(
"/api/attachments/:tableId/delete",
paramResource("tableId"),
authorized(PermissionTypes.TABLE, PermissionLevels.WRITE),
controller.deleteObjects
)
.get("/:appId/:path*", controller.serveApp) .get("/:appId/:path*", controller.serveApp)
.get("/app/:appUrl/:path*", controller.serveApp) .get("/app/:appUrl/:path*", controller.serveApp)
.post( .post(

View file

@ -15,6 +15,7 @@ const {
streamUpload, streamUpload,
deleteFolder, deleteFolder,
downloadTarball, downloadTarball,
deleteFiles,
} = require("./utilities") } = require("./utilities")
const { updateClientLibrary } = require("./clientLibrary") const { updateClientLibrary } = require("./clientLibrary")
const env = require("../../environment") const env = require("../../environment")
@ -327,5 +328,6 @@ exports.cleanup = appIds => {
exports.upload = upload exports.upload = upload
exports.retrieve = retrieve exports.retrieve = retrieve
exports.retrieveToTmp = retrieveToTmp exports.retrieveToTmp = retrieveToTmp
exports.deleteFiles = deleteFiles
exports.TOP_LEVEL_PATH = TOP_LEVEL_PATH exports.TOP_LEVEL_PATH = TOP_LEVEL_PATH
exports.NODE_MODULES_PATH = NODE_MODULES_PATH exports.NODE_MODULES_PATH = NODE_MODULES_PATH