From 8a4a386ec577f3b33417bee99f3a703fe94ea0a7 Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Thu, 9 Apr 2020 18:33:08 +0100 Subject: [PATCH] Add util, fix fetch DMs, fully implement delete. --- src/database/permissions.rs | 6 +-- src/guards/channel.rs | 1 + src/main.rs | 1 + src/routes/channel.rs | 86 ++++++++++++++++++++++++++++++++----- src/routes/user.rs | 38 ++++++++++++---- src/util/mod.rs | 6 +++ 6 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 src/util/mod.rs diff --git a/src/database/permissions.rs b/src/database/permissions.rs index d5eaa73..0c20185 100644 --- a/src/database/permissions.rs +++ b/src/database/permissions.rs @@ -159,7 +159,7 @@ impl PermissionCalculator { let mut other_user = ""; for item in arr { if item == &self.user.id { - permissions = 49; + permissions = 177; } else { other_user = item; } @@ -174,7 +174,7 @@ impl PermissionCalculator { { permissions = 1; } else if has_mutual_connection(self.user.id, other_user.to_string()) { - permissions = 49; + permissions = 177; } } } @@ -188,7 +188,7 @@ impl PermissionCalculator { if let Some(arr) = &channel.recipients { for item in arr { if item == &self.user.id { - permissions = 49; + permissions = 177; break; } } diff --git a/src/guards/channel.rs b/src/guards/channel.rs index 39323b0..756f8f3 100644 --- a/src/guards/channel.rs +++ b/src/guards/channel.rs @@ -64,6 +64,7 @@ impl<'r> FromParam<'r> for ChannelRef { "type": 1, "recipients": 1, "guild": 1, + "owner": 1, }) .build(), ) diff --git a/src/main.rs b/src/main.rs index a3de253..876bb51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ pub mod database; pub mod email; pub mod guards; pub mod routes; +pub mod util; pub mod websocket; use dotenv; diff --git a/src/routes/channel.rs b/src/routes/channel.rs index cd3f5b8..a9fedb6 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -5,6 +5,7 @@ use crate::database::{ }; use crate::guards::auth::UserRef; use crate::guards::channel::ChannelRef; +use crate::util::vec_to_set; use bson::{doc, from_bson, Bson, Bson::UtcDatetime}; use chrono::prelude::*; @@ -51,11 +52,8 @@ pub fn create_group(user: UserRef, info: Json<CreateGroup>) -> Response { let name: String = info.name.chars().take(32).collect(); let nonce: String = info.nonce.chars().take(32).collect(); - let mut set = HashSet::new(); + let mut set = vec_to_set(&info.users); set.insert(user.id.clone()); - for item in &info.users { - set.insert(item.clone()); - } if set.len() > MAXGROUPSIZE { return Response::BadRequest(json!({ "error": "Maximum group size is 50." })); @@ -109,11 +107,29 @@ pub fn channel(user: UserRef, target: ChannelRef) -> Option<Response> { with_permissions!(user, target); match target.channel_type { - 0..=1 => Some(Response::Success(json!({ + 0 => Some(Response::Success(json!({ "id": target.id, "type": target.channel_type, "recipients": target.recipients, }))), + 1 => { + if let Some(info) = target.fetch_data(doc! { + "name": 1, + "description": 1, + "owner": 1, + }) { + Some(Response::Success(json!({ + "id": target.id, + "type": target.channel_type, + "recipients": target.recipients, + "name": info.get_str("name").unwrap(), + "owner": info.get_str("owner").unwrap(), + "description": info.get_str("description").unwrap_or(""), + }))) + } else { + None + } + }, 2 => { if let Some(info) = target.fetch_data(doc! { "name": 1, @@ -146,11 +162,33 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> { } let col = database::get_collection("channels"); + let target_id = target.id.clone(); + + let try_delete = || { + let messages = database::get_collection("messages"); + + if messages.delete_many( + doc! { "channel": &target_id }, + None + ).is_ok() { + if col.delete_one( + doc! { "_id": &target_id }, + None + ).is_ok() { + Some(Response::Result(super::Status::Ok)) + } else { + Some(Response::InternalServerError(json!({ "error": "Failed to delete group." }))) + } + } else { + Some(Response::InternalServerError(json!({ "error": "Failed to delete messages." }))) + } + }; + match target.channel_type { 0 => { if col .update_one( - doc! { "_id": target.id }, + doc! { "_id": &target_id }, doc! { "$set": { "active": false } }, None, ) @@ -164,14 +202,40 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> { } } 1 => { - // ? TODO: group dm + let mut recipients = + vec_to_set(&target.recipients.expect("Missing recipients on Group DM.")); + let owner = target.owner.expect("Missing owner on Group DM."); - Some(Response::Result(super::Status::Ok)) + if recipients.len() == 1 { + try_delete() + } else { + recipients.remove(&user.id); + let new_owner = if owner == user.id { + recipients.iter().next().unwrap() + } else { + &owner + }; + + if col.update_one( + doc! { "_id": target_id }, + doc! { + "$set": { + "owner": new_owner, + }, + "$pull": { + "recipients": &user.id, + } + }, + None + ).is_ok() { + Some(Response::Result(super::Status::Ok)) + } else { + Some(Response::InternalServerError(json!({ "error": "Failed to remove you from the group." }))) + } + } } 2 => { - // ? TODO: guild - - Some(Response::Result(super::Status::Ok)) + try_delete() } _ => Some(Response::InternalServerError( json!({ "error": "Unknown error has occurred." }), diff --git a/src/routes/user.rs b/src/routes/user.rs index 7833d42..0126424 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -92,21 +92,41 @@ pub fn dms(user: UserRef) -> Response { ], "recipients": user.id }, - None, + FindOptions::builder() + .projection(doc! { + + }) + .build(), ) .expect("Failed channel lookup"); let mut channels = Vec::new(); for item in results { - let channel: Channel = - from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap channel."); + if let Ok(doc) = item { + let id = doc.get_str("_id").unwrap(); + let recipients = doc.get_array("recipients").unwrap(); - channels.push(json!({ - "id": channel.id, - "type": channel.channel_type, - "recipients": channel.recipients, - "active": channel.active.unwrap() - })); + match doc.get_i32("type").unwrap() { + 0 => { + channels.push(json!({ + "id": id, + "type": 0, + "recipients": recipients, + })); + }, + 1 => { + channels.push(json!({ + "id": id, + "type": 1, + "recipients": recipients, + "name": doc.get_str("name").unwrap(), + "owner": doc.get_str("owner").unwrap(), + "description": doc.get_str("description").unwrap_or(""), + })); + }, + _ => unreachable!() + } + } } Response::Success(json!(channels)) diff --git a/src/util/mod.rs b/src/util/mod.rs new file mode 100644 index 0000000..fe40409 --- /dev/null +++ b/src/util/mod.rs @@ -0,0 +1,6 @@ +use hashbrown::HashSet; +use std::iter::FromIterator; + +pub fn vec_to_set<T: Clone + Eq + std::hash::Hash>(data: &Vec<T>) -> HashSet<T> { + HashSet::from_iter(data.iter().cloned()) +} -- GitLab