diff --git a/src/api/routes/channels/#channel_id/attachments.ts b/src/api/routes/channels/#channel_id/attachments.ts
index d515a120c..d0297dce8 100644
--- a/src/api/routes/channels/#channel_id/attachments.ts
+++ b/src/api/routes/channels/#channel_id/attachments.ts
@@ -35,6 +35,7 @@ import {
import { Request, Response, Router } from "express";
import { In } from "typeorm";
import { CloudAttachment } from "../../../../util/entities/CloudAttachment";
+import fetch from "node-fetch-commonjs";
const router: Router = Router();
@@ -97,4 +98,38 @@ router.post(
},
);
+router.delete("/:cloud_attachment_url", async (req: Request, res: Response) => {
+ const { channel_id, cloud_attachment_url } = req.params;
+
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ const att = await CloudAttachment.findOneOrFail({ where: { uploadFilename: decodeURI(cloud_attachment_url) } });
+ if (att.userId !== user.id) {
+ return res.status(403).json({
+ code: 403,
+ message: "You do not own this attachment.",
+ });
+ }
+
+ if (att.channelId !== channel.id) {
+ return res.status(400).json({
+ code: 400,
+ message: "Attachment does not belong to this channel.",
+ });
+ }
+
+ const response = await fetch(
+ `${Config.get().cdn.endpointPrivate || "http://localhost:3001"}/attachments/${att.uploadFilename}`,
+ {
+ headers: {
+ signature: Config.get().security.requestSignature
+ },
+ method: "DELETE",
+ },
+ );
+
+ await att.remove();
+ return res.status(response.status).send(response.body);
+});
+
export default router;
diff --git a/src/cdn/routes/attachments.ts b/src/cdn/routes/attachments.ts
index fbab566a8..2ab75224a 100644
--- a/src/cdn/routes/attachments.ts
+++ b/src/cdn/routes/attachments.ts
@@ -124,13 +124,13 @@ router.put("/:channel_id/:batch_id/:attachment_id/:filename", multer.single("fil
uploadFilename: `${channel_id}/${batch_id}/${attachment_id}/${filename}`,
channelId: channel_id,
userAttachmentId: attachment_id,
- userFilename: filename
+ userFilename: filename,
},
});
const maxLength = Config.get().cdn.maxAttachmentSize;
- console.log("[Cloud Upload] Uploading attachment", att.id, att.userFilename, `Max size: ${maxLength} bytes\n`, att);
+ console.log("[Cloud Upload] Uploading attachment", att.id, att.userFilename, `Max size: ${maxLength} bytes`);
const chunks: Buffer[] = [];
let length = 0;
@@ -161,9 +161,32 @@ router.put("/:channel_id/:batch_id/:attachment_id/:filename", multer.single("fil
att.size = buffer.length;
await att.save();
- console.log("[Cloud Upload] Saved attachment", att.id, att.userFilename, att);
+ console.log("[Cloud Upload] Saved attachment", att.id, att.userFilename);
res.status(200).end();
});
});
+router.delete("/:channel_id/:batch_id/:attachment_id/:filename", async (req: Request, res: Response) => {
+ if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature");
+
+ const { channel_id, batch_id, attachment_id, filename } = req.params;
+ const path = `attachments/${channel_id}/${batch_id}/${attachment_id}/${filename}`;
+
+ const att = await CloudAttachment.findOne({
+ where: {
+ uploadFilename: `${channel_id}/${batch_id}/${attachment_id}/${filename}`,
+ channelId: channel_id,
+ userAttachmentId: attachment_id,
+ userFilename: filename,
+ },
+ });
+
+ if (att) {
+ await att.remove();
+ await storage.delete(path);
+ return res.send({ success: true });
+ }
+ return res.status(404).send("Attachment not found");
+});
+
export default router;
|