From c562d33c8f117d4490d1e1568c6a4a1a3380ba84 Mon Sep 17 00:00:00 2001
From: Paul Makles <paulmakles@gmail.com>
Date: Mon, 18 Jan 2021 21:02:04 +0000
Subject: [PATCH] Add message delete route.

---
 src/database/entities/message.rs      |  2 +-
 src/database/permissions/channel.rs   |  6 ++++-
 src/notifications/events.rs           |  4 ++-
 src/routes/channels/message_delete.rs | 39 +++++++++++++++++++++++++++
 src/routes/channels/message_edit.rs   |  2 +-
 src/routes/channels/mod.rs            |  4 ++-
 6 files changed, 52 insertions(+), 5 deletions(-)
 create mode 100644 src/routes/channels/message_delete.rs

diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs
index 13975de..8009934 100644
--- a/src/database/entities/message.rs
+++ b/src/database/entities/message.rs
@@ -71,7 +71,7 @@ impl Message {
 
     pub async fn publish_delete(self) -> Result<()> {
         let channel = self.channel.clone();
-        ClientboundNotification::MessageDelete(self.id)
+        ClientboundNotification::MessageDelete { id: self.id }
             .publish(channel)
             .await
             .ok();
diff --git a/src/database/permissions/channel.rs b/src/database/permissions/channel.rs
index 7164b3f..41656bd 100644
--- a/src/database/permissions/channel.rs
+++ b/src/database/permissions/channel.rs
@@ -7,6 +7,7 @@ use std::ops;
 pub enum ChannelPermission {
     View = 1,
     SendMessage = 2,
+    ManageMessages = 4,
 }
 
 bitfield! {
@@ -14,6 +15,7 @@ bitfield! {
     u32;
     pub get_view, _: 31;
     pub get_send_message, _: 30;
+    pub get_manage_messages, _: 29;
 }
 
 impl_op_ex!(+ |a: &ChannelPermission, b: &ChannelPermission| -> u32 { *a as u32 | *b as u32 });
@@ -23,7 +25,9 @@ pub async fn calculate(user: &User, target: &Channel) -> ChannelPermissions<[u32
     match target {
         Channel::SavedMessages { user: owner, .. } => {
             if &user.id == owner {
-                ChannelPermissions([ChannelPermission::View + ChannelPermission::SendMessage])
+                ChannelPermissions([ChannelPermission::View
+                    + ChannelPermission::SendMessage
+                    + ChannelPermission::ManageMessages])
             } else {
                 ChannelPermissions([0])
             }
diff --git a/src/notifications/events.rs b/src/notifications/events.rs
index cde3946..15beec5 100644
--- a/src/notifications/events.rs
+++ b/src/notifications/events.rs
@@ -38,7 +38,9 @@ pub enum ClientboundNotification {
 
     Message(Message),
     MessageEdit(Message),
-    MessageDelete(String),
+    MessageDelete {
+        id: String,
+    },
 
     /*MessageCreate {
         id: String,
diff --git a/src/routes/channels/message_delete.rs b/src/routes/channels/message_delete.rs
new file mode 100644
index 0000000..61204e7
--- /dev/null
+++ b/src/routes/channels/message_delete.rs
@@ -0,0 +1,39 @@
+use crate::database::*;
+use crate::util::result::{Error, Result};
+
+use mongodb::bson::doc;
+
+#[delete("/<target>/messages/<msg>")]
+pub async fn req(user: User, target: Ref, msg: Ref) -> Result<()> {
+    let channel = target.fetch_channel().await?;
+
+    let perm = permissions::channel::calculate(&user, &channel).await;
+    if !perm.get_view() {
+        Err(Error::LabelMe)?
+    }
+
+    let message = msg.fetch_message().await?;
+    if message.author != user.id && !perm.get_manage_messages() {
+        match channel {
+            Channel::SavedMessages { .. } => unreachable!(),
+            _ => Err(Error::CannotEditMessage)?,
+        }
+    }
+
+    get_collection("messages")
+        .delete_one(
+            doc! {
+                "_id": &message.id
+            },
+            None,
+        )
+        .await
+        .map_err(|_| Error::DatabaseError {
+            operation: "delete_one",
+            with: "message",
+        })?;
+
+    message.publish_delete().await?;
+
+    Ok(())
+}
diff --git a/src/routes/channels/message_edit.rs b/src/routes/channels/message_edit.rs
index ccc2f8a..0e57c18 100644
--- a/src/routes/channels/message_edit.rs
+++ b/src/routes/channels/message_edit.rs
@@ -2,7 +2,7 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use chrono::Utc;
-use mongodb::bson::{Bson, DateTime, doc};
+use mongodb::bson::{doc, Bson, DateTime};
 use rocket_contrib::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
diff --git a/src/routes/channels/mod.rs b/src/routes/channels/mod.rs
index f888557..dd20b77 100644
--- a/src/routes/channels/mod.rs
+++ b/src/routes/channels/mod.rs
@@ -2,6 +2,7 @@ use rocket::Route;
 
 mod delete_channel;
 mod fetch_channel;
+mod message_delete;
 mod message_edit;
 mod message_fetch;
 mod message_query;
@@ -14,6 +15,7 @@ pub fn routes() -> Vec<Route> {
         message_send::req,
         message_query::req,
         message_fetch::req,
-        message_edit::req
+        message_edit::req,
+        message_delete::req
     ]
 }
-- 
GitLab