summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-09-13 17:59:21 +0200
committerGitHub <noreply@github.com>2021-09-13 17:59:21 +0200
commit924f3cc39a270065fab917f113bcd7eca514c836 (patch)
tree89367fdebb4f2592b5183047b04ec4259daeaaf3
parent:bug: fix In() query (diff)
parentDelete attachments of deleted messages, fix #273 (diff)
downloadserver-924f3cc39a270065fab917f113bcd7eca514c836.tar.xz
Merge pull request #355 from AlTech98/attachments
Attachments fixes
-rw-r--r--api/assets/schemas.json6
-rw-r--r--api/src/routes/channels/#channel_id/messages/#message_id/index.ts7
-rw-r--r--api/src/routes/channels/#channel_id/messages/index.ts1
-rw-r--r--api/src/util/Attachments.ts12
-rw-r--r--api/src/util/cdn.ts13
-rw-r--r--cdn/src/util/FileStorage.ts1
-rw-r--r--util/src/entities/Message.ts2
7 files changed, 37 insertions, 5 deletions
diff --git a/api/assets/schemas.json b/api/assets/schemas.json
index ac7df859..94aa0660 100644
--- a/api/assets/schemas.json
+++ b/api/assets/schemas.json
@@ -462,7 +462,11 @@
             "payload_json": {
                 "type": "string"
             },
-            "file": {}
+            "file": {},
+            "attachments": {
+                "type": "array",
+                "items": {}
+            }
         },
         "additionalProperties": false,
         "definitions": {
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
index d0f780db..b5220fab 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -3,6 +3,7 @@ import { Router, Response, Request } from "express";
 import { route } from "@fosscord/api";
 import { handleMessage, postHandleMessage } from "@fosscord/api";
 import { MessageCreateSchema } from "../index";
+import { deleteMessageAttachments } from "@fosscord/api/util/Attachments";
 
 const router = Router();
 // TODO: message content/embed string length limit
@@ -11,7 +12,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
 	const { message_id, channel_id } = req.params;
 	var body = req.body as MessageCreateSchema;
 
-	const message = await Message.findOneOrFail({ id: message_id, channel_id });
+	const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
 
 	const permissions = await getPermission(req.user_id, undefined, channel_id);
 
@@ -33,6 +34,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
 	});
 
 	await Promise.all([
+		await deleteMessageAttachments(message_id, new_message.attachments), //This delete all the attachments not in the array
 		new_message!.save(),
 		await emitEvent({
 			event: "MESSAGE_UPDATE",
@@ -46,8 +48,6 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
 	return res.json(message);
 });
 
-// TODO: delete attachments in message
-
 // permission check only if deletes messagr from other user
 router.delete("/", route({}), async (req: Request, res: Response) => {
 	const { message_id, channel_id } = req.params;
@@ -60,6 +60,7 @@ router.delete("/", route({}), async (req: Request, res: Response) => {
 		permission.hasThrow("MANAGE_MESSAGES");
 	}
 
+	await deleteMessageAttachments(message_id);
 	await Message.delete({ id: message_id });
 
 	await emitEvent({
diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts
index 11334367..25ecc1c7 100644
--- a/api/src/routes/channels/#channel_id/messages/index.ts
+++ b/api/src/routes/channels/#channel_id/messages/index.ts
@@ -51,6 +51,7 @@ export interface MessageCreateSchema {
 	};
 	payload_json?: string;
 	file?: any;
+	attachments?: any[]; //TODO we should create an interface for attachments
 }
 
 // https://discord.com/developers/docs/resources/channel#create-message
diff --git a/api/src/util/Attachments.ts b/api/src/util/Attachments.ts
new file mode 100644
index 00000000..addda97f
--- /dev/null
+++ b/api/src/util/Attachments.ts
@@ -0,0 +1,12 @@
+import { Attachment } from "@fosscord/util";
+import { deleteFile } from "@fosscord/api";
+import { URL } from "url";
+
+export async function deleteMessageAttachments(messageId: string, keep?: Attachment[]) {
+	let attachments = await Attachment.find({ message_id: messageId });
+	if (keep)
+		attachments = attachments.filter(x => !keep.map(k => k.id).includes(x.id));
+	await Promise.all(attachments.map(a => a.remove()));
+
+	attachments.forEach(a => deleteFile((new URL(a.url)).pathname)); //We don't need to await since this is done on the cdn
+}
diff --git a/api/src/util/cdn.ts b/api/src/util/cdn.ts
index 3c71d980..88b0ea0d 100644
--- a/api/src/util/cdn.ts
+++ b/api/src/util/cdn.ts
@@ -38,3 +38,16 @@ export async function handleFile(path: string, body?: string): Promise<string |
 		throw new HTTPError("Invalid " + path);
 	}
 }
+
+export async function deleteFile(path: string) {
+	const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
+		headers: {
+			signature: Config.get().security.requestSignature,
+		},
+		method: "DELETE",
+	});
+	const result = await response.json();
+
+	if (response.status !== 200) throw result;
+	return result;
+}
diff --git a/cdn/src/util/FileStorage.ts b/cdn/src/util/FileStorage.ts
index fae6eb1a..e0b24a84 100644
--- a/cdn/src/util/FileStorage.ts
+++ b/cdn/src/util/FileStorage.ts
@@ -37,6 +37,7 @@ export class FileStorage implements Storage {
 	}
 
 	async delete(path: string) {
+		//TODO we should delete the parent directory if empty
 		fs.unlinkSync(getPath(path));
 	}
 }
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
index f4c7fdc7..506db71a 100644
--- a/util/src/entities/Message.ts
+++ b/util/src/entities/Message.ts
@@ -128,7 +128,7 @@ export class Message extends BaseClass {
 	sticker_items?: Sticker[];
 
 	@JoinColumn({ name: "attachment_ids" })
-	@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message)
+	@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true })
 	attachments?: Attachment[];
 
 	@Column({ type: "simple-json" })