From b58755dbeb6d39d8f82e6bb5c2ecf47ad1bd2b4a Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Fri, 4 Feb 2022 16:48:32 +0000 Subject: [PATCH] feat(channels): implement fetch, edit, delete --- src/routes/channels/channel_delete.rs | 65 +++++++++++++++++++++-- src/routes/channels/channel_edit.rs | 75 ++++++++++++++++++++++++--- src/routes/channels/channel_fetch.rs | 14 +++-- src/routes/users/edit_user.rs | 8 +-- 4 files changed, 145 insertions(+), 17 deletions(-) diff --git a/src/routes/channels/channel_delete.rs b/src/routes/channels/channel_delete.rs index 17185732..ff3f72bf 100644 --- a/src/routes/channels/channel_delete.rs +++ b/src/routes/channels/channel_delete.rs @@ -1,8 +1,67 @@ -use revolt_quark::{EmptyResponse, Result}; +use revolt_quark::{Error, EmptyResponse, Result, models::{User, Channel, channel::PartialChannel}, Ref, Db, perms, ChannelPermission}; use mongodb::bson::doc; #[delete("/")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref) -> Result { + let channel = target.as_channel(db).await?; + let perm = perms(&user).channel(&channel).calc_channel(db).await; + + if !perm.get_view() { + return Err(Error::NotFound) + } + + match channel { + Channel::SavedMessages { .. } => Err(Error::NoEffect), + Channel::DirectMessage { id, .. } => { + db.update_channel(&id, &PartialChannel { + active: Some(false), + ..Default::default() + }, vec![]).await?; + + Ok(EmptyResponse) + } + Channel::Group { + id, + owner, + recipients, + .. + } => { + if user.id == owner { + if let Some(new_owner) = recipients.iter().find(|x| *x != &user.id) { + db.update_channel(&id, &PartialChannel { + owner: Some(new_owner.into()), + ..Default::default() + }, vec![]).await?; + } else { + db.delete_channel(&id).await?; + return Ok(EmptyResponse); + } + } + + db.remove_user_from_group(&id, &user.id).await?; + + /*ClientboundNotification::ChannelGroupLeave { + id: id.clone(), + user: user.id.clone(), + } + .publish(id.clone()); + + Content::SystemMessage(SystemMessage::UserLeft { id: user.id }) + .send_as_system(&target) + .await + .ok();*/ + + Ok(EmptyResponse) + } + Channel::TextChannel { id, .. } | + Channel::VoiceChannel { id, .. } => { + if perm.get_manage_channel() { + db.delete_channel(&id).await?; + Ok(EmptyResponse) + } else { + Err(Error::MissingPermission { permission: ChannelPermission::ManageChannel as i32 }) + } + } + } } diff --git a/src/routes/channels/channel_edit.rs b/src/routes/channels/channel_edit.rs index 6d6575a7..2228866e 100644 --- a/src/routes/channels/channel_edit.rs +++ b/src/routes/channels/channel_edit.rs @@ -1,7 +1,7 @@ -use revolt_quark::{EmptyResponse, Result, models::channel::FieldsChannel}; +use revolt_quark::{Error, Result, models::{channel::{FieldsChannel, PartialChannel, Channel}, User, File}, Ref, Database, perms, ChannelPermission}; use mongodb::bson::doc; -use rocket::serde::json::Json; +use rocket::{serde::json::Json, State}; use serde::{Deserialize, Serialize}; use validator::Validate; @@ -15,12 +15,75 @@ pub struct Data { description: Option, #[validate(length(min = 1, max = 128))] icon: Option, - remove: Option, #[serde(skip_serializing_if = "Option::is_none")] - nsfw: Option + nsfw: Option, + #[validate(length(min = 1))] + remove: Option>, } #[patch("/", data = "")] -pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json) -> Result { - todo!() +pub async fn req(db: &State, user: User, target: Ref, data: Json) -> Result> { + let data = data.into_inner(); + data.validate().map_err(|error| Error::FailedValidation { error })?; + + let mut channel = target.as_channel(db).await?; + if !perms(&user).channel(&channel).calc_channel(db).await.get_manage_channel() { + return Err(Error::MissingPermission { permission: ChannelPermission::ManageChannel as i32 }) + } + + if data.name.is_none() && data.description.is_none() && data.icon.is_none() && data.nsfw.is_none() && data.remove.is_none() { + return Ok(Json(channel)) + } + + let mut partial: PartialChannel = Default::default(); + match &mut channel { + Channel::Group { id, name, description, icon, nsfw, .. } + | Channel::TextChannel { id, name, description, icon, nsfw, .. } + | Channel::VoiceChannel { id, name, description, icon, nsfw, .. } => { + if let Some(fields) = &data.remove { + if fields.contains(&FieldsChannel::Icon) { + if let Some(icon) = &icon { + db.mark_attachment_as_deleted(&icon.id).await?; + } + } + + for field in fields { + match field { + FieldsChannel::Description => { + description.take(); + }, + FieldsChannel::Icon => { + icon.take(); + }, + _ => {} + } + } + } + + if let Some(icon_id) = data.icon { + partial.icon = Some(File::use_icon(db, &icon_id, id).await?); + *icon = partial.icon.clone(); + } + + if let Some(new_name) = data.name { + *name = new_name.clone(); + partial.name = Some(new_name); + } + + if let Some(new_description) = data.description { + partial.description = Some(new_description); + *description = partial.description.clone(); + } + + if let Some(new_nsfw) = data.nsfw { + *nsfw = new_nsfw; + partial.nsfw = Some(new_nsfw); + } + + db.update_channel(id, &partial, data.remove.unwrap_or_default()).await?; + }, + _ => return Err(Error::InvalidOperation) + }; + + Ok(Json(channel)) } diff --git a/src/routes/channels/channel_fetch.rs b/src/routes/channels/channel_fetch.rs index f79a413d..066344bb 100644 --- a/src/routes/channels/channel_fetch.rs +++ b/src/routes/channels/channel_fetch.rs @@ -1,8 +1,14 @@ -use revolt_quark::Result; +use revolt_quark::{Error, Result, models::{User, Channel}, Ref, Database, perms, ChannelPermission}; -use rocket::serde::json::Value; +use rocket::{serde::json::Json, State}; #[get("/")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +pub async fn req(db: &State, user: User, target: Ref) -> Result> { + let target = target.as_channel(db).await?; + + if perms(&user).channel(&target).calc_channel(db).await.get_view() { + Ok(Json(target)) + } else { + Err(Error::MissingPermission { permission: ChannelPermission::View as i32 }) + } } diff --git a/src/routes/users/edit_user.rs b/src/routes/users/edit_user.rs index 492681b5..b5734497 100644 --- a/src/routes/users/edit_user.rs +++ b/src/routes/users/edit_user.rs @@ -44,15 +44,15 @@ pub async fn req(db: &State, mut user: User, data: Json) -> Resu if let Some(fields) = &data.remove { if fields.contains(&FieldsUser::Avatar) { - if let Some(_avatar) = &user.avatar { - // TODO: delete the avatar + if let Some(avatar) = &user.avatar { + db.mark_attachment_as_deleted(&avatar.id).await?; } } if fields.contains(&FieldsUser::ProfileBackground) { if let Some(profile) = &user.profile { - if let Some(_background) = &profile.background { - // TODO: delete the background + if let Some(background) = &profile.background { + db.mark_attachment_as_deleted(&background.id).await?; } } }