fix: Uploaded and immediately deleted images are not removed from storage (#4562)

* fix: Uploaded and immediately deleted images are not removed from storage upon permanant delete
closes #4557

* Move attachment deletion async
This commit is contained in:
Tom Moor
2022-12-11 08:29:38 -08:00
committed by GitHub
parent 7e22526cc7
commit 0f19c550f9
5 changed files with 59 additions and 22 deletions

View File

@@ -1,7 +1,9 @@
import { uniq } from "lodash";
import { QueryTypes } from "sequelize";
import { sequelize } from "@server/database/sequelize";
import Logger from "@server/logging/Logger";
import { Document, Attachment } from "@server/models";
import DeleteAttachmentTask from "@server/queues/tasks/DeleteAttachmentTask";
import parseAttachmentIds from "@server/utils/parseAttachmentIds";
export default async function documentPermanentDeleter(documents: Document[]) {
@@ -22,34 +24,53 @@ export default async function documentPermanentDeleter(documents: Document[]) {
`;
for (const document of documents) {
const attachmentIds = parseAttachmentIds(document.text);
// Find any attachments that are referenced in the text content
const attachmentIdsInText = parseAttachmentIds(document.text);
for (const attachmentId of attachmentIds) {
const [{ count }] = await sequelize.query(query, {
type: QueryTypes.SELECT,
replacements: {
documentId: document.id,
// Find any attachments that were originally uploaded to this document
const attachmentIdsForDocument = (
await Attachment.findAll({
attributes: ["id"],
where: {
teamId: document.teamId,
query: attachmentId,
documentId: document.id,
},
});
})
).map((attachment) => attachment.id);
if (parseInt(count) === 0) {
const attachment = await Attachment.findOne({
where: {
const attachmentIds = uniq([
...attachmentIdsInText,
...attachmentIdsForDocument,
]);
await Promise.all(
attachmentIds.map(async (attachmentId) => {
// Check if the attachment is referenced in any other documents this
// is needed as it's easy to copy and paste content between documents.
// An uploaded attachment may end up referenced in multiple documents.
const [{ count }] = await sequelize.query<{ count: string }>(query, {
type: QueryTypes.SELECT,
replacements: {
documentId: document.id,
teamId: document.teamId,
id: attachmentId,
query: attachmentId,
},
});
if (attachment) {
await attachment.destroy();
Logger.info("commands", `Attachment ${attachmentId} deleted`);
} else {
Logger.info("commands", `Unknown attachment ${attachmentId} ignored`);
// If the attachment is not referenced in any other documents then
// delete it from the database and the storage provider.
if (parseInt(count) === 0) {
Logger.info(
"commands",
`Attachment ${attachmentId} scheduled for deletion`
);
await DeleteAttachmentTask.schedule({
attachmentId,
teamId: document.teamId,
});
}
}
}
})
);
}
return Document.scope("withDrafts").destroy({