diff --git a/src/database/permissions.rs b/src/database/permissions.rs index d5eaa7316c6d706315d101994b24d74fbdeee7b1..0c2018539d2c72de0c3d2c5205b66107e334ba5b 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 39323b03a7122f3790400dcb5c8d34af4507e65f..756f8f36e198f7384b83826bd905180ac74a32b2 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 a3de253a052a1bd60e53474e4710b387768c898e..876bb51766a6a2c1f24e73aee57dbd741e94ef38 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 cd3f5b8fca939c0494cbd918bac6ffbcfed1b6b7..a9fedb633258ea6b1e1826889bfd594a6eee0628 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 7833d4238454e4f1a64e8ea9a45762d78ee91c71..0126424eaf53b77263aa69fa9462637ae556fe32 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 0000000000000000000000000000000000000000..fe40409f7f0a0a455e9e3dbf719567ef047ff17e --- /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()) +}