From ca1d8bb526fb36afda9c615e15799e7f1d7db960 Mon Sep 17 00:00:00 2001 From: Flemmli97 <34157027+Flemmli97@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:21:20 +0100 Subject: [PATCH] feat: update group permissions (#622) Co-authored-by: Flemmli97 Co-authored-by: Darius Clark Co-authored-by: ashneverdawn <8341280+ashneverdawn@users.noreply.github.com> --- extensions/warp-ipfs/examples/messenger.rs | 4 +- .../warp-ipfs/src/store/message/task.rs | 107 +++++++++++++----- extensions/warp-ipfs/tests/group.rs | 8 +- warp/src/raygun/mod.rs | 15 ++- 4 files changed, 101 insertions(+), 33 deletions(-) diff --git a/extensions/warp-ipfs/examples/messenger.rs b/extensions/warp-ipfs/examples/messenger.rs index 830b261af..1fc317fbf 100644 --- a/extensions/warp-ipfs/examples/messenger.rs +++ b/extensions/warp-ipfs/examples/messenger.rs @@ -470,7 +470,7 @@ async fn main() -> anyhow::Result<()> { let mut permissions = GroupPermissions::new(); if open { for did in &did_keys { - permissions.insert(did.clone(), vec![GroupPermission::AddParticipants, GroupPermission::SetGroupName].into_iter().collect()); + permissions.insert(did.clone(), GroupPermission::values().into_iter().collect()); } } if let Err(e) = instance.create_group_conversation( @@ -529,7 +529,7 @@ async fn main() -> anyhow::Result<()> { let mut permissions = GroupPermissions::new(); if open { for did in conversation.recipients().to_owned() { - permissions.insert(did, vec![GroupPermission::AddParticipants, GroupPermission::SetGroupName].into_iter().collect()); + permissions.insert(did, GroupPermission::values().into_iter().collect()); } } if let Err(e) = instance.update_conversation_permissions(topic, permissions).await { diff --git a/extensions/warp-ipfs/src/store/message/task.rs b/extensions/warp-ipfs/src/store/message/task.rs index 4619ead70..689c4e24d 100644 --- a/extensions/warp-ipfs/src/store/message/task.rs +++ b/extensions/warp-ipfs/src/store/message/task.rs @@ -1872,7 +1872,7 @@ impl ConversationTask { .has_permission(own_did, GroupPermission::AddParticipants) && creator.ne(own_did) { - return Err(Error::PublicKeyInvalid); + return Err(Error::Unauthorized); } if creator.eq(did_key) { @@ -1939,8 +1939,13 @@ impl ConversationTask { let own_did = &self.identity.did_key(); - if creator.ne(own_did) { - return Err(Error::PublicKeyInvalid); + if creator.ne(own_did) + && !self + .document + .permissions + .has_permission(own_did, GroupPermission::RemoveParticipants) + { + return Err(Error::Unauthorized); } if creator.eq(did_key) { @@ -2089,10 +2094,10 @@ impl ConversationTask { if !&self .document .permissions - .has_permission(own_did, GroupPermission::SetGroupName) + .has_permission(own_did, GroupPermission::EditGroupInfo) && creator.ne(own_did) { - return Err(Error::PublicKeyInvalid); + return Err(Error::Unauthorized); } self.document.name = (!name.is_empty()).then_some(name.to_string()); @@ -2164,15 +2169,20 @@ impl ConversationTask { ConversationImageType::Banner => MAX_CONVERSATION_BANNER_SIZE, ConversationImageType::Icon => MAX_CONVERSATION_ICON_SIZE, }; - - let own_did = self.identity.did_key(); - - if self.document.conversation_type() == ConversationType::Group - && !matches!(self.document.creator.as_ref(), Some(creator) if own_did.eq(creator)) - { - return Err(Error::InvalidConversation); + if self.document.conversation_type() == ConversationType::Group { + let Some(creator) = self.document.creator.as_ref() else { + return Err(Error::InvalidConversation); + }; + let own_did = self.identity.did_key(); + if !&self + .document + .permissions + .has_permission(&own_did, GroupPermission::EditGroupImages) + && own_did.ne(creator) + { + return Err(Error::Unauthorized); + } } - let (cid, size, ext) = match location { Location::Constellation { path } => { let file = self @@ -2301,12 +2311,19 @@ impl ConversationTask { &mut self, image_type: ConversationImageType, ) -> Result<(), Error> { - let own_did = self.identity.did_key(); - - if self.document.conversation_type() == ConversationType::Group - && !matches!(self.document.creator.as_ref(), Some(creator) if own_did.eq(creator)) - { - return Err(Error::InvalidConversation); + if self.document.conversation_type() == ConversationType::Group { + let Some(creator) = self.document.creator.as_ref() else { + return Err(Error::InvalidConversation); + }; + let own_did = self.identity.did_key(); + if !&self + .document + .permissions + .has_permission(&own_did, GroupPermission::EditGroupImages) + && own_did.ne(creator) + { + return Err(Error::Unauthorized); + } } let cid = match image_type { @@ -2348,14 +2365,20 @@ impl ConversationTask { pub async fn set_description(&mut self, desc: Option<&str>) -> Result<(), Error> { let conversation_id = self.conversation_id; - let own_did = &self.identity.did_key(); - if self.document.conversation_type() == ConversationType::Group { let Some(creator) = self.document.creator.as_ref() else { return Err(Error::InvalidConversation); }; - if own_did != creator { - return Err(Error::InvalidConversation); //TODO: + + let own_did = self.identity.did_key(); + + if !&self + .document + .permissions + .has_permission(&own_did, GroupPermission::EditGroupInfo) + && own_did.ne(creator) + { + return Err(Error::Unauthorized); } } @@ -3370,7 +3393,12 @@ async fn message_event( } } ConversationUpdateKind::RemoveParticipant { did } => { - if !this.document.creator.as_ref().is_some_and(|c| c == sender) { + if !this.document.creator.as_ref().is_some_and(|c| c == sender) + && !this + .document + .permissions + .has_permission(sender, GroupPermission::RemoveParticipants) + { return Err(Error::Unauthorized); } if !this.document.recipients.contains(&did) { @@ -3404,7 +3432,7 @@ async fn message_event( && !this .document .permissions - .has_permission(sender, GroupPermission::SetGroupName) + .has_permission(sender, GroupPermission::EditGroupInfo) { return Err(Error::Unauthorized); } @@ -3444,7 +3472,7 @@ async fn message_event( && !this .document .permissions - .has_permission(sender, GroupPermission::SetGroupName) + .has_permission(sender, GroupPermission::EditGroupInfo) { return Err(Error::Unauthorized); } @@ -3490,6 +3518,15 @@ async fn message_event( } } ConversationUpdateKind::AddedIcon | ConversationUpdateKind::RemovedIcon => { + if this.document.conversation_type == ConversationType::Group + && !this.document.creator.as_ref().is_some_and(|c| c == sender) + && !this + .document + .permissions + .has_permission(sender, GroupPermission::EditGroupImages) + { + return Err(Error::Unauthorized); + } this.replace_document(conversation).await?; if let Err(e) = this @@ -3501,6 +3538,15 @@ async fn message_event( } ConversationUpdateKind::AddedBanner | ConversationUpdateKind::RemovedBanner => { + if this.document.conversation_type == ConversationType::Group + && !this.document.creator.as_ref().is_some_and(|c| c == sender) + && !this + .document + .permissions + .has_permission(sender, GroupPermission::EditGroupImages) + { + return Err(Error::Unauthorized); + } this.replace_document(conversation).await?; if let Err(e) = this @@ -3511,6 +3557,15 @@ async fn message_event( } } ConversationUpdateKind::ChangeDescription { description } => { + if this.document.conversation_type == ConversationType::Group + && !this.document.creator.as_ref().is_some_and(|c| c == sender) + && !this + .document + .permissions + .has_permission(sender, GroupPermission::EditGroupInfo) + { + return Err(Error::Unauthorized); + } if let Some(desc) = description.as_ref() { if desc.is_empty() || desc.len() > MAX_CONVERSATION_DESCRIPTION { return Err(Error::InvalidLength { diff --git a/extensions/warp-ipfs/tests/group.rs b/extensions/warp-ipfs/tests/group.rs index d56e23619..90740f90e 100644 --- a/extensions/warp-ipfs/tests/group.rs +++ b/extensions/warp-ipfs/tests/group.rs @@ -317,11 +317,11 @@ mod test { let mut permissions = GroupPermissions::new(); permissions.insert( did_b.clone(), - vec![GroupPermission::SetGroupName].into_iter().collect(), + vec![GroupPermission::EditGroupInfo].into_iter().collect(), ); permissions.insert( did_c.clone(), - vec![GroupPermission::SetGroupName].into_iter().collect(), + vec![GroupPermission::EditGroupInfo].into_iter().collect(), ); instance_a @@ -601,8 +601,8 @@ mod test { let ret = instance_b.update_conversation_name(id_b, "test").await; - if permissions[&did_b].contains(&GroupPermission::SetGroupName) - && permissions[&did_c].contains(&GroupPermission::SetGroupName) + if permissions[&did_b].contains(&GroupPermission::EditGroupInfo) + && permissions[&did_c].contains(&GroupPermission::EditGroupInfo) { // Non-owner should be able to change the name. ret?; diff --git a/warp/src/raygun/mod.rs b/warp/src/raygun/mod.rs index edf08f63b..9fc03c120 100644 --- a/warp/src/raygun/mod.rs +++ b/warp/src/raygun/mod.rs @@ -880,7 +880,20 @@ impl Conversation { #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)] pub enum GroupPermission { AddParticipants, - SetGroupName, + RemoveParticipants, + EditGroupInfo, + EditGroupImages, +} + +impl GroupPermission { + pub fn values() -> Vec { + vec![ + Self::AddParticipants, + Self::RemoveParticipants, + Self::EditGroupInfo, + Self::EditGroupImages, + ] + } } #[derive(Default, Clone, Copy, Deserialize, Serialize, Debug, PartialEq, Eq, Display)]