From 3d3db80e6197fa8b774769c2788a1ad1aa52ab67 Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Mon, 18 Jan 2021 14:50:17 +0000 Subject: [PATCH] Channel subscription, message sending, channel delete. --- src/database/entities/channel.rs | 8 ++++++ src/database/entities/message.rs | 38 +++++++++++++++++++++++++-- src/database/permissions/channel.rs | 17 ++++++++++++ src/notifications/events.rs | 2 ++ src/notifications/subscriptions.rs | 37 +++++++++++++++++++++++++- src/routes/channels/delete_channel.rs | 37 ++++++++++++++++++++++++++ src/routes/channels/mod.rs | 4 ++- 7 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 src/routes/channels/delete_channel.rs diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs index 42bc1fc..30e24b7 100644 --- a/src/database/entities/channel.rs +++ b/src/database/entities/channel.rs @@ -28,6 +28,14 @@ pub enum Channel { } impl Channel { + pub fn id(&self) -> &str { + match self { + Channel::SavedMessages { id, .. } => id, + Channel::DirectMessage { id, .. } => id, + Channel::Group { id, .. } => id, + } + } + pub async fn save(&self) -> Result<()> { get_collection("channels") .insert_one( diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs index 59f51cb..d5a1197 100644 --- a/src/database/entities/message.rs +++ b/src/database/entities/message.rs @@ -1,5 +1,6 @@ -// use mongodb::bson::DateTime; -// use serde::{Deserialize, Serialize}; +use crate::{database::*, notifications::events::ClientboundNotification, util::result::Result}; +use mongodb::bson::{DateTime, to_bson}; +use serde::{Deserialize, Serialize}; /*#[derive(Serialize, Deserialize, Debug)] pub struct PreviousEntry { @@ -20,3 +21,36 @@ pub struct Message { pub previous_content: Vec<PreviousEntry>, }*/ + +#[derive(Serialize, Deserialize, Debug)] +pub struct Message { + #[serde(rename = "_id")] + pub id: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub nonce: Option<String>, + pub channel: String, + pub author: String, + + pub content: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub edited: Option<DateTime>, +} + +impl Message { + pub async fn send(self) -> Result<()> { + get_collection("messages") + .insert_one( + to_bson(&self).unwrap().as_document().unwrap().clone(), + None + ) + .await; + + let channel = self.channel.clone(); + ClientboundNotification::Message(self) + .publish(channel) + .await + .ok(); + + Ok(()) + } +} diff --git a/src/database/permissions/channel.rs b/src/database/permissions/channel.rs index cfb4ebd..37ff81e 100644 --- a/src/database/permissions/channel.rs +++ b/src/database/permissions/channel.rs @@ -28,6 +28,23 @@ pub async fn calculate(user: &User, target: &Channel) -> ChannelPermissions<[u32 ChannelPermissions([ 0 ]) } } + Channel::DirectMessage { recipients, .. } => { + if recipients.iter().find(|x| *x == &user.id).is_some() { + if let Some(recipient) = recipients + .iter() + .find(|x| *x != &user.id) { + let perms = super::user::calculate(&user, recipient).await; + + if perms.get_send_message() { + return ChannelPermissions([ ChannelPermission::View + ChannelPermission::SendMessage ]); + } + + return ChannelPermissions([ ChannelPermission::View as u32 ]); + } + } + + ChannelPermissions([ 0 ]) + } _ => unreachable!() } } diff --git a/src/notifications/events.rs b/src/notifications/events.rs index 0e3be5d..cf4f0e4 100644 --- a/src/notifications/events.rs +++ b/src/notifications/events.rs @@ -36,6 +36,8 @@ pub enum ClientboundNotification { channels: Vec<Channel> }, + Message(Message), + /*MessageCreate { id: String, nonce: Option<String>, diff --git a/src/notifications/subscriptions.rs b/src/notifications/subscriptions.rs index b099e48..0c9105c 100644 --- a/src/notifications/subscriptions.rs +++ b/src/notifications/subscriptions.rs @@ -1,7 +1,10 @@ use crate::database::*; -use super::hive::get_hive; +use futures::StreamExt; +use mongodb::bson::doc; use hive_pubsub::PubSub; +use super::hive::get_hive; +use mongodb::options::FindOptions; pub async fn generate_subscriptions(user: &User) -> Result<(), String> { let hive = get_hive(); @@ -13,5 +16,37 @@ pub async fn generate_subscriptions(user: &User) -> Result<(), String> { } } + let mut cursor = get_collection("channels") + .find( + doc! { + "$or": [ + { + "type": "SavedMessages", + "user": &user.id + }, + { + "type": "DirectMessage", + "recipients": &user.id, + "active": true + }, + { + "type": "Group", + "recipients": &user.id + } + ] + }, + FindOptions::builder() + .projection(doc! { "_id": 1 }) + .build() + ) + .await + .map_err(|_| "Failed to fetch channels.".to_string())?; + + while let Some(result) = cursor.next().await { + if let Ok(doc) = result { + hive.subscribe(user.id.clone(), doc.get_str("_id").unwrap().to_string())?; + } + } + Ok(()) } diff --git a/src/routes/channels/delete_channel.rs b/src/routes/channels/delete_channel.rs new file mode 100644 index 0000000..8704d81 --- /dev/null +++ b/src/routes/channels/delete_channel.rs @@ -0,0 +1,37 @@ +use crate::database::*; +use crate::util::result::{Error, Result}; + +use mongodb::bson::doc; + +#[delete("/<target>")] +pub async fn req(user: User, target: Ref) -> Result<()> { + let target = target.fetch_channel().await?; + + let perm = permissions::channel::calculate(&user, &target).await; + if !perm.get_view() { + Err(Error::LabelMe)? + } + + match target { + Channel::SavedMessages { .. } => Err(Error::NoEffect), + Channel::DirectMessage { .. } => { + get_collection("channels") + .update_one( + doc! { + "_id": target.id() + }, + doc! { + "$set": { + "active": false + } + }, + None + ) + .await + .map_err(|_| Error::DatabaseError { operation: "update_one", with: "channel" })?; + + Ok(()) + }, + _ => unimplemented!() + } +} diff --git a/src/routes/channels/mod.rs b/src/routes/channels/mod.rs index 2137b3c..2f2d3b9 100644 --- a/src/routes/channels/mod.rs +++ b/src/routes/channels/mod.rs @@ -1,9 +1,11 @@ use rocket::Route; mod fetch_channel; +mod delete_channel; pub fn routes() -> Vec<Route> { routes![ - fetch_channel::req + fetch_channel::req, + delete_channel::req ] } -- GitLab