From fa960ebc9421d31eec0ca12bee97881e5442e08b Mon Sep 17 00:00:00 2001 From: Paul <paulmakles@gmail.com> Date: Mon, 3 May 2021 11:17:28 +0100 Subject: [PATCH] Send out unset in event. --- src/database/entities/channel.rs | 7 ++++ src/notifications/events.rs | 17 ++++++++++ src/routes/channels/edit_channel.rs | 46 +++++++++++++++++++------- src/routes/users/change_username.rs | 1 + src/routes/users/edit_user.rs | 51 ++++++++++++++++++----------- 5 files changed, 90 insertions(+), 32 deletions(-) diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs index c1fd37b..1c7c96a 100644 --- a/src/database/entities/channel.rs +++ b/src/database/entities/channel.rs @@ -106,6 +106,7 @@ impl Channel { ClientboundNotification::ChannelUpdate { id: id.clone(), data, + clear: None } .publish(id) .await @@ -195,6 +196,12 @@ impl Channel { .publish(id.to_string()) .await .ok(); + + if let Channel::Group { icon, .. } = self { + if let Some(attachment) = icon { + attachment.delete().await?; + } + } Ok(()) } diff --git a/src/notifications/events.rs b/src/notifications/events.rs index c67c7d1..9ff4cf0 100644 --- a/src/notifications/events.rs +++ b/src/notifications/events.rs @@ -30,6 +30,19 @@ pub enum ServerboundNotification { EndTyping { channel: String }, } +#[derive(Serialize, Deserialize, Debug)] +pub enum RemoveUserField { + ProfileContent, + ProfileBackground, + StatusText, + Avatar +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum RemoveChannelField { + Icon +} + #[derive(Serialize, Deserialize, Debug)] #[serde(tag = "type")] pub enum ClientboundNotification { @@ -53,6 +66,8 @@ pub enum ClientboundNotification { ChannelUpdate { id: String, data: JsonValue, + #[serde(skip_serializing_if = "Option::is_none")] + clear: Option<RemoveChannelField> }, ChannelGroupJoin { id: String, @@ -77,6 +92,8 @@ pub enum ClientboundNotification { UserUpdate { id: String, data: JsonValue, + #[serde(skip_serializing_if = "Option::is_none")] + clear: Option<RemoveUserField> }, UserRelationship { id: String, diff --git a/src/routes/channels/edit_channel.rs b/src/routes/channels/edit_channel.rs index 4e1d971..ff5c473 100644 --- a/src/routes/channels/edit_channel.rs +++ b/src/routes/channels/edit_channel.rs @@ -1,4 +1,4 @@ -use crate::database::*; +use crate::{database::*, notifications::events::RemoveChannelField}; use crate::notifications::events::ClientboundNotification; use crate::util::result::{Error, Result}; @@ -17,15 +17,16 @@ pub struct Data { description: Option<String>, #[validate(length(min = 1, max = 128))] icon: Option<String>, + remove: Option<RemoveChannelField> } -#[patch("/<target>", data = "<info>")] -pub async fn req(user: User, target: Ref, info: Json<Data>) -> Result<()> { - let info = info.into_inner(); - info.validate() +#[patch("/<target>", data = "<data>")] +pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<()> { + let data = data.into_inner(); + data.validate() .map_err(|error| Error::FailedValidation { error })?; - if info.name.is_none() && info.description.is_none() && info.icon.is_none() { + if data.name.is_none() && data.description.is_none() && data.icon.is_none() && data.remove.is_none() { return Ok(()); } @@ -42,16 +43,27 @@ pub async fn req(user: User, target: Ref, info: Json<Data>) -> Result<()> { match &target { Channel::Group { id, icon, .. } => { let mut set = doc! {}; - if let Some(name) = &info.name { + let mut unset = doc! {}; + + let mut remove_icon = false; + if let Some(remove) = &data.remove { + match remove { + RemoveChannelField::Icon => { + unset.insert("icon", 1); + remove_icon = true; + } + } + } + + if let Some(name) = &data.name { set.insert("name", name); } - if let Some(description) = info.description { + if let Some(description) = &data.description { set.insert("description", description); } - let mut remove_icon = false; - if let Some(attachment_id) = info.icon { + if let Some(attachment_id) = &data.icon { let attachment = File::find_and_use(&attachment_id, "icons", "object", &user.id).await?; set.insert( "icon", @@ -64,10 +76,19 @@ pub async fn req(user: User, target: Ref, info: Json<Data>) -> Result<()> { remove_icon = true; } + let mut operations = doc! {}; + if set.len() > 0 { + operations.insert("$set", &set); + } + + if unset.len() > 0 { + operations.insert("$unset", unset); + } + get_collection("channels") .update_one( doc! { "_id": &id }, - doc! { "$set": &set }, + operations, None ) .await @@ -76,12 +97,13 @@ pub async fn req(user: User, target: Ref, info: Json<Data>) -> Result<()> { ClientboundNotification::ChannelUpdate { id: id.clone(), data: json!(set), + clear: data.remove } .publish(id.clone()) .await .ok(); - if let Some(name) = info.name { + if let Some(name) = data.name { Message::create( "00000000000000000000000000".to_string(), id.clone(), diff --git a/src/routes/users/change_username.rs b/src/routes/users/change_username.rs index 206c8eb..1daa11f 100644 --- a/src/routes/users/change_username.rs +++ b/src/routes/users/change_username.rs @@ -58,6 +58,7 @@ pub async fn req( ClientboundNotification::UserUpdate { id: user.id.clone(), data: json!(data.0), + clear: None } .publish(user.id.clone()) .await diff --git a/src/routes/users/edit_user.rs b/src/routes/users/edit_user.rs index ee5db91..f240a57 100644 --- a/src/routes/users/edit_user.rs +++ b/src/routes/users/edit_user.rs @@ -1,4 +1,4 @@ -use crate::database::*; +use crate::{database::*, notifications::events::RemoveUserField}; use crate::notifications::events::ClientboundNotification; use crate::util::result::{Error, Result}; @@ -17,14 +17,6 @@ pub struct UserProfileData { background: Option<String>, } -#[derive(Serialize, Deserialize)] -pub enum RemoveField { - ProfileContent, - ProfileBackground, - StatusText, - Avatar -} - #[derive(Validate, Serialize, Deserialize)] pub struct Data { #[validate] @@ -33,15 +25,12 @@ pub struct Data { profile: Option<UserProfileData>, #[validate(length(min = 1, max = 128))] avatar: Option<String>, - remove: Option<RemoveField> + remove: Option<RemoveUserField> } #[patch("/<_ignore_id>", data = "<data>")] pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> { let mut data = data.into_inner(); - if data.status.is_none() && data.profile.is_none() && data.avatar.is_none() { - return Ok(()); - } data.validate() .map_err(|error| Error::FailedValidation { error })?; @@ -52,19 +41,19 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> let mut remove_background = false; let mut remove_avatar = false; - if let Some(remove) = data.remove { + if let Some(remove) = &data.remove { match remove { - RemoveField::ProfileContent => { + RemoveUserField::ProfileContent => { unset.insert("profile.content", 1); }, - RemoveField::ProfileBackground => { + RemoveUserField::ProfileBackground => { unset.insert("profile.background", 1); remove_background = true; } - RemoveField::StatusText => { + RemoveUserField::StatusText => { unset.insert("status.text", 1); }, - RemoveField::Avatar => { + RemoveUserField::Avatar => { unset.insert("avatar", 1); remove_avatar = true; } @@ -117,18 +106,28 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> None }; + let mut operations = doc! {}; + if set.len() > 0 { + operations.insert("$set", set); + } + + if unset.len() > 0 { + operations.insert("$unset", unset); + } + get_collection("users") - .update_one(doc! { "_id": &user.id }, doc! { "$set": set }, None) + .update_one(doc! { "_id": &user.id }, operations, None) .await .map_err(|_| Error::DatabaseError { operation: "update_one", with: "user", })?; - if let Some(status) = data.status { + if let Some(status) = &data.status { ClientboundNotification::UserUpdate { id: user.id.clone(), data: json!({ "status": status }), + clear: None } .publish(user.id.clone()) .await @@ -139,6 +138,18 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> ClientboundNotification::UserUpdate { id: user.id.clone(), data: json!({ "avatar": avatar }), + clear: None + } + .publish(user.id.clone()) + .await + .ok(); + } + + if let Some(clear) = data.remove { + ClientboundNotification::UserUpdate { + id: user.id.clone(), + data: json!({}), + clear: Some(clear) } .publish(user.id.clone()) .await -- GitLab